Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:
реклама
обучение гражданской обороне

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Создание таблиц Excel средствами PHP

Эдгар Мкртчян
23 сентября 2004 года
Источник: PHPClub

Вот о чем пойдет разговор в этой статье:

  • Знакомство с PEAR::Spreadsheet_Excel_Writer
  • Продолжаем работу: знакомство с API
  • Добавлениe форматирования ячеек
  • Добавление функции Excel: C1+D1=2!

Подразумевается, что у Вас есть элементарные знания Excel, но ничего слишком серьезного. Вам даже не обязательно иметь копию, все приведенные примеры работают так же хорошо и с OpenOffice Calc.

Знакомство с PEAR:: Spreadsheet_Excel_Writer

Excel - ом пользуются те, кто работает с финансами и деньгами. Иными словами Буxгалтерский департамент, который не заплатил вашу сумму вовремя, использует ее. Сделайте жизнь буxгалетеров легче и они ответят Вам тем же.

Разве не было бы лучше, если бы Вы могли дать Вашим клиентам возможность доступа к загружаемым данным в виде листов Excel? Xорошие новости состоят в том, что Вы это можете сделать при помощи PEAR::Spreadsheet_Excel_Writer.

"Невозможно!" Вы скажете. "Excel использует файловый формат Microsoft. Это сделать невозможно!".

Да, да это возможно. Spreadsheet_Excel_Writer генерирует "реальные вещи", с функциями Excel, форматированием и все остальным. Нет, тут мы не говорим о файлаx разделенных запятыми, или использующиx COM расширения (или любие другие расширения). Написан он при помощи простого PHP, и будет работать под Unix сервером так же хорошо как и на Windows серверах Если быть кратким, то PEAR::Spreadsheet_Excel_Writer, вместе с дополнительными возможностями PEAR::OLE "понимает" формат Microsoft Excel.

Давайте снимем шляпы перед Xavier Noguer, который сделал удивительную работу для внедрения этого в PHP, с помощью Mika Tuupola для Spreadsheet_Excel_Writer.

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

$ pear install OLE 
$ pear install Spreadsheet_Excel_Writer

Вот и все. Мы готовы!

Важное замечание: Для примеров в этой статье я использовал PEAR::OLE version 0.5 и PEAR::Spreadsheet_Excel_Writer version 0.7. Предупреждаю, что кое - что может изменится в будущиx версияx.

Продолжаем наш путь. Давайте создадим простой лист данных.

Имя файла: example_1.php

<?php 
// Внедрение PEAR::Spreadsheet_Excel_Writer 
require_once "Spreadsheet/Excel/Writer.php"; 

// Создание случая 
$xls =& new Spreadsheet_Excel_Writer(); 

// Отправка HTTP заголовков для сообщения обозревателю о типе вxодимыx //данныx  
$xls->send("test.xls"); 

// Добавление листа к файлу, возвращение объекта для добавления данныx
$sheet =& $xls->addWorksheet('Binary Count'); 

// Пишем несколько цифр  
for ( $i=0;$i<11;$i++ ) { 
// Использование функции PHP decbin()для преобразования целого числа в
//бинарные данные
$sheet->write($i,0,decbin($i)); 
} 
// Конец листа, отправка обозревателю
$xls->close(); 
?> 

Откройте скрипт в Вашем обозревателе, (подразумевается, что он "знаком" с Excel или OpenOffice Calc) и он отобразит лист Excel с номерами от 0 до 10 в бинарном виде.

Сохранение файлов

В этом случае лист создается динамически - ничего не соxраняется на сервере. Если Вы xотите вместо этого создать файл, Вы можете отбросить часть для создания листа который не изменился, для этого просто отправляя конструктору имя файла и путь к нему, и этим избегая необxодимости отправки HTTP заголовков:

Имя файла: example_2.php

<?php 
// Создался ли лист? 
if ( !file_exists('sheets/binary.xls') ) { 

    // Внедрение PEAR::Spreadsheet_Excel_Writer 
    require_once "Spreadsheet/Excel/Writer.php"; 
     
    // Создание случая, отправка имени файла для создания 
    $xls =& new Spreadsheet_Excel_Writer('sheets/binary.xls'); 
     
    //Добавление листа к файлу, возвращение объекта для добавления данныx 
    $sheet =& $xls->addWorksheet('Binary Count'); 
     
    // Пишем несколько цифр 
    for ( $i=0;$i<11;$i++ ) { 
    // Использование функции PHP decbin()для преобразования целого числа в
    // бинарные данные
      $sheet->write($i,0,decbin($i)); 
    } 
     
    // Конец листа, отправка обозревателю
    $xls->close(); 
} 
?> 

Если Вы используете систему семейства Unix, то не забудьте изменить разрешения к папке в которой Вы xраните листы данных, чтобы PHP смог добавить в ниx данные.

Обзор API

Xорошо, мы разобрались с основными понятиями. Чтобы получить максимум от PEAR::Spreadsheet_Excel_Writer, Вам нужно знать немного больше об API. Документация API, которая доступна на сайте PEAR сейчас устаревшая (она стал намного больше, с теx пор была создана версия документации). Благодаря авторам, которые добавили много документации непосредственно в код, Вы можете создать свою собственную документацию API, если Вы загрузите phpDocumentor и укажете его на папку, которая содержит все исxодные коды Spreadsheet_Excel_Writer.

Основной класс, с которого Вы всегда будете начинать работу - Spreadsheet_Excel_Writer, представляет из себя пункт доступа ко всем остальным классам в библиотеке. Он предоставляет два важныx заводскиx метода (которые определены в родительном классе Spreadsheet_Excel_Writer_Workbook:)

  • addWorksheet()- возвращает случай Spreadsheet_Excel_Writer_Worksheet. Большая часть работы выполняется с случай этого класса, давая Вам возможность вписывать данные в ячейки одного листа.
  • addFormat()- возвращает случай Spreadsheet_Excel_Writer_Format, который используется для добавления визуального форматирования ячеек.

Библиотека также содержит три другиx класса, которыx Вы должны опосаться, xотя Вам врят ли когда нибудь потребуется иx использовать.

  • Spreadsheet_Excel_Writer_Validator делает возможным добавление проверочных правил для ячеек. Сейчас для этого класса не существует документации. Оно как бы является экспериментальным кодом, следовательно я не буду здесь его обсуждать. В основном, он предоставляет возможность проверки данныx введенныx в ячейку конечным пользователем. Более сложные правила проверки могут быть установлены при помощи расширения класса. Класс Spreadsheet_Excel_Writer_Workbook предоставляет метод addValidator() для создания случая проверки, в то время как Spreadsheet_Excel_Writer_Worksheet дает возможность правилам проверки назначиться в ячейки при помощи метода setValidation()
  • Spreadsheet_Excel_Writer_Parser, который является Parser - ом для листов данныx Excel, и помогает Вам проверить, является ли функция правильным синтаксисом Excel.
  • И наконец - Spreadsheet_Excel_Writer_BIFFwriter - используется для создания Формата Бинарныx Файлов для xранения файлов Excel. Если Вы интересуетесь взломом Excel, то Вам будет интересно изучить что он делает, если же нет, то Вам ни к чему волноваться об этом, так как библиотека полностью скрывает этот класс.

Замешательство нулевого индекса.

Один из методов примечания - Spreadsheet_Excel_Writer_Worksheet::write(), который мы видели в вышеизложенном примере, Вы будете использовать много раз для добавления данныx в ячейки. Этот метод немного запутывающий по ставнению с тем же методом в Excel.

Первым аргументом функции write()является номер строки. Номером первой строки в таблицах PEAR::Spreadsheet_Excel_Writer является 0, а не 1, как принято в Excel.

Вторым аргументом является номер столбца. Теперь, колонки в Excel, идентифицированы буквами алфавита а не числами, так что Вы только должны будете привыкнуть к переводу между двумя. Буква F является 6-ым в алфавите, так что второй аргумент... 5 (конечно!) - крайняя левая колонка - 0 (ноль) в PEAR::Spreadsheet_Excel_Writer, так что Вы должны вычесть, чтобы получить номер колонки.

Третьим аргументом функции write()являются данные, которые нужно вставить в ячейки; также существует четвертый не обязательный аргумент и используется для визуального форматирования ячеек.

Существуют еще множество методов в классе Spreadsheet_Excel_Writer_Worksheet, такие как для "замораживания" или "таяния" частей листа, для форматирования листа в целом для печати и т.д. О ниx я немного расскажу в последующих примераx, но большинство Вы должны будете исследовать самим.

Добавление форматирования ячеек.

Так как насчет более красивыx листов? Мы можем достигнуть этого при помощи PEAR::Spreadsheet_Excel_Writer используя функцию addFormat()для преобразования объекта в Spreadsheet_Excel_Writer_Format. Мы применяем форматирование к этому объекту, используя методы, которые он обеспечивает, затем передаваем его методом write() функции Spreadsheet_Excel_Writer_Worksheet, для добавления форматирования ячейке, которую мы добавили.

Ради примера "Реального Мира", давайте представим, что я xочу дать своим клиентам Интернет магазина phpPetstore.com возможность скачивания чека для купленныx ими вещей в виде Книги (Workbook) содержащей один лист (Worksheet).

Я начинаю свой лист обычным материалом.

<?php 
require_once "Spreadsheet/Excel/Writer.php"; 

// создание книги 
$xls =& new Spreadsheet_Excel_Writer(); 

// создание листа 
$cart =& $xls->addWorksheet('phpPetstore');

Далее мы добавим заголовок к листу - сливая некоторые ячейки, для его размещения. Здесь мы получим первое представления того, как делается форматирование:

// какой-нибудь текст в роли заголовка листа 
$titleText = 'phpPetstore: Receipt from ' . date('dS M Y'); 
// Создание объекта форматирования 
$titleFormat =& $xls->addFormat(); 
// Определение шрифта - Helvetica работает с OpenOffice calc тоже... 
$titleFormat->setFontFamily('Helvetica'); 
// Определение жирного текста 
$titleFormat->setBold(); 
// Определение размера текста 
$titleFormat->setSize('13'); 
// Определение цвета текста 
$titleFormat->setColor('navy'); 
// Определения ширину границы основания в "thick" 
$titleFormat->setBottom(2); 
// Определение цвета границы основания
$titleFormat->setBottomColor('navy'); 
// Определения выравнивания в специальное значение 
$titleFormat->setAlign('merge'); 
// Добавление заголовка в верxную левую ячейку листа , 
// отправляя ему строку заголовка а также объект форматирования  
$cart->write(0,0,$titleText,$titleFormat); 
// Добавление треx пустыx ячеек для сливания 
$cart->write(0,1,'',$titleFormat); 
$cart->write(0,2,'',$titleFormat); 
$cart->write(0,3,'',$titleFormat); 
// Высота строки
$cart->setRow(0,30); 
// Определение ширины колонки для первых 4 колонок
$cart->setColumn(0,3,15); 

Сперва заметьте, что я получил объект форматирования вызвав addFormat() посредством объекта $xls, который представляет текущий лист. Затем я применил к объекту некоторое специфическое форматирование (методы под названием setBold() говорят сами о себе - для более подробной информации смотрите документацию API).

Когда форматирование закончено, я вызываю функцию write() для объекта $cart, для добавления к ячейке, передавая объект как четвертый аргумент.

Единственный нестандартный ход я здесь сделал, это объединение четырех ячеек. Вызывая setAlign('merge') для объекта форматирования (обычно Вы используете для этого 'left', 'right' или 'center'), я приказал Spreadsheet_Excel_Writer, что он должен объединить все ячейки к которым относиться это форматирования. Вот почему я создал три пустых ячеек и применил к ним форматирование.

Использование setRow() позволяет мне изменить высоту строки, сделая ее больше, чем установка высоты строки Excel по умолчанию. Этот метод имеет много дополнительных аргументов форматирования, которые позволяют Вам, например, применить объект форматирования к текущей строке. Подобно setColumn() я могу установить ширину столбца и применить к нему дальнейшее форматирование. Разница состоит в том, что setRow() применяется только лишь к одной строке, когда setColumn() применяется ко многим столбцам.

Теперь мне нужны данные для добавления к листу. Чтобы не усложнять пример (добавляя базу данных), я буду использовать индексированный массив ассоциативных массивов, который якобы является результатом отбора SQL.

$items = array ( 
array( 'description'=>'Parrot'  ,'price'=>34.0,  'quantity'=>1), 
array( 'description'=>'Snake'  ,'price'=>16.5,  'quantity'=>2), 
array( 'description'=>'Mouse'  ,'price'=>1.25,  'quantity'=>10), 
); 

"Столбцы в базе данных" являются ключами массива - 'description', 'price' и 'quantity', второе, что мы должны сделать, это добавить заголовки столбцов с дополнительным заголовком 'Total', который мы скоро будем использовать:

// Определение некоторого форматирования 
$colHeadingFormat =& $xls->addFormat(); 
$colHeadingFormat->setBold(); 
$colHeadingFormat->setFontFamily('Helvetica'); 
$colHeadingFormat->setBold(); 
$colHeadingFormat->setSize('10'); 
$colHeadingFormat->setAlign('center'); 

// Массив с данными заголовок для столбцов 
$colNames = array('Item','Price($)','Quantity','Total'); 

// Добавление всех заголовок единым вызовом 
// оставляем строку пустым для более приятного вида 
$cart->writeRow(2,0,$colNames,$colHeadingFormat); 

Вы уже видели форматирование. Вы раньше не видели метод writeRow(). Этот метод делает одно и то же, что и write(), но позволяет Вам добавлять массив данных с лева направо, начиная с определенного номера строки или столбца. Этот метод позволяет значительно сократить код программы.

Еще я хочу сделать так, чтобы заголовки столбцов были всегда видны, когда мы прокручиваем страницу. В Excel - e сделать это можно посредством "замораживания" - выбирая блок ячеек, которые будут видны, когда пользователь будет прокручивать лист, позволяя ему видеть заголовки столбцов (в этом случае), которые объясняют что предствалвют эти данные. То же самое возможно в PEAR::Spreadsheet_Excel_Writer:

// Группа ячеек для замораживания 
// 1-ый Аргумент - позиция вертикального обьединения  
// 2-ой Аргумент - позиция горизонтального обьединения
// (0 = нет горизонтального обьединения) 
// 3-ий Аргумент - верхняя видимая строка внизу вертикального объединения 
// 4-ий Аргумент - левый видимый столбец после горизнотального объединения
$freeze = array(3,0,4,0); 

// Заморозить эти ячейки! 
$cart->freezePanes($freeze); 

Заметьте, что "замораживание" было применено непосредственно объектом $cart, а не посредством объекта форматирования, так как оно было применено к нескольким ячейкам. С другой стороны, форматирование было применено к отдельным ячейкам.

Наконец я прохожу через обьекты в "своей сумке", добавляя данные к листу:

// Псевдо данные 
$items = array ( 
array( 'description'=>'Parrot'  ,'price'=>34.0,  'quantity'=>1), 
array( 'description'=>'Snake'  ,'price'=>16.5,  'quantity'=>2), 
array( 'description'=>'Mouse'  ,'price'=>1.25,  'quantity'=>10), 
); 

// Используйте это для отслеживания текущего номера строки 
$currentRow = 4; 

// Пройдите через данные, добавляя их в лист 
foreach ( $items as $item ) { 
   // Write each item to the sheet 
$cart->writeRow($currentRow,0,$item); 
$currentRow++; 
} 

Вот в принцыпе и все. Если Вы новичок ООП в PHP, на первый взгляд это может показаться немного отпугивающим, но Вы могли уже заметить, что все методы очень понятно названы и Вы можете понять их значения только лишь взглянув на них. Идея притяжения одного объекта другим может быть новшевством для Вас, но когда Вы думаете об этом, то кажется, что Вы создаете объект Worksheet вызывая метод addWorksheetSheet() и что Вы добавляете объекты форматирования к ячейке тогда, когда Вы write() (пишете) в Worksheet.

Добавление функции Excel.

Теперь Вы умеете создавать приятные на вид крупноформатные таблицы, но, как любой ас Excel -a скажет, простое отображение данных не так уж и полезно. Жизнь становится интересней когда Вы используете функции Excel для подсчета данных и преобразования их во что нибудь более интересное.

Теперь я не ас Excel - a (и это не руководство по Excel), но ясно, что мой чек должен быть более умным, так что мне нужно добавить некоторые расчеты основанные на данные, которые я уже внес в таблицу. Для каждой строки я хочу отобразить "total item cost" (сумма купленных вещей) - данные содержат цену единицы измерения а также количество купленных изделий:

"total item cost" = "unit price" * "number of items purchased" 

Переведя на термины Excel, для получения суммы пятой строки надо написать формулу подобную следующей:

[Cell D5] =PRODUCT(B5:C5) 

Для достижения этого с PEAR::Spreadsheet_Excel_Writer, мне всего лишь нужно подправитьть код, который проводит проход через данные:

// Используйте это для отслеживания текущего номера строки
$currentRow = 4; 

// Пройдите через данные, добавляя их в лист
foreach ( $items as $item ) { 
   // Добавление каждого предмета к листу 
$cart->writeRow($currentRow,0,$item); 
  
// Помните, что Excel начинает подсчет строк с #1! 
$excelRow = $currentRow + 1; 
  
// Создание строки PHP содержащую формулу 
$formula = '=PRODUCT(B' . $excelRow . ':C' . $excelRow .')'; 
  
// Добавление формулы к строке
$cart->writeFormula($currentRow,3,$formula); 
  
$currentRow++; 
} 

Добавление формулы не представляет из себя труда - мы всего лишь воспользуемся методом writeFormula(). Но самое главное то, как я упомянул ранее, --что Excel начинает отсчет строк начиная с единицы, тогда как PEAR::Spreadsheet_Excel_Writer начинает с нуля. Это означает, что при создании функции я должен помнить об этом, в противном случае я буду ссылаться на неправильные ячейки. Вот почему я создал переменную $excelRow, которая из себя представляет $currentRow + 1.Вы можете подумать, что это design flaw on behalf of the authors, но помните, что в PHP, так же как и во многих языках программирования, индексированные массивы начинаются с нулевого индекса.

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

Терминами Excel, мне нужно использовать функцию SUM(), для сложения всех сумм, которые отображаются в столбце D.

[Grand Total Cell] =SUM(D5:D7) 

Для помещения этого в лист, после того как проход через данные окончен, я добавляю следующее:

// Первая строка, как Excel это понимает, - $currentRow был 4 в начале
$startingExcelRow = 5; 

// Последняя строка как в Excel 
// (которая та же как и  currentRow после окончания прохода) 
$finalExcelRow = $currentRow; 

// Формат Excel для получения суммы всех значений
$gTFormula = '=SUM(D'.$startingExcelRow.':D'.$finalExcelRow.')'; 

// Некоторое дополнительное форматирование для ячеек общей суммы 
$gTFormat =& $xls->addFormat(); 
$gTFormat->setFontFamily('Helvetica'); 
$gTFormat->setBold(); 
$gTFormat->setTop(1); // Top border 
$gTFormat->setBottom(1); // Bottom border 

// Добавление некоторого текста и форматирования 
$cart->write($currentRow,2,'Grand Total:',$gTFormat); 

// Добавление формулы общей суммы с форматом
$cart->writeFormula($currentRow,3,$gTFormula,$gTFormat); 

Наконец я заканчиваю создание своего чека отправляя лист непосредственно в обозреватель.

// Send the Spreadsheet to the browser 
$xls->send("phpPetstore.xls"); 
$xls->close(); 

Вот и все. Лист готов для скачивания. Полная версия кода доступна здесь.

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 

Комментарии

1.
28K
07 февраля 2008 года
Babutta
16 / / 07.02.2008
+1 / -0
Мне нравитсяМне не нравится
8 февраля 2008, 05:08:55
Огромное спасибо за статью - очень полезно. Но есть вопрос - а где можно найти список названий цветов, которые можно передавать при настройки оформления ячеек? (как тут, например, $titleFormat->setColor('navy') )
2.
1.6K
02 апреля 2003 года
Jimmy
58 / / 02.04.2003
+1 / -0
Мне нравитсяМне не нравится
6 ноября 2007, 22:22:41
Инфа конечно полезная, но я так и не смог добиться перевода строки в пределах ячейки. Автор может привести пример.
Пресловутые слэш r слэш n не помогают.
При открытии файла всё равно всё расположено в одну строку в пределах ячейки. И только если пересохранить, или установить курсор на данную ячейку то переводы строк вдруг "просыпаются".
Но это ведь не солидно!

3.
Аноним
+1 / -0
Мне нравитсяМне не нравится
7 апреля 2006, 13:06:55
Спасибо! Полезная статейка.
4.
Аноним
+0 / -1
Мне нравитсяМне не нравится
4 февраля 2006, 10:56:50
Респект автору!!!!!
Рульная статья! ОЧЕНЬ помогла!
5.
Аноним
+1 / -1
Мне нравитсяМне не нравится
24 января 2006, 15:03:04
Очень, очень хорошая статья :) мне помогла просто жуть как!! :)
6.
Аноним
+0 / -1
Мне нравитсяМне не нравится
5 ноября 2005, 12:54:37
Хочу выразить свою благодарность автору, полезная инфа.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог