Open XML word content controls

北战南征 提交于 2019-12-11 03:07:12

问题


Here is my code trying to get the content controls with the tag "company"

                using (WordprocessingDocument template = WordprocessingDocument.Open("d:/dev/ProposalTemplate1.dotx", true))
                {
                MainDocumentPart mainPart = template.MainDocumentPart;
                SdtBlock block = mainPart.Document.Body.Descendants<SdtBlock>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "TEST").Single();
                Text t = block.Descendants<Text>().Single();
                t.Text = "COMPANY_NAME"; 
                }

I got the error "Object reference not set to an instance of an object" because of the query line but I don't know why...

This works well when I create a simple template with just one content controls but not when using a bigger word template

Any idea ?

EDIT I try doing it without .Single() but still not working

            MainDocumentPart mainPart = template.MainDocumentPart;
            var blocks = mainPart.Document.Body.Descendants<SdtBlock>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "Company");
            foreach (SdtBlock block in blocks)
            {
                Text t = block.Descendants<Text>().Single();
                t.Text = "COMPANY1";
            }

EDIT 2 I change the Text.Single() The problem is still there "Object reference not set to an instance of an object" on the SdtBlock block = ... line

            MainDocumentPart mainPart = template.MainDocumentPart;
            var blocks = mainPart.Document.Body.Descendants<SdtBlock>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "Company");
            foreach (SdtBlock block in blocks)
            {
                var t = block.Descendants<Text>();
                foreach (Text text in t)
                {
                    text.Text = "COMPANY1";
                }
            }

回答1:


Not all SdtBlock elements have child Tag elements. You are assuming one exists and attempting to access the Val property but are getting a null reference exception in doing so.

You can fix it by checking for null within the Where predicate:

var blocks = mainPart.Document.Body.Descendants<SdtBlock>().Where(r => 
    {
        var tag = r.SdtProperties.GetFirstChild<Tag>();
        return tag != null && tag.Val == "Company";
    });

As per the comments there is more information about the issues you originally had with using Single in my answer here.




回答2:


Try this:

foreach( SdtBlock sdt in sdtList )
                    {
                        if( sdt.SdtProperties != null )
                        {
                            Tag tag = sdt.SdtProperties.GetFirstChild<Tag>();

                            if( tag!= null )
                            {
                                if( tag.Val.Value == "Company" )
                                {
                                    if( sdt.InnerText != string.Empty )
                                    {
                                        //Do something
                                    }
                                }
                            }
                        }
                    }



回答3:


Accepted solution returns no results on my query either. So i come up with this solution;

var doc = document.MainDocumentPart.Document;
List<Tag> sdtSubTable = doc.Body.Descendants<Tag>().Where(r =>
{
return r != null && r.Val.Value.Contains("Company");
}).ToList();


来源:https://stackoverflow.com/questions/29532841/open-xml-word-content-controls

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!