使用 Word 2007 XML 对象模型从 Word 模板生成 Word 文档






2.50/5 (6投票s)
如何使用 Word 2007 XML 格式从 Word 模板生成 Word 文档。
引言
在许多项目中,开发人员需要以特定格式或从模板生成 Word 文档中的报告。 使用服务器端 Word 实例化来生成这些文档的旧方法会消耗大量服务器资源,不建议使用。 一种替代方法是使用 Word 2007 XML 对象进行 Word 生成。 可以此处找到有关 Word 2007 XML 格式的基本信息。
本文涵盖了通过填充书签及其样式,从服务器上的模板生成合同文档。
Using the Code
此代码需要 Word 2007 和 .NET Framework 3.0 或更高版本才能工作。.NET 3.0 附带一个名为 WindowsBase.dll 的特殊 DLL 和一个名为 System.IO.Packaging
的命名空间,用于在不实例化服务器上的 Word 对象的情况下生成 Word 文档。
//Namespaces required
using System.IO;
using System.IO.Packaging;
using System.Xml;
using System.Collections.Generic;
//Variable and constants.
const string documentRelationshipType =
"http://schemas.openxmlformats.org/" +
"officeDocument/2006/relationships/officeDocument";
const string headerContentType =
"application/vnd.openxmlformats-" +
"officedocument.wordprocessingml.header+xml";
const string footerContentType =
"application/vnd.openxmlformats-" +
"officedocument.wordprocessingml.footer+xml";
XmlNamespaceManager nsManager;
//Method which will create the documents on the fly.
private void CreateWordDocument()
{
Random RandomClass = new Random();
int randomInt = RandomClass.Next();
//Word template file
string templateName = "Template.docx";
//New file name to be generated from
string docFileName = "Doc_" + randomInt + ".docx";
File.Copy(Server.MapPath(@"_Documents/" + templateName),
Server.MapPath(@"_Documents/" + docFileName),true);
string fileName = Server.MapPath(@"_Documents/" + docFileName);
PackagePart documentPart = null;
Package package =
Package.Open(fileName, FileMode.Open, FileAccess.ReadWrite);
// Get the main document part (document.xml).
foreach (System.IO.Packaging.PackageRelationship documentRelationship
in package.GetRelationshipsByType(documentRelationshipType))
{
NameTable nt = new NameTable();
nsManager = new XmlNamespaceManager(nt);
nsManager.AddNamespace("w",
"http://schemas.openxmlformats.org/wordprocessingml/2006/main");
Uri documentUri = PackUriHelper.ResolvePartUri(
new Uri("/", UriKind.Relative), documentRelationship.TargetUri);
documentPart = package.GetPart(documentUri);
#region Update Document Bookmarks
//Get document xml
XmlDocument xdoc = new XmlDocument();
//xdoc.Load(documentPart.GetStream());
xdoc.Load(documentPart.GetStream(FileMode.Open,FileAccess.Read));
//Select all bookmark nodes
XmlNodeList nodeList =
xdoc.SelectNodes("//w:bookmarkStart", nsManager);
foreach (XmlNode node in nodeList)
{
// S_ADDRESS_V1 and S_ADDRESS_V2 are
// the bookmarks defined in the template
if(this.SetBookmarkText(xdoc, node, "S_ADDRESS_V1",
RandomClass.Next().ToString())) continue;
if (this.SetBookmarkText(xdoc, node, "S_ADDRESS_V2",
RandomClass.Next().ToString())) continue;
}
#endregion
#region Update Header/Footer Bookmarks
PackagePartCollection documentParts = package.GetParts();
foreach (PackagePart part in documentParts)
{
//Update header bookmarks
if (part.ContentType == headerContentType)
{
//Get document xml
XmlDocument xheader = new XmlDocument();
xheader.Load(part.GetStream(FileMode.Open, FileAccess.Read));
//Select all bookmark nodes
XmlNodeList headerNodeList =
xheader.SelectNodes("//w:bookmarkStart", nsManager);
foreach (XmlNode node in headerNodeList)
{
//HEADER5 is the bookmark of header in template
if (this.SetBookmarkText(xheader, node,
"HEADER5", "Test Header")) continue;
}
//Save
if (headerNodeList.Count > 0)
{
StreamWriter streamHeader =
new StreamWriter(part.GetStream(FileMode.Open, FileAccess.Write));
xheader.Save(streamHeader);
streamHeader.Close();
}
}
//Update footer bookmarks
if (part.ContentType == footerContentType)
{
//Get document xml
XmlDocument xfooter = new XmlDocument();
xfooter.Load(part.GetStream(FileMode.Open, FileAccess.Read));
//Select all bookmark nodes
XmlNodeList footerNodeList =
xfooter.SelectNodes("//w:bookmarkStart", nsManager);
foreach (XmlNode node in footerNodeList)
{
//FOOTER_1_1
if (this.SetBookmarkText(xfooter, node,
"FOOTER_1_1", "Number", true)) continue;
if (this.SetBookmarkText(xfooter, node,
"FOOTER_1_2", "123456", true)) continue;
}
//Save
if (footerNodeList.Count > 0)
{
StreamWriter streamFooter =
new StreamWriter(part.GetStream(FileMode.Open, FileAccess.Write));
xfooter.Save(streamFooter);
streamFooter.Close();
}
}
}
#endregion
StreamWriter streamPart = new StreamWriter(
documentPart.GetStream(FileMode.Open, FileAccess.Write));
xdoc.Save(streamPart);
streamPart.Close();
}
package.Flush();
package.Close();
////send response to browser
/*string File_Name = "_Documents/" + docFileName;
string popupScript = "<script language="'javascript'">" +
"window.open('" + File_Name + "', 'Document', " +
"'width=700, height=600, menubar=yes, resizable=yes')" +
"</script>";
ClientScript.RegisterClientScriptBlock(this.GetType(),
"PopupScriptOffer", popupScript);
*/
}
/// <summary>
///
/// </summary>
/// <param name="xdoc"></param>
/// <param name="node"></param>
/// <param name="bookmarkName"></param>
private bool SetBookmarkText(XmlDocument xdoc, XmlNode node,
string bookmarkName, string bookmarkValue)
{
if (node.NextSibling.Name.ToString() == "w:bookmarkEnd")
{
if (node.Attributes["w:name"].Value == bookmarkName)
{
//get the node previous sibling style
//("w:rPr") to apply to the bookmark text
XmlNode nodeStyle = node.PreviousSibling.CloneNode(true);
//parent node "w:p"
XmlNode bookmrkParent = node.ParentNode;
XmlElement tagRun;
tagRun = xdoc.CreateElement("w:r",
nsManager.LookupNamespace("w"));
bookmrkParent.AppendChild(tagRun);
//if (nodeStyle != null && nodeStyle.FirstChild.Name == "w:rPr")
// tagRun.AppendChild(nodeStyle.FirstChild);
if (nodeStyle.SelectSingleNode("//w:rPr", nsManager) != null)
tagRun.AppendChild(nodeStyle.SelectSingleNode("//w:rPr", nsManager));
XmlElement tagText;
tagText = xdoc.CreateElement("w:t",
nsManager.LookupNamespace("w"));
tagRun.AppendChild(tagText);
//*** insert text into part as a Text node
XmlNode nodeText;
nodeText = xdoc.CreateNode(XmlNodeType.Text,
"w:t", nsManager.LookupNamespace("w"));
nodeText.Value = bookmarkValue;
tagText.AppendChild(nodeText);
return true;
}
}
return false;
}
private bool SetBookmarkText(XmlDocument xdoc, XmlNode node,
string bookmarkName, string bookmarkValue, bool IsFooter)
{
if (node.NextSibling.Name.ToString() == "w:bookmarkEnd")
{
if (node.Attributes["w:name"].Value == bookmarkName)
{
//get the node previous sibling style
//("w:rPr") to apply to the bookmark text
XmlNode nodeStyle = node.PreviousSibling.CloneNode(true);
//parent node "w:p"
XmlNode bookmrkParent = node.ParentNode;
XmlElement tagRun;
tagRun = xdoc.CreateElement("w:r",
nsManager.LookupNamespace("w"));
bookmrkParent.AppendChild(tagRun);
if (nodeStyle.SelectSingleNode("//w:rPr", nsManager) != null)
{
XmlNode xfootStyle =
nodeStyle.SelectSingleNode("//w:rPr", nsManager);
//reduce font size for footer to 16. <w:sz w:val="20" />
/*if (IsFooter)
{
xfootStyle.SelectSingleNode("//w:sz",
nsManager).Attributes["w:val"].Value = "16";
}*/
tagRun.AppendChild(xfootStyle);
}
XmlElement tagText;
tagText = xdoc.CreateElement("w:t",
nsManager.LookupNamespace("w"));
tagRun.AppendChild(tagText);
//*** insert text into part as a Text node
XmlNode nodeText;
nodeText = xdoc.CreateNode(XmlNodeType.Text,
"w:t", nsManager.LookupNamespace("w"));
nodeText.Value = bookmarkValue;
tagText.AppendChild(nodeText);
return true;
}
}
return false;
}