Tag Archives: wordwriter

How to use SetCultureInfo with date functions and formatting

Problem

The SetCultureInfo method allows you to override the server’s default locale when generating a new Word file from a template with WordWriter. This is especially useful for the display of dates. It is important, however, to understand that any date formatting must be applied to the Word Template Merge Field instead of in the ASP.NET script.

Solution

To see a standard field code for a DateTimeObject merge field, right-click on the field, and choose Toggle Field codes:

 {MERGEFIELD DateTimeObject} 

You can see that there are no formatting switches applied to this field. In this situation, the default format of “yyy-MM-dd HH:mm:ss” (4-digit year, month, day, military hour, minute, second) will be applied. To set the culture info to a particular language, such as German:

CultureInfo deDe = new CultureInfo("de-DE");
wt.CultureInfo = deDe;

For more information see our documentation on WordTemplate.CultureInfo.

Best coding practices

Unexpected date formatting behavior can be prevented by keeping the following in mind: The Word template is expecting to receive the date as a System.DateTime object. If it is passed a String instead of a System.DateTime object, it will not be able to apply the formatting codes and apply the correct Culture settings.

How to apply a banded style on a table with WordTemplate

Problem

In a template document created in Word 2003, table styles behave correctly when new rows are added by WordWriter. However, if a new template document is created in Word 2007 with the new table styles, these styles do not persist as expected when saved in the binary (.doc) format. This can easily be demonstrated with the banded coloring styles which are displayed as alternating row coloring.

After processing with WordTemplate, the additional rows in the table will have a solid background color instead of a banded styling. MS Word itself shows the same behavior when adding rows to a table styled with the new 2007 styles and saved to the 97-2003 binary file format (.doc). This appears to be a compatability issue at the file format level, with Word not fully supporting the new table styles in the binary file format.

Banded styles behave as expected with OOXML (.docx) files, which have been supported by WordTemplate since version 4.0.

Solution

Option 1: Save the file as .doc before applying table formatting

When Word 2007 opens a .doc file, it opens in compatibility mode which only makes available features that are supported for that format. However, when Word 2007 creates a new document, it doesn’t know which format the user will choose to save it in, so all options are shown, including those which aren’t compatible with the binary format.

The easiest solution would be to save the file as 97-2003 binary file format (.doc) before applying any table formatting. Once the file has been saved, only the styles compatible with the binary format will be available and you can use them freely. If you have already created a template file with 2007 formatting, simply reapply the styling to the tables after the file has been saved in binary format.

Option 2: Use the OOXML file format

Alternatively, with WordWriter 4.0 and above, the other good solution is to use the OOXML (.docx) file format. The resulting populated table will be as you expect when using that file format. The feature is supported in the file format level, so you can place your data marker in such formatted table and it will expand and maintain the selected style.

How to use merge documents together with Document.Append

Problem

Prior to WordWriter 4.5.0, the only way to merge entire documents was to use InsertAfter. Starting in WordWriter 4.5.0, Document.Append() was introduced as an improved way to merge documents together.

This post covers the behavior of Document.Append().

Solution

The default behavior of Document.Append() is creating a section-page break between the original document and the inserted document:

 documentOne.Append(newDocument); 

To merge the two documents so they appear continuous, simply change the section break type to be continuous:

int mySectionsCount = thisDocument.Sections.Length;
thisDocument.Append(otherDocument);
thisDocument.Sections[mySectionsCount].Break = Section.BreakType.Continuous;

Example:

For a more complicated example, here we want to insert into our current work document (thisDocument) a header from one template document and body content from another template document. Note that we want both the header and the body to be on the same page, so we change the type of the section break at the tail of the header to continuous.

// adding header document
Document headerDocument = Wapp.Open(_headerSource);
thisDocument.Append(headerDocument);


// adding body document
Document bodyDocument = Wapp.Open(_bodySource);
int sectionCount = thisDocument.Sections.Length;
thisDocument.Append(bodyDocument);
thisDocument.Sections[sectionCount].Break = Section.BreakType.Continuous;

Note that if the initial document (the one you append into) is empty, we get a blank page at the beginning of the document. To fix that we need to delete the first empty section:

 thisDocument.Sections[0].DeleteElement(); 

All other InsertAfter operations that don’t deal with sections should stay unchanged.

Inserting a subreport into a WordWriter report

Problem

You need to insert a subreport into a larger report using WordWriter.

Solution

Option 1:

Generate each subreport separately and then use the WordApplication API to merge the subreports into the larger report. The subreports could be appended to the main report document with Document.Append, or if you need to insert the subreport into a particular place, you can use Element.InsertAfter or Element.InsertBefore.

Option 2

Flatten your data set and use WordWriter Grouping and Nesting. Grouping and Nesting would allow you repeat sections of a document for a particular subgroup in the data.

NOTE: Both these solutions require WordWriter Enterprise Edition. For more information about the features offered in Enterprise Edition, check out the OfficeWriter Change Log page.

Tools to convert Word documents to PDF

Problem

WordWriter does not support converting between file formats. This includes converting between DOC/DOCX and PDF. We generally recommend that you use a 3rd party component to convert Word documents to PDF files.

Solution

Note: Most Word to PDF converters require Office to be installed on the server in order to render the Word components before generating the PDF file. Microsoft does not recommend this:

Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, ASP.NET, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when Office is run in this environment.

For more details, see Considerations for server-side Automation of Office.

Word Services for SharePoint

If you are using SharePoint Server 2010, then one possibility is to use Word Services to perform the format conversion. This entails writing code to convert a Word document that is in a list or a document library in SharePoint.

This is a blog post that describes Converting Word Documents to PDF using SharePoint Server 2010 and Word Services. In this case, Word Services automatically converts a document to PDF when the Word document is added to a list.

Rainbow PDF

Rainbow PDF by Atenna House has a server-based converter that does not require Office on the server. However, since Office is not installed, this component does not have the ability to render all Word document elements. Word documents rendered to PDF with Rainbow PDF experience loss of fidelity.

EasyPDF

EasyPDF by BCL Technologies has a a PDF Creator SDK as well as server-side solutions that can convert Word documents to PDF. EasyPDF does require Office to be installed on the server, however it carefully manages the instances of Word to avoid hitting the pitfalls that normally happen when automating Office on the server.

How to use merge fields with a bar code format

Problem

You create a Word document containing a merge field formatted with a Bar Code font, such as Code 39. You use the WordTemplate class to process the document. However, in the generated document, the merge field is populated with text in the Times New Roman font. The problem is illustrated in the figures below:

Merge field
Formatted merge field
Output

Solution

A bar code field must begin and end with a delimiter character. For the Code 39 font, this required delimiter is represented in human-readable text as the * character.

When you create the merge field in a Word document, insert the * character into the merge field using merge field switches. Then you can format the merge field with a bar code font. The procedure is as follows:

1. From the Word menu, select Insert, Field.

2. In the dialog box, select MergeField and fill in the fields as illustrated in the figure below. Use an appropriate name for Field name.

After you close the dialog box, the merge field should appear as follows:

3. Select the entire merge field and format it with a bar code font, such as Code 39.

In the generated document, the merge field should now contain the text in the bar code font. The following figure shows the results for the string *0123456789*.

To see that this does in fact represent the correct string, you can select the text and choose a different, readable font, or copy and paste the text into a text editor.

Running VBA macros in Internet Explorer

Problem

Some VBA macros in a spreadsheet processed by ExcelWriter or WordWriter fail to execute when the file is opened in Internet Explorer. However, if the file is saved to the local filesystem and opened afterwards in Excel or Word, the macro works fine.

Solution

This issue is with MS Office and Internet Explorer, not with OfficeWriter. OfficeWriter preserves all VBA macros when processing a spreadsheet or document. However, not all VBA will execute in the Excel or Word browser plug-ins. In order to guarantee that all your macros will run in your OfficeWriter-generated files, it is recommended to use the Save option that will open the file in a separate Excel or Word window rather than in the browser.

For more information, see this article: Some Macro Commands Are Not Run in MS Internet Explorer.

Code samples

To make sure that your OfficeWriter-generated files are opened in Excel or Word instead of the browser, specify ‘false’ when using the Save method:
xlt.Save(Page.Response, "WorkbookWithMacros_out.xlsm", false); //ExcelTemplate
xla.Save(workbook, Page.Response, "WorkbookWithMacros_out.xlsm", false); //ExcelApplication
wt.Save(Page.Response, "DocWithMacros_out.docm", false); //WordTemplate
wapp.Save(document, Page.Response, "DocWithMacros_out.doc", false); //WordApplication

How to create a Hanging indentation for a paragraph

Problem

In MS Word you can create a paragraph that has a hanging indentation. A hanging indentation means that the entire paragraph is indented except for the first line:

In Word this is created through the Paragraph dialog:

To get to this dialog in Word 2010/2007, select the paragraph you want to format > right click > select Paragraph. To get to this dialog in Word 2003, select the paragraph you want to format > Format menu > select Paragraph.

This post covers how to do this with WordWriter.

Solution

Though there isn’t a property for hanging indentation in the current version of WordWriter, if a hanging indentation is set in an input file or template the hanging indentation will be preserved.

It is also possible to create a hanging indentation using WordApplication by setting the indent property of the ParagraphFormatting object twice with SetIndent:

Note: The indentation is set using the Twips measurement unit (Twip = 1/1440 Inch). To simplify the use of Twips WordWriter provides a TwipsConverter object that allows you to convert twips to or from inches, centimeters and points.

The code below creates a 1 inch hanging indentation. Notice the negative value given to the FirstLine indentation:

ParagraphFormatting pFormat = doc.CreateParagraphFormatting();
//using the TwipsConverter to convert the inches into Twips
int TwipIndentVal = TwipsConverter.FromInches(1);


//setting the paragraph to be indented 1 inch left
pFormat.set_Indent(TwipIndentVal, ParagraphFormatting.IndentLocation.Left);


//The negative value takes back the first line by 1 inch, to the left margin
pFormat.set_Indent(-TwipIndentVal, ParagraphFormatting.IndentLocation.FirstLine);
Paragraph par = doc.InsertParagraphAfter(null, pFormat);

How to insert HTML into Word documents

Problem

Many customers have rich text data that’s stored in databases as HTML and they need to display the HTML-formatted data in Word documents.

Solution

Using WordTemplate:

The ability to insert RTF and HTML documents into Word documents was introduced in WordWriter 8.0 for the WordTemplate object. For more information, read our tutorial for Inserting an Embedded Document in the documentation.

Using WordApplication:

SoftArtisans has an open source project called HTMLtoWord that allows users to insert well-formed HTML (XHTML) snippets into Word documents as formatted text. This uses the WordApplication project, so you must have WordWriter Enterprise Edition to use this project.

The project can be downloaded from SourceForge.net. For more information, see Using HTMLtoWord.

How to insert images from the internet into a Word document

Problem

The Element.InsertImageAfter() method in the WordApplication object can insert an image into a document from an image file location or a FileStream. It cannot insert an image from a URL as a string, however. In order to insert an image from a URL, you must first retrieve the image as a stream.

For more information about inserting images with WordTemplate please refer to our documentation.

Solution

Response programmatically and return the Response as a stream. The HttpWebRequest and WebResponse objects are described in Microsoft’s MSDN documentation.

In this example, the Word document is being filled with data using the WordTemplate object. Then, it is passed to the WordApplication object, where the the SearchMatch object is used to find all instances in the document of a string ending in an image file extension that is WordWriter-compatible (.jpg, .jpeg, .gif, .png, .bmp) using a Regular Expression. Then the .NET HttpWebResponse and WebResponse objects are used to retrieve the image as a stream. Finally, the images are inserted into the document.

Note: If you are using this code in a Web Application, you will need to pass the correct credentials to the proxy server or you will receive a 407 error. Microsoft has a support article addressing this issue located here.

Example


protected void InsertImagesFromURL()
{
//Create the Word Template object and open the template WordTemplate
wt = new WordTemplate(); wt.Open(Page.MapPath("templates/DatabaseSourceTest.doc"));


//Insert sample images into a template document
string[] data = new string[2] { "http://www.mbta.com/images/logo-mbta.gif", "http://www.purepage.com/sample/purepageimages/final_logo_bmp.Bmp" };
string[] names = new string[2] { "OrderID", "CustomerID" };


//Set the datasource for the template
wt.SetDataSource(data, names);
wt.Process();


//Open the template as a WordApplication Document for editing
WordApplication wa = new WordApplication();
Document doc = wa.Open(wt);


//Call the SearchAndReplaceWithImage method to search the document for
//image URLs and replace them with images
SearchAndReplaceWithImage(doc);


//Export the final document
wa.Save(doc, Page.Response, "output.doc", false);
}


public void SearchAndReplaceWithImage(Document doc)
{
//Search for all strings in the document ending in
//.jpg, .jpeg, .png, .bmp.
//These are all of the valid picture types that can be imported
//using WordWriter.
//Use regular expressions to perform the search efficiently.
SearchMatch[] searcherator = doc.Search(@"(?i).*jpe?g$|.*gif$|.*png$|.*bmp$");


//For every string that ends with an image extension, do this
for (int i = 0; i < searcherator.Length; i++)
{


//Select a match from the SearchMatch array
SearchMatch match = (SearchMatch)searcherator[i];


//Use the DownloadAndInsertImage method to retrieve the image as
//a stream stream and insert it into the document.
DownloadAndInsertImage(match);
}
}


public void DownloadAndInsertImage(SearchMatch match)
{


//Retrieve the URL as a string from the SearchMatch object
string strhttp = match.Element.Text;


//Send an HTTP request and get the image at the URL as an HTTP response
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(strhttp);
WebResponse myResp = myReq.GetResponse();


//Get a stream from the webresponse
Stream stream = myResp.GetResponseStream();


//Insert the image into the document and delete the URL string
match.Element.InsertImageAfter(stream);
match.Element.DeleteElement(); }