Trying to create new Office documents in SharePoint using client-side development technologies, i.e. Javascript with JSOM or REST is a common enough scenario, though Googling it with Bing yields little to no help.
It is possible to create new Office documents in SharePoint using JSOM, but not REST, at this time at least. Also, the solution in this post doesn’t work for SharePoint Server 2013 on-premise, I haven’t looked at 2016 so I’m not sure in that case.
You have to dig deep into the innards of Core.js (around line 4737 in the debug version) to find the code which actually does this, so if you go to a Document Library, click New and then choose an Office Document format, as shown below;
Clicking “Word” for instance, calls into a function called CreateNewDefaultDocument in core.js, and that code is shown below;
It accepts 3 paremeters;
- j – this is the Id of the current list context, this can be null
- d – this is an integer enumeration of the Microsoft.SharePoint.Client.DocumentTemplateType type where Word=1, Excel=2, PowerPoint=3, OneNote=4, ExcelForm=5
- h – this is the server relative URL of an Office Document Template
The target library for the new document in this case, is determined by the function picking up the correct list context, from which, all it needs is the listName property.
i.e. the list guid in the form {A28BF06E-1374-4858-9D35-62C5904B8503}
Basically, if you pass a truthy value for d then a blank Office document of that type is created, whereas if you pass a non-truthy value for d and a valid server relative URL of an Office Document Template for h, the new document will be created from that template (this can be a template or regular document).
Once the document is created, you are navigated to the Office Web Application for that document so you can view/edit it.
So the 2 JSOM methods used are either;
- createDocumentFromTemplate(…)
- createDocument(…)
Both of these are methods of the SP.List object, and if you follow the link to the documentation page, you’ll notice that they aren’t listed. This doesn’t mean they’re not documented though, if you download the [MS-CSOMSPT]: SharePoint Client-Side Object Model Protocol document, they are documented in there, and a whole lot else too.
Now, the above scenario may well suit your needs, assuming you can deal with the function being able to determine the correct list context, however my needs where slightly different.
I wanted to create a new document using a template, then show the edit document properties dialog, and then finally (in my code) make a decision about whether to open the document in Office Web Apps, or do something else, the code to do just this, is show below and also available from this gist.
/** Creates an Office Document in a SharePoint Document Library using the supplied Office Document Template | |
* see: https://msdn.microsoft.com/en-us/library/dd958478(v=office.12).aspx | |
* @param {} newDocumentName - empty or the new document filename | |
* @param {} listName - the target list (ID) in the form {A28BF06E-1374-4858-9D35-62C5904B8503} | |
* @param {} docType - Microsoft.SharePoint.Client.DocumentTemplateType | |
* - Invalid=0, Word=1, Excel=2, PowerPoint=3, OneNote=4, ExcelForm=5 | |
* @param {} templateUrl - the absolute/server relative URL of the document template (can be template or document) | |
* @param {} waitUI - optional, the notification handle of a wiat dialog to close | |
* e.g. | |
* var waitUI = SP.UI.ModalDialog.showWaitScreenWithNoClose('Creating Document...', "Please wait, this shouldn't take long...", 100, 380); | |
* @return {} promise | |
*/ | |
function createNewDocument(newDocumentName, listName, docType, templateUrl, waitUI) { | |
var d = new $.Deferred(); | |
var ctx = SP.ClientContext.get_current(); | |
var web = ctx.get_web(); | |
var list = web.get_lists().getById(listName); | |
var folder = list.get_rootFolder(); | |
var docName = newDocumentName && newDocumentName.length | |
? String.format("{0}", newDocumentName) | |
: String.format("New Document - {0}.docx", new Date().format("yyyy-mm-dd_hhMMss")); | |
/** replace illegal filename characters */ | |
docName = docName.replace(/[~#!@£$%^&*()\{\}\\:,<>?/|"]+/gi, '-'); | |
var docItem = templateUrl && templateUrl.length | |
? list.createDocumentFromTemplate(docName, folder, templateUrl) | |
: list.createDocument(docName, folder, docType || 1); | |
var wfUrl = docItem.getWOPIFrameUrl(SP.Utilities.SPWOPIFrameAction.edit); | |
var docFile = docItem.get_file(); | |
ctx.load(list, "DefaultEditFormUrl"); | |
ctx.load(docItem, "Id"); | |
ctx.load(docFile, "ServerRelativeUrl", "CheckOutType"); | |
ctx.executeQueryAsync(onCreateSuccess, onFail); | |
return d.promise(); | |
function onCreateSuccess() { | |
var wopiUrl = wfUrl.get_value(); | |
var docInfo = { | |
documentName: docName, | |
editDocumentPropertiesUrl: String.format("{0}?ID={1}&Source={2}", list.get_defaultEditFormUrl(), docItem.get_id(), _spPageContextInfo.webServerRelativeUrl), | |
fileServerRelativeUrl: docFile.get_serverRelativeUrl(), | |
wopiEditDocumentUrl: Boolean(wopiUrl) ? wopiUrl.replace(/wopiframe\.aspx/gi, "WOPIFrame2.aspx") : "", | |
}; | |
console.info("Document: " + docInfo.documentName + " checked in."); | |
console.info("File: " + docInfo.fileServerRelativeUrl); | |
console.info("Edit properties url: " + docInfo.editDocumentPropertiesUrl); | |
console.info("WOPI edit document url: " + docInfo.wopiEditDocumentUrl); | |
var opts = { | |
url: docInfo.editDocumentPropertiesUrl, | |
args: null, | |
title: "Create New Document", | |
dialogReturnValueCallback: onDialogReturn.bind(docInfo), | |
}; | |
if (waitUI) { | |
waitUI.close(); | |
} | |
OpenPopUpPageWithDialogOptions(opts); | |
} | |
function onDialogReturn(returnValue, docObject) { | |
/** | |
docObject = { | |
isFolder: false, | |
newFileIcon: "icdocx.png", | |
newFileSize: 18420, | |
newFileUrl: "/sites/somesite/Documents/Document - 2017-43-17_030239.docx" | |
} | |
*/ | |
console.info("returned from edit properties"); | |
console.info(this); | |
console.info(returnValue); | |
console.info(docObject); | |
if (returnValue === SP.UI.DialogResult.OK) { | |
//GoToPage(this.wopiEditDocumentUrl); | |
} | |
var r = $.extend(docObject, this); | |
r.editPropertiesDialogReturn = returnValue; | |
d.resolve(r); | |
} | |
function onFail(c, b) { | |
console.error(b.get_message()); | |
alert("Critical Error: " + b.get_message()); | |
d.reject("Critical Error: " + b.get_message()); | |
} | |
} |
Phil,
Thank you very much. I was looking around and finally found a positive approach. I am trying to create a document based on a document template in sharepoint hosted add in.Can you please let me know if thats possible?
Thanks,
I don’t see why not, the technique uses only the Javascript CSOM API
Can I create a new document utilizing a content type already in the document library? If so, can you show?
The article is about creating Office documents in SharePoint using Javascript, if you want to use Content Types to create documents you can assign an Office document template to a Content Type using the SharePoint UI