4

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.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
erosebe
  • 927
  • 3
  • 16
  • 31

3 Answers3

6

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;
helrich
  • 1,300
  • 1
  • 15
  • 34
  • 1
    Does this method require Microsoft Word be installed on the server this code runs from? – Ben Apr 25 '22 at 18:10
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.

perry
  • 266
  • 1
  • 6
  • 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. – erosebe Oct 16 '14 at 16:43
  • No problem! You gave me enough rep to vote up comments now, so thanks for that. – perry Oct 16 '14 at 16:54
  • 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. – erosebe Oct 17 '14 at 17:33
  • I updated the answer to clarify, it's one of the very minor differences between VB and C#. VB is lovely :) – perry Oct 17 '14 at 17:54
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";
gman
  • 167
  • 1
  • 16