Open XML - 如何向 docx 文档添加水印
我正在尝试获取现有文档,如果标题不存在,则创建一个,然后在标题中添加一个水印,对角线写着“DRAFT”。我遵循了发布的示例 这里,我已经得到了代码,如果标题已经存在,它将添加水印。
当前的问题是,当我添加新标题、添加对文档的引用,然后将水印添加到标题时,文档会损坏并且无法再在 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;
}
}
}
}
更新:
现在通过更改文件打开方式解决了这个问题。当我们将 Main 函数更改为:
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 中正确打开。谢谢布拉德!
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. 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.
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.
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. Save to my desktop as "TestDoc.docx" and close the file. Then I run the app from 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.
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:
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. Thanks Brad!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
现在可以通过更改文件打开方式来解决此问题。当我们将 Main 函数更改为:
文档现在可以在 word 中正确打开。感谢 Sonoma Partners 的同事 Brad B. 发现了这个!
This is now resolved by changing the way the file is opened up. When we change the Main function to:
The document now correctly opens in word. Thanks to Brad B. a coworker at Sonoma Partners for finding this!
删除该行
并用类似于
编辑的内容替换对sectionproperties的检查:
完整的if then..将如下所示:
remove the line
AND replace the check for sectionproperties with something similar to
EDIT:
the complete if then.. would look like this: