Leverage type hinting to assert array parameters

This commit is contained in:
Adrien Crivelli 2017-04-16 13:15:04 +09:00
parent 033a4bdad5
commit 06ca8f9b04
No known key found for this signature in database
GPG Key ID: B182FD79DC6DE92E
10 changed files with 407 additions and 475 deletions

View File

@ -709,10 +709,10 @@ class Cell
* *
* @return string String representation of $pRange * @return string String representation of $pRange
*/ */
public static function buildRange($pRange) public static function buildRange(array $pRange)
{ {
// Verify range // Verify range
if (!is_array($pRange) || empty($pRange) || !is_array($pRange[0])) { if (empty($pRange) || !is_array($pRange[0])) {
throw new Exception('Range does not contain any information'); throw new Exception('Range does not contain any information');
} }

View File

@ -84,13 +84,9 @@ class IOFactory
* *
* @throws Reader\Exception * @throws Reader\Exception
*/ */
public static function setSearchLocations($value) public static function setSearchLocations(array $value)
{ {
if (is_array($value)) { self::$searchLocations = $value;
self::$searchLocations = $value;
} else {
throw new Reader\Exception('Invalid parameter passed.');
}
} }
/** /**

View File

@ -462,12 +462,8 @@ class HeaderFooter
* *
* @return HeaderFooter * @return HeaderFooter
*/ */
public function setImages($images) public function setImages(array $images)
{ {
if (!is_array($images)) {
throw new \PhpOffice\PhpSpreadsheet\Exception('Invalid parameter!');
}
$this->headerFooterImages = $images; $this->headerFooterImages = $images;
return $this; return $this;

View File

@ -1172,253 +1172,250 @@ class Html extends BaseWriter implements IWriter
* @param \PhpOffice\PhpSpreadsheet\Worksheet $pSheet \PhpOffice\PhpSpreadsheet\Worksheet * @param \PhpOffice\PhpSpreadsheet\Worksheet $pSheet \PhpOffice\PhpSpreadsheet\Worksheet
* @param array $pValues Array containing cells in a row * @param array $pValues Array containing cells in a row
* @param int $pRow Row number (0-based) * @param int $pRow Row number (0-based)
* @param mixed $cellType * @param mixed $cellType eg: 'td'
* *
* @throws \PhpOffice\PhpSpreadsheet\Writer\Exception * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
* *
* @return string * @return string
*/ */
private function generateRow(\PhpOffice\PhpSpreadsheet\Worksheet $pSheet, $pValues = null, $pRow = 0, $cellType = 'td') private function generateRow(\PhpOffice\PhpSpreadsheet\Worksheet $pSheet, array $pValues, $pRow, $cellType)
{ {
if (is_array($pValues)) { // Construct HTML
// Construct HTML $html = '';
$html = '';
// Sheet index // Sheet index
$sheetIndex = $pSheet->getParent()->getIndex($pSheet); $sheetIndex = $pSheet->getParent()->getIndex($pSheet);
// DomPDF and breaks // DomPDF and breaks
if ($this->isPdf && count($pSheet->getBreaks()) > 0) { if ($this->isPdf && count($pSheet->getBreaks()) > 0) {
$breaks = $pSheet->getBreaks(); $breaks = $pSheet->getBreaks();
// check if a break is needed before this row // check if a break is needed before this row
if (isset($breaks['A' . $pRow])) { if (isset($breaks['A' . $pRow])) {
// close table: </table> // close table: </table>
$html .= $this->generateTableFooter(); $html .= $this->generateTableFooter();
// insert page break // insert page break
$html .= '<div style="page-break-before:always" />'; $html .= '<div style="page-break-before:always" />';
// open table again: <table> + <col> etc. // open table again: <table> + <col> etc.
$html .= $this->generateTableHeader($pSheet); $html .= $this->generateTableHeader($pSheet);
}
} }
// Write row start
if (!$this->useInlineCss) {
$html .= ' <tr class="row' . $pRow . '">' . PHP_EOL;
} else {
$style = isset($this->cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow])
? $this->assembleCSS($this->cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]) : '';
$html .= ' <tr style="' . $style . '">' . PHP_EOL;
}
// Write cells
$colNum = 0;
foreach ($pValues as $cellAddress) {
$cell = ($cellAddress > '') ? $pSheet->getCell($cellAddress) : '';
$coordinate = \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($colNum) . ($pRow + 1);
if (!$this->useInlineCss) {
$cssClass = '';
$cssClass = 'column' . $colNum;
} else {
$cssClass = [];
if ($cellType == 'th') {
if (isset($this->cssStyles['table.sheet' . $sheetIndex . ' th.column' . $colNum])) {
$this->cssStyles['table.sheet' . $sheetIndex . ' th.column' . $colNum];
}
} else {
if (isset($this->cssStyles['table.sheet' . $sheetIndex . ' td.column' . $colNum])) {
$this->cssStyles['table.sheet' . $sheetIndex . ' td.column' . $colNum];
}
}
}
$colSpan = 1;
$rowSpan = 1;
// initialize
$cellData = '&nbsp;';
// \PhpOffice\PhpSpreadsheet\Cell
if ($cell instanceof \PhpOffice\PhpSpreadsheet\Cell) {
$cellData = '';
if (is_null($cell->getParent())) {
$cell->attach($pSheet);
}
// Value
if ($cell->getValue() instanceof \PhpOffice\PhpSpreadsheet\RichText) {
// Loop through rich text elements
$elements = $cell->getValue()->getRichTextElements();
foreach ($elements as $element) {
// Rich text start?
if ($element instanceof \PhpOffice\PhpSpreadsheet\RichText\Run) {
$cellData .= '<span style="' . $this->assembleCSS($this->createCSSStyleFont($element->getFont())) . '">';
if ($element->getFont()->getSuperScript()) {
$cellData .= '<sup>';
} elseif ($element->getFont()->getSubScript()) {
$cellData .= '<sub>';
}
}
// Convert UTF8 data to PCDATA
$cellText = $element->getText();
$cellData .= htmlspecialchars($cellText);
if ($element instanceof \PhpOffice\PhpSpreadsheet\RichText\Run) {
if ($element->getFont()->getSuperScript()) {
$cellData .= '</sup>';
} elseif ($element->getFont()->getSubScript()) {
$cellData .= '</sub>';
}
$cellData .= '</span>';
}
}
} else {
if ($this->preCalculateFormulas) {
$cellData = \PhpOffice\PhpSpreadsheet\Style\NumberFormat::toFormattedString(
$cell->getCalculatedValue(),
$pSheet->getParent()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode(),
[$this, 'formatColor']
);
} else {
$cellData = \PhpOffice\PhpSpreadsheet\Style\NumberFormat::toFormattedString(
$cell->getValue(),
$pSheet->getParent()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode(),
[$this, 'formatColor']
);
}
$cellData = htmlspecialchars($cellData);
if ($pSheet->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont()->getSuperScript()) {
$cellData = '<sup>' . $cellData . '</sup>';
} elseif ($pSheet->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont()->getSubScript()) {
$cellData = '<sub>' . $cellData . '</sub>';
}
}
// Converts the cell content so that spaces occuring at beginning of each new line are replaced by &nbsp;
// Example: " Hello\n to the world" is converted to "&nbsp;&nbsp;Hello\n&nbsp;to the world"
$cellData = preg_replace('/(?m)(?:^|\\G) /', '&nbsp;', $cellData);
// convert newline "\n" to '<br>'
$cellData = nl2br($cellData);
// Extend CSS class?
if (!$this->useInlineCss) {
$cssClass .= ' style' . $cell->getXfIndex();
$cssClass .= ' ' . $cell->getDataType();
} else {
if ($cellType == 'th') {
if (isset($this->cssStyles['th.style' . $cell->getXfIndex()])) {
$cssClass = array_merge($cssClass, $this->cssStyles['th.style' . $cell->getXfIndex()]);
}
} else {
if (isset($this->cssStyles['td.style' . $cell->getXfIndex()])) {
$cssClass = array_merge($cssClass, $this->cssStyles['td.style' . $cell->getXfIndex()]);
}
}
// General horizontal alignment: Actual horizontal alignment depends on dataType
$sharedStyle = $pSheet->getParent()->getCellXfByIndex($cell->getXfIndex());
if ($sharedStyle->getAlignment()->getHorizontal() == \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_GENERAL
&& isset($this->cssStyles['.' . $cell->getDataType()]['text-align'])
) {
$cssClass['text-align'] = $this->cssStyles['.' . $cell->getDataType()]['text-align'];
}
}
}
// Hyperlink?
if ($pSheet->hyperlinkExists($coordinate) && !$pSheet->getHyperlink($coordinate)->isInternal()) {
$cellData = '<a href="' . htmlspecialchars($pSheet->getHyperlink($coordinate)->getUrl()) . '" title="' . htmlspecialchars($pSheet->getHyperlink($coordinate)->getTooltip()) . '">' . $cellData . '</a>';
}
// Should the cell be written or is it swallowed by a rowspan or colspan?
$writeCell = !(isset($this->isSpannedCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum])
&& $this->isSpannedCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum]);
// Colspan and Rowspan
$colspan = 1;
$rowspan = 1;
if (isset($this->isBaseCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum])) {
$spans = $this->isBaseCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum];
$rowSpan = $spans['rowspan'];
$colSpan = $spans['colspan'];
// Also apply style from last cell in merge to fix borders -
// relies on !important for non-none border declarations in createCSSStyleBorder
$endCellCoord = \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($colNum + $colSpan - 1) . ($pRow + $rowSpan);
if (!$this->useInlineCss) {
$cssClass .= ' style' . $pSheet->getCell($endCellCoord)->getXfIndex();
}
}
// Write
if ($writeCell) {
// Column start
$html .= ' <' . $cellType;
if (!$this->useInlineCss) {
$html .= ' class="' . $cssClass . '"';
} else {
//** Necessary redundant code for the sake of \PhpOffice\PhpSpreadsheet\Writer\Pdf **
// We must explicitly write the width of the <td> element because TCPDF
// does not recognize e.g. <col style="width:42pt">
$width = 0;
$i = $colNum - 1;
$e = $colNum + $colSpan - 1;
while ($i++ < $e) {
if (isset($this->columnWidths[$sheetIndex][$i])) {
$width += $this->columnWidths[$sheetIndex][$i];
}
}
$cssClass['width'] = $width . 'pt';
// We must also explicitly write the height of the <td> element because TCPDF
// does not recognize e.g. <tr style="height:50pt">
if (isset($this->cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]['height'])) {
$height = $this->cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]['height'];
$cssClass['height'] = $height;
}
//** end of redundant code **
$html .= ' style="' . $this->assembleCSS($cssClass) . '"';
}
if ($colSpan > 1) {
$html .= ' colspan="' . $colSpan . '"';
}
if ($rowSpan > 1) {
$html .= ' rowspan="' . $rowSpan . '"';
}
$html .= '>';
// Image?
$html .= $this->writeImageInCell($pSheet, $coordinate);
// Chart?
if ($this->includeCharts) {
$html .= $this->writeChartInCell($pSheet, $coordinate);
}
// Cell data
$html .= $cellData;
// Column end
$html .= '</' . $cellType . '>' . PHP_EOL;
}
// Next column
++$colNum;
}
// Write row end
$html .= ' </tr>' . PHP_EOL;
// Return
return $html;
} }
throw new \PhpOffice\PhpSpreadsheet\Writer\Exception('Invalid parameters passed.');
// Write row start
if (!$this->useInlineCss) {
$html .= ' <tr class="row' . $pRow . '">' . PHP_EOL;
} else {
$style = isset($this->cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow])
? $this->assembleCSS($this->cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]) : '';
$html .= ' <tr style="' . $style . '">' . PHP_EOL;
}
// Write cells
$colNum = 0;
foreach ($pValues as $cellAddress) {
$cell = ($cellAddress > '') ? $pSheet->getCell($cellAddress) : '';
$coordinate = \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($colNum) . ($pRow + 1);
if (!$this->useInlineCss) {
$cssClass = '';
$cssClass = 'column' . $colNum;
} else {
$cssClass = [];
if ($cellType == 'th') {
if (isset($this->cssStyles['table.sheet' . $sheetIndex . ' th.column' . $colNum])) {
$this->cssStyles['table.sheet' . $sheetIndex . ' th.column' . $colNum];
}
} else {
if (isset($this->cssStyles['table.sheet' . $sheetIndex . ' td.column' . $colNum])) {
$this->cssStyles['table.sheet' . $sheetIndex . ' td.column' . $colNum];
}
}
}
$colSpan = 1;
$rowSpan = 1;
// initialize
$cellData = '&nbsp;';
// \PhpOffice\PhpSpreadsheet\Cell
if ($cell instanceof \PhpOffice\PhpSpreadsheet\Cell) {
$cellData = '';
if (is_null($cell->getParent())) {
$cell->attach($pSheet);
}
// Value
if ($cell->getValue() instanceof \PhpOffice\PhpSpreadsheet\RichText) {
// Loop through rich text elements
$elements = $cell->getValue()->getRichTextElements();
foreach ($elements as $element) {
// Rich text start?
if ($element instanceof \PhpOffice\PhpSpreadsheet\RichText\Run) {
$cellData .= '<span style="' . $this->assembleCSS($this->createCSSStyleFont($element->getFont())) . '">';
if ($element->getFont()->getSuperScript()) {
$cellData .= '<sup>';
} elseif ($element->getFont()->getSubScript()) {
$cellData .= '<sub>';
}
}
// Convert UTF8 data to PCDATA
$cellText = $element->getText();
$cellData .= htmlspecialchars($cellText);
if ($element instanceof \PhpOffice\PhpSpreadsheet\RichText\Run) {
if ($element->getFont()->getSuperScript()) {
$cellData .= '</sup>';
} elseif ($element->getFont()->getSubScript()) {
$cellData .= '</sub>';
}
$cellData .= '</span>';
}
}
} else {
if ($this->preCalculateFormulas) {
$cellData = \PhpOffice\PhpSpreadsheet\Style\NumberFormat::toFormattedString(
$cell->getCalculatedValue(),
$pSheet->getParent()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode(),
[$this, 'formatColor']
);
} else {
$cellData = \PhpOffice\PhpSpreadsheet\Style\NumberFormat::toFormattedString(
$cell->getValue(),
$pSheet->getParent()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode(),
[$this, 'formatColor']
);
}
$cellData = htmlspecialchars($cellData);
if ($pSheet->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont()->getSuperScript()) {
$cellData = '<sup>' . $cellData . '</sup>';
} elseif ($pSheet->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont()->getSubScript()) {
$cellData = '<sub>' . $cellData . '</sub>';
}
}
// Converts the cell content so that spaces occuring at beginning of each new line are replaced by &nbsp;
// Example: " Hello\n to the world" is converted to "&nbsp;&nbsp;Hello\n&nbsp;to the world"
$cellData = preg_replace('/(?m)(?:^|\\G) /', '&nbsp;', $cellData);
// convert newline "\n" to '<br>'
$cellData = nl2br($cellData);
// Extend CSS class?
if (!$this->useInlineCss) {
$cssClass .= ' style' . $cell->getXfIndex();
$cssClass .= ' ' . $cell->getDataType();
} else {
if ($cellType == 'th') {
if (isset($this->cssStyles['th.style' . $cell->getXfIndex()])) {
$cssClass = array_merge($cssClass, $this->cssStyles['th.style' . $cell->getXfIndex()]);
}
} else {
if (isset($this->cssStyles['td.style' . $cell->getXfIndex()])) {
$cssClass = array_merge($cssClass, $this->cssStyles['td.style' . $cell->getXfIndex()]);
}
}
// General horizontal alignment: Actual horizontal alignment depends on dataType
$sharedStyle = $pSheet->getParent()->getCellXfByIndex($cell->getXfIndex());
if ($sharedStyle->getAlignment()->getHorizontal() == \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_GENERAL
&& isset($this->cssStyles['.' . $cell->getDataType()]['text-align'])
) {
$cssClass['text-align'] = $this->cssStyles['.' . $cell->getDataType()]['text-align'];
}
}
}
// Hyperlink?
if ($pSheet->hyperlinkExists($coordinate) && !$pSheet->getHyperlink($coordinate)->isInternal()) {
$cellData = '<a href="' . htmlspecialchars($pSheet->getHyperlink($coordinate)->getUrl()) . '" title="' . htmlspecialchars($pSheet->getHyperlink($coordinate)->getTooltip()) . '">' . $cellData . '</a>';
}
// Should the cell be written or is it swallowed by a rowspan or colspan?
$writeCell = !(isset($this->isSpannedCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum])
&& $this->isSpannedCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum]);
// Colspan and Rowspan
$colspan = 1;
$rowspan = 1;
if (isset($this->isBaseCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum])) {
$spans = $this->isBaseCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum];
$rowSpan = $spans['rowspan'];
$colSpan = $spans['colspan'];
// Also apply style from last cell in merge to fix borders -
// relies on !important for non-none border declarations in createCSSStyleBorder
$endCellCoord = \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($colNum + $colSpan - 1) . ($pRow + $rowSpan);
if (!$this->useInlineCss) {
$cssClass .= ' style' . $pSheet->getCell($endCellCoord)->getXfIndex();
}
}
// Write
if ($writeCell) {
// Column start
$html .= ' <' . $cellType;
if (!$this->useInlineCss) {
$html .= ' class="' . $cssClass . '"';
} else {
//** Necessary redundant code for the sake of \PhpOffice\PhpSpreadsheet\Writer\Pdf **
// We must explicitly write the width of the <td> element because TCPDF
// does not recognize e.g. <col style="width:42pt">
$width = 0;
$i = $colNum - 1;
$e = $colNum + $colSpan - 1;
while ($i++ < $e) {
if (isset($this->columnWidths[$sheetIndex][$i])) {
$width += $this->columnWidths[$sheetIndex][$i];
}
}
$cssClass['width'] = $width . 'pt';
// We must also explicitly write the height of the <td> element because TCPDF
// does not recognize e.g. <tr style="height:50pt">
if (isset($this->cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]['height'])) {
$height = $this->cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]['height'];
$cssClass['height'] = $height;
}
//** end of redundant code **
$html .= ' style="' . $this->assembleCSS($cssClass) . '"';
}
if ($colSpan > 1) {
$html .= ' colspan="' . $colSpan . '"';
}
if ($rowSpan > 1) {
$html .= ' rowspan="' . $rowSpan . '"';
}
$html .= '>';
// Image?
$html .= $this->writeImageInCell($pSheet, $coordinate);
// Chart?
if ($this->includeCharts) {
$html .= $this->writeChartInCell($pSheet, $coordinate);
}
// Cell data
$html .= $cellData;
// Column end
$html .= '</' . $cellType . '>' . PHP_EOL;
}
// Next column
++$colNum;
}
// Write row end
$html .= ' </tr>' . PHP_EOL;
// Return
return $html;
} }
/** /**

View File

@ -210,7 +210,7 @@ class ContentTypes extends WriterPart
* *
* @throws \PhpOffice\PhpSpreadsheet\Writer\Exception * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
*/ */
private function writeDefaultContentType(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter $objWriter = null, $pPartname = '', $pContentType = '') private function writeDefaultContentType(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter $objWriter, $pPartname, $pContentType)
{ {
if ($pPartname != '' && $pContentType != '') { if ($pPartname != '' && $pContentType != '') {
// Write content type // Write content type
@ -232,7 +232,7 @@ class ContentTypes extends WriterPart
* *
* @throws \PhpOffice\PhpSpreadsheet\Writer\Exception * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
*/ */
private function writeOverrideContentType(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter $objWriter = null, $pPartname = '', $pContentType = '') private function writeOverrideContentType(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter $objWriter, $pPartname, $pContentType)
{ {
if ($pPartname != '' && $pContentType != '') { if ($pPartname != '' && $pContentType != '') {
// Write content type // Write content type

View File

@ -163,7 +163,7 @@ class Drawing extends WriterPart
* *
* @throws \PhpOffice\PhpSpreadsheet\Writer\Exception * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
*/ */
public function writeDrawing(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter $objWriter = null, \PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing $pDrawing = null, $pRelationId = -1) public function writeDrawing(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter $objWriter, \PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing $pDrawing, $pRelationId = -1)
{ {
if ($pRelationId >= 0) { if ($pRelationId >= 0) {
// xdr:oneCellAnchor // xdr:oneCellAnchor
@ -271,54 +271,6 @@ class Drawing extends WriterPart
$objWriter->endElement(); $objWriter->endElement();
} }
/*
// a:scene3d
$objWriter->startElement('a:scene3d');
// a:camera
$objWriter->startElement('a:camera');
$objWriter->writeAttribute('prst', 'orthographicFront');
$objWriter->endElement();
// a:lightRig
$objWriter->startElement('a:lightRig');
$objWriter->writeAttribute('rig', 'twoPt');
$objWriter->writeAttribute('dir', 't');
// a:rot
$objWriter->startElement('a:rot');
$objWriter->writeAttribute('lat', '0');
$objWriter->writeAttribute('lon', '0');
$objWriter->writeAttribute('rev', '0');
$objWriter->endElement();
$objWriter->endElement();
$objWriter->endElement();
*/
/*
// a:sp3d
$objWriter->startElement('a:sp3d');
// a:bevelT
$objWriter->startElement('a:bevelT');
$objWriter->writeAttribute('w', '25400');
$objWriter->writeAttribute('h', '19050');
$objWriter->endElement();
// a:contourClr
$objWriter->startElement('a:contourClr');
// a:srgbClr
$objWriter->startElement('a:srgbClr');
$objWriter->writeAttribute('val', 'FFFFFF');
$objWriter->endElement();
$objWriter->endElement();
$objWriter->endElement();
*/
$objWriter->endElement(); $objWriter->endElement();
$objWriter->endElement(); $objWriter->endElement();

View File

@ -397,7 +397,7 @@ class Rels extends WriterPart
* *
* @throws \PhpOffice\PhpSpreadsheet\Writer\Exception * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
*/ */
private function writeRelationship(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter $objWriter = null, $pId = 1, $pType = '', $pTarget = '', $pTargetMode = '') private function writeRelationship(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter $objWriter, $pId, $pType, $pTarget, $pTargetMode = '')
{ {
if ($pType != '' && $pTarget != '') { if ($pType != '' && $pTarget != '') {
// Write relationship // Write relationship

View File

@ -241,7 +241,7 @@ class Workbook extends WriterPart
* *
* @throws \PhpOffice\PhpSpreadsheet\Writer\Exception * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
*/ */
private function writeSheet(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter $objWriter, $pSheetname = '', $pSheetId = 1, $pRelId = 1, $sheetState = 'visible') private function writeSheet(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter $objWriter, $pSheetname, $pSheetId = 1, $pRelId = 1, $sheetState = 'visible')
{ {
if ($pSheetname != '') { if ($pSheetname != '') {
// Write sheet // Write sheet

View File

@ -978,86 +978,82 @@ class Worksheet extends WriterPart
* *
* @throws \PhpOffice\PhpSpreadsheet\Writer\Exception * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
*/ */
private function writeSheetData(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter $objWriter = null, \PhpOffice\PhpSpreadsheet\Worksheet $pSheet = null, $pStringTable = null) private function writeSheetData(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter $objWriter, \PhpOffice\PhpSpreadsheet\Worksheet $pSheet, array $pStringTable)
{ {
if (is_array($pStringTable)) { // Flipped stringtable, for faster index searching
// Flipped stringtable, for faster index searching $aFlippedStringTable = $this->getParentWriter()->getWriterPart('stringtable')->flipStringTable($pStringTable);
$aFlippedStringTable = $this->getParentWriter()->getWriterPart('stringtable')->flipStringTable($pStringTable);
// sheetData // sheetData
$objWriter->startElement('sheetData'); $objWriter->startElement('sheetData');
// Get column count // Get column count
$colCount = \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($pSheet->getHighestColumn()); $colCount = \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($pSheet->getHighestColumn());
// Highest row number // Highest row number
$highestRow = $pSheet->getHighestRow(); $highestRow = $pSheet->getHighestRow();
// Loop through cells // Loop through cells
$cellsByRow = []; $cellsByRow = [];
foreach ($pSheet->getCoordinates() as $coordinate) { foreach ($pSheet->getCoordinates() as $coordinate) {
$cellAddress = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($coordinate); $cellAddress = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($coordinate);
$cellsByRow[$cellAddress[1]][] = $coordinate; $cellsByRow[$cellAddress[1]][] = $coordinate;
}
$currentRow = 0;
while ($currentRow++ < $highestRow) {
// Get row dimension
$rowDimension = $pSheet->getRowDimension($currentRow);
// Write current row?
$writeCurrentRow = isset($cellsByRow[$currentRow]) || $rowDimension->getRowHeight() >= 0 || $rowDimension->getVisible() == false || $rowDimension->getCollapsed() == true || $rowDimension->getOutlineLevel() > 0 || $rowDimension->getXfIndex() !== null;
if ($writeCurrentRow) {
// Start a new row
$objWriter->startElement('row');
$objWriter->writeAttribute('r', $currentRow);
$objWriter->writeAttribute('spans', '1:' . $colCount);
// Row dimensions
if ($rowDimension->getRowHeight() >= 0) {
$objWriter->writeAttribute('customHeight', '1');
$objWriter->writeAttribute('ht', \PhpOffice\PhpSpreadsheet\Shared\StringHelper::formatNumber($rowDimension->getRowHeight()));
}
// Row visibility
if ($rowDimension->getVisible() == false) {
$objWriter->writeAttribute('hidden', 'true');
}
// Collapsed
if ($rowDimension->getCollapsed() == true) {
$objWriter->writeAttribute('collapsed', 'true');
}
// Outline level
if ($rowDimension->getOutlineLevel() > 0) {
$objWriter->writeAttribute('outlineLevel', $rowDimension->getOutlineLevel());
}
// Style
if ($rowDimension->getXfIndex() !== null) {
$objWriter->writeAttribute('s', $rowDimension->getXfIndex());
$objWriter->writeAttribute('customFormat', '1');
}
// Write cells
if (isset($cellsByRow[$currentRow])) {
foreach ($cellsByRow[$currentRow] as $cellAddress) {
// Write cell
$this->writeCell($objWriter, $pSheet, $cellAddress, $pStringTable, $aFlippedStringTable);
}
}
// End row
$objWriter->endElement();
}
}
$objWriter->endElement();
} else {
throw new \PhpOffice\PhpSpreadsheet\Writer\Exception('Invalid parameters passed.');
} }
$currentRow = 0;
while ($currentRow++ < $highestRow) {
// Get row dimension
$rowDimension = $pSheet->getRowDimension($currentRow);
// Write current row?
$writeCurrentRow = isset($cellsByRow[$currentRow]) || $rowDimension->getRowHeight() >= 0 || $rowDimension->getVisible() == false || $rowDimension->getCollapsed() == true || $rowDimension->getOutlineLevel() > 0 || $rowDimension->getXfIndex() !== null;
if ($writeCurrentRow) {
// Start a new row
$objWriter->startElement('row');
$objWriter->writeAttribute('r', $currentRow);
$objWriter->writeAttribute('spans', '1:' . $colCount);
// Row dimensions
if ($rowDimension->getRowHeight() >= 0) {
$objWriter->writeAttribute('customHeight', '1');
$objWriter->writeAttribute('ht', \PhpOffice\PhpSpreadsheet\Shared\StringHelper::formatNumber($rowDimension->getRowHeight()));
}
// Row visibility
if ($rowDimension->getVisible() == false) {
$objWriter->writeAttribute('hidden', 'true');
}
// Collapsed
if ($rowDimension->getCollapsed() == true) {
$objWriter->writeAttribute('collapsed', 'true');
}
// Outline level
if ($rowDimension->getOutlineLevel() > 0) {
$objWriter->writeAttribute('outlineLevel', $rowDimension->getOutlineLevel());
}
// Style
if ($rowDimension->getXfIndex() !== null) {
$objWriter->writeAttribute('s', $rowDimension->getXfIndex());
$objWriter->writeAttribute('customFormat', '1');
}
// Write cells
if (isset($cellsByRow[$currentRow])) {
foreach ($cellsByRow[$currentRow] as $cellAddress) {
// Write cell
$this->writeCell($objWriter, $pSheet, $cellAddress, $aFlippedStringTable);
}
}
// End row
$objWriter->endElement();
}
}
$objWriter->endElement();
} }
/** /**
@ -1071,113 +1067,109 @@ class Worksheet extends WriterPart
* *
* @throws \PhpOffice\PhpSpreadsheet\Writer\Exception * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
*/ */
private function writeCell(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter $objWriter = null, \PhpOffice\PhpSpreadsheet\Worksheet $pSheet = null, $pCellAddress = null, $pStringTable = null, $pFlippedStringTable = null) private function writeCell(\PhpOffice\PhpSpreadsheet\Shared\XMLWriter $objWriter, \PhpOffice\PhpSpreadsheet\Worksheet $pSheet, $pCellAddress, array $pFlippedStringTable)
{ {
if (is_array($pStringTable) && is_array($pFlippedStringTable)) { // Cell
// Cell $pCell = $pSheet->getCell($pCellAddress);
$pCell = $pSheet->getCell($pCellAddress); $objWriter->startElement('c');
$objWriter->startElement('c'); $objWriter->writeAttribute('r', $pCellAddress);
$objWriter->writeAttribute('r', $pCellAddress);
// Sheet styles // Sheet styles
if ($pCell->getXfIndex() != '') { if ($pCell->getXfIndex() != '') {
$objWriter->writeAttribute('s', $pCell->getXfIndex()); $objWriter->writeAttribute('s', $pCell->getXfIndex());
}
// If cell value is supplied, write cell value
$cellValue = $pCell->getValue();
if (is_object($cellValue) || $cellValue !== '') {
// Map type
$mappedType = $pCell->getDataType();
// Write data type depending on its type
switch (strtolower($mappedType)) {
case 'inlinestr': // Inline string
case 's': // String
case 'b': // Boolean
$objWriter->writeAttribute('t', $mappedType);
break;
case 'f': // Formula
$calculatedValue = ($this->getParentWriter()->getPreCalculateFormulas()) ?
$pCell->getCalculatedValue() : $cellValue;
if (is_string($calculatedValue)) {
$objWriter->writeAttribute('t', 'str');
}
break;
case 'e': // Error
$objWriter->writeAttribute('t', $mappedType);
} }
// If cell value is supplied, write cell value // Write data depending on its type
$cellValue = $pCell->getValue(); switch (strtolower($mappedType)) {
if (is_object($cellValue) || $cellValue !== '') { case 'inlinestr': // Inline string
// Map type if (!$cellValue instanceof \PhpOffice\PhpSpreadsheet\RichText) {
$mappedType = $pCell->getDataType(); $objWriter->writeElement('t', \PhpOffice\PhpSpreadsheet\Shared\StringHelper::controlCharacterPHP2OOXML(htmlspecialchars($cellValue)));
} elseif ($cellValue instanceof \PhpOffice\PhpSpreadsheet\RichText) {
$objWriter->startElement('is');
$this->getParentWriter()->getWriterPart('stringtable')->writeRichText($objWriter, $cellValue);
$objWriter->endElement();
}
// Write data type depending on its type break;
switch (strtolower($mappedType)) { case 's': // String
case 'inlinestr': // Inline string if (!$cellValue instanceof \PhpOffice\PhpSpreadsheet\RichText) {
case 's': // String if (isset($pFlippedStringTable[$cellValue])) {
case 'b': // Boolean $objWriter->writeElement('v', $pFlippedStringTable[$cellValue]);
$objWriter->writeAttribute('t', $mappedType);
break;
case 'f': // Formula
$calculatedValue = ($this->getParentWriter()->getPreCalculateFormulas()) ?
$pCell->getCalculatedValue() : $cellValue;
if (is_string($calculatedValue)) {
$objWriter->writeAttribute('t', 'str');
} }
break; } elseif ($cellValue instanceof \PhpOffice\PhpSpreadsheet\RichText) {
case 'e': // Error $objWriter->writeElement('v', $pFlippedStringTable[$cellValue->getHashCode()]);
$objWriter->writeAttribute('t', $mappedType); }
}
// Write data depending on its type break;
switch (strtolower($mappedType)) { case 'f': // Formula
case 'inlinestr': // Inline string $attributes = $pCell->getFormulaAttributes();
if (!$cellValue instanceof \PhpOffice\PhpSpreadsheet\RichText) { if ($attributes['t'] == 'array') {
$objWriter->writeElement('t', \PhpOffice\PhpSpreadsheet\Shared\StringHelper::controlCharacterPHP2OOXML(htmlspecialchars($cellValue))); $objWriter->startElement('f');
} elseif ($cellValue instanceof \PhpOffice\PhpSpreadsheet\RichText) { $objWriter->writeAttribute('t', 'array');
$objWriter->startElement('is'); $objWriter->writeAttribute('ref', $pCellAddress);
$this->getParentWriter()->getWriterPart('stringtable')->writeRichText($objWriter, $cellValue); $objWriter->writeAttribute('aca', '1');
$objWriter->endElement(); $objWriter->writeAttribute('ca', '1');
} $objWriter->text(substr($cellValue, 1));
$objWriter->endElement();
break; } else {
case 's': // String $objWriter->writeElement('f', substr($cellValue, 1));
if (!$cellValue instanceof \PhpOffice\PhpSpreadsheet\RichText) { }
if (isset($pFlippedStringTable[$cellValue])) { if ($this->getParentWriter()->getOffice2003Compatibility() === false) {
$objWriter->writeElement('v', $pFlippedStringTable[$cellValue]); if ($this->getParentWriter()->getPreCalculateFormulas()) {
} if (!is_array($calculatedValue) && substr($calculatedValue, 0, 1) != '#') {
} elseif ($cellValue instanceof \PhpOffice\PhpSpreadsheet\RichText) { $objWriter->writeElement('v', \PhpOffice\PhpSpreadsheet\Shared\StringHelper::formatNumber($calculatedValue));
$objWriter->writeElement('v', $pFlippedStringTable[$cellValue->getHashCode()]);
}
break;
case 'f': // Formula
$attributes = $pCell->getFormulaAttributes();
if ($attributes['t'] == 'array') {
$objWriter->startElement('f');
$objWriter->writeAttribute('t', 'array');
$objWriter->writeAttribute('ref', $pCellAddress);
$objWriter->writeAttribute('aca', '1');
$objWriter->writeAttribute('ca', '1');
$objWriter->text(substr($cellValue, 1));
$objWriter->endElement();
} else {
$objWriter->writeElement('f', substr($cellValue, 1));
}
if ($this->getParentWriter()->getOffice2003Compatibility() === false) {
if ($this->getParentWriter()->getPreCalculateFormulas()) {
if (!is_array($calculatedValue) && substr($calculatedValue, 0, 1) != '#') {
$objWriter->writeElement('v', \PhpOffice\PhpSpreadsheet\Shared\StringHelper::formatNumber($calculatedValue));
} else {
$objWriter->writeElement('v', '0');
}
} else { } else {
$objWriter->writeElement('v', '0'); $objWriter->writeElement('v', '0');
} }
}
break;
case 'n': // Numeric
// force point as decimal separator in case current locale uses comma
$objWriter->writeElement('v', str_replace(',', '.', $cellValue));
break;
case 'b': // Boolean
$objWriter->writeElement('v', ($cellValue ? '1' : '0'));
break;
case 'e': // Error
if (substr($cellValue, 0, 1) == '=') {
$objWriter->writeElement('f', substr($cellValue, 1));
$objWriter->writeElement('v', substr($cellValue, 1));
} else { } else {
$objWriter->writeElement('v', $cellValue); $objWriter->writeElement('v', '0');
} }
}
break;
case 'n': // Numeric
// force point as decimal separator in case current locale uses comma
$objWriter->writeElement('v', str_replace(',', '.', $cellValue));
break;
case 'b': // Boolean
$objWriter->writeElement('v', ($cellValue ? '1' : '0'));
break;
case 'e': // Error
if (substr($cellValue, 0, 1) == '=') {
$objWriter->writeElement('f', substr($cellValue, 1));
$objWriter->writeElement('v', substr($cellValue, 1));
} else {
$objWriter->writeElement('v', $cellValue);
}
break; break;
}
} }
$objWriter->endElement();
} else {
throw new \PhpOffice\PhpSpreadsheet\Writer\Exception('Invalid parameters passed.');
} }
$objWriter->endElement();
} }
/** /**

View File

@ -223,18 +223,17 @@ class CellTest extends \PHPUnit_Framework_TestCase
return require 'data/CellBuildRange.php'; return require 'data/CellBuildRange.php';
} }
/**
* @expectedException \TypeError
*/
public function testBuildRangeInvalid() public function testBuildRangeInvalid()
{ {
$cellRange = ''; if (PHP_MAJOR_VERSION < 7) {
try { $this->markTestSkipped('Cannot catch type hinting error with PHP 5.6');
Cell::buildRange($cellRange);
} catch (\Exception $e) {
$this->assertInstanceOf(Exception::class, $e);
$this->assertEquals($e->getMessage(), 'Range does not contain any information');
return;
} }
$this->fail('An expected exception has not been raised.');
$cellRange = '';
Cell::buildRange($cellRange);
} }
/** /**