Работа с документами
Работа с документами
Aspose.Words FOSS for .NET представляет каждый файл Word в виде объектной модели в памяти, корневой класс — Document, при этом DocumentBuilder предоставляет высокоуровневый, основанный на курсоре API для создания контента. Это руководство охватывает создание и загрузку документов, авторинг с помощью DocumentBuilder, структуру разделов/тела, обход дерева узлов, объединение документов и их защиту.
Создание и загрузка документов
Создайте пустой документ с помощью new Document() или откройте существующий файл, передав путь или Stream в конструктор Document(fileName) или Document(stream). Перегрузки, принимающие аргумент LoadOptions, позволяют управлять поведением загрузки, например, указывая пароль для зашифрованного файла.
Перед загрузкой файла из неизвестного или ненадёжного источника FileFormatUtil.DetectFileFormat(fileName) (или перегрузка Stream) возвращает FileFormatInfo, описывающий обнаруженный LoadFormat, и то, IsEncrypted, HasDigitalSignature или HasMacros файл.
Создание контента с помощью DocumentBuilder
DocumentBuilder оборачивает Document и предоставляет курсор, которым вы перемещаетесь по документу, вставляя содержимое. Write(text) и Writeln(text) вставляют текст в позицию курсора; InsertParagraph() начинает новый абзац. Свойства форматирования в билдере — Font, ParagraphFormat, ListFormat, PageSetup — применяются к следующему записываемому материалу.
Перемещайте курсор с помощью MoveToDocumentStart(), MoveToDocumentEnd(), MoveToSection(sectionIndex), MoveToBookmark(bookmarkName) или MoveToParagraph(paragraphIndex, characterIndex). Свойства CurrentNode, CurrentParagraph и CurrentSection билдера сообщают его текущую позицию в дереве.
Структура документа: разделы и тело
Document содержит SectionCollection (Document.Sections, плюс FirstSection / LastSection); каждый Section имеет один Body, необязательную коллекцию колонтитулов и свой собственный PageSetup. Section.AppendContent(sourceSection) и PrependContent(sourceSection) копируют содержимое между разделами, а ClearContent() сбрасывает раздел, не удаляя его из документа.
Внутри Body содержимое доступно через Body.Paragraphs (это ParagraphCollection) и Body.Tables. Range — доступный из Document, Section, Paragraph и других узлов — представляет собой непрерывную область дерева; Range.Text считывает его простой текст, а Range.Replace(pattern, replacement) выполняет поиск и замену только в этой области.
Обход дерева узлов с помощью DocumentVisitor
Каждая часть документа — разделы, абзацы, runs, таблицы, fields, shapes, комментарии, footnotes — является Node в составном дереве с корнем в Document. Чтобы обработать каждый узел заданного типа без ручной рекурсии, наследуйте абстрактный DocumentVisitor и переопределите необходимые callbacks Visit*Start / Visit*End, такие как VisitParagraphStart(paragraph) или VisitRun(run), затем вызовите document.Accept(visitor). Каждый callback может вернуть VisitorAction (Continue, SkipThisNode или Stop) для управления ходом обхода.
Клонирование, импорт и добавление содержимого
Document.Clone() создает глубокую копию всего документа. Чтобы переместить содержимое между двумя разными экземплярами Document, вызовите ImportNode(srcNode, isImportChildren) в документе-получателе, чтобы импортировать узел из внешнего дерева, или вызовите Document.AppendDocument(srcDoc, importFormatMode), чтобы добавить разделы одного документа к другому, используя выбранный ImportFormatMode — KeepSourceFormatting, UseDestinationStyles или KeepDifferentStyles. DocumentBuilder.InsertDocument(srcDoc, importFormatMode) вставляет содержимое исходного документа в курсор билдера вместо конца документа-получателя.
Защита документов
Document.Protect(type, password) ограничивает редактирование в соответствии со значением ProtectionType — ReadOnly, AllowOnlyComments, AllowOnlyRevisions, AllowOnlyFormFields или NoProtection для снятия защиты. Unprotect() (с паролем или без него) отменяет её. Это ограничение редактирования, применяемое Word, отдельное от шифрования паролем OOXML, которое OoxmlSaveOptions.Password использует при сохранении файла.
Советы и лучшие практики
- Предпочитайте
DocumentBuilderпри создании нового контента; переходите к прямому управлению узлами (AppendChild,InsertAfter,Clone), когда требуется тонкий контроль над существующим деревом. - Вызовите
FileFormatUtil.DetectFileFormatперед загрузкой файла из ненадёжного или пользовательского источника, чтобы проверитьLoadFormatи заранее отклонить неподдерживаемый или зашифрованный ввод. - При объединении документов с помощью
AppendDocumentилиInsertDocumentвыбирайтеImportFormatModeосознанно —KeepSourceFormattingсохраняет внешний вид исходного документа,UseDestinationStylesсоответствует набору стилей целевого документа. - Используйте подкласс
DocumentVisitorвместо ручного рекурсивного обхода дерева, когда необходимо последовательно обрабатывать каждый экземпляр типа узла. Document.Protect— это ограничение редактирования, а не шифрование — комбинируйте его сOoxmlSaveOptions.Password, если сам сохраняемый файл должен требовать пароль для открытия.
Общие проблемы
| Проблема | Причина | Исправление |
|---|---|---|
Document(fileName) выдает ошибку для файла, который открывается без проблем в Word | Формат файла не поддерживается этой редакцией для загрузки | Сначала вызовите FileFormatUtil.DetectFileFormat и проверьте возвращённый LoadFormat перед загрузкой |
| При добавлении содержимого оно наследует неправильные шрифты или стили | Несоответствие ImportFormatMode между наборами стилей источника и назначения | Передайте KeepSourceFormatting или UseDestinationStyles явно, а не полагайтесь на значение по умолчанию |
Обход DocumentVisitor останавливается преждевременно или пропускает содержимое | Переопределение Visit*Start / Visit*End возвращает SkipThisNode или Stop непреднамеренно | Возвращайте VisitorAction.Continue из каждого переопределения, если только вы специально не намерены пропустить или остановить |
Unprotect() не оказывает никакого влияния | Документ не был защищён паролем, либо был указан неверный пароль | Вызовите Unprotect() без аргументов, если Protect был вызван без пароля, иначе передайте соответствующий пароль |
FAQ
В чём разница между Document.Clone() и ImportNode?
Clone() копирует весь документ в новый экземпляр Document. ImportNode(srcNode, isImportChildren) переносит отдельный узел (и при желании его дочерние элементы) из дерева одного документа в другой, что используется при комбинировании конкретного содержания, а не целых документов.
Какие форматы файлов может загружать Document(fileName)?
Document(fileName) загружает DOCX, DOCM, DOTX, DOTM, Flat OPC (включая макрос-поддерживаемые и шаблонные варианты), Markdown и обычный текст. Более старые форматы обработки текста и веб-форматы исключены из загрузчиков этой версии.
Как узнать, где в данный момент расположен DocumentBuilder?
Прочитайте CurrentNode, CurrentParagraph или CurrentSection на экземпляре builder.
Шифрует ли Document.Protect сохранённый файл?
Нет — это ограничение редактирования, наложенное Word при открытии файла. Чтобы требовать пароль только для открытия файла, установите OoxmlSaveOptions.Password при сохранении.
Как прочитать только абзацы в теле документа?
Используйте коллекцию Body.Paragraphs или Body.GetChildNodes(nodeType, isDeep) для других типов узлов.
API Reference Сводка
| Класс/Метод | Описание: |
|---|---|
Document | Корень модели объектного документа; конструкторы загружают из файла или потока, либо создают пустой документ. |
Document.Save | Записывает документ в файл, поток или HTTP ответ в выбранном формате. |
Document.Clone() | Создаёт глубокую копию всего документа. |
Document.Protect(type, password) / Unprotect() | Применяет или удаляет ограничение редактирования. |
Document.AppendDocument(srcDoc, importFormatMode) | Добавляет разделы другого документа к этому. |
DocumentBuilder | Курсорный API для написания текста и вставки содержимого в документ. |
DocumentBuilder.InsertDocument(srcDoc, importFormatMode) | Вставляет содержимое исходного документа в позицию курсора. |
Section / SectionCollection | Один раздел документа и совокупность всех разделов. |
Body | Контейнер для основного текста (абзацев и таблиц) раздела. |
Range | Непрерывная область дерева документа; поддерживает Text и Replace. |
DocumentVisitor | Абстрактный базовый класс для обхода каждого узла дерева документа. |
ProtectionType | Перечисление ограничений редактирования на уровне документа. |
FileFormatUtil.DetectFileFormat | Определяет формат файла или потока перед загрузкой. |