Visual Studio Tools for Office (VSTO) + MS Word Document Template - c#

My requirement is to create a word document dynamically i.e. create a document with template having data placeholders like version, author, header etc. How can I create this template & open the document and replace the placeholder with actual data by code (C#)? I have to put placeholders in document header/footer, document page & watermark.
Also, how can I pass data from other project to VSTO project?
Please suggest me some demo videos, user guide, tutorial or manual regarding the same? Thanks.

Firstly you need to create your template with fields or bookmarks to contain your data.
Using bookmarks you create your template and add bookmarks where you want to insert your data. In your VSTO addin would fill the bookmark with the following. This example is from an application level addin
For the sake of this I'll assume you are retrieving data from a data base and that you have a bookmark called ProductName
Microsoft.Office.Interop.Word.Document doc = Globals.ThisAddIn.Application.ActiveDocument;
string productName = GetProductNameFromDatabase();
doc.Bookmarks["ProductName"].Range.Text = productName;
I am afraid this only answers the specific question of adding data to a word document.

Related

Write hidden information (like software name & version) in Excel file using OpenXML

My c# software exports to Excel files using OpenXML. I am reading and editing these files in the software even after user edits them in Excel. I want to add the software name and version somewhere, so, when the software opens the file, recognize it. Is there any property in the Workbook as document information, comments, or only visible to OpenXML not Excel?
For now the best workaround is to save this information in an excel sheet and hide the sheet. The point is this information should not be accidentally deleted by the user.
I'd use a Custom XML Part.
The content of a Custom XML Part is only accessible through the object model or by unzipping the file "package". So the information can't be altered accidentally or even viewed without extra effort. And if you're processing the file via Open XML, accessing a Custom XML Part is reasonably straight-forward.
(The user can see Document Properties (suggested in a comment) via the UI, in the File/Info tab.)
Set a custom property for excel document via Openxml
Find method SetCustomProperty() at the bottom of page. This function is written for Word document so change open-file line to below one for Excel document
using (var document = SpreadsheetDocument.Open(fileName, true))
And you are good to add any property to your file.
How to Hide properties
The properties will be visible in Excel through File-> Info -> Properties -> Advanced Properties window. Users will be able to delete them there. If this is not desired, a property won't be visible in excel if instead of this unique id
newProp.FormatId = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}";
another one is used:
newProp.FormatId = Guid.NewGuid().ToString("B");
Note: for saving string use VTLPWSTR type. Do not use type VTBString along with the unique ID given above as Excel automatically deletes your property when you edit it in there (just by experience, I don't know why!).
How to read the properties?
You saved your file. Then, open it again and loop over all properties
foreach (CustomDocumentProperty property in document.CustomFilePropertiesPart.Properties)
{
if (property.Name.Value == nameof(Product) &&
property.VTBString.Text == Product)
return true;
}
where Product is string property holds the name of software, and VTBString is used to save value of Product. As many properties as desired can be saved and read with this method.

c# controlling word file table

I need to create a new word 2016 file, using VS2017, insert content (that's the easy part), and also to control it like doing the following:
Merge certain cells in same row, or same column
Define Right to Left or LTR
color the text/the background.
and more similar tasks.
I can open a document using
using Microsoft.Office;
using Word = Microsoft.Office.Interop.Word;
I can add text and save the document, yet still I don't see a way to fine control the color/direction and more parameters. After reading the documentation, it seems that this is probably not supported, unless I missed it.
I would appreciate if anyone can guide to a detailed documentation how to edit a word file from C# program.
Anyway, I can bypass it by creating an excel file which is simple using Interop and then insert it.
Here is a working solution for merging cells in a table, using VS2017 c#
var doc = DocX.Create(word_fname);
Table table = doc.AddTable(tableSize, 3);
table.Rows[row_cnt].MergeCells(1, 2); // to merge the 2nd & 3rd cells in the specific row

Generate a Word document (docx) using data from an XML file / Convert XML to a Word document based on a template

I have an XML file with the data that I need to be populated on a Word document.
I need to find a way, to define a template which can be used as a base line to populate data from an XML file and create an output document.
I believe there are two ways to do this.
Create an XSLT file which will be the "template" and use this to generate Word documents using it in conjunction with the XML file.
Use content controls in Word to create a template document and somehow map to an XML file.
I just don't know the details on how to implement either way. Or not sure if there is another, easier way to accomplish this task.
Could someone show an example of how this can be implemented. Just a simple example would be sufficient.
I prefer C# for any coding. I am using Word 2016 but want it to be compatible from Word 2007 to Word 2016 and everything in between if possible since users will be using these versions. Thank you!
Figured out how to use content controls to generate documents and how to populate data from an XML into content controls. I've divided this into 2 parts:
Part 1: Create your template document for document generation
Part 2: Use code in C# to generate documents based on template
Part 1: Create your template document for document generation
Create a sample XML based on which you can create the Word template for document generation. Preferably start with a less complicated version to get the hang of it.
I used the following XML for testing. For testing I didn't have repeating sections, pictures etc.
<?xml version="1.0" encoding="utf-8"?>
<mydata xmlns="http://CustomDemoXML.htm">
<field1>This is the value in field1 from the XML file</field1>
<field2>This is the value in field2 from the XML file</field2>
<field3>This is the value in field3 from the XML file</field3>
</mydata>
Note 1: This is will be just a sample XML to create your Word template. XML file(s) with real data in this same format can later be applied when generating Word document(s) from the template.
Note 2: The xmlns attribute can contain literally anything you want and it doesn't have to be a URL starting with http.
Save your sample XML file to any location so that it can be imported to the template you are about to create.
Make sure the Developer tab is enabled on your copy of Word [File -> Options -> Customize Ribbon -> Under Customize the Ribbon, make sure Developer is selected -> OK]. Details: How to: Show the Developer Tab on the Ribbon
Create a new Word document (or use an existing Word document) which will be your template for document generation.
On the Developer tab, click on XML Mapping Pane. This will open the XML Mapping Pane on the right side of the document.
On the XML Mapping Pane, select the Custom XML Part drop down -> Select (Add new part).
Select the XML file that you saved on step 1 -> Open.
On the XML Mapping Pane, select the Custom XML Part drop down -> Select the item with the text that was on the xmlns attribute of the custom XML file. If you use the sample file above, it would be http://CustomDemoXML.htm.
Add a some static text to a Word document and add a Plain Text Content Control next to it (on the Developer tab -> Controls section. Repeat for all fields you need to add.
For the sample XML above, I had the following Word document:
Click on the first Plain Text Content Control -> On the XML Mapping Pane, right click the field you want mapped to that content control -> Click Map to Selected Content Control. Repeat for all the fields you want to map.
Note: Alternatively, instead of adding the Plain Text Content Control items from the developer tab on step #8, you could right click on the field you want to map on the XML Mapping Pane -> Click Insert Content Control -> Click Plain Text.
Similarly, you can also add other types of controls such as checkboxes, date pickers and even repeating sections (it supports nested repeating sections too! - since Word 2013) and map data from XML to those using just native Word functionality and without any third party tools!
Save your template document.
Part 2: Use code in C# to generate documents based on template
This uses Microsoft's recommended OpenXML SDK to generate documents using an XML file containing real data.
Build your XML file/open an existing XML file with which to generate a document from the template created above. This needs to be in the same format as the sample XML file used to create the template.
Use the OpenXML SDK to delete any CustomXMLPart elements from the document. This assumes no other custom XML parts are used in the document which is the case in this example. For complex scenarios, you can delete specific XML parts if needed.
Use the OpenXML SDK to add a new CustomXMLPart based on the XML file in step#1 above.
Here is the sample code I have to "refresh"/"reload" the sample data in the template with a data from an XML file containing real data (assuming the XML file used to generate the document is already created and saved):
using System.IO;
using DocumentFormat.OpenXml.Packaging;
namespace SampleNamespace
{
public static class SampleClass
{
public static void GenerateDocument()
{
string rootPath = #"C:\Temp";
string xmlDataFile = rootPath + #"\MyNewData.xml";
string templateDocument = rootPath + #"\MyTemplate.docx";
string outputDocument = rootPath + #"\MyGeneratedDocument.docx";
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(templateDocument, true))
{
//get the main part of the document which contains CustomXMLParts
MainDocumentPart mainPart = wordDoc.MainDocumentPart;
//delete all CustomXMLParts in the document. If needed only specific CustomXMLParts can be deleted using the CustomXmlParts IEnumerable
mainPart.DeleteParts<CustomXmlPart>(mainPart.CustomXmlParts);
//add new CustomXMLPart with data from new XML file
CustomXmlPart myXmlPart = mainPart.AddCustomXmlPart(CustomXmlPartType.CustomXml);
using (FileStream stream = new FileStream(xmlDataFile, FileMode.Open))
{
myXmlPart.FeedData(stream);
}
}
}
}
}
That's it!
Ok, found a detailed guide on using XSLT as a template to generate the Word document here: Using XSLT and Open XML to Create a Word 2007 Document.
Looks like even though this article is for Word 2007, it works perfectly in Word 2016.
Only issue with this method is if changes are needed to the template later on, it takes a lot of effort to update the xslt file and it's not user friendly to do so since it cannot be updated in Word itself and the actual XML of the document needs to be manipulated.
On the plus side, document generation is VERY flexible with all the power available through XSL (foreach, variables, if conditions etc.)
We created an automated way to have XML file data populate into a Word or PowerPoint document. We utilize an add-in that uses content controls to link the Excel content (ranges, tables, charts, shapes, etc.) to Word or PowerPoint. The links are portable and robust. It's also easy to update if you need to make any changes do your documents. You can find the add-in through your Excel application - just search add-ins "Excel-to-Word Document Automation" through "Get Add-ins" on the Insert tab. You can also find out more about it here.

Get elements inside and outside table element in OpenXML

How can I discriminate the elements inside a table and those outside? And additionally how can I verify tables without a content control name?
I suggest you use Linq To XML. On MSDN there is an example console application that displays all paragraph text of a Word Document.
Near the bottom is a comment - Find all paragraphs in the document - this is the Linq To XML piece that pulls out the paragraphs from the body of the Word document.
// Find all paragraphs in the document.
var paragraphs =
from para in xDoc
.Root
.Element(w + "body")
.Descendants(w + "p") ...
Instead of a "p", you will need to use "tbl". This is how to collect all of the tables from a Document in order to verify their contents. To inspect each row and column will involve more code to loop through the tables data, but this should get you started.
If you install the Open XML Productivity Tool, you can view all of the xml of any Open XML document. The screen below shows the tool with a Word doc containing a table.
[]
The left pane show the structure of a typical table in a Word doc. The right is the Open XML Table spec. The tool helps you know what to read and what to ignore when you are writing your liq to xml code to read and verify the data in your tables.
If you have a specific table format you need to read for your project and you are stuck, post the table and the code you tried in another question. Otherwise based on your original question, this answer should be enough to help you get started towards your solution.

Microsoft Word 2007 VSTO, Create table outside word?

I am using VSTO to fill data into a table in a Microsoft Word 2007 template. The amount of data varies and filling many pages (+50) takes a lot of time.
The code I use to create a table:
Word.Table table = doc.Tables.Add(tablePosition,
numberOfRows,
8,
ref System.Reflection.Missing.Value,
ref System.Reflection.Missing.Value);
I suspect that the time consumption is due to the communication between Visual Studio (C#) and Word each time I insert data into a cell. If this is the case, it might be faster to create the table in C# and afterwards insert it into Word.
The Microsot.Office.Interop.Word.Table is an abstract class - thus I cannot do this
Word.Table table = new Word.Table();
which would have been handy.
Are there other possibilities when just using VSTO?
Try creating the table in HTML Clipboard format, add to clipboard, then paste.
Try creating the table in HTML and inserting it.
Try creating tab-delimited string with newline character for each record. Insert string with selection, convert selection to table using tabs as delimiter.
Create template as XML, transforming data with Xslt into Word XML Document.
Create template as a "Directory Mail Merge", perform mail merge with data.
Depending on your requirements, I recommend using the mail merge technique because the user can edit the template and mail merges are fast, especially if you have 50+ pages.
Although I do similar things with LabVIEW7.1 and Word2000, the problem is similar. I have not found a way to insert blocks of data (table) with one command. There is even a problem when inserting single elements too fast for word, it occasionally hangs than and must be killed in order to solve that. Unfortunately there is no event nor property that signals word's ability to accept the next command and data set - at least I could not find anything.
As this is in a test sequencer I have the time to feed the test results into word with delays long enough to assume word is ready again when the next portion of data is send...

Categories