Ms word 如何使用openxml合并具有不同标题的word文档?
我正试图通过下面的例子将多个文档合并到一个文档中,正如在另一篇文章中所发布的那样。 我正在使用Ms word 如何使用openxml合并具有不同标题的word文档?,ms-word,openxml,openxml-sdk,Ms Word,Openxml,Openxml Sdk,我正试图通过下面的例子将多个文档合并到一个文档中,正如在另一篇文章中所发布的那样。 我正在使用AltChunk AltChunk=new AltChunk()。合并文档时,似乎不会保留每个文档的单独听者。合并文档将包含合并期间第一个文档的标题。如果要合并的第一个文档不包含侦听器,则新合并文档的所有其余部分将不包含标题,反之亦然 我的问题是,如何保存合并文档的不同标题 使用系统; 使用System.IO; 使用System.Linq; 使用DocumentFormat.OpenXml.Packa
AltChunk AltChunk=new AltChunk()
。合并文档时,似乎不会保留每个文档的单独听者。合并文档将包含合并期间第一个文档的标题。如果要合并的第一个文档不包含侦听器,则新合并文档的所有其余部分将不包含标题,反之亦然
我的问题是,如何保存合并文档的不同标题
使用系统;
使用System.IO;
使用System.Linq;
使用DocumentFormat.OpenXml.Packaging;
使用DocumentFormat.OpenXml.Wordprocessing;
命名空间WordMergeProject
{
公共课程
{
私有静态void Main(字符串[]args)
{
byte[]word1=File.ReadAllBytes(@.\..\word1.docx”);
byte[]word2=File.ReadAllBytes(@.\..\word2.docx”);
字节[]结果=合并(字1,字2);
文件.writealBytes(@.\..\word3.docx),结果;
}
专用静态字节[]合并(字节[]dest,字节[]src)
{
字符串altChunkId=“altChunkId”+DateTime.Now.Ticks.ToString();
var memoryStreamDest=新的MemoryStream();
MemoryStream dest.Write(dest,0,dest.Length);
memoryStreamDest.Seek(0,SeekOrigin.Begin);
var MemoryStream src=新的MemoryStream(src);
使用(WordprocessingDocument doc=WordprocessingDocument.Open(memoryStreamDest,true))
{
MainDocumentPart mainPart=doc.MainDocumentPart;
替代格式导入部分替代部分=
mainPart.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.WordprocessingML,altChunkId);
altPart.FeedData(memoryStreamSrc);
var altChunk=new altChunk();
altChunk.Id=altChunkId;
openxmlement lastElem=mainPart.Document.Body.Elements().LastOrDefault();
if(lastElem==null)
{
lastElem=mainPart.Document.Body.Elements().Last();
}
//佩奇·艾因弗根
段落pageBreakP=新段落();
运行PageBreaker=新运行();
Break pageBreakBr=newbreak(){Type=BreakValues.Page};
pageBreakP.Append(pagebreaker);
pagebreaker.Append(pageBreakBr);
返回memoryStreamDest.ToArray();
}
}
}
我遇到了这个问题a并花了相当长的时间;我最终编写了一个链接到一个示例文件的问题。使用Alt Chunk实现文件与页眉和页脚的集成并非易事。我将尝试在这里介绍要点。这取决于页眉和页脚包含的内容类型(假设微软没有解决我最初遇到的任何问题)完全依靠AltChunk可能是不可能的
(还请注意,可能有一些工具/API可以处理这个问题-我不知道,在这个网站上问这个问题可能是离题的。)
背景
在解决问题之前,了解Word如何处理不同的页眉和页脚会有帮助。要了解它,请启动Word
分节符/取消页眉/页脚链接
- 在页面上键入一些文本并插入标题
- 将焦点移到页面的末尾,然后转到功能区中的
选项卡页面布局
- 页面设置/分页符/下一页分页符
- 进入此页面的标题区域,注意蓝色“标记”中的信息:您将在左侧看到一个节标识符,在右侧看到“与上一个相同”。默认情况下,“与上一个相同”。要创建不同的标题,请单击标题中的“链接到上一个”按钮
- 转到Word的大纲视图
- 单击“显示文档”
- 使用“插入”插入其他文件
using System;
using System.IO;
using System.Linq;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
namespace WordMergeProject
{
public class Program
{
private static void Main(string[] args)
{
byte[] word1 = File.ReadAllBytes(@"..\..\word1.docx");
byte[] word2 = File.ReadAllBytes(@"..\..\word2.docx");
byte[] result = Merge(word1, word2);
File.WriteAllBytes(@"..\..\word3.docx", result);
}
private static byte[] Merge(byte[] dest, byte[] src)
{
string altChunkId = "AltChunkId" + DateTime.Now.Ticks.ToString();
var memoryStreamDest = new MemoryStream();
memoryStreamDest.Write(dest, 0, dest.Length);
memoryStreamDest.Seek(0, SeekOrigin.Begin);
var memoryStreamSrc = new MemoryStream(src);
using (WordprocessingDocument doc = WordprocessingDocument.Open(memoryStreamDest, true))
{
MainDocumentPart mainPart = doc.MainDocumentPart;
AlternativeFormatImportPart altPart =
mainPart.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.WordprocessingML, altChunkId);
altPart.FeedData(memoryStreamSrc);
var altChunk = new AltChunk();
altChunk.Id = altChunkId;
OpenXmlElement lastElem = mainPart.Document.Body.Elements<AltChunk>().LastOrDefault();
if(lastElem == null)
{
lastElem = mainPart.Document.Body.Elements<Paragraph>().Last();
}
//Page Brake einfügen
Paragraph pageBreakP = new Paragraph();
Run pageBreakR = new Run();
Break pageBreakBr = new Break() { Type = BreakValues.Page };
pageBreakP.Append(pageBreakR);
pageBreakR.Append(pageBreakBr);
return memoryStreamDest.ToArray();
}
}
}
private void btnMergeWordDocs_Click(object sender, EventArgs e)
{
string sourceFolder = @"C:\Test\MergeDocs\";
string targetFolder = @"C:\Test\";
string altChunkIdBase = "acID";
int altChunkCounter = 1;
string altChunkId = altChunkIdBase + altChunkCounter.ToString();
MainDocumentPart wdDocTargetMainPart = null;
Document docTarget = null;
AlternativeFormatImportPartType afType;
AlternativeFormatImportPart chunk = null;
AltChunk ac = null;
using (WordprocessingDocument wdPkgTarget = WordprocessingDocument.Create(targetFolder + "mergedDoc.docx", DocumentFormat.OpenXml.WordprocessingDocumentType.Document, true))
{
//Will create document in 2007 Compatibility Mode.
//In order to make it 2010 a Settings part must be created and a CompatMode element for the Office version set.
wdDocTargetMainPart = wdPkgTarget.MainDocumentPart;
if (wdDocTargetMainPart == null)
{
wdDocTargetMainPart = wdPkgTarget.AddMainDocumentPart();
Document wdDoc = new Document(
new Body(
new Paragraph(
new Run(new Text() { Text = "First Para" })),
new Paragraph(new Run(new Text() { Text = "Second para" })),
new SectionProperties(
new SectionType() { Val = SectionMarkValues.NextPage },
new PageSize() { Code = 9 },
new PageMargin() { Gutter = 0, Bottom = 1134, Top = 1134, Left = 1318, Right = 1318, Footer = 709, Header = 709 },
new Columns() { Space = "708" },
new TitlePage())));
wdDocTargetMainPart.Document = wdDoc;
}
docTarget = wdDocTargetMainPart.Document;
SectionProperties secPropLast = docTarget.Body.Descendants<SectionProperties>().Last();
SectionProperties secPropNew = (SectionProperties)secPropLast.CloneNode(true);
//A section break must be in a ParagraphProperty
Paragraph lastParaTarget = (Paragraph)docTarget.Body.Descendants<Paragraph>().Last();
ParagraphProperties paraPropTarget = lastParaTarget.ParagraphProperties;
if (paraPropTarget == null)
{
paraPropTarget = new ParagraphProperties();
}
paraPropTarget.Append(secPropNew);
Run paraRun = lastParaTarget.Descendants<Run>().FirstOrDefault();
//lastParaTarget.InsertBefore(paraPropTarget, paraRun);
lastParaTarget.InsertAt(paraPropTarget, 0);
//Process the individual files in the source folder.
//Note that this process will permanently change the files by adding a section break.
System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(sourceFolder);
IEnumerable<System.IO.FileInfo> docFiles = di.EnumerateFiles();
foreach (System.IO.FileInfo fi in docFiles)
{
using (WordprocessingDocument pkgSourceDoc = WordprocessingDocument.Open(fi.FullName, true))
{
IEnumerable<HeaderPart> partsHeader = pkgSourceDoc.MainDocumentPart.GetPartsOfType<HeaderPart>();
IEnumerable<FooterPart> partsFooter = pkgSourceDoc.MainDocumentPart.GetPartsOfType<FooterPart>();
//If the source document has headers or footers we want to retain them.
//This requires inserting a section break at the end of the document.
if (partsHeader.Count() > 0 || partsFooter.Count() > 0)
{
Body sourceBody = pkgSourceDoc.MainDocumentPart.Document.Body;
SectionProperties docSectionBreak = sourceBody.Descendants<SectionProperties>().Last();
//Make a copy of the document section break as this won't be imported into the target document.
//It needs to be appended to the last paragraph of the document
SectionProperties copySectionBreak = (SectionProperties)docSectionBreak.CloneNode(true);
Paragraph lastpara = sourceBody.Descendants<Paragraph>().Last();
ParagraphProperties paraProps = lastpara.ParagraphProperties;
if (paraProps == null)
{
paraProps = new ParagraphProperties();
lastpara.Append(paraProps);
}
paraProps.Append(copySectionBreak);
}
pkgSourceDoc.MainDocumentPart.Document.Save();
}
//Insert the source file into the target file using AltChunk
afType = AlternativeFormatImportPartType.WordprocessingML;
chunk = wdDocTargetMainPart.AddAlternativeFormatImportPart(afType, altChunkId);
System.IO.FileStream fsSourceDocument = new System.IO.FileStream(fi.FullName, System.IO.FileMode.Open);
chunk.FeedData(fsSourceDocument);
//Create the chunk
ac = new AltChunk();
//Link it to the part
ac.Id = altChunkId;
docTarget.Body.InsertAfter(ac, docTarget.Body.Descendants<Paragraph>().Last());
docTarget.Save();
altChunkCounter += 1;
altChunkId = altChunkIdBase + altChunkCounter.ToString();
chunk = null;
ac = null;
}
}
}
<w:body xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:p>
<w:pPr>
<w:pStyle w:val="Heading1" />
</w:pPr>
<w:subDoc r:id="rId6" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" />
</w:p>
<w:sectPr>
<w:headerReference w:type="default" r:id="rId7" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" />
<w:type w:val="continuous" />
<w:pgSz w:w="11906" w:h="16838" />
<w:pgMar w:top="1417" w:right="1417" w:bottom="1134" w:left="1417" w:header="708" w:footer="708" w:gutter="0" />
<w:cols w:space="708" />
<w:docGrid w:linePitch="360" />
</w:sectPr>
</w:body>
public class GeneratedClass
{
// Creates an Body instance and adds its children.
public Body GenerateBody()
{
Body body1 = new Body();
Paragraph paragraph1 = new Paragraph();
ParagraphProperties paragraphProperties1 = new ParagraphProperties();
ParagraphStyleId paragraphStyleId1 = new ParagraphStyleId(){ Val = "Heading1" };
paragraphProperties1.Append(paragraphStyleId1);
SubDocumentReference subDocumentReference1 = new SubDocumentReference(){ Id = "rId6" };
paragraph1.Append(paragraphProperties1);
paragraph1.Append(subDocumentReference1);
SectionProperties sectionProperties1 = new SectionProperties();
HeaderReference headerReference1 = new HeaderReference(){ Type = HeaderFooterValues.Default, Id = "rId7" };
SectionType sectionType1 = new SectionType(){ Val = SectionMarkValues.Continuous };
PageSize pageSize1 = new PageSize(){ Width = (UInt32Value)11906U, Height = (UInt32Value)16838U };
PageMargin pageMargin1 = new PageMargin(){ Top = 1417, Right = (UInt32Value)1417U, Bottom = 1134, Left = (UInt32Value)1417U, Header = (UInt32Value)708U, Footer = (UInt32Value)708U, Gutter = (UInt32Value)0U };
Columns columns1 = new Columns(){ Space = "708" };
DocGrid docGrid1 = new DocGrid(){ LinePitch = 360 };
sectionProperties1.Append(headerReference1);
sectionProperties1.Append(sectionType1);
sectionProperties1.Append(pageSize1);
sectionProperties1.Append(pageMargin1);
sectionProperties1.Append(columns1);
sectionProperties1.Append(docGrid1);
body1.Append(paragraph1);
body1.Append(sectionProperties1);
return body1;
}
}