Filling Word template fields with C#
Asked Answered
L

3

5

Currently, if I create a Word Document Template with fields, and then fill them using C#, I do it similar to this...

object missing = Type.Missing;
Word.Application app = new Word.Application();
Word.Document doc = app.Documents.Open("file.doc", ref missing, true);
Word.FormFields fields = doc.FormFields;
fields[2].Result = "foo"
fields[3].Result = "bar"

Is there a better way to reference the fields?

I notice when creating the template I can add a Title and a Tag to the field, but I haven't found a way to reference those properties. It would be nice to be able to name fields and reference them directly, instead of just counting and figuring out which field I am on.

Lanellelanette answered 16/10, 2014 at 16:6 Comment(0)
S
4

Are you using legacy forms? When you add a legacy form field to a Word doc, under Properties > Field Settings there is a Bookmark which is basically the name of the field. By default, a legacy text field will have a Bookmark of "Text1", "Text2", etc.

So in VBA:

ActiveDocument.FormFields("Text1").Result = "asdf"

In your case it might be (C#):

doc.FormFields["Text1"].Result = "asdf"

Or you could simply write a loop that scans the list of fields and looks for a given name (pseudo-VB):

Function GetFieldByName(name As String) As Field
    Dim i
    For i = 0 to fields.count - 1
        If fields(i).Name = name Then Return fields(i)
    Next
    Return Nothing
End Function

If you're using the newer form field controls where you can set a Tag and automate with VSTO (C#):

doc.SelectContentControlsByTag("Address")[1].Range.Text = "asdf"

Read more about Content Controls here.

Stovepipe answered 16/10, 2014 at 16:40 Comment(4)
Hey, alright. That last thing you mentioned is what would work for me. I guess I was stuck looking in the Fields and didn't know about ContentControls. Thanks.Lanellelanette
No problem! You gave me enough rep to vote up comments now, so thanks for that.Stovepipe
Hey, just for the record, your example code has a type. The (1) should be [1]. And it really is 1 based, instead of 0, which is kinda odd.Lanellelanette
I updated the answer to clarify, it's one of the very minor differences between VB and C#. VB is lovely :)Stovepipe
O
7

One good way to do it is to, at each place in the template you would like to add text later, place a bookmark (Insert -> Links -> Bookmark). To use them from your code, you would access each bookmark by its name, see this example:

Word._Application wApp = new Word.Application();
Word.Documents wDocs = wApp.Documents;
Word._Document wDoc = wDocs.Open(ref "file_path_here", ReadOnly:false);
wDoc.Activate();

Word.Bookmarks wBookmarks = wDoc.Bookmarks;
Word.Bookmark wBookmark = wBookmarks["Bookmark_name"];
Word.Range wRange = wBookmark.Range;
wRange.Text = valueToSetInTemplate;
Obmutescence answered 16/10, 2014 at 16:19 Comment(1)
Does this method require Microsoft Word be installed on the server this code runs from?Nally
S
4

Are you using legacy forms? When you add a legacy form field to a Word doc, under Properties > Field Settings there is a Bookmark which is basically the name of the field. By default, a legacy text field will have a Bookmark of "Text1", "Text2", etc.

So in VBA:

ActiveDocument.FormFields("Text1").Result = "asdf"

In your case it might be (C#):

doc.FormFields["Text1"].Result = "asdf"

Or you could simply write a loop that scans the list of fields and looks for a given name (pseudo-VB):

Function GetFieldByName(name As String) As Field
    Dim i
    For i = 0 to fields.count - 1
        If fields(i).Name = name Then Return fields(i)
    Next
    Return Nothing
End Function

If you're using the newer form field controls where you can set a Tag and automate with VSTO (C#):

doc.SelectContentControlsByTag("Address")[1].Range.Text = "asdf"

Read more about Content Controls here.

Stovepipe answered 16/10, 2014 at 16:40 Comment(4)
Hey, alright. That last thing you mentioned is what would work for me. I guess I was stuck looking in the Fields and didn't know about ContentControls. Thanks.Lanellelanette
No problem! You gave me enough rep to vote up comments now, so thanks for that.Stovepipe
Hey, just for the record, your example code has a type. The (1) should be [1]. And it really is 1 based, instead of 0, which is kinda odd.Lanellelanette
I updated the answer to clarify, it's one of the very minor differences between VB and C#. VB is lovely :)Stovepipe
D
0

For my particular document we had to address it differently because the elements were variables.

object missing = Type.Missing;
Word.Application app = new Word.Application();
Word.Document doc = app.Documents.Open(@"C:\\test1.dot", ref missing, true);
doc.Activate(); 
doc.Variables["CASE PLAN_PLAN_STATUS"].Value = "asdf1";
Dosage answered 8/6, 2020 at 16:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.