Jan
1
Written by:
Michael Washington
1/1/2015 9:40 AM
You can implement SharePoint documents in your AngularJS applications much easier when you create your code in a Visual Studio LightSwitch Cloud Business app. Essentially we will make a SharePoint CSOM call to create a Word Document in an associated SharePoint list when we create a new task in our SharePoint Provider Hosted application.
The Application
We start with the application created in AngularJS Posting To SharePoint Newsfeed Using Visual Studio LightSwitch.
We add tasks using the add new button and then click Save.
After the task is saved, we can click on the task in the list to edit it.
We will see that a Microsoft Word Document has been created and attached to the task.
We can click on either the Direct Link or the Inline Edit link to open the document.
If we click on the Inline Edit link, the document will open in Word Online in Office 365.
Creating The Application
We start with the application created in AngularJS Posting To SharePoint Newsfeed Using Visual Studio LightSwitch.
This project is based on the application created in the article An End-to-End AngularJS SharePoint Module using LightSwitch OData as a Back-End.
Add References
First, to provide the functionality to programmatically create Word documents, install the Open XML SDK for Microsoft Office (OpenXMLSDKV25.msi) from this link.
Add a reference to DocumentFormat.OpenXml…
…and WindowsBase.
In the Properties for DocumentFormat.OpenXml, ensure you set Copy Local to True so that it will be deployed when you deploy the application to production.
Update the ToDo Table
Open the ToDo table and create a field called TaskID.
We will use this field later to connect this table to the SharePoint Document Library.
Connect LightSwitch To SharePoint Document Library
We will now follow the instructions in the article: Implementing Documents in a SharePoint 2013 Cloud Business App (LightSwitch) to connect the project to the SharePoint Document Library.
First, we need to create a SharePoint Document Library List.
Log into your SharePoint Development site, and click add an app under Site Contents.
Add a Document Library.
Call it TaskDocuments.
After the list is added to the list of apps in Site Contents, select the SETTINGS.
We now need to add a column (TaskID) to allow us to associate a Document to a Task.
In the Settings, select Create column.
Call the column TaskID and set its type to Single line of text.
This is so that each document can be associated with a Task in the application.
Click OK.
Connect To The Document Library
In Visual Studio, right-click on Data Sources and select Add Data Source.
Select SharePoint.
Enter the address of your Development SharePoint server.
You may have to log in.
Select the TaskDocuments from Document Libraries, and UserInformationList from Lists.
The lists will show in the project.
- Open the TaskDocument table and click the Relationship button.
- Select ToDo as the To table and set the Multiplicity to Many to One.
- Set TaskID as the Primary and Foreign keys.
- Click OK.
The relationship will show.
Creating The Word Document
Next, we open the ToDo table and select the _Inserting method.
We add the following code to the end of the method:
// Create a unique ID for this Task
// so that we can also store it in the Document
// Library document to relate it to the ToDo item
entity.TaskID = System.Guid.NewGuid().ToString();
//Load the lists from the Web object.
Microsoft.SharePoint.Client.ListCollection Lists = web.Lists;
clientContext.Load<Microsoft.SharePoint.Client.ListCollection>(Lists);
clientContext.ExecuteQuery();
// Get the target library and its root folder.
Microsoft.SharePoint.Client.List TaskDocumentsLibrary =
Lists.GetByTitle("TaskDocuments");
Microsoft.SharePoint.Client.Folder destintationFolder =
TaskDocumentsLibrary.RootFolder;
clientContext.Load(destintationFolder);
clientContext.ExecuteQuery();
// Build a Word Document by using OOXML
// First create it in a folder in this Web app.
using (WordprocessingDocument wordDocument =
WordprocessingDocument.Create(
HttpContext.Current.Server.MapPath("~/LocalOOXMLDocument.docx"),
WordprocessingDocumentType.Document))
{
// Add a main document part.
MainDocumentPart mainPart = wordDocument.AddMainDocumentPart();
// Create the document structure.
mainPart.Document = new Document();
Body body = mainPart.Document.AppendChild(new Body());
// Create a paragraph.
Paragraph para = body.AppendChild(new Paragraph());
Run run = para.AppendChild(new Run());
run.AppendChild(
new Text(
String.Format("Here's some text for {0}", entity.TaskName)
));
}
// The local file has been created in the folder of the Web project
// Read it and create a new file in SharePoint, based on this local file.
FileStream fs = null;
byte[] documentBytes;
fs = System.IO.File.OpenRead(
HttpContext.Current.Server.MapPath("~/LocalOOXMLDocument.docx"));
documentBytes = new byte[fs.Length];
fs.Read(documentBytes, 0, Convert.ToInt32(fs.Length));
// At this stage, the file contents of the OOXML document have
// been read into the byte array
// Use that as the content of a new file in SharePoint.
Microsoft.SharePoint.Client.FileCreationInformation ooxmlFile
= new Microsoft.SharePoint.Client.FileCreationInformation();
ooxmlFile.Overwrite = true;
ooxmlFile.Url = clientContext.Url
+ destintationFolder.Name
+ "/" + entity.TaskName + ".docx";
ooxmlFile.Content = documentBytes;
Microsoft.SharePoint.Client.File newFile =
TaskDocumentsLibrary.RootFolder.Files.Add(ooxmlFile);
clientContext.Load(newFile);
clientContext.ExecuteQuery();
// Get the ListItem associated with the File
Microsoft.SharePoint.Client.ListItem listItem = newFile.ListItemAllFields;
// Update the TaskId field
// so the document will be associated with the ToDo item
listItem["TaskID"] = entity.TaskID;
listItem.Update();
clientContext.ExecuteQuery();
You will need to add the following Using statements to the top of the class:
using System.IO;
using Microsoft.SharePoint.Client;
using System.Web;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
Update the AngularJS Application
Open the JayDataCRUD.js file and update the Angular controller with the following code:
// Create empty collection
$scope.TaskDocuments = [];
// Call the /SharePointDocuments.svc LightSwitch OData service
$data.initService('/SharePointDocuments.svc').then(function (SharePointDocuments) {
$scope.SharePointDocuments = SharePointDocuments;
$scope.TaskDocuments = SharePointDocuments.TaskDocuments.toLiveArray();
});
// Create a colTaskDocument property that will
// return the TaskDocuments for the selected
// TaskID
Object.defineProperty($scope, "colTaskDocument", {
get: function () {
if ($scope.selectedToDo)
return $scope.SharePointDocuments
.TaskDocuments
.filter('TaskID',
'==',
$scope.selectedToDo.TaskID)
.toLiveArray();
}
});
Open the JayDataCRUD.aspx file and update the markup with the following code:
<table>
<tr data-ng-repeat="TaskDocument in colTaskDocument">
<td>
{{TaskDocument.Name}}
</td>
</tr>
</table>
We can now run the application…
We can create a new task and then click on it to edit it.
We see that an associated Word document has been created and its name will display.
When we go directly to the SharePoint TaskDocument list, we see the Word document can be viewed.
Link To The SharePoint Document From AngularJS
If we navigate directly to the LightSwitch OData feed that it automatically creates for the SharePoint TaskDocuments list (when we connect to it in LightSwitch), we see that it exposes a direct link to the Word document (don’t worry a user still has to be authenticated to get to it).
We can use this property to provide a link to the document in our AngularJS application.
First we add the following filter to the JayDataCRUD.js file (place under var app = angular.module('app', ['jaydata']):
app.filter('WordViewer', function () {
return function (DocumentURL, DocumentName) {
// Get the domain from the DocumentURL
// Create a temp element
var a = document.createElement('a');
// Assign DocumentURL to the .href
// so we can call .hostname in the final step
a.href = DocumentURL;
// Return the URL
return 'https://'
+ a.hostname
+ '/_layouts/15/WopiFrame.aspx?sourcedoc='
+ DocumentURL
+ '&file='
+ DocumentName
+ '&action=default';
};
});
Next, we update the markup in the JayDataCRUD.aspx file to consume the filter:
<table>
<tr data-ng-repeat="TaskDocument in colTaskDocument">
<td>
{{TaskDocument.Name}}
<a href="{{TaskDocument.Microsoft_LightSwitch_ReadLink}}">[Direct Link]</a>
<a href="{{ TaskDocument.Microsoft_LightSwitch_ReadLink | WordViewer : TaskDocument.Name }}">
[Inline Edit]</a>
</td>
</tr>
</table>
When we run the application, we now have a direct link and a inline edit link to the associated Word document.
Links
SharePoint 2013: Create Word documents using OOXML in apps for SharePoint
Link to open in browser with Office Web Apps
Welcome to the Open XML SDK 2.5 for Office
Links – LightSwitch Help Website
AngularJS Posting To SharePoint Newsfeed Using Visual Studio LightSwitch
An End-to-End AngularJS SharePoint Module using LightSwitch OData as a Back-End
Deploy A LightSwitch Application To Office 365 / SharePoint Online
Exploring SharePoint 2013 Visual Studio Cloud Business Apps (LightSwitch)
Implementing Documents in a SharePoint 2013 Cloud Business App (LightSwitch)
Creating A SharePoint Online Testing Site
Creating A LightSwitch SharePoint 2013 Multi-Tenant Provider-Hosted Application
Download Code
The LightSwitch project is available at http://lightswitchhelpwebsite.com/Downloads.aspx
(you must have Visual Studio 2013 (or higher) installed and a SharePoint Developer site to run the code)
4 comment(s) so far...
Hi Michael, Nice article,
can i replace existing file (i mean upload same file and replace with existing one).
By mshahnawaz on
10/24/2016 12:09 PM
|
@mshahnawaz - When you upload a document with the same name it should overwrite the previous one.
By Michael Washington on
10/24/2016 12:11 PM
|
Hi Michael,
i am following this article : https://blogs.msdn.microsoft.com/officeapps/2014/03/18/integrating-documents-into-cloud-business-apps/
i was also expecting that it should be overwrite the previous one but doesn't happen.
By mshahnawaz on
10/25/2016 4:19 AM
|
@mshahnawaz - Perhaps there is a setting on your SharePoint site or collection. The only other thing I could suggest is adding code to delete the current file first (sorry I have no examples).
By Michael Washington on
10/25/2016 4:22 AM
|