Exercise 2: Generating Documents using Word ServicesIn this exercise you will be adding an Event Receiver to the State Reports document library that will convert all docx files submitted into XPS and PDF files. This is done using Word Services and a scheduled job that converts all registered documents every 15 minutes. To provide feedback to the user you will also be implementing a simple web part that will provide a summary of the jobs submitted to Word Services. Task 1 – Create the Printable Document Library event receiverIn this task, you will define a List Item Event Receiver that will fire anytime an item a new file is added or updated in the document library. This Event Receiver will start a print job that will convert the added or updated docx file into an XPS and PDF document. - Create a new event receiver item in the PrintableDocumentLibrary item
- Right click PrintableDocumentLibrary in the Solution Explorer and select Add -> New Item
- In the Add New Item dialog, select the Visual C#\Visual Basic -> SharePoint -> 2010 template category
- Select the Event Receiver template
- Set the Name to PrintableDocumentReceiver and click Add
- In the dialog check the checkboxes by
- An item was added
- An item was updated
.png) Figure 11Create new Event Receiver - Click Finish to create the Event Receiver
- Create a StartJob method that accepts the files to convert and the format and starts a conversion job
- Add the following using statement to the file
using Microsoft.Office.Word.Server.Conversions;
Imports Microsoft.Office.Word.Server.Conversions
- In the PrintableDocumentReceiver class, add the following StartJob method
private void StartJob(SPWeb web, SaveFormat format,
string sourceUrl, string targetUrl)
{
}
Private Sub StartJob(ByVal web As SPWeb, ByVal format As SaveFormat, ByVal sourceUrl As String, ByVal targetUrl As String)
End Sub
- In the new method, create a ConversionJobSettings object to control how the documents are converted
ConversionJobSettings settings = new ConversionJobSettings()
{
OutputFormat = format,
UpdateFields = true,
OutputSaveBehavior = SaveBehavior.AlwaysOverwrite
};
Dim settings As New ConversionJobSettings() With {.OutputFormat = format, .UpdateFields = True, .OutputSaveBehavior = SaveBehavior.AlwaysOverwrite}
- Create a new ConversionJob using the settings and your current user token
ConversionJob conversionJob =
new ConversionJob(Constants.WordServicesAppName, settings)
{
SubscriptionId = Constants.SubscriptionId,
UserToken = web.CurrentUser.UserToken
};
Dim conversionJob As New ConversionJob(Constants.WordServicesAppName, settings) With {.SubscriptionId = Constants.SubscriptionId, .UserToken = web.CurrentUser.UserToken}
The SubscriptionId is a shared Guid that allows the application to find its active jobs. - Add the source and target file urls to the job and then start it
conversionJob.AddFile(sourceUrl, targetUrl);
conversionJob.Start();
conversionJob.AddFile(sourceUrl, targetUrl)
conversionJob.Start()
It is possible to add multiple source/target pairs and even choose to convert entire folders or lists. In this case, you are starting one job for each type of conversion.
- Implement a PrintDocument method that uses StartJob to convert all docx files to XPS and PDF
- Add a new PrintDocument method to the PrintableDocumentReceiver class
private void PrintDocument(SPWeb web, string listItemUrl)
{
}
Private Sub PrintDocument(ByVal web As SPWeb, ByVal listItemUrl As String)
End Sub
- Wrap all the code in the method with an if statement that checks if the listItemUrl ends with a .docx extension
private void PrintDocument(SPWeb web, string listItemUrl) {
if (listItemUrl.EndsWith(".docx"))
{
}
} Private Sub PrintDocument(ByVal web As SPWeb, ByVal listItemUrl As String)
If listItemUrl.EndsWith(".docx") Then
End If
End Sub - Calculate the sourceUrl using the web’s url and the list item’s url
string sourceUrl = web.Url + "/" + listItemUrl;
Dim sourceUrl As String = web.Url & "/" & listItemUrl
- Calculate the target url by removing the .docx
string targetUrl = sourceUrl.Substring(0, sourceUrl.Length - 5);
Dim targetUrl As String = sourceUrl.Substring(0, sourceUrl.Length - 5)
- Start a job for XPS and PDF conversion using the StartJob method
StartJob(web, SaveFormat.XPS, sourceUrl, targetUrl + ".xps");
StartJob(web, SaveFormat.PDF, sourceUrl, targetUrl + ".pdf");
StartJob(web, SaveFormat.XPS, sourceUrl, targetUrl & ".xps")
StartJob(web, SaveFormat.PDF, sourceUrl, targetUrl & ".pdf")
- Implement the ItemAdded and ItemUpdated methods by having them call the PrintDocument method
/// <summary>
/// An item was added.
/// </summary>
public override void ItemAdded(SPItemEventProperties properties)
{
PrintDocument(properties.Web, properties.ListItem.Url);
base.ItemAdded(properties);
}
/// <summary>
/// An item was updated.
/// </summary>
public override void ItemUpdated(SPItemEventProperties properties)
{
PrintDocument(properties.Web, properties.ListItem.Url);
base.ItemUpdated(properties);
}
''' <summary>
''' An item was added.
''' </summary>
Public Overrides Sub ItemAdded(ByVal properties As SPItemEventProperties)
PrintDocument(properties.Web, properties.ListItem.Url)
MyBase.ItemAdded(properties)
End Sub
''' <summary>
''' An item was updated.
''' </summary>
Public Overrides Sub ItemUpdated(ByVal properties As SPItemEventProperties)
PrintDocument(properties.Web, properties.ListItem.Url)
MyBase.ItemUpdated(properties)
End Sub
Task 2 – Build the PrintingStatus web partIn this task you will create a web part that will monitor the printing jobs started in a Printable Document Library. This web part will show the total number of jobs in action and the number of jobs in each state. - Add a new Visual Web Part to the project
- Right click StateReportApplication in the Solution Explorer and click Add -> New Item
- In the Add New Item dialog, select the Visual C#\Visual Basic -> SharePoint -> 2010 template category
- Select the Visual Web Part template
- Set the Name to PrintingStatus and click Add
- Design the user interface for the web part
- Open the designer by right clicking PrintingStatusUserControl.ascx in the Solution Explorer and clicking View Designer
- Click the Source button at the bottom of the designer
- At the bottom of the ascx file, add the following markup to define status indicators for the total number of printing jobs, total jobs in progress, and total jobs not started.
<table>
<tr>
<td>Active Printing Jobs</td>
<td><asp:Label ID="ActiveJobs" runat="server" /></td>
</tr>
<tr>
<td style="padding-left:20px">Jobs In Progress</td>
<td><asp:Label ID="InProgressJobs" runat="server" /></td>
</tr>
<tr>
<td style="padding-left:20px">Jobs Not Started</td>
<td><asp:Label ID="NotStartedJobs" runat="server" /></td>
</tr>
- Add the following markup to the end of the file to provide a spacer row and an display of the next scheduled Word Services execution
<tr><td></td><td></td></tr>
<tr>
<td colspan="2" align="center">Next execution:
<asp:Label ID="NextRunTime" runat="server" /></td>
</tr>
</table>
- Switch to the Design view using the button at the bottom of the window and verify it looks like the image below
.png) Figure 12Completed Print Status Design
- Implement the web part’s Page_Load method to display information about active jobs
- View the web parts code by right clicking the designer and selecting View Code
- Add the following using statements to the file
using System.Collections.ObjectModel;
using System.Linq;
using Microsoft.Office.Word.Server.Conversions;
using Microsoft.Office.Word.Server.Service;
using Microsoft.SharePoint.Administration;
Imports System.Collections.ObjectModel
Imports System.Linq
Imports Microsoft.Office.Word.Server.Conversions
Imports Microsoft.Office.Word.Server.Service
Imports Microsoft.SharePoint.Administration
- In the Page_Load method add the following code to retrieve all active jobs and update the UI
ReadOnlyCollection<ConversionJobInfo> activeJobs =
ConversionJobStatus.GetAllActiveJobs(
Constants.WordServicesAppName, Constants.SubscriptionId);
ActiveJobs.Text = activeJobs.Count.ToString();
Dim activeJobs As ReadOnlyCollection(Of ConversionJobInfo) = ConversionJobStatus.GetAllActiveJobs(Constants.WordServicesAppName, Constants.SubscriptionId)
ActiveJobs.Text = activeJobs.Count.ToString()
The SubscriptionId is used to only return jobs started by the event receiver created in the previous task - Traverse through the list of active jobs and find how many documents are in the InProgress or NotStarted state
int inProgressJobs = 0;
int notStartedJobs = 0;
foreach (ConversionJobInfo info in activeJobs)
{
ConversionJobStatus status =
new ConversionJobStatus(Constants.WordServicesAppName,
info.JobId, null);
inProgressJobs += status.InProgress;
notStartedJobs += status.NotStarted;
}
Dim inProgressJobs As Integer = 0
Dim notStartedJobs As Integer = 0
For Each info As ConversionJobInfo In activeJobs
Dim status As New ConversionJobStatus(Constants.WordServicesAppName, info.JobId, Nothing)
inProgressJobs += status.InProgress
notStartedJobs += status.NotStarted
Next info
The GetAllActiveJobs method gets us information about each active job. You will need to create ConvertsionJobStatus objects to find all the details about the jobs. - Using the total conversions in progress and not started, update the UI
InProgressJobs.Text = inProgressJobs.ToString();
NotStartedJobs.Text = notStartedJobs.ToString();
InProgressJobs.Text = inProgressJobs.ToString()
NotStartedJobs.Text = notStartedJobs.ToString()
- Use the WordService object to retrieve the next schedule run time of the conversion jobs
- Add the following code to the end of the Page_Load method to access the WordService object
WordService service = SPFarm.Local.Services.GetValue<WordService>();
Dim service As WordService = SPFarm.Local.Services.GetValue(Of WordService)()
- Using the JobDefinitions list, retrieve the first schedule job in the collection
SPJobDefinition job = service.JobDefinitions.First();
Dim job As SPJobDefinition = service.JobDefinitions.First()
- Using the job’s Schedule property, calculate the next occurrence and display it to the screen
NextRunTime.Text =
job.Schedule.NextOccurrence(DateTime.Now).
ToShortTimeString();
NextRunTime.Text = job.Schedule.NextOccurrence(Date.Now).ToShortTimeString()
Task 3 – Place the Printing Status web part on the pageIn this task, you will update the main site page by adding a Printing Status web part to the page. - Build and deploy the State Report application to SharePoint
- Right click StateReportApplication in the Solution Explorer and click Deploy
- Add a Printing Status web part to the main page of the site
- In Internet Explorer navigate to http://intranet.contoso.com/sites/OfficeServiceApplications
- Click Edit Page on the Page ribbon tab
- Click Add a Web Part in the right web part zone
- In the Web Part pane, choose the Custom category and the PrintingStatus web part
- Click Add to add the web part to the page
- Once the web part is added, drag it below the existing Generate Report web part and click Stop Editing
.png) Figure 13Completed Printing Status Web Part
Exercise 2 VerificationIn order to verify that you have correctly performed all steps of exercise 2, proceed as follows: Test the Event Handler and Web PartTest your event handler and web part by generating a new state report and verifying an XPS and PDF file are generated as well by Word Services. - In Internet Explorer navigate to http://intranet.contoso.com/sites/OfficeServiceApplications
- Choose AL in the drop down list inside the GenerateReport web part and click Generate Report
- Verify that AL shows up in the State Reports list and verify that a printing job shows up in the PrintStatus web part.
.png) Figure 14Printing jobs in progress - Since the job is scheduled in the future, use Central Admin to force it to run now
- In another Internet Explorer tab, navigate to http://demo2010a:2010/default.aspx
- In the Monitoring section, click the Check job status link
.png) Figure 15Check job status link - In the View drop down, choose Job Definition
- In the Job Definition drop down choose Change Job Definition
.png) Figure 16Filter by Job Definition - Page to the right until you find Word Automation Services Timer Job and click it
- Click the job in the Scheduled section at the top of the page
- On the Edit Timer Job page, click Run Now to force the conversion jobs to execute
.png)
- Verify an XPS and PDF version of the report are in the AL folder
- Back in the site tab of Internet Explorer, click the link to the AL folder in the State Reports web part
- Verify there are three documents in the folder, a docx, an XPS, and a PDF
.png) Figure 18Printed Report Files - Click the link on the XPS file to view it
.png) Figure 19Printed Report as XPS
| |