12 读写openxml
offic2007都是用openxml来构建,当我们在文档中插入一个图表,该图表的样式数据会已xml文件的形式保存在文件charts目录下。我们也可以自定义xml文件然后绑定到文档中。在服务器上程序只需求修改xml文件就可以改变文档中绑定的数据。
下面我们试验通过Package对象来取得docx文件中的xml文件。提示一下:对docx操作的代码不能直接写在该docx文档的工程中,否则系统会提示该文件已经被占用。
//构建Package对象,打开word文档
Package package = Package.Open(@"D:\Backup\我的文档\VisualStudio2008\Projects\WordDocument2\WordDocument2\bin\Debug\WordDocument2.docx");
//用uri对象设置包内文件路径
Uri documetUri = newUri("/word/charts/chart1.xml",UriKind.Relative);
//取得包内文件
PackagePartdocumanetPart = package.GetPart(documetUri);
//声明一个xml对象
XmlDocument documentXml = newXmlDocument();
//将包内文件装载如xml对象
documentXml.Load(documanetPart.GetStream());
//声明xml读取对象
XmlNodeReader readerXml = newXmlNodeReader(documentXml);
while (readerXml.Read())//遍历xml文件
{
if (readerXml.NodeType == XmlNodeType.Element)//如果节点是一个元素。节点有元素和属性两个类型
{
//判断当前节点名是否是我们指定的。如果是就将它输出
//if (xmlread.LocalName.Equals("id")|| xmlread.LocalName.Equals("name") ||xmlread.LocalName.Equals("age"))
//{
//读处节点名和节点数据
// Response.Write(xmlread.LocalName + ":" + xmlread.ReadString());
//}
//string str = readerXml.LocalName+" : " +readerXml.ReadString();
//Console.WriteLine(str);
}
string str = readerXml.LocalName + " : " + readerXml.ReadString();
Console.WriteLine(str);
}
//关闭xml读取对象
readerXml.Close();
另外一个openxml读写的例子
Openxml可以自定义用户数据包,一般在customXml\ item1.xml中。我们可以使用Content Control Toolkit工具生成用户数据xml,然后把用户xml绑定到word控件中。我们只需要修改用户xml就可以实现word数据的动态绑定了。
//构建Package对象,打开word文档
Package package = Package.Open(@"testXml.docx");
//用uri对象设置包内文件路径
Uri documetUri = newUri("/customXml/item1.xml",UriKind.Relative);
//取得包内文件
PackagePart documanetPart =package.GetPart(documetUri);
//声明一个xml对象
XmlDocument documentXml = newXmlDocument();
//将包内文件装载如xml对象
documentXml.Load(documanetPart.GetStream());
//声明xml读取对象
XmlNodeReader readerXml = newXmlNodeReader(documentXml);
//指明要修改的xml节点
XmlNodeList xmlNodeList = documentXml.SelectNodes("/dataroot[1]/表1[1]/name[1]");
//修改节点内容
xmlNodeList[0].InnerText = "世界,你好,我会用xml了!!!";
//写回package
documentXml.Save(documanetPart.GetStream(FileMode.Create,FileAccess.Write));
//收回资源
readerXml.Close();
package.Close();
//打开word
string WordPath = @"testXml.docx";
Process.Start("winword",WordPath);
13 openxml工具PackageExplorer和Content Control Toolkit
1 ContentControl Toolkit它是微软公司的一个开源软件,通过它我们可以很方便的实现xml与文档的数据绑定。
首先我们在word中通过 开发工具\控件\Aa插入数据控件。然后打开Content ControlToolkit后,开源在左边工作区发现我们插入的数据控件,在右边我们可以看见word的xml结构。打开在edit view页标签可以对xml进行编辑,xml只有一个根目录,一次我们不能够直接增加节点,要把节点嵌入到根目录中。例如:我们增加一个节点
然后回到bind view页标签,我们就可以看到我们刚才增加的data目录和test节点。在这里我们就可以直接将test节点拖入工作区的数据控件上,自动实现绑定。
另外提一下,默认情况下,开发工具是关闭的。开发开发工具选项如何打开——在 左上角offic按钮\word选项\常用\在功能区显示开发工具选项。
手工建立用户xml很麻烦,我们可以将数据表导出成xml文件,然后在工具的editview页标签中通过XML an open按钮打开。这样我们就很方便的导入一个xml,但是该工具只能导入一个xml文件,如果我们有多个xml,我们需要自己手工合并成一个xml文件后,在导入到工具中。
2 使用PackageExplorer我们可以很方便的看见offic文档中的xml文件结构,但是注意该软件对中文支持不好,在其中修改xml时,切忌不要使用中文,offic文档打开否则会报错。
14 PackageHelper
这个类是微软公司提供的,该类主要目的是创建一个packag,然后构建其中的部件然后保存。相当于手动创建一个offic文档。如果我们只是需要打开一个创建好的offic文档不需要使用该类,使用上门的代码就可以了。
using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Packaging;
using System.IO;
using System.Xml;
using System.Xml.XPath;
namespace OPENXML
{
///
/// This class encapsulates the common functions performed
/// when working with a package located in memory.
///
internalsealed class PackageHelper : IDisposable
{
#region Private Fields
privateMemoryStream m_packageData;
privatePackage m_package;
#endregion
#region Constructor
///
/// Creates a new instance of a package basedc on the dataprovided.
///
///
publicPackageHelper(byte[] data)
{
//load the memory stream
m_packageData = new MemoryStream();
m_packageData.Write(data, 0, data.Length);
//open the package
m_package =
Package.Open(m_packageData,
FileMode.Open,
FileAccess.ReadWrite); //use read write access
}
#endregion
#region Disposal Methods
///
/// Close the package and the memory stream
///
publicvoid Dispose()
{
m_package.Close();
m_packageData.Close();
}
#endregion
#region Package Management Methods
///
/// Saves the package data stored in the internal memorystream to a file.
///
///The filename to write the package to
publicvoid Save(stringfilename)
{
//flush and data in the package buffers to the stream
m_package.Flush();
m_package.Close();
//write the stream to the output file
using(FileStream outputStream = File.Create(filename))
m_packageData.WriteTo(outputStream);
//close the stream
m_packageData.Close();
}
#endregion
#region Part Management Methods
///
/// Opens the part and loads the XML into an XmlDocument.
///
///
///
publicXmlDocument GetWritablePart(Uri partUri)
{
//get the part
PackagePartwritablePart = m_package.GetPart(partUri);
//load the part into a XmlDocument
XmlDocumentpartXml = new XmlDocument();
using(Stream partStream =
writablePart.GetStream(FileMode.Open,FileAccess.Read))
{
partXml.Load(partStream);
}
//return the document
returnpartXml;
}
///
/// Replaces all content in the part with the XML in theXmlDocument.
///
///
///
publicvoid SavePart(UripartUri, XmlDocument partXml)
{
//get the part
PackagePartwritablePart = m_package.GetPart(partUri);
// load thepart into a XmlDocument
using(Stream partStream =
writablePart.GetStream(FileMode.Open,FileAccess.Write))
{
partStream.SetLength(0);
partXml.Save(partStream);
}
}
#endregion
}
}
15 使用解压缩方式来修改openxml文件
直接通过packag方式,我们很难得到word文件中
\word\embeddings\ Microsoft_Office_Excel____1.xlsx的excle文件。该文件是word中图表chart对象和excle对象的数据源,我们只需要修改它就可以达到修改word中excle和chart对象的目的。
1 我们先来通过解压缩的方式修改客户xml文件
首先要导入ICSharpCode.SharpZipLib.dll
//xml文件的地址
stringxmlPath = @"testXml1\customXml\item1.xml";
//声明一个xml对象
XmlDocumentdocumentXml = new XmlDocument();
//将包内文件装载如xml对象
documentXml.Load(xmlPath);
//声明xml读取对象
XmlNodeReaderreaderXml = new XmlNodeReader(documentXml);
//指明要修改的xml节点
XmlNodeListxmlNodeList = documentXml.SelectNodes("/dataroot[1]/表1[1]/name[1]");
//修改节点内容
xmlNodeList[0].InnerText= "offic2007都是用openxml来构建";
//保存xml文件
documentXml.Save(xmlPath);
//收回资源
readerXml.Close();
package.Close();
//删除目标位置上的docx文件,为新建文件腾出位置。
File.Delete("t.docx");
//声明zip对象,
FastZipfz = new FastZip();
//创建压缩文件,指定输出文件地址和文件名,压缩目录地址。
fz.CreateZip("t.docx", "testXml1",true, null);
//打开文档
Process.Start("winword", "t.docx");
16 读写excle(用Schema定位xml节点,修改后保存)
读写excle数据源的难点在于如何定位,1首先声明excle的Schema,用它来构建数据的路径。然后使用SelectSingleNode方法把数据节点提取出来
public static void ZIPexcle()
{
//构建Package对象,打开word文档
string fileName = @"test1.xlsx";
Package package = Package.Open(fileName);
Uri documetUri = newUri("/xl/worksheets/sheet1.xml",UriKind.Relative);
PackagePart documanetPart =package.GetPart(documetUri);
//声明一个xml对象
XmlDocument documentXml = newXmlDocument();
documentXml.Load(documanetPart.GetStream());
setXml(documentXml,"B1","101");//修改xml节点值
//保存xml文件
documentXml.Save(documanetPart.GetStream(FileMode.Create,FileAccess.Write));
package.Close();
}
//修改xml节点值
private static void setXml( XmlDocumentdocumentXml,string changAccess,string changValue)
{
//构建excle的Schema
const string worksheetSchema= "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
NameTable nt = newNameTable();
XmlNamespaceManager nsManager = new XmlNamespaceManager(nt);
nsManager.AddNamespace("d",worksheetSchema);
//从xml中取出节点
XmlNode cellNode = documentXml.SelectSingleNode(string.Format("//d:sheetData/d:row/d:c[@r='{0}']",changAccess), nsManager);
cellNode["v"].InnerText =changValue;//修改节点值
}
17 使用sqlserver导出xml,然后绑定到Content Control Toolkit中
我们很多文档都是要绑定当数据库中去,因此我们需要将数据库中的表导出成xml格式文件然后通过Content Control Toolkit导入,最后绑定到文档标签中。
1 、sqlserver导出xml
很多版本的sqlser2005不支持导出功能,那么我们可以通过语句实现导出。
SELECT* FROM [t1] for xml auto ,ELEMENTS
2 、导入到Content Control Toolkit中
导入Content Control Toolkit后就会自动插入到用户xml文件中,但是我们需要注意用户xml只能有一个根节点,但是从sqlserver导出的xml结构中没有根节点。因此我们需要手工添加一个根节点。
18 VSTO和openxml中读写table
1 在VSTO中打开table
如果在VSTO程序中可以直接用这个代码吧table打开
this.Tables[1].Rows[1].Cells[1].Range.Text="great";
如果在其他工程中需要打开word中得tabl可以用下面的代码
string paTh = Environment.CurrentDirectory;
string filePath = paTh+@"\test.docx";
object missing = Type.Missing;
object[] filename = newobject[1] { filePath };
try
{
Microsoft.Office.Interop.Word.ApplicationwordApp = new Microsoft.Office.Interop.Word.Application();
Document wordDoc = wordApp.Documents.Open(ref filename[0], refmissing, ref missing, refmissing, ref missing, refmissing, ref missing, refmissing, ref missing, refmissing, ref missing, refmissing, ref missing, refmissing, ref missing, refmissing);
string str =wordDoc.Tables[1].Rows[1].Cells[1].Range.Text;
wordDoc.Tables[1].Rows[1].Cells[1].Range.Text="test";
object[] options = newobject[1] { true};
wordDoc.Save();
wordDoc.Close(ref options[0], ref missing, refmissing);
}
catch (Exceptionex)
{
//MessageBox.Show(ex.Message);
//returnfalse;
}
2 在openxml中打开table
使用openxml的Documents方法来操作表格非常麻烦。还是使用VSTO得对象来得方便。
using (WordprocessingDocument doc = WordprocessingDocument.Open(
@"G:\测试\OPENXML\INSER_TTABLE\bin\Debug\test.docx",false))
{
//取出第一個Table
DocumentFormat.OpenXml.Wordprocessing.Tabletbl = doc.MainDocumentPart.Document.Body
.Elements
//取得TableRow陣列
var rows = tbl.Elements<TableRow>().ToArray();
for (int i = 0; i< rows.Length; i++)
{
//取得TableRow的TableCell陣列
var cells = rows[i].Elements<TableCell>()
.ToArray();
//顯示每列的內容
for (intj = 0; j < cells.Length; j++)
{
Console.WriteLine("Row:{0} Cell:{1} Value={2}",
i, j,
cells[j].Elements
//cells[j].Elements
}
}
}
Console.Read();