Pull to refresh

Comments 17

1. К сожалению, код протестировать без артефактов на диске не получится.
2. У Excel немного больше форматов, чем «строка», «число», «дата». Например, форматированные проценты, дроби с конфигурируемым количеством знаков после запятой.
3. Форматирование ячейки (не путать с форматом!) тут не учитывается тоже.

П.С. Я так понимаю, автор делал сей код для простенького упаковщика, но с таким же успехом можно было использовать fputcsv(...)

П.П.С. Я нисколько не умаляю заслуг ТС! Написал и поделился — молодец! Даёшь качественные пулл-реквесты!
1. Разместил файл template.xlsx на Gitub. Можете им воспользоваться.
2. Верно-верно. Но публикация ведь про мой опыт, а мне нужны были только указанные мной форматы.

Однако, нет ничего проще использовать и другие форматы. Попробую описать по пунктам:
a. Открыть template.xlsx
b. Ввести в какую-нибудь ячейку тестовое значение и отформатировать его так, как вам нужно
c. Стереть введенное значение (можно не стирать, но ...)
d. Сохранить template.xlsx
e. Переименовать xlsx в xip.
f. Распаковать.
g. Найти файл /xl/styles.xml.
h. Открыть его в каком-нибудь приложении для просмотра, например, в Internet Explorer.
i. Найти тэг cellXfs, в нем и будут содержаться все стили, включая новый.
Рекомендую проделать эти операции на копии template.xlsx, чтобы в п.i сравнить исходный styles.xml и конечный styles.xml. Обращаю внимание еще и на тот факт, что ссылка на стиль осуществляется по порядковому номеру стиля.

3. Именно так, ведь простой экспорт подразумевает экспорт именно значений, а не форматов. Хотя, справедливости ради, укажу на тот факт, что в функции appendCellString учитывается установка флага isBold, который позволяет сделать строковые значения жирным шрифтом.

Про fputcsv знаю, но значения сохраненные в csv формате при открытии в Excel рискуют быть искаженными. Уж очень любит Microsoft Excel «догадываться» какой формат надо установить для значения и превращает все подряд в даты. Кроме этого, обычному современному пользователю csv формат неизвестен, ну или вызывает замешательство и депрессию. В общем, такой простенький экспорт в формате xlsx оправдан тем, что сокращает количество обращений пользователей с вопросом: «Что делать с CSV?»
Кстати, про команду «Данные» — «Из текста» в Excel знает тоже не каждый пользователь.

Смысл публикации именно в том, чтобы поделиться опытом и позволить другим программистам, коллегам, не ломать голову при решении подобных задач. Написание класса для экспорта в XLSX у меня отняло примерно пару дней. Сперва разбирался с шаблоном. Потом со строками и датами. Потом оформлял в класс. Если кто-то другой прочитав эту публикацию сэкономит пару дней я буду только рад!
Спасибо за статью. Как раз в ближайшую неделю-две придется ковыряться с XLS на тему подмены значений.
C xls нужно будет по-другому как-то работать.
сорри, опечатался, имел в виду как раз XLSX
Это круто. Действительно, библиотеки, которые умеют все, очень толстые и неповоротливые. Простое решение, которое включает в себя только то что надо, мне кажется, в этом случае просто идеально подходи.
Deaddy указал на то, что в предыдущем сообщений Вы написали XLS, а не XLSX. Если это не опечатка, то надо понимать, что это разные форматы. То, что подходит для XLSX не подойдет для XLS.
Вы, видимо, что-то напутали =). Я не автор предыдущего сообщения про XLS.
Вариант интересный конечно, но есть же PHPExcel — phpexcel.codeplex.com/
Удобно, красиво и без придумывания велосипеда
На больших файлах он съест всю память.
Если в таблице больше 25 столбцов, то формируется не валидный файл.
public function appendCellNum($value)
{
    $this->curCel++;
    $this->currentRow[] = '<c r="'.chr(64+$this->curCel).$this->numRows.'"><v>'.$value.'</v></c>';
}

chr(64+$this->curCel)
вернет символы, которые не входят в алфавит и их уже нельзя использовать в нумерации ячеек. Например, если столбцов 26, то будет использован символ [.
Ну и в заголовке sheet1.xml это тоже используется:
fwrite($this->workSheetHandler, '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"><dimension ref="A1:'.chr(64+$this->colCount).$this->rowCount.'"/><sheetData>');
Верно подмечено!
Решаемо:

function numToLetter($num)
{
	$f = '';
	do 
	{
		$f = chr(64 + $num % 26) . $f;
		$num = floor($num / 26);
	}
	while ($num > 0);
	return $f;
}

echo '<br/>letters: ',numToLetter(1905); //return BUG


Спасибо за замечание.
Жаль, что решение не автономно и есть связь с Yii.
SimpleXLSXGen
$books = [
  ['ISBN', 'title', 'author', 'publisher', 'ctry' ],
  [618260307, 'The Hobbit', 'J. R. R. Tolkien', 'Houghton Mifflin', 'USA'],
  [908606664, 'Slinky Malinki', 'Lynley Dodd', 'Mallinson Rendel', 'NZ']
];
$xlsx = SimpleXLSXGen::fromArray( $books );
$xlsx->saveAs('books.xlsx');
// $xlsx->downloadAs('books.xlsx');

Вот это то что надо. Основной функционал и ничего лишнего. Спасибо!
Еще бы простейшее форматирование — жирный, кегль — и было бы просто супер.

Sign up to leave a comment.

Articles