none
BuildingBlockEntries and Ranges RRS feed

  • Question

  • Good day,

    The question is regarding - is it possible to create buildingblockentires without a range definition?  I programmatically created a content control, select it's range and add it to the QuickParts gallery, and save this file as a template (.dotx) file. Example Code:  

    objContentControl = ap.ActiveDocument.ContentControls.Add(Word.

    WdContentControlType.wdContentControlRichText, refmissing);

    Word.Range rng = ap.ActiveDocument.Paragraphs[1].Range;

    myCusttemplate.BuildingBlockEntries.Add("MyName"

     

    , Word.WdBuildingBlockTypes.wdTypeQuickParts, "MyCategory", rng, "MyTest"

    );

     

    I attach my custom template to a Word document. When inserting the buildingblock "MyName" into Word, it inserts it at the start position of the current mouse position, not where the cursor is currently position in the active document, believe this is due to the range defined of the buildingblock.  Can a buildingblockentry be added without a range?  Or how can a buildingblockentry be creatd with out range defined?

    Can anyone provide feedback as to how I can insert the buildingblock to the current cursor position in the document?

    Thanks in advance for any information (and hopefully this posted to the correct forum). 

     

    Thursday, April 28, 2011 6:19 PM

Answers

  • Good day Cindy, Rich

    A followup I have solved my issue.  And hopefully will help any other folks out there trying this method:

    Programmatically adding content controls to the quickpart was not working correctly as after the control is added to the gallery, and then inserting using standard Insert --> QuickPart -->  My part it inserted at the starting position of the line and not the cursor potion. 

    The solution was two-fold.

    1. A space " " needs to be inserted PRIOR to the adding the control to the word document, obtaining the entire range. (Example - if you add the control at the beginning of the line, it does not work).

    ap.ActiveWindow.Selection.TypeText(" ");
    Word.Range mainRange = ap.ActiveWindow.Selection.Range;
    objCC = ap.ActiveDocument.ContentControls.AddWord.WdContentControlType.wdContentControlText, mainRange);

    2. Next change (thanks Cindy) was grabbing the specified control/range mimicing selecting keystrokes and moving the selection appropriately.

    ap.ActiveWindow.Selection.HomeKey(Word.WdUnits.wdLine);
    ap.ActiveWindow.Selection.MoveRight(Word.WdUnits.wdCharacter, Count: 1);
    ap.ActiveWindow.Selection.EndKey(Word.WdUnits.wdLine, Extend: Word.WdMovementType.wdExtend);
    ap.ActiveWindow.Selection.MoveLeft(Word.WdUnits.wdCharacter, Count: 1, Extend: Word.WdMovementType.wdExtend);
    Word.Range rng = ap.ActiveWindow.Selection.Range;
    template.BuildingBlockEntries.Add("My Part", Word.WdBuildingBlockTypes.wdTypeQuickParts, "My Data", rng, "My Part", Word.WdDocPartInsertOptions.wdInsertContent);
     

    Thanks for all your assistance. This item can/will be marked as answered.

    • Marked as answer by CoolShaw Tuesday, May 10, 2011 1:22 PM
    Tuesday, May 10, 2011 1:22 PM

All replies

  • Hi CoolShaw,

     

    In VB, I’m C challenged; it seems to me that for creating the building blocks entry it would look like this:

     

    Dim rng As Microsoft.Office.Interop.Word.Range

    wdoc.ActiveDocument.Paragraphs(1).Range.Select()

     rng = wdoc.Selection

     wdoc.NormalTemplate.BuildingBlockEntries.Add("MyName", _

                Microsoft.Office.Interop.Word.WdBuildingBlockTypes.wdTypeQuickParts, _

                "MyCategory", rng, "MyTest", _

                Microsoft.Office.Interop.Word.WdDocPartInsertOptions.wdInsertParagraph)

     

    And then for inserting it in a document it would look something like this:

     

    wdoc.Selection.Select()

    wdoc.NormalTemplate.BuildingBlockEntries.Item("MyName").Insert(wdoc.Selection.Range)

     

    The selection.range for the insert should be the cursor position in the document.


    Regards, Rich
    Thursday, April 28, 2011 10:06 PM
  • Thanks Rich.

    This is clear - here it is in C#. 

    objCC = ap.ActiveDocument.ContentControls.Add(Word.WdContentControlType.wdContentControlRichText, ref missing);
    objCC.Title = "My part";
    objCC.SetPlaceholderText(null, null, "My part");
    objCC.Tag = "My Tag";
    objCC.LockContents = false;

    //Get Range of newly added content control in new document (copied document)
    Word.Range rng = ap.ActiveDocument.Paragraphs[1].Range;

    //Add new content control to the quickpart gallery
    template.BuildingBlockEntries.Add("MyPart", Word.WdBuildingBlockTypes.wdTypeQuickParts, "My Part", rng, "My Part");

    The challenge: the new quickpart entry is not being inserted programmatically. users will access it using normal word funtionality bia the QuickParts ribbon (Insert -> Quick Part -> "My Part").  It inserts at the beginning of the sentence where the curors is, not, for instance, at a tab or right justification... 

    I appreciate any feedback.

    Thanks in advance...


    Monday, May 2, 2011 1:16 PM
  • Piecing some things together,

    How about ...  Word.Selection currentSelection = Application.Selection;

    Then ... template.BuildingBlockEntries.Item("MyName").Insert(currentSelection);

     


    Regards, Rich
    Monday, May 2, 2011 6:21 PM
  • Good Afternoon Rich,

    Thanks so much for your reply and apologies on the late response.

    Using the Word.Selection does not work as buildingblockenties.Add() needs range definition in order to add the item to the template's buildingblock entry...

    I'd appreciate any other ideas...

     

    Regards...

     


    Wednesday, May 4, 2011 7:39 PM
  • To my knowledge a building block quick part should always insert at the current position of the active document. The range property simply defines the quick part entry to add and not the insertion point of the entry. 

    Below is an example that adds the entry into a template’s building blocks. When the user selects the “Title” auto text it is inserted wherever their cursor is positioned.

            Dim objTemplate As Microsoft.Office.Interop.Word.Template

            Dim objBB As Microsoft.Office.Interop.Word.BuildingBlock

            Dim objRange As Microsoft.Office.Interop.Word.Range

     

            ' Set the template to store the building block

            objTemplate = wdoc.ActiveDocument.AttachedTemplate

     

            ' Collapse the range, set the range, and add the text

            wdoc.Selection.Collapse()

            objRange = wdoc.Selection.Range

            objRange.Text = "Building blocks test"

     

            ' Add the building block to the template

            objBB = objTemplate.BuildingBlockEntries.Add( _

                Name:="Title", _

                Type:=Word.WdBuildingBlockTypes.wdTypeAutoText, _

                Category:="LGPro", _

                Range:=objRange)

     

    Maybe I've misunderstood your question and if so please follow-up.


    Regards, Rich
    Thursday, May 5, 2011 3:28 AM
  • Using the Word.Selection does not work as buildingblockenties.Add() needs range definition in order to add the item to the template's buildingblock entry...



    Hi CoolShaw

    Actually, it should be Word.Selection.Range. Word.Selection will work in the VB-languages as its default property is Range, and VB will try that to see if it works. C# doesn't afford you that luxury.

    But you can define any Range, it need not be selected, when adding a BuildingBlock to a template "container". For example, it could be Document.Paragraphs[3].Range or Document.Tables[2].Range

    So you've interpreted the Add method correctly. I think the problem is elsewhere:

    <<When inserting the buildingblock "MyName" into Word, it inserts it at the start position of the current mouse position, not where the cursor is currently position in the active document, believe this is due to the range defined of the buildingblock.  Can a buildingblockentry be added without a range?  Or how can a buildingblockentry be creatd with out range defined?>>

    There's a setting in these newer versions of Word that moves the insertion point to the part of the document being viewed. It's been getting on my nerves the last few days, which is why this occurs to me. I guess this is a good a time as any to refresh my memory which option that is and change the setting on my machine :-)

    Word Options/Advanced, section Editing options. What's been bothering me is this one, and I think it may be the problem your case, as well. Try turning it off:

    "Use smart cursoring    Select this option to specify that the cursor moves as you scroll up or down. When you press the LEFT ARROW, RIGHT ARROW, UP ARROW, or DOWN ARROW key after you scroll, the cursor responds at the page currently in view, not at its previous position."


    Cindy Meister, VSTO/Word MVP
    Thursday, May 5, 2011 7:37 AM
    Moderator
  • Good day Rich, Cindy

    Thank you both for your comments.

    To you both: the need is to create template which consists of content controls based on an XML definition.  I create these controls via a temporary document (where I attach the buildingblocks.dotx), adding each one individual based on the XML property specification and bind the content control. 

    Programmatically --  I add the control to the temp document, SELECT its range, and add the control to the quickpart utilizing the buildingblockentry.Add() method. Using Word.Selection.Range does not work in this scenario because it does not select the content control - I am defining the specific range for the control that's added, e.g. Paragragh[1].

    @Rich - if you right justify, and insert the Document Property "Author" you'll note that the content control inserts where the cursor is, right justified.  This is the functionality I'm attempting to mimic.

    @Cindy, I WISH this was the silver bullet but it did not solve the issue...

    Given the description above - do you think this is possible to implement via code?

    Thanks in advance...

    Thursday, May 5, 2011 2:04 PM
  • Hi CoolShaw

    <<Programmatically --  I add the control to the temp document, SELECT its range, and add the control to the quickpart utilizing the buildingblockentry.Add() method. Using Word.Selection.Range does not work in this scenario because it does not select the content control - I am defining the specific range for the control that's added, e.g. Paragragh[1].>>

    It really shouldn't make any difference whether you're selecting the content control, or just using the Range, but it makes no difference to me whether you do it one way or the other.

    <<if you right justify, and insert the Document Property "Author" you'll note that the content control inserts where the cursor is, right justified.  This is the functionality I'm attempting to mimic.>>

    Most likely the problem is the paragraph formatting that's being saved when you create the building block. Look at the .Add method signature for BuildingBlocks or BuildingBlockEntries: the last argument is InsertOptions. This specifies whether the entry should be inserted as its own paragraph, which would then include the paragraph formatting (alignment in this case), as its own page or "inline". You certainly need the last (which you aren't using in your code snippet earlier), and best to make sure no paragraph mark is included in your selection (or Range) when creating the BuildingBlock.


    Cindy Meister, VSTO/Word MVP
    Thursday, May 5, 2011 4:38 PM
    Moderator
  • Good day Cindy,

     

    Thanks so much for your responses.  I added the definition as you noted but no, no luck. here is the snippet:

    Word.

    Range rng = ap.ActiveDocument.Paragraphs[1].Range;

    template.BuildingBlockEntries.Add("My Part", Word.

    WdBuildingBlockTypes.wdTypeQuickParts, "My Part", rng, "My Part", Word.WdDocPartInsertOptions.wdInsertContent);

     OH how I wish this was the silver bullet.  So frustrating.

    Friday, May 6, 2011 2:14 AM
  • Your defined range still includes the paragraph mark. 

    You'll want the original "Word.Range rng = ap.ActiveDocument.Paragraph(1).Range" to define the starting and ending positions of the range but then to a subtract 1 from the ending position and reset the range based on actiual starting/ending positions.

    rng = ap.ActiveDocument.Range(rngStart, rngEnd - 1);


    Regards, Rich
    Friday, May 6, 2011 3:04 AM
  • Good day Rich,

    As you suggested updated code snippet:

    Word.

    Range

    rng = ap.ActiveDocument.Paragraphs[1].Range;

     

    int

    rngStart = ap.ActiveDocument.Paragraphs[1].Range.Start;

     

    int

    rngEnd = ap.ActiveDocument.Paragraphs[1].Range.End;

    rng = ap.ActiveDocument.Range(rngStart, rngEnd-1);

    Did not work...

    Friday, May 6, 2011 3:22 AM
  • Well I'm kind of out of ideas for now and will have to ponder this some.

    BTW the range position variables should be Int64.


    Regards, Rich
    Friday, May 6, 2011 4:28 AM
  • I really appreciate your assistance. I'll continue to dig.

    Regards...

    Friday, May 6, 2011 10:18 AM
  • Good day Rich, Cindy,

    Thanks so much for all your assistance.  Wanted to elaborate on my findings...  Getting the range of the activedocument.selection (or the specific range where the content control was added to the active document, e.g. Paragraph[1]) - obtains the correct range of the content control to add to the buildingblockentry...

    I tested getting the range of the content control itself however this only obtains the range's text but not the content control.

    Still investigating.


    Friday, May 6, 2011 10:31 AM
  • Hi CoolShaw

    <<I tested getting the range of the content control itself however this only obtains the range's text but not the content control.>>

    Test extending the range by one character to the left and/or to the right (Range.MoveEnd Unit:=Word.WdUnit.wdCharacter, Count:=1 / Range.MoveStart Unit:=Word.WdUnit.wdCharacter, Count:=-1). That should pick up the content control, as I recall.


    Cindy Meister, VSTO/Word MVP
    Sunday, May 8, 2011 8:02 AM
    Moderator
  • Good day Cindy, Rich

    A followup I have solved my issue.  And hopefully will help any other folks out there trying this method:

    Programmatically adding content controls to the quickpart was not working correctly as after the control is added to the gallery, and then inserting using standard Insert --> QuickPart -->  My part it inserted at the starting position of the line and not the cursor potion. 

    The solution was two-fold.

    1. A space " " needs to be inserted PRIOR to the adding the control to the word document, obtaining the entire range. (Example - if you add the control at the beginning of the line, it does not work).

    ap.ActiveWindow.Selection.TypeText(" ");
    Word.Range mainRange = ap.ActiveWindow.Selection.Range;
    objCC = ap.ActiveDocument.ContentControls.AddWord.WdContentControlType.wdContentControlText, mainRange);

    2. Next change (thanks Cindy) was grabbing the specified control/range mimicing selecting keystrokes and moving the selection appropriately.

    ap.ActiveWindow.Selection.HomeKey(Word.WdUnits.wdLine);
    ap.ActiveWindow.Selection.MoveRight(Word.WdUnits.wdCharacter, Count: 1);
    ap.ActiveWindow.Selection.EndKey(Word.WdUnits.wdLine, Extend: Word.WdMovementType.wdExtend);
    ap.ActiveWindow.Selection.MoveLeft(Word.WdUnits.wdCharacter, Count: 1, Extend: Word.WdMovementType.wdExtend);
    Word.Range rng = ap.ActiveWindow.Selection.Range;
    template.BuildingBlockEntries.Add("My Part", Word.WdBuildingBlockTypes.wdTypeQuickParts, "My Data", rng, "My Part", Word.WdDocPartInsertOptions.wdInsertContent);
     

    Thanks for all your assistance. This item can/will be marked as answered.

    • Marked as answer by CoolShaw Tuesday, May 10, 2011 1:22 PM
    Tuesday, May 10, 2011 1:22 PM