diff --git a/composer.json b/composer.json
index a15eb52..48afd5c 100644
--- a/composer.json
+++ b/composer.json
@@ -1,20 +1,40 @@
{
- "name": "box/spout",
+ "name": "smart145/spout",
"description": "PHP Library to read and write spreadsheet files (CSV, XLSX and ODS), in a fast and scalable way",
"type": "library",
- "keywords": ["php","read","write","csv","xlsx","ods","odf","open","office","excel","spreadsheet","scale","memory","stream","ooxml"],
+ "keywords": [
+ "php",
+ "read",
+ "write",
+ "csv",
+ "xlsx",
+ "ods",
+ "odf",
+ "open",
+ "office",
+ "excel",
+ "spreadsheet",
+ "scale",
+ "memory",
+ "stream",
+ "ooxml"
+ ],
"license": "Apache-2.0",
- "homepage": "https://www.github.com/box/spout",
+ "homepage": "https://www.github.com/smart145/spout",
"authors": [
{
"name": "Adrien Loison",
"email": "adrien@box.com"
+ },
+ {
+ "name": "Dariel Ramos",
+ "email": "vdariel90@gmail.com"
}
],
"require": {
"php": ">=5.4.0",
"ext-zip": "*",
- "ext-xmlreader" : "*"
+ "ext-xmlreader": "*"
},
"require-dev": {
"phpunit/phpunit": "^4.8.0"
@@ -38,5 +58,4 @@
"php": "5.4.0"
}
}
-
}
diff --git a/src/Spout/Common/Escaper/ODS.php b/src/Spout/Common/Escaper/ODS.php
index 9de665b..4ffd766 100644
--- a/src/Spout/Common/Escaper/ODS.php
+++ b/src/Spout/Common/Escaper/ODS.php
@@ -26,13 +26,13 @@ class ODS implements EscaperInterface
// 'ENT_DISALLOWED' ensures that invalid characters in the given document type are replaced.
// Otherwise control characters like a vertical tab "\v" will make the XML document unreadable by the XML processor
// @link https://github.com/box/spout/issues/329
- $replacedString = htmlspecialchars($string, ENT_NOQUOTES | ENT_DISALLOWED, 'UTF-8');
+ $replacedString = htmlspecialchars($string, ENT_NOQUOTES | ENT_DISALLOWED);
} else {
// We are on hhvm or any other engine that does not support ENT_DISALLOWED.
//
// @NOTE: Using ENT_NOQUOTES as only XML entities ('<', '>', '&') need to be encoded.
// Single and double quotes can be left as is.
- $escapedString = htmlspecialchars($string, ENT_NOQUOTES, 'UTF-8');
+ $escapedString = htmlspecialchars($string, ENT_NOQUOTES);
// control characters values are from 0 to 1F (hex values) in the ASCII table
// some characters should not be escaped though: "\t", "\r" and "\n".
diff --git a/src/Spout/Common/Escaper/XLSX.php b/src/Spout/Common/Escaper/XLSX.php
index 12b44d7..7c6c61b 100644
--- a/src/Spout/Common/Escaper/XLSX.php
+++ b/src/Spout/Common/Escaper/XLSX.php
@@ -44,7 +44,7 @@ class XLSX implements EscaperInterface
$escapedString = $this->escapeControlCharacters($string);
// @NOTE: Using ENT_NOQUOTES as only XML entities ('<', '>', '&') need to be encoded.
// Single and double quotes can be left as is.
- $escapedString = htmlspecialchars($escapedString, ENT_NOQUOTES, 'UTF-8');
+ $escapedString = htmlspecialchars($escapedString, ENT_NOQUOTES);
return $escapedString;
}
diff --git a/src/Spout/Writer/XLSX/Internal/Workbook.php b/src/Spout/Writer/XLSX/Internal/Workbook.php
index bcdce7f..8df057b 100644
--- a/src/Spout/Writer/XLSX/Internal/Workbook.php
+++ b/src/Spout/Writer/XLSX/Internal/Workbook.php
@@ -3,10 +3,10 @@
namespace Box\Spout\Writer\XLSX\Internal;
use Box\Spout\Writer\Common\Internal\AbstractWorkbook;
+use Box\Spout\Writer\Common\Sheet;
use Box\Spout\Writer\XLSX\Helper\FileSystemHelper;
use Box\Spout\Writer\XLSX\Helper\SharedStringsHelper;
use Box\Spout\Writer\XLSX\Helper\StyleHelper;
-use Box\Spout\Writer\Common\Sheet;
/**
* Class Workbook
@@ -35,6 +35,9 @@ class Workbook extends AbstractWorkbook
/** @var \Box\Spout\Writer\XLSX\Helper\StyleHelper Helper to apply styles */
protected $styleHelper;
+ /** @var array contain column width information */
+ protected $columnwidths = [];
+
/**
* @param string $tempFolder
* @param bool $shouldUseInlineStrings
@@ -42,8 +45,13 @@ class Workbook extends AbstractWorkbook
* @param \Box\Spout\Writer\Style\Style $defaultRowStyle
* @throws \Box\Spout\Common\Exception\IOException If unable to create at least one of the base folders
*/
- public function __construct($tempFolder, $shouldUseInlineStrings, $shouldCreateNewSheetsAutomatically, $defaultRowStyle)
- {
+ public function __construct(
+ $tempFolder,
+ $shouldUseInlineStrings,
+ $shouldCreateNewSheetsAutomatically,
+ $defaultRowStyle,
+ $columnwidths
+ ) {
parent::__construct($shouldCreateNewSheetsAutomatically, $defaultRowStyle);
$this->shouldUseInlineStrings = $shouldUseInlineStrings;
@@ -56,6 +64,7 @@ class Workbook extends AbstractWorkbook
// This helper will be shared by all sheets
$xlFolder = $this->fileSystemHelper->getXlFolder();
$this->sharedStringsHelper = new SharedStringsHelper($xlFolder);
+ $this->columnwidths = $columnwidths;
}
/**
@@ -86,12 +95,24 @@ class Workbook extends AbstractWorkbook
$sheet = new Sheet($newSheetIndex, $this->internalId);
$worksheetFilesFolder = $this->fileSystemHelper->getXlWorksheetsFolder();
- $worksheet = new Worksheet($sheet, $worksheetFilesFolder, $this->sharedStringsHelper, $this->styleHelper, $this->shouldUseInlineStrings);
+ $worksheet = new Worksheet($sheet, $worksheetFilesFolder, $this->sharedStringsHelper, $this->styleHelper,
+ $this->shouldUseInlineStrings, $this->columnwidths);
$this->worksheets[] = $worksheet;
return $worksheet;
}
+ /**
+ * Set column width for sheet that will be created
+ * should only be called from the writer
+ *
+ * @param array $columnwidths
+ */
+ public function _setColumnWidth($columnwidths)
+ {
+ $this->columnwidths = $columnwidths;
+ }
+
/**
* Closes the workbook and all its associated sheets.
* All the necessary files are written to disk and zipped together to create the XLSX file.
diff --git a/src/Spout/Writer/XLSX/Internal/Worksheet.php b/src/Spout/Writer/XLSX/Internal/Worksheet.php
index 0bd909d..392371d 100644
--- a/src/Spout/Writer/XLSX/Internal/Worksheet.php
+++ b/src/Spout/Writer/XLSX/Internal/Worksheet.php
@@ -65,8 +65,14 @@ EOD;
* @param bool $shouldUseInlineStrings Whether inline or shared strings should be used
* @throws \Box\Spout\Common\Exception\IOException If the sheet data file cannot be opened for writing
*/
- public function __construct($externalSheet, $worksheetFilesFolder, $sharedStringsHelper, $styleHelper, $shouldUseInlineStrings)
- {
+ public function __construct(
+ $externalSheet,
+ $worksheetFilesFolder,
+ $sharedStringsHelper,
+ $styleHelper,
+ $shouldUseInlineStrings,
+ $columnwidths
+ ) {
$this->externalSheet = $externalSheet;
$this->sharedStringsHelper = $sharedStringsHelper;
$this->styleHelper = $styleHelper;
@@ -76,8 +82,8 @@ EOD;
$this->stringsEscaper = \Box\Spout\Common\Escaper\XLSX::getInstance();
$this->stringHelper = new StringHelper();
- $this->worksheetFilePath = $worksheetFilesFolder . '/' . strtolower($this->externalSheet->getName()) . '.xml';
- $this->startSheet();
+ $this->worksheetFilePath = $worksheetFilesFolder.'/'.strtolower($this->externalSheet->getName()).'.xml';
+ $this->startSheet($columnwidths);
}
/**
@@ -86,12 +92,24 @@ EOD;
* @return void
* @throws \Box\Spout\Common\Exception\IOException If the sheet data file cannot be opened for writing
*/
- protected function startSheet()
+ protected function startSheet($columnwidths = null)
{
$this->sheetFilePointer = fopen($this->worksheetFilePath, 'w');
$this->throwIfSheetFilePointerIsNotAvailable();
fwrite($this->sheetFilePointer, self::SHEET_XML_FILE_HEADER);
+
+ if (!empty($columnwidths)) {
+ foreach ($columnwidths as $c) {
+ fwrite($this->sheetFilePointer,
+ ''
+ );
+ }
+ }
+
fwrite($this->sheetFilePointer, '');
}
@@ -162,6 +180,7 @@ EOD;
protected function isEmptyRow($dataRow)
{
$numCells = count($dataRow);
+
// using "reset()" instead of "$dataRow[0]" because $dataRow can be an associative array
return ($numCells === 1 && CellHelper::isEmpty(reset($dataRow)));
}
@@ -182,9 +201,9 @@ EOD;
$rowIndex = $this->lastWrittenRowIndex + 1;
$numCells = count($dataRow);
- $rowXML = '';
+ $rowXML = '';
- foreach($dataRow as $cellValue) {
+ foreach ($dataRow as $cellValue) {
$rowXML .= $this->getCellXML($rowIndex, $cellNumber, $cellValue, $style->getId());
$cellNumber++;
}
@@ -210,25 +229,31 @@ EOD;
protected function getCellXML($rowIndex, $cellNumber, $cellValue, $styleId)
{
$columnIndex = CellHelper::getCellIndexFromColumnIndex($cellNumber);
- $cellXML = 'getCellXMLFragmentForNonEmptyString($cellValue);
- } else if (CellHelper::isBoolean($cellValue)) {
- $cellXML .= ' t="b">' . intval($cellValue) . '';
- } else if (CellHelper::isNumeric($cellValue)) {
- $cellXML .= '>' . $cellValue . '';
- } else if (empty($cellValue)) {
- if ($this->styleHelper->shouldApplyStyleOnEmptyCell($styleId)) {
- $cellXML .= '/>';
- } else {
- // don't write empty cells that do no need styling
- // NOTE: not appending to $cellXML is the right behavior!!
- $cellXML = '';
- }
} else {
- throw new InvalidArgumentException('Trying to add a value with an unsupported type: ' . gettype($cellValue));
+ if (CellHelper::isBoolean($cellValue)) {
+ $cellXML .= ' t="b">'.intval($cellValue).'';
+ } else {
+ if (CellHelper::isNumeric($cellValue)) {
+ $cellXML .= '>'.$cellValue.'';
+ } else {
+ if (empty($cellValue)) {
+ if ($this->styleHelper->shouldApplyStyleOnEmptyCell($styleId)) {
+ $cellXML .= '/>';
+ } else {
+ // don't write empty cells that do no need styling
+ // NOTE: not appending to $cellXML is the right behavior!!
+ $cellXML = '';
+ }
+ } else {
+ throw new InvalidArgumentException('Trying to add a value with an unsupported type: '.gettype($cellValue));
+ }
+ }
+ }
}
return $cellXML;
@@ -248,10 +273,10 @@ EOD;
}
if ($this->shouldUseInlineStrings) {
- $cellXMLFragment = ' t="inlineStr">' . $this->stringsEscaper->escape($cellValue) . '';
+ $cellXMLFragment = ' t="inlineStr">'.$this->stringsEscaper->escape($cellValue).'';
} else {
$sharedStringId = $this->sharedStringsHelper->writeString($cellValue);
- $cellXMLFragment = ' t="s">' . $sharedStringId . '';
+ $cellXMLFragment = ' t="s">'.$sharedStringId.'';
}
return $cellXMLFragment;
diff --git a/src/Spout/Writer/XLSX/Writer.php b/src/Spout/Writer/XLSX/Writer.php
index 965955a..b1deaba 100644
--- a/src/Spout/Writer/XLSX/Writer.php
+++ b/src/Spout/Writer/XLSX/Writer.php
@@ -30,6 +30,9 @@ class Writer extends AbstractMultiSheetsWriter
/** @var Internal\Workbook The workbook for the XLSX file */
protected $book;
+ /** @var array contain column width information */
+ protected $columnwidths = [];
+
/**
* Sets a custom temporary folder for creating intermediate files/folders.
* This must be set before opening the writer.
@@ -44,6 +47,7 @@ class Writer extends AbstractMultiSheetsWriter
$this->throwIfWriterAlreadyOpened('Writer must be configured before opening it.');
$this->tempFolder = $tempFolder;
+
return $this;
}
@@ -61,6 +65,45 @@ class Writer extends AbstractMultiSheetsWriter
$this->throwIfWriterAlreadyOpened('Writer must be configured before opening it.');
$this->shouldUseInlineStrings = $shouldUseInlineStrings;
+
+ return $this;
+ }
+
+ /**
+ * Clear all column width specification
+ * @return Writer
+ */
+ public function clearColumnWidth()
+ {
+ $this->columnwidths = [];
+ if ($this->book) {
+ $this->book->_setColumnWidth($this->columnwidths);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add a width definition for the next sheet that will be generated
+ * @param number $width column width
+ * @param number $min column position ( A=1 ) where this width should take effect
+ * @param number $max end of range where width take effect ( default to min )
+ * @return Writer
+ */
+ public function setColumnsWidth($width, $min, $max = null)
+ {
+ if ($max === null) {
+ $max = $min;
+ }
+ $this->columnwidths[] = [
+ 'width' => $width,
+ 'min' => $min,
+ 'max' => $max,
+ ];
+ if ($this->book) {
+ $this->book->_setColumnWidth($this->columnwidths);
+ }
+
return $this;
}
@@ -73,8 +116,9 @@ class Writer extends AbstractMultiSheetsWriter
protected function openWriter()
{
if (!$this->book) {
- $tempFolder = ($this->tempFolder) ? : sys_get_temp_dir();
- $this->book = new Workbook($tempFolder, $this->shouldUseInlineStrings, $this->shouldCreateNewSheetsAutomatically, $this->defaultRowStyle);
+ $tempFolder = ($this->tempFolder) ?: sys_get_temp_dir();
+ $this->book = new Workbook($tempFolder, $this->shouldUseInlineStrings,
+ $this->shouldCreateNewSheetsAutomatically, $this->defaultRowStyle, $this->columnwidths);
$this->book->addNewSheetAndMakeItCurrent();
}
}