VSTO学习之三 openxml

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只有一个根目录,一次我们不能够直接增加节点,要把节点嵌入到根目录中。例如:我们增加一个节点

  

    tttt

 

 

然后回到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.

        ///

        ///Byte arrayrepresenting the package.

        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.

        ///

        ///The uri of thepart to open.

        ///XmlDocument containing the xml from the part.

        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.

        ///

        ///The uri of thepart to replace.

        ///XmlDocumentcontaining the xml to place into the part.

        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

                   .ElementsTable>().First();

              

 

                

 

                //取得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].ElementsParagraph>().First().InnerText);

                      //cells[j].Elements().First().InnerText= "king";

                   }

                }

            }

            Console.Read();

你可能感兴趣的:(VSTO学习之三 openxml)