OpenXML 替换word模板中的标签
最近的项目(MOSS项目)需要,用户需要根据word模板生成相关的word文档,具体需求是根据infopath表单中的内容和相关的模板生成一份word文档
着手做之前想想要是用word api操作的话,后台进程,多用户并发操作等等问题
看来还是用openxml来操作比较好,于是找了找资料,实现了这小小的功能
现在把代码贴出来跟大家分享下
使用openxml技术时,首先需要引用windowsbase.dll
部分常量
const string documentRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
const string strUri = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
static List<string> bookmarkText;
string bookmarkName;
该方法是将模板中所有标签都取出,并放到一个datatable中
void bindTable(string fileName)
{
dt = new DataTable();
dt.Columns.Add("标签", typeof(string));
dt.Columns.Add("内容", typeof(string));
DataRow dr;
Stream strm = null;
PackagePart documentPart;
Package package;
using (SPSite site = new SPSite("http://ascentn-moss:8686/"))
{
SPWeb web = site.OpenWeb();
strm = web.GetFile(fileName).OpenBinaryStream();
documentPart = null;
package = Package.Open(strm, FileMode.Open, FileAccess.ReadWrite);
//FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate);
//PackagePart documentPart = null;
//Package package = Package.Open(fileName, FileMode.Open, FileAccess.ReadWrite);
//MessageBox.Show(strm.Length.ToString());
// Package package = Package.Open(strm, FileMode.Open, FileAccess.ReadWrite);
foreach (System.IO.Packaging.PackageRelationship documentRelationship in package.GetRelationshipsByType(documentRelationshipType))
{
NameTable nt = new NameTable();
XmlNamespaceManager nsManager = new XmlNamespaceManager(nt);
nsManager.AddNamespace("w", strUri);
Uri documentUri = PackUriHelper.ResolvePartUri(new Uri("/", UriKind.Relative), documentRelationship.TargetUri);
documentPart = package.GetPart(documentUri);
XmlDocument xdoc = new XmlDocument();
xdoc.Load(documentPart.GetStream());
XmlNodeList nodeList = xdoc.SelectNodes("//w:bookmarkStart", nsManager);
foreach (XmlNode node in nodeList)
{
dr = dt.NewRow();
if (node.NextSibling.Name.ToString() == "w:bookmarkEnd")
{
bookmarkText = new List<string>();
bookmarkName = node.Attributes["w:name"].Value;
bookmarkText.Add(" ");
dr[0] = bookmarkName;
//dataGridView
}
else
{
bookmarkName = node.Attributes["w:name"].Value;
dr[0] = bookmarkName;
string bookmarkId = node.Attributes["w:id"].Value;
bookmarkText = new List<string>();
XmlNode nextParentNode = node.ParentNode;
XmlNode nodeIterate = node.NextSibling;
while (nodeIterate.Name.ToString() != "w:bookmarkEnd")
{
if (nodeIterate.Name.ToString() == "w:r")
bookmarkText.Add(nodeIterate.InnerText);
nodeIterate = nodeIterate.NextSibling;
if (nodeIterate == null)
{
if (nextParentNode.NextSibling.Attributes.Count != 0)
{
if ((nextParentNode.NextSibling.Attributes["w:id"].Value == bookmarkId))
{
nodeIterate = nextParentNode.NextSibling;
}
}
else
{
nextParentNode = nextParentNode.NextSibling;
nodeIterate = nextParentNode.FirstChild;
bookmarkText.Add('\n' + nodeIterate.InnerText);
}
}
}
//dic.Add(bookmarkName, bookmarkText);
}
dt.Rows.Add(dr);
}
}
package.Close();
}
}
接下来需要做的是用infopath中的相关节点去逐个替换标签内容
#region 处理标签
string spUrl = (string)ds["SPServer"];
APWS.Service apws = new APWS.Service();
apws.Url = spUrl + "/spsws/Service.asmx";
apws.Credentials = WFSystem.GetSystemUserCredential();
System.IO.MemoryStream fileStream = new System.IO.MemoryStream();
string newfilename = string.Empty;
if(fileLocation.EndsWith("/"))
newfilename = fileLocation + fileName + template.Substring(template.LastIndexOf('.'));
else
newfilename = fileLocation +"/"+ fileName + template.Substring(template.LastIndexOf('.'));
apws.SPCopyFile(template, newfilename);
fileStream.Write(apws.SPOpenBinary(newfilename), 0, apws.SPGetFileLenght(newfilename));
originalDocPackage = Package.Open(fileStream, FileMode.Open, FileAccess.ReadWrite);
foreach (PackageRelationship relationship in originalDocPackage.GetRelationshipsByType(documentRelationshipType))
{
Uri documentUri = PackUriHelper.ResolvePartUri(new Uri("/", UriKind.Relative), relationship.TargetUri);
originalDocumentPart = originalDocPackage.GetPart(documentUri);
break;
}
originalXmlDocument = new XmlDocument();
originalXmlDocument.Load(originalDocumentPart.GetStream());
NameTable nt = new NameTable();
XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(nt);
xmlNamespaceManager.AddNamespace("w", strUri);
#region 多个书签循环检索
XmlNodeList bookmarknodeList = originalXmlDocument.SelectNodes("//w:bookmarkStart", xmlNamespaceManager);
XmlNodeList bookmarknodeEndList = originalXmlDocument.SelectNodes("//w:bookmarkEnd", xmlNamespaceManager);
XmlNode parentNodeOfBookMark;
foreach (XmlNode xmlnode in bookmarknodeList)
{
foreach (string columnName in hvalues.Keys)
{
if (xmlnode.Attributes["w:name"].Value == columnName)
{
if (xmlnode.NextSibling.Name == "w:r")
{
xmlnode.NextSibling.RemoveChild(xmlnode.NextSibling.LastChild);
XmlElement textElement = originalXmlDocument.CreateElement("w:t", strUri);
xmlnode.NextSibling.AppendChild(textElement);
XmlNode textNode = originalXmlDocument.CreateNode(XmlNodeType.Text, "w:t", strUri);
if(hvalues[columnName].ToString().EndsWith("T00:00:00"))
textNode.Value = hvalues[columnName].ToString().Substring(0,hvalues[columnName].ToString().IndexOf('T'));
else
textNode.Value = hvalues[columnName].ToString();
textElement.AppendChild(textNode);
}
}
}
parentNodeOfBookMark = xmlnode.ParentNode;
parentNodeOfBookMark.RemoveChild(xmlnode);
}
foreach (XmlNode xmlnode in bookmarknodeEndList)
{
parentNodeOfBookMark = xmlnode.ParentNode;
parentNodeOfBookMark.RemoveChild(xmlnode);
}
#endregion
//save document
originalXmlDocument.Save(originalDocumentPart.GetStream(FileMode.Create, FileAccess.Write));
byte[] bs = fileStream.ToArray();
apws.SPSaveBinary(newfilename, bs);
originalDocPackage.Close();
#endregion
以上只是贴出了其中主要的代码

浙公网安备 33010602011771号