Начиная с 10-ой версии Flash Player можно собирать Excel-документы без участия сервера.
Немного теории.
В качестве Excel-документов я рассматриваю документы созданные в Microsoft Excel 2007 с расширением .xlsx. Именно с этой версии Microsoft открыла свой формат электронных таблиц. И теперь - это не файл с бинарными записями, а .zip-архив с набором .xml-документов.
Таким образом для создания .xlsx-документов нам необходимо записать данные в .xml-документы, затем собрать их в .zip-архив и в завершении заменить его расширение на ".xlsx".
Что мы имеем во Flash Player?
- Полноценная работа с xml-разметкой (пакет классов flash.xml). Мы можем с легкостью записывать наши данные в .xml-документы.
- Работа с бинарными данными (класс flash.utils.ByteArray), с помощью которой можно организовать сборку zip-архива.
- Сохранение бинарных данных на компьютер пользователя (класс flash.net.FileReference).
Всё что нам необходимо, мы имеем. Поэтому перейдем к практике.
Запись данных в XML
Первым делом нужно разобраться с содержимом .xlsx-документа, а именно с .xml-документами. Для этого я в Microsoft Excel 2007 создал новый документ, сделал некоторые записи,
сохранил, поменял расширение на .zip и увидел такую вот структуру с каталогами и файлами.
Свои записи (Ivan, Ivanov, Ivanovich) я нашел в файле xl/sharedString.xml. Насколько я понял, это хранилище для текстовой информации.
<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="3" uniqueCount="3"> <si><t>Ivanov<t><si> <si><t>Ivan<t><si> <si><t>Ivanovich<t><si> <sst>Далее я открыл файл xl/worksheets/sheet1.xml и действительно в описание столбца увидел ссылку (а точнее индекс) на содержимое из xl/sharedString.xml.
... <row r="1" spans="1:3"> <c r="A1" t="s"><v>0<v><c> <row> ...Для начала этой информации нам достаточно.
Рассматривать подробно все возможности записи .xml-документов внутри .xlsx-файлов я не буду. Ознакомится с ними можно прочитав книгу "OpenXML. Кратко и доступно", автором которой является Воутер Ван Вугт.
Скажу только то, что благодаря такой открытой структуре .xlsx-документа, вы сможете с легкостью записывать не только текстовую информацию, но и изображения, диаграммы и все остальные объекты Microsoft Excel.
Сборка XML-документов в ZIP-архив
Теперь когда с записью в .xml-документы разобрались давайте попробуем их собрать в архив. Писать архиватор мы не будем, используем готовый. Меньше всего проблем у меня возникло с библиотекой FZip, так что используем её.
... var zip:FZip = new FZip(); zip.addFile("_rels/.rels", Templates._RELS); zip.addFile("docProps/app.xml", Templates.APP_XML); zip.addFile("docProps/core.xml", Templates.CORE_XML); zip.addFile("xl/_rels/workbook.xml.rels", Templates.WORKBOOK_XML_RELS); zip.addFile("xl/theme/theme1.xml", Templates.THEME1); zip.addFile("xl/worksheets/_rels/sheet1.xml.rels", Templates.SHEET1_XML_RELS); zip.addFile("xl/worksheets/sheet1.xml", Templates.SHEET1_XML); zip.addFile("xl/sharedStrings.xml", Templates.SHARED_STRING_XML); zip.addFile("xl/styles.xml", Templates.STYLES_XML); zip.addFile("xl/workbook.xml", Templates.WORKBOOK_XML); zip.addFile("[content_types].xml", Templates.CONTENT_TYPES_XML); // var brr:ByteArray = new ByteArray(); zip.serialize(brr, true); ...
Сохранение на компьютер пользователя
Сохранить, собранный архив на локальный диск пользователя, можно при помощи класса flash.net.FileReference. Начиная с 10 версии FlashPlayer'a у этого класса появился метод save, который перед сохранением показывает диалоговое окно с выбор место сохранения. Вызываем его и в первом параметре пишем имя сохраняемого файла по умолчанию с расширением "xlsx".
... var file:FileReference = new FileReference(); file.save("excel_file.xlsx", brr); ...
Пример
спасибо. Пригодится как-нибудь.
ОтветитьУдалитьподскажите, как правильно подключить библиотеку FZip?
ОтветитьУдалитьхочу сказать спасибо за хорошее описание. очень пригодилось!
ОтветитьУдалитьФарид,
ОтветитьУдалитьисправьте пожалуйста свой пример.
1. Порядок файлов в архиве важен (Google Spreadsheets отказывается открывать файл).
2. [Content_Types].xml надо писать учитывая регистр (проблема с Open Office)
...
var zip:FZip = new FZip();
zip.addFileFromString("[Content_Types].xml", Templates.CONTENT_TYPES_XML);
zip.addFileFromString("_rels/.rels", Templates._RELS);
zip.addFileFromString("xl/_rels/workbook.xml.rels", Templates.WORKBOOK_XML_RELS);
zip.addFileFromString("xl/workbook.xml", Templates.WORKBOOK_XML);
zip.addFileFromString("xl/theme/theme1.xml", Templates.THEME1);
zip.addFileFromString("xl/worksheets/_rels/sheet1.xml.rels", Templates.SHEET1_XML_RELS);
zip.addFileFromString("xl/worksheets/sheet1.xml", Templates.SHEET1_XML);
zip.addFileFromString("xl/sharedStrings.xml", Templates.SHARED_STRING_XML);
zip.addFileFromString("xl/styles.xml", Templates.STYLES_XML);
zip.addFileFromString("docProps/app.xml", Templates.APP_XML);
zip.addFileFromString("docProps/core.xml", Templates.CORE_XML);
//
var brr:ByteArray = new ByteArray();
zip.serialize(brr, true);
...
Спасибо за поправки :)
ОтветитьУдалитьПриколно придумал фарид тебе респект!
ОтветитьУдалитьНо нельзя было расписать что класс fzip взять от сюда (https://github.com/claus/fzip/). Хорошо ya под рукой.
А так же можно попросить без опечаток:
file.save("excel_file.xlsx", brr);
В этом методе первый параметр это сами данные, а второй это название файла. 10 минут потратил пока в мануал не залез.
Но а так респектный пост написал.
А не то я все постаринке через веб сервер и php создавал excel. Молодец. Юрик Пермь
Библиотека FZip не учитывает возможность использования русских букв. As3coder, не подскажешь ли как это можно исправить?
ОтветитьУдалитьА подробнее? Где именно у вас не получается использовать русские символы? В Excel-документе, про который говорится в посте? Или в имени файла внутри архива, который можно получить с помощь библиотеки FZip?
ОтветитьУдалитьВ самом xlsx файле который получается после сборки zip-архива вместо русских букв что-то типа "Иванов". Это если в исходном xl/sharedStrings.xml были русские буквы.
ОтветитьУдалитьНе нашёл как это исправить..
А в примере, который имеется в посте, тоже наблюдается проблема с русскими символами?
ОтветитьУдалитьесли русские символы писать в текстовые поля, то на выходе также абракадабра
ОтветитьУдалить..когда я скачиваю твой пример там названия листов: "Лист1", "Лист2",.. на русском; у меня же при сборке и там странные символы
?
Во-первых, шаблоны (.xml-файлы из .xlsx-архива), которые вы используете должны быть в кодировке UTF-8. Возможно, это указывается еще каким-то тегом. Нужно разбираться. Во-вторых, .as-файлы вашего проекта тоже должны быть в UTF-8.
ОтветитьУдалитьи так везде UTF-8.. ну что ж, спасибо, буду искать..
ОтветитьУдалитьВообще пост полезный, идея хорошая
А не подскажете ли в чем проблема? У меня формируется отчет по лабораторной работе и помимо текстовых данных нужно вставить график, график строиться непосредственно во флеше, через JPGEncoder я его перегоняю в ByteArray и кидаю в папку ./xl/media, создаю ./xl/drawings/drawings1.xml(координаты взял с дубликата созданного в самом Excel), рельсы, но когда открываю отчет изображения нет, никаких ошибок тоже, смотрю содержимое xlsx - график лежит там где и нужно, что не так ума не приложу, если бы были кривые файлы, то при открытии предлагало бы восстановить файл, но как уже и писал, никаких ошибок =\
ОтветитьУдалитьЕсли нужно выгрузить в Excel ряды данных (числа) я использую CSV формат и всего две строчки кода.
ОтветитьУдалитьНапример, так:
var file:FileReference = new FileReference();
file.save("1;2;4;5\n"+"4;5;6;" + String(2), "excel_file.csv");
В результате при открытии файла excel_file.csv в Excel мы видим таблицу состоящую из 2-строк и 4- х столбцов.