我一直试图让这个工作好几天,并且作为最后的手段在这里发布。
背景 - 我正在创建一个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(我认为)。
答案 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;我们以同样的方式完成了它。
我希望它有所帮助!