Open XML - 如何向docx文档添加水印

12

我试图对现有文档进行操作,如果没有页眉,则创建一个页眉,并在页眉中添加一个水印,上面写着“草稿”(倾斜)。我遵循了此处发布的示例,并且已经将代码完成到了只要页眉存在就可以添加水印的程度。

当前的问题是,当我添加新的页眉、将引用添加到文档并向页眉添加水印时,文档会损坏,并且无法在Word 2010中打开。

为了测试,我一直在执行以下操作:从Word自身创建一个新的Word文档,其中页面主体包含文本“TestDoc”。将文件保存到桌面上并命名为“TestDoc.docx”,然后关闭该文件。接下来我从Visual Studio运行应用程序。以下代码将始终使其损坏。如果我给文件添加一个没有文本的页眉,然后保存,水印将正确显示。

目前为止,这是我的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Vml;
using DocumentFormat.OpenXml.Vml.Office;
using DocumentFormat.OpenXml.Vml.Wordprocessing;
using DocumentFormat.OpenXml.Wordprocessing;
using HorizontalAnchorValues = DocumentFormat.OpenXml.Vml.Wordprocessing.HorizontalAnchorValues;
using Lock = DocumentFormat.OpenXml.Vml.Office.Lock;
using VerticalAnchorValues = DocumentFormat.OpenXml.Vml.Wordprocessing.VerticalAnchorValues;

namespace DocumentWatermarkTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var doc = WordprocessingDocument.Open(@"C:\Users\loggedinuser\Desktop\TestDoc.docx", true);
            AddWatermark(doc);
            doc.MainDocumentPart.Document.Save();
        }

        static Header MakeHeader()
        {
            var header = new Header();
            var paragraph = new Paragraph();
            var run = new Run();
            var text = new Text();
            text.Text = "";
            run.Append(text);
            paragraph.Append(run);
            header.Append(paragraph);
            return header;
        }

        static void AddWatermark(WordprocessingDocument doc)
        {
            if (doc.MainDocumentPart.HeaderParts.Count() == 0)
            {
                doc.MainDocumentPart.DeleteParts(doc.MainDocumentPart.HeaderParts);
                var newHeaderPart = doc.MainDocumentPart.AddNewPart<HeaderPart>();
                var rId = doc.MainDocumentPart.GetIdOfPart(newHeaderPart);
                var headerRef = new HeaderReference();
                headerRef.Id = rId;
                var sectionProps = doc.MainDocumentPart.Document.Body.Elements<SectionProperties>().LastOrDefault();
                if (sectionProps == null)
                {
                    sectionProps = new SectionProperties();
                    doc.MainDocumentPart.Document.Body.Append(sectionProps);
                }
                sectionProps.RemoveAllChildren<HeaderReference>();
                sectionProps.Append(headerRef);

                newHeaderPart.Header = MakeHeader();
                newHeaderPart.Header.Save();
            }

            foreach (HeaderPart headerPart in doc.MainDocumentPart.HeaderParts)
            {
                var sdtBlock1 = new SdtBlock();
                var sdtProperties1 = new SdtProperties();
                var sdtId1 = new SdtId() { Val = 87908844 };
                var sdtContentDocPartObject1 = new DocPartObjectSdt();
                var docPartGallery1 = new DocPartGallery() { Val = "Watermarks" };
                var docPartUnique1 = new DocPartUnique();
                sdtContentDocPartObject1.Append(docPartGallery1);
                sdtContentDocPartObject1.Append(docPartUnique1);
                sdtProperties1.Append(sdtId1);
                sdtProperties1.Append(sdtContentDocPartObject1);

                var sdtContentBlock1 = new SdtContentBlock();
                var paragraph2 = new Paragraph()
                                     {
                                         RsidParagraphAddition = "00656E18",
                                         RsidRunAdditionDefault = "00656E18"
                                     };
                var paragraphProperties2 = new ParagraphProperties();
                var paragraphStyleId2 = new ParagraphStyleId() { Val = "Header" };
                paragraphProperties2.Append(paragraphStyleId2);
                var run1 = new Run();
                var runProperties1 = new RunProperties();
                var noProof1 = new NoProof();
                var languages1 = new Languages() { EastAsia = "zh-TW" };
                runProperties1.Append(noProof1);
                runProperties1.Append(languages1);
                var picture1 = new Picture();
                var shapetype1 = new Shapetype()
                                     {
                                         Id = "_x0000_t136",
                                         CoordinateSize = "21600,21600",
                                         OptionalNumber = 136,
                                         Adjustment = "10800",
                                         EdgePath = "m@7,l@8,m@5,21600l@6,21600e"
                                     };
                var formulas1 = new Formulas();
                var formula1 = new Formula() { Equation = "sum #0 0 10800" };
                var formula2 = new Formula() { Equation = "prod #0 2 1" };
                var formula3 = new Formula() { Equation = "sum 21600 0 @1" };
                var formula4 = new Formula() { Equation = "sum 0 0 @2" };
                var formula5 = new Formula() { Equation = "sum 21600 0 @3" };
                var formula6 = new Formula() { Equation = "if @0 @3 0" };
                var formula7 = new Formula() { Equation = "if @0 21600 @1" };
                var formula8 = new Formula() { Equation = "if @0 0 @2" };
                var formula9 = new Formula() { Equation = "if @0 @4 21600" };
                var formula10 = new Formula() { Equation = "mid @5 @6" };
                var formula11 = new Formula() { Equation = "mid @8 @5" };
                var formula12 = new Formula() { Equation = "mid @7 @8" };
                var formula13 = new Formula() { Equation = "mid @6 @7" };
                var formula14 = new Formula() { Equation = "sum @6 0 @5" };

                formulas1.Append(formula1);
                formulas1.Append(formula2);
                formulas1.Append(formula3);
                formulas1.Append(formula4);
                formulas1.Append(formula5);
                formulas1.Append(formula6);
                formulas1.Append(formula7);
                formulas1.Append(formula8);
                formulas1.Append(formula9);
                formulas1.Append(formula10);
                formulas1.Append(formula11);
                formulas1.Append(formula12);
                formulas1.Append(formula13);
                formulas1.Append(formula14);
                var path1 = new Path()
                {
                    AllowTextPath = DocumentFormat.OpenXml.Vml.BooleanValues.True,
                    ConnectionPointType = ConnectValues.Custom,
                    ConnectionPoints = "@9,0;@10,10800;@11,21600;@12,10800",
                    ConnectAngles = "270,180,90,0"
                };
                var textPath1 = new TextPath()
                {
                    On = DocumentFormat.OpenXml.Vml.BooleanValues.True,
                    FitShape = DocumentFormat.OpenXml.Vml.BooleanValues.True
                };
                var shapeHandles1 = new Handles();

                var shapeHandle1 = new Handle()
                                       {
                                           Position = "#0,bottomRight",
                                           XRange = "6629,14971"
                                       };

                shapeHandles1.Append(shapeHandle1);

                var lock1 = new Lock
                {
                    Extension = ExtensionHandlingBehaviorValues.Edit,
                    TextLock = DocumentFormat.OpenXml.Vml.Office.BooleanValues.True,
                    ShapeType = DocumentFormat.OpenXml.Vml.Office.BooleanValues.True
                };

                shapetype1.Append(formulas1);
                shapetype1.Append(path1);
                shapetype1.Append(textPath1);
                shapetype1.Append(shapeHandles1);
                shapetype1.Append(lock1);
                var shape1 = new Shape()
                                 {
                                     Id = "PowerPlusWaterMarkObject357476642",
                                     Style = "position:absolute;left:0;text-align:left;margin-left:0;margin-top:0;width:527.85pt;height:131.95pt;rotation:315;z-index:-251656192;mso-position-horizontal:center;mso-position-horizontal-relative:margin;mso-position-vertical:center;mso-position-vertical-relative:margin",
                                     OptionalString = "_x0000_s2049",
                                     AllowInCell = DocumentFormat.OpenXml.Vml.BooleanValues.False,
                                     FillColor = "silver",
                                     Stroked = DocumentFormat.OpenXml.Vml.BooleanValues.False,
                                     Type = "#_x0000_t136"
                                 };


                var fill1 = new Fill() { Opacity = ".5" };
                TextPath textPath2 = new TextPath()
                                         {
                                             Style = "font-family:\"Calibri\";font-size:1pt",
                                             String = "DRAFT"
                                         };

                var textWrap1 = new TextWrap()
                                    {
                                        AnchorX = HorizontalAnchorValues.Margin,
                                        AnchorY = VerticalAnchorValues.Margin
                                    };

                shape1.Append(fill1);
                shape1.Append(textPath2);
                shape1.Append(textWrap1);
                picture1.Append(shapetype1);
                picture1.Append(shape1);
                run1.Append(runProperties1);
                run1.Append(picture1);
                paragraph2.Append(paragraphProperties2);
                paragraph2.Append(run1);
                sdtContentBlock1.Append(paragraph2);
                sdtBlock1.Append(sdtProperties1);
                sdtBlock1.Append(sdtContentBlock1);
                headerPart.Header.Append(sdtBlock1);
                headerPart.Header.Save();
                //break;
            }
        }
    }
}

更新:

现在已通过改变文件的打开方式解决。当我们将主函数更改为:

static void Main(string[] args)
        {
            //var doc = WordprocessingDocument.Open(@"C:\Users\loggedinuser\Desktop\TestDoc.docx", true);
            //AddWatermark(doc);
            //doc.MainDocumentPart.Document.Save();
            byte[] sourceBytes = File.ReadAllBytes(@"C:\Users\loggedinuser\Desktop\TestDoc.docx");

            MemoryStream inMemoryStream = new MemoryStream();
            inMemoryStream.Write(sourceBytes, 0, (int)sourceBytes.Length);

            var doc = WordprocessingDocument.Open(inMemoryStream, true);
            AddWatermark(doc);
            doc.MainDocumentPart.Document.Save();

            doc.Close();
            doc.Dispose();
            doc = null;

            using (FileStream fileStream = new FileStream(@"C:\Users\loggedinuser\Desktop\TestDoc.docx", System.IO.FileMode.Create))
            {
                inMemoryStream.WriteTo(fileStream);
            }

            inMemoryStream.Close();
            inMemoryStream.Dispose();
            inMemoryStream = null;
        }

文档现在可以正确地在Word中打开。感谢Brad!

2个回答

7
现在,我们通过更改打开文件的方式来解决这个问题。当我们将主函数更改为以下内容时:
static void Main(string[] args)
{
    //var doc = WordprocessingDocument.Open(@"C:\Users\loggedinuser\Desktop\TestDoc.docx", true);
    //AddWatermark(doc);
    //doc.MainDocumentPart.Document.Save();
    byte[] sourceBytes = File.ReadAllBytes(@"C:\Users\loggedinuser\Desktop\TestDoc.docx");
    MemoryStream inMemoryStream = new MemoryStream();
    inMemoryStream.Write(sourceBytes, 0, (int)sourceBytes.Length);

    var doc = WordprocessingDocument.Open(inMemoryStream, true);
    AddWatermark(doc);
    doc.MainDocumentPart.Document.Save();

    doc.Close();
    doc.Dispose();
    doc = null;

    using (FileStream fileStream = new FileStream(@"C:\Users\loggedinuser\Desktop\TestDoc.docx", System.IO.FileMode.Create))
    {
        inMemoryStream.WriteTo(fileStream);
    }

    inMemoryStream.Close();
    inMemoryStream.Dispose();
    inMemoryStream = null;
}

现在该文档在 Word 中正确打开了。感谢 Sonoma Partners 的同事 Brad B. 找到了这个问题的解决方案!


1

删除该行

doc.MainDocumentPart.DeleteParts(doc.MainDocumentPart.HeaderParts);

并且将检查sectionproperties的部分替换为类似的内容

if (doc.MainDocumentPart.Document.Body.Elements<SectionProperties>().Count == 0)

编辑:

完整的if then语句应该是这样的:

var sectionProps = null;

if (doc.MainDocumentPart.Document.Body.Elements<SectionProperties>().Count == 0)
{
sectionProps = new SectionProperties();
doc.MainDocumentPart.Document.Body.Append(sectionProps);
}
else
{
sectionProps = doc.MainDocumentPart.Document.Body.Elements<SectionProperties>().Last();
}

当我进行更改时,它跳过了您上面提出的if语句,并给出了以下错误:无法打开文件TestDoc.docx,因为其内容存在问题。详细信息:Microsoft Office无法打开此文件,因为某些部分丢失或无效。位置:部分:/word/document.xml,行:1,列:0。 - Rob
我已经进行了更改,但仍然出现错误。我应该编辑上面的代码以包含您建议的更改吗? - Rob
很抱歉没能帮上忙 :-( 我认为你不应该编辑上面的代码。 - Yahia
我们找到了答案。我们打开文档的方式导致了问题。当主函数改为上面的内容时,它就可以工作了。 - Rob
1
我使用上述代码添加水印。它从第二页开始添加水印,并完全跳过第一页。当我查看doc.MainDocumentPart.HeaderPart的计数时,有一个较少的页眉。我是否漏掉了什么? - RRR
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接