Я столкнулся с этим вопросом несколько лет go и потратил немало времени на него; В конце концов я написал статью в блоге , которая ссылается на образец файла. Достичь интеграции файлов с верхними и нижними колонтитулами с помощью Alt-Chunk не так просто. Я постараюсь охватить основы, здесь. В зависимости от того, какие типы содержимого содержатся в верхних и нижних колонтитулах (и при условии, что Microsoft не решила ни одну из проблем, с которыми я столкнулся), может оказаться невозможным полностью полагаться на AltChunk. быть Инструменты / API, которые могут справиться с этим - я не знаю, и спрашиваю, что на этом сайте будет off-topi c.)
Фон
Перед тем, как атаковать проблему, это помогает чтобы понять, как Word обрабатывает разные колонтитулы. Чтобы почувствовать это, запустите Word ...
Разрывы разделов / Отключение верхних / нижних колонтитулов
- Введите текст на странице и вставьте заголовок
- Переместить фокус в конец страницы и go на вкладку
Page Layout
на ленте - Настройка страницы / Разрывы / Разрыв следующей страницы
- Go в область заголовка для этой страницы и запишите информацию в синих «тегах»: вы увидите идентификатор раздела слева и «То же, что и предыдущий» справа. «То же, что и предыдущий» - это значение по умолчанию, чтобы создать другой заголовок, нажмите кнопку «Ссылка на предыдущий» в заголовке
Итак, правило :
требуется разрыв раздела с несвязанными верхними и нижними колонтитулами, чтобы иметь различное содержимое верхнего / нижнего колонтитула в документе.
Master / Sub- документы
Word обладает (не) известной функциональностью, называемой «Главный документ», которая позволяет связывать внешние («под») документы в «главный» документ. Это автоматически добавляет необходимые разрывы разделов и отменяет связь верхних и нижних колонтитулов, так что оригиналы сохраняются.
- Go в представлении структуры Word
- Нажмите «Показать документ»
- Используйте «Вставить» для вставки других файлов
Обратите внимание, что вставлено два разрыва раздела , один из которых типа «Следующая страница», а другой - «Непрерывный». Первый вставляется в входящий файл; второй в "мастер" файле.
При вставке файла *1057* необходимо сделать два разбиения раздела, так как последний абзац (который содержит разрыв раздела для конца документа) не переносится в целевой документ , Разрыв раздела в целевом документе содержит информацию, позволяющую отсоединить входящий заголовок от заголовка, уже имеющегося в целевом документе.
Когда мастер сохранен, закрыт и повторно открыт, вложенные документы находятся в «свернутое» состояние (имена файлов в виде гиперссылок вместо содержимого). Их можно развернуть, вернувшись в представление Outline и нажав кнопку «Развернуть». Чтобы полностью включить вложенный документ в документ, щелкните значок в левом верхнем углу рядом с вложенным документом, а затем нажмите «Отменить связь».
Объединение Word Open XML файлы
Это то есть тип среды, которую должен создать Open XML SDK при объединении файлов, чьи верхние и нижние колонтитулы необходимо сохранить. Теоретически, любой подход должен работать. Практически у меня были проблемы с использованием только разрывов разделов; Я никогда не тестировал использование основного документа в Word Open XML.
Вставка разрывов разделов
Вот базовый c код для вставки разрывов разделов и отсоединение заголовков перед вводом файла с помощью AltChunk
. Глядя на мои старые посты и статьи, пока нет сложной нумерации страниц, она работает:
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;
}
}
}
Если есть сложная нумерация страниц (цитируется из моей статьи в блоге):
К сожалению, в приложении Word есть ошибка при интеграции «кусочков» документов Word в основной документ. Процесс имеет Неприятная привычка не сохранять количество свойств объекта SectionProperties, среди которых тот, который устанавливает, имеет ли раздел Различную первую страницу (), и тот, который перезапускает нумерацию страниц () в разделе. Пока вашим документам не нужно управлять такими заголовками и колонтитулами, вы, вероятно, можете использовать подход «altChunk».
Но если вам нужно обрабатывать сложные верхние и нижние колонтитулы, единственный доступный в настоящее время метод - копировать каждый документ целиком, по частям. Это нетривиальное мероприятие, поскольку существует множество возможных типов деталей, которые могут быть связаны не только с основным телом документа, но также с каждой частью верхнего и нижнего колонтитула.
... или попробуйте подход Основной / Дополнительный документ.
Основной / Дополнительный документ
Этот подход, безусловно, сохранит всю информацию, однако откроется как Основной документ, и Word API (пользовательский код или код автоматизации) необходим для «отсоединения» вложенных документов, чтобы превратить их в единый интегрированный документ.
Открытие файла мастер-документа в Open XML SDK Productivity Tool показывает, что вставка вложенных документов в основной документ является довольно простой процедурой:
Основное слово Open XML для документа с одним вложенным документом:
<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;
}
}