• Microsoft .NET
  • C#.NET
  • Основы, лучшие методы и соглашения реализации событий в C#

Формат файла .bin Office 2007 - Часть соединений

ОГЛАВЛЕНИЕ

Часть соединений

Часть соединений является строкой соединения с источником данных. В отличие от того, как части таблицы запроса связываются с частями таблицы, части соединений не связываются с частями таблицы запроса посредством отношений (нет файла querytablexxx.bin.rels). Зато у части таблицы запроса есть атрибут идентификатора соединения в элементе <queryTable> (запись BIFF12_QUERYTABLE). Файлы части соединений предоставляются на уровне книги, т.е. совместно используются по всему листу и связанным объектам, и поэтому части соединений связываются с отношениями книги (workbook.bin.rels). Часть соединений выглядит так:

<connections>
ad 03 (00)

<connection id="1"
               sourceFile="C:\Database1.mdb"
               keepAlive="1"
               name="Database1"
               type="5"
               refreshedVersion="3"
               background="1"
               saveData="1">
c9 01 (51) 03 00 02 00 00 00 51 00 09 00 05 00 00 00 01 00 00 00
01 00 00 00 00 10 00 00 00 43 00
3a 00 5c 00 44 00 61 00 74 00 61 00 62 00 61 00 73 00 65 00 31 00
2e 00 6d 00 64 00 62 00 09 00 00
00 44 00 61 00 74 00 61 00 62 00 61 00 73 00 65 00 31 00

<dbPr connection=Provider=Microsoft.ACE.OLEDB.12.0;
User ID=Admin;Data Source=C:\Database1.mdb;
Mode=Share Deny Write;Extended Properties="";
Jet OLEDB:System database="";Jet OLEDB:Registry Path="";
Jet OLEDB:Engine Type=5;Jet OLEDB:Database Locking Mode=0;
Jet OLEDB:Global Partial Bulk Ops=2;
Jet OLEDB:Global Bulk Transactions=1;
Jet OLEDB:New Database Password="";Jet OLEDB:Create System
Database=False;Jet OLEDB:Encrypt Database=False;
Jet OLEDB:Don't Copy Locale on Compact=False;
Jet OLEDB:Compact Without Replica Repair=False;
Jet OLEDB:SFP=False;Jet OLEDB:
Support Complex Data=False" command="Table1" commandType="3">
cb 01 (81 09) 03 00 00 00 02 34 02 00 00 50 00 72 00 6f 00 76 00
69 00 64 00 65 00 72 00 3d 00 4d 00
69 00 63 00 72 00 6f 00 73 00 6f 00 66 00 74 00 2e 00 41 00 43 00
45 00 2e 00 4f 00 4c 00 45 00 44 00
42 00 2e 00 31 00 32 00 2e 00 30 00 3b 00 55 00 73 00 65 00 72 00
20 00 49 00 44 00 3d 00 41 00 64 00
6d 00 69 00 6e 00 3b 00 44 00 61 00 74 00 61 00 20 00 53 00 6f 00
75 00 72 00 63 00 65 00 3d 00 43 00
3a 00 5c 00 44 00 61 00 74 00 61 00 62 00 61 00 73 00 65 00 31 00
2e 00 6d 00 64 00 62 00 3b 00 4d 00
6f 00 64 00 65 00 3d 00 53 00 68 00 61 00 72 00 65 00 20 00 44 00
65 00 6e 00 79 00 20 00 57 00 72 00
69 00 74 00 65 00 3b 00 45 00 78 00 74 00 65 00 6e 00 64 00 65 00
64 00 20 00 50 00 72 00 6f 00 70 00
65 00 72 00 74 00 69 00 65 00 73 00 3d 00 22 00 22 00 3b 00 4a 00
65 00 74 00 20 00 4f 00 4c 00 45 00
44 00 42 00 3a 00 53 00 79 00 73 00 74 00 65 00 6d 00 20 00 64 00
61 00 74 00 61 00 62 00 61 00 73 00
65 00 3d 00 22 00 22 00 3b 00 4a 00 65 00 74 00 20 00 4f 00 4c 00
45 00 44 00 42 00 3a 00 52 00 65 00
67 00 69 00 73 00 74 00 72 00 79 00 20 00 50 00 61 00 74 00 68 00
3d 00 22 00 22 00 3b 00 4a 00 65 00
74 00 20 00 4f 00 4c 00 45 00 44 00 42 00 3a 00 45 00 6e 00 67 00
69 00 6e 00 65 00 20 00 54 00 79 00
70 00 65 00 3d 00 35 00 3b 00 4a 00 65 00 74 00 20 00 4f 00 4c 00
45 00 44 00 42 00 3a 00 44 00 61 00
74 00 61 00 62 00 61 00 73 00 65 00 20 00 4c 00 6f 00 63 00 6b 00
69 00 6e 00 67 00 20 00 4d 00 6f 00
64 00 65 00 3d 00 30 00 3b 00 4a 00 65 00 74 00 20 00 4f 00 4c 00
45 00 44 00 42 00 3a 00 47 00 6c 00
6f 00 62 00 61 00 6c 00 20 00 50 00 61 00 72 00 74 00 69 00 61 00
6c 00 20 00 42 00 75 00 6c 00 6b 00
20 00 4f 00 70 00 73 00 3d 00 32 00 3b 00 4a 00 65 00 74 00 20 00
4f 00 4c 00 45 00 44 00 42 00 3a 00
47 00 6c 00 6f 00 62 00 61 00 6c 00 20 00 42 00 75 00 6c 00 6b 00
20 00 54 00 72 00 61 00 6e 00 73 00
61 00 63 00 74 00 69 00 6f 00 6e 00 73 00 3d 00 31 00 3b 00 4a 00
65 00 74 00 20 00 4f 00 4c 00 45 00
44 00 42 00 3a 00 4e 00 65 00 77 00 20 00 44 00 61 00 74 00 61 00
62 00 61 00 73 00 65 00 20 00 50 00
61 00 73 00 73 00 77 00 6f 00 72 00 64 00 3d 00 22 00 22 00 3b 00
4a 00 65 00 74 00 20 00 4f 00 4c 00
45 00 44 00 42 00 3a 00 43 00 72 00 65 00 61 00 74 00 65 00 20 00
53 00 79 00 73 00 74 00 65 00 6d 00
20 00 44 00 61 00 74 00 61 00 62 00 61 00 73 00 65 00 3d 00 46 00
61 00 6c 00 73 00 65 00 3b 00 4a 00
65 00 74 00 20 00 4f 00 4c 00 45 00 44 00 42 00 3a 00 45 00 6e 00
63 00 72 00 79 00 70 00 74 00 20 00
44 00 61 00 74 00 61 00 62 00 61 00 73 00 65 00 3d 00 46 00 61 00
6c 00 73 00 65 00 3b 00 4a 00 65 00
74 00 20 00 4f 00 4c 00 45 00 44 00 42 00 3a 00 44 00 6f 00 6e 00
27 00 74 00 20 00 43 00 6f 00 70 00
79 00 20 00 4c 00 6f 00 63 00 61 00 6c 00 65 00 20 00 6f 00 6e 00
20 00 43 00 6f 00 6d 00 70 00 61 00
63 00 74 00 3d 00 46 00 61 00 6c 00 73 00 65 00 3b 00 4a 00 65 00
74 00 20 00 4f 00 4c 00 45 00 44 00
42 00 3a 00 43 00 6f 00 6d 00 70 00 61 00 63 00 74 00 20 00 57 00
69 00 74 00 68 00 6f 00 75 00 74 00
20 00 52 00 65 00 70 00 6c 00 69 00 63 00 61 00 20 00 52 00 65 00
70 00 61 00 69 00 72 00 3d 00 46 00
61 00 6c 00 73 00 65 00 3b 00 4a 00 65 00 74 00 20 00 4f 00 4c 00
45 00 44 00 42 00 3a 00 53 00 46 00
50 00 3d 00 46 00 61 00 6c 00 73 00 65 00 3b 00 4a 00 65 00 74 00
20 00 4f 00 4c 00 45 00 44 00 42 00
3a 00 53 00 75 00 70 00 70 00 6f 00 72 00 74 00 20 00 43 00 6f 00
6d 00 70 00 6c 00 65 00 78 00 20 00
44 00 61 00 74 00 61 00 3d 00 46 00 61 00 6c 00 73 00 65 00 06 00
00 00 54 00 61 00 62 00 6c 00 65 00
31 00

</dbPr>
cc 01 (00)

</connection>
ca 01 (00)

</connections>
ae 03 (00)

Задействуются следующие записи:

//записи соединения
public const int BIFF12_CONNECTIONS           = 0x03AD;
public const int BIFF12_CONNECTIONS_END       = 0x03AE;
public const int BIFF12_CONNECTION            = 0x01C9;
public const int BIFF12_CONNECTION_END        = 0x01CA;
public const int BIFF12_DBPR                  = 0x01CB;
public const int BIFF12_DBPR_END              = 0x01CC;

Часть сводной таблицы

О части сводной таблицы известно следующее:
•    В отличие от других объектов, применяемых к ячейкам, типа таблиц, сводные таблицы не объявляются и не упоминаются в части листа, где они видимы! И это одинаково независимо от того, хранятся сводные таблицы в XML или в BIN.
•    Несмотря на это, файл отношений части листа (_rels/sheetxxx.bin.rels) фактически определяет связь с одной или несколькими сводными таблицами при любой возможности (части сводных таблиц хранятся в отдельной, родительской, папке).
•    Часть сводной таблицы (pivotTables/pivotTablexxx.bin) определяет ее макет и сводные поля, но не фактический источник данных.
•    Как лист, часть сводной таблицы не связывается явно с частью определения сводного кэша (где определяется источник данных), хотя она хранит ссылку в связанном файле отношений (_rels/pivotTablexxx.bin.rels)
•    Часть определения сводного кэша (pivotCache/pivotCacheDefinitionxxx.bin) определяет фактический источник данных сводной таблицы, как в:

// была создана сводная таблица, чьим источником данных является
// содержимое объекта Table1
  <cacheSource type="worksheet">
    <worksheetSource name="Table1" r:id="rId2"/>
  </cacheSource>

Часть настроек принтера

Часть настроек принтера является двоичным дампом структуры WIN32 DEVMODE (подробней смотрите в MSDN). Эта информация хранилась в более ранних версиях Excel (97 и выше) как запись BIFF8 [PLS].

Части индекса и цепи расчета

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

Замечание о защищенных паролем документах

Хотя это строго не связано с форматами файла BIN, если защитить паролем книги Excel 2007, то конечный файл, будь то .XLSX или нет, будет зашифрован с помощью RC4 в контейнере OLE. Весь файл зашифрован в потоке EncryptedPackage. Ниже показан снимок экрана с защищенной паролем книгой, просматриваемой в просмотрщике документа OLE:

 

Защищенная паролем книга Excel 2007 зашифрована в контейнере OLE

Разумеется, не ожидается, что защищенные паролем книги будут использоваться программно.
В каком порядке должны читаться части?
•    Книга
•    Общие строки
•    Стили
•    Лист(ы)
•    Необязательные таблицы, рисунки, ...

Как получить значение ячейки?

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

Объекты, такие как гиперссылки, таблицы, диаграмма, именованные диапазоны, сводные таблицы, определены поверх этих ячеек и определены в другом месте, после блока BIFF12_SHEETDATA соответствующей части листа, или в других частях (именованные диапазоны определяются в части книги, поэтому они совместно ипсользуются сквозь все листы, внтуренние и внешние).

Как получить стиль ячейки?

Как сказано ранее, ячейка хранит данные стиля форматирования. Отдельные ячейки хранят стиль форматирования, индекс с отсчетом от нуля в таблице стилей. Вообще, те стили являются стилями отдельной ячейки и ссылаются на коллекцию <cellXfs> индивидуальных стилей <xf>. В свою очередь, каждый <xf> имеет индекс к следующим коллекциям: форматы числа, рамки, шрифты, выравнивание и узор заливки.

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

Последние слова

Считыватель BIFF12, представленный в данной статье, является незавершенной работой над форматом файла .bin Office 2007, который содержит нижележащих форматов файла. Код, представленный на C++ и на C#, является основой библиотеки чтения/записи/манипулирования благодаря тому, что обработчики записи полностью отвечают за чтение/запись/манипулирование соответствующими записями (оттого есть так много классов).

Чтобы превратить существующий исходный код в настоящую библиотеку манипулирования, надо создать экзепмляры отдельных записей. Например, вместо того чтобы делать на C# следующее:

// извлечь связанный обработчик записи для идентификатора записи
// (h – хэш-таблица)
BaseRecord recHandler = (BaseRecord) h[recid];

Надо сделать так:

// создать экземпляр обработчика записи на базе идентификатора записи
// (h – хэш-таблица)
BaseRecord rec = (BaseRecord) Activator.CreateInstance(h[recid].GetType());

И, конечно, реализовать метод Write() для каждого обработчика записи.

Целью было разобрать наименее документированные форматы файла .bin внутри файлов ZIP и придумать способ чтения значений в ячейках произвольной книги Excel 2007 независимо от формата файла.