HotXLS пише строги (Strict) Open XML работни книги по ISO/IEC 29500 от Delphi и C++Builder чрез задаване на едно единствено свойство, StrictOOXML, преди записване. Всяка част от пакета, от xl/workbook.xml надолу до файловете за връзки и типовете съдържание, се записва със строгите речници purl.oclc.org, вместо преходните (transitional) schemas.openxmlformats.org, а функции, които Strict не позволява, се отхвърлят с изрично изключение, вместо да бъдат записани въпреки всичко
Повечето разработчици се сблъскват с това изискване чрез документ за обществена поръчка. Търгове в публичния сектор в няколко юрисдикции изискват стандартизираната от ISO форма на Open XML, а не преходната форма, която Office записва по подразбиране, а архив, който налага ISO 29500 Strict, ще отхвърли обикновен .xlsx, дори когато Excel го отваря напълно нормално. Преходните именни пространства съществуват, за да поддържат наследено бинарно поведение; строгите са самият стандарт
Каква всъщност е разликата между Strict и Transitional?
Видимата разлика е в речника. Строга част от работна книга декларира http://purl.oclc.org/ooxml/spreadsheetml/main като своя коренно именно пространство и http://purl.oclc.org/ooxml/officeDocument/relationships за препратки към връзки, и никое преходно именно пространство не може да оцелее никъде в пакета. Типовете на връзките се променят заедно с това, така че коренната част за връзки назовава .../ooxml/officeDocument/relationships/officeDocument, а не познатия еквивалент от openxmlformats, а типът за разширени свойства е camelCase, като extendedProperties
Невидимата разлика е в обхвата. Strict съзнателно пропуска части от преходната схема, които са съществували само за да позволят обратна съвместимост с наследени бинарни файлове, заедно с разширенията на доставчика, добавени от Office впоследствие. Затова преобразуването не е търсене и замяна на низове: някои функции просто нямат строг запис и изобщо не трябва да бъдат записвани
Включване на режима
Обичайният код за създаване не се променя. Изградете работната книга по обичайния начин, задайте флага и запишете:
var
Wb: TXLSXWorkbook;
Sh: TXLSXWorksheet;
begin
Wb := TXLSXWorkbook.Create;
try
Sh := Wb.Sheets.Add('Data');
Sh.Cells[1, 1].Value := 'Product';
Sh.Cells[1, 2].Value := 'Amount';
Sh.Cells[2, 1].Value := 'Widget';
Sh.Cells[2, 2].Value := 17;
Sh.Cells[3, 2].Formula := '=SUM(B2:B2)';
Wb.StrictOOXML := True; // ISO/IEC 29500 Strict изход
if Wb.SaveAs('archive-copy.xlsx') <> 1 then
raise Exception.Create('strict save failed');
finally
Wb.Free;
end;
end;
Флагът се нулира в началото на всяка операция по записване и се преприсвоява от свойството на работната книга, така че изключение при едно записване не може да просмуче строгия режим в следващото. Тази подробност има значение в сървърни процеси, където един обект на работна книга обслужва няколко заявки за експорт
Защо строг запис може да откаже да се изпълни?
Четири семейства функции са разширения на Microsoft без еквивалент в ISO 29500 Strict, а HotXLS повдига изключение при записване, вместо да изведе пакет, който твърди строго съответствие, а не е такъв:
// Строгият изход не може да вгради VBA проект
// -> запишете работни книги с макроси като преходни .xlsm
// Строгият изход не може да носи формулярни контроли
// -> бутони, отметки, комбинирани списъци и техните ctrlProps
// Строгият изход не може да носи нишкови коментари
// -> съвременния модел с лица/нишки, не класическите бележки
// Строгият изход не може да носи метаданни за динамични масиви
// -> обхвати на разливане, записани чрез частта с метаданни
Шумният отказ е правилният компромис тук. Тихо изпуснат VBA проект превръща работеща работна книга в счупена, която все още се отваря, а докладът за грешката пристига от потребител седмици по-късно. Изключение назовава функцията и свойството, което трябва да се промени, докато извикващият код все още знае какво е експортирал. Запазването на макроси и външни връзки по преходния път е разгледано в запазване на VBA проекти и външни връзки
Две семейства разширения се обработват по различен начин, и си струва да се знае защо. Data bars, спарклайни и подобни функции живеят в речниците x14 и xm, а SVG вариантите на изображенията живеят в c15. Това е съдържание от списък с разширения, чиито именни пространства са самоописващи се, общите анализатори за електронни таблици ги толерират, и няма ISO еквивалент, в който да се превърнат. HotXLS ги запазва, вместо да изхвърля потребителско съдържание. Ако валидатор във вашия конвейер е строг и по отношение на разширенията, а не само на именните пространства, премахнете тези функции от изходната работна книга преди експорт
Преводът трябва да достигне части, които обикновено никой не пренаписва
Интересният инженерен проблем при строгия изход не е XML на работния лист. Това са частите, които бърз писач би предпочел да копира дословно. HotXLS запазва теми, връзки, външни връзки, диаграми и pivot blob-ове, като копира оригиналните им компресирани байтове директно, което е точно правилното нещо за вярност и точно грешното за строг изход, защото копираните байтове носят преходни именни пространства
При StrictOOXML тези пет запазени пътя преминават към преизграждане или към превеждащо възпроизвеждане, заобикаляйки бързия път с копиране на байтове. Целият XML преминава през една рутина за превод, която се закотвя на стойности на атрибути в двойни кавички, така че низ, изглеждащ като URI вътре в клетка, никога не може да бъде пренаписан по случайност. Текст на клетка, съдържащ същия URI, е екраниран като обект (entity) в XML, така че закотвената замяна не може да го види. Стрийминг писачът превежда своя скелет първо и след това разделя на sheetData, тъй като блоковете с редове изобщо не съдържат URI на речник. Свързаната механика за пътя на запазване е разгледана в безстратни обратни преобразувания на теми, списъци с разширения и calcChain
Четене на файлове, записани от Excel като строги
Изходът е само половината от историята. Excel предлага "Strict Open XML Spreadsheet" като опция за запис, и файлове, произведени по този начин, трябва да се отварят правилно. HotXLS нормализира типовете връзки на всяко място за анализиране на връзки в пакета — корена, външните връзки, работните листове, чертежите и pivot таблиците — така че строг тип връзка съвпада със същата вътрешна константа като преходния му еквивалент
Съответствието на страната на четенето е нормализация на префиксите на именни пространства, която позволява произволни префикси и двата речника да се разрешават до една канонична таблица с имена. Тази работа е от полза както за обикновените файлове, така и за строгите, тъй като генератори на трети страни свързват префикси свободно, а това е същата механика, описана в разрешаване на OPC връзки в XLSX пакети
Кратък списък за проверка преди издаване на строг изход
Проверявайте пакета, не Excel. Excel отваря и двете форми без проблем, така че успешно отваряне не доказва нищо за съответствие. Разархивирайте резултата и потвърдете, че xl/workbook.xml декларира purl именното пространство, че никоя част не съдържа schemas.openxmlformats.org/spreadsheetml, и че типовете връзки в _rels/.rels и xl/_rels/workbook.xml.rels използват строгите форми
После отворете отново файла чрез HotXLS и сравнете стойности, формули, формати и хипервръзки спрямо източника. Тест с обратно четене е единственият евтин начин да се докаже, че преводът не е повредил съдържанието, и той едновременно упражнява нормализацията на страната на четене. Ако вашите работни книги носят диаграми, проверете и тях, тъй като частта с диаграмата е една от запазените части, която преминава към преизграден път в строг режим
Строгият изход, толерантното четене и безстратното запазване са част от един и същ OOXML двигател за Delphi и C++Builder; пълният списък с функции е на страницата на HotXLS Delphi компонента за електронни таблици