如何使用OpenXML

时间:2017-04-25 10:44:51

标签: c# asp.net xml checkbox openxml

我一直试图让这个工作好几天,并且作为最后的手段在这里发布。

背景 - 我正在创建一个Web应用程序,允许用户将数据输入到网页中,并使用占位符将此数据转换为Microsoft Word文档。此Word文档是一个模板,可以填充数据并保存到用户计算机。

功能已解决 - 我已设法使用用户数据填充所有必需的文本字段。这根本不是问题。我创建了一个搜索和替换方法,为我做了所有这些,所以我不是要求与此相关的帮助。

问题 - 用户在网页上输入的数据中包含几个布尔值。这些布尔值将用于检查或取消选中Word文档中的某些复选框。 Word文档中的每个复选框都有一个需要用来定位它的书签。我已经尝试了几种方法来搜索Word文档的整个xml并更改分配给该特定Checkbox元素的值。

从Word模板中提取的样本xml

<w:document>
<w:body>        
    <w:tbl>         
        <w:tr>          
            <w:tc>          
                <w:p w:rsidR="007D2E4C" w:rsidRPr="00233E81" w:rsidRDefault="007D2E4C" w:rsidP="007D2E4C">
                    <w:r>   
                        <w:fldChar w:fldCharType="begin">
                            <w:ffData>
                                <w:name w:val="cbxmeal0"/>
                                <w:enabled/>
                                <w:calcOnExit w:val="0"/>
                                <w:checkBox>
                                    <w:sizeAuto/>
                                    <w:default w:val="0"/>
                                </w:checkBox>
                            </w:ffData>
                        </w:fldChar>
                    </w:r>
                    <w:bookmarkStart w:id="10" w:name="cbxmeal0"/>
                    <w:r>
                        <w:rPr>
                            <w:sz w:val="20"/>
                        </w:rPr>
                        <w:instrText xml:space="preserve"> FORMCHECKBOX </w:instrText>
                    </w:r>
                    <w:r w:rsidR="00B128CE">
                        <w:rPr>
                            <w:sz w:val="20"/>
                        </w:rPr>
                    </w:r>
                    <w:r w:rsidR="00B128CE">
                        <w:rPr>
                            <w:sz w:val="20"/>
                        </w:rPr>
                        <w:fldChar w:fldCharType="separate"/>
                    </w:r>
                    <w:r>
                        <w:rPr>
                            <w:sz w:val="20"/>
                        </w:rPr>
                        <w:fldChar w:fldCharType="end"/>
                    </w:r>
                    <w:bookmarkEnd w:id="10"/>
                </w:p>
            </w:tc>
        </w:tr>
    </w:tbl>
</w:body>

上面的xml文本是超简化版本,但结构完全相同。这里有一个更简单的结构版本Document > Body > Table > Table_Row > Table_Cell > Paragraph > Run > Field_Char > Form_Field_Data > Checkbox

下面是我在查找书签和复选框时迭代xml文本的极其难看的方式。注意:我只是计划让它工作,然后我会稍后进行优化。

            foreach (var table in document.MainDocumentPart.Document.Body.ChildElements.Where(t => t is DocumentFormat.OpenXml.Wordprocessing.Table))
        {
            foreach (var row in table.ChildElements.Where(r => r is DocumentFormat.OpenXml.Wordprocessing.TableRow))
            {
                foreach (var cell in row.ChildElements.Where(c => c is DocumentFormat.OpenXml.Wordprocessing.TableCell))
                {
                    foreach (var paragraph in cell.ChildElements.Where(p => p is DocumentFormat.OpenXml.Wordprocessing.Paragraph))
                    {
                        foreach (var run in paragraph.ChildElements.Where(r => r is DocumentFormat.OpenXml.Wordprocessing.Run))
                        {
                            foreach (var fieldChar in run.ChildElements.Where(fc => fc is DocumentFormat.OpenXml.Wordprocessing.FieldChar))
                            {
                                foreach (var formFieldData in fieldChar.ChildElements)
                                {
                                    foreach (var child in formFieldData.ChildElements)
                                    {
                                        //Check bookmark name
                                        //If bookmark name matches, 
                                        //Set checkbox value to true
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

如果有人可以提供任何帮助,无论是网站地址还是实际代码,这将非常有帮助,因为我对此任务失去信心!另外,请原谅我的LINQ用法,因为我很少使用它!

软件 - 我正在使用Visual Studio 2015,Microsoft Office 2016和OpenXML 2.6(我认为)。

1 个答案:

答案 0 :(得分:1)

这应该对你有帮助。

using (var wordDoc = WordprocessingDocument.Open(@"C:\test\cb\checkbox.docx", true))
{
    MainDocumentPart mainPart = wordDoc.MainDocumentPart;
    var document = mainPart.Document;
    var bookmarks = document.Body.Descendants<BookmarkStart>();

    var myBookmark = bookmarks.First(bms => bms.Name == "cbxmeal0");
    Paragraph paragraph = (Paragraph)myBookmark.Parent;

    Run myCheckbox = (Run)paragraph.Descendants<FieldCode>().First().Parent;
    Run newRun = new Run(@"
<w:r xmlns:w=""http://schemas.openxmlformats.org/wordprocessingml/2006/main"">
    <w:fldChar w:fldCharType=""begin"">
        <w:ffData>
            <w:name w:val=""cbxmeal0"" />
            <w:enabled />
            <w:calcOnExit w:val=""0"" />
            <w:checkBox>
                <w:sizeAuto />
                <w:default w:val=""1"" />
            </w:checkBox>
        </w:ffData>
    </w:fldChar>
</w:r>
");
    paragraph.InsertBefore(newRun, myCheckbox);
}

我已根据您提供的XML创建了Word文档。前几行只是我放大包含你的复选框的Run。

有趣的是,&#34; newRun&#34;我创造。您可以使用XML创建代码,这是我已经完成的,但简单地说,它添加了一个&#34; FieldChar&#34;到您的复选框,将其设置为选中。我不太确定在包含复选框的Run之前插入它是否很重要,但在我的测试中,它是Word自己做的,这就是为什么我&我#39;我们以同样的方式完成了它。

我希望它有所帮助!