Skip to content

Instantly share code, notes, and snippets.

@markvds
Created September 3, 2014 13:44
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save markvds/2b5161063557a850b073 to your computer and use it in GitHub Desktop.
Save markvds/2b5161063557a850b073 to your computer and use it in GitHub Desktop.
Excel Writer
<?php
/**
* Simple excel generating from PHP5
*
* @package Utilities
* @license http://www.opensource.org/licenses/mit-license.php
* @author Oliver Schwarz <oliver.schwarz@gmail.com>
* @version 1.0
*/
/**
* Generating excel documents on-the-fly from PHP5
*
* Uses the excel XML-specification to generate a native
* XML document, readable/processable by excel.
*
* Modified by Mark van der Sanden, Magentics
*/
class Mgcs_General_Model_Excel_Writer
{
/**
* Header (of document)
* @var string
*/
private $_header = '';
/**
* Footer (of document)
* @var string
*/
private $_footer = '';
/**
* Lines to output in the excel document
* @var array
*/
private $_lines = array();
private $_htmlLines = array();
/**
* Used encoding
* @var string
*/
private $_encoding;
/**
* Worksheet title
* @var string
*/
private $_worksheetTitle;
protected $_styles = array(
'shorttime' => '<NumberFormat ss:Format="Short Time"/>',
'shortdate' => '<NumberFormat ss:Format="Short Date"/>',
'generaldate' => '<NumberFormat ss:Format="General Date"/>',
'euro' => '<NumberFormat ss:Format="_ &quot;€&quot;\ * #,##0.00_ ;_ &quot;€&quot;\ * \-#,##0.00_ ;_ &quot;€&quot;\ * &quot;-&quot;??_ ;_ @_ "/>',
);
/**
* Constructor
*
* The constructor allows the setting of some additional
* parameters so that the library may be configured to
* one's needs.
*
* On converting types:
* When set to true, the library tries to identify the type of
* the variable value and set the field specification for Excel
* accordingly. Be careful with article numbers or postcodes
* starting with a '0' (zero)!
*
* @param string $sEncoding Encoding to be used (defaults to UTF-8)
* @param boolean $bConvertTypes Convert variables to field specification
* @param string $sWorksheetTitle Title for the worksheet
*/
public function __construct($encoding = 'UTF-8', $worksheetTitle = 'Table1')
{
$this->setEncoding($encoding ? $encoding : 'UTF-8');
$this->setWorksheetTitle($worksheetTitle);
$this->_header =
'<?xml version="1.0" encoding="%s"?>' . "\n" .
'<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" 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">' . "\n" .
' <Styles>' . "\n";
foreach ($this->_styles as $name => $style) {
$this->_header .= ' <Style ss:ID="' . $name . '">' . $style . '</Style>' . "\n";
}
$this->_header .=
' </Styles>' . "\n"
;
$this->_footer =
'</Workbook>'
;
}
/**
* Set encoding
* @param string Encoding type to set
*/
public function setEncoding($sEncoding)
{
$this->_encoding = $sEncoding;
}
/**
* Set worksheet title
*
* Strips out not allowed characters and trims the
* title to a maximum length of 31.
*
* @param string $title Title for worksheet
*/
public function setWorksheetTitle ($title)
{
$title = preg_replace ("/[\\\|:|\/|\?|\*|\[|\]]/", "", $title);
$title = substr ($title, 0, 31);
$this->_worksheetTitle = $title;
}
/**
* Adds a single row to the document
*
* The values can be a scalar value or array. Scalar values get
* added as string, array can have the following keys:
* - style: one of the keys in $this->_styles (shortdate, shorttime, generaldate, euro)
* - type: case insensitive Excel type (string, number, date, datetime, ...)
*
* Excel types:
* - String Hello
* - Number 123.12
* - Date 2010-02-03
* - DateTime 1999-05-31T13:20:00Z-05:00
* - Time 13:20:00, 13:20:00Z-05:00
* - anyURI http://www.example.com/
* - Boolean true, false, 1, 0
* - Integer -1, 1234
* - Double 1.23, 1.876, 12.78E-2
*
* @see http://msdn.microsoft.com/en-us/library/aa203732%28office.11%29.aspx
* @param array $array Array with cell values
* @return void
*/
public function addRow($array)
{
$types = array(
'String', 'Number', 'Date', 'DateTime', 'Time',
'anyURI', 'Boolean','Integer', 'Double'
);
$cells = '';
$htmlCells = '';
foreach ($array as $value) {
$type = 'String';
$style = '';
$htmlStyle = '';
if (is_array($value)) {
if (!empty($value['type'])) {
$value['type'] = strtolower($value['type']);
foreach ($types as $_type) {
if ($value['type'] == strtolower($_type)) {
$type = $_type;
}
}
}
if (!empty($value['style'])) {
$value['style'] = strtolower($value['style']);
foreach (array_keys($this->_styles) as $_style) {
if ($value['style'] == strtolower($_style)) {
$style = $_style;
}
}
}
if (isset($value['value'])) {
$value = $value['value'];
} else {
$value = '';
}
} else {
// kept for compatibility reasons
if (preg_match('/^##([a-z]{1,15})(\|[a-z]{1,15})?:(.*)/i', $value, $matches)) {
$type = $matches[1];
$value = $matches[3];
if (!empty($matches[2])) {
$style = substr($matches[2], 1);
}
}
}
switch ($type) {
case 'Number':
case 'Integer':
case 'Double':
$htmlStyle = 'text-align: right;';
break;
}
if ($type == 'DateTime' && preg_match('/[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}/', $value)) {
$value = date('Y-m-d\TH:i:s', strtotime($value));
}
if ($type == 'DateTime' && preg_match('/^[0-9]+$/', $value)) {
$value = date('Y-m-d\TH:i:s', $value);
}
$styleDeclaration = '';
if ($style) {
$styleDeclaration = ' ss:StyleID="' . $style . '"';
}
$cells .= '<Cell' . $styleDeclaration . '><Data ss:Type="' . htmlspecialchars($type, ENT_COMPAT, $this->_encoding) . '">' . htmlentities($value, ENT_COMPAT, $this->_encoding) . '</Data></Cell>' . "\n";
$htmlCells .= '<td ' . ($htmlStyle ? sprintf('style="%s"', htmlspecialchars($htmlStyle)) : '') . '>' . htmlentities($value) . '</td>' . "\n";
}
$this->_lines[] = "<Row>\n" . $cells . "</Row>\n";
$this->_htmlLines[] = '<tr>' . $htmlCells . '</tr>' . "\n";
}
/**
* Add an array to the document
* @param array 2-dimensional array
*/
public function addArray ($array)
{
foreach ($array as $row) {
$this->addRow($row);
}
}
/**
* Generate the excel file
* @param string $filename Name of excel file to generate (...xls)
*/
public function getXML()
{
// print out document to the browser
// need to use stripslashes for the damn ">"
$output = '';
$output .= stripslashes(sprintf($this->_header, $this->_encoding));
$output .= "\n<Worksheet ss:Name=\"" . $this->_worksheetTitle . "\">\n<Table>\n";
foreach ($this->_lines as $line) {
$output .= $line;
}
$output .= "</Table>\n</Worksheet>\n";
$output .= $this->_footer;
return $output;
}
public function stream($filename = 'document.xml')
{
// correct/validate filename
$filename = basename(preg_replace('/[^aA-zZ0-9\_\.-]/', '', $filename));
// deliver header (as recommended in php manual)
header("Content-Type: application/vnd.ms-excel; charset=" . $this->_encoding);
header("Content-Disposition: attachment; filename=\"" . $filename . "\"");
echo $this->getXML();
}
public function write($filename = 'excel-export.xml')
{
file_put_contents($filename, $this->getXML());
}
/**
* Generate and stream or save the xml
*
* Kept for compatibility reasons
*
* @deprecated
* @param string $filename
* @param bool $stream
*/
public function generateXML($filename = 'excel-export', $stream = true)
{
if ($stream) {
return $this->stream($filename);
} else {
return $this->write($filename);
}
}
public function getHtml($firstRowIsHeader = true)
{
$html = '<table>' . "\n";
foreach ($this->_htmlLines as $line) {
$html .= $line;
}
$html .= '</table>' . "\n";
return $html;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment