最近的項目(MOSS項目)需要,用戶需要根據word模板生成相關的word文檔,具體需求是根據infopath 表單中的內容和相關的模板生成一份word文檔
著手做之前想想要是用word api操作的話,後台進程,多用戶並發操作等等問題
看來還是用openxml來操作比較好,於是找了找資料,實現了這小小的功能
現在把代碼貼出來跟大家分享下
使用openxml技術時,首先需要引用windowsbase.dll
部分常量
const string documentRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument&quo t;;
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
以上只是貼出了其中主要的代碼
本文配套源碼:http://www.bianceng.net/dotnet/201212/808.htm