Erik
Erik

Reputation: 954

Why does this docx-processing code not work/compile?

I have this code, which processes a Word docx file:

void bookmarkReplace(BookmarkStart bms, Dictionary<string, string> values )
{
    foreach( var key in values)
    {
        string bookmarkName = bms.Name;
        if (bms.Name.Equals( key.Key))
        {

            bms.InsertBeforeSelf<BookmarkStart>(new Run(new Text(key.Value)));
            bms.Remove();
            break;
        }
    }
}

and it does not even compile . The InsertBeforeSelf gives an error: "has some invalid arguments", because before the BookmarkStart, you may not insert other types than BookmarkStart. Weird. Why would that be ? My Word docx file shows a <w:pRr> element before a BookmarkStart element:

<w:p w14:paraId="49842CE1" w14:textId="1248047E" w:rsidR="000C7F1A" w:rsidRDefault="000C7F1A" w:rsidP="00BB4EA3">
    <w:pPr>
       <w:spacing w:after="0" w:line="240" w:lineRule="auto"/>
       <w:jc w:val="right"/>
       <w:rPr>
          <w:lang w:val="en-US"/>
       </w:rPr>
    </w:pPr>
    <w:bookmarkStart w:id="17" w:name="FlexLV"/>
    <w:bookmarkEnd w:id="17"/>
</w:p>

Any suggestions as to how to solve this problem of replacing a BookmarkStart with a text run? btw: later in the program, I remove all BookmarkStart and BookmarkEnd elements.

Upvotes: 0

Views: 89

Answers (1)

petelids
petelids

Reputation: 12815

InsertBeforeSelf is generic with the generic type T being the type of the new element that you are inserting, not the type of the element you are inserting it before. This line:

bms.InsertBeforeSelf<BookmarkStart>(new Run(new Text(key.Value)));

is saying you want to insert a BookmarkStart before bms and the BookmarkStart you wish to insert is a new Run. Clearly a Run is not a BookmarkStart so you get a compile error:

cannot convert from 'DocumentFormat.OpenXml.Wordprocessing.Run' to 'DocumentFormat.OpenXml.Wordprocessing.BookmarkStart'

The fix is easy enough, you need to define the generic type as a Run as that's what you're actually inserting:

bms.InsertBeforeSelf<Run>(new Run(new Text(key.Value)));

Simpler still, you can forgo the type altogether and let the compiler infer it from the parameter:

bms.InsertBeforeSelf(new Run(new Text(key.Value))); //the compiler infers that T is a Run

Upvotes: 1

Related Questions