Schemas openxmlformats org что это
Перейти к содержимому

Schemas openxmlformats org что это

  • автор:

Коротко об OpenXML

Вот уже более десятка лет разработчики бизнес-приложений регулярно сталкиваются с задачей генерации документов в форматах, поддерживаемых наиболее популярными офисными приложениями. Подобные задачи ставятся заказчиками проектов по разработке или внедрению информационных систем из-за того, что офисные приложения (в нашей стране это в первую очередь различные версии Microsoft Office), как правило, в той или иной мере знакомы всем бизнес-пользователям, а это существенно упрощает и удешевляет их обучение, обязательно проводимое в процессе внедрения новых решений, а также сопровождение самого решения.

Какие технологии обычно используются разработчиками для генерации подобных документов? Последние десять лет наиболее распространенным способом генерации документов формата Microsoft Office являлась технология COM (Component Object Model) — одна из базовых технологий Windows. Ее применение основано на том, что приложения Microsoft Office, равно как и многие приложения и службы самой операционной системы Windows, реализуют свои прикладные программные интерфейсы в виде COM-интерфейсов, доступных внешним приложениям. Практически все, что может сделать пользователь любого приложения семейства Microsoft Office с помощью меню, клавиатуры и панели инструментов, может быть реализовано в автоматическом режиме, то есть путем манипуляции соответствующим офисным приложением из бизнес-приложения, генерирующего соответствующие документы.

Читатели, интересующиеся деталями применения технологии COM для генерации офисных документов, могут обратиться к публикациям в нашем издании примерно семилетней давности (см., например, цикл статей «Автоматизация приложений Microsoft Office в примерах» в КомпьютерПресс № 11 и 12’2000) — эти материалы по-прежнему доступны на нашем сайте www.compress.ru. В данной же публикации мы не будем вдаваться в многократно обсуждавшиеся технические подробности, а вместо этого обратим внимание на один из недостатков этого подхода, который в конце 90-х годов казался несущественным, но сегодня должен обязательно учитываться.

Представим себе информационную систему, в которой генерация документов формата Microsoft Office должна осуществляться централизованно, а сами документы должны быть предназначены для применения большим количеством пользователей. Подобные требования могут предъявляться к средству генерации, например, еженедельных отчетов для менеджмента на основе корпоративной базы данных либо нормативной документации наподобие должностных инструкций на основании данных, регулярно обновляемых в том или ином средстве управления бизнес-процессами. Наиболее удобно при решении подобных задач осуществлять генерацию документов автоматически по расписанию, без участия пользователя, причем не на рабочей станции, а на сервере. Применение технологии COM в этом случае налагает серьезные ограничения на серверную операционную систему (это обязательно должна быть одна из версий Windows) и вынуждает иметь на сервере установленные офисные приложения. Очевидно, что генерация документов без наличия собственно офисных приложений была бы более удобной, ведь в этом случае серверное приложение не обязано работать под управлением той же платформы, что и офисные приложения. А это, в свою очередь, означает, что для создания подобных решений нужно, чтобы формат данных офисных приложений был документирован.

Форматы некоторых офисных приложений Microsoft были документированы вплоть до 2000 года, однако начиная с Office 2000 компания Microsoft перестала предоставлять доступ к спецификациям этих форматов, потому единственным способом корректной генерации документов Microsoft Office с этого момента и до выхода Office 2007 было применение все той же технологии COM. Однако после выхода Office 2007 данная ситуация изменилась — теперь формат офисных приложений Microsoft стал открытым и документированным. А это означает, что решения, генерирующие офисные документы, можно создавать в отсутствие самих офисных приложений — более того, создавать их на любой платформе.

Что такое OpenXML

Как было отмечено выше, идея открытого формата офисных документов отнюдь не нова. Однако именно в последнее время наметилась тенденция массового перехода офисных приложений к открытым форматам. Так, известный офисный пакет OpenOffice.org поддерживает открытый формат ODF (Open Document Format), спецификация которого является общедоступной, а кроме того, сегодня доступен и инструментарий разработки приложений, работающих с документами в формате ODF, — ODF Toolkit.

Формат OpenXML полностью поддерживает функциональность всех версий Microsoft Office — он позволяет сохранять все особенности документов, созданных с помощью Microsoft Office 2007 и предшествующих версий.

То, что существует техническая возможность создавать и сохранять документы формата OpenXML с помощью приложений, отличных от Microsoft Office 2007, интересно в первую очередь разработчикам бизнес-приложений и системным интеграторам. Что касается пользователей, их должна больше заинтересовать уже реализованная возможность его применения — например чтение и сохранение файлов формата OpenXML может быть осуществлено в рамках трех предыдущих версий Microsoft Office (начиная с Office 2000). Так, при попытке открыть документ этого формата с помощью Office 2003 пользователю будет предложено загрузить соответствующий конвертор (он доступен по адресу: http://www.microsoft.com/downloads/details.aspx?FamilyId=941B3470-3AE9-4AEE-8F43-C6BB74CD1466&displaylang=en), после установки которого чтение и сохранение документов формата OpenXML может осуществляться и прежними версиями Office.

Отметим, что формат OpenXML поддерживается не только офисными приложениями Microsoft — недавно компания Novell объявила о том, что версия OpenOffice, поставляемая ею на рынок, тоже будет поддерживать указанный формат.

Стандарты OpenXML

Формат OpenXML является отраслевым стандартом — в декабре организация ECMA стандартизовала спецификацию OpenXML.

Данный стандарт включает ряд более детальных стандартов. Главным из них является стандарт OPC (Open Packaging Convention), описывающий структуру файла, наличие различных типов данных в документе, взаимосвязь его составных частей, а также, при необходимости, цифровую подпись. Помимо OPC, структура документов OpenXML использует такие стандарты, как WordprocessingML, описывающий разметку текстовых документов, SpreadSheetML, определяющий структуру электронных таблиц, PresentationML, задающий структуру презентаций, DravingML, указывающий структуру графиков, диаграмм и некоторых графических объектов, а также стандарты, описывающие формулы, выражения и метаданные документа.

Отметим, что формат OpenXML предполагает различные способы интеграции данных документа с данными других приложений — он позволяет не просто применять схему форматирования, соответствующую функциональности современных версий офисных пакетов, но и определять свои схемы, позволяющие обмениваться данными с бизнес-приложениями.

Внутри документов OpenXML

СС точки зрения пользователя, документ в формате OpenXML представляет собой ZIP-архив. В этом можно убедиться, создав документ в Microsoft Word 2007, Microsoft Excel 2007 или Microsoft PowerPoint 2007 и заменив его расширение на *.zip. Этот архив содержит XML-данные, бинарные части, а также XML-описания их взаимосвязей.

Рассмотрим пример простейшего документа Word, cодержащего обычный текст, гиперссылку и графическое изображение (рис. 1).

Рис. 1. Пример документа Microsoft Word 2007

Данный документ имеет расширение *.docx (документ Microsoft Word 2007, не содержащий макросов). Заменив его расширение на *.zip и открыв его с помощью любого архиватора, поддерживающего метод упаковки ZIP, мы увидим структуру, изображенную на рис. 2.

Рис. 2. Структура документа Microsoft Word 2007

В корневой папке архива находится описание типов данных, содержащихся в документе, — внимательное изучение этого описания позволяет понять, что в документе имеется, к примеру, графическое изображение в формате GIF:

Папка _rels содержит файл с описанием взаимосвязей составных частей документа. В папке word находится файл document.xml, содержащий данные документа, в том числе текст «A paragraph», ссылку на рисунок с описанием его размеров и способа расположения в документе, указание на гиперссылку с описанием ее расположения, а также указания на стили текста:

Как я разбирал docx с помощью XSLT

Задача обработки документов в формате docx, а также таблиц xlsx и презентаций pptx является весьма нетривиальной. В этой статье расскажу как научиться парсить, создавать и обрабатывать такие документы используя только XSLT и ZIP архиватор.

Зачем?

docx — самый популярный формат документов, поэтому задача отдавать информацию пользователю в этом формате всегда может возникнуть. Один из вариантов решения этой проблемы — использование готовой библиотеки, может не подходить по ряду причин:

  • библиотеки может просто не существовать
  • в проекте не нужен ещё один чёрный ящик
  • ограничения библиотеки по платформам и т.п.
  • проблемы с лицензированием
  • скорость работы

Поэтому в этой статье будем использовать только самые базовые инструменты для работы с docx документом.

Структура docx

Для начала разоберёмся с тем, что собой представляет docx документ. docx это zip архив который физически содержит 2 типа файлов:

  • xml файлы с расширениями xml и rels
  • медиа файлы (изображения и т.п.)

А логически — 3 вида элементов:

  • Типы (Content Types) — список типов медиа файлов (например png) встречающихся в документе и типов частей документов (например документ, верхний колонтитул).
  • Части (Parts) — отдельные части документа, для нашего документа это document.xml, сюда входят как xml документы так и медиа файлы.
  • Связи (Relationships) идентифицируют части документа для ссылок (например связь между разделом документа и колонтитулом), а также тут определены внешние части (например гиперссылки).

Они подробно описаны в стандарте ECMA-376: Office Open XML File Formats, основная часть которого — PDF документ на 5000 страниц, и ещё 2000 страниц бонусного контента.

Минимальный docx

Простейший docx после распаковки выглядит следующим образом

image

Давайте посмотрим из чего он состоит.

[Content_Types].xml

Находится в корне документа и перечисляет MIME типы содержимого документа:

_rels/.rels

Главный список связей документа. В данном случае определена всего одна связь — сопоставление с идентификатором rId1 и файлом word/document.xml — основным телом документа.

word/document.xml

word/document.xml

    Test          

Если открыть этот документ в текстовом редакторе, то увидим документ из одного слова Test .

word/_rels/document.xml.rels

Здесь содержится список связей части word/document.xml . Название файла связей создаётся из названия части документа к которой он относится и добавления к нему расширения rels . Папка с файлом связей называется _rels и находится на том же уровне, что и часть к которой он относится. Так как связей в word/document.xml никаких нет то и в файле пусто:

Даже если связей нет, этот файл должен существовать.

docx и Microsoft Word

docx созданный с помощью Microsoft Word, да в принципе и с помощью любого другого редактора имеет несколько дополнительных файлов.

image

Вот что в них содержится:

  • docProps/core.xml — основные метаданные документа согласно Open Packaging Conventions и Dublin Core [1], [2].
  • docProps/app.xml — общая информация о документе: количество страниц, слов, символов, название приложения в котором был создан документ и т.п.
  • word/settings.xml — настройки относящиеся к текущему документу.
  • word/styles.xml — стили применимые к документу. Отделяют данные от представления.
  • word/webSettings.xml — настройки отображения HTML частей документа и настройки того, как конвертировать документ в HTML.
  • word/fontTable.xml — список шрифтов используемых в документе.
  • word/theme1.xml — тема (состоит из цветовой схемы, шрифтов и форматирования).

В сложных документах частей может быть гораздо больше.

Реверс-инжиниринг docx

Итак, первоначальная задача — узнать как какой-либо фрагмент документа хранится в xml, чтобы потом создавать (или парсить) подобные документы самостоятельно. Для этого нам понадобятся:

  • Архиватор zip
  • Библиотека для форматирования XML (Word выдаёт XML без отступов, одной строкой)
  • Средство для просмотра diff между файлами, я буду использовать git и TortoiseGit
Инструменты
  • Под Windows: zip, unzip, libxml2, git, TortoiseGit
  • Под Linux: apt-get install zip unzip libxml2 libxml2-utils git

Также понадобятся скрипты для автоматического (раз)архивирования и форматирования XML.
Использование под Windows:

  • unpack file dir — распаковывает документ file в папку dir и форматирует xml
  • pack dir file — запаковывает папку dir в документ file

Использование под Linux аналогично, только ./unpack.sh вместо unpack , а pack становится ./pack.sh .

Использование

Поиск изменений происходит следующим образом:

  1. Создаём пустой docx файл в редакторе.
  2. Распаковываем его с помощью unpack в новую папку.
  3. Коммитим новую папку.
  4. Добавляем в файл из п. 1. изучаемый элемент (гиперссылку, таблицу и т.д.).
  5. Распаковываем изменённый файл в уже существующую папку.
  6. Изучаем diff, убирая ненужные изменения (перестановки связей, порядок пространств имён и т.п.).
  7. Запаковываем папку и проверяем что получившийся файл открывается.
  8. Коммитим изменённую папку.
Пример 1. Выделение текста жирным

Посмотрим на практике, как найти тег который определяет форматирование текста жирным шрифтом.

  1. Создаём документ bold.docx с обычным (не жирным) текстом Test.
  2. Распаковываем его: unpack bold.docx bold .
  3. Коммитим результат.
  4. Выделяем текст Test жирным.
  5. Распаковываем unpack bold.docx bold .
  6. Изначально diff выглядел следующим образом:

diff

Рассмотрим его подробно:

docProps/app.xml
@@ -1,9 +1,9 @@ - 0 + 1

Изменение времени нам не нужно.

docProps/core.xml
@@ -4,9 +4,9 @@ - 1 + 2 2017-02-07T19:37:00Z - 2017-02-07T19:37:00Z + 2017-02-08T10:01:00Z

Изменение версии документа и даты модификации нас также не интересует.

word/document.xml
@@ -1,24 +1,26 @@ - +   +    - +  +   Test    - +

Изменения в w:rsidR не интересны — это внутренняя информация для Microsoft Word. Ключевое изменение тут

в параграфе с Test. Видимо элемент и делает текст жирным. Оставляем это изменение и отменяем остальные.

word/settings.xml
@@ -1,8 +1,9 @@ + @@ -17,10 +18,11 @@ + 

Также не содержит ничего относящегося к жирному тексту. Отменяем.

7 Запаковываем папку с 1м изменением (добавлением ) и проверяем что документ открывается и показывает то, что ожидалось.
8 Коммитим изменение.

Пример 2. Нижний колонтитул

Теперь разберём пример посложнее — добавление нижнего колонтитула.
Вот первоначальный коммит. Добавляем нижний колонтитул с текстом 123 и распаковываем документ. Такой diff получается первоначально:

diff

Сразу же исключаем изменения в docProps/app.xml и docProps/core.xml — там тоже самое, что и в первом примере.

[Content_Types].xml
@@ -4,10 +4,13 @@  + + + 

footer явно выглядит как то, что нам нужно, но что делать с footnotes и endnotes? Являются ли они обязательными при добавлении нижнего колонтитула или их создали заодно? Ответить на этот вопрос не всегда просто, вот основные пути:

  • Посмотреть, связаны ли изменения друг с другом
  • Экспериментировать
  • Ну а если совсем не понятно что происходит:

Читать документацию

Идём пока что дальше.

word/_rels/document.xml.rels

Изначально diff выглядит вот так:

@@ -1,8 +1,11 @@  +  +   - - + + + 

Видно, что часть изменений связана с тем, что Word изменил порядок связей, уберём их:

@@ -3,6 +3,9 @@ + + + 

Опять появляются footer, footnotes, endnotes. Все они связаны с основным документом, перейдём к нему:

word/document.xml
@@ -15,10 +15,11 @@   +     

Редкий случай когда есть только нужные изменения. Видна явная ссылка на footer из sectPr. А так как ссылок в документе на footnotes и endnotes нет, то можно предположить что они нам не понадобятся.

word/settings.xml
@@ -1,19 +1,30 @@   +   + + + + + + + +        + + 

А вот и появились ссылки на footnotes, endnotes добавляющие их в документ.

word/styles.xml
@@ -480,6 +480,50 @@     + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 

Изменения в стилях нас интересуют только если мы ищем как поменять стиль. В данном случае это изменение можно убрать.

word/footer1.xml

Посмотрим теперь собственно на сам нижний колонтитул (часть пространств имён опущена для читабельности, но в документе они должны быть):

Тут виден текст 123. Единственное, что надо исправить — убрать ссылку на .

В результате анализа всех изменений делаем следующие предположения:

  • footnotes и endnotes не нужны
  • В [Content_Types].xml надо добавить footer
  • В word/_rels/document.xml.rels надо добавить ссылку на footer
  • В word/document.xml в тег надо добавить

Уменьшаем diff до этого набора изменений:

final diff

Затем запаковываем документ и открываем его.
Если всё сделано правильно, то документ откроется и в нём будет нижний колонтитул с текстом 123. А вот и итоговый коммит.

Таким образом процесс поиска изменений сводится к поиску минимального набора изменений, достаточного для достижения заданного результата.

Практика

Найдя интересующее нас изменение, логично перейти к следующему этапу, это может быть что-либо из:

  • Создания docx
  • Парсинг docx
  • Преобразования docx

Тут нам потребуются знания XSLT и XPath.

Давайте напишем достаточно простое преобразование — замену или добавление нижнего колонтитула в существующий документ. Писать я буду на языке Caché ObjectScript, но даже если вы его не знаете — не беда. В основном будем вызовать XSLT и архиватор. Ничего более. Итак, приступим.

Алгоритм

Алгоритм выглядит следующим образом:

  1. Распаковываем документ.
  2. Добавляем наш нижний колонтитул.
  3. Прописываем ссылку на него в [Content_Types].xml и word/_rels/document.xml.rels .
  4. В word/document.xml в тег добавляем тег или заменяем в нём ссылку на наш нижний колонтитул.
  5. Запаковываем документ.
Распаковка

В Caché ObjectScript есть возможность выполнять команды ОС с помощью функции $zf(-1, oscommand). Вызовем unzip для распаковки документа с помощью обёртки над $zf(-1):

/// Используя %3 (unzip) распаковать файл %1 в папку %2 Parameter UNZIP = "%3 %1 -d %2"; /// Распаковать архив source в папку targetDir ClassMethod executeUnzip(source, targetDir) As %Status
Создаём файл нижнего колонтитула

На вход поступает текст нижнего колонтитула, запишем его в файл in.xml:

TEST

В XSLT (файл — footer.xsl) будем создавать нижний колонтитул с текстом из тега xml (часть пространств имён опущена, вот полный список):

do ##class(%XML.XSLT.Transformer).TransformFile("in.xml", "footer.xsl", footer0.xml") 

В результате получится файл нижнего колонтитула footer0.xml :

      TEST   
Добавляем ссылку на колонтитул в список связей основного документа

Сссылки с идентификатором rId0 как правило не существует. Впрочем можно использовать XPath для получения идентификатора которого точно не существует.
Добавляем ссылку на footer0.xml c идентификатором rId0 в word/_rels/document.xml.rels :

Прописываем ссылки в документе

Далее надо в каждый тег добавить тег или заменить в нём ссылку на наш нижний колонтитул. Оказалось, что у каждого тега может быть 3 тега — для первой страницы, четных страниц и всего остального:

                
Добавляем колонтитул в [Content_Types].xml

Добавляем в [Content_Types].xml информацию о том, что /word/footer0.xml имеет тип application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml :

В результате

Весь код опубликован. Работает он так:

do ##class(Converter.Footer).modifyFooter("in.docx", "out.docx", "TEST")
  • in.docx — исходный документ
  • out.docx — выходящий документ
  • TEST — текст, который добавляется в нижний колонтитул

Выводы

Используя только XSLT и ZIP можно успешно работать с документами docx, таблицами xlsx и презентациями pptx.

Открытые вопросы

  1. Изначально хотел использовать 7z вместо zip/unzip т… к. это одна утилита и она более распространена на Windows. Однако я столкнулся с такой проблемой, что документы запакованные 7z под Linux не открываются в Microsoft Office. Я попробовал достаточно много вариантов вызова, однако положительного результата добиться не удалось.
  2. Ищу XSD со схемами ECMA-376 версии 5 и комментариями. XSD версии 5 без комментариев доступен к загрузке на сайте ECMA, но без комментариев в нём сложно разобраться. XSD версии 2 с комментариями доступен к загрузке.

Ссылки

  • ECMA-376
  • Описание docx
  • Подробная статья про docx
  • Репозиторий со скриптами
  • Репозиторий с преобразователем нижнего колонтитула

Файлы MS Office «изнутри». Open Packaging Conventions. Базовые принципы. Компоненты и связи

Файлы MS Office

Сегодняшним постом я хочу начать серию материалов. В ней я планирую немного поговорить о том, что представляют собой файлы MS Office “изнутри”, а также об инструментах (утилитах и библиотеках) для их создания, изучения, изменения, …

image

Сегодняшним постом я хочу начать еще одну серию. В ней я планирую немного поговорить о том, что представляют собой файлы MS Office “изнутри”, а также об инструментах (утилитах и библиотеках) для их создания, изучения, изменения, …

Прежде чем перейти к содержательной части некоторый предваряющий disclaimer (традиционно ):

Я в основном буду касаться современных офисных форматов, тех что появились в редакции Office 2007. Их еще называют XML-based форматами, в противовес старым бинарным (и это закрепилось в расширении файлов: docx, pptx, xlsx, … – в противовес doc, ppt, xls, …), ну или просто Open XML

Некоторая часть статей (по крайней мере в самом начале) будет основана на материалах Open XML Developer Workshop (контент и видео), который вел Doug Mahugh. Если вам не хочется ждать моих статей рекомендую обратиться к этим материалам

Еще одним хорошим подспорьем для изучающих Open XML будет книга Воутер Ван Вугт. OpenXML. Кратко и доступно. Ранее она в электронном виде была доступна в блоге евангелиста Microsoft Владимира Габриеля, но теперь – увы. Так что, если вам интересно и не хочется тратить время на поиск, можете взять здесь.

Вроде бы все. Можно приступать.

Что такое Open Packaging Conventions?

В двух словах, это формат контейнеров, поддерживающих хранение как структурированных (XML), так и неструктурированных компонентов (картинки, видео, бинарные компоненты, …) в одном файле.

Краткая но довольно информативная статья об OPC есть на wikipedia.

Что можно сказать в общем об этом стандарте/формате? Я бы выделил такие моменты:

● Формальное описание является частью ECMA-376. Office Open XML File Formats, более конкретно – второй частью Part 2 — Open Packaging Conventions.

● Сам стандарт описывает только структуру хранения и самые общие метаданные (типа автора, даты,…) поэтому потенциально в таком контейнере можно хранить практически что угодно.

Например, вот несколько форматов, основанных на OPC от самого Microsoft:

o .docx, pptx, xlsx, .vsdx – форматы Word, Power Point, Excel и Visio

o .xps (.oxps) – формат “электронной бумаги” или формат c фиксированной разметкой, предназначенный для передачи документов без искажения форматирования (в чем-то аналог PDF).

o .vsix – формат расширений Visual Studio, начиная с версии 2010

o .cspkg – формат пакетов для Windows Azure Cloud Services

o .appx – формат пакетов приложений Windows Store (для Windows 8)

Что представляют собой контейнеры в OPC?

Тут нужно сделать одну существенную оговорку: сам стандарт разбивает описание контейнеров на 2 части: абстрактную модель (которая описывает из каких элементов состоят контейнеры, но ни слова не говорит о том как это должно храниться физически) и физический формат пакета, т.е. конкретную реализацию.

Т.е. в чистой теории, контейнер в OPC может храниться единый файл, а может, например, как набор отдельных ресурсов на Web-сервере. Но (!) на текущий момент определена только 1 реализация – в виде единого файла ZIP-архива.

Структура контейнеров в OPC

Вообще говоря, концептуальная схема пакетов в Open Packaging Conventions очень проста, она включает в себя всего два элемента:

● компоненты (parts), которые собственно и содержат хранящийся контент (любой: xml, image, video, …)

● отношения (relationships), которые определяют

o предназначение (смысл/семантику) каждой части

o отношения между частями, а также между частями и пакетом целиком

image

Как уже было сказано выше компонент в OPC это и есть основная единица хранения контента. Каждый компонент характеризуется 2-я составляющими: именем и типом содержимого.

Имя компонента состоит из набора сегментов, начинающихся с прямого слэша (“/”), вот несколько примеров:

В спецификации приведены более формальные правила построения имен, из которых я укажу только основные (на мой взгляд):

● все имена должны начинаться с прямого слэша (“/”) и не должны им заканчиваться

● имя недолжно содержать пустых сегментов (т.е. /images//image1.jpg – неправильное имя)

● ни одно имя компонента не должно строиться как имя уже существующего компонента + новый сегмент. Т.е. если есть компонент с именем /abc/abc, то компонент с именем /abc/abc/a существовать не может, зато вполне может существовать компонент с именем /abc/abcde

● имена могут записываться Unicode-символами или использовать кодирование в виде /a/%D1%86.xml

Тип содержимого компонента задается в соответствии с RFC 2616 (раздел Media Types) т.е. в виде /:

Связи

Любой компонент в пакете (а также сам пакет) может ссылаться на другие компоненты или некоторые ресурсы за пределами пакета. Для представления этих ссылок введен специальный механизм связей. По большому счету, связи позволяют решить 2 задачи:

● получить список связанных с компонентом ресурсов, без необходимости анализировать его содержимое (которое может быть очень большим, иметь разную структуру, быть зашифрованным или вообще не поддерживать хранение ссылок)

● поменять набор связей компонента, не меняя его содержимого (которое может быть, например, зашифровано или защищено цифровой подписью)

Создавая свой пакет вы, конечно же, можете не использовать связи. Вместо этого везде в коде использовать фиксированные имена компонент, а где нужны списки связанных ресурсов, ссылаться на них прямо из самих компонент. Однако, рекомендации “лучших собаководов” все же советуют использовать связи везде, где это возможно.

Информация о связях для каждого компонента (а также самого пакета), хранится в специальных компонентах связей (relationships parts) тип содержимого которых application/vnd.openxmlformats-package.relationships+xml

Имена компонентов связи строятся из имени исходных компонент, к которым:

● добавляется предпоследний сегмент с именем _rels

● дописывается “расширение” .rels

Связи самого пакета хранятся в специальном компоненте с именем /_rels/.rels

Например, если в пакете у нас есть компонент с именем /document/mainPart.xml и два связанных компонента с картинками (пусть их мена будут /images/image1.png и /images/image2.jpeg), то пакет для них будет иметь следующую структуру:

image

Содержимое компонента связи представляет собой XML следующего формата:


Type=»http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles»
Target=»styles.xml» />
Type=»http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme»
Target=»theme/theme1.xml» />
Type=»http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable»
Target=»fontTable.xml» />
Type=»http://schemas.openxmlformats.org/officeDocument/2006/relationships/image»
Target=»file:///C:\Users\Public\Pictures\Sample%20Pictures\Desert.jpg»
TargetMode=»External» />

Как уже наверняка понятно из приведенного фрагмента, каждый тэг определяет одну связь. Его атрибуты:

Идентификатор связи. На него ссылаются из содержимого компонент, когда необходимо использовать конкретную связь.

Тип связи. По сути дела тип указывает семантику связи. Например, две разных связи могут указывать на 2 компонента типа image/jpeg, но одно изображение будет картинкой в тексте документа, а второе – миниатюрой (thumbnail) всей страницы целиком.
В качестве типа может использоваться любой валидный URI

(Необязательный) Принимает одно из возможных значений:

· Internal (значение по умолчанию) – указывает, что связь ссылается на компонент пакета

· External – связь указывает на ресурс за пределами пакета

Адрес ресурса или компонента на который ссылается связь

Важный момент: для обращения к компонентам и внешним ресурсам можно использовать как абсолютные адреса (для компонент это будет их полное имя), так и относительные. В последнем случае полное имя компоненты рассматривается как путь в файловой системе, каждый сегмент, кроме последнего – имя “папки”, а последний – имя “файла”. Вот несколько примеров такой адресации:

Имя исходного компонента

.xlsx изнутри. Разбор структуры файлов. Разбор каждого .xml файла

Недавно мне понадобилось встроить в CRM возможность создания отчетов в Excel посредством PHP, но готовые решения были сильно громоздкими. Поэтому я решил написать собственную библиотеку для работы с Excel файлами через PHP. Но информации о внутренности Excel было очень мало и мне пришлось собирать ее по крупинкам, иногда методами тыка, проб и ошибок разбирал работу некоторых элементов.

На написание данной статьи меня натолкнули уже существующие статьи от @Lachrimae.

Но дополнять ее в комментариях — очень громоздко и неудобно. Поэтому я решил поделиться всеми свои знаниями в новой статье, и если это поможет кому-то, то мои старания будут более, чем не напрасны.

Оглавление:

  1. Структура файлов;
  2. Разбор файла _rels/.rels;
  3. Разбор docProps/app.xml;
  4. Разбор docProps/core.xml;
  5. Разбор xl/_rels/workbook.xml.rels;
  6. Разбор xl/printerSettings/printerSettings1.bin;
  7. Разбор xl/theme/theme1.xml;
  8. Разбор xl/worksheets/_rels/sheet1.xml.rels;
  9. Разбор xl/worksheets/sheet1.xml;
  10. Разбор xl/caclChain.xml;
  11. Разбор xl/sharedStrings.xml;
  12. Разбор xl/styles.xml;
  13. Разбор xl/workbook.xml;
  14. Разбор [Content_Types].xml;
  15. Завершение.

Структура файлов

Так как Excel — это архив файлов .xml, то мы можем его распаковать и увидеть следующее содержание:

Дерево файлов и подкаталогов

Некоторые файлы могут отсутствовать, такие как: xl/worksheets/_rels/sheet.xml.rels, xl/calcChain.xml, xl/printerSettings/printerSettings1.bin и sharedString.xml

В папках xl/worksheets, xl/printerSettings и xl/worksheets/_rels могут быть по несколько файлов.

Давайте разберёмся, для чего все эти файлы, начнём по порядку:

_rels/.rels — описание связей файлов, касаемых самой работы Excel;

docProps/app.xml — описание и настройки приложения Excel;

docProps/core.xml — здесь записывается имя создателя файла, время создания и последнего редактирования файла;

xl/_rels/workbook.xml.rels — перечень и описание зависимостей файлов, используемых в книге;

xl/printerSettings/printerSettings1.bin — описание настроек для печати листа;

xl/theme/theme1.xml — описание стилей приложения;

xl/worksheets/_rels/sheet1.xml.rels — описание связей листа xl/worksheets/sheet1.xml с другими документами;

xl/worksheets/sheet1.xml — описание всего происходящего на листе, который находится на первой позиции в списке листов книги. Название листа и название файла никак не связаны, файл всегда называется sheet1, sheet2 и т.д. На каждый лист приходится один такой файл;

xl/caclChain.xml — цепочка вычислений. Конструкция, указывающая порядок вычислений ячеек в книге в последний раз;

xl/sharedStrings.xml — перечень строковых значений, используемых во всей книге;

xl/styles.xml — описание стилей, используемых во всей книге;

xl/workbook.xml — описание настроек книги и перечень используемых листов;

[Content_Types].xml — описание всех файлов и их типов.

Разбор файла _rels/.rels

Если открыть файл — мы увидим следующее содержание:

В первой строке у нас объявляется тип документа — xml с его версией, кодировкой и автономности.

standalone (автономность) — Это объявление указывает, содержит ли внешнее подмножество DTD (Document Type Definition — определение типа документа) какие-либо объявления, которые могут повлиять на текущее содержимое документа.

Вторая строчка — открывающий тег для описания связей документов. Атрибут xmlns — означает, что используется пространство имен, от сюда и название самого атрибута — xml NameSpace.

Далее идут 3 строки связей с документами. У каждого есть атрибуты: Id — уникальное имя для связи, Type — ссылка на стандарт, описывающий нужный нам тип документа, Target — путь к исполняемому файлу.

Разбор docProps/app.xml

Содержимое данного файла примерно такая (не все элементы могут присутствовать и иметь тот же вид, что и у меня):

  Microsoft Excel 0 false   Worksheets  1     Лист 1   false false false 14.0300 

Первая строка нам уже знакома.

Во второй строке открывающий тег properties и эта строка похожа на рассмотренную нами ранее.

Третья строка содержит название приложения. В данном случае — Microsoft Excel (что не удивительно). Данную строку лучше не изменять, ибо приложение упадет.

Означает безопасность документа и в зависимости от числа имеет следующий посыл:

0 — Документ не защищен

1 — Документ защищен паролем.

2 — Рекомендуется открывать документ только для чтения.

4 — Документ принудительно открыт только для чтения.

8 — Документ заблокирован для заметок.

false

указывает режим отображения эскиза документа. Установите для этого элемента значение TRUE, чтобы включить масштабирование эскиза документа на экране. Установите для этого элемента значение FALSE, чтобы включить обрезку эскиза документа, чтобы отображались только те разделы, которые соответствуют отображаемому значению (из документации microsoft).

Далее открывается тег HeadingPairs, внутри которого описаны группы частей документа и количество частей в каждой группе. Эти части являются не частями документа, а концептуальными представлениями разделов документа.

Внутри HeadingPairs мы имеем 1 векторный контент, в котором имеются 2 его части (подробнее о векторах и baseType можно почитать в документации microsoft).

Первая часть означает, что мы описываем листы в книге, а во второй части указываем количество этих листов.

Следующий тег — TitlesOfParts. Он описывает наименования частей документа. в данном случае — названия листов в книге. Здесь также указывается количество частей векторного контента.

В теге Company можно записать название компании.

Следующий элемент — LinksUpToDate — указывает, актуальны ли гиперссылки в документе. Установите для этого элемента значение TRUE, чтобы показать, что гиперссылки обновлены. Установите для этого элемента значение FALSE, чтобы указать, что гиперссылки устарели (из документации microsoft).

Элемент SharedDoc указывает, является ли этот документ в настоящее время общим для нескольких производителей. Если для этого элемента установлено значение TRUE, производителям следует проявлять осторожность при обновлении документа.

HyperlinksChanged указывает, что одна или несколько гиперссылок в этой части были обновлены исключительно в этой части производителем. Следующий производитель, который откроет этот документ, обновит отношения гиперссылок новыми гиперссылками, указанными в этой части.

Тег AppVersion указывает версию используемого приложения Excel при создании файла

Разбор docProps/core.xml

Содержимое файла примерно таково:

  Виктор 2006-09-16T00:00:00Z 2006-09-16T00:00:00Z 

Первая строка нам уже знакома.

Во второй строке открывающий тег cp:coreProperties и эта строка похожа на рассмотренную нами ранее. Внутри него описываются свойства приложения:

dc:creator — Имя создателя документа;

dcterms:created — дата и время создания файла;

dcterms:modified — дата и время последнего изменения файла;

Разбор xl/_rels/workbook.xml.rels

Примерное содержимое файла:

Этот файл похож на раннее рассмотренный нами, только здесь уже описываются зависимости для файлов, которые используются непосредственно в книге.

Здесь записаны зависимости всех листов в книге, файла со строковыми значениями, цепочками вычислений и прочих файлов (мы разберем эти файлы дальше)

Разбор xl/printerSettings/printerSettings1.bin

Это файл, содержащий код в бинарном виде. Чтобы разобрать этот файл нужно описать много вещей про бинарники, а, чтобы научить писать правильно такой файл, потребуется много сил, времени и много текста. Да и в целом не вижу смысла вам работать с этим файлом. (честно говоря, я сам поверхностно знаком с этой темой).

Разбор xl/theme/theme1.xml

У меня не было надобностей разбирать этот файл, поэтому пока не буду описывать его работу. Но если кому-то понадобится (не знаю зачем) подробный разбор этого файла — я постараюсь сделать это.

Разбор xl/worksheets/_rels/sheet1.xml.rels

Содержимое этого файла может быть следующим:

Здесь описана одна зависимость с файлом xl/printerSettings/printerSettings1.bin — настройками для печати.

Разбор xl/worksheets/sheet1.xml

Начинается самое интересное и большое в этой статье.

Начинается такой файл с обычного объявления типа документа xml и некоторых настроек:

Строка третья означает размер экспортируемого диапазона (с какой по какую ячейку находятся данные).

В теге sheetViewselection описывается выделенная клетка (или диапазон клеток).

Атрибут activeCell — активная ячейка, sqref — выделенная ячейка или диапазон ячеек.

такая строка может выглядеть и вот так:

Здесь уже вместо атрибута activeCell стоит activeCellId, потому что в атрибуте sqref мы видим несколько диапазонов. исходя из этого выясняем, что активный диапазон является A1:C3. на изображении ниже показано, как выглядит такой вариант выделения ячеек.

Выделенные ячейки

Про тег pane, sheetFormatPr и cols хорошо рассказано в статье от @Lachrimae:

Собственно, закрепление строки — тег . И вот какие здесь использованы атрибуты:

ySplit — показывает количество закрепленных строк. Для закрепления столбцов есть аналогичный атрибут xSplit;

topLeftCell — указание левой верхней ячейки, видимой по умолчанию НЕзакрепленной области;

activePane — указание местонахождения НЕзакрепленной области. В руководствах сказано, что этот атрибут регулирует, с какой стороны будет НЕзакрепленная область. Правда, попробовав разные значения, я почему-то получил одинаковый результат. Как вариант «by default» я для себя выбрал bottomRight;

state — указатель состояния закрепленной области. Для простого закрепления строки используется значение frozen

Тег . Пример:

Интересен нам здесь в основном атрибут defaultRowHeight, то есть высота столбца по умолчанию. Стандартный, привычный нам вариант — 15 у.е. Если назначить его, скажем, 30 у.е., то строки, для которых высота не указана отдельно, станут в 2 раза выше. Однако, для того чтоб применить значение, отличное от дефолтного, необходимо указать атрибут customHeight со значением «true». Выглядит это примерно так:

Тег . Помогает установить ширину столбцов отличную от дефолтной. В заполненном виде выглядит примерно так:

Вложенные теги обозначают не каждый один столбец, как могло показаться, а группу столбцов, идущих подряд и имеющих единую ширину.

Атрибут min — первый столбец группы;

Атрибут max — последний столбец группы;

Атрибут width — ширина столбца из группы;

Атрибут customWidth — флаг применения кастомной ширины, без него ширина все равно будет дефолтной;

Тег sheetData — описание содержимого ячеек и их настроек.

здесь структура такова:

   1  0  1  2  1    2  SUM(A1:E1) 2   

В Excel это будет выглядеть вот так:

Ячейки с данными

Давайте разбираться, что же все-таки в коде происходит.

Мы видим два тега row — это наши строки. У каждой есть атрибут r — это номер строки. Атрибут spans означает сколько столбцов задействовано, dyDescent — вертикальное расстояние в пикселях между ячейками. Атрибут ht устанавливает высоту всей строки в пунктах, а тег customHeight говорит, что мы используем нестандартную высоту строки.

В теге row есть теги c — это ячейки в строке. у каждого тега есть атрибут r — означающий позицию ячейки. Но атрибут t — присутствует не у всех, потому что запись t=»s» — означает, что у ячейки установлен тип строки, а у кого этого атрибута нет — тип устанавливается стандартный — числовой. Еще у тегов c может присутствовать атрибут s, в котором записывается номер применяемого к ячейке стиля из файла xl/styles.xml (мы доберемся до него позже).

Внутри тегов c есть теги v — это наши значения, записываемые в ячейки. Но не все так просто. Те значения, которые находятся в теге c без атрибута t — те значения записываются без изменений, т.е. записывается в ячейку само число из тега v, а вот те значения, которые находятся в теге c с атрибутом t — уже обрабатываются по-другому: в теге v записан порядковый номер строки в файле xl/sharedStrings.xml (мы доберемся до него позже). В ячейку уже записывается строка, которая имеет порядковый номер, записанный в теге v.

Но мы можем заметить, что одна ячейка имеет помимо тега v еще тег f. Это тег с формулой, в данном случае формула означает: сумма ячеек от A1 до E1. А в теге v записан уже посчитанный ответ. Делать это не обязательно, но если не записать — то при открытии документа excel предложит сохранить изменения, т.к. он сам автоматически посчитал и записал этот результат.

С тегом sheetData разобрались, идем дальше.

Про теги mergeCells и autoFilter снова обратимся к статье от @Lachrimae:

Тег .

Как мы знаем, в Excel есть возможность объединения ячеек. Все объединенные ячейки на листе перечислены здесь. В заполненном виде тег выглядит примерно так:

Как видно, одна объединенная ячейка обозначена одним тегом с единственным атрибутом ref, задающим диапазон объединения.

Тег . Фильтры, которые так любят видеть в отчетах наши пользователи. В заполненном виде тег выглядит так:

Нетрудно понять, что атрибут ref задает зону, занимаемую активными ячейками фильтров.

Тег printOptions — параметры печати. Атрибут headings — означает, что будут печататься заголовки, а атрибут gridLines — что будут печататься линии сетки.

Тег pageMargins задает поля сверху, снизу, справа, слева, у заголовков и у подвала для печатаемой страницы.

Тег pageSetup предпочтительные настройки бумаги, опять же, для печати.

Атрибут paperSize — устанавливает размер бумаги.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *