Parse xlsx with php

searbe / parse_xlsx.php

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

/**
* I had to parse an XLSX spreadsheet (which should damn well have been a CSV!)
* but the usual tools were hitting the memory limit pretty quick. I found that
* manually parsing the XML worked pretty well. Note that this, most likely,
* won’t work if cells contain anything more than text or a number (so formulas,
* graphs, etc . I don’t know what’d happen).
*/
$ inputFile = ‘/path/to/spreadsheet.xlsx’ ;
$ dir = ‘/path/to/tmp/dir’ ;
// Unzip
$ zip = new ZipArchive ();
$ zip -> open ( $ inputFile );
$ zip -> extractTo ( $ dir );
// Open up shared strings & the first worksheet
$ strings = simplexml_load_file( $ dir . ‘/xl/sharedStrings.xml’ );
$ sheet = simplexml_load_file( $ dir . ‘/xl/worksheets/sheet1.xml’ );
// Parse the rows
$ xlrows = $ sheet -> sheetData -> row ;
foreach ( $ xlrows as $ xlrow )
$ arr = array ();
// In each row, grab it’s value
foreach ( $ xlrow -> c as $ cell )
$ v = ( string ) $ cell -> v ;
// If it has a «t» (type?) of «s» (string?), use the value to look up string value
if (isset( $ cell [ ‘t’ ]) && $ cell [ ‘t’ ] == ‘s’ )
$ s = array ();
$ si = $ strings -> si [( int ) $ v ];
// Register & alias the default namespace or you’ll get empty results in the xpath query
$ si -> registerXPathNamespace ( ‘n’ , ‘http://schemas.openxmlformats.org/spreadsheetml/2006/main’ );
// Cat together all of the ‘t’ (text?) node values
foreach ( $ si -> xpath ( ‘.//n:t’ ) as $ t )
$ s [] = ( string ) $ t ;
>
$ v = implode( $ s );
>
$ arr [] = $ v ;
>
// Assuming the first row are headers, stick them in the headers array
if (count( $ headers ) == 0 )
$ headers = $ arr ;
> else
// Combine the row with the headers — make sure we have the same column count
$ values = array_pad( $ arr , count( $ headers ), » );
$ row = array_combine( $ headers , $ values );
/**
* Here, do whatever you like with the [header => value] assoc array in $row.
* It might be useful just to run this script without any code here, to watch
* memory usage simply iterating over your spreadsheet.
*/
>
>
@unlink( $ dir );
@unlink( $ inputFile );

Источник

Разбираем xlsx в PHP без готовых библиотек

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

Все бы ничего, но хостер заказчика дает 64мб памяти под выполнение и плевать он хотел на то, что у клиента Exсel файлы вообще без форматирования весят по 10-15мб, что при загрузке его PHPExel съедает (на тест-сервере) что-то около 500мб памяти.
Решение под катом с трудом дотянуло до 5мб.

Предусловия:
1. Имеется Exсel документ листов так в 10-20 с данными о товарах в интернет-каталоге. В каждом листе шапка — «название», «цена» и т.п. + воз доп. характеристик в 40 столбцов — и собственно данные в количестве «у-экселя-сантиметровый-скроллер»;
2. никакого CSV использовать нельзя. Все данные у заказчика уже в Exel и пересохранять их он не собирается… пообещали тут и все;
3. Spreadsheet_Excel_Writer откинут по причине неуниверсальности, хотя написано про него много хорошего. Жду комментариев по memory tests;
4. что удивительно, универсальных решений гугль не предложил. Неужели никто не сталкивался с такой проблемой на PHP *nix, удивился я.

Решение:
После перебора различных способов, вежливо предоставленных гуглом, решили почитать спецификации (эхх, учил меня отец. ). Увидев там ключевые слова основан на Open XML и используется сжатие ZIP быстро позвонили заказчику и перевели разговор в русло xlsx и только: «Ну вы же понимаете! 21 век все-таки! Зачем нам хвататься за старое! Нужно одной ногой стоять в будущем!»

Далее алгоритм таков: принимаем файл, распаковываем его и внимательно смотрим на получившееся.
Полную инвентаризацию надо будет на досуге провести, а сейчас же нам наиболее интересно содержимое директории [xl], конкретно — /xl/worksheets/ и файл /xl/sharedStrings.xml.
В файле /xl/workbook.xml лежит описание листов, но т.к. задачи собрать названия листов не стояло, этот пункт я пропущу. При необходимости разобраться в нем не составит труда.

. Наименование  Описание  Изображение  URL  !Классификация  !Бренд  ~1ф, 220-240 В, 50 Гц  . 

и так далее в том же духе. Представляет собой текстовые данные в ячейках исходного документа. Со всех листов! Пока просто соберем эти данные в массив.

 $xml = simplexml_load_file(PATH . '/upload/xls_data/xl/sharedStrings.xml'); $sharedStringsArr = array(); foreach ($xml->children() as $item) < $sharedStringsArr[] = (string)$item->t; > 

/xl/worksheets/
Это директория с файлами типа «sheet1.xml» с описанием данных листов. Конкретно в каждом файле нас интересует содержимое и его детей .

Методом сопоставлений и экспериментов было выяснено, что атрибут [t=«s»] у ячейки (судя по всему type=string) является указанием на то, что значение берем из файла sharedStrings.xml. Указатель — значение — номер элемента из $sharedStringsArr. Если не указан — берем само значение за значение ячейки.

 $handle = @opendir(PATH . '/upload/xls_data/xl/worksheets'); $out = array(); while ($file = @readdir($handle)) < //проходим по всем файлам из директории /xl/worksheets/ if ($file != "." && $file != ".." && $file != '_rels') < $xml = simplexml_load_file(PATH . '/upload/xls_data/xl/worksheets/' . $file); //по каждой строке $row = 0; foreach ($xml->sheetData->row as $item) < $out[$file][$row] = array(); //по каждой ячейке строки $cell = 0; foreach ($item as $child) < $attr = $child->attributes(); $value = isset($child->v)? (string)$child->v:false; $out[$file][$row][$cell] = isset($attr['t']) ? $sharedStringsArr[$value] : $value; $cell++; > $row++; > > > var_dump($out); 

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

Напоследок скажу, что толком в спецификации xlsx не разбирался, а только выполнил поставленную задачу с конкретными xlsx документами. Куда-то ведь должны писаться формулы и изображения (t=«i»?). Когда столкнусь с такой задачей — непременно опишу, а пока представляю нетребовательный к системе алгоритм для сбора текстовых данных из xslx. Надеюсь, будет востребован, т.к. в поисках подобного не встречал.

P.S. Только расставляя метки наткнулся на Работа с большими файлами экселя. Хабрить надо было, а не гуглить — много бы времени сэкономил.

UPD:
Вот только что вот оказалось, что пустая ячейка может быть представлена как отсутствием параметра в , так и отсутсвием самого . Необходимо сверять атрибут «r».

Источник

Обзор PHP расширений для чтения файлов Excel

В статье представлены различные PHP-расширения для чтения файлов XLS, XLSX, описаны их плюсы и минусы, а также примеры чтения.

PHPExcel

Огромная библиотека читает и формирует фалы xls, xlsx, csv.

Пример чтения файла в массив:

require_once __DIR__ . '/PHPExcel-1.8/Classes/PHPExcel/IOFactory.php'; // Файл xlsx $xls = PHPExcel_IOFactory::load(__DIR__ . '/test.xlsx'); // Первый лист $xls->setActiveSheetIndex(0); $sheet = $xls->getActiveSheet(); foreach ($sheet->toArray() as $row)

SimpleXLSX

  • Менее прожорлив к памяти.
  • Не всегда может прочитать файл, например файл сформированный PHPExcel.
require_once __DIR__ . '/simple-xlsx/simplexlsx.class.php'; // Файл xlsx $xlsx = new SimpleXLSX(__DIR__ . '/test.xlsx'); // Первый лист $sheet = $xlsx->rows(1); foreach ($sheet as $row)

PHP-ExcelReader

require_once __DIR__ . '/phpExcelReader/Excel/reader.php'; $data = new Spreadsheet_Excel_Reader(); $data->setOutputEncoding('UTF-8'); // Файл xls $data->read(__DIR__ . '/test.xls'); // Первый лист $sheet = $data->sheets[0]['cells']; foreach ($sheet as $row)

PHP-Excel-Reader

Форк библиотеки «PHP Excel Reader» с SourceForge предназначенный для вывода таблицы в HTML.

Например файл example.xls выведет следующим образом:

 table.excel < border: 1px solid #CCCCCC; border-collapse:collapse; font-family:sans-serif; font-size:12px; margin: 0 auto; >table.excel thead th, table.excel tbody th < border: 1px solid #CCCCCC; text-align: center; vertical-align:bottom; >table.excel tbody th < text-align:center; width:20px; >table.excel tbody td < vertical-align:bottom; >table.excel tbody td dump(true, true); ?>

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

Nuovo Spreadsheet-Reader

Читает файлы XLSX, XLS, CSV и OpenOffice ods. Для чтения XLS используется предыдущая библиотека php-excel-reader.

require_once __DIR__ . '/spreadsheet-reader/php-excel-reader/excel_reader2.php'; require_once __DIR__ . '/spreadsheet-reader/SpreadsheetReader.php'; // Файл xlsx, xls, csv, ods. $Reader = new SpreadsheetReader(__DIR__ . '/test.xlsx'); // Номер листа. $Reader -> ChangeSheet(0); foreach ($Reader as $Row)

PHP-Spreadsheetreader

Откроет только файлы в формате XML Excel 2004.

$file = __DIR__ . '/test.xml'; require_once __DIR__ . '/SpreadsheetReader/SpreadsheetReader.php'; $reader = new SpreadsheetReader; // Файл xml $sheets = $reader->read(__DIR__ . '/test.xml'); // Выводим Первый лист foreach ($sheets[0] as $row)

Источник

Как сделать чтение и выгрузку excel на php

В профессии разработчика часто приходится сталкиваться с работой с табличными данными (списки товаров, новостей, мероприятий). С точки зрения пользователя проще всего работать с excel или google sheets api и заказчик зачастую может прислать данные для импорта на сайт в одном из этих форматов. Сегодня мы рассмотрим простую библиотеку SimpleXLSX, которая умеет конвертировать excel-файл в формате .xlsx в обычный массив на php.

Скачать библиотеку вы можете по ссылке с github. Я работаю в основном с WordPress, поэтому ее подключение у меня выглядит следующим образом:

require_once get_template_directory() . '/includes/plugin-additions/simplexlsx.class.php';

В качестве примера мы будем использовать простой пример списка городов:

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

// Simple XLSX Parser Template $fileImport = get_stylesheet_directory() . '/data/example.xlsx'; if ( $xlsx = SimpleXLSX::parse( $fileImport )) < $sheetData = $xlsx->rows(1); $excel = array(); $names = array(); foreach ( $sheetData as $keyD => $sheetRow ) < if ( $keyD == 0 ) < foreach ( $sheetRow as $keyC =>$sheetCol ) < if ( $sheetCol ) $names[$keyC] = $sheetCol; >> else < if ( $sheetRow['0'] ) $title = $sheetRow['0']; foreach ( $sheetRow as $keyC =>$sheetCol ) < if ( isset( $title ) && $sheetCol ) < $excel[$title][$names[$keyC]] = $sheetCol; >> unset( $title ); > // // end if $keyD != 0 > // end foreach $sheetData var_dump( $excel ); > else

Итоговый массив $excel в этом примере выглядит так:

array(5) < ["Архангельск"]=>array(4) < ["title"]=>string(22) "Архангельск" ["english"]=> string(11) "Arkhangelsk" ["ISO"]=> string(6) "RU-ARK" ["population"]=> string(7) "346 979" > ["Волгоград"]=> array(4) < ["title"]=>string(18) "Волгоград" ["english"]=> string(9) "Volgograd" ["ISO"]=> string(6) "RU-VGG" ["population"]=> string(9) "1 008 998" > ["Кемерово"]=> array(4) < ["title"]=>string(16) "Кемерово" ["english"]=> string(8) "Kemerovo" ["ISO"]=> string(6) "RU-KEM" ["population"]=> string(7) "556 382" > ["Тамбов"]=> array(4) < ["title"]=>string(12) "Тамбов" ["english"]=> string(6) "Tambov" ["ISO"]=> string(6) "RU-TAM" ["population"]=> string(7) "292 140" > ["Хабаровск"]=> array(5) < ["title"]=>string(18) "Хабаровск" ["english"]=> string(10) "Khabarovsk" ["ISO"]=> string(24) "RU-KHA" ["population"]=> string(24) "616 372" > >

PS. Эта библиотека не умеет писать в excel-файлы и в случае такой необходимости есть отдельная библиотека simplexlsxgen того же автора.

skillbox banner 480x320 jivo banner 480x320 kwork banner 480x320

Читайте также

Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 4 / 5. Количество оценок: 3

Оценок пока нет. Поставьте оценку первым.

Похожие посты

Разработка сайтов для бизнеса

Если у вас есть вопрос, на который вы не знаете ответ — напишите нам, мы поможем разобраться. Мы всегда рады интересным знакомствам и новым проектам.

Источник

Читайте также:  font-weight
Оцените статью