Php creating excel file

К сожалению разработчики прекратили поддержку и разработку проекта, но PHPExcel все равно остается популярной библиотекой которая выполняет свои задачи, последняя версия нормально работает на PHP 7.

Проект на GitHub.

1

Создание документа

require_once __DIR__ . '/PHPExcel-1.8/Classes/PHPExcel.php';
require_once __DIR__ . '/PHPExcel-1.8/Classes/PHPExcel/Writer/Excel2007.php';

$xls = new PHPExcel();

PHP

Если нужно открыть существующий файл:

require_once __DIR__ . '/PHPExcel-1.8/Classes/PHPExcel.php';
require_once __DIR__ . '/PHPExcel-1.8/Classes/PHPExcel/Writer/Excel2007.php';
require_once __DIR__ . '/PHPExcel-1.8/Classes/PHPExcel/IOFactory.php';

$xls = PHPExcel_IOFactory::load(__DIR__ . '/file.xlsx');

PHP

Установка сводки документа:

$xls->getProperties()->setTitle("Название");
$xls->getProperties()->setSubject("Тема");
$xls->getProperties()->setCreator("Автор");
$xls->getProperties()->setManager("Руководитель");
$xls->getProperties()->setCompany("Организация");
$xls->getProperties()->setCategory("Группа");
$xls->getProperties()->setKeywords("Ключевые слова");
$xls->getProperties()->setDescription("Примечания");
$xls->getProperties()->setLastModifiedBy("Автор изменений");
$xls->getProperties()->setCreated("25.03.2019");

PHP

Защита книги паролем:

$xls->getActiveSheet()->getProtection()->setSheet(true);
$xls->getActiveSheet()->getProtection()->setSort(true);
$xls->getActiveSheet()->getProtection()->setInsertRows(true);
$xls->getActiveSheet()->getProtection()->setFormatCells(true);
$xls->getActiveSheet()->getProtection()->setPassword('123456');

PHP

Создаем новый лист, далее работаем с ним через переменную $sheet.

$xls->setActiveSheetIndex(0);
$sheet = $xls->getActiveSheet();
$sheet->setTitle('Название листа');

PHP

Параметры печати

// Формат
$sheet->getPageSetup()->SetPaperSize(PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4);

// Ориентация
// ORIENTATION_PORTRAIT — книжная
// ORIENTATION_LANDSCAPE — альбомная
$sheet->getPageSetup()->setOrientation(PHPExcel_Worksheet_PageSetup::ORIENTATION_PORTRAIT);

// Поля
$sheet->getPageMargins()->setTop(1);
$sheet->getPageMargins()->setRight(0.75);
$sheet->getPageMargins()->setLeft(0.75);
$sheet->getPageMargins()->setBottom(1);

// Верхний колонтитул
$sheet->getHeaderFooter()->setOddHeader("Название листа");

// Нижний колонтитул
$sheet->getHeaderFooter()->setOddFooter('&L&B Название листа &R Страница &P из &N');

PHP

Запись в ячейку и ее формат

$sheet->setCellValue("A1", "Значение");

PHP

Формат ячеек определяется автоматически, иногда это вызывает проблемы. Например, значения 1., 10.0, 0.1 выведутся как 1, 10, 0,1. Чтобы это исправить нужно использовать метод setCellValueExplicit() в место setCellValue().

$sheet->setCellValueExplicit("A1", '1.', PHPExcel_Cell_DataType::TYPE_STRING);
$sheet->setCellValueExplicit("A2", '10.0', PHPExcel_Cell_DataType::TYPE_STRING);
$sheet->setCellValueExplicit("A3", '0.1', PHPExcel_Cell_DataType::TYPE_STRING);

PHP

2

Размеры ячеек

Ширина столбцов

// Ширина столбца A 
$sheet->getColumnDimension("A")->setWidth(100);

// Авто ширина колонки по содержимому
$sheet->getColumnDimensionByColumn("A")->setAutoSize(true);

PHP

Высота строк

// Высота 1-й строки
$sheet->getRowDimension("1")->setRowHeight(50);

PHP

Вставленный в ячейку длинный текст будет выходить за ее пределы, переносы rn работать не будут.

$sheet->setCellValue("A1", "Excel — программа rn для работы с электронными таблицами");

PHP

Метод setWrapText(true) включает переносы строк и авто высоту.

$sheet->setCellValue("A1", "Excel — программа rn для работы с электронными таблицами");
$sheet->getStyle("A1")->getAlignment()->setWrapText(true);

PHP

3

Объединение ячеек

// Объединение ячеек в колонке
$sheet->mergeCells("A1:A6");
$sheet->setCellValue("A1", "A1:A6");

// Объединение ячеек в строке
$sheet->mergeCells("C2:I2");
$sheet->setCellValue("C2", "C2:I2");

// Объединение ячеек по диапазону
$sheet->mergeCells("C4:I6");
$sheet->setCellValue("C4", "C4:I6");

PHP

Объединение ячеек PHPExcel

4

Стили текста

// Шрифт Times New Roman
$sheet->getStyle('A1')->getFont()->setName('Times New Roman');

// Размер шрифта 18
$sheet->getStyle("A2")->getFont()->setSize(18);

// Цвет шрифта
$sheet->getStyle("A3")->getFont()->getColor()->setRGB('ff0000');

// Жирный
$sheet->getStyle("A4")->getFont()->setBold(true);

// Курсив
$sheet->getStyle("A5")->getFont()->setItalic(true);

// Подчеркнутый текст
$sheet->getStyle("A6")->getFont()->setUnderline(true);

// Зачеркнутый текст
$sheet->getStyle("A7")->getFont()->setStrikethrough(true);

PHP

Стили текста PHPExcel

Также можно задать сразу несколько стилей для ячейки, массивом:

$style = array(
	'font' => array(
		'name'      => 'Times New Roman',
		'size'      => 18,   
		'color'     => array('rgb' => 'FF0000'),              
		'bold'      => true,
		'italic'    => true,
		'underline' => true,
		'strike'    => true,
	)
);

$sheet->getStyle('A1')->applyFromArray($style);

PHP

Установить стили шрифта для всего документа:

$sheet->getDefaultStyle()->getFont()->setName('Times New Roman');
$sheet->getDefaultStyle()->getFont()->setSize(18);

PHP

Или:

$style = array(
	'font' => array(
		'name' => 'Times New Roman',
		'size' => 18,  
	)
);

$sheet->getDefaultStyle()->applyFromArray($style);

PHP

5

Выравнивание в ячейке

По горизонтали:

// По левому краю
$sheet->getStyle("A1")->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_LEFT);

// По центру
$sheet->getStyle("A1")->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_CENTER);

// По правому краю
$sheet->getStyle("A1")->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_RIGHT);

PHP

По вертикали:

// Сверху
$sheet->getStyle("A1")->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_TOP);

// По центру
$sheet->getStyle("A1")->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_CENTER);

// Снизу
$sheet->getStyle("A1")->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_BOTTOM);

PHP

6

Фон ячейки

Стили фона устанавливаются массивом значений, type – определяет стиль заливки, далее в зависимости от выбранного стиля задаются его настройки в параметрах color, startcolor, endcolor, rotation.

PHPExcel_Style_Fill::FILL_SOLID

$bg = array(
	'fill' => array(
		'type' => PHPExcel_Style_Fill::FILL_SOLID,
		'color' => array('rgb' => '01B050')
	)
);
$sheet->getStyle("B2")->applyFromArray($bg);

PHP

PHPExcel_Style_Fill::FILL_SOLID

PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR

$bg = array(
	'fill' => array(
		'type' => PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR,
		'startcolor' => array('rgb' => '01B050'),
		'endcolor' => array('rgb' => 'f1ee3b'),
		'rotation' => 90
	)
);                 
$sheet->getStyle("B2")->applyFromArray($bg);

PHP

PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR

PHPExcel_Style_Fill::FILL_GRADIENT_PATH

$bg = array(
	'fill' => array(
		'type' => PHPExcel_Style_Fill::FILL_GRADIENT_PATH,
		'startcolor' => array('rgb' => '01B050'),
		'endcolor' => array('rgb' => 'f1ee3b'),
	)
);                 
$sheet->getStyle("B2")->applyFromArray($bg);

PHP

PHPExcel_Style_Fill::FILL_GRADIENT_PATH

PHPExcel_Style_Fill::FILL_PATTERN_DARKDOWN

$bg = array(
	'fill' => array(
		'type' => PHPExcel_Style_Fill::FILL_PATTERN_DARKDOWN,
		'startcolor' => array('rgb' => '01B050'),
		'endcolor' => array('rgb' => 'f1ee3b'),
	)
);                 
$sheet->getStyle("B2")->applyFromArray($bg);

PHP

PHPExcel_Style_Fill::FILL_PATTERN_DARKDOWN

PHPExcel_Style_Fill::FILL_PATTERN_DARKGRAY

$bg = array(
	'fill' => array(
		'type' => PHPExcel_Style_Fill::FILL_PATTERN_DARKGRAY,
		'startcolor' => array('rgb' => '01B050'),
		'endcolor' => array('rgb' => 'f1ee3b'),
	)
);                 
$sheet->getStyle("B2")->applyFromArray($bg);

PHP

PHPExcel_Style_Fill::FILL_PATTERN_DARKGRAY

PHPExcel_Style_Fill::FILL_PATTERN_DARKGRID

$bg = array(
	'fill' => array(
		'type' => PHPExcel_Style_Fill::FILL_PATTERN_DARKGRID,
		'startcolor' => array('rgb' => '01B050'),
		'endcolor' => array('rgb' => 'f1ee3b'),
	)
);                 
$sheet->getStyle("B2")->applyFromArray($bg);

PHP

PHPExcel_Style_Fill::FILL_PATTERN_DARKGRID

PHPExcel_Style_Fill::FILL_PATTERN_DARKHORIZONTAL

$bg = array(
	'fill' => array(
		'type' => PHPExcel_Style_Fill::FILL_PATTERN_DARKHORIZONTAL,
		'startcolor' => array('rgb' => '01B050'),
		'endcolor' => array('rgb' => 'f1ee3b'),
	)
);                 
$sheet->getStyle("B2")->applyFromArray($bg);

PHP

PHPExcel_Style_Fill::FILL_PATTERN_DARKHORIZONTAL

PHPExcel_Style_Fill::FILL_PATTERN_DARKTRELLIS

$bg = array(
	'fill' => array(
		'type' => PHPExcel_Style_Fill::FILL_PATTERN_DARKTRELLIS,
		'startcolor' => array('rgb' => '01B050'),
		'endcolor' => array('rgb' => 'f1ee3b'),
	)
);                 
$sheet->getStyle("B2")->applyFromArray($bg);

PHP

PHPExcel_Style_Fill::FILL_PATTERN_DARKTRELLIS

PHPExcel_Style_Fill::FILL_PATTERN_DARKUP

$bg = array(
	'fill' => array(
		'type' => PHPExcel_Style_Fill::FILL_PATTERN_DARKUP,
		'startcolor' => array('rgb' => '01B050'),
		'endcolor' => array('rgb' => 'f1ee3b'),
	)
);                 
$sheet->getStyle("B2")->applyFromArray($bg);

PHP

PHPExcel_Style_Fill::FILL_PATTERN_DARKUP

PHPExcel_Style_Fill::FILL_PATTERN_DARKVERTICAL

$bg = array(
	'fill' => array(
		'type' => PHPExcel_Style_Fill::FILL_PATTERN_DARKVERTICAL,
		'startcolor' => array('rgb' => '01B050'),
		'endcolor' => array('rgb' => 'f1ee3b'),
	)
);                 
$sheet->getStyle("B2")->applyFromArray($bg);

PHP

PHPExcel_Style_Fill::FILL_PATTERN_DARKVERTICAL

PHPExcel_Style_Fill::FILL_PATTERN_GRAY0625

$bg = array(
	'fill' => array(
		'type' => PHPExcel_Style_Fill::FILL_PATTERN_GRAY0625,
		'startcolor' => array('rgb' => '01B050'),
		'endcolor' => array('rgb' => 'f1ee3b'),
	)
);                 
$sheet->getStyle("B2")->applyFromArray($bg);

PHP

PHPExcel_Style_Fill::FILL_PATTERN_GRAY0625

PHPExcel_Style_Fill::FILL_PATTERN_GRAY125

$bg = array(
	'fill' => array(
		'type' => PHPExcel_Style_Fill::FILL_PATTERN_GRAY125,
		'startcolor' => array('rgb' => '01B050'),
		'endcolor' => array('rgb' => 'f1ee3b'),
	)
);                 
$sheet->getStyle("B2")->applyFromArray($bg);

PHP

PHPExcel_Style_Fill::FILL_PATTERN_GRAY125

PHPExcel_Style_Fill::FILL_PATTERN_LIGHTDOWN

$bg = array(
	'fill' => array(
		'type' => PHPExcel_Style_Fill::FILL_PATTERN_LIGHTDOWN,
		'startcolor' => array('rgb' => '01B050'),
		'endcolor' => array('rgb' => 'f1ee3b'),
	)
);                 
$sheet->getStyle("B2")->applyFromArray($bg);

PHP

PHPExcel_Style_Fill::FILL_PATTERN_LIGHTDOWN

PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRAY

$bg = array(
	'fill' => array(
		'type' => PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRAY,
		'startcolor' => array('rgb' => '01B050'),
		'endcolor' => array('rgb' => 'f1ee3b'),
	)
);                 
$sheet->getStyle("B2")->applyFromArray($bg);

PHP

PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRAY

PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRID

$bg = array(
	'fill' => array(
		'type' => PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRID,
		'startcolor' => array('rgb' => '01B050'),
		'endcolor' => array('rgb' => 'f1ee3b'),
	)
);                 
$sheet->getStyle("B2")->applyFromArray($bg);

PHP

PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRID

PHPExcel_Style_Fill::FILL_PATTERN_LIGHTHORIZONTAL

$bg = array(
	'fill' => array(
		'type' => PHPExcel_Style_Fill::FILL_PATTERN_LIGHTHORIZONTAL,
		'startcolor' => array('rgb' => '01B050'),
		'endcolor' => array('rgb' => 'f1ee3b'),
	)
);                 
$sheet->getStyle("B2")->applyFromArray($bg);

PHP

PHPExcel_Style_Fill::FILL_PATTERN_LIGHTHORIZONTAL

PHPExcel_Style_Fill::FILL_PATTERN_LIGHTTRELLIS

$bg = array(
	'fill' => array(
		'type' => PHPExcel_Style_Fill::FILL_PATTERN_LIGHTTRELLIS,
		'startcolor' => array('rgb' => '01B050'),
		'endcolor' => array('rgb' => 'f1ee3b'),
	)
);                 
$sheet->getStyle("B2")->applyFromArray($bg);

PHP

PHPExcel_Style_Fill::FILL_PATTERN_LIGHTTRELLIS

PHPExcel_Style_Fill::FILL_PATTERN_LIGHTUP

$bg = array(
	'fill' => array(
		'type' => PHPExcel_Style_Fill::FILL_PATTERN_LIGHTUP,
		'startcolor' => array('rgb' => '01B050'),
		'endcolor' => array('rgb' => 'f1ee3b'),
	)
);                 
$sheet->getStyle("B2")->applyFromArray($bg);

PHP

PHPExcel_Style_Fill::FILL_PATTERN_LIGHTUP

PHPExcel_Style_Fill::FILL_PATTERN_LIGHTVERTICAL

$bg = array(
	'fill' => array(
		'type' => PHPExcel_Style_Fill::FILL_PATTERN_LIGHTVERTICAL,
		'startcolor' => array('rgb' => '01B050'),
		'endcolor' => array('rgb' => 'f1ee3b'),
	)
);                 
$sheet->getStyle("B2")->applyFromArray($bg);

PHP

PHPExcel_Style_Fill::FILL_PATTERN_LIGHTVERTICAL

PHPExcel_Style_Fill::FILL_PATTERN_MEDIUMGRAY

$bg = array(
	'fill' => array(
		'type' => PHPExcel_Style_Fill::FILL_PATTERN_MEDIUMGRAY,
		'startcolor' => array('rgb' => '01B050'),
		'endcolor' => array('rgb' => 'f1ee3b'),
	)
);                 
$sheet->getStyle("B2")->applyFromArray($bg);

PHP

PHPExcel_Style_Fill::FILL_PATTERN_MEDIUMGRAY

7

Границы

Стили линий задаются костантами:

Вид Константа
PHPExcel_Style_Border::BORDER_NONE
PHPExcel_Style_Border::BORDER_THIN
PHPExcel_Style_Border::BORDER_MEDIUM
PHPExcel_Style_Border::BORDER_THICK
PHPExcel_Style_Border::BORDER_DOUBLE
PHPExcel_Style_Border::BORDER_HAIR
PHPExcel_Style_Border::BORDER_DOTTED
PHPExcel_Style_Border::BORDER_DASHED
PHPExcel_Style_Border::BORDER_DASHDOT
PHPExcel_Style_Border::BORDER_DASHDOTDOT
PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT
PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT
PHPExcel_Style_Border::BORDER_MEDIUMDASHED
PHPExcel_Style_Border::BORDER_SLANTDASHDOT

Внешняя рамка у ячеек

$border = array(
	'borders'=>array(
		'outline' => array(
			'style' => PHPExcel_Style_Border::BORDER_THIN,
			'color' => array('rgb' => '000000')
		),
	)
);

$sheet->getStyle("B2:J5")->applyFromArray($border);

PHP

Внешняя рамка у ячеек

Внутриния рамка у ячеек

$border = array(
	'borders'=>array(
		'inside' => array(
			'style' => PHPExcel_Style_Border::BORDER_THIN,
			'color' => array('rgb' => '000000')
		),
	)
);

$sheet->getStyle("B2:J5")->applyFromArray($border);

PHP

Внутриния рамка у ечеек

Таблица

$border = array(
	'borders'=>array(
		'allborders' => array(
			'style' => PHPExcel_Style_Border::BORDER_THIN,
			'color' => array('rgb' => '000000')
		)
	)
);

$sheet->getStyle("B2:J5")->applyFromArray($border);

PHP

Таблица

Таблица с жирной рамкой

$border = array(
	'borders'=>array(
		'outline' => array(
			'style' => PHPExcel_Style_Border::BORDER_THICK,
			'color' => array('rgb' => '000000')
		),
		'allborders' => array(
			'style' => PHPExcel_Style_Border::BORDER_THIN,
			'color' => array('rgb' => '000000')
		)
	)
);

$sheet->getStyle("B2:J5")->applyFromArray($border);

PHP

Таблица с жирной рамкой

Отдельные линии

            case '':
			case 'bottom':
			case 'diagonal':
			case 'horizontal':
			case '':
			case 'left':
			case '':
			case 'right':
			case 'top':
			case 'vertical':

Сверху:

$border = array(
	'borders'=>array(
		'top' => array(
			'style' => PHPExcel_Style_Border::BORDER_THIN,
			'color' => array('rgb' => '000000')
		)
	)
);
$sheet->getStyle("B2")->applyFromArray($border);

PHP

Снизу:

$border = array(
	'borders'=>array(
		'bottom' => array(
			'style' => PHPExcel_Style_Border::BORDER_THIN,
			'color' => array('rgb' => '000000')
		)
	)
);
$sheet->getStyle("B4")->applyFromArray($border);

PHP

Слева:

$border = array(
	'borders'=>array(
		'left' => array(
			'style' => PHPExcel_Style_Border::BORDER_THIN,
			'color' => array('rgb' => '000000')
		)
	)
);
$sheet->getStyle("B6")->applyFromArray($border);

PHP

Справа:

$border = array(
	'borders'=>array(
		'right' => array(
			'style' => PHPExcel_Style_Border::BORDER_THIN,
			'color' => array('rgb' => '000000')
		)
	)
);
$sheet->getStyle("B8")->applyFromArray($border);

PHP

Отдельные линии

8

Изображения

$objDrawing = new PHPExcel_Worksheet_Drawing();
$objDrawing->setResizeProportional(false);  
$objDrawing->setName('Название картинки');
$objDrawing->setDescription('Описание картинки');
$objDrawing->setPath(__DIR__ . '/logo.png');
$objDrawing->setCoordinates('B2');                      
$objDrawing->setOffsetX(10); 
$objDrawing->setOffsetY(10);                
$objDrawing->setWidth(163); 
$objDrawing->setHeight(50); 
$objDrawing->setWorksheet($sheet);

PHP

Изображения в PHPExcel

9

$sheet->setCellValue("A1", "Ссылка на example.com");
$sheet->getCell("A1")->getHyperlink()->setUrl("http://example.com");
$sheet->getCell("A1")->getHyperlink()->setTooltip('Подсказка');

// У текста нужно сделать синий цвет и подчеркивание
$sheet->getStyle("A1")->applyFromArray(
	array(
		'font' => array(
			'color' => array(
				'rgb' => '0000FF'
			), 
			'underline' => 'single'
		)
	)
);

PHP

Гиперссылка в PHPExcel

10

Формулы

Русские названия функций не поддерживаются, придется использовать латинские аналоги.

$sheet->setCellValue("A3", "=SUM(A1:A2)");

PHP

СУММ SUM Cуммирование значений в ячейках
ЕСЛИ IF Условие
ПРОСМОТР LOOKUP Поиск по значению
ВПР VLOOKUP Поиск значения по диапазону
ПОИСКПОЗ MATCH Поиск положенияв диапазоне ячеек
ВЫБОР CHOOSE Выбор одного значения из списка
ДАТА DATE Возвращает порядковый номер определенной даты
ДНИ DAYS Возвращает число дней между двумя датами
НАЙТИ, НАЙТИБ FIND, FINDB Поиск вхождения одной строки в другую
ИНДЕКС INDEX Возвращает значение или ссылку на него из таблицы или диапазона

11

Сохранение

XLSX

Отдача на скачивание:

header("Expires: Mon, 1 Apr 1974 05:00:00 GMT");
header("Last-Modified: " . gmdate("D,d M YH:i:s") . " GMT");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
header("Content-type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
header("Content-Disposition: attachment; filename=file.xlsx");

$objWriter = new PHPExcel_Writer_Excel2007($xls);
$objWriter->save('php://output'); 
exit();	

PHP

Если возникает ошибка – «Uncaught exception 'PHPExcel_Writer_Exception' with message 'Could not close zip file php://output.'», то следует сделать скачивание через временный файл:

header("Expires: Mon, 1 Apr 1974 05:00:00 GMT");
header("Last-Modified: " . gmdate("D,d M YH:i:s") . " GMT");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
header("Content-type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
header("Content-Disposition: attachment; filename=file.xlsx");

$file_path = __DIR__ . "/xlsx.tmp";
$objWriter = new PHPExcel_Writer_Excel2007($xls);
$objWriter->save($file_path);
readfile($file_path);
unlink($file_path);
exit();

PHP

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

$objWriter = new PHPExcel_Writer_Excel2007($xls);
$objWriter->save(__DIR__ . '/file.xlsx');

PHP

XLS (Excel 97-2004)

Отдача на скачивание:

header("Expires: Mon, 1 Apr 1974 05:00:00 GMT");
header("Last-Modified: " . gmdate("D,d M YH:i:s") . " GMT");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
header("Content-type: application/vnd.ms-excel");
header("Content-Disposition: attachment; filename=file.xls");
	
$objWriter = new PHPExcel_Writer_Excel5($xls);
$objWriter->save('php://output'); 
exit();	

PHP

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

$objWriter = new PHPExcel_Writer_Excel5($xls);
$objWriter->save(__DIR__ . '/file.xls');

PHP

As others have mentioned, PhpSpreadsheet provides a nice library for this. Assuming you have it installed via composer and the vendor/autoload.php has been included in your project, you can use the function below to generate an xlsx from an array of arrays. I’ve included extensive comments here to help teach beginners about how PhpSpreadsheet works and what the code is doing:

function writeXLSX($filename, $rows, $keys = [], $formats = []) {
    // instantiate the class
    $doc = new PhpOfficePhpSpreadsheetSpreadsheet();
    $sheet = $doc->getActiveSheet();

    // $keys are for the header row.  If they are supplied we start writing at row 2
    if ($keys) {
        $offset = 2;
    } else {
        $offset = 1;
    }

    // write the rows
    $i = 0;
    foreach($rows as $row) {
        $doc->getActiveSheet()->fromArray($row, null, 'A' . ($i++ + $offset));
    }

    // write the header row from the $keys
    if ($keys) {
        $doc->setActiveSheetIndex(0);
        $doc->getActiveSheet()->fromArray($keys, null, 'A1');
    }

    // get last row and column for formatting
    $last_column = $doc->getActiveSheet()->getHighestColumn();
    $last_row = $doc->getActiveSheet()->getHighestRow();

    // autosize all columns to content width
    for ($i = 'A'; $i <= $last_column; $i++) {
        $doc->getActiveSheet()->getColumnDimension($i)->setAutoSize(TRUE);
    }

    // if $keys, freeze the header row and make it bold
    if ($keys) {
        $doc->getActiveSheet()->freezePane('A2');
        $doc->getActiveSheet()->getStyle('A1:' . $last_column . '1')->getFont()->setBold(true);
    }
    
    // format all columns as text
    $doc->getActiveSheet()->getStyle('A2:' . $last_column . $last_row)->getNumberFormat()->setFormatCode(PhpOfficePhpSpreadsheetStyleNumberFormat::FORMAT_TEXT);
    if ($formats) {
        // if there are user supplied formats, set each column format accordingly
        // $formats should be an array with column letter as key and one of the PhpOffice constants as value
        // https://phpoffice.github.io/PhpSpreadsheet/1.2.1/PhpOffice/PhpSpreadsheet/Style/NumberFormat.html
        // EXAMPLE:
        // ['C' => PhpOfficePhpSpreadsheetStyleNumberFormat::FORMAT_NUMBER_00, 'D' => PhpOfficePhpSpreadsheetStyleNumberFormat::FORMAT_NUMBER_00]
        foreach ($formats as $col => $format) {
            $doc->getActiveSheet()->getStyle($col . $offset . ':' . $col . $last_row)->getNumberFormat()->setFormatCode($format);
        }
    }

    // write and save the file
    $writer = new PhpOfficePhpSpreadsheetWriterXlsx($doc);
    $writer->save($filename);
}

EXAMPLE USAGE:

$rows = [
    ['sku' => 'A123', 'price' => '99'],
    ['sku' => 'B456', 'price' => '5.35'],
    ['sku' => 'C789', 'price' => '17.7']
];
$keys = array_keys(current($rows));
$formats = ['B' => PhpOfficePhpSpreadsheetStyleNumberFormat::FORMAT_NUMBER_00];

writeXLSX('pricelist.xlsx', $rows, $keys, $formats);

Привет! Однажды у меня возникала задача по генерации отчетов в Excel на backend’е, которую я решил и теперь могу поделиться одним из способов создания документов Excel и добавлением в них данных средствами PHP.

Существует несколько библиотек для работы с xls файлами на PHP, но мы рассмотрим PHPExcel, попробуем создать файл xls, наполнить его данными и немного оформить стиль, то есть разберемся с базовым функционалом, которого будет достаточно для выполнения многих задач связанных с генерацией документов Excel на PHP. Однако, библиотека позволяет делать многое, в том числе работать с формулами, применять различные стили оформления, работать с листами.

Код скрипта, который вы увидите по ходу прочтения статьи, доступен на github.

Библиотека PHPExcel доступна в Composer как PHPOffice/PHPExcel. Я инициализирую в пустом каталоге composer и добавлю в зависимости PHPOffice/PHPExcel.

$ composer init
$ composer require PHPOffice/PHPExcel

После создам файл generator.php и в нем подключу автозагрузку библиотек Composer’а.

<?php

require './vendor/autoload.php';

Теперь можно приступить к работе, используя библиотеку PHPExcel.

Давайте создадим пустой документ со списком котов «CatList».

$document = new PHPExcel();
$objWriter = PHPExcel_IOFactory::createWriter($document, 'Excel5');

$objWriter->save("CatList.xls");

Мы создали экземпляр класса PHPExcell и создали объект, используя фабрику, который занимается сохранением документов. Кстати, вторым аргументом метода createWriter можно передавать значение «PDF» и таким образом генерировать PDF файлы средствами PHP.

После запуска скрипта в директории появился файл CatList.xls, его можно открыть в Excel и убедиться, что он пустой и программа его открывает без ошибок.

Заполнение Excel документа данными

Давайте попробуем засунуть в файл список котов, создав три столбца с порядковым номером, именем и цветом шерстки. Сперва нам нужны исходные данные, их мы создадим вручную в виде массива

$catList = [
	['name' => 'Tom', 'color' => 'red'],
	['name' => 'Bars', 'color' => 'white'],
	['name' => 'Jane', 'color' => 'Yellow'],
];

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

$document = new PHPExcel();

$sheet = $document->setActiveSheetIndex(0); // Выбираем первый лист в документе

$columnPosition = 0; // Начальная координата x
$startLine = 2; // Начальная координата y

// Вставляем заголовок в "A2" 
$sheet->setCellValueByColumnAndRow($columnPosition, $startLine, 'Our cats');

// Выравниваем по центру
$sheet->getStyleByColumnAndRow($columnPosition, $startLine)->getAlignment()->setHorizontal(
    PHPExcel_Style_Alignment::HORIZONTAL_CENTER);

// Объединяем ячейки "A2:C2"
$document->getActiveSheet()->mergeCellsByColumnAndRow($columnPosition, $startLine, $columnPosition+2, $startLine);

// Перекидываем указатель на следующую строку
$startLine++;

На выходе получаем документ с заголовком, вставленным в объединенную ячейку по центру. Перейдем к отрисовке шапки.

// Массив с названиями столбцов
$columns = ['№', 'Name', 'Color'];

// Указатель на первый столбец
$currentColumn = $columnPosition;

// Формируем шапку
foreach ($columns as $column) {
    // Красим ячейку
    $sheet->getStyleByColumnAndRow($currentColumn, $startLine)
        ->getFill()
        ->setFillType(PHPExcel_Style_Fill::FILL_SOLID)
        ->getStartColor()
        ->setRGB('4dbf62');

    $sheet->setCellValueByColumnAndRow($currentColumn, $startLine, $column);

    // Смещаемся вправо
    $currentColumn++;
}

На выходе получаем

Шапка документа

Шапка документа

Перейдем к заполнению данными из списка наших котов.

// Формируем список
foreach ($catList as $key=>$catItem) {
	// Перекидываем указатель на следующую строку
    $startLine++;
    // Указатель на первый столбец
    $currentColumn = $columnPosition;
    // Вставляем порядковый номер
    $sheet->setCellValueByColumnAndRow($currentColumn, $startLine, $key+1);

    // Ставляем информацию об имени и цвете
    foreach ($catItem as $value) {
        $currentColumn++;
    	$sheet->setCellValueByColumnAndRow($currentColumn, $startLine, $value);
    }
}

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

Список котов

Список котов

Весь код скрипта

<?php

require './vendor/autoload.php';

$catList = [
	['name' => 'Tom', 'color' => 'red'],
	['name' => 'Bars', 'color' => 'white'],
	['name' => 'Jane', 'color' => 'Yellow'],
];

$document = new PHPExcel();

$sheet = $document->setActiveSheetIndex(0); // Выбираем первый лист в документе

$columnPosition = 0; // Начальная координата x
$startLine = 2; // Начальная координата y

// Вставляем заголовок в "A2" 
$sheet->setCellValueByColumnAndRow($columnPosition, $startLine, 'Our cats');

// Выравниваем по центру
$sheet->getStyleByColumnAndRow($columnPosition, $startLine)->getAlignment()->setHorizontal(
    PHPExcel_Style_Alignment::HORIZONTAL_CENTER);

// Объединяем ячейки "A2:C2"
$document->getActiveSheet()->mergeCellsByColumnAndRow($columnPosition, $startLine, $columnPosition+2, $startLine);

// Перекидываем указатель на следующую строку
$startLine++;

// Массив с названиями столбцов
$columns = ['№', 'Name', 'Color'];

// Указатель на первый столбец
$currentColumn = $columnPosition;

// Формируем шапку
foreach ($columns as $column) {
    // Красим ячейку
    $sheet->getStyleByColumnAndRow($currentColumn, $startLine)
        ->getFill()
        ->setFillType(PHPExcel_Style_Fill::FILL_SOLID)
        ->getStartColor()
        ->setRGB('4dbf62');

    $sheet->setCellValueByColumnAndRow($currentColumn, $startLine, $column);

    // Смещаемся вправо
    $currentColumn++;
}

// Формируем список
foreach ($catList as $key=>$catItem) {
	// Перекидываем указатель на следующую строку
    $startLine++;
    // Указатель на первый столбец
    $currentColumn = $columnPosition;
    // Вставляем порядковый номер
    $sheet->setCellValueByColumnAndRow($currentColumn, $startLine, $key+1);

    // Ставляем информацию об имени и цвете
    foreach ($catItem as $value) {
        $currentColumn++;
    	$sheet->setCellValueByColumnAndRow($currentColumn, $startLine, $value);
    }
}

$objWriter = PHPExcel_IOFactory::createWriter($document, 'Excel5');
$objWriter->save("CatList.xls");

PHPExcel — библиотека для создания и чтения данных из файлов формата OpenXML (который используется в MS Excel 2007). С ее помощью можно считывать из файлов, записывать в файлы, форматировать содержимое, работать с формулами и т.д. Для работы PHPExcel требуется версия PHP 5.2 или выше, с установленными библиотеками Zip, XML и GD2.

Установка PHPExcel

Первым делом библиотеку необходимо скачать. Для этого переходим на официальный сайт библиотеки и скачиваем архив PHPExcel-1.7.8.zip. После распаковки мы получим несколько файлов и папок:

  • Classes
  • Documentation
  • Tests
  • changelog.txt
  • install.txt
  • license.txt

Файлы — это различные описания по предыдущим версиям, лицензионное соглашение и очень краткая инструкция по установке. Далее, в папке Classes, содержится непосредственно сама библиотека PHPExcel — эту папку необходимо скопировать в корень нашего скрипта.

В папке Documentation содержится документация по библиотеке на английском языке. В папке Tests — примеры по использованию библиотеки.

Создание Excel-файла

Итак, давайте создадим файл makeexcel.php и начинаем работать с ним. Для начала нам необходимо подключить главный файл библиотеки PHPExcel.php (который находится в папке Classes) и создать объект класса PHPExcel:

require_once 'Classes/PHPExcel.php';
$pExcel = new PHPExcel();

Настройки листа книги Excel

Документ Excel состоит из книг, а каждая книга в свою очередь, состоит из листов. Далее лист состоит из набора ячеек, доступ к которым осуществляется по координатам. То есть у нас есть столбцы, которые имеют буквенные имена (А, В, С и т.д) и есть строки, которые пронумерованы. Значит, что бы получить доступ к первой ячейке нужно указать код А1. Точно также мы с помощью библиотеки будем получать доступ к каждой ячейке.

Итак, первым делом необходимо выбрать активный лист, на который мы будем выводить данные и получить объект этого листа:

$pExcel->setActiveSheetIndex(0);
$aSheet = $pExcel->getActiveSheet();

С помощью метода setActiveSheetIndex(0) указываем индекс (номер) активного листа. Нумерация листов начинается с нуля. Далее с помощью метода getActiveSheet() получаем объект этого активного листа, то есть другими словами получаем доступ к нему для работы. И сохраняем этот объект в переменную $aSheet.

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

$pExcel->createSheet();

Затем, по аналогии, указываем индекс и получаем объект активного листа.

// Ориентация страницы и  размер листа
$aSheet->getPageSetup()
       ->setOrientation(PHPExcel_Worksheet_PageSetup::ORIENTATION_PORTRAIT);
$aSheet->getPageSetup()
       ->SetPaperSize(PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4);
// Поля документа
$aSheet->getPageMargins()->setTop(1);
$aSheet->getPageMargins()->setRight(0.75);
$aSheet->getPageMargins()->setLeft(0.75);
$aSheet->getPageMargins()->setBottom(1);
// Название листа
$aSheet->setTitle('Прайс-лист');
// Шапка и футер (при печати)
$aSheet->getHeaderFooter()
       ->setOddHeader('&CТД ТИНКО: прайс-лист');
$aSheet->getHeaderFooter()
       ->setOddFooter('&L&B'.$aSheet->getTitle().'&RСтраница &P из &N');
// Настройки шрифта
$pExcel->getDefaultStyle()->getFont()->setName('Arial');
$pExcel->getDefaultStyle()->getFont()->setSize(8);

Вначале задаем ориентацию листа при помощи метода setOrientation(), которому передаем константу класса PHPExcel_Worksheet_PageSetup:

  • ORIENTATION_PORTRAIT — книжная
  • ORIENTATION_LANDSCAPE — альбомная

Обратите внимание, что перед методом setOrientation() необходимо вызвать метод getPageSetup(), который предоставляет доступ к настройкам страницы.

Далее вызываем метод SetPaperSize(), который позволяет задать размер страницы для печати. Ему передаем параметром константу PAPERSIZE_A4 класса PHPExcel_Worksheet_PageSetup. Что означает, что размер листа страницы будет установлен А4.

Далее устанавливаем поля документа, то есть отступы от краев документа. Отступы задаются в специальных символьных единицах. Вначале, обратите внимание, вызываем у объекта $aSheet метод getPageMargins(), который вернет объект класса, отвечающего за настройки полей страницы. Затем вызываем методы setTop(), setRight(), setLeft() и setBottom().

Далее при помощи метода setTitle(‘Прайс лист’) задаем название нашего листа.

Если нужно, можно при печати выводить шапку и подвал листа:

  • setOddHeader();
  • setOddFooter();

Обратите внимание на передаваемые параметры:

  • для шапки передаем строку ‘&CТД ТИНКО: прайс-лист’; метка &C означает, что текст нужно расположить по центру.
  • для подвала передаем строку ‘&L&B’.$aSheet->getTitle().’&RСтраница &P из &N’; это означает, что нужно вывести слева и жирным шрифтом (&L&B) название листа (метод $aSheet->getTitle()), затем справа (&R) вывести номер страницы (&P) из общего количества страниц (&N).

Затем указываем настройки шрифта по умолчанию:

  • setName(‘Arial’) — задаем имя шрифта;
  • setSize(8) — задаем размер шрифта.

Наполнение документа данными

Для начала давайте зададим ширину столбцов (в символьных единицах), которые нам понадобятся:

$aSheet->getColumnDimension('A')->setWidth(3);
$aSheet->getColumnDimension('B')->setWidth(7);
$aSheet->getColumnDimension('C')->setWidth(20);
$aSheet->getColumnDimension('D')->setWidth(40);
$aSheet->getColumnDimension('E')->setWidth(10);

Теперь заполним несколько ячеек текстом:

$aSheet->mergeCells('A1:E1');
$aSheet->getRowDimension('1')->setRowHeight(20);
$aSheet->setCellValue('A1','ТД ТИНКО');
$aSheet->mergeCells('A2:E2');
$aSheet->setCellValue('A2','Поставка технических средств безопасности');
$aSheet->mergeCells('A4:C4');
$aSheet->setCellValue('A4','Дата создания прайс-листа');

Здесь мы сначала объеденяем ячейки с А1 до E1 при помощи метода mergeCells(), далее задаем высоту строки: вначале получаем доступ к строке 1 при помощи метода getRowDimension(‘1’), затем задаем высоту — setRowHeight(20). Далее при помощи метода setCellValue(‘A1′,’ТД ТИНКО’), устанавливаем значение ячейки А1.

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

Далее давайте в ячейку D4 запишем текущую дату:

// Записываем данные в ячейку
$date = date('d-m-Y');
$aSheet->setCellValue('D4',$date);
// Устанавливает формат данных в ячейке (дата вида дд-мм-гггг)
$aSheet->getStyle('D4')->getNumberFormat()
->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX14);

С помощью констант, определенных в классе PHPExcel_Style_NumberFormat, можно задать формат ячейки: FORMAT_GENERAL (общий), FORMAT_TEXT (текст), FORMAT_NUMBER (число), FORMAT_NUMBER_00 (число с дробной частью), FORMAT_PERCENTAGE (процент), FORMAT_PERCENTAGE_00 (процент с дробной частью) и т.п.

Теперь, используя метод setCellValue(), а также цикл while() наполним данными наш прайс-лист:

mysql_connect(DB_HOST, DB_USER, DB_PASS);
mysql_query('SET NAMES utf8');
mysql_select_db(DB_NAME);

// Создаем шапку таблички данных
$aSheet->setCellValue('A6','№');
$aSheet->setCellValue('B6','Код');
$aSheet->setCellValue('C6','Наименование');
$aSheet->setCellValue('D6','Описание');
$aSheet->setCellValue('E6','Цена');

$query = "SELECT `code`, `name`, `description`, `price` FROM `products` WHERE 1 LIMIT 10";
$res = mysql_query( $query );

$i = 1;
while( $prd = mysql_fetch_assoc($res) ) {
    $aSheet->setCellValue('A'.($i+6), $i);
    $aSheet->setCellValue('B'.($i+6), $prd['code']);
    $aSheet->setCellValue('C'.($i+6), $prd['name']);
    $aSheet->setCellValue('D'.($i+6), $prd['description']);
    $aSheet->setCellValue('E'.($i+6), $prd['price']);
    $i++;
}

Стилизация данных

Давайте немного украсим наш прайс-лист, то есть каждой ячейке добавим стилей. Для этого необходимо создать массив со стилями и при помощи метода applyFromArray(), применить этот массив к ячейке (или ячейкам):

// массив стилей
$style_wrap = array(
    // рамки
    'borders'=>array(
        // внешняя рамка
        'outline' => array(
            'style'=>PHPExcel_Style_Border::BORDER_THICK,
            'color' => array(
                'rgb'=>'006464'
            )
        ),
        // внутренняя
        'allborders'=>array(
            'style'=>PHPExcel_Style_Border::BORDER_THIN,
            'color' => array(
                'rgb'=>'CCCCCC'
            )
        )
    )
);

$aSheet->getStyle('A1:F'.($i+5))->applyFromArray($style_wrap);

Теперь, по аналогии, применим стили к остальным ячейкам:

// Стили для верхней надписи (первая строка)
$style_header = array(
    // Шрифт
    'font'=>array(
        'bold' => true,
        'name' => 'Times New Roman',
        'size' => 15,
        'color'=>array(
            'rgb' => '006464'
        )
    ),
    // Выравнивание
    'alignment' => array(
        'horizontal' => PHPExcel_STYLE_ALIGNMENT::HORIZONTAL_CENTER,
        'vertical' => PHPExcel_STYLE_ALIGNMENT::VERTICAL_CENTER,
    ),
    // Заполнение цветом
    'fill' => array(
        'type' => PHPExcel_STYLE_FILL::FILL_SOLID,
        'color'=>array(
            'rgb' => '99CCCC'
        )
    ),
    'borders'=>array(
        'bottom'=>array(
            'style'=>PHPExcel_Style_Border::BORDER_THIN,
            'color' => array(
                'rgb'=>'006464'
            )
        )
    )
);
$aSheet->getStyle('A1:E1')->applyFromArray($style_header);

// Стили для слогана компании (вторая строка)
$style_slogan = array(
    // шрифт
    'font'=>array(
        'bold' => true,
        'italic' => true,
        'name' => 'Times New Roman',
        'size' => 12,
        'color'=>array(
            'rgb' => '006464'
        )
    ),
    // выравнивание
    'alignment' => array(
        'horizontal' => PHPExcel_STYLE_ALIGNMENT::HORIZONTAL_CENTER,
        'vertical' => PHPExcel_STYLE_ALIGNMENT::VERTICAL_CENTER,
    ),
    // заполнение цветом
    'fill' => array(
        'type' => PHPExcel_STYLE_FILL::FILL_SOLID,
        'color'=>array(
            'rgb' => '99CCCC'
        )
    ),
    //рамки
    'borders' => array(
        'bottom' => array(
            'style'=>PHPExcel_Style_Border::BORDER_THIN,
            'color' => array(
                'rgb'=>'006464'
            )
        )
    )
);
$aSheet->getStyle('A2:E2')->applyFromArray($style_slogan);

// Стили для текта возле даты
$style_tdate = array(
    // выравнивание
    'alignment' => array(
        'horizontal' => PHPExcel_STYLE_ALIGNMENT::HORIZONTAL_RIGHT,
    ),
    // заполнение цветом
    'fill' => array(
        'type' => PHPExcel_STYLE_FILL::FILL_SOLID,
        'color'=>array(
            'rgb' => 'EEEEEE'
        )
    ),
    // рамки
    'borders' => array(
        'right' => array(
            'style'=>PHPExcel_Style_Border::BORDER_NONE
        )
    )
);
$aSheet->getStyle('A4:D4')->applyFromArray($style_tdate);
 
// Стили для даты
$style_date = array(
    // заполнение цветом
    'fill' => array(
        'type' => PHPExcel_STYLE_FILL::FILL_SOLID,
        'color'=>array(
            'rgb' => 'EEEEEE'
        )
    ),
    // рамки
    'borders' => array(
        'left' => array(
            'style'=>PHPExcel_Style_Border::BORDER_NONE
        )
    ),
);
$aSheet->getStyle('E4')->applyFromArray($style_date);
 
// Стили для шапки таблицы (шестая строка)
$style_hprice = array(
    // выравнивание
    'alignment' => array(
    'horizontal' => PHPExcel_STYLE_ALIGNMENT::HORIZONTAL_CENTER,
    ),
    // заполнение цветом
    'fill' => array(
        'type' => PHPExcel_STYLE_FILL::FILL_SOLID,
        'color'=>array(
            'rgb' => 'CFCFCF'
        )
    ),
    // шрифт
    'font'=>array(
        'bold' => true,
        /* 'italic' => true, */
        'name' => 'Times New Roman',
        'size' => 10
    ),
);
$aSheet->getStyle('A6:E6')->applyFromArray($style_hprice);

// Cтили для данных в таблице прайс-листа
$style_price = array(
    'alignment' => array(
    'horizontal' => PHPExcel_STYLE_ALIGNMENT::HORIZONTAL_LEFT,
    )
);
$aSheet->getStyle('A7:E'.($i+5))->applyFromArray($style_price);

Сохранение документа

Осталось только сохранить наш документ:

/*
$objWriter = PHPExcel_IOFactory::createWriter($pExcel, 'Excel5');
$objWriter->save('simple.xls');
*/
$objWriter = PHPExcel_IOFactory::createWriter($pExcel, 'Excel2007');
$objWriter->save('simple.xlsx');

или так

/*
$objWriter = new PHPExcel_Writer_Excel5($pExcel);
$objWriter->save('simple.xls');
*/
$objWriter = new PHPExcel_Writer_Excel2007($pExcel);
$objWriter->save('simple.xlsx');

Если нужно вывести документ в браузер

/*
header('Content-Type:application/vnd.ms-excel');
header('Content-Disposition:attachment;filename="simple.xls"');
$objWriter = new PHPExcel_Writer_Excel5($pExcel);
*/
header('Content-Type:xlsx:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition:attachment;filename="simple.xlsx"');
$objWriter = new PHPExcel_Writer_Excel2007($pExcel);
$objWriter->save('php://output');

Первый заголовок указывает браузеру тип открываемого контента — это документ формата Excel. Второй — говорит браузеру, что документ необходимо отдать пользователю на скачивание под именем simple.xlsx.

Добавление формул

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

Использование ссылок на ячейки позволяет пересчитывать результат по формулам, когда происходят изменения содержимого ячеек, включенных в формулы. Формулы Excel начинаются со знака =. Скобки ( ) могут использоваться для определения порядка математических операции.

Примеры формул Excel: =27+36, =А1+А2-АЗ, =SUM(А1:А5), =MAX(АЗ:А5), =(А1+А2)/АЗ.

PHPExcel тоже поддерживает добавление формул в ячейки. Установить формулу можно так:

// формула для вычисления суммы
$formula = '=SUM(D2:D4)';
$aSheet->setCellValue('D5', $formula);

Добавление формул

Чтение Excel-файла

Самый простой вариант — считать все таблицы (на всех листах) и записать данные в трехмерный массив:

// Подключаем библиотеку
require_once 'Classes/PHPExcel.php';
$pExcel = PHPExcel_IOFactory::load('simple.xlsx');

// Цикл по листам Excel-файла
foreach ($pExcel->getWorksheetIterator() as $worksheet) {
    // выгружаем данные из объекта в массив
    $tables[] = $worksheet->toArray();
}

Теперь можно вывести массив:

// Цикл по листам Excel-файла
foreach( $tables as $table ) {
    echo '<table border="1">';
    // Цикл по строкам
    foreach($table as $row) {
        echo '<tr>';
        // Цикл по колонкам
        foreach( $row as $col ) {
            echo '<td>'.$col.'</td>';
        }
        echo '</tr>';
    }
    echo '</table>';
}

Для получения значения отдельной ячейки:

// выбираем лист, с которым будем работать
$pExcel->setActiveSheetIndex(0);
$aSheet = $pExcel->getActiveSheet();
// получаем доступ к ячейке по номеру строки 
// (нумерация с единицы) и столбца (нумерация с нуля) 
$cell = $aSheet->getCellByColumnAndRow($col, $row);
// читаем значение ячейки
$value = $cell->getValue()

или так:

$value = $pExcel->getActiveSheet()->getCellValue('B2')

Еще два примера:

// Цикл по листам Excel-файла
foreach( $pExcel->getWorksheetIterator() as $worksheet ) {
    echo '<h2>Лист «'.$worksheet->getTitle().'»</h2>';
    echo '<table border="1">';
    // Цикл по строкам
    foreach( $worksheet->getRowIterator() as $row ) {
        echo '<tr>';
        // Цикл по колонкам
        foreach( $row->getCellIterator() as $cell ) {
            $value = $cell->getValue();
            // $calcValue = $cell->getCalculatedValue()
            // $dataType = PHPExcel_Cell_DataType::dataTypeForValue($value);
            echo '<td>'.$value.'</td>';
        }
        echo '</tr>';
    }
    echo '</table>';
}
// Цикл по листам Excel-файла
foreach ($pExcel->getWorksheetIterator() as $worksheet) {
    $worksheetTitle     = $worksheet->getTitle();
    $highestRow         = $worksheet->getHighestRow(); // например, 10
    $highestColumn      = $worksheet->getHighestColumn(); // например, 'E'
    $highestColumnIndex = PHPExcel_Cell::columnIndexFromString($highestColumn);
    $nrColumns = ord($highestColumn) - 64;
    echo '<h2>Лист «'.$worksheetTitle.'» ';
    echo $nrColumns . ' колонок (A-' . $highestColumn . ') ';
    echo ' и ' . $highestRow . ' строк.</h2>';
    echo '<table border="1">';
    // Цикл по строкам
    for ($row = 1; $row <= $highestRow; $row++) {
        echo '<tr>';
        // Цикл по колонкам
        for ($col = 0; $col < $highestColumnIndex; $col++) {
            $cell = $worksheet->getCellByColumnAndRow($col, $row);
            echo '<td>'.$cell->getValue().'</td>';
        }
        echo '</tr>';
    }
    echo '</table>';
}

Дополнительно

  • Документация разработчика PHPExcel на русском
  • Блог на Laravel 7, часть 17. Временная зона для пользователей, деплой на хостинг TimeWeb
  • Блог на Laravel 7, часть 16. Роль нового пользователя, сообщение админу о новом посте
  • Блог на Laravel 7, часть 15. Восстановление постов, slug для категории, поста и страницы
  • Блог на Laravel 7, часть 14. Валидация данных и права доступа при загрузке изображений
  • Блог на Laravel 7, часть 13. Загрузка и ресайз изображений для категорий и постов блога
  • Блог на Laravel 7, часть 12. Доп.страницы сайта в панели управления и в публичной части
  • Блог на Laravel 7, часть 11. Панель управления — назначение ролей и прав для пользователей

Поиск:
Excel • MS • PHP • Web-разработка

Каталог оборудования

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Производители

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Функциональные группы

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Периодически появляется необходимость, создания excel таблицы средствами php. Например, выгрузить данные из базы, формирование различных отчетов, актов, смет, каталогов и тд.

Встроенных функций в php для этого нет, но на сегодняшний день, для генерации xlsx документов, можно воспользоваться пакетом phpoffice/phpspreadsheet о нем и пойдет речь в данной статье, разберем установку и примеры использования.

Прежде чем приступать к написанию кода, стоит понять, как работает phpoffice/phpspreadsheet, а именно то, что до момента вывода файла в браузер или сохранения на сервер, мы работаем с виртуальной таблицей, по которой можно перемещаться, как по ячейкам Excel, но только в коде.

Структура проекта

Первоначальная структура проекта:

├── Файл index.php
├── Файл composer.json
├── Директория src
   └── Файл Excphp.php

Шаг 1 — Проверка наличия composer

Для начала убедитесь, что у Вас установлен composer, сделать это можно командой, в консоле composer -v

Если видим подобное сообщение в ответ, то можно идти дальше, иначе необходимо установить composer

   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ / __ `__ / __ / __ / ___/ _ / ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
____/____/_/ /_/ /_/ .___/____/____/___/_/
                    /_/
Composer version 2.0.14 2021-05-21 17:03:37

Usage:
  command [options] [arguments]

Options:
  -h, --help                     Display this help message
  -q, --quiet                    Do not output any message
  -V, --version                  Display this application version
      --ansi                     Force ANSI output
      --no-ansi                  Disable ANSI output
  -n, --no-interaction           Do not ask any interactive question
      --profile                  Display timing and memory usage information
      --no-plugins               Whether to disable plugins.
  -d, --working-dir=WORKING-DIR  If specified, use the given directory as working directory.
      --no-cache                 Prevent use of the cache
  -v|vv|vvv, --verbose           Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Available commands:
  about                Shows the short information about Composer.
  archive              Creates an archive of this composer package.
  browse               Opens the package's repository URL or homepage in your browser.
  cc                   Clears composer's internal package cache.
  check-platform-reqs  Check that platform requirements are satisfied.
  clear-cache          Clears composer's internal package cache.
  clearcache           Clears composer's internal package cache.
  config               Sets config options.
  create-project       Creates new project from a package into given directory.
  depends              Shows which packages cause the given package to be installed.
  diagnose             Diagnoses the system to identify common errors.
  dump-autoload        Dumps the autoloader.
  dumpautoload         Dumps the autoloader.
  exec                 Executes a vendored binary/script.
  fund                 Discover how to help fund the maintenance of your dependencies.
  global               Allows running commands in the global composer dir ($COMPOSER_HOME).
  help                 Displays help for a command
  home                 Opens the package's repository URL or homepage in your browser.
  i                    Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json.
  info                 Shows information about packages.
  init                 Creates a basic composer.json file in current directory.
  install              Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json.
  licenses             Shows information about licenses of dependencies.
  list                 Lists commands
  outdated             Shows a list of installed packages that have updates available, including their latest version.
  prohibits            Shows which packages prevent the given package from being installed.
  remove               Removes a package from the require or require-dev.
  require              Adds required packages to your composer.json and installs them.
  run                  Runs the scripts defined in composer.json.
  run-script           Runs the scripts defined in composer.json.
  search               Searches for packages.
  self-update          Updates composer.phar to the latest version.
  selfupdate           Updates composer.phar to the latest version.
  show                 Shows information about packages.
  status               Shows a list of locally modified packages.
  suggests             Shows package suggestions.
  u                    Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.
  update               Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.
  upgrade              Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.
  validate             Validates a composer.json and composer.lock.
  why                  Shows which packages cause the given package to be installed.
  why-not              Shows which packages prevent the given package from being installed.

Итак, composer есть, идем дальше.

Шаг 2 — создаем файл composer.json

Содержимое файла:

{
    "require": {
      "phpoffice/phpspreadsheet": "^1.18"
    },
  "autoload": {
    "psr-4": { "": "src/" }
  }
}

Небольшие пояснения, первая секция загрузит нам phpoffice/phpspreadsheet»: «^1.18, а секция autoload позволит подключать свои классы в проект из директории src, подробнее описано здесь.

Запускаем в консоле команду composer require
из директории, где был создан файл composer.json

Видим подобное сообщение:

 Search for a package: 
./composer.json has been updated
Running composer update 
Loading composer repositories with package information
Updating dependencies
Lock file operations: 11 installs, 0 updates, 0 removals
  - Locking ezyang/htmlpurifier (v4.14.0)
  - Locking maennchen/zipstream-php (2.1.0)
  - Locking markbaker/complex (3.0.1)
  - Locking markbaker/matrix (3.0.0)
  - Locking myclabs/php-enum (1.8.3)
  - Locking phpoffice/phpspreadsheet (1.23.0)
  - Locking psr/http-client (1.0.1)
  - Locking psr/http-factory (1.0.1)
  - Locking psr/http-message (1.0.1)
  - Locking psr/simple-cache (2.0.0)
  - Locking symfony/polyfill-mbstring (v1.25.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 11 installs, 0 updates, 0 removals
  - Downloading psr/simple-cache (2.0.0)
  - Downloading phpoffice/phpspreadsheet (1.23.0)
  - Installing myclabs/php-enum (1.8.3): Extracting archive
  - Installing psr/simple-cache (2.0.0): Extracting archive
  - Installing psr/http-message (1.0.1): Extracting archive
  - Installing psr/http-factory (1.0.1): Extracting archive
  - Installing psr/http-client (1.0.1): Extracting archive
  - Installing markbaker/matrix (3.0.0): Extracting archive
  - Installing markbaker/complex (3.0.1): Extracting archive
  - Installing symfony/polyfill-mbstring (v1.25.0): Extracting archive
  - Installing maennchen/zipstream-php (2.1.0): Extracting archive
  - Installing ezyang/htmlpurifier (v4.14.0): Extracting archive
  - Installing phpoffice/phpspreadsheet (1.23.0): Extracting archive
4 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating autoload files
3 packages you are using are looking for funding.
Use the `composer fund` command to find out more!

В начале сделаем простую табличку, в виде небольшого расчета с материалами и работами, которые мы будем заполнять статично, не как массив в цикле, и сохраним документ. В процессе рассмотрим некоторые методы. Чтобы понять принцип взаимодействия, далее будем усложнять процесс.

Шаг 3 — создаем простой excel документ средствами php

Согласно структуре проекта, описанной в начале статьи, в директории src, создаем файл класса Excphp.php. Его код с комментариями:

<?php

use PhpOfficePhpSpreadsheetSpreadsheet;
use PhpOfficePhpSpreadsheetWriterXlsx;

class Excphp{

    public function genDoc()
    {
        // Создаем новый Spreadsheet объект
        $spreadsheet = new Spreadsheet();

        // Подключение к активной таблице
        $sheet = $spreadsheet->getActiveSheet();

        // Объединяем ячейки от A1:F1
        $sheet->mergeCells("A1:F1");

        // Устанавливаем значение ячейке A1
        $sheet->setCellValue("A1", "Стоимость работ");

        // Установка значений в шапку таблицы
        $sheet->setCellValue("A2", "№ п/п");
        $sheet->setCellValue("B2", "Наименование работ/материалов");
        $sheet->setCellValue("C2", "Ед. изм");
        $sheet->setCellValue("D2", "Кол-во");
        $sheet->setCellValue("E2", "Стоимость");
        $sheet->setCellValue("F2", "Сумма");

        // Установка 1-го ряда значений в таблицу
        $sheet->setCellValue("A3", "1");
        $sheet->setCellValue("B3", "Укладка асфальта");
        $sheet->setCellValue("C3", "м3");
        $sheet->setCellValue("D3", "100");
        $sheet->setCellValue("E3", "500");
        $sheet->setCellValue("F3", "50000");

        // Установка 2-го ряда значений в таблицу
        $sheet->setCellValue("A4", "2");
        $sheet->setCellValue("B4", "Доставка асфальта");
        $sheet->setCellValue("C4", "м3");
        $sheet->setCellValue("D4", "100");
        $sheet->setCellValue("E4", "1000");
        $sheet->setCellValue("F4", "100000");

        // получение текущей даты, будет использоваться в имени файла
        $dt = date("h:i:s");

        // создание объекта Xlsx
        $writer = new Xlsx($spreadsheet);

        // если требуется сохранять файл на сервер, то удалите комментарий у строки ниже
        // $writer->save("file-$dt.xlsx");

        // отправка файла в браузер
        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment;filename="file-'.$dt.'.xlsx"');
        $writer->save('php://output');
    }

}

После создания файла Excphp.php, необходимо выполнить команду, в консоле, в корне проекта composer dump-autoload -o в результате увидим:

Generating optimized autoload files
Generated optimized autoload files containing 765 classes

Зачем это нужно, описано здесь

Также создадим файл index.php, в корне документа, согласно структуры проекта. Его код:

<?php

set_include_path(__DIR__);
require 'vendor/autoload.php';

$obj = new Excphp();

$obj->genDoc();

Если все было сделано, как описано выше, то при открытии в браузере файла index.php, будет происходить автоматическое скачивание файла xlsx, как картинке ниже.

создание excel в php

Первый пример создания файла xlsx реализован, естественно это самое простое, что можно было бы сделать. Основное действие по наполнению документа — это передача значений по координатам, как в обычном excel документе, через метод setCellValue(«F4», «100000») куда передается координата ячейки и значение. По ссылке ниже, можно скачать исходники данного примера. Далее рассмотрим более сложные примеры.

Скачать исходники

После скачивания, распакуйте архив с примером, в директорию с проектом и запустите две команды, в консоле :

  1. composer require
  2. composer dump-autoload -o

Пробуйте и тестируйте!

Шаг 4 — более сложные примеры

В следующем примере заполним таблицу в цикле foreach из подготовленного массива с данными, добавим формулы, и немного стилевого оформления.

Отредактируйте файл index.php, его новый код:

<?php

set_include_path(__DIR__);
require 'vendor/autoload.php';

$arrToWrite = array(
    1 => array(
        "NAME" => "Монтаж металлоконструкций",
        "PRICE" => 100,
        "QUANTITY" => 5,
        "UNIT" => "шт."
    ),
    2 => array(
        "NAME" => "Вывоз мусора",
        "PRICE" => 1000,
        "QUANTITY" => 2,
        "UNIT" => "шт."
    ),
    3 => array(
        "NAME" => "Монтаж кабеля",
        "PRICE" => 120,
        "QUANTITY" => 100,
        "UNIT" => "м.п."
    ),
    4 => array(
        "NAME" => "Монтаж опор освещения",
        "PRICE" => 2500,
        "QUANTITY" => 10,
        "UNIT" => "шт."
    ),
    5 => array(
        "NAME" => "Благоустройство территории",
        "PRICE" => 5500,
        "QUANTITY" => 100,
        "UNIT" => "м2."
    ),
    6 => array(
        "NAME" => "Проектирование",
        "PRICE" => 6000,
        "QUANTITY" => 1,
        "UNIT" => "копмл."
    ),
    7 => array(
        "NAME" => "Щебень фракция 5-20",
        "PRICE" => 5000,
        "QUANTITY" => 10,
        "UNIT" => "м3."
    ),
    8 => array(
        "NAME" => "Цемент",
        "PRICE" => 1000,
        "QUANTITY" => 10,
        "UNIT" => "уп."
    ),
    9 => array(
        "NAME" => "Алебастр",
        "PRICE" => 300,
        "QUANTITY" => 5,
        "UNIT" => "уп."
    ),
);



$obj = new Excphp();

$obj->genDoc($arrToWrite);

Добавили ассоциативный массив, с данными, на практике что-то подобное будет приходить из базы или по API. Этот массив передаем в качестве параметра, методу genDoc

Изменения произошли и в файле класса Excphp.php. Его новый код:

<?php

use PhpOfficePhpSpreadsheetSpreadsheet;
use PhpOfficePhpSpreadsheetWriterXlsx;

class Excphp{

    public function genDoc($arrToWrite)
    {
        // Создаем новый Spreadsheet объект
        $spreadsheet = new Spreadsheet();

        // Подключение к активной таблице
        $sheet = $spreadsheet->getActiveSheet();

        // Объединяем ячейки от A1:F1
        $sheet->mergeCells("A1:F1");

        // Устанавливаем значение ячейке A1
        $sheet->setCellValue("A1", "Стоимость строительный работ");

        // Установка значений в шапку таблицы
        $sheet->setCellValue("A2", "№ п/п");
        $sheet->setCellValue("B2", "Наименование работ/материалов");
        $sheet->setCellValue("C2", "Ед. изм");
        $sheet->setCellValue("D2", "Кол-во");
        $sheet->setCellValue("E2", "Стоимость");
        $sheet->setCellValue("F2", "Сумма");

        // получаем номер последней строки с записью и прибавляем 1, чтобы писать на следующей строке
        $highestRow = $sheet->getHighestRow() + 1;

        // цикл по массиву, наполняем таблицу
        foreach($arrToWrite as $key => $value){
            $sheet->setCellValue("A$highestRow", "$key");
            $sheet->setCellValue("B$highestRow", "{$value['NAME']}");
            $sheet->setCellValue("C$highestRow", "{$value['UNIT']}");
            $sheet->setCellValue("D$highestRow", "{$value['QUANTITY']}");
            $sheet->setCellValue("E$highestRow", "{$value['PRICE']}");
            $sheet->setCellValue("F$highestRow", "=D$highestRow*E$highestRow");

            // увеличиваем значение последней линии
            $highestRow ++;
        }

        // Выведем внизу таблицы итого, еще раз считаем последнюю строку и прибавим единицу
        $highestRow = $sheet->getHighestRow() + 1;

        // Объединяем ячейки от A:E
        $sheet->mergeCells("A$highestRow:E$highestRow");

        // В объединенную ячейку запишем слово "итого"
        $sheet->setCellValue("A$highestRow", "Итого");

        // запишем формулу с суммой, по колонке F, в этом же ряду
        // мы знаем, что начинается наполняться данными таблица с 3-го ряда
        $SUMRANGE = 'F3:F' . ($highestRow - 1);
        $sheet->setCellValue("F$highestRow", "=SUM($SUMRANGE)");

        // увеличим ширину ячейки B (Наименование работ/материалов)
        $sheet->getColumnDimension('B')->setWidth(70);

        // стилевое оформление шапки таблицы
        // подготовка массива для задания стилей
        $styleArray = [
            'font' => [
                'bold' => true,
            ],
            'alignment' => [
                'horizontal' => PhpOfficePhpSpreadsheetStyleAlignment::HORIZONTAL_LEFT,
            ],
            'borders' => [
                'allBorders' => [
                    'borderStyle' => PhpOfficePhpSpreadsheetStyleBorder::BORDER_THIN,
                ],
            ],
            'fill' => [
                'fillType' => PhpOfficePhpSpreadsheetStyleFill::FILL_SOLID,
                'color' => [
                    'rgb' => 'FFFFFF',
                ],
            ],
        ];

        // Установка стилей для строки
        $spreadsheet->getActiveSheet()->getStyle('A2:F2')->applyFromArray($styleArray);

        // получение даты, будет использоваться в имени файла
        $dt = date("h:i:s");

        // создание объекта Xlsx
        $writer = new Xlsx($spreadsheet);

        // если требуется сохранять файл на сервер, то раскомментируйте строку ниже
        // $writer->save("file-$dt.xlsx");

        // отправка файла в браузер
        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment;filename="file-'.$dt.'.xlsx"');
        $writer->save('php://output');
    }

}

В новой редакции файла Excphp.php метод genDoc принимает в качестве аргумента массив, из которого в цикле заполняется таблица. Для наполнения в цикле, был применен метод getHighestRow(), который возвращает номер последней строки, куда были отправлены данные, очень полезный метод, зная это, мы распечатываем массив работ на следующей строке, по своим ячейкам, прибавляя 1 на каждой итерации (инкремент ++). Ячейки F заполняются математическим выражением. Шапка таблицы осталась статичной, к ней были применены стили. В коде я оставил комментарии почти на каждой строчке кода, но если вдруг будут вопросы, пишите в комментариях к статье, постараюсь помочь.

В результате, при открытии файла index.php в браузере, у Вас должен автоматически скачиваться excel документ, как на gif-ке ниже:

Пример 2 создание excel из php

Скачать новый пример, можно по ссылке ниже.

Скачать исходники пример 2

После скачивания, распакуйте архив с примером, в директорию с проектом и запустите две команды, в консоле :

  1. composer require
  2. composer dump-autoload -o

Пробуйте и тестируйте!

Полный список возможного функционала можно посмотреть по ссылке https://phpspreadsheet.readthedocs.io/en/latest/

Статья будет дополнена, по мере поступления вопросов и комментариев. Всем успехов в разработке!

Дополнение к статье, видео процесса, как сделать excel в php


Рекламный блок, для развития проекта

Понравилась статья? Поделить с друзьями:
  • Php content type word
  • Php application vnd ms excel
  • Php and word document
  • Php and microsoft excel
  • Php and excel spreadsheet