zoukankan      html  css  js  c++  java
  • 【转】【OpenXML】OpenXML操作word

    OpenXML概述

    项目中经常需要操作word,之前的方式是采用COM接口,这个接口很不稳定,经常报错。现在开始采用OpenXML。OpenXML(OOXML)是微软在Office 2007中提出的一种新的文档格式,Office 2007中的Word、Excel、PowerPoint默认均采用OpenXML格式 。
    OpenXml相对于用MS提供的COM组件来生成WORD,有如下优势:

    1.相对于MS 的COM组件,因为版本带来的不兼容问题,及各种会生成WORD半途会崩溃的问题.
    2.对比填满一张30多页的WORD来说(包含图,表等),用COM组件来生成会占用20秒,Openxml1秒.
    3.MS Word软件太贵了,你的客户装的是开源WORD,如LibreOffice,OpenOffice.这样你就只能用Openxml生成的WORD文档,各种支持MS Word都能打开,避免客户机器上安装MS Word.
    4.代码简单。用OpenXML开发word简直太方便了!!!

    要做OpenXML的开发,需要了解OpenXML的基本结构。

    Open XML SDK 2.0 tool

    因为OpenXML的结构比较复杂,开始开发时往往不好入门,摸不清其结构。微软很贴心的提供了一个工具,Open XML SDK Productivity Tool for Microsoft Office。
    下载地址  百度云:OpenXMLSDKTool 提取码: u6q8  OpenXMLSDK  提取码: k873
    这个工具可以打开任意一个docx的文档,然后Reflect Code,得到整个文档代码,之后怎么操作直接看代码就好了,真是太方便了。

    另外这个工具也提供了文档,不清楚的可以查一下文档。

    代码示例

    我参考上面的工具,写了一个简单的操作word的帮助类。

    using System.Collections.Generic;
    using System.IO;
    using DocumentFormat.OpenXml;
    using DocumentFormat.OpenXml.Packaging;
    using DocumentFormat.OpenXml.Wordprocessing;
    using AA = DocumentFormat.OpenXml.Drawing;
    using DW = DocumentFormat.OpenXml.Drawing.Wordprocessing;
    using PIC = DocumentFormat.OpenXml.Drawing.Pictures;
    
    namespace Wisdombud.Office
    {
        public static class OpenXmlUtil
        {
    
            /// <summary>
            /// 按书签替换图片
            /// </summary>
            /// <param name="filePath"></param>
            /// <param name="picPath"></param>
            /// <param name="bm"></param>
            /// <param name="x">宽度厘米</param>
            /// <param name="y">高度厘米</param>
            /// <param name="type"></param>
            public static void ReplaceBMPicture(string filePath, string picPath, string bm)
            {
                RemoveBookMarkContent(filePath, bm);
                InsertBMPicture(filePath, picPath, bm);
            }
    
            /// <summary>
            /// 按书签替换图片
            /// </summary>
            /// <param name="filePath"></param>
            /// <param name="picPath"></param>
            /// <param name="bm"></param>
            /// <param name="x">宽度厘米</param>
            /// <param name="y">高度厘米</param>
            /// <param name="type"></param>
            public static void ReplaceBMPicture(string filePath, string picPath, string bm, long x, ImagePartType type)
            {
                RemoveBookMarkContent(filePath, bm);
                InsertBMPicture(filePath, picPath, bm, x, type);
            }
            /// <summary>
            /// 按书签替换图片
            /// </summary>
            /// <param name="filePath"></param>
            /// <param name="picPath"></param>
            /// <param name="bm"></param>
            /// <param name="x">宽度厘米</param>
            /// <param name="y">高度厘米</param>
            /// <param name="type"></param>
            public static void ReplaceBMPicture(string filePath, string picPath, string bm, long x, long y, ImagePartType type)
            {
                RemoveBookMarkContent(filePath, bm);
                InsertBMPicture(filePath, picPath, bm, x, y, type);
            }
            /// <summary>
            /// 按书签插入图片
            /// </summary>
            /// <param name="filePath"></param>
            /// <param name="picPath"></param>
            /// <param name="bm"></param>
            /// <param name="x">宽度厘米</param>
            /// <param name="y">高度厘米</param>
            /// <param name="type"></param>
            public static void InsertBMPicture(string filePath, string picPath, string bm, long x, ImagePartType type)
            {
                long y = 0;
                using (System.Drawing.Bitmap objPic = new System.Drawing.Bitmap(picPath))
                {
                    y = (x * objPic.Height) / objPic.Width;
                }
                InsertBMPicture(filePath, picPath, bm, x, y, type);
            }
    
            /// <summary>
            /// 按书签插入图片
            /// </summary>
            /// <param name="filePath"></param>
            /// <param name="picPath"></param>
            /// <param name="bm"></param>
            /// <param name="x">宽度厘米</param>
            /// <param name="y">高度厘米</param>
            /// <param name="type"></param>
            public static void InsertBMPicture(string filePath, string picPath, string bm, long x, long y, ImagePartType type)
            {
                using (WordprocessingDocument doc =
                   WordprocessingDocument.Open(filePath, true))
                {
                    MainDocumentPart mainPart = doc.MainDocumentPart;
    
                    BookmarkStart bmStart = findBookMarkStart(doc, bm);
                    if (bmStart == null)
                    {
                        return;
                    }
    
                    ImagePart imagePart = mainPart.AddImagePart(type);
    
                    using (FileStream stream = new FileStream(picPath, FileMode.Open))
                    {
                        imagePart.FeedData(stream);
                    }
                    long cx = 360000L * x;//360000L = 1厘米
                    long cy = 360000L * y;
                    Run r = AddImageToBody(doc, mainPart.GetIdOfPart(imagePart), cx, cy);
                    bmStart.Parent.InsertAfter<Run>(r, bmStart);
                    mainPart.Document.Save();
                }
            }
            /// <summary>
            /// 按书签插入图片。默认15厘米,JPG
            /// </summary>
            /// <param name="filePath"></param>
            /// <param name="picPath"></param>
            /// <param name="bm"></param>
            public static void InsertBMPicture(string filePath, string picPath, string bm)
            {
                InsertBMPicture(filePath, picPath, bm, 15, 15, ImagePartType.Jpeg);
            }
            /// <summary>
            /// 查找书签
            /// </summary>
            /// <param name="doc"></param>
            /// <param name="bmName"></param>
            /// <returns></returns>
            private static BookmarkStart findBookMarkStart(WordprocessingDocument doc, string bmName)
            {
                foreach (var footer in doc.MainDocumentPart.FooterParts)
                {
                    foreach (var inst in footer.Footer.Descendants<BookmarkStart>())
                    {
                        if (inst.Name == bmName)
                        {
                            return inst;
                        }
                    }
                }
    
                foreach (var header in doc.MainDocumentPart.HeaderParts)
                {
                    foreach (var inst in header.Header.Descendants<BookmarkStart>())
                    {
                        if (inst.Name == bmName)
                        {
                            return inst;
                        }
                    }
                }
                foreach (var inst in doc.MainDocumentPart.RootElement.Descendants<BookmarkStart>())
                {
                    if (inst is BookmarkStart)
                    {
                        if (inst.Name == bmName)
                        {
                            return inst;
                        }
                    }
                }
    
                return null;
            }
    
            /// <summary>
            /// 查找书签
            /// </summary>
            /// <param name="doc"></param>
            /// <param name="bmName"></param>
            /// <returns></returns>
            private static List<BookmarkStart> findAllBookMarkStart(WordprocessingDocument doc)
            {
                List<BookmarkStart> ret = new List<BookmarkStart>();
                foreach (var footer in doc.MainDocumentPart.FooterParts)
                {
                    ret.AddRange(footer.Footer.Descendants<BookmarkStart>());
    
                }
                foreach (var header in doc.MainDocumentPart.HeaderParts)
                {
                    ret.AddRange(header.Header.Descendants<BookmarkStart>());
                }
                ret.AddRange(doc.MainDocumentPart.RootElement.Descendants<BookmarkStart>());
                return ret;
            }
            /// <summary>
            /// 查找书签
            /// </summary>
            /// <param name="doc"></param>
            /// <param name="bmName"></param>
            /// <returns></returns>
            private static List<BookmarkEnd> findAllBookMarkEnd(WordprocessingDocument doc)
            {
                List<BookmarkEnd> ret = new List<BookmarkEnd>();
                foreach (var footer in doc.MainDocumentPart.FooterParts)
                {
                    ret.AddRange(footer.Footer.Descendants<BookmarkEnd>());
    
                }
                foreach (var header in doc.MainDocumentPart.HeaderParts)
                {
                    ret.AddRange(header.Header.Descendants<BookmarkEnd>());
                }
                ret.AddRange(doc.MainDocumentPart.RootElement.Descendants<BookmarkEnd>());
                return ret;
            }
    
    
            /// <summary>
            /// 查找书签END
            /// </summary>
            /// <param name="doc"></param>
            /// <param name="bmName"></param>
            /// <returns></returns>
            private static BookmarkEnd findBookMarkEnd(WordprocessingDocument doc, string id)
            {
                foreach (var footer in doc.MainDocumentPart.FooterParts)
                {
                    foreach (var inst in footer.Footer.Descendants<BookmarkEnd>())
                    {
                        if (inst.Id == id)
                        {
                            return inst;
                        }
                    }
                }
    
                foreach (var header in doc.MainDocumentPart.HeaderParts)
                {
                    foreach (var inst in header.Header.Descendants<BookmarkEnd>())
                    {
                        if (inst.Id == id)
                        {
                            return inst;
                        }
                    }
                }
                foreach (var inst in doc.MainDocumentPart.RootElement.Descendants<BookmarkEnd>())
                {
                    if (inst.Id == id)
                    {
                        return inst;
                    }
    
                }
    
                return null;
            }
    
            private static Run AddImageToBody(WordprocessingDocument wordDoc, string relationshipId, long cx, long cy)
            {
                return new Run(new Drawing(
                         new DW.Inline(
                             new DW.Extent() { Cx = cx, Cy = cy },
                             new DW.EffectExtent()
                             {
                                 LeftEdge = 0L,
                                 TopEdge = 0L,
                                 RightEdge = 0L,
                                 BottomEdge = 0L
                             },
                             new DW.DocProperties()
                             {
                                 Id = (UInt32Value)1U,
                                 Name = "Picture 1"
                             },
                             new DW.NonVisualGraphicFrameDrawingProperties(
                                 new AA.GraphicFrameLocks() { NoChangeAspect = true }),
                             new AA.Graphic(
                                 new AA.GraphicData(
                                     new PIC.Picture(
                                         new PIC.NonVisualPictureProperties(
                                             new PIC.NonVisualDrawingProperties()
                                             {
                                                 Id = (UInt32Value)0U,
                                                 Name = "New Bitmap Image.jpg"
                                             },
                                             new PIC.NonVisualPictureDrawingProperties()),
                                         new PIC.BlipFill(
                                             new AA.Blip(
                                                 new AA.BlipExtensionList(
                                                     new AA.BlipExtension()
                                                     {
                                                         Uri =
                                                           "{28A0092B-C50C-407E-A947-70E740481C1C}"
                                                     })
                                             )
                                             {
                                                 Embed = relationshipId,
                                                 CompressionState =
                                                 AA.BlipCompressionValues.Print
                                             },
                                             new AA.Stretch(
                                                 new AA.FillRectangle())),
                                         new PIC.ShapeProperties(
                                             new AA.Transform2D(
                                                 new AA.Offset() { X = 0L, Y = 0L },
                                                 new AA.Extents() { Cx = 990000L, Cy = 792000L }),
                                             new AA.PresetGeometry(
                                                 new AA.AdjustValueList()
                                             ) { Preset = AA.ShapeTypeValues.Rectangle }))
                                 ) { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" })
                         )
                         {
                             DistanceFromTop = (UInt32Value)0U,
                             DistanceFromBottom = (UInt32Value)0U,
                             DistanceFromLeft = (UInt32Value)0U,
                             DistanceFromRight = (UInt32Value)0U,
                             EditId = "50D07946"
                         }));
    
                // Append the reference to body, the element should be in a Run.
                //  wordDoc.MainDocumentPart.Document.Body.AppendChild(new Paragraph(new Run(element)));
            }
    
            public static void DeleteRange(string filePath, string stringStart, string stringStop, int way)
            {
                using (WordprocessingDocument doc = WordprocessingDocument.Open(filePath, true))
                {
                    List<OpenXmlElement> list = RangeFind(doc, stringStart, stringStop, way);
                    foreach (var inst in list)
                    {
                        inst.Remove();
                    }
                }
            }
            /// <summary>
            /// 1 标记1结束到标记2开始;2 标记1结束到标记2结束;3 标记1开始到标记2结束; 4 标记1开始到标记2开始;
            /// trimhuiche 如果为true,则考虑回车;否则不考虑回车。
            /// chzhao@wisdombud.com
            /// </summary>
            /// <param name="stringStart"></param>
            /// <param name="stringStop"></param>
            /// <param name="way"></param>
            public static List<OpenXmlElement> RangeFind(WordprocessingDocument doc, string stringStart, string stringStop, int way)
            {
                List<OpenXmlElement> ret = new List<OpenXmlElement>();
                bool add = false;
                foreach (var inst in doc.MainDocumentPart.Document.Body.Elements())
                {
    
                    if (way == 1)
                    {
                        if (inst.InnerText.Contains(stringStop))
                        {
                            add = false;
                        }
                        if (add)
                        {
                            ret.Add(inst.CloneNode(true));
                        }
                        if (inst.InnerText == stringStart)
                        {
                            add = true;
                        }
                    }
                    else if (way == 2)
                    {
    
                        if (add)
                        {
                            ret.Add(inst.CloneNode(true));
                        }
                        if (inst.InnerText == stringStart)
                        {
                            add = true;
                        }
                        if (inst.InnerText.Contains(stringStop))
                        {
                            add = false;
                        }
                    }
                    else if (way == 3)
                    {
                        if (inst.InnerText == stringStart)
                        {
                            add = true;
                        }
                        if (add)
                        {
                            ret.Add(inst.CloneNode(true));
                        }
    
                        if (inst.InnerText.Contains(stringStop))
                        {
                            add = false;
                        }
                    }
                    else if (way == 4)
                    {
                        if (inst.InnerText == stringStart)
                        {
                            add = true;
                        }
                        if (inst.InnerText.Contains(stringStop))
                        {
                            add = false;
                        }
                        if (add)
                        {
                            ret.Add(inst.CloneNode(true));
                        }
    
                    }
    
    
    
                }
                return ret;
            }
    
    
            /// <summary>
            /// 修改书签
            /// </summary>
            /// <param name="filePath">word文档</param>
            /// <param name="bmName">书签名字</param>
            /// <param name="text">替换的文本</param>
            public static void ModifyBM(string filePath, string bmName, string text)
            {
                using (WordprocessingDocument doc = WordprocessingDocument.Open(filePath, true))
                {
                    BookmarkStart bmStart = findBookMarkStart(doc, bmName);
    
                    Run bookmarkText = bmStart.NextSibling<Run>();
                    if (bookmarkText != null)
                    {
                        Text t = bookmarkText.GetFirstChild<Text>();
                        if (t != null)
                        {
                            t.Text = text;
                        }
                    }
                }
            }
            /// <summary>
            /// 删除书签内容
            /// </summary>
            /// <param name="bookmark"></param>
            public static void RemoveBookMarkContent(string filePath, string bmName)
            {
                using (WordprocessingDocument doc = WordprocessingDocument.Open(filePath, true))
                {
                    BookmarkStart bmStart = findBookMarkStart(doc, bmName);
                    BookmarkEnd bmEnd = findBookMarkEnd(doc, bmStart.Id);
                    while (true)
                    {
                        var run = bmStart.NextSibling();
                        if (run == null)
                        {
                            break;
                        }
                        if (run is BookmarkEnd && (BookmarkEnd)run == bmEnd)
                        {
                            break;
                        }
    
                        run.Remove();
                    }
    
                }
            }
            /// <summary>
            /// 重命名书签,在书签前面加前缀
            /// </summary>
            /// <param name="filePath"></param>
            /// <param name="prefix">前缀</param>
            public static void RenameBookMark(string filePath, string prefix)
            {
                using (WordprocessingDocument doc = WordprocessingDocument.Open(filePath, true))
                {
                    foreach (var inst in findAllBookMarkStart(doc))
                    {
                        inst.Name = prefix + inst.Name;
                    }
                }
            }
    
            /// <summary>
            /// 重命名书签
            /// </summary>
            /// <param name="filePath"></param>
            /// <param name="oldName"></param>
            /// <param name="newName"></param>
            public static void RenameBookMark(string filePath, string oldName, string newName)
            {
                using (WordprocessingDocument doc = WordprocessingDocument.Open(filePath, true))
                {
                    var bm = findBookMarkStart(doc, oldName);
                    bm.Name = newName;
                }
            }
    
            /// <summary>
            /// 删除书签
            /// </summary>
            /// <param name="bookmark"></param>
            public static void RemoveBookMark(string filePath, string bmName)
            {
                using (WordprocessingDocument doc = WordprocessingDocument.Open(filePath, true))
                {
                    var bmStart = findBookMarkStart(doc, bmName);
                    if (bmStart == null)
                    {
                        return;
                    }
                    var bmEnd = findBookMarkEnd(doc, bmStart.Id);
                    bmStart.Remove();
                    bmEnd.Remove();
    
                }
            }
            /// <summary>
            /// 合并文档
            /// </summary>
            /// <param name="finalFile"></param>
            /// <param name="files"></param>
            public static void Combine(string finalFile, List<string> files)
            {
                if (files.Count < 2)
                {
                    return;
                }
                File.Copy(files[0], finalFile, true);
                using (WordprocessingDocument doc = WordprocessingDocument.Open(finalFile, true))
                {
                    Body b = doc.MainDocumentPart.Document.Body;
                    for (int i = 1; i < files.Count; i++)
                    {
                        using (WordprocessingDocument doc1 = WordprocessingDocument.Open(files[i], true))
                        {
                            foreach (var inst in doc1.MainDocumentPart.Document.Body.Elements())
                            {
                                b.Append(inst.CloneNode(true));
                            }
                        }
                    }
                }
            }
        }
    }

    原文地址:https://www.cnblogs.com/wardensky/p/5482199.html

  • 相关阅读:
    Node.js Express框架
    Node.js Web模块
    Node.js 工具模块
    Node.js GET/POST请求
    Node.js 文件系统
    Node.js 常用工具
    【day03】Xhtml
    【day02】Xhtml
    【紫书】【重要】Not so Mobile UVA
    【紫书】Tree UVA
  • 原文地址:https://www.cnblogs.com/mqxs/p/14345972.html
Copyright © 2011-2022 走看看