Conditional Fields RRS feed

  • Question

  • Hi,

    I've been looking at using fields to turn on / turn off ranges of a document based on the value of a custom document property. Adding a field such as:

    { if {docproperty xyzzy} = 0 "Zero" "One" }

    will basically show the text "Zero" or "One" depending on the value of the custom property which is fine. If I then edit the field and insert an image within the text "One" then then image is conditionally displayed too.

    Taking this one set further I'd like to be able to drag select a region and then add a condition field to the selected region so effectively I'd like to create, in code, something like:

    { if {docproperty xyzzy} = 0 "<selected range." "" }

    A field can be added with code such as:

                Range r = Globals.ThisAddIn.Application.Selection.Range;

                object fieldIF = WdFieldType.wdFieldIf;

                object fieldDocProperty = WdFieldType.wdFieldDocProperty;

                Field f = r.Fields.Add(r, ref fieldIF, "{XYZZY} = 0 \"FRIDAY\" \"THURSDAY\"", true);

                Range ifExpressionRange = f.Code;

                var find1 = ifExpressionRange.Find.Execute("{XYZZY}");

                Object xyxxy = "XYZZY";
                r.Fields.Add(ifExpressionRange, ref fieldDocProperty, ref xyxxy, false);

    But I don't want the text "FRIDAY" and "THURSDAY", I want to inject the selected range. Any suggestions would be greatly appreciated.


    Friday, August 10, 2018 3:30 PM

All replies

  • In VBA, you might use something like:

    Sub Demo()
    Dim Rng As Range
    Set Rng = ActiveDocument.Paragraphs(2).Range
    With Rng
      .InsertBefore "= 0 """
      .Collapse wdCollapseStart
      .Fields.Add .Duplicate, wdFieldEmpty, "DOCPROPERTY Condition", False
      .End = .Paragraphs(1).Range.End - 1
      .InsertBefore "IF"
      .InsertAfter """"
      .Fields.Add .Duplicate, wdFieldEmpty, , False
    End With
    End Sub
    where 'Condition' is the name of your document property. To include the terminating paragraph break, omit the '- 1'. I'll leave it to you to do the necessary adaptation.

    Paul Edstein
    [MS MVP - Word]

    Friday, August 10, 2018 11:29 PM
  • Very good work with the complex field construction :-)

    My preference would be to work with a second Range object for inserting the field, leaving the original Selection.Range intact until the end. The sample code below inserts the field immediately after the Selection. It uses Range.Duplicate to make a shallow copy of the Range. (Word's Range objects are unique in the object model in that, if you set one Range equal to another Range the Ranges are linked - changing one changes the other.)

    This Range is then collapsed to its end-point so that the Selection is not over-written.

    Find.Execute returns a boolen, and the code sample uses that to determine whether the Find was successful.

    A second Find is executed to get the position of "Friday". The selection is then written to the found Range using Range.FormattedText. And then the original Range is deleted. Finally, the field is updated.

                Word.Range r = Globals.ThisAddIn.Application.Selection.Range;
                Word.Range rField = r.Duplicate;
                object oCollapseEnd = Word.WdCollapseDirection.wdCollapseEnd;
                rField.Collapse(ref oCollapseEnd);
                object fieldIF = Word.WdFieldType.wdFieldIf;
                object fieldDocProperty = Word.WdFieldType.wdFieldDocProperty;
                Word.Field f = rField.Fields.Add(rField, ref fieldIF, "{XYZZY} = 0 \"FRIDAY\" \"THURSDAY\"", true);
                Word.Range ifExpressionRange = f.Code;
                bool find1 = ifExpressionRange.Find.Execute("{XYZZY}");
                if (find1)
                    Object xyxxy = "XYZZY";
                    Word.Field fldComplex = rField.Fields.Add(ifExpressionRange, ref fieldDocProperty, ref xyxxy, false);
                    bool find2 = ifExpressionRange.Find.Execute("Friday");
                    if (find2)
                        ifExpressionRange.FormattedText = r.FormattedText;
                        System.Diagnostics.Debug.Print("Not found");

    Cindy Meister, Office Developer/Word MVP, <a href=""> my blog</a>

    Sunday, August 19, 2018 11:41 AM