SimpleXLSXGen
Export data to Excel XLSX file. PHP XLSX generator. No external tools and libraries.
- XLSX reader here
- XLS reader here
- CSV reader/writer here
Sergey Shuchkin sergey.shuchkin@gmail.com 2020-2023
Hey, bro, please ★ the package for my motivation and donate for more motivation!
Basic Usage
$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 = ShuchkinSimpleXLSXGen::fromArray( $books ); $xlsx->saveAs('books.xlsx'); // or downloadAs('books.xlsx') or $xlsx_content = (string) $xlsx
Installation
The recommended way to install this library is through Composer.
New to Composer?
This will install the latest supported version:
$ composer require shuchkin/simplexlsxgen
or download class here
Examples
Use UTF-8 encoded strings.
Data types
$data = [ ['Integer', 123], ['Float', 12.35], ['Percent', '12%'], ['Currency $', '$500.67'], ['Currency €', '200 €'], ['Currency ₽', '1200.30 ₽'], ['Currency (other)', '<style nf=""£"#,##0.00">500</style>'], ['Datetime', '2020-05-20 02:38:00'], ['Date', '2020-05-20'], ['Time', '02:38:00'], ['Datetime PHP', new DateTime('2021-02-06 21:07:00')], ['String', 'Very long UTF-8 string in autoresized column'], ['Formula', '<f v="135.35">SUM(B1:B2)</f>'], ['Hyperlink', 'https://github.com/shuchkin/simplexlsxgen'], ['Hyperlink + Anchor', '<a href="https://github.com/shuchkin/simplexlsxgen">SimpleXLSXGen</a>'], ['Internal link', '<a href="sheet2!A1">Go to second page</a>'], ['RAW string', "" . '2020-10-04 16:02:00'] ]; SimpleXLSXGen::fromArray($data)->saveAs('datatypes.xlsx');
Formatting
$data = [ ['Normal', '12345.67'], ['Bold', '<b>12345.67</b>'], ['Italic', '<i>12345.67</i>'], ['Underline', '<u>12345.67</u>'], ['Strike', '<s>12345.67</s>'], ['Bold + Italic', '<b><i>12345.67</i></b>'], ['Hyperlink', 'https://github.com/shuchkin/simplexlsxgen'], ['Italic + Hyperlink + Anchor', '<i><a href="https://github.com/shuchkin/simplexlsxgen">SimpleXLSXGen</a></i>'], ['Green', '<style color="#00FF00">12345.67</style>'], ['Bold Red Text', '<b><style color="#FF0000">12345.67</style></b>'], ['Size 32 Font', '<style font-size="32">Big Text</style>'], ['Blue Text and Yellow Fill', '<style bgcolor="#FFFF00" color="#0000FF">12345.67</style>'], ['Border color', '<style border="#000000">Black Thin Border</style>'], ['<top>Border style</top>','<style border="medium"><wraptext>none, thin, medium, dashed, dotted, thick, double, hair, mediumDashed, dashDot,mediumDashDot, dashDotDot, mediumDashDotDot, slantDashDot</wraptext></style>'], ['Border sides', '<style border="none dotted#0000FF medium#FF0000 double">Top No + Right Dotted + Bottom medium + Left double</style>'], ['Left', '<left>12345.67</left>'], ['Center', '<center>12345.67</center>'], ['Right', '<right>Right Text</right>'], ['Center + Bold', '<center><b>Name</b></center>'], ['Row height', '<style height="50">Row Height = 50</style>'], ['Top', '<style height="50"><top>Top</top></style>'], ['Middle + Center', '<style height="50"><middle><center>Middle + Center</center></middle></style>'], ['Bottom + Right', '<style height="50"><bottom><right>Bottom + Right</right></bottom></style>'], ['<center>MERGE CELLS MERGE CELLS MERGE CELLS MERGE CELLS MERGE CELLS</center>', null], ['<top>Word wrap</top>', "<wraptext>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book</wraptext>"], ]; SimpleXLSXGen::fromArray($data) ->setDefaultFont('Courier New') ->setDefaultFontSize(14) ->setColWidth(1, 35) ->mergeCells('A20:B20') ->saveAs('styles_and_tags.xlsx');
RAW Strings
Prefix #0 cell value (use double quotes).
$PushkinDOB = '1799-07-06'; $data = [ ['Datetime as raw string', "".'2023-01-09 11:16:34'], ['Date as raw string', "".$PushkinDOB], ['Disable type detection', "".'+12345'], ['Insert greater/less them simbols', "".'20- short term: <6 month'], ]; SimpleXLSXGen::fromArray($data) ->saveAs('test_rawstrings.xlsx');
More examples
// Fluid interface, output to browser for download ShuchkinSimpleXLSXGen::fromArray( $books )->downloadAs('table.xlsx'); // Fluid interface, multiple sheets ShuchkinSimpleXLSXGen::fromArray( $books )->addSheet( $books2 )->download(); // Alternative interface, sheet name, get xlsx content $xlsx_cache = (string) (new ShuchkinSimpleXLSXGen)->addSheet( $books, 'Modern style'); // Classic interface use ShuchkinSimpleXLSXGen $xlsx = new SimpleXLSXGen(); $xlsx->addSheet( $books, 'Catalog 2021' ); $xlsx->addSheet( $books2, 'Stephen King catalog'); $xlsx->downloadAs('books_2021.xlsx'); exit(); // Autofilter $xlsx->autoFilter('A1:B10'); // Freeze rows and columns from top-left corner up to, but not including, // the row and column of the indicated cell $xlsx->freezePanes('C3'); // RTL mode // Column A is on the far right, Column B is one column left of Column A, and so on. Also, information in cells is displayed in the Right to Left format. $xlsx->rightToLeft();
JS array to Excel (AJAX)
<?php // array2excel.php if (isset($_POST['array2excel'])) { require __DIR__.'/simplexlsxgen/src/SimpleXLSXGen.php'; $data = json_decode($_POST['array2excel'], false); ShuchkinSimpleXLSXGen::fromArray($data)->downloadAs('file.xlsx'); return; } ?> <html lang="en"> <head> <title>JS array to Excel</title> </head> <script> function array2excel() { var books = [ ["ISBN", "title", "author", "publisher", "ctry"], [618260307, "The Hobbit", "J. R. R. Tolkien", "Houghton Mifflin", "USA"], [908606664, "Slinky Malinki", "Lynley Dodd", "Mallinson Rendel", "NZ"] ]; var json = JSON.stringify(books); var request = new XMLHttpRequest(); request.onload = function () { if (this.status === 200) { var file = new Blob([this.response], {type: this.getResponseHeader('Content-Type')}); var fileURL = URL.createObjectURL(file); var filename = "", m; var disposition = this.getResponseHeader('Content-Disposition'); if (disposition && (m = /"([^"]+)"/.exec(disposition)) !== null) { filename = m[1]; } var a = document.createElement("a"); if (typeof a.download === 'undefined') { window.location = fileURL; } else { a.href = fileURL; a.download = filename; document.body.appendChild(a); a.click(); } } else { alert("Error: " + this.status + " " + this.statusText); } } request.open('POST', "array2excel.php"); request.responseType = "blob"; request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); request.send("array2excel=" + encodeURIComponent(json)); } </script> <body> <input type="button" onclick="array2excel()" value="array2excel" /> </body> </html>
Debug
ini_set('error_reporting', E_ALL ); ini_set('display_errors', 1 ); $data = [ ['Debug', 123] ]; ShuchkinSimpleXLSXGen::fromArray( $data )->saveAs('debug.xlsx');
Время на прочтение
3 мин
Количество просмотров 41K
К написанию данного топика меня подтолкнула одна заметка о генерации xls в PHP.
Способ, представленный в той заметке действительно очень прост, но не всегда может быть удобен.
Есть множество других способов передать табличные данные из PHP в Excel, я опишу тот, который показался мне наиболее простым и функциональным. Нужно особенно отметить, что что я не говорю о генерации xls файла, а лишь предлагаю пользователю открыть полученные данные при помощи Excel так, что пользователи не искушённые в программировании не заметят подлога.
Итак, первое что необходимо сделать — разместить на нашей страничке ссылку на скрипт генерирующий следующие заголовки:
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false);
header("Content-Type: application/x-msexcel");
header("Content-Disposition: attachment; filename="" . iconv('UTF-8', 'CP1251', $object->getFileName()) . "";");
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . $object->getFileSize());
$object — сферический объект в вакууме, который каждый читатель реализует так, как ему больше нравится. Назначение геттеров getFileName() и getFileSize() понятно из названий. Здесь стоит выделить один неочевидный нюанс (спасибо savostin за то что напомнил об этом) — getFileName() конечно может возвращать любое имя файла, но если вы хотите что бы браузер предложил открыть полученный контент в Excel, то расширение файла должно быть xls.
Ничего нового я пока не рассказал, все это придумано до меня, впрочем как и то что будет описано ниже.
Как верно было отмечено в комментариях к заметке о генерации xls в PHP, Excel гораздо быстрее работает с XML. Но самое главное преимущество, пожалуй, все же не в скорости, а в гораздо более широких возможностях. Углубляться в дебри я не стану, а лишь приведу простой пример, и ссылку на подробное описание всех тегов.
Итак, после того как заголовки сгенерированны, нам нужно отдать пользователю собственно данные. Я обычно заворачиваю генерацию таблицы в отдельный метод:
echo $object->getContent();
А таблицу генерирую при помощи Smarty:
<?xml version="1.0"?> <?mso-application progid="Excel.Sheet"?> <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40"> <Styles> <Style ss:ID="bold"> <Font ss:Bold="1"/> </Style> </Styles> <Worksheet ss:Name="WorksheetName"> <Table> <Row> {foreach from=$data.header item=caption} <Cell ss:StyleID="bold"><Data ss:Type="String">{$caption.columnName}</Data></Cell> {/foreach} </Row> {foreach from=$data.content item=row} <Row> {foreach from=$row item=col} <Cell><Data ss:Type="String">{$col}</Data></Cell> {/foreach} </Row> {/foreach} </Table> </Worksheet> </Workbook>
Как видно из кода, в шаблон передается массив $data содержащий два массива — строку заголовка таблицы и собственно данные.
Стоит отметить что использовать шаблонизатор только для генерации XML несколько накладно, и получить XML можно множеством других способов. В моем конкретном случае генерация XML это лишь маленькая плюшка в большом проекте, где без шаблонизатора не обойтись.
В качестве примера я привел простейшую таблицу, при желании можно манипулировать гораздо большим числом атрибутов. Это особенно приятно, если учесть, что для реализации не требуются никакие сторонние библиотеки.
Описанный метод несколько лет работает на одном проекте и ни один пользователь до сих пор не заподозрил, что открываемые им данные не являются документом MS Office.
Подробнее о структуре XML используемой в MS Excel можно почитать в MSDN XML Spreadsheet Reference
В своей профессиональной деятельности я периодически сталкиваюсь с задачами экспорта/генерации данных в формате XLS/XLSX (Excel). Библиотека PhpSpreadsheet позволяет их решить.
Данная библиотека является логичным продолжением библиотеки PHPExcel, которая уже несколько лет не поддерживается.
Скачать и установить библиотеку предлагается с помощью composer:
composer require phpoffice/phpspreadsheet
Сайт: https://phpspreadsheet.readthedocs.io
Опишу реализацию типичных задач.
Обратите внимание, что для корректной работы XMLWriter (библиотеки PHP) необходима корректная его настройка:
Типовой Hello World
<?php require 'vendor/autoload.php'; use PhpOfficePhpSpreadsheetSpreadsheet; use PhpOfficePhpSpreadsheetWriterXlsx; $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); $sheet->setCellValue('A1', 'Hello World !'); $writer = new Xlsx($spreadsheet); $writer->save('hello world.xlsx');
Получение Excel документа через Ajax запрос
Php обработчик генерации XLSX документа:
header('Content-Type: application/json'); require 'vendor/autoload.php'; use PhpOfficePhpSpreadsheetSpreadsheet; use PhpOfficePhpSpreadsheetWriterXlsx; $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); //some code... $writer = new Xlsx($spreadsheet); ob_start(); $writer->save('php://output'); $xlsData = ob_get_contents(); ob_end_clean(); echo json_encode('data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,'.base64_encode($xlsData));
JS:
$.ajax({ type:'POST', url:"...", // path to php handler data: {...}, // some post data dataType:'json' }).done(function(data){ var $a = $("<a>"); $a.attr("href",data); $("body").append($a); $a.attr("download","Report.xlsx"); $a[0].click(); $a.remove(); });
Здесь кратко поясню:
PHP обработчик формирует Excel документ и кодирует его в base64. Далее JS создает временную ссылку и в тег «href» кладёт этот закодированный контент. После инициации клика по ссылке происходит скачивание XLSX документа, а сама ссылка удаляется со страницы. Этакая мгновенная генерация Excel документа.
Установка заголовка листа
$sheet = $spreadsheet->getActiveSheet(); $sheet->setTitle('Some title');
Добавление текстового контента в ячейку
Можно добавлять по координатам (отчет начинается с единицы):
$sheet = $spreadsheet->getActiveSheet(); //$columnIndex - номер колонки //$row - номер строки //$data - текстовые данные для добавления $sheet->setCellValueByColumnAndRow($columnIndex, $row, $data);
Также можно воспользоваться символьными идентификаторами:
$sheet = $spreadsheet->getActiveSheet(); $sheet->setCellValue('A1', 'Some data');
Выравнивание
По координатам:
$sheet->getStyleByColumnAndRow(1,1) ->getAlignment() ->setHorizontal(PhpOfficePhpSpreadsheetStyleAlignment::HORIZONTAL_RIGHT);
Через идентификатор ячейки:
$sheet->getStyle('B1') ->getAlignment() ->setHorizontal(PhpOfficePhpSpreadsheetStyleAlignment::HORIZONTAL_RIGHT);
Через интервал идентификаторов ячеек:
$sheet->getStyle('B1:B5') ->getAlignment() ->setHorizontal(PhpOfficePhpSpreadsheetStyleAlignment::HORIZONTAL_RIGHT);
Установка стиля границы (border) ячейки/ячеек
$borderStyleArray = array( 'borders' => array( 'outline' => array( 'borderStyle' => PhpOfficePhpSpreadsheetStyleBorder::BORDER_THIN, 'color' => array('rgb' => '000000'), ), 'horizontal' => array( 'borderStyle' => PhpOfficePhpSpreadsheetStyleBorder::BORDER_THIN, 'color' => array('rgb' => '000000'), ), 'vertical' => array( 'borderStyle' => PhpOfficePhpSpreadsheetStyleBorder::BORDER_THIN, 'color' => array('rgb' => '000000'), ), ), ); $sheet->getStyle('F4:J4')->applyFromArray($borderStyleArray);
Объединение ячеек
$sheet->mergeCells('A4:E4');
Заливка ячейки/ячеек цветом
$sheet->getStyle('F4') ->getFill() ->setFillType(PhpOfficePhpSpreadsheetStyleFill::FILL_SOLID) ->getStartColor() ->setRGB('ecf9fd');
p.s. более подробную документацию по PhpSpreadsheet можно найти в самой библиотеке, скачанной с помощью composer-а:
After putting so much effort into importing your data into an SQL
database and connecting it to your website, how do you get it back out
and into Excel in order to keep your off-line and on-line systems
synchronised?
The following article presents a simple method for downloading any
data from PHP into an Excel spreadsheet — or at least something that
looks like one.
What we’re actually doing here is creating a
text (TAB or CSV) file containing the data which can then be opened by
Excel or any other spreadsheet. Before you ask, that means NO
formatting, NO colours and NO formulae — just the actual data.
For maximum compatibility with recent version of Excel, Numbers and
other applications you should use the CSV
download format rather than tab-delimted text.
Preparing the data
The following examples use the dataset created for and earlier
article Sorting Arrays of Arrays which is
defined as follows:
<?PHP
$data = [
["firstname" => "Mary", "lastname" => "Johnson", "age" => 25],
["firstname" => "Amanda", "lastname" => "Miller", "age" => 18],
["firstname" => "James", "lastname" => "Brown", "age" => 31],
["firstname" => "Patricia", "lastname" => "Williams", "age" => 7],
["firstname" => "Michael", "lastname" => "Davis", "age" => 43],
["firstname" => "Sarah", "lastname" => "Miller", "age" => 24],
["firstname" => "Patrick", "lastname" => "Miller", "age" => 27]
];
?>
Further down this page you will find examples for creating a
downloadable file using data sourced from an SQL query.
The first step is to output the data in a tab-delimited format (CSV
can also be used but is slightly more complicated). To achieve this we
use the following code:
<?PHP
header("Content-Type: text/plain");
$flag = FALSE;
foreach($data as $row) {
if(!$flag) {
// display field/column names as first row
echo implode("t", array_keys($row)) . "rn";
$flag = TRUE;
}
echo implode("t", array_values($row)) . "rn";
}
exit;
We set the content type to text/plain so that the output can
more easily be viewed in the browser. Otherwise, because there is no
HTML formatting, the output would appear as a single line of text.
The first line of output will be the column headings (in this case
the field names are used). Values are separated with a tab t
and rows with a line break n. The output should look
something like the following:
firstname lastname age
Mary Johnson 25
Amanda Miller 18
James Brown 31
Patricia Williams 7
Michael Davis 43
Sarah Miller 24
Patrick Miller 27
There’s already a weakness in this code that may not be immediately
obvious. What if one of the fields to be ouput already contains one or
more tab characters, or worse, a newline? That’s going to throw the
whole process out as we rely on those characters to indicate column- and
line-breaks.
The solution is to ‘escape’ the tab characters. In this case we’re
going to replace tabs with a literal t and line breaks with a
literal n so they don’t affect the formatting:
<?PHP
function cleanData(&$str)
{
$str = preg_replace("/t/", "\t", $str);
$str = preg_replace("/r?n/", "\n", $str);
}
header("Content-Type: text/plain");
$flag = FALSE;
foreach($data as $row) {
array_walk($row, __NAMESPACE__ . 'cleanData');
if(!$flag) {
// display field/column names as first row
echo implode("t", array_keys($row)) . "rn";
$flag = TRUE;
}
echo implode("t", array_values($row)) . "rn";
}
exit;
The __NAMESPACE__ reference and are required
to be compatible with PHP
Namespaces, and should be included whether or not you are currently
using namespaces for your code to be future-compatible.
Before each row is echoed any tab characters are replaced
«t» so that our columns aren’t broken up. Also any line
breaks within the data are replaced with «n». Now, how to
set this up as a download…
Triggering a download
What many programmers don’t realise is that you don’t have to create
a file, even a temporary one, in order for one to be downloaded. It’s
sufficient to ‘mimic’ a download by passing the equivalent HTTP headers
followed by the data.
If we create a PHP file with the following code then when it’s called
a file will be downloaded which can be opened directly using Excel.
<?PHP
function cleanData(&$str)
{
$str = preg_replace("/t/", "\t", $str);
$str = preg_replace("/r?n/", "\n", $str);
if(strstr($str, '"')) $str = '"' . str_replace('"', '""', $str) . '"';
}
// filename for download
$filename = "website_data_" . date('Ymd') . ".xls";
header("Content-Disposition: attachment; filename="$filename"");
header("Content-Type: application/vnd.ms-excel");
$flag = FALSE;
foreach($data as $row) {
array_walk($row, __NAMESPACE__ . 'cleanData');
if(!$flag) {
// display field/column names as first row
echo implode("t", array_keys($row)) . "rn";
$flag = TRUE;
}
echo implode("t", array_values($row)) . "rn";
}
exit;
Note that we’ve added an extra line to the cleanData
function to detect double-quotes and escape any value that contains
them. Without this an uneven number of quotes in a string can confuse
Excel.
source
This should result in a file being downloaded and saved to your
computer. If all goes well then the filename will be
named «website_data_20230416.xls» and will open in Excel looking something like this:
How does it work? Setting the headers tells the browser to expect a
file with a given name and type. The data is then echoed, but instead
of appearing on the page it becomes the downloaded file.
Because of the .xls extension and the vnd.ms-excel file
type, most computers will associate it with Excel and double-clicking
will cause that program to open. You could also modify the file name
and mime type to indicate a different spreadsheet package or database
application.
There is no way to specify data/cell formatting, column widths,
etc, using this method. To include formatting try generating HTML code
or a script that actually builds an Excel file. Or create your own
macro in Excel that applies formatting after the import.
A similar technique can be used to allow users to download files that
have been uploaded previously using PHP and stored with different names.
More on that later…
Exporting from an SQL database
If your goal is to allow data to be exported from a query result
then the changes are relatively simple:
<?PHP
// Original PHP code by Chirp Internet: www.chirpinternet.eu
// Please acknowledge use of this code by including this header.
function cleanData(&$str)
{
$str = preg_replace("/t/", "\t", $str);
$str = preg_replace("/r?n/", "\n", $str);
if(strstr($str, '"')) $str = '"' . str_replace('"', '""', $str) . '"';
}
// filename for download
$filename = "website_data_" . date('Ymd') . ".xls";
header("Content-Disposition: attachment; filename="$filename"");
header("Content-Type: application/vnd.ms-excel");
$flag = FALSE;
$result = pg_query("SELECT * FROM table ORDER BY field") or die('Query failed!');
while(FALSE !== ($row = pg_fetch_assoc($result))) {
array_walk($row, __NAMESPACE__ . 'cleanData');
if(!$flag) {
// display field/column names as first row
echo implode("t", array_keys($row)) . "rn";
$flag = TRUE;
}
echo implode("t", array_values($row)) . "rn";
}
exit;
This is the entire script required to query the database, clean the
data, and trigger a file download.
The database functions need to match the database you’re using.
MySQL users for example will need to use mysqli_query
and either mysqli_fetch_assoc or mysqli_fetch_assoc in place of the PostgreSQL
functions. Or better, PDO::query().
For other databases see under User Comments
below or check the PHP documentation.
If you are seeing duplicate
columns (numbered as well as labeled) you need to change the fetch call
to return only the associative (ASSOC) array.
If you’re having trouble at this stage, remove the
Content-Disposition header and change the Content-Type back to
text/plain. This makes debugging a lot easier as you can see
the output in your browser rather than having to download and open the
generated file every time you edit the script.
Preventing Excel’s ridiculous auto-format
When importing from a text file as we’re essentially doing here,
Excel has a nasty habit of mangling dates, timestamps, phone numbers and
similar input values.
For our purposes, some simple additions to the cleanData
function take care of most of the problems:
<?PHP
// Original PHP code by Chirp Internet: www.chirpinternet.eu
// Please acknowledge use of this code by including this header.
function cleanData(&$str)
{
// escape tab characters
$str = preg_replace("/t/", "\t", $str);
// escape new lines
$str = preg_replace("/r?n/", "\n", $str);
// convert 't' and 'f' to boolean values
if($str == 't') $str = 'TRUE';
if($str == 'f') $str = 'FALSE';
// force certain number/date formats to be imported as strings
if(preg_match("/^0/", $str) || preg_match("/^+?d{8,}$/", $str) || preg_match("/^d{4}.d{1,2}.d{1,2}/", $str)) {
$str = "'$str";
}
// escape fields that include double quotes
if(strstr($str, '"')) $str = '"' . str_replace('"', '""', $str) . '"';
}
?>
The section that prevents values being scrambled does so by inserting
an apostrophe at the start of the cell. When you open the resuling file
in Excel you may see the apostrophe, but editing the field will make it
disappear while retaining the string format. Excel is strange that way.
The types of values being escape this way are: values starting with a
zero; values starting with an optional + and at least 8
consecutive digits (phone numbers); and values starting with numbers in
YYYY-MM-DD format (timestamps). The relevant regular expressions have
been highlighted in the code above.
Exporting to CSV format
As newer versions of Excel are becoming fussy about opening files
with a .xls extension that are not actual Excel binary files, making CSV
format with a .csv extension is now a better option.
The tab-delimited text options describe above may be a bit limiting
if your data contains newlines or tab breaks that you want to preserve
when opened in Excel or another spreadsheet application.
A better format then is comma-separated variables (CSV) which can be
generated as follows:
<?PHP
// Original PHP code by Chirp Internet: www.chirpinternet.eu
// Please acknowledge use of this code by including this header.
function cleanData(&$str)
{
if($str == 't') $str = 'TRUE';
if($str == 'f') $str = 'FALSE';
if(preg_match("/^0/", $str) || preg_match("/^+?d{8,}$/", $str) || preg_match("/^d{4}.d{1,2}.d{1,2}/", $str)) {
$str = "'$str";
}
if(strstr($str, '"')) $str = '"' . str_replace('"', '""', $str) . '"';
}
// filename for download
$filename = "website_data_" . date('Ymd') . ".csv";
header("Content-Disposition: attachment; filename="$filename"");
header("Content-Type: text/csv");
$out = fopen("php://output", 'w');
$flag = FALSE;
$result = pg_query("SELECT * FROM table ORDER BY field") or die('Query failed!');
while(FALSE !== ($row = pg_fetch_assoc($result))) {
array_walk($row, __NAMESPACE__ . 'cleanData');
if(!$flag) {
// display field/column names as first row
fputcsv($out, array_keys($row), ',', '"');
$flag = TRUE;
}
fputcsv($out, array_values($row), ',', '"');
}
fclose($out);
exit;
Normally the fputcsv command is used to write data in CSV
format to a separate file. In this script we’re tricking it into
writing directly to the page by telling it to write to
php://output instead of a regular file. A nice trick.
source
As an aside, to export directly to CSV format from the command line
interface in PostgreSQL you can use simply:
postgres=# COPY (SELECT * FROM table ORDER BY field) TO '/tmp/table.csv' WITH CSV HEADER;
and for MySQL, something like the following:
SELECT * FROM table ORDER BY field
INTO OUTFILE '/tmp/table.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY 'n'
Exporting to CSV with Unicode intact
If like us your data contains UTF-8 characters you will notice that
Excel doesn’t handle them very well. Other applications can open UTF-8
content without problems, but Microsoft apparently still occupies the
dark ages.
Fortunately, there is a trick you can use. Below you can see how we
modify the script to convert everything from UTF-8 to UTF-16 Lower
Endian (UTF-16LE) format which Excel, at least on Windows, will recognise.
When opening this file in Excel you might find all the data
bunched into the first column. This should be fixable using the
«Text to Columns…» command under the Data menu.
<?PHP
// Original PHP code by Chirp Internet: www.chirpinternet.eu
// Please acknowledge use of this code by including this header.
function cleanData(&$str)
{
if($str == 't') $str = 'TRUE';
if($str == 'f') $str = 'FALSE';
if(preg_match("/^0/", $str) || preg_match("/^+?d{8,}$/", $str) || preg_match("/^d{4}.d{1,2}.d{1,2}/", $str)) {
$str = "'$str";
}
if(strstr($str, '"')) $str = '"' . str_replace('"', '""', $str) . '"';
$str = mb_convert_encoding($str, 'UTF-16LE', 'UTF-8');
}
// filename for download
$filename = "website_data_" . date('Ymd') . ".csv";
header("Content-Disposition: attachment; filename="$filename"");
header("Content-Type: text/csv; charset=UTF-16LE");
$out = fopen("php://output", 'w');
$flag = FALSE;
$result = pg_query("SELECT * FROM table ORDER BY field") or die('Query failed!');
while(FALSE !== ($row = pg_fetch_assoc($result))) {
array_walk($row, __NAMESPACE__ . 'cleanData');
if(!$flag) {
// display field/column names as first row
fputcsv($out, array_keys($row), ',', '"');
$flag = TRUE;
}
fputcsv($out, array_values($row), ',', '"');
}
fclose($out);
exit;
This script may not work for all versions of Excel. Please let us
know using the Feedback form below if you encounter problems or come up
with a better solution.
Changing column headings
The above database download examples all use the database field
names for the first row of the exported file which may not be what you
want. If you want to specify your own more user-friendly headings you
can modify the code as follow:
<PHP
$colnames = [
'memberno' => "Member No.",
'date_joined' => "Date joined",
'title' => "Title",
'firstname' => "First name",
'lastname' => "Last name",
'address' => "Address",
'postcode' => "Postcode",
'city' => "City",
'country' => "Country",
'phone' => "Telephone",
'mobile' => "Mobile",
'fax' => "Facsimile",
'email' => "Email address",
'notes' => "Notes"
];
function map_colnames($input)
{
global $colnames;
return isset($colnames[$input]) ? $colnames[$input] : $input;
}
// filename for download
$filename = "website_data_" . date('Ymd') . ".csv";
...
if(!$flag) {
// display field/column names as first row
$firstline = array_map(__NAMESPACE__ . 'map_colnames', array_keys($row));
fputcsv($out, $firstline, ',', '"');
$flag = TRUE;
}
...
?>
The values in the first row will be mapped according to the
$colnames associative array. If no mapping is provided for a
fieldname it will remain unchanged. Of course you will want to provide
your own list of suitable headings. They don’t have to be in order.
source
References
- Easy way to create XLS file from PHP
- Keeping leading zeros and large numbers
< PHP
Most recent 20 of 63 comments:
Post your comment or question
Data is any set of characters that is translated for some purpose, like for analysis. It can be any character or value, including text and numbers, pictures, sound, or video. If data is not put into context then it does not do anything to a human being or machine.
We generally export data from the websites to save it on the computer for offline used like to maintain list data and to analysis it. Excel is the best format to Export data in a file because reading large files is much easier in Excel for the user. Also, you can use additional functions like selecting individual cells to import the data, convert dates and time automatically, filters, sorting, reading formulas and their results etc.
In this blog we will learn how to export PHP data to .xls file step by step. With the help of simple PHP script you can export data to Excel and download it in a .xls file.
STEP 1: Create an Array to store the data
I have created an array ($customers_data) to store the customers details. You can create your own array as per your requirement:
$customers_data = array( array( 'customers_id' => '1', 'customers_firstname' => 'Chris', 'customers_lastname' => 'Cavagin', 'customers_email' => 'chriscavagin@gmail.com', 'customers_telephone' => '9911223388' ), array( 'customers_id' => '2', 'customers_firstname' => 'Richard', 'customers_lastname' => 'Simmons', 'customers_email' => 'rsimmons@media.com', 'customers_telephone' => '9911224455' ), array( 'customers_id' => '3', 'customers_firstname' => 'Steve', 'customers_lastname' => 'Beaven', 'customers_email' => 'ateavebeaven@gmail.com', 'customers_telephone' => '8855223388' ), array( 'customers_id' => '4', 'customers_firstname' => 'Howard', 'customers_lastname' => 'Rawson', 'customers_email' => 'howardraw@gmail.com', 'customers_telephone' => '9911334488' ), array( 'customers_id' => '5', 'customers_firstname' => 'Rachel', 'customers_lastname' => 'Dyson', 'customers_email' => 'racheldyson@gmail.com', 'customers_telephone' => '9912345388' ) );
STEP 2: Create a function to filter the data:
This function is used to detect double-quotes and escape any value that contains them. Without this an uneven number of quotes in a string can confuse Excel.
// Filter Customer Data function filterCustomerData(&$str) { $str = preg_replace("/t/", "\t", $str); $str = preg_replace("/r?n/", "\n", $str); if(strstr($str, '"')) $str = '"' . str_replace('"', '""', $str) . '"'; }
STEP 3: Define file name and content header for download:
$file_name variable is used to hold the name of the file and also define content header for download.
// File Name & Content Header For Download $file_name = "customers_data.xls"; header("Content-Disposition: attachment; filename="$file_name""); header("Content-Type: application/vnd.ms-excel");
STEP 4: Define Loop through each row in $customers_data
//To define column name in first row. $column_names = false; // run loop through each row in $customers_data foreach($customers_data as $row) { if(!$column_names) { echo implode("t", array_keys($row)) . "n"; $column_names = true; } // The array_walk() function runs each array element in a user-defined function. array_walk($row, 'filterCustomerData'); echo implode("t", array_values($row)) . "n"; } exit;
1. Define a variable $column_names which is used to print the column name in first row of excel.
2. Run a loop through each row and used array_walk() function to run each row in a user defined function.
STEP 5: Run script file in your environment:
If all goes well then the filename will be named “customers_data.xls” downloaded and saved in your computer. You can open this file in Excel which look like as following:
Click here to download the complete code.
You can reach us at support@knowband.com for any queries. We also provide all kinds of customization needed on an online eCommerce store. You can also find the best modules of Prestashop, Opencart, Magento and Magento 2 at Knowband.
Take a look at our bestseller module Prestashop One Page supercheckout here: