Как стать автором
Поиск
Написать публикацию
Обновить

Комментарии 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.
Ой, простите. Моя вина.
Вариант интересный конечно, но есть же 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');

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

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации