Comments 11
Не так просто пересадить клиента с xls на xlsx.
Обычно клиенты хотят поддержки обоих форматов, и чаще старый, нежели новый.
В данной ситуации повезло =)
Обычно клиенты хотят поддержки обоих форматов, и чаще старый, нежели новый.
В данной ситуации повезло =)
Формула пишется в теге f (на одном уровне с v).
Тип (t) может быть «inlineStr», тогда строка записана не в SharedString, а прямо внутри ячейки, но в теге is (а не v) (хотя практически я с этим не сталкивался).
Целые числа и даты, а также вещественные числа и время (дата со временем) выглядят одинаково в теге v. Потому что дата, например, — это число дней с 01.01.1900.
Чтобы понять что это на самом деле нужно смотреть в атрибут s — это индекс стиля из workbook.xml.
Тип (t) может быть «inlineStr», тогда строка записана не в SharedString, а прямо внутри ячейки, но в теге is (а не v) (хотя практически я с этим не сталкивался).
Целые числа и даты, а также вещественные числа и время (дата со временем) выглядят одинаково в теге v. Потому что дата, например, — это число дней с 01.01.1900.
Чтобы понять что это на самом деле нужно смотреть в атрибут s — это индекс стиля из workbook.xml.
P.S. Только расставляя метки наткнулся на Работа с большими файлами экселя. Хабрить надо было, а не гуглить — много бы времени сэкономил.
Там же через OLEDB работают.
UFO just landed and posted this here
помню, что когда-то нужно было обработать несколько десятков msword документов из табличними данними — и вот почесалась репа и накидалось на коленке решение с использованием php streams:
$questions = array(); foreach(new DirectoryIterator(realpath('data')) as $file) { if($file->isFile()) { $path = "zip://" . $file->getPathname() . '#word/document.xml'; _parse($path, $questions); } } function _parse($path, &$questions) { $xml = simplexml_load_file($path); $ns = $xml->getDocNamespaces(); $xml->registerXPathNamespace('w', $ns['w']); foreach($xml->xpath('/w:document/w:body/w:tbl') as $elem) {
А как экранируются служебные символы, например < >?
Методом проб и ошибок выяснил, что с помощью htmlspecialchars
P.s. Сам спросил, сам ответил. Надеюсь кому то будет полезно.
P.s. Сам спросил, сам ответил. Надеюсь кому то будет полезно.
Ну логично.
Дополнение от reak002
Хочу предложить небольшое дополнение к коду в виде:
вместо
после чего код будет собирать полную сетку документа.
Вот собственно видоизмененный код:
Хочу предложить небольшое дополнение к коду в виде:
$keyN = preg_replace('/\d/', '', $attr['r']);
$out[$file][$row][$keyN] = isset($attr['t']) ? $sharedStringsArr[$value] : $value;
вместо
$out[$file][$row][$cell] = isset($attr['t']) ? $sharedStringsArr[$value] : $value;
$cell++;
после чего код будет собирать полную сетку документа.
Вот собственно видоизмененный код:
$handle = @opendir(TEMP_DIR_PATH . '/' . $name.'/xl/worksheets');
$out = array();
while ($file = @readdir($handle)) {
//проходим по всем файлам из директории /xl/worksheets/
if ($file != "." && $file != ".." && $file != '_rels') {
$xml = simplexml_load_file(TEMP_DIR_PATH . '/' . $name.'/xl/worksheets/' . $file);
//по каждой строке
$row = 0;
foreach ($xml->sheetData->row as $item) {
$out[$file][$row] = array();
//по каждой ячейке строки
foreach ($item as $child) {
$attr = $child->attributes();
$value = isset($child->v)? (string)$child->v:false;
$keyN = preg_replace('/\d/', '', $attr['r']);
$out[$file][$row][$keyN] = isset($attr['t']) ? $sharedStringsArr[$value] : $value;
}
$row++;
}
}
}
return $out;
Встретился с такой необходимостью, так как стали приходить битые xlsx файлы, которые надо было записывать в базу данных. С источником файлов было бесполезно договариваться.
Sign up to leave a comment.
Разбираем xlsx в PHP без готовых библиотек