Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Распаковка zip архива 
V
    Опции темы
dexterov
Дата 12.12.2015, 00:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 5.11.2015

Репутация: нет
Всего: нет



Здравствуйте.

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

В начале файла прописываю:
Код

#using "System.dll"
#using "WindowsBase.dll"
#using "System.xml.dll"

    using namespace System::IO;
    using namespace System::Text;
    using namespace System::Xml;
    using namespace System::Xml::XPath;
    using namespace System::IO::Packaging;


И сам код:
Код

            Package ^pkg = Package::Open(file.xlsx, FileMode::Open, FileAccess::Read);
            PackagePartCollection ^packagePartCol = pkg->GetParts();
            PackageRelationshipCollection ^packageRelCol = pkg->GetRelationships();
 
            pkg->Close();
            delete pkg;


Коллекцию частей и отношений я благополучно получаю, компилируется без проблем, а вот как получить доступ к конкретной части - не понимаю.
Как мне открыть, например, как текстовый файл xl\workbook.xml?
PM   Вверх
dexterov
Дата 14.12.2015, 20:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 5.11.2015

Репутация: нет
Всего: нет



Удалось разобраться как читать файлы xlsx, распаковывая их и считывая текстовые данные. Код приведу тут, наверняка пригодится. В моем примере меня интересовали лишь текстовые строки из ячеек и числа, так что все остальные типы данных ячеек (дата, булев тип, формула) просто игнорируются. И все данные запихиваются в массив строк. Для парсинга строк использовались регулярные выражения (using namespace System::Text::RegularExpressions).

Код

#using "System.dll"
#using "WindowsBase.dll"
#using "System.xml.dll"
 
    using namespace System::Text;
    using namespace System::Text::RegularExpressions;
    using namespace System::Xml;
    using namespace System::Xml::XPath;
    using namespace System::IO::Packaging;


Код

            Package ^pkg = Package::Open(xlsx_file_name, FileMode::Open, FileAccess::Read); //  распаковываем архив
            PackagePartCollection ^packagePartCol = pkg->GetParts();                    //  получаем ссылки на все части архива
            array<String ^> ^sharedstrings = gcnew array<String ^>(1000);               //  массив для хранения набора текстовых строк из файла /xl/sharedStrings.xml
            array<String ^> ^sheets = gcnew array<String ^>(5) {"/xl/worksheets/sheet1.xml", 
                "/xl/worksheets/sheet2.xml", "/xl/worksheets/sheet3.xml", 
                "/xl/worksheets/sheet4.xml", "/xl/worksheets/sheet5.xml"};                                 // обрабатываем 5 вкладок файла xlsx
            array <System::String ^, 3> ^xls_data = gcnew array <System::String ^, 3>(5, 30, 50);  //     сохраняем содержимое xlsx файла в 3-мерный массив
                        for each (PackagePart ^pp in packagePartCol)                                //  ищем среди распакованных файлов нужный (со строками)
                if (pp->Uri->OriginalString == L"/xl/sharedStrings.xml")
                {
                    Stream ^fs = pp->GetStream();
                    array<Byte> ^by = gcnew array<Byte>(fs->Length);
                    fs->Read(by, 0, fs->Length);
                    String ^str_by = UTF8Encoding::UTF8->GetString(by);
                    int i = 0;
                    Regex ^reg = gcnew Regex("<t.*?>(?<capture>.*?)</t>");
                    for (Match ^m = reg->Match(str_by); m->Success; m = m->NextMatch())
                    {
                        sharedstrings[i] = m->Groups["capture"]->Value;
                        ++i;
                    }
                    delete(IDisposable ^) fs;
                }
            for (int sh = 0; sh<5; ++sh)                                                             //  перебор по пяти вкладкам
                for each (PackagePart ^pp in packagePartCol)
                    if (pp->Uri->OriginalString == sheets[sh])
                    {
                        Stream ^fs = pp->GetStream();
                        array<Byte> ^by = gcnew array<Byte>(fs->Length);
                        fs->Read(by, 0, fs->Length);
                        String ^str_by = UTF8Encoding::UTF8->GetString(by);
                        Regex ^reg = gcnew Regex("<row.+?r="(?<row>[0-9]+?)".*?>(?<cells>.*?)</row>");
                        for (Match ^m = reg->Match(str_by); m->Success && Int32::Parse(m->Groups["row"]->Value)<30; m = m->NextMatch())                                      //   находим строки
                        {
                            int row = Int32::Parse(m->Groups["row"]->Value);
                            int col = 0;
                            String ^cells = m->Groups["cells"]->Value;
                            String ^cell_pattern =  "<c.+?r="(?<index>[A-Z]+?[0-9]+?)".*?";     //  ищем индекс ячейки |<c r="D3" ...|
                            cell_pattern +=         "(((t="(?<type>[a-zA-z]+?)")?>";                //  ищем тип ячейки, если он есть  |t="s">| (см. Open Xml Standart, часть 1, глава 18.18.11)
                            cell_pattern +=         "((<v.*?>(?<digit>[0-9]+?)</v>)|";              //  ищем номер значения из sharedstrings, если оно есть |<v>30</v>| или
                            cell_pattern +=         "(<is.*?><t.*?>(?<inlinestr>.*?)</t></is>))";   //  или считываем его отсюда |<is><t>inline_string</t></is>|
                            cell_pattern +=         "</c>)|(/>))";                                  //  проверяем, а было ли что-то в ячейке <c ...>...</c> или она пустая <c .../>
                            Regex ^reg_c = gcnew Regex(cell_pattern);
                            for (Match ^mm = reg_c->Match(cells); mm->Success && col<50; mm = mm->NextMatch())                                     //      обрабатываем все ячейки из строки
                            {
                                String ^cell_index = mm->Groups["index"]->Value;
                                if (mm->Groups["type"]->Value == "s")
                                    xls_data[sh, row-1, col] = sharedstrings[Int32::Parse(mm->Groups["digit"]->Value)];                    //     записываем значение в 3-мерный массив строк: sh - номер вкладки, row - номер строки, col - номер столбца
                                else if (mm->Groups["type"]->Value == "b")
                                    xls_data[sh, row-1, col] = "Boolean type of cell in XLSX file";
                                else if (mm->Groups["type"]->Value == "d")
                                    xls_data[sh, row-1, col] = "Date format of cell";
                                else if (mm->Groups["type"]->Value == "e")
                                    xls_data[sh, row-1, col] = "Error cell in XLSX file";
                                else if (mm->Groups["type"]->Value == "n")
                                    xls_data[sh, row-1, col] = mm->Groups["digit"]->Value;
                                else if (mm->Groups["type"]->Value == "str")
                                    xls_data[sh, row-1, col] = "Cell contain formula string";
                                else if (mm->Groups["type"]->Value == "inlineStr")
                                    xls_data[sh, row-1, col] = mm->Groups["inlinestr"]->Value;
                                else if (mm->Groups["type"]->Value == "" && mm->Groups["digit"]->Value != "")
                                    xls_data[sh, row-1, col] = mm->Groups["digit"]->Value;
                                else xls_data[sh, row-1, col] = "Undefined value (out of table)";
                                ++col;
                            }
                        }
                    delete(IDisposable ^) fs;
                    }
            pkg->Close();
            delete pkg;

PM   Вверх
Romikgy
Дата 14.12.2015, 20:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 1
Всего: 146



.... это так вопрос в воздух .... вы уверены , что код написан на С++ ?


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
dexterov
Дата 14.12.2015, 21:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 5.11.2015

Репутация: нет
Всего: нет



Проект создавался как С++/CLI Windows Forms и компилируется с ключом /clr:pure.
Это, конечно, не чистый С++, а managed-код под .NET.
PM   Вверх
xvr
Дата 15.12.2015, 15:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



А какие идеологические препятствия были что бы просто взять соотвествующий SDK для чтения xlsx файлов, благо что MS изготовило его исключительно в .NET виде и абсолютно задаром раздает всем желающим ?

PM MAIL   Вверх
dexterov
Дата 16.12.2015, 01:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 5.11.2015

Репутация: нет
Всего: нет



Я попытался взять SDK, но что-то компилятор ругался на подключаемые using namespace, все примеры исключительно на шарпе, а я искал на C++, поэтому решил, что проще использовать Package для распаковки, а дальше руками, тем более, что формат не сложный.

Это сообщение отредактировал(а) dexterov - 16.12.2015, 01:36
PM   Вверх
xvr
Дата 16.12.2015, 14:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Цитата(dexterov @  16.12.2015,  01:32 Найти цитируемый пост)
все примеры исключительно на шарпе, а я искал на C++,

Под .NET и C++ и C# отлично уживаются в одной программе.


PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

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


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0972 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.