我不得不实现一些非常相似的东西,我最终使用了自定义的“PlaceHolder”字段而不是 Word 字段(它们确实有各种限制,例如 - 页眉、页脚和正文都使用不同的对象)。
在我的 word 模板中,我标记了一个像这样的 PlaceHolder - ##MyPlaceHolderName!#。然后,我使用 RegEx 解析 word 模板的文本以查找所有 PlaceHolders,并将它们替换为 InfoPath 表单的实际值。
此解决方案的唯一缺点是,您的 PlaceHolders 和 InfoPath 字段需要具有相同的名称,否则您将无法进行任何匹配。
考虑这种方法:
private void FillDocument(Stream documentStream, string xmlFields)
{
var doc = new XmlDocument();
doc.LoadXml(xmlFields);
var props = doc.SelectSingleNode("properties");
if (props == null) throw new Exception("No properties found.");
//transform the xml properties to dictionary for easier replacement
var fields = props.ChildNodes.Cast<XmlNode>().ToDictionary
(node => string.Format("##{0}!#", node.Name), node => node.InnerText);
using (var document = WordprocessingDocument.Open(documentStream, true))
{
var main = document.MainDocumentPart;
//replace the fields in the main document
main.Document.InnerXml = ReplaceFields(main.Document.InnerXml, fields);
//replace the fields in the headers
foreach (var headerPart in main.HeaderParts)
headerPart.Header.InnerXml = ReplaceFields(headerPart.Header.InnerXml, fields);
//replace the fields in the footers
foreach (var footerPart in main.FooterParts)
footerPart.Footer.InnerXml = ReplaceFields(footerPart.Footer.InnerXml, fields);
main.Document.Save();
}
}
private string ReplaceFields(string xmlPart, Dictionary<string, string> fields)
{
//searches the xml for the declared fields
var fieldRegex = new Regex("##[^#]*!#");
var matches = fieldRegex.Matches(xmlPart);
foreach (Match match in matches)
{
//the fields are within tags (InnerText) so remove all other xml stuff
var innerRegex = new Regex("<[^>]*>");
string fieldName = innerRegex.Replace(match.Groups[0].Value, "");
//replace the actual value of the field
if(fields.ContainsKey(fieldName))
xmlPart = xmlPart.Replace(match.Groups[0].Value, fields[fieldName]);
}
return xmlPart;
}
您将按如下方式使用它:
//open the file from as stream (in this example, the file is opened from SP
using (var stream = templateFile.OpenBinaryStream())
{
//iterate the properties you need and add them in this format
var xmlProperties = "<properties><MyPlaceHolderName>MyPlaceHolderValue</MyPlaceHolderName></properties>";
//fill out the fields
FillDocument(stream, xmlProperties);
}
我知道 Xml-Replacing 和 xmlProperties 相对疯狂,但由于我的要求,我不得不像这样实现它(方法由 InfoPath 的 WebService 调用)。如果您需要进一步的帮助,请告诉我。