简体   繁体   English

打开 XML - 如何在 docx 文档中添加水印

[英]Open XML - How to add a watermark to a docx document

I'm trying to take an existing document and if a header doesn't exist, create one, and then add a watermark to the header that says "DRAFT" diagonally.我正在尝试获取现有文档,如果 header 不存在,请创建一个,然后将水印添加到 header 对角线显示“草稿”。 I've followed an example posted here and I've gotten the code to the point where it will add the watermark if the header already exists.我已经按照此处发布的示例进行操作,并且如果 header 已经存在,我已经将代码添加到添加水印的地步。

The current issue is when I add a new header, add the reference to the document, and then add the watermark to the header, the document becomes corrupt and can no longer open in Word 2010.当前的问题是当我添加一个新的 header,添加对文档的引用,然后将水印添加到 header 时,文档损坏,无法再在 Word 2010 中打开。

To test I've been doing the following: Create a new word document from word itself with text of "TestDoc" in the main part of the page.为了测试我一直在做以下事情:从word本身创建一个新的word文档,在页面的主要部分使用“TestDoc”的文本。 Save to my desktop as "TestDoc.docx" and close the file.以“TestDoc.docx”的形式保存到我的桌面并关闭文件。 Then I run the app from Visual Studio.然后我从 Visual Studio 运行应用程序。 The code below will always make it corrupted.下面的代码将始终使其损坏。 If I add a header to the file with no text in it and then hit save, the watermark will be displayed correctly.如果我将 header 添加到没有文本的文件中,然后点击保存,水印将正确显示。

Here is what I have so far:这是我到目前为止所拥有的:

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;
            }
        }
    }
}

UPDATE:更新:

This is now resolved by changing the way the file is opened up.现在通过更改文件的打开方式来解决此问题。 When we change the Main function to:当我们将 Main function 更改为:

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;
        }

The document now correctly opens in word.该文档现在可以正确地以 Word 格式打开。 Thanks Brad!谢谢布拉德!

This is now resolved by changing the way the file is opened up.现在通过更改文件的打开方式来解决此问题。 When we change the Main function to:当我们将 Main function 更改为:

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;
}

The document now correctly opens in word.该文档现在可以正确地以 Word 格式打开。 Thanks to Brad B. a coworker at Sonoma Partners for finding this!感谢 Sonoma Partners 的同事 Brad B. 找到了这个!

remove the line删除线

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

AND replace the check for sectionproperties with something similar to并将 sectionproperties 的检查替换为类似于

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

EDIT:编辑:

the complete if then.. would look like this:完整的 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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM