Копирование содержимого части пакета Open XML в часть документа в другом пакете
В этом разделе показано, как использовать классы в пакете SDK Open XML для Office для копирования содержимого части документа Open XML Wordprocessing в часть документа в другом текстовом документе программным способом.
Пакеты и части документов
Документ Open XML хранится в виде пакета, формат которого определяется стандартом ISO/IEC 29500. Пакет может содержать несколько частей, между которыми существуют связи. Связь между частями определяет категорию документа. Документ может быть определен как текстовый, если его элемент связи пакета содержит связь с основной частью документа. Если элемент связи пакета содержит связь с частью презентации, документ может быть определен как документ презентации. Если элемент связи пакета содержит связь с частью книги, документ определяется как электронная таблица. В данном практическом руководстве рассматривается пакет текстового документа.
Получение объекта WordprocessingDocument
Чтобы открыть существующий документ, создайте WordprocessingDocument экземпляр класса, как показано в следующих двух using
инструкциях. В той же инструкции вы открываете текстовый файл с указанным именем файла с помощью Open метода с логическим параметром .
Исходный файл, который задает параметру значение , false
чтобы открыть его для доступа только для чтения. Для целевого файла задайте параметру значение true
, чтобы включить редактирование документа.
using (WordprocessingDocument wordDoc1 = WordprocessingDocument.Open(fromDocument1, false))
using (WordprocessingDocument wordDoc2 = WordprocessingDocument.Open(toDocument2, true))
В версии 3.0.0+ Close() метод был удален в пользу использования инструкции using.
Это гарантирует, что Dispose() метод автоматически вызывается при достижении закрывающей фигурной скобки. Блок, следующий за инструкцией using, создает область для объекта, создаваемого или именуемого в инструкции using.
WordprocessingDocument Так как класс в пакете SDK open XML автоматически сохраняет и закрывает объект в рамках его IDisposable реализации, а так как Dispose() вызывается автоматически при выходе из блока, не нужно явно вызывать Save() или Dispose() до тех пор, пока вы используете инструкцию using
.
Структура документа WordProcessingML
Базовая структура WordProcessingML
документа состоит из document
элементов и body
, за которыми следует один или несколько элементов уровня блока, таких как p
, который представляет абзац. Абзац содержит один или несколько r
элементов. Представляет r
собой область текста с общим набором свойств, таких как форматирование. Выполнение содержит один или несколько t
элементов. Элемент t
содержит диапазон текста. В следующем примере кода показана разметка WordprocessingML
для документа, содержащего текст "Пример текста".
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:body>
<w:p>
<w:r>
<w:t>Example text.</w:t>
</w:r>
</w:p>
</w:body>
</w:document>
С помощью пакета SDK Open XML можно создавать структуру документа и содержимое с помощью строго типизированных классов, соответствующих WordprocessingML
элементам. Эти классы находятся в пространстве имен. В следующей таблице перечислены имена классов, которые соответствуют document
элементам , body
, p
, r
и t
.
Элемент WordprocessingML | Класс пакета SDK Open XML | Описание |
---|---|---|
<document/> |
Document | Корневой элемент основной части документа. |
<body/> |
Body | Контейнер для структур уровня блокировки, таких как абзацы, таблицы, примечания и других элементов, описанных в спецификации ISO/IEC 29500. |
<p/> |
Paragraph | Абзац. |
<r/> |
Run | Прогон. |
<t/> |
Text | Диапазон текста. |
Дополнительные сведения об общей структуре частей и элементов документа WordprocessingML см. в разделе Структура документа WordprocessingML.
Часть темы
Часть темы содержит сведения о цветах, шрифтах и формате документа. Он определен в спецификации ISO/IEC 29500 следующим образом.
Экземпляр части этого типа содержит информацию о теме документа, которая включает в себя цветовую схему, схему шрифтов и схему форматов (последнюю также называют эффектами). Для документа WordprocessingML выбор темы помимо прочего влияет на цвет и стиль заголовков. Для документа SpreadsheetML выбор темы помимо прочего влияет на цвет и стиль содержимого ячеек и диаграмм. При выборе темы для документа PresentationML наряду с прочими элементами изменяются форматирование слайдов, раздаточные материалы и заметки через связанный с ними образец.
Пакет WordprocessingML или SpreadsheetML должен содержать не более одной части "тема", которая должна быть конечным объектом неявной связи в части "основной документ" (§11.3.10) или "книга" (§12.3.23). Пакет PresentationML не должен содержать ни одной части "тема" или содержать одну такую часть для каждой части "образец выдач" (§13.3.3), "образец заметок" (§13.3.4), "образец слайда" (§13.3.10) или "презентация" (§13.3.6) посредством неявной связи.
Пример. Следующий элемент отношения основного документа WordprocessingML содержит связь с частью Theme, которая хранится в теме или theme1.xml ЭЛЕМЕНТА ZIP:
<Relationships xmlns="…">
<Relationship Id="rId4"
Type="https://…/theme" Target="theme/theme1.xml"/>
</Relationships>
© ISO/IEC 29500: 2016
Механизм работы примера кода
Чтобы скопировать содержимое части документа в пакете Open XML в часть документа в другом пакете, полный путь к каждому текстовому документу передается в качестве параметра CopyThemeContent
в метод. Затем код открывает оба документа в виде WordprocessingDocument объектов и создает переменные, которые ссылаются на ThemePart части в каждом из пакетов.
static void CopyThemeContent(string fromDocument1, string toDocument2)
{
using (WordprocessingDocument wordDoc1 = WordprocessingDocument.Open(fromDocument1, false))
using (WordprocessingDocument wordDoc2 = WordprocessingDocument.Open(toDocument2, true))
{
ThemePart? themePart1 = wordDoc1?.MainDocumentPart?.ThemePart;
ThemePart? themePart2 = wordDoc2?.MainDocumentPart?.ThemePart;
Затем код считывает содержимое исходной ThemePart части с помощью объекта и записывает в целевую StreamReader
ThemePartStreamWriterчасть с помощью .
using (StreamReader streamReader = new StreamReader(themePart1.GetStream()))
using (StreamWriter streamWriter = new StreamWriter(themePart2.GetStream(FileMode.Create)))
{
streamWriter.Write(streamReader.ReadToEnd());
}
Пример кода
В приведенном ниже коде выполняется копирование содержимого части документа из одного пакета Open XML в другой. Чтобы вызвать CopyThemeContent
метод, можно использовать следующий пример, в котором часть темы копируется из пакетов, расположенных по адресуargs[0]
, в .args[1]
string fromDocument1 = args[0];
string toDocument2 = args[1];
CopyThemeContent(fromDocument1, toDocument2);
Важно!
Перед запуском программы убедитесь, что в исходном документе задана часть темы. Чтобы добавить тему в документ, откройте ее в Microsoft Word, перейдите на вкладку Конструктор, выберите пункт Темы и выберите одну из доступных тем.
После запуска программы можно просмотреть файл, чтобы увидеть измененную тему.
Ниже приведен полный пример кода на языках C# и Visual Basic.
static void CopyThemeContent(string fromDocument1, string toDocument2)
{
using (WordprocessingDocument wordDoc1 = WordprocessingDocument.Open(fromDocument1, false))
using (WordprocessingDocument wordDoc2 = WordprocessingDocument.Open(toDocument2, true))
{
ThemePart? themePart1 = wordDoc1?.MainDocumentPart?.ThemePart;
ThemePart? themePart2 = wordDoc2?.MainDocumentPart?.ThemePart;
// If the theme parts are null, then there is nothing to copy.
if (themePart1 is null || themePart2 is null)
{
return;
}
using (StreamReader streamReader = new StreamReader(themePart1.GetStream()))
using (StreamWriter streamWriter = new StreamWriter(themePart2.GetStream(FileMode.Create)))
{
streamWriter.Write(streamReader.ReadToEnd());
}
}
}