Refactoring xlsx reader (#1033)
Start work on breaking up monolithic Reader and Writer classes into dedicated subclasses to make maintenance work easier
This commit is contained in:
parent
e884271dc2
commit
1e711541f1
@ -39,7 +39,7 @@
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": "5.6|^7.0",
|
||||
"php": "^5.6|^7.0",
|
||||
"ext-ctype": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-gd": "*",
|
||||
|
@ -418,7 +418,7 @@ class Properties
|
||||
*
|
||||
* @param string $propertyName
|
||||
*
|
||||
* @return string
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCustomPropertyValue($propertyName)
|
||||
{
|
||||
|
@ -7,7 +7,7 @@ use DateTimeZone;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||
use PhpOffice\PhpSpreadsheet\Document\Properties;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Ods\Properties as DocumentProperties;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Security\XmlScanner;
|
||||
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
||||
use PhpOffice\PhpSpreadsheet\Settings;
|
||||
@ -265,7 +265,7 @@ class Ods extends BaseReader
|
||||
|
||||
$zip = new ZipArchive();
|
||||
if (!$zip->open($pFilename)) {
|
||||
throw new Exception('Could not open ' . $pFilename . ' for reading! Error opening file.');
|
||||
throw new Exception("Could not open {$pFilename} for reading! Error opening file.");
|
||||
}
|
||||
|
||||
// Meta
|
||||
@ -275,97 +275,13 @@ class Ods extends BaseReader
|
||||
'SimpleXMLElement',
|
||||
Settings::getLibXmlLoaderOptions()
|
||||
);
|
||||
if ($xml === false) {
|
||||
throw new Exception('Unable to read data from {$pFilename}');
|
||||
}
|
||||
|
||||
$namespacesMeta = $xml->getNamespaces(true);
|
||||
|
||||
$docProps = $spreadsheet->getProperties();
|
||||
$officeProperty = $xml->children($namespacesMeta['office']);
|
||||
foreach ($officeProperty as $officePropertyData) {
|
||||
$officePropertyDC = [];
|
||||
if (isset($namespacesMeta['dc'])) {
|
||||
$officePropertyDC = $officePropertyData->children($namespacesMeta['dc']);
|
||||
}
|
||||
foreach ($officePropertyDC as $propertyName => $propertyValue) {
|
||||
$propertyValue = (string) $propertyValue;
|
||||
switch ($propertyName) {
|
||||
case 'title':
|
||||
$docProps->setTitle($propertyValue);
|
||||
|
||||
break;
|
||||
case 'subject':
|
||||
$docProps->setSubject($propertyValue);
|
||||
|
||||
break;
|
||||
case 'creator':
|
||||
$docProps->setCreator($propertyValue);
|
||||
$docProps->setLastModifiedBy($propertyValue);
|
||||
|
||||
break;
|
||||
case 'date':
|
||||
$creationDate = strtotime($propertyValue);
|
||||
$docProps->setCreated($creationDate);
|
||||
$docProps->setModified($creationDate);
|
||||
|
||||
break;
|
||||
case 'description':
|
||||
$docProps->setDescription($propertyValue);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
$officePropertyMeta = [];
|
||||
if (isset($namespacesMeta['dc'])) {
|
||||
$officePropertyMeta = $officePropertyData->children($namespacesMeta['meta']);
|
||||
}
|
||||
foreach ($officePropertyMeta as $propertyName => $propertyValue) {
|
||||
$propertyValueAttributes = $propertyValue->attributes($namespacesMeta['meta']);
|
||||
$propertyValue = (string) $propertyValue;
|
||||
switch ($propertyName) {
|
||||
case 'initial-creator':
|
||||
$docProps->setCreator($propertyValue);
|
||||
|
||||
break;
|
||||
case 'keyword':
|
||||
$docProps->setKeywords($propertyValue);
|
||||
|
||||
break;
|
||||
case 'creation-date':
|
||||
$creationDate = strtotime($propertyValue);
|
||||
$docProps->setCreated($creationDate);
|
||||
|
||||
break;
|
||||
case 'user-defined':
|
||||
$propertyValueType = Properties::PROPERTY_TYPE_STRING;
|
||||
foreach ($propertyValueAttributes as $key => $value) {
|
||||
if ($key == 'name') {
|
||||
$propertyValueName = (string) $value;
|
||||
} elseif ($key == 'value-type') {
|
||||
switch ($value) {
|
||||
case 'date':
|
||||
$propertyValue = Properties::convertProperty($propertyValue, 'date');
|
||||
$propertyValueType = Properties::PROPERTY_TYPE_DATE;
|
||||
|
||||
break;
|
||||
case 'boolean':
|
||||
$propertyValue = Properties::convertProperty($propertyValue, 'bool');
|
||||
$propertyValueType = Properties::PROPERTY_TYPE_BOOLEAN;
|
||||
|
||||
break;
|
||||
case 'float':
|
||||
$propertyValue = Properties::convertProperty($propertyValue, 'r4');
|
||||
$propertyValueType = Properties::PROPERTY_TYPE_FLOAT;
|
||||
|
||||
break;
|
||||
default:
|
||||
$propertyValueType = Properties::PROPERTY_TYPE_STRING;
|
||||
}
|
||||
}
|
||||
}
|
||||
$docProps->setCustomProperty($propertyValueName, $propertyValue, $propertyValueType);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
(new DocumentProperties($spreadsheet))->load($xml, $namespacesMeta);
|
||||
|
||||
// Content
|
||||
|
||||
|
136
src/PhpSpreadsheet/Reader/Ods/Properties.php
Normal file
136
src/PhpSpreadsheet/Reader/Ods/Properties.php
Normal file
@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Reader\Ods;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Document\Properties as DocumentProperties;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
|
||||
class Properties
|
||||
{
|
||||
private $spreadsheet;
|
||||
|
||||
public function __construct(Spreadsheet $spreadsheet)
|
||||
{
|
||||
$this->spreadsheet = $spreadsheet;
|
||||
}
|
||||
|
||||
public function load(\SimpleXMLElement $xml, $namespacesMeta)
|
||||
{
|
||||
$docProps = $this->spreadsheet->getProperties();
|
||||
$officeProperty = $xml->children($namespacesMeta['office']);
|
||||
foreach ($officeProperty as $officePropertyData) {
|
||||
/** @var \SimpleXMLElement $officePropertyData */
|
||||
$officePropertiesDC = [];
|
||||
if (isset($namespacesMeta['dc'])) {
|
||||
$officePropertiesDC = $officePropertyData->children($namespacesMeta['dc']);
|
||||
}
|
||||
$this->setCoreProperties($docProps, $officePropertiesDC);
|
||||
|
||||
$officePropertyMeta = [];
|
||||
if (isset($namespacesMeta['dc'])) {
|
||||
$officePropertyMeta = $officePropertyData->children($namespacesMeta['meta']);
|
||||
}
|
||||
foreach ($officePropertyMeta as $propertyName => $propertyValue) {
|
||||
$this->setMetaProperties($namespacesMeta, $propertyValue, $propertyName, $docProps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function setCoreProperties(DocumentProperties $docProps, \SimpleXMLElement $officePropertyDC)
|
||||
{
|
||||
foreach ($officePropertyDC as $propertyName => $propertyValue) {
|
||||
$propertyValue = (string) $propertyValue;
|
||||
switch ($propertyName) {
|
||||
case 'title':
|
||||
$docProps->setTitle($propertyValue);
|
||||
|
||||
break;
|
||||
case 'subject':
|
||||
$docProps->setSubject($propertyValue);
|
||||
|
||||
break;
|
||||
case 'creator':
|
||||
$docProps->setCreator($propertyValue);
|
||||
$docProps->setLastModifiedBy($propertyValue);
|
||||
|
||||
break;
|
||||
case 'creation-date':
|
||||
$creationDate = strtotime($propertyValue);
|
||||
$docProps->setCreated($creationDate);
|
||||
$docProps->setModified($creationDate);
|
||||
|
||||
break;
|
||||
case 'keyword':
|
||||
$docProps->setKeywords($propertyValue);
|
||||
|
||||
break;
|
||||
case 'description':
|
||||
$docProps->setDescription($propertyValue);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function setMetaProperties(
|
||||
$namespacesMeta,
|
||||
\SimpleXMLElement $propertyValue,
|
||||
$propertyName,
|
||||
DocumentProperties $docProps
|
||||
) {
|
||||
$propertyValueAttributes = $propertyValue->attributes($namespacesMeta['meta']);
|
||||
$propertyValue = (string) $propertyValue;
|
||||
switch ($propertyName) {
|
||||
case 'initial-creator':
|
||||
$docProps->setCreator($propertyValue);
|
||||
|
||||
break;
|
||||
case 'keyword':
|
||||
$docProps->setKeywords($propertyValue);
|
||||
|
||||
break;
|
||||
case 'creation-date':
|
||||
$creationDate = strtotime($propertyValue);
|
||||
$docProps->setCreated($creationDate);
|
||||
|
||||
break;
|
||||
case 'user-defined':
|
||||
$this->setUserDefinedProperty($propertyValueAttributes, $propertyValue, $docProps);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private function setUserDefinedProperty($propertyValueAttributes, $propertyValue, DocumentProperties $docProps)
|
||||
{
|
||||
$propertyValueName = '';
|
||||
$propertyValueType = DocumentProperties::PROPERTY_TYPE_STRING;
|
||||
foreach ($propertyValueAttributes as $key => $value) {
|
||||
if ($key == 'name') {
|
||||
$propertyValueName = (string) $value;
|
||||
} elseif ($key == 'value-type') {
|
||||
switch ($value) {
|
||||
case 'date':
|
||||
$propertyValue = DocumentProperties::convertProperty($propertyValue, 'date');
|
||||
$propertyValueType = DocumentProperties::PROPERTY_TYPE_DATE;
|
||||
|
||||
break;
|
||||
case 'boolean':
|
||||
$propertyValue = DocumentProperties::convertProperty($propertyValue, 'bool');
|
||||
$propertyValueType = DocumentProperties::PROPERTY_TYPE_BOOLEAN;
|
||||
|
||||
break;
|
||||
case 'float':
|
||||
$propertyValue = DocumentProperties::convertProperty($propertyValue, 'r4');
|
||||
$propertyValueType = DocumentProperties::PROPERTY_TYPE_FLOAT;
|
||||
|
||||
break;
|
||||
default:
|
||||
$propertyValueType = DocumentProperties::PROPERTY_TYPE_STRING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$docProps->setCustomProperty($propertyValueName, $propertyValue, $propertyValueType);
|
||||
}
|
||||
}
|
@ -4,11 +4,19 @@ namespace PhpOffice\PhpSpreadsheet\Reader;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Hyperlink;
|
||||
use PhpOffice\PhpSpreadsheet\Document\Properties;
|
||||
use PhpOffice\PhpSpreadsheet\NamedRange;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Security\XmlScanner;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\AutoFilter;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Chart;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\ColumnAndRowAttributes;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\ConditionalStyles;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\DataValidations;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Hyperlinks;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\PageSetup;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Properties as PropertyReader;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\SheetViewOptions;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\SheetViews;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Styles;
|
||||
use PhpOffice\PhpSpreadsheet\ReferenceHelper;
|
||||
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
||||
use PhpOffice\PhpSpreadsheet\Settings;
|
||||
@ -21,7 +29,6 @@ use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Border;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Borders;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Color;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Conditional;
|
||||
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Protection;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Style;
|
||||
@ -324,60 +331,6 @@ class Xlsx extends BaseReader
|
||||
return $contents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Worksheet column attributes by attributes array passed.
|
||||
*
|
||||
* @param Worksheet $docSheet
|
||||
* @param string $column A, B, ... DX, ...
|
||||
* @param array $columnAttributes array of attributes (indexes are attribute name, values are value)
|
||||
* 'xfIndex', 'visible', 'collapsed', 'outlineLevel', 'width', ... ?
|
||||
*/
|
||||
private function setColumnAttributes(Worksheet $docSheet, $column, array $columnAttributes)
|
||||
{
|
||||
if (isset($columnAttributes['xfIndex'])) {
|
||||
$docSheet->getColumnDimension($column)->setXfIndex($columnAttributes['xfIndex']);
|
||||
}
|
||||
if (isset($columnAttributes['visible'])) {
|
||||
$docSheet->getColumnDimension($column)->setVisible($columnAttributes['visible']);
|
||||
}
|
||||
if (isset($columnAttributes['collapsed'])) {
|
||||
$docSheet->getColumnDimension($column)->setCollapsed($columnAttributes['collapsed']);
|
||||
}
|
||||
if (isset($columnAttributes['outlineLevel'])) {
|
||||
$docSheet->getColumnDimension($column)->setOutlineLevel($columnAttributes['outlineLevel']);
|
||||
}
|
||||
if (isset($columnAttributes['width'])) {
|
||||
$docSheet->getColumnDimension($column)->setWidth($columnAttributes['width']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Worksheet row attributes by attributes array passed.
|
||||
*
|
||||
* @param Worksheet $docSheet
|
||||
* @param int $row 1, 2, 3, ... 99, ...
|
||||
* @param array $rowAttributes array of attributes (indexes are attribute name, values are value)
|
||||
* 'xfIndex', 'visible', 'collapsed', 'outlineLevel', 'rowHeight', ... ?
|
||||
*/
|
||||
private function setRowAttributes(Worksheet $docSheet, $row, array $rowAttributes)
|
||||
{
|
||||
if (isset($rowAttributes['xfIndex'])) {
|
||||
$docSheet->getRowDimension($row)->setXfIndex($rowAttributes['xfIndex']);
|
||||
}
|
||||
if (isset($rowAttributes['visible'])) {
|
||||
$docSheet->getRowDimension($row)->setVisible($rowAttributes['visible']);
|
||||
}
|
||||
if (isset($rowAttributes['collapsed'])) {
|
||||
$docSheet->getRowDimension($row)->setCollapsed($rowAttributes['collapsed']);
|
||||
}
|
||||
if (isset($rowAttributes['outlineLevel'])) {
|
||||
$docSheet->getRowDimension($row)->setOutlineLevel($rowAttributes['outlineLevel']);
|
||||
}
|
||||
if (isset($rowAttributes['rowHeight'])) {
|
||||
$docSheet->getRowDimension($row)->setRowHeight($rowAttributes['rowHeight']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads Spreadsheet from file.
|
||||
*
|
||||
@ -537,8 +490,7 @@ class Xlsx extends BaseReader
|
||||
}
|
||||
}
|
||||
}
|
||||
$styles = [];
|
||||
$cellStyles = [];
|
||||
|
||||
$xpath = self::getArrayItem($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles']"));
|
||||
//~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
|
||||
$xmlStyles = simplexml_load_string(
|
||||
@ -546,6 +498,9 @@ class Xlsx extends BaseReader
|
||||
'SimpleXMLElement',
|
||||
Settings::getLibXmlLoaderOptions()
|
||||
);
|
||||
|
||||
$styles = [];
|
||||
$cellStyles = [];
|
||||
$numFmts = null;
|
||||
if ($xmlStyles && $xmlStyles->numFmts[0]) {
|
||||
$numFmts = $xmlStyles->numFmts[0];
|
||||
@ -625,31 +580,10 @@ class Xlsx extends BaseReader
|
||||
}
|
||||
}
|
||||
|
||||
$dxfs = [];
|
||||
if (!$this->readDataOnly && $xmlStyles) {
|
||||
// Conditional Styles
|
||||
if ($xmlStyles->dxfs) {
|
||||
foreach ($xmlStyles->dxfs->dxf as $dxf) {
|
||||
$style = new Style(false, true);
|
||||
self::readStyle($style, $dxf);
|
||||
$dxfs[] = $style;
|
||||
}
|
||||
}
|
||||
// Cell Styles
|
||||
if ($xmlStyles->cellStyles) {
|
||||
foreach ($xmlStyles->cellStyles->cellStyle as $cellStyle) {
|
||||
if ((int) ($cellStyle['builtinId']) == 0) {
|
||||
if (isset($cellStyles[(int) ($cellStyle['xfId'])])) {
|
||||
// Set default style
|
||||
$style = new Style();
|
||||
self::readStyle($style, $cellStyles[(int) ($cellStyle['xfId'])]);
|
||||
|
||||
// normal style, currently not using it for anything
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$styleReader = new Styles($xmlStyles);
|
||||
$styleReader->setStyleBaseData(self::$theme, $styles, $cellStyles);
|
||||
$dxfs = $styleReader->dxfs($this->readDataOnly);
|
||||
$styles = $styleReader->styles();
|
||||
|
||||
//~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
|
||||
$xmlWorkbook = simplexml_load_string(
|
||||
@ -716,134 +650,19 @@ class Xlsx extends BaseReader
|
||||
$docSheet->setSheetState((string) $eleSheet['state']);
|
||||
}
|
||||
|
||||
if (isset($xmlSheet->sheetViews, $xmlSheet->sheetViews->sheetView)) {
|
||||
if (isset($xmlSheet->sheetViews->sheetView['zoomScale'])) {
|
||||
$zoomScale = (int) ($xmlSheet->sheetViews->sheetView['zoomScale']);
|
||||
if ($zoomScale <= 0) {
|
||||
// setZoomScale will throw an Exception if the scale is less than or equals 0
|
||||
// that is OK when manually creating documents, but we should be able to read all documents
|
||||
$zoomScale = 100;
|
||||
}
|
||||
|
||||
$docSheet->getSheetView()->setZoomScale($zoomScale);
|
||||
}
|
||||
if (isset($xmlSheet->sheetViews->sheetView['zoomScaleNormal'])) {
|
||||
$zoomScaleNormal = (int) ($xmlSheet->sheetViews->sheetView['zoomScaleNormal']);
|
||||
if ($zoomScaleNormal <= 0) {
|
||||
// setZoomScaleNormal will throw an Exception if the scale is less than or equals 0
|
||||
// that is OK when manually creating documents, but we should be able to read all documents
|
||||
$zoomScaleNormal = 100;
|
||||
}
|
||||
|
||||
$docSheet->getSheetView()->setZoomScaleNormal($zoomScaleNormal);
|
||||
}
|
||||
if (isset($xmlSheet->sheetViews->sheetView['view'])) {
|
||||
$docSheet->getSheetView()->setView((string) $xmlSheet->sheetViews->sheetView['view']);
|
||||
}
|
||||
if (isset($xmlSheet->sheetViews->sheetView['showGridLines'])) {
|
||||
$docSheet->setShowGridLines(self::boolean((string) $xmlSheet->sheetViews->sheetView['showGridLines']));
|
||||
}
|
||||
if (isset($xmlSheet->sheetViews->sheetView['showRowColHeaders'])) {
|
||||
$docSheet->setShowRowColHeaders(self::boolean((string) $xmlSheet->sheetViews->sheetView['showRowColHeaders']));
|
||||
}
|
||||
if (isset($xmlSheet->sheetViews->sheetView['rightToLeft'])) {
|
||||
$docSheet->setRightToLeft(self::boolean((string) $xmlSheet->sheetViews->sheetView['rightToLeft']));
|
||||
}
|
||||
if (isset($xmlSheet->sheetViews->sheetView->pane)) {
|
||||
$xSplit = 0;
|
||||
$ySplit = 0;
|
||||
$topLeftCell = null;
|
||||
|
||||
if (isset($xmlSheet->sheetViews->sheetView->pane['xSplit'])) {
|
||||
$xSplit = (int) ($xmlSheet->sheetViews->sheetView->pane['xSplit']);
|
||||
}
|
||||
|
||||
if (isset($xmlSheet->sheetViews->sheetView->pane['ySplit'])) {
|
||||
$ySplit = (int) ($xmlSheet->sheetViews->sheetView->pane['ySplit']);
|
||||
}
|
||||
|
||||
if (isset($xmlSheet->sheetViews->sheetView->pane['topLeftCell'])) {
|
||||
$topLeftCell = (string) $xmlSheet->sheetViews->sheetView->pane['topLeftCell'];
|
||||
}
|
||||
|
||||
$docSheet->freezePane(Coordinate::stringFromColumnIndex($xSplit + 1) . ($ySplit + 1), $topLeftCell);
|
||||
if ($xmlSheet) {
|
||||
if (isset($xmlSheet->sheetViews, $xmlSheet->sheetViews->sheetView)) {
|
||||
$sheetViews = new SheetViews($xmlSheet->sheetViews->sheetView, $docSheet);
|
||||
$sheetViews->load();
|
||||
}
|
||||
|
||||
if (isset($xmlSheet->sheetViews->sheetView->selection)) {
|
||||
if (isset($xmlSheet->sheetViews->sheetView->selection['sqref'])) {
|
||||
$sqref = (string) $xmlSheet->sheetViews->sheetView->selection['sqref'];
|
||||
$sqref = explode(' ', $sqref);
|
||||
$sqref = $sqref[0];
|
||||
$docSheet->setSelectedCells($sqref);
|
||||
}
|
||||
}
|
||||
$sheetViewOptions = new SheetViewOptions($docSheet, $xmlSheet);
|
||||
$sheetViewOptions->load($this->getReadDataOnly());
|
||||
|
||||
(new ColumnAndRowAttributes($docSheet, $xmlSheet))
|
||||
->load($this->getReadFilter(), $this->getReadDataOnly());
|
||||
}
|
||||
|
||||
if (isset($xmlSheet->sheetPr, $xmlSheet->sheetPr->tabColor)) {
|
||||
if (isset($xmlSheet->sheetPr->tabColor['rgb'])) {
|
||||
$docSheet->getTabColor()->setARGB((string) $xmlSheet->sheetPr->tabColor['rgb']);
|
||||
}
|
||||
}
|
||||
if (isset($xmlSheet->sheetPr, $xmlSheet->sheetPr['codeName'])) {
|
||||
$docSheet->setCodeName((string) $xmlSheet->sheetPr['codeName'], false);
|
||||
}
|
||||
if (isset($xmlSheet->sheetPr, $xmlSheet->sheetPr->outlinePr)) {
|
||||
if (isset($xmlSheet->sheetPr->outlinePr['summaryRight']) &&
|
||||
!self::boolean((string) $xmlSheet->sheetPr->outlinePr['summaryRight'])) {
|
||||
$docSheet->setShowSummaryRight(false);
|
||||
} else {
|
||||
$docSheet->setShowSummaryRight(true);
|
||||
}
|
||||
|
||||
if (isset($xmlSheet->sheetPr->outlinePr['summaryBelow']) &&
|
||||
!self::boolean((string) $xmlSheet->sheetPr->outlinePr['summaryBelow'])) {
|
||||
$docSheet->setShowSummaryBelow(false);
|
||||
} else {
|
||||
$docSheet->setShowSummaryBelow(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($xmlSheet->sheetPr, $xmlSheet->sheetPr->pageSetUpPr)) {
|
||||
if (isset($xmlSheet->sheetPr->pageSetUpPr['fitToPage']) &&
|
||||
!self::boolean((string) $xmlSheet->sheetPr->pageSetUpPr['fitToPage'])) {
|
||||
$docSheet->getPageSetup()->setFitToPage(false);
|
||||
} else {
|
||||
$docSheet->getPageSetup()->setFitToPage(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($xmlSheet->sheetFormatPr)) {
|
||||
if (isset($xmlSheet->sheetFormatPr['customHeight']) &&
|
||||
self::boolean((string) $xmlSheet->sheetFormatPr['customHeight']) &&
|
||||
isset($xmlSheet->sheetFormatPr['defaultRowHeight'])) {
|
||||
$docSheet->getDefaultRowDimension()->setRowHeight((float) $xmlSheet->sheetFormatPr['defaultRowHeight']);
|
||||
}
|
||||
if (isset($xmlSheet->sheetFormatPr['defaultColWidth'])) {
|
||||
$docSheet->getDefaultColumnDimension()->setWidth((float) $xmlSheet->sheetFormatPr['defaultColWidth']);
|
||||
}
|
||||
if (isset($xmlSheet->sheetFormatPr['zeroHeight']) &&
|
||||
((string) $xmlSheet->sheetFormatPr['zeroHeight'] == '1')) {
|
||||
$docSheet->getDefaultRowDimension()->setZeroHeight(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($xmlSheet->printOptions) && !$this->readDataOnly) {
|
||||
if (self::boolean((string) $xmlSheet->printOptions['gridLinesSet'])) {
|
||||
$docSheet->setShowGridlines(true);
|
||||
}
|
||||
if (self::boolean((string) $xmlSheet->printOptions['gridLines'])) {
|
||||
$docSheet->setPrintGridlines(true);
|
||||
}
|
||||
if (self::boolean((string) $xmlSheet->printOptions['horizontalCentered'])) {
|
||||
$docSheet->getPageSetup()->setHorizontalCentered(true);
|
||||
}
|
||||
if (self::boolean((string) $xmlSheet->printOptions['verticalCentered'])) {
|
||||
$docSheet->getPageSetup()->setVerticalCentered(true);
|
||||
}
|
||||
}
|
||||
|
||||
$this->readColumnsAndRowsAttributes($xmlSheet, $docSheet);
|
||||
|
||||
if ($xmlSheet && $xmlSheet->sheetData && $xmlSheet->sheetData->row) {
|
||||
$cIndex = 1; // Cell Start from 1
|
||||
foreach ($xmlSheet->sheetData->row as $row) {
|
||||
@ -963,49 +782,8 @@ class Xlsx extends BaseReader
|
||||
}
|
||||
}
|
||||
|
||||
$conditionals = [];
|
||||
if (!$this->readDataOnly && $xmlSheet && $xmlSheet->conditionalFormatting) {
|
||||
foreach ($xmlSheet->conditionalFormatting as $conditional) {
|
||||
foreach ($conditional->cfRule as $cfRule) {
|
||||
if (((string) $cfRule['type'] == Conditional::CONDITION_NONE || (string) $cfRule['type'] == Conditional::CONDITION_CELLIS || (string) $cfRule['type'] == Conditional::CONDITION_CONTAINSTEXT || (string) $cfRule['type'] == Conditional::CONDITION_EXPRESSION) && isset($dxfs[(int) ($cfRule['dxfId'])])) {
|
||||
$conditionals[(string) $conditional['sqref']][(int) ($cfRule['priority'])] = $cfRule;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($conditionals as $ref => $cfRules) {
|
||||
ksort($cfRules);
|
||||
$conditionalStyles = [];
|
||||
foreach ($cfRules as $cfRule) {
|
||||
$objConditional = new Conditional();
|
||||
$objConditional->setConditionType((string) $cfRule['type']);
|
||||
$objConditional->setOperatorType((string) $cfRule['operator']);
|
||||
|
||||
if ((string) $cfRule['text'] != '') {
|
||||
$objConditional->setText((string) $cfRule['text']);
|
||||
}
|
||||
|
||||
if (isset($cfRule['stopIfTrue']) && (int) $cfRule['stopIfTrue'] === 1) {
|
||||
$objConditional->setStopIfTrue(true);
|
||||
}
|
||||
|
||||
if (count($cfRule->formula) > 1) {
|
||||
foreach ($cfRule->formula as $formula) {
|
||||
$objConditional->addCondition((string) $formula);
|
||||
}
|
||||
} else {
|
||||
$objConditional->addCondition((string) $cfRule->formula);
|
||||
}
|
||||
$objConditional->setStyle(clone $dxfs[(int) ($cfRule['dxfId'])]);
|
||||
$conditionalStyles[] = $objConditional;
|
||||
}
|
||||
|
||||
// Extract all cell references in $ref
|
||||
$cellBlocks = explode(' ', str_replace('$', '', strtoupper($ref)));
|
||||
foreach ($cellBlocks as $cellBlock) {
|
||||
$docSheet->getStyle($cellBlock)->setConditionalStyles($conditionalStyles);
|
||||
}
|
||||
}
|
||||
(new ConditionalStyles($docSheet, $xmlSheet, $dxfs))->load();
|
||||
}
|
||||
|
||||
$aKeys = ['sheet', 'objects', 'scenarios', 'formatCells', 'formatColumns', 'formatRows', 'insertColumns', 'insertRows', 'insertHyperlinks', 'deleteColumns', 'deleteRows', 'selectLockedCells', 'sort', 'autoFilter', 'pivotTables', 'selectUnlockedCells'];
|
||||
@ -1026,103 +804,7 @@ class Xlsx extends BaseReader
|
||||
}
|
||||
|
||||
if ($xmlSheet && $xmlSheet->autoFilter && !$this->readDataOnly) {
|
||||
$autoFilterRange = (string) $xmlSheet->autoFilter['ref'];
|
||||
if (strpos($autoFilterRange, ':') !== false) {
|
||||
$autoFilter = $docSheet->getAutoFilter();
|
||||
$autoFilter->setRange($autoFilterRange);
|
||||
|
||||
foreach ($xmlSheet->autoFilter->filterColumn as $filterColumn) {
|
||||
$column = $autoFilter->getColumnByOffset((int) $filterColumn['colId']);
|
||||
// Check for standard filters
|
||||
if ($filterColumn->filters) {
|
||||
$column->setFilterType(Column::AUTOFILTER_FILTERTYPE_FILTER);
|
||||
$filters = $filterColumn->filters;
|
||||
if ((isset($filters['blank'])) && ($filters['blank'] == 1)) {
|
||||
// Operator is undefined, but always treated as EQUAL
|
||||
$column->createRule()->setRule(null, '')->setRuleType(Column\Rule::AUTOFILTER_RULETYPE_FILTER);
|
||||
}
|
||||
// Standard filters are always an OR join, so no join rule needs to be set
|
||||
// Entries can be either filter elements
|
||||
foreach ($filters->filter as $filterRule) {
|
||||
// Operator is undefined, but always treated as EQUAL
|
||||
$column->createRule()->setRule(null, (string) $filterRule['val'])->setRuleType(Column\Rule::AUTOFILTER_RULETYPE_FILTER);
|
||||
}
|
||||
// Or Date Group elements
|
||||
foreach ($filters->dateGroupItem as $dateGroupItem) {
|
||||
// Operator is undefined, but always treated as EQUAL
|
||||
$column->createRule()->setRule(
|
||||
null,
|
||||
[
|
||||
'year' => (string) $dateGroupItem['year'],
|
||||
'month' => (string) $dateGroupItem['month'],
|
||||
'day' => (string) $dateGroupItem['day'],
|
||||
'hour' => (string) $dateGroupItem['hour'],
|
||||
'minute' => (string) $dateGroupItem['minute'],
|
||||
'second' => (string) $dateGroupItem['second'],
|
||||
],
|
||||
(string) $dateGroupItem['dateTimeGrouping']
|
||||
)
|
||||
->setRuleType(Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP);
|
||||
}
|
||||
}
|
||||
// Check for custom filters
|
||||
if ($filterColumn->customFilters) {
|
||||
$column->setFilterType(Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER);
|
||||
$customFilters = $filterColumn->customFilters;
|
||||
// Custom filters can an AND or an OR join;
|
||||
// and there should only ever be one or two entries
|
||||
if ((isset($customFilters['and'])) && ($customFilters['and'] == 1)) {
|
||||
$column->setJoin(Column::AUTOFILTER_COLUMN_JOIN_AND);
|
||||
}
|
||||
foreach ($customFilters->customFilter as $filterRule) {
|
||||
$column->createRule()->setRule(
|
||||
(string) $filterRule['operator'],
|
||||
(string) $filterRule['val']
|
||||
)
|
||||
->setRuleType(Column\Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
|
||||
}
|
||||
}
|
||||
// Check for dynamic filters
|
||||
if ($filterColumn->dynamicFilter) {
|
||||
$column->setFilterType(Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER);
|
||||
// We should only ever have one dynamic filter
|
||||
foreach ($filterColumn->dynamicFilter as $filterRule) {
|
||||
// Operator is undefined, but always treated as EQUAL
|
||||
$column->createRule()->setRule(
|
||||
null,
|
||||
(string) $filterRule['val'],
|
||||
(string) $filterRule['type']
|
||||
)
|
||||
->setRuleType(Column\Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER);
|
||||
if (isset($filterRule['val'])) {
|
||||
$column->setAttribute('val', (string) $filterRule['val']);
|
||||
}
|
||||
if (isset($filterRule['maxVal'])) {
|
||||
$column->setAttribute('maxVal', (string) $filterRule['maxVal']);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check for dynamic filters
|
||||
if ($filterColumn->top10) {
|
||||
$column->setFilterType(Column::AUTOFILTER_FILTERTYPE_TOPTENFILTER);
|
||||
// We should only ever have one top10 filter
|
||||
foreach ($filterColumn->top10 as $filterRule) {
|
||||
$column->createRule()->setRule(
|
||||
(((isset($filterRule['percent'])) && ($filterRule['percent'] == 1))
|
||||
? Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT
|
||||
: Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_BY_VALUE
|
||||
),
|
||||
(string) $filterRule['val'],
|
||||
(((isset($filterRule['top'])) && ($filterRule['top'] == 1))
|
||||
? Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP
|
||||
: Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_BOTTOM
|
||||
)
|
||||
)
|
||||
->setRuleType(Column\Rule::AUTOFILTER_RULETYPE_TOPTENFILTER);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(new AutoFilter($docSheet, $xmlSheet))->load();
|
||||
}
|
||||
|
||||
if ($xmlSheet && $xmlSheet->mergeCells && $xmlSheet->mergeCells->mergeCell && !$this->readDataOnly) {
|
||||
@ -1134,124 +816,12 @@ class Xlsx extends BaseReader
|
||||
}
|
||||
}
|
||||
|
||||
if ($xmlSheet && $xmlSheet->pageMargins && !$this->readDataOnly) {
|
||||
$docPageMargins = $docSheet->getPageMargins();
|
||||
$docPageMargins->setLeft((float) ($xmlSheet->pageMargins['left']));
|
||||
$docPageMargins->setRight((float) ($xmlSheet->pageMargins['right']));
|
||||
$docPageMargins->setTop((float) ($xmlSheet->pageMargins['top']));
|
||||
$docPageMargins->setBottom((float) ($xmlSheet->pageMargins['bottom']));
|
||||
$docPageMargins->setHeader((float) ($xmlSheet->pageMargins['header']));
|
||||
$docPageMargins->setFooter((float) ($xmlSheet->pageMargins['footer']));
|
||||
}
|
||||
|
||||
if ($xmlSheet && $xmlSheet->pageSetup && !$this->readDataOnly) {
|
||||
$docPageSetup = $docSheet->getPageSetup();
|
||||
|
||||
if (isset($xmlSheet->pageSetup['orientation'])) {
|
||||
$docPageSetup->setOrientation((string) $xmlSheet->pageSetup['orientation']);
|
||||
}
|
||||
if (isset($xmlSheet->pageSetup['paperSize'])) {
|
||||
$docPageSetup->setPaperSize((int) ($xmlSheet->pageSetup['paperSize']));
|
||||
}
|
||||
if (isset($xmlSheet->pageSetup['scale'])) {
|
||||
$docPageSetup->setScale((int) ($xmlSheet->pageSetup['scale']), false);
|
||||
}
|
||||
if (isset($xmlSheet->pageSetup['fitToHeight']) && (int) ($xmlSheet->pageSetup['fitToHeight']) >= 0) {
|
||||
$docPageSetup->setFitToHeight((int) ($xmlSheet->pageSetup['fitToHeight']), false);
|
||||
}
|
||||
if (isset($xmlSheet->pageSetup['fitToWidth']) && (int) ($xmlSheet->pageSetup['fitToWidth']) >= 0) {
|
||||
$docPageSetup->setFitToWidth((int) ($xmlSheet->pageSetup['fitToWidth']), false);
|
||||
}
|
||||
if (isset($xmlSheet->pageSetup['firstPageNumber'], $xmlSheet->pageSetup['useFirstPageNumber']) &&
|
||||
self::boolean((string) $xmlSheet->pageSetup['useFirstPageNumber'])) {
|
||||
$docPageSetup->setFirstPageNumber((int) ($xmlSheet->pageSetup['firstPageNumber']));
|
||||
}
|
||||
|
||||
$relAttributes = $xmlSheet->pageSetup->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships');
|
||||
if (isset($relAttributes['id'])) {
|
||||
$unparsedLoadedData['sheets'][$docSheet->getCodeName()]['pageSetupRelId'] = (string) $relAttributes['id'];
|
||||
}
|
||||
}
|
||||
|
||||
if ($xmlSheet && $xmlSheet->headerFooter && !$this->readDataOnly) {
|
||||
$docHeaderFooter = $docSheet->getHeaderFooter();
|
||||
|
||||
if (isset($xmlSheet->headerFooter['differentOddEven']) &&
|
||||
self::boolean((string) $xmlSheet->headerFooter['differentOddEven'])) {
|
||||
$docHeaderFooter->setDifferentOddEven(true);
|
||||
} else {
|
||||
$docHeaderFooter->setDifferentOddEven(false);
|
||||
}
|
||||
if (isset($xmlSheet->headerFooter['differentFirst']) &&
|
||||
self::boolean((string) $xmlSheet->headerFooter['differentFirst'])) {
|
||||
$docHeaderFooter->setDifferentFirst(true);
|
||||
} else {
|
||||
$docHeaderFooter->setDifferentFirst(false);
|
||||
}
|
||||
if (isset($xmlSheet->headerFooter['scaleWithDoc']) &&
|
||||
!self::boolean((string) $xmlSheet->headerFooter['scaleWithDoc'])) {
|
||||
$docHeaderFooter->setScaleWithDocument(false);
|
||||
} else {
|
||||
$docHeaderFooter->setScaleWithDocument(true);
|
||||
}
|
||||
if (isset($xmlSheet->headerFooter['alignWithMargins']) &&
|
||||
!self::boolean((string) $xmlSheet->headerFooter['alignWithMargins'])) {
|
||||
$docHeaderFooter->setAlignWithMargins(false);
|
||||
} else {
|
||||
$docHeaderFooter->setAlignWithMargins(true);
|
||||
}
|
||||
|
||||
$docHeaderFooter->setOddHeader((string) $xmlSheet->headerFooter->oddHeader);
|
||||
$docHeaderFooter->setOddFooter((string) $xmlSheet->headerFooter->oddFooter);
|
||||
$docHeaderFooter->setEvenHeader((string) $xmlSheet->headerFooter->evenHeader);
|
||||
$docHeaderFooter->setEvenFooter((string) $xmlSheet->headerFooter->evenFooter);
|
||||
$docHeaderFooter->setFirstHeader((string) $xmlSheet->headerFooter->firstHeader);
|
||||
$docHeaderFooter->setFirstFooter((string) $xmlSheet->headerFooter->firstFooter);
|
||||
}
|
||||
|
||||
if ($xmlSheet && $xmlSheet->rowBreaks && $xmlSheet->rowBreaks->brk && !$this->readDataOnly) {
|
||||
foreach ($xmlSheet->rowBreaks->brk as $brk) {
|
||||
if ($brk['man']) {
|
||||
$docSheet->setBreak("A$brk[id]", Worksheet::BREAK_ROW);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($xmlSheet && $xmlSheet->colBreaks && $xmlSheet->colBreaks->brk && !$this->readDataOnly) {
|
||||
foreach ($xmlSheet->colBreaks->brk as $brk) {
|
||||
if ($brk['man']) {
|
||||
$docSheet->setBreak(Coordinate::stringFromColumnIndex((string) $brk['id'] + 1) . '1', Worksheet::BREAK_COLUMN);
|
||||
}
|
||||
}
|
||||
if ($xmlSheet && !$this->readDataOnly) {
|
||||
$unparsedLoadedData = (new PageSetup($docSheet, $xmlSheet))->load($unparsedLoadedData);
|
||||
}
|
||||
|
||||
if ($xmlSheet && $xmlSheet->dataValidations && !$this->readDataOnly) {
|
||||
foreach ($xmlSheet->dataValidations->dataValidation as $dataValidation) {
|
||||
// Uppercase coordinate
|
||||
$range = strtoupper($dataValidation['sqref']);
|
||||
$rangeSet = explode(' ', $range);
|
||||
foreach ($rangeSet as $range) {
|
||||
$stRange = $docSheet->shrinkRangeToFit($range);
|
||||
|
||||
// Extract all cell references in $range
|
||||
foreach (Coordinate::extractAllCellReferencesInRange($stRange) as $reference) {
|
||||
// Create validation
|
||||
$docValidation = $docSheet->getCell($reference)->getDataValidation();
|
||||
$docValidation->setType((string) $dataValidation['type']);
|
||||
$docValidation->setErrorStyle((string) $dataValidation['errorStyle']);
|
||||
$docValidation->setOperator((string) $dataValidation['operator']);
|
||||
$docValidation->setAllowBlank($dataValidation['allowBlank'] != 0);
|
||||
$docValidation->setShowDropDown($dataValidation['showDropDown'] == 0);
|
||||
$docValidation->setShowInputMessage($dataValidation['showInputMessage'] != 0);
|
||||
$docValidation->setShowErrorMessage($dataValidation['showErrorMessage'] != 0);
|
||||
$docValidation->setErrorTitle((string) $dataValidation['errorTitle']);
|
||||
$docValidation->setError((string) $dataValidation['error']);
|
||||
$docValidation->setPromptTitle((string) $dataValidation['promptTitle']);
|
||||
$docValidation->setPrompt((string) $dataValidation['prompt']);
|
||||
$docValidation->setFormula1((string) $dataValidation->formula1);
|
||||
$docValidation->setFormula2((string) $dataValidation->formula2);
|
||||
}
|
||||
}
|
||||
}
|
||||
(new DataValidations($docSheet, $xmlSheet))->load();
|
||||
}
|
||||
|
||||
// unparsed sheet AlternateContent
|
||||
@ -1265,50 +835,25 @@ class Xlsx extends BaseReader
|
||||
}
|
||||
|
||||
// Add hyperlinks
|
||||
$hyperlinks = [];
|
||||
if (!$this->readDataOnly) {
|
||||
$hyperlinkReader = new Hyperlinks($docSheet);
|
||||
// Locate hyperlink relations
|
||||
if ($zip->locateName(dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels')) {
|
||||
$relationsFileName = dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels';
|
||||
if ($zip->locateName($relationsFileName)) {
|
||||
//~ http://schemas.openxmlformats.org/package/2006/relationships"
|
||||
$relsWorksheet = simplexml_load_string(
|
||||
$this->securityScanner->scan(
|
||||
$this->getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels')
|
||||
$this->getFromZipArchive($zip, $relationsFileName)
|
||||
),
|
||||
'SimpleXMLElement',
|
||||
Settings::getLibXmlLoaderOptions()
|
||||
);
|
||||
foreach ($relsWorksheet->Relationship as $ele) {
|
||||
if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink') {
|
||||
$hyperlinks[(string) $ele['Id']] = (string) $ele['Target'];
|
||||
}
|
||||
}
|
||||
$hyperlinkReader->readHyperlinks($relsWorksheet);
|
||||
}
|
||||
|
||||
// Loop through hyperlinks
|
||||
if ($xmlSheet && $xmlSheet->hyperlinks) {
|
||||
/** @var SimpleXMLElement $hyperlink */
|
||||
foreach ($xmlSheet->hyperlinks->hyperlink as $hyperlink) {
|
||||
// Link url
|
||||
$linkRel = $hyperlink->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships');
|
||||
|
||||
foreach (Coordinate::extractAllCellReferencesInRange($hyperlink['ref']) as $cellReference) {
|
||||
$cell = $docSheet->getCell($cellReference);
|
||||
if (isset($linkRel['id'])) {
|
||||
$hyperlinkUrl = $hyperlinks[(string) $linkRel['id']];
|
||||
if (isset($hyperlink['location'])) {
|
||||
$hyperlinkUrl .= '#' . (string) $hyperlink['location'];
|
||||
}
|
||||
$cell->getHyperlink()->setUrl($hyperlinkUrl);
|
||||
} elseif (isset($hyperlink['location'])) {
|
||||
$cell->getHyperlink()->setUrl('sheet://' . (string) $hyperlink['location']);
|
||||
}
|
||||
|
||||
// Tooltip
|
||||
if (isset($hyperlink['tooltip'])) {
|
||||
$cell->getHyperlink()->setTooltip((string) $hyperlink['tooltip']);
|
||||
}
|
||||
}
|
||||
}
|
||||
$hyperlinkReader->setHyperlinks($xmlSheet->hyperlinks);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2482,94 +2027,4 @@ class Xlsx extends BaseReader
|
||||
|
||||
return (bool) $xsdBoolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read columns and rows attributes from XML and set them on the worksheet.
|
||||
*
|
||||
* @param SimpleXMLElement $xmlSheet
|
||||
* @param Worksheet $docSheet
|
||||
*/
|
||||
private function readColumnsAndRowsAttributes(SimpleXMLElement $xmlSheet, Worksheet $docSheet)
|
||||
{
|
||||
$columnsAttributes = [];
|
||||
$rowsAttributes = [];
|
||||
if (isset($xmlSheet->cols) && !$this->readDataOnly) {
|
||||
foreach ($xmlSheet->cols->col as $col) {
|
||||
for ($i = (int) ($col['min']); $i <= (int) ($col['max']); ++$i) {
|
||||
if ($col['style'] && !$this->readDataOnly) {
|
||||
$columnsAttributes[Coordinate::stringFromColumnIndex($i)]['xfIndex'] = (int) $col['style'];
|
||||
}
|
||||
if (self::boolean($col['hidden'])) {
|
||||
$columnsAttributes[Coordinate::stringFromColumnIndex($i)]['visible'] = false;
|
||||
}
|
||||
if (self::boolean($col['collapsed'])) {
|
||||
$columnsAttributes[Coordinate::stringFromColumnIndex($i)]['collapsed'] = true;
|
||||
}
|
||||
if ($col['outlineLevel'] > 0) {
|
||||
$columnsAttributes[Coordinate::stringFromColumnIndex($i)]['outlineLevel'] = (int) $col['outlineLevel'];
|
||||
}
|
||||
$columnsAttributes[Coordinate::stringFromColumnIndex($i)]['width'] = (float) $col['width'];
|
||||
|
||||
if ((int) ($col['max']) == 16384) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($xmlSheet && $xmlSheet->sheetData && $xmlSheet->sheetData->row) {
|
||||
foreach ($xmlSheet->sheetData->row as $row) {
|
||||
if ($row['ht'] && !$this->readDataOnly) {
|
||||
$rowsAttributes[(int) $row['r']]['rowHeight'] = (float) $row['ht'];
|
||||
}
|
||||
if (self::boolean($row['hidden']) && !$this->readDataOnly) {
|
||||
$rowsAttributes[(int) $row['r']]['visible'] = false;
|
||||
}
|
||||
if (self::boolean($row['collapsed'])) {
|
||||
$rowsAttributes[(int) $row['r']]['collapsed'] = true;
|
||||
}
|
||||
if ($row['outlineLevel'] > 0) {
|
||||
$rowsAttributes[(int) $row['r']]['outlineLevel'] = (int) $row['outlineLevel'];
|
||||
}
|
||||
if ($row['s'] && !$this->readDataOnly) {
|
||||
$rowsAttributes[(int) $row['r']]['xfIndex'] = (int) $row['s'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$readFilter = (\get_class($this->getReadFilter()) !== DefaultReadFilter::class ? $this->getReadFilter() : null);
|
||||
|
||||
// set columns/rows attributes
|
||||
$columnsAttributesSet = [];
|
||||
$rowsAttributesSet = [];
|
||||
foreach ($columnsAttributes as $coordColumn => $columnAttributes) {
|
||||
if ($readFilter !== null) {
|
||||
foreach ($rowsAttributes as $coordRow => $rowAttributes) {
|
||||
if (!$readFilter->readCell($coordColumn, $coordRow, $docSheet->getTitle())) {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($columnsAttributesSet[$coordColumn])) {
|
||||
$this->setColumnAttributes($docSheet, $coordColumn, $columnAttributes);
|
||||
$columnsAttributesSet[$coordColumn] = true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($rowsAttributes as $coordRow => $rowAttributes) {
|
||||
if ($readFilter !== null) {
|
||||
foreach ($columnsAttributes as $coordColumn => $columnAttributes) {
|
||||
if (!$readFilter->readCell($coordColumn, $coordRow, $docSheet->getTitle())) {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($rowsAttributesSet[$coordRow])) {
|
||||
$this->setRowAttributes($docSheet, $coordRow, $rowAttributes);
|
||||
$rowsAttributesSet[$coordRow] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
144
src/PhpSpreadsheet/Reader/Xlsx/AutoFilter.php
Normal file
144
src/PhpSpreadsheet/Reader/Xlsx/AutoFilter.php
Normal file
@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
|
||||
class AutoFilter
|
||||
{
|
||||
private $worksheet;
|
||||
|
||||
private $worksheetXml;
|
||||
|
||||
public function __construct(Worksheet $workSheet, \SimpleXMLElement $worksheetXml)
|
||||
{
|
||||
$this->worksheet = $workSheet;
|
||||
$this->worksheetXml = $worksheetXml;
|
||||
}
|
||||
|
||||
public function load()
|
||||
{
|
||||
$autoFilterRange = (string) $this->worksheetXml->autoFilter['ref'];
|
||||
if (strpos($autoFilterRange, ':') !== false) {
|
||||
$this->readAutoFilter($autoFilterRange, $this->worksheetXml);
|
||||
}
|
||||
}
|
||||
|
||||
private function readAutoFilter($autoFilterRange, $xmlSheet)
|
||||
{
|
||||
$autoFilter = $this->worksheet->getAutoFilter();
|
||||
$autoFilter->setRange($autoFilterRange);
|
||||
|
||||
foreach ($xmlSheet->autoFilter->filterColumn as $filterColumn) {
|
||||
$column = $autoFilter->getColumnByOffset((int) $filterColumn['colId']);
|
||||
// Check for standard filters
|
||||
if ($filterColumn->filters) {
|
||||
$column->setFilterType(Column::AUTOFILTER_FILTERTYPE_FILTER);
|
||||
$filters = $filterColumn->filters;
|
||||
if ((isset($filters['blank'])) && ($filters['blank'] == 1)) {
|
||||
// Operator is undefined, but always treated as EQUAL
|
||||
$column->createRule()->setRule(null, '')->setRuleType(Rule::AUTOFILTER_RULETYPE_FILTER);
|
||||
}
|
||||
// Standard filters are always an OR join, so no join rule needs to be set
|
||||
// Entries can be either filter elements
|
||||
foreach ($filters->filter as $filterRule) {
|
||||
// Operator is undefined, but always treated as EQUAL
|
||||
$column->createRule()->setRule(null, (string) $filterRule['val'])->setRuleType(Rule::AUTOFILTER_RULETYPE_FILTER);
|
||||
}
|
||||
|
||||
// Or Date Group elements
|
||||
$this->readDateRangeAutoFilter($filters, $column);
|
||||
}
|
||||
|
||||
// Check for custom filters
|
||||
$this->readCustomAutoFilter($filterColumn, $column);
|
||||
// Check for dynamic filters
|
||||
$this->readDynamicAutoFilter($filterColumn, $column);
|
||||
// Check for dynamic filters
|
||||
$this->readTopTenAutoFilter($filterColumn, $column);
|
||||
}
|
||||
}
|
||||
|
||||
private function readDateRangeAutoFilter(\SimpleXMLElement $filters, Column $column)
|
||||
{
|
||||
foreach ($filters->dateGroupItem as $dateGroupItem) {
|
||||
// Operator is undefined, but always treated as EQUAL
|
||||
$column->createRule()->setRule(
|
||||
null,
|
||||
[
|
||||
'year' => (string) $dateGroupItem['year'],
|
||||
'month' => (string) $dateGroupItem['month'],
|
||||
'day' => (string) $dateGroupItem['day'],
|
||||
'hour' => (string) $dateGroupItem['hour'],
|
||||
'minute' => (string) $dateGroupItem['minute'],
|
||||
'second' => (string) $dateGroupItem['second'],
|
||||
],
|
||||
(string) $dateGroupItem['dateTimeGrouping']
|
||||
)->setRuleType(Rule::AUTOFILTER_RULETYPE_DATEGROUP);
|
||||
}
|
||||
}
|
||||
|
||||
private function readCustomAutoFilter(\SimpleXMLElement $filterColumn, Column $column)
|
||||
{
|
||||
if ($filterColumn->customFilters) {
|
||||
$column->setFilterType(Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER);
|
||||
$customFilters = $filterColumn->customFilters;
|
||||
// Custom filters can an AND or an OR join;
|
||||
// and there should only ever be one or two entries
|
||||
if ((isset($customFilters['and'])) && ($customFilters['and'] == 1)) {
|
||||
$column->setJoin(Column::AUTOFILTER_COLUMN_JOIN_AND);
|
||||
}
|
||||
foreach ($customFilters->customFilter as $filterRule) {
|
||||
$column->createRule()->setRule(
|
||||
(string) $filterRule['operator'],
|
||||
(string) $filterRule['val']
|
||||
)->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function readDynamicAutoFilter(\SimpleXMLElement $filterColumn, Column $column)
|
||||
{
|
||||
if ($filterColumn->dynamicFilter) {
|
||||
$column->setFilterType(Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER);
|
||||
// We should only ever have one dynamic filter
|
||||
foreach ($filterColumn->dynamicFilter as $filterRule) {
|
||||
// Operator is undefined, but always treated as EQUAL
|
||||
$column->createRule()->setRule(
|
||||
null,
|
||||
(string) $filterRule['val'],
|
||||
(string) $filterRule['type']
|
||||
)->setRuleType(Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER);
|
||||
if (isset($filterRule['val'])) {
|
||||
$column->setAttribute('val', (string) $filterRule['val']);
|
||||
}
|
||||
if (isset($filterRule['maxVal'])) {
|
||||
$column->setAttribute('maxVal', (string) $filterRule['maxVal']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function readTopTenAutoFilter(\SimpleXMLElement $filterColumn, Column $column)
|
||||
{
|
||||
if ($filterColumn->top10) {
|
||||
$column->setFilterType(Column::AUTOFILTER_FILTERTYPE_TOPTENFILTER);
|
||||
// We should only ever have one top10 filter
|
||||
foreach ($filterColumn->top10 as $filterRule) {
|
||||
$column->createRule()->setRule(
|
||||
(((isset($filterRule['percent'])) && ($filterRule['percent'] == 1))
|
||||
? Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT
|
||||
: Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_BY_VALUE
|
||||
),
|
||||
(string) $filterRule['val'],
|
||||
(((isset($filterRule['top'])) && ($filterRule['top'] == 1))
|
||||
? Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP
|
||||
: Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_BOTTOM
|
||||
)
|
||||
)->setRuleType(Rule::AUTOFILTER_RULETYPE_TOPTENFILTER);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
src/PhpSpreadsheet/Reader/Xlsx/BaseParserClass.php
Normal file
19
src/PhpSpreadsheet/Reader/Xlsx/BaseParserClass.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||
|
||||
class BaseParserClass
|
||||
{
|
||||
protected static function boolean($value)
|
||||
{
|
||||
if (is_object($value)) {
|
||||
$value = (string) $value;
|
||||
}
|
||||
|
||||
if (is_numeric($value)) {
|
||||
return (bool) $value;
|
||||
}
|
||||
|
||||
return $value === strtolower('true');
|
||||
}
|
||||
}
|
204
src/PhpSpreadsheet/Reader/Xlsx/ColumnAndRowAttributes.php
Normal file
204
src/PhpSpreadsheet/Reader/Xlsx/ColumnAndRowAttributes.php
Normal file
@ -0,0 +1,204 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\IReadFilter;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
|
||||
class ColumnAndRowAttributes extends BaseParserClass
|
||||
{
|
||||
private $worksheet;
|
||||
|
||||
private $worksheetXml;
|
||||
|
||||
public function __construct(Worksheet $workSheet, \SimpleXMLElement $worksheetXml = null)
|
||||
{
|
||||
$this->worksheet = $workSheet;
|
||||
$this->worksheetXml = $worksheetXml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Worksheet column attributes by attributes array passed.
|
||||
*
|
||||
* @param string $columnAddress A, B, ... DX, ...
|
||||
* @param array $columnAttributes array of attributes (indexes are attribute name, values are value)
|
||||
* 'xfIndex', 'visible', 'collapsed', 'outlineLevel', 'width', ... ?
|
||||
*/
|
||||
private function setColumnAttributes($columnAddress, array $columnAttributes)
|
||||
{
|
||||
if (isset($columnAttributes['xfIndex'])) {
|
||||
$this->worksheet->getColumnDimension($columnAddress)->setXfIndex($columnAttributes['xfIndex']);
|
||||
}
|
||||
if (isset($columnAttributes['visible'])) {
|
||||
$this->worksheet->getColumnDimension($columnAddress)->setVisible($columnAttributes['visible']);
|
||||
}
|
||||
if (isset($columnAttributes['collapsed'])) {
|
||||
$this->worksheet->getColumnDimension($columnAddress)->setCollapsed($columnAttributes['collapsed']);
|
||||
}
|
||||
if (isset($columnAttributes['outlineLevel'])) {
|
||||
$this->worksheet->getColumnDimension($columnAddress)->setOutlineLevel($columnAttributes['outlineLevel']);
|
||||
}
|
||||
if (isset($columnAttributes['width'])) {
|
||||
$this->worksheet->getColumnDimension($columnAddress)->setWidth($columnAttributes['width']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Worksheet row attributes by attributes array passed.
|
||||
*
|
||||
* @param int $rowNumber 1, 2, 3, ... 99, ...
|
||||
* @param array $rowAttributes array of attributes (indexes are attribute name, values are value)
|
||||
* 'xfIndex', 'visible', 'collapsed', 'outlineLevel', 'rowHeight', ... ?
|
||||
*/
|
||||
private function setRowAttributes($rowNumber, array $rowAttributes)
|
||||
{
|
||||
if (isset($rowAttributes['xfIndex'])) {
|
||||
$this->worksheet->getRowDimension($rowNumber)->setXfIndex($rowAttributes['xfIndex']);
|
||||
}
|
||||
if (isset($rowAttributes['visible'])) {
|
||||
$this->worksheet->getRowDimension($rowNumber)->setVisible($rowAttributes['visible']);
|
||||
}
|
||||
if (isset($rowAttributes['collapsed'])) {
|
||||
$this->worksheet->getRowDimension($rowNumber)->setCollapsed($rowAttributes['collapsed']);
|
||||
}
|
||||
if (isset($rowAttributes['outlineLevel'])) {
|
||||
$this->worksheet->getRowDimension($rowNumber)->setOutlineLevel($rowAttributes['outlineLevel']);
|
||||
}
|
||||
if (isset($rowAttributes['rowHeight'])) {
|
||||
$this->worksheet->getRowDimension($rowNumber)->setRowHeight($rowAttributes['rowHeight']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IReadFilter $readFilter
|
||||
* @param bool $readDataOnly
|
||||
*/
|
||||
public function load(IReadFilter $readFilter = null, $readDataOnly = false)
|
||||
{
|
||||
if ($this->worksheetXml === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$columnsAttributes = [];
|
||||
$rowsAttributes = [];
|
||||
if (isset($this->worksheetXml->cols)) {
|
||||
$columnsAttributes = $this->readColumnAttributes($this->worksheetXml->cols, $readDataOnly);
|
||||
}
|
||||
|
||||
if ($this->worksheetXml->sheetData && $this->worksheetXml->sheetData->row) {
|
||||
$rowsAttributes = $this->readRowAttributes($this->worksheetXml->sheetData->row, $readDataOnly);
|
||||
}
|
||||
|
||||
// set columns/rows attributes
|
||||
$columnsAttributesAreSet = [];
|
||||
foreach ($columnsAttributes as $columnCoordinate => $columnAttributes) {
|
||||
if ($readFilter === null ||
|
||||
!$this->isFilteredColumn($readFilter, $columnCoordinate, $rowsAttributes)) {
|
||||
if (!isset($columnsAttributesAreSet[$columnCoordinate])) {
|
||||
$this->setColumnAttributes($columnCoordinate, $columnAttributes);
|
||||
$columnsAttributesAreSet[$columnCoordinate] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$rowsAttributesAreSet = [];
|
||||
foreach ($rowsAttributes as $rowCoordinate => $rowAttributes) {
|
||||
if ($readFilter === null ||
|
||||
!$this->isFilteredRow($readFilter, $rowCoordinate, $columnsAttributes)) {
|
||||
if (!isset($rowsAttributesAreSet[$rowCoordinate])) {
|
||||
$this->setRowAttributes($rowCoordinate, $rowAttributes);
|
||||
$rowsAttributesAreSet[$rowCoordinate] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function isFilteredColumn(IReadFilter $readFilter, $columnCoordinate, array $rowsAttributes)
|
||||
{
|
||||
foreach ($rowsAttributes as $rowCoordinate => $rowAttributes) {
|
||||
if (!$readFilter->readCell($columnCoordinate, $rowCoordinate, $this->worksheet->getTitle())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function readColumnAttributes(\SimpleXMLElement $worksheetCols, $readDataOnly)
|
||||
{
|
||||
$columnAttributes = [];
|
||||
|
||||
foreach ($worksheetCols->col as $column) {
|
||||
$startColumn = Coordinate::stringFromColumnIndex((int) $column['min']);
|
||||
$endColumn = Coordinate::stringFromColumnIndex((int) $column['max']);
|
||||
++$endColumn;
|
||||
for ($columnAddress = $startColumn; $columnAddress !== $endColumn; ++$columnAddress) {
|
||||
$columnAttributes[$columnAddress] = $this->readColumnRangeAttributes($column, $readDataOnly);
|
||||
|
||||
if ((int) ($column['max']) == 16384) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $columnAttributes;
|
||||
}
|
||||
|
||||
private function readColumnRangeAttributes(\SimpleXMLElement $column, $readDataOnly)
|
||||
{
|
||||
$columnAttributes = [];
|
||||
|
||||
if ($column['style'] && !$readDataOnly) {
|
||||
$columnAttributes['xfIndex'] = (int) $column['style'];
|
||||
}
|
||||
if (self::boolean($column['hidden'])) {
|
||||
$columnAttributes['visible'] = false;
|
||||
}
|
||||
if (self::boolean($column['collapsed'])) {
|
||||
$columnAttributes['collapsed'] = true;
|
||||
}
|
||||
if (((int) $column['outlineLevel']) > 0) {
|
||||
$columnAttributes['outlineLevel'] = (int) $column['outlineLevel'];
|
||||
}
|
||||
$columnAttributes['width'] = (float) $column['width'];
|
||||
|
||||
return $columnAttributes;
|
||||
}
|
||||
|
||||
private function isFilteredRow(IReadFilter $readFilter, $rowCoordinate, array $columnsAttributes)
|
||||
{
|
||||
foreach ($columnsAttributes as $columnCoordinate => $columnAttributes) {
|
||||
if (!$readFilter->readCell($columnCoordinate, $rowCoordinate, $this->worksheet->getTitle())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function readRowAttributes(\SimpleXMLElement $worksheetRow, $readDataOnly)
|
||||
{
|
||||
$rowAttributes = [];
|
||||
|
||||
foreach ($worksheetRow as $row) {
|
||||
if ($row['ht'] && !$readDataOnly) {
|
||||
$rowAttributes[(int) $row['r']]['rowHeight'] = (float) $row['ht'];
|
||||
}
|
||||
if (self::boolean($row['hidden'])) {
|
||||
$rowAttributes[(int) $row['r']]['visible'] = false;
|
||||
}
|
||||
if (self::boolean($row['collapsed'])) {
|
||||
$rowAttributes[(int) $row['r']]['collapsed'] = true;
|
||||
}
|
||||
if ((int) $row['outlineLevel'] > 0) {
|
||||
$rowAttributes[(int) $row['r']]['outlineLevel'] = (int) $row['outlineLevel'];
|
||||
}
|
||||
if ($row['s'] && !$readDataOnly) {
|
||||
$rowAttributes[(int) $row['r']]['xfIndex'] = (int) $row['s'];
|
||||
}
|
||||
}
|
||||
|
||||
return $rowAttributes;
|
||||
}
|
||||
}
|
92
src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php
Normal file
92
src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php
Normal file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Style\Conditional;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
|
||||
class ConditionalStyles
|
||||
{
|
||||
private $worksheet;
|
||||
|
||||
private $worksheetXml;
|
||||
|
||||
private $dxfs;
|
||||
|
||||
public function __construct(Worksheet $workSheet, \SimpleXMLElement $worksheetXml, array $dxfs = [])
|
||||
{
|
||||
$this->worksheet = $workSheet;
|
||||
$this->worksheetXml = $worksheetXml;
|
||||
$this->dxfs = $dxfs;
|
||||
}
|
||||
|
||||
public function load()
|
||||
{
|
||||
$this->setConditionalStyles(
|
||||
$this->worksheet,
|
||||
$this->readConditionalStyles($this->worksheetXml)
|
||||
);
|
||||
}
|
||||
|
||||
private function readConditionalStyles($xmlSheet)
|
||||
{
|
||||
$conditionals = [];
|
||||
foreach ($xmlSheet->conditionalFormatting as $conditional) {
|
||||
foreach ($conditional->cfRule as $cfRule) {
|
||||
if (((string) $cfRule['type'] == Conditional::CONDITION_NONE
|
||||
|| (string) $cfRule['type'] == Conditional::CONDITION_CELLIS
|
||||
|| (string) $cfRule['type'] == Conditional::CONDITION_CONTAINSTEXT
|
||||
|| (string) $cfRule['type'] == Conditional::CONDITION_EXPRESSION)
|
||||
&& isset($this->dxfs[(int) ($cfRule['dxfId'])])) {
|
||||
$conditionals[(string) $conditional['sqref']][(int) ($cfRule['priority'])] = $cfRule;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $conditionals;
|
||||
}
|
||||
|
||||
private function setConditionalStyles(Worksheet $worksheet, array $conditionals)
|
||||
{
|
||||
foreach ($conditionals as $ref => $cfRules) {
|
||||
ksort($cfRules);
|
||||
$conditionalStyles = $this->readStyleRules($cfRules);
|
||||
|
||||
// Extract all cell references in $ref
|
||||
$cellBlocks = explode(' ', str_replace('$', '', strtoupper($ref)));
|
||||
foreach ($cellBlocks as $cellBlock) {
|
||||
$worksheet->getStyle($cellBlock)->setConditionalStyles($conditionalStyles);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function readStyleRules($cfRules)
|
||||
{
|
||||
$conditionalStyles = [];
|
||||
foreach ($cfRules as $cfRule) {
|
||||
$objConditional = new Conditional();
|
||||
$objConditional->setConditionType((string) $cfRule['type']);
|
||||
$objConditional->setOperatorType((string) $cfRule['operator']);
|
||||
|
||||
if ((string) $cfRule['text'] != '') {
|
||||
$objConditional->setText((string) $cfRule['text']);
|
||||
}
|
||||
|
||||
if (isset($cfRule['stopIfTrue']) && (int) $cfRule['stopIfTrue'] === 1) {
|
||||
$objConditional->setStopIfTrue(true);
|
||||
}
|
||||
|
||||
if (count($cfRule->formula) > 1) {
|
||||
foreach ($cfRule->formula as $formula) {
|
||||
$objConditional->addCondition((string) $formula);
|
||||
}
|
||||
} else {
|
||||
$objConditional->addCondition((string) $cfRule->formula);
|
||||
}
|
||||
$objConditional->setStyle(clone $this->dxfs[(int) ($cfRule['dxfId'])]);
|
||||
$conditionalStyles[] = $objConditional;
|
||||
}
|
||||
|
||||
return $conditionalStyles;
|
||||
}
|
||||
}
|
50
src/PhpSpreadsheet/Reader/Xlsx/DataValidations.php
Normal file
50
src/PhpSpreadsheet/Reader/Xlsx/DataValidations.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
|
||||
class DataValidations
|
||||
{
|
||||
private $worksheet;
|
||||
|
||||
private $worksheetXml;
|
||||
|
||||
public function __construct(Worksheet $workSheet, \SimpleXMLElement $worksheetXml)
|
||||
{
|
||||
$this->worksheet = $workSheet;
|
||||
$this->worksheetXml = $worksheetXml;
|
||||
}
|
||||
|
||||
public function load()
|
||||
{
|
||||
foreach ($this->worksheetXml->dataValidation as $dataValidation) {
|
||||
// Uppercase coordinate
|
||||
$range = strtoupper($dataValidation['sqref']);
|
||||
$rangeSet = explode(' ', $range);
|
||||
foreach ($rangeSet as $range) {
|
||||
$stRange = $this->worksheet->shrinkRangeToFit($range);
|
||||
|
||||
// Extract all cell references in $range
|
||||
foreach (Coordinate::extractAllCellReferencesInRange($stRange) as $reference) {
|
||||
// Create validation
|
||||
$docValidation = $this->worksheet->getCell($reference)->getDataValidation();
|
||||
$docValidation->setType((string) $dataValidation['type']);
|
||||
$docValidation->setErrorStyle((string) $dataValidation['errorStyle']);
|
||||
$docValidation->setOperator((string) $dataValidation['operator']);
|
||||
$docValidation->setAllowBlank($dataValidation['allowBlank'] != 0);
|
||||
$docValidation->setShowDropDown($dataValidation['showDropDown'] == 0);
|
||||
$docValidation->setShowInputMessage($dataValidation['showInputMessage'] != 0);
|
||||
$docValidation->setShowErrorMessage($dataValidation['showErrorMessage'] != 0);
|
||||
$docValidation->setErrorTitle((string) $dataValidation['errorTitle']);
|
||||
$docValidation->setError((string) $dataValidation['error']);
|
||||
$docValidation->setPromptTitle((string) $dataValidation['promptTitle']);
|
||||
$docValidation->setPrompt((string) $dataValidation['prompt']);
|
||||
$docValidation->setFormula1((string) $dataValidation->formula1);
|
||||
$docValidation->setFormula2((string) $dataValidation->formula2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
58
src/PhpSpreadsheet/Reader/Xlsx/Hyperlinks.php
Normal file
58
src/PhpSpreadsheet/Reader/Xlsx/Hyperlinks.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
|
||||
class Hyperlinks
|
||||
{
|
||||
private $worksheet;
|
||||
|
||||
private $hyperlinks = [];
|
||||
|
||||
public function __construct(Worksheet $workSheet)
|
||||
{
|
||||
$this->worksheet = $workSheet;
|
||||
}
|
||||
|
||||
public function readHyperlinks(\SimpleXMLElement $relsWorksheet)
|
||||
{
|
||||
foreach ($relsWorksheet->Relationship as $element) {
|
||||
if ($element['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink') {
|
||||
$this->hyperlinks[(string) $element['Id']] = (string) $element['Target'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function setHyperlinks(\SimpleXMLElement $worksheetXml)
|
||||
{
|
||||
foreach ($worksheetXml->hyperlink as $hyperlink) {
|
||||
$this->setHyperlink($hyperlink, $this->worksheet);
|
||||
}
|
||||
}
|
||||
|
||||
private function setHyperlink(\SimpleXMLElement $hyperlink, Worksheet $worksheet)
|
||||
{
|
||||
// Link url
|
||||
$linkRel = $hyperlink->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships');
|
||||
|
||||
foreach (Coordinate::extractAllCellReferencesInRange($hyperlink['ref']) as $cellReference) {
|
||||
$cell = $worksheet->getCell($cellReference);
|
||||
if (isset($linkRel['id'])) {
|
||||
$hyperlinkUrl = $this->hyperlinks[(string) $linkRel['id']];
|
||||
if (isset($hyperlink['location'])) {
|
||||
$hyperlinkUrl .= '#' . (string) $hyperlink['location'];
|
||||
}
|
||||
$cell->getHyperlink()->setUrl($hyperlinkUrl);
|
||||
} elseif (isset($hyperlink['location'])) {
|
||||
$cell->getHyperlink()->setUrl('sheet://' . (string) $hyperlink['location']);
|
||||
}
|
||||
|
||||
// Tooltip
|
||||
if (isset($hyperlink['tooltip'])) {
|
||||
$cell->getHyperlink()->setTooltip((string) $hyperlink['tooltip']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
150
src/PhpSpreadsheet/Reader/Xlsx/PageSetup.php
Normal file
150
src/PhpSpreadsheet/Reader/Xlsx/PageSetup.php
Normal file
@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
|
||||
class PageSetup extends BaseParserClass
|
||||
{
|
||||
private $worksheet;
|
||||
|
||||
private $worksheetXml;
|
||||
|
||||
public function __construct(Worksheet $workSheet, \SimpleXMLElement $worksheetXml = null)
|
||||
{
|
||||
$this->worksheet = $workSheet;
|
||||
$this->worksheetXml = $worksheetXml;
|
||||
}
|
||||
|
||||
public function load(array $unparsedLoadedData)
|
||||
{
|
||||
if (!$this->worksheetXml) {
|
||||
return $unparsedLoadedData;
|
||||
}
|
||||
|
||||
$this->margins($this->worksheetXml, $this->worksheet);
|
||||
$unparsedLoadedData = $this->pageSetup($this->worksheetXml, $this->worksheet, $unparsedLoadedData);
|
||||
$this->headerFooter($this->worksheetXml, $this->worksheet);
|
||||
$this->pageBreaks($this->worksheetXml, $this->worksheet);
|
||||
|
||||
return $unparsedLoadedData;
|
||||
}
|
||||
|
||||
private function margins(\SimpleXMLElement $xmlSheet, Worksheet $worksheet)
|
||||
{
|
||||
if ($xmlSheet->pageMargins) {
|
||||
$docPageMargins = $worksheet->getPageMargins();
|
||||
$docPageMargins->setLeft((float) ($xmlSheet->pageMargins['left']));
|
||||
$docPageMargins->setRight((float) ($xmlSheet->pageMargins['right']));
|
||||
$docPageMargins->setTop((float) ($xmlSheet->pageMargins['top']));
|
||||
$docPageMargins->setBottom((float) ($xmlSheet->pageMargins['bottom']));
|
||||
$docPageMargins->setHeader((float) ($xmlSheet->pageMargins['header']));
|
||||
$docPageMargins->setFooter((float) ($xmlSheet->pageMargins['footer']));
|
||||
}
|
||||
}
|
||||
|
||||
private function pageSetup(\SimpleXMLElement $xmlSheet, Worksheet $worksheet, array $unparsedLoadedData)
|
||||
{
|
||||
if ($xmlSheet->pageSetup) {
|
||||
$docPageSetup = $worksheet->getPageSetup();
|
||||
|
||||
if (isset($xmlSheet->pageSetup['orientation'])) {
|
||||
$docPageSetup->setOrientation((string) $xmlSheet->pageSetup['orientation']);
|
||||
}
|
||||
if (isset($xmlSheet->pageSetup['paperSize'])) {
|
||||
$docPageSetup->setPaperSize((int) ($xmlSheet->pageSetup['paperSize']));
|
||||
}
|
||||
if (isset($xmlSheet->pageSetup['scale'])) {
|
||||
$docPageSetup->setScale((int) ($xmlSheet->pageSetup['scale']), false);
|
||||
}
|
||||
if (isset($xmlSheet->pageSetup['fitToHeight']) && (int) ($xmlSheet->pageSetup['fitToHeight']) >= 0) {
|
||||
$docPageSetup->setFitToHeight((int) ($xmlSheet->pageSetup['fitToHeight']), false);
|
||||
}
|
||||
if (isset($xmlSheet->pageSetup['fitToWidth']) && (int) ($xmlSheet->pageSetup['fitToWidth']) >= 0) {
|
||||
$docPageSetup->setFitToWidth((int) ($xmlSheet->pageSetup['fitToWidth']), false);
|
||||
}
|
||||
if (isset($xmlSheet->pageSetup['firstPageNumber'], $xmlSheet->pageSetup['useFirstPageNumber']) &&
|
||||
self::boolean((string) $xmlSheet->pageSetup['useFirstPageNumber'])) {
|
||||
$docPageSetup->setFirstPageNumber((int) ($xmlSheet->pageSetup['firstPageNumber']));
|
||||
}
|
||||
|
||||
$relAttributes = $xmlSheet->pageSetup->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships');
|
||||
if (isset($relAttributes['id'])) {
|
||||
$unparsedLoadedData['sheets'][$worksheet->getCodeName()]['pageSetupRelId'] = (string) $relAttributes['id'];
|
||||
}
|
||||
}
|
||||
|
||||
return $unparsedLoadedData;
|
||||
}
|
||||
|
||||
private function headerFooter(\SimpleXMLElement $xmlSheet, Worksheet $worksheet)
|
||||
{
|
||||
if ($xmlSheet->headerFooter) {
|
||||
$docHeaderFooter = $worksheet->getHeaderFooter();
|
||||
|
||||
if (isset($xmlSheet->headerFooter['differentOddEven']) &&
|
||||
self::boolean((string) $xmlSheet->headerFooter['differentOddEven'])) {
|
||||
$docHeaderFooter->setDifferentOddEven(true);
|
||||
} else {
|
||||
$docHeaderFooter->setDifferentOddEven(false);
|
||||
}
|
||||
if (isset($xmlSheet->headerFooter['differentFirst']) &&
|
||||
self::boolean((string) $xmlSheet->headerFooter['differentFirst'])) {
|
||||
$docHeaderFooter->setDifferentFirst(true);
|
||||
} else {
|
||||
$docHeaderFooter->setDifferentFirst(false);
|
||||
}
|
||||
if (isset($xmlSheet->headerFooter['scaleWithDoc']) &&
|
||||
!self::boolean((string) $xmlSheet->headerFooter['scaleWithDoc'])) {
|
||||
$docHeaderFooter->setScaleWithDocument(false);
|
||||
} else {
|
||||
$docHeaderFooter->setScaleWithDocument(true);
|
||||
}
|
||||
if (isset($xmlSheet->headerFooter['alignWithMargins']) &&
|
||||
!self::boolean((string) $xmlSheet->headerFooter['alignWithMargins'])) {
|
||||
$docHeaderFooter->setAlignWithMargins(false);
|
||||
} else {
|
||||
$docHeaderFooter->setAlignWithMargins(true);
|
||||
}
|
||||
|
||||
$docHeaderFooter->setOddHeader((string) $xmlSheet->headerFooter->oddHeader);
|
||||
$docHeaderFooter->setOddFooter((string) $xmlSheet->headerFooter->oddFooter);
|
||||
$docHeaderFooter->setEvenHeader((string) $xmlSheet->headerFooter->evenHeader);
|
||||
$docHeaderFooter->setEvenFooter((string) $xmlSheet->headerFooter->evenFooter);
|
||||
$docHeaderFooter->setFirstHeader((string) $xmlSheet->headerFooter->firstHeader);
|
||||
$docHeaderFooter->setFirstFooter((string) $xmlSheet->headerFooter->firstFooter);
|
||||
}
|
||||
}
|
||||
|
||||
private function pageBreaks(\SimpleXMLElement $xmlSheet, Worksheet $worksheet)
|
||||
{
|
||||
if ($xmlSheet->rowBreaks && $xmlSheet->rowBreaks->brk) {
|
||||
$this->rowBreaks($xmlSheet, $worksheet);
|
||||
}
|
||||
if ($xmlSheet->colBreaks && $xmlSheet->colBreaks->brk) {
|
||||
$this->columnBreaks($xmlSheet, $worksheet);
|
||||
}
|
||||
}
|
||||
|
||||
private function rowBreaks(\SimpleXMLElement $xmlSheet, Worksheet $worksheet)
|
||||
{
|
||||
foreach ($xmlSheet->rowBreaks->brk as $brk) {
|
||||
if ($brk['man']) {
|
||||
$worksheet->setBreak("A{$brk['id']}", Worksheet::BREAK_ROW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function columnBreaks(\SimpleXMLElement $xmlSheet, Worksheet $worksheet)
|
||||
{
|
||||
foreach ($xmlSheet->colBreaks->brk as $brk) {
|
||||
if ($brk['man']) {
|
||||
$worksheet->setBreak(
|
||||
Coordinate::stringFromColumnIndex(((int) $brk['id']) + 1) . '1',
|
||||
Worksheet::BREAK_COLUMN
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
124
src/PhpSpreadsheet/Reader/Xlsx/SheetViewOptions.php
Normal file
124
src/PhpSpreadsheet/Reader/Xlsx/SheetViewOptions.php
Normal file
@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
|
||||
class SheetViewOptions extends BaseParserClass
|
||||
{
|
||||
private $worksheet;
|
||||
|
||||
private $worksheetXml;
|
||||
|
||||
public function __construct(Worksheet $workSheet, \SimpleXMLElement $worksheetXml = null)
|
||||
{
|
||||
$this->worksheet = $workSheet;
|
||||
$this->worksheetXml = $worksheetXml;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $readDataOnly
|
||||
*/
|
||||
public function load($readDataOnly = false)
|
||||
{
|
||||
if ($this->worksheetXml === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($this->worksheetXml->sheetPr)) {
|
||||
$this->tabColor($this->worksheetXml->sheetPr);
|
||||
$this->codeName($this->worksheetXml->sheetPr);
|
||||
$this->outlines($this->worksheetXml->sheetPr);
|
||||
$this->pageSetup($this->worksheetXml->sheetPr);
|
||||
}
|
||||
|
||||
if (isset($this->worksheetXml->sheetFormatPr)) {
|
||||
$this->sheetFormat($this->worksheetXml->sheetFormatPr);
|
||||
}
|
||||
|
||||
if (!$readDataOnly && isset($this->worksheetXml->printOptions)) {
|
||||
$this->printOptions($this->worksheetXml->printOptions);
|
||||
}
|
||||
}
|
||||
|
||||
private function tabColor(\SimpleXMLElement $sheetPr)
|
||||
{
|
||||
if (isset($sheetPr->tabColor, $sheetPr->tabColor['rgb'])) {
|
||||
$this->worksheet->getTabColor()->setARGB((string) $sheetPr->tabColor['rgb']);
|
||||
}
|
||||
}
|
||||
|
||||
private function codeName(\SimpleXMLElement $sheetPr)
|
||||
{
|
||||
if (isset($sheetPr['codeName'])) {
|
||||
$this->worksheet->setCodeName((string) $sheetPr['codeName'], false);
|
||||
}
|
||||
}
|
||||
|
||||
private function outlines(\SimpleXMLElement $sheetPr)
|
||||
{
|
||||
if (isset($sheetPr->outlinePr)) {
|
||||
if (isset($sheetPr->outlinePr['summaryRight']) &&
|
||||
!self::boolean((string) $sheetPr->outlinePr['summaryRight'])) {
|
||||
$this->worksheet->setShowSummaryRight(false);
|
||||
} else {
|
||||
$this->worksheet->setShowSummaryRight(true);
|
||||
}
|
||||
|
||||
if (isset($sheetPr->outlinePr['summaryBelow']) &&
|
||||
!self::boolean((string) $sheetPr->outlinePr['summaryBelow'])) {
|
||||
$this->worksheet->setShowSummaryBelow(false);
|
||||
} else {
|
||||
$this->worksheet->setShowSummaryBelow(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function pageSetup(\SimpleXMLElement $sheetPr)
|
||||
{
|
||||
if (isset($sheetPr->pageSetUpPr)) {
|
||||
if (isset($sheetPr->pageSetUpPr['fitToPage']) &&
|
||||
!self::boolean((string) $sheetPr->pageSetUpPr['fitToPage'])) {
|
||||
$this->worksheet->getPageSetup()->setFitToPage(false);
|
||||
} else {
|
||||
$this->worksheet->getPageSetup()->setFitToPage(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function sheetFormat(\SimpleXMLElement $sheetFormatPr)
|
||||
{
|
||||
if (isset($sheetFormatPr['customHeight']) &&
|
||||
self::boolean((string) $sheetFormatPr['customHeight']) &&
|
||||
isset($sheetFormatPr['defaultRowHeight'])) {
|
||||
$this->worksheet->getDefaultRowDimension()
|
||||
->setRowHeight((float) $sheetFormatPr['defaultRowHeight']);
|
||||
}
|
||||
|
||||
if (isset($sheetFormatPr['defaultColWidth'])) {
|
||||
$this->worksheet->getDefaultColumnDimension()
|
||||
->setWidth((float) $sheetFormatPr['defaultColWidth']);
|
||||
}
|
||||
|
||||
if (isset($sheetFormatPr['zeroHeight']) &&
|
||||
((string) $sheetFormatPr['zeroHeight'] === '1')) {
|
||||
$this->worksheet->getDefaultRowDimension()->setZeroHeight(true);
|
||||
}
|
||||
}
|
||||
|
||||
private function printOptions(\SimpleXMLElement $printOptions)
|
||||
{
|
||||
if (self::boolean((string) $printOptions['gridLinesSet'])) {
|
||||
$this->worksheet->setShowGridlines(true);
|
||||
}
|
||||
if (self::boolean((string) $printOptions['gridLines'])) {
|
||||
$this->worksheet->setPrintGridlines(true);
|
||||
}
|
||||
if (self::boolean((string) $printOptions['horizontalCentered'])) {
|
||||
$this->worksheet->getPageSetup()->setHorizontalCentered(true);
|
||||
}
|
||||
if (self::boolean((string) $printOptions['verticalCentered'])) {
|
||||
$this->worksheet->getPageSetup()->setVerticalCentered(true);
|
||||
}
|
||||
}
|
||||
}
|
127
src/PhpSpreadsheet/Reader/Xlsx/SheetViews.php
Normal file
127
src/PhpSpreadsheet/Reader/Xlsx/SheetViews.php
Normal file
@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
|
||||
class SheetViews extends BaseParserClass
|
||||
{
|
||||
private $sheetViewXml;
|
||||
|
||||
private $worksheet;
|
||||
|
||||
public function __construct(\SimpleXMLElement $sheetViewXml, Worksheet $workSheet)
|
||||
{
|
||||
$this->sheetViewXml = $sheetViewXml;
|
||||
$this->worksheet = $workSheet;
|
||||
}
|
||||
|
||||
public function load()
|
||||
{
|
||||
$this->zoomScale();
|
||||
$this->view();
|
||||
$this->gridLines();
|
||||
$this->headers();
|
||||
$this->direction();
|
||||
|
||||
if (isset($this->sheetViewXml->pane)) {
|
||||
$this->pane();
|
||||
}
|
||||
if (isset($this->sheetViewXml->selection, $this->sheetViewXml->selection['sqref'])) {
|
||||
$this->selection();
|
||||
}
|
||||
}
|
||||
|
||||
private function zoomScale()
|
||||
{
|
||||
if (isset($this->sheetViewXml['zoomScale'])) {
|
||||
$zoomScale = (int) ($this->sheetViewXml['zoomScale']);
|
||||
if ($zoomScale <= 0) {
|
||||
// setZoomScale will throw an Exception if the scale is less than or equals 0
|
||||
// that is OK when manually creating documents, but we should be able to read all documents
|
||||
$zoomScale = 100;
|
||||
}
|
||||
|
||||
$this->worksheet->getSheetView()->setZoomScale($zoomScale);
|
||||
}
|
||||
|
||||
if (isset($this->sheetViewXml['zoomScaleNormal'])) {
|
||||
$zoomScaleNormal = (int) ($this->sheetViewXml['zoomScaleNormal']);
|
||||
if ($zoomScaleNormal <= 0) {
|
||||
// setZoomScaleNormal will throw an Exception if the scale is less than or equals 0
|
||||
// that is OK when manually creating documents, but we should be able to read all documents
|
||||
$zoomScaleNormal = 100;
|
||||
}
|
||||
|
||||
$this->worksheet->getSheetView()->setZoomScaleNormal($zoomScaleNormal);
|
||||
}
|
||||
}
|
||||
|
||||
private function view()
|
||||
{
|
||||
if (isset($this->sheetViewXml['view'])) {
|
||||
$this->worksheet->getSheetView()->setView((string) $this->sheetViewXml['view']);
|
||||
}
|
||||
}
|
||||
|
||||
private function gridLines()
|
||||
{
|
||||
if (isset($this->sheetViewXml['showGridLines'])) {
|
||||
$this->worksheet->setShowGridLines(
|
||||
self::boolean((string) $this->sheetViewXml['showGridLines'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function headers()
|
||||
{
|
||||
if (isset($this->sheetViewXml['showRowColHeaders'])) {
|
||||
$this->worksheet->setShowRowColHeaders(
|
||||
self::boolean((string) $this->sheetViewXml['showRowColHeaders'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function direction()
|
||||
{
|
||||
if (isset($this->sheetViewXml['rightToLeft'])) {
|
||||
$this->worksheet->setRightToLeft(
|
||||
self::boolean((string) $this->sheetViewXml['rightToLeft'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function pane()
|
||||
{
|
||||
$xSplit = 0;
|
||||
$ySplit = 0;
|
||||
$topLeftCell = null;
|
||||
|
||||
if (isset($this->sheetViewXml->pane['xSplit'])) {
|
||||
$xSplit = (int) ($this->sheetViewXml->pane['xSplit']);
|
||||
}
|
||||
|
||||
if (isset($this->sheetViewXml->pane['ySplit'])) {
|
||||
$ySplit = (int) ($this->sheetViewXml->pane['ySplit']);
|
||||
}
|
||||
|
||||
if (isset($this->sheetViewXml->pane['topLeftCell'])) {
|
||||
$topLeftCell = (string) $this->sheetViewXml->pane['topLeftCell'];
|
||||
}
|
||||
|
||||
$this->worksheet->freezePane(
|
||||
Coordinate::stringFromColumnIndex($xSplit + 1) . ($ySplit + 1),
|
||||
$topLeftCell
|
||||
);
|
||||
}
|
||||
|
||||
private function selection()
|
||||
{
|
||||
$sqref = (string) $this->sheetViewXml->selection['sqref'];
|
||||
$sqref = explode(' ', $sqref);
|
||||
$sqref = $sqref[0];
|
||||
|
||||
$this->worksheet->setSelectedCells($sqref);
|
||||
}
|
||||
}
|
265
src/PhpSpreadsheet/Reader/Xlsx/Styles.php
Normal file
265
src/PhpSpreadsheet/Reader/Xlsx/Styles.php
Normal file
@ -0,0 +1,265 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Border;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Borders;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Color;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Fill;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Font;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Protection;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Style;
|
||||
|
||||
class Styles extends BaseParserClass
|
||||
{
|
||||
/**
|
||||
* Theme instance.
|
||||
*
|
||||
* @var Theme
|
||||
*/
|
||||
private static $theme = null;
|
||||
|
||||
private $styles = [];
|
||||
|
||||
private $cellStyles = [];
|
||||
|
||||
private $styleXml;
|
||||
|
||||
public function __construct(\SimpleXMLElement $styleXml)
|
||||
{
|
||||
$this->styleXml = $styleXml;
|
||||
}
|
||||
|
||||
public function setStyleBaseData(Theme $theme, $styles, $cellStyles)
|
||||
{
|
||||
self::$theme = $theme;
|
||||
$this->styles = $styles;
|
||||
$this->cellStyles = $cellStyles;
|
||||
}
|
||||
|
||||
private static function readFontStyle(Font $fontStyle, \SimpleXMLElement $fontStyleXml)
|
||||
{
|
||||
$fontStyle->setName((string) $fontStyleXml->name['val']);
|
||||
$fontStyle->setSize((float) $fontStyleXml->sz['val']);
|
||||
|
||||
if (isset($fontStyleXml->b)) {
|
||||
$fontStyle->setBold(!isset($fontStyleXml->b['val']) || self::boolean((string) $fontStyleXml->b['val']));
|
||||
}
|
||||
if (isset($fontStyleXml->i)) {
|
||||
$fontStyle->setItalic(!isset($fontStyleXml->i['val']) || self::boolean((string) $fontStyleXml->i['val']));
|
||||
}
|
||||
if (isset($fontStyleXml->strike)) {
|
||||
$fontStyle->setStrikethrough(!isset($fontStyleXml->strike['val']) || self::boolean((string) $fontStyleXml->strike['val']));
|
||||
}
|
||||
$fontStyle->getColor()->setARGB(self::readColor($fontStyleXml->color));
|
||||
|
||||
if (isset($fontStyleXml->u) && !isset($fontStyleXml->u['val'])) {
|
||||
$fontStyle->setUnderline(Font::UNDERLINE_SINGLE);
|
||||
} elseif (isset($fontStyleXml->u, $fontStyleXml->u['val'])) {
|
||||
$fontStyle->setUnderline((string) $fontStyleXml->u['val']);
|
||||
}
|
||||
|
||||
if (isset($fontStyleXml->vertAlign, $fontStyleXml->vertAlign['val'])) {
|
||||
$verticalAlign = strtolower((string) $fontStyleXml->vertAlign['val']);
|
||||
if ($verticalAlign === 'superscript') {
|
||||
$fontStyle->setSuperscript(true);
|
||||
}
|
||||
if ($verticalAlign === 'subscript') {
|
||||
$fontStyle->setSubscript(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function readFillStyle(Fill $fillStyle, \SimpleXMLElement $fillStyleXml)
|
||||
{
|
||||
if ($fillStyleXml->gradientFill) {
|
||||
/** @var \SimpleXMLElement $gradientFill */
|
||||
$gradientFill = $fillStyleXml->gradientFill[0];
|
||||
if (!empty($gradientFill['type'])) {
|
||||
$fillStyle->setFillType((string) $gradientFill['type']);
|
||||
}
|
||||
$fillStyle->setRotation((float) ($gradientFill['degree']));
|
||||
$gradientFill->registerXPathNamespace('sml', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main');
|
||||
$fillStyle->getStartColor()->setARGB(self::readColor(self::getArrayItem($gradientFill->xpath('sml:stop[@position=0]'))->color));
|
||||
$fillStyle->getEndColor()->setARGB(self::readColor(self::getArrayItem($gradientFill->xpath('sml:stop[@position=1]'))->color));
|
||||
} elseif ($fillStyleXml->patternFill) {
|
||||
$patternType = (string) $fillStyleXml->patternFill['patternType'] != '' ? (string) $fillStyleXml->patternFill['patternType'] : 'solid';
|
||||
$fillStyle->setFillType($patternType);
|
||||
if ($fillStyleXml->patternFill->fgColor) {
|
||||
$fillStyle->getStartColor()->setARGB(self::readColor($fillStyleXml->patternFill->fgColor, true));
|
||||
} else {
|
||||
$fillStyle->getStartColor()->setARGB('FF000000');
|
||||
}
|
||||
if ($fillStyleXml->patternFill->bgColor) {
|
||||
$fillStyle->getEndColor()->setARGB(self::readColor($fillStyleXml->patternFill->bgColor, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function readBorderStyle(Borders $borderStyle, \SimpleXMLElement $borderStyleXml)
|
||||
{
|
||||
$diagonalUp = self::boolean((string) $borderStyleXml['diagonalUp']);
|
||||
$diagonalDown = self::boolean((string) $borderStyleXml['diagonalDown']);
|
||||
if (!$diagonalUp && !$diagonalDown) {
|
||||
$borderStyle->setDiagonalDirection(Borders::DIAGONAL_NONE);
|
||||
} elseif ($diagonalUp && !$diagonalDown) {
|
||||
$borderStyle->setDiagonalDirection(Borders::DIAGONAL_UP);
|
||||
} elseif (!$diagonalUp && $diagonalDown) {
|
||||
$borderStyle->setDiagonalDirection(Borders::DIAGONAL_DOWN);
|
||||
} else {
|
||||
$borderStyle->setDiagonalDirection(Borders::DIAGONAL_BOTH);
|
||||
}
|
||||
|
||||
self::readBorder($borderStyle->getLeft(), $borderStyleXml->left);
|
||||
self::readBorder($borderStyle->getRight(), $borderStyleXml->right);
|
||||
self::readBorder($borderStyle->getTop(), $borderStyleXml->top);
|
||||
self::readBorder($borderStyle->getBottom(), $borderStyleXml->bottom);
|
||||
self::readBorder($borderStyle->getDiagonal(), $borderStyleXml->diagonal);
|
||||
}
|
||||
|
||||
private static function readBorder(Border $border, \SimpleXMLElement $borderXml)
|
||||
{
|
||||
if (isset($borderXml['style'])) {
|
||||
$border->setBorderStyle((string) $borderXml['style']);
|
||||
}
|
||||
if (isset($borderXml->color)) {
|
||||
$border->getColor()->setARGB(self::readColor($borderXml->color));
|
||||
}
|
||||
}
|
||||
|
||||
private static function readAlignmentStyle(Alignment $alignment, \SimpleXMLElement $alignmentXml)
|
||||
{
|
||||
$alignment->setHorizontal((string) $alignmentXml->alignment['horizontal']);
|
||||
$alignment->setVertical((string) $alignmentXml->alignment['vertical']);
|
||||
|
||||
$textRotation = 0;
|
||||
if ((int) $alignmentXml->alignment['textRotation'] <= 90) {
|
||||
$textRotation = (int) $alignmentXml->alignment['textRotation'];
|
||||
} elseif ((int) $alignmentXml->alignment['textRotation'] > 90) {
|
||||
$textRotation = 90 - (int) $alignmentXml->alignment['textRotation'];
|
||||
}
|
||||
|
||||
$alignment->setTextRotation((int) $textRotation);
|
||||
$alignment->setWrapText(self::boolean((string) $alignmentXml->alignment['wrapText']));
|
||||
$alignment->setShrinkToFit(self::boolean((string) $alignmentXml->alignment['shrinkToFit']));
|
||||
$alignment->setIndent((int) ((string) $alignmentXml->alignment['indent']) > 0 ? (int) ((string) $alignmentXml->alignment['indent']) : 0);
|
||||
$alignment->setReadOrder((int) ((string) $alignmentXml->alignment['readingOrder']) > 0 ? (int) ((string) $alignmentXml->alignment['readingOrder']) : 0);
|
||||
}
|
||||
|
||||
private function readStyle(Style $docStyle, $style)
|
||||
{
|
||||
$docStyle->getNumberFormat()->setFormatCode($style->numFmt);
|
||||
|
||||
if (isset($style->font)) {
|
||||
self::readFontStyle($docStyle->getFont(), $style->font);
|
||||
}
|
||||
|
||||
if (isset($style->fill)) {
|
||||
self::readFillStyle($docStyle->getFill(), $style->fill);
|
||||
}
|
||||
|
||||
if (isset($style->border)) {
|
||||
self::readBorderStyle($docStyle->getBorders(), $style->border);
|
||||
}
|
||||
|
||||
if (isset($style->alignment)) {
|
||||
self::readAlignmentStyle($docStyle->getAlignment(), $style->alignment);
|
||||
}
|
||||
|
||||
// protection
|
||||
if (isset($style->protection)) {
|
||||
$this->readProtectionLocked($docStyle, $style);
|
||||
$this->readProtectionHidden($docStyle, $style);
|
||||
}
|
||||
|
||||
// top-level style settings
|
||||
if (isset($style->quotePrefix)) {
|
||||
$docStyle->setQuotePrefix(true);
|
||||
}
|
||||
}
|
||||
|
||||
private function readProtectionLocked(Style $docStyle, $style)
|
||||
{
|
||||
if (isset($style->protection['locked'])) {
|
||||
if (self::boolean((string) $style->protection['locked'])) {
|
||||
$docStyle->getProtection()->setLocked(Protection::PROTECTION_PROTECTED);
|
||||
} else {
|
||||
$docStyle->getProtection()->setLocked(Protection::PROTECTION_UNPROTECTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function readProtectionHidden(Style $docStyle, $style)
|
||||
{
|
||||
if (isset($style->protection['hidden'])) {
|
||||
if (self::boolean((string) $style->protection['hidden'])) {
|
||||
$docStyle->getProtection()->setHidden(Protection::PROTECTION_PROTECTED);
|
||||
} else {
|
||||
$docStyle->getProtection()->setHidden(Protection::PROTECTION_UNPROTECTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function readColor($color, $background = false)
|
||||
{
|
||||
if (isset($color['rgb'])) {
|
||||
return (string) $color['rgb'];
|
||||
} elseif (isset($color['indexed'])) {
|
||||
return Color::indexedColor($color['indexed'] - 7, $background)->getARGB();
|
||||
} elseif (isset($color['theme'])) {
|
||||
if (self::$theme !== null) {
|
||||
$returnColour = self::$theme->getColourByIndex((int) $color['theme']);
|
||||
if (isset($color['tint'])) {
|
||||
$tintAdjust = (float) $color['tint'];
|
||||
$returnColour = Color::changeBrightness($returnColour, $tintAdjust);
|
||||
}
|
||||
|
||||
return 'FF' . $returnColour;
|
||||
}
|
||||
}
|
||||
|
||||
return ($background) ? 'FFFFFFFF' : 'FF000000';
|
||||
}
|
||||
|
||||
public function dxfs($readDataOnly = false)
|
||||
{
|
||||
$dxfs = [];
|
||||
if (!$readDataOnly && $this->styleXml) {
|
||||
// Conditional Styles
|
||||
if ($this->styleXml->dxfs) {
|
||||
foreach ($this->styleXml->dxfs->dxf as $dxf) {
|
||||
$style = new Style(false, true);
|
||||
$this->readStyle($style, $dxf);
|
||||
$dxfs[] = $style;
|
||||
}
|
||||
}
|
||||
// Cell Styles
|
||||
if ($this->styleXml->cellStyles) {
|
||||
foreach ($this->styleXml->cellStyles->cellStyle as $cellStyle) {
|
||||
if ((int) ($cellStyle['builtinId']) == 0) {
|
||||
if (isset($this->cellStyles[(int) ($cellStyle['xfId'])])) {
|
||||
// Set default style
|
||||
$style = new Style();
|
||||
$this->readStyle($style, $this->cellStyles[(int) ($cellStyle['xfId'])]);
|
||||
|
||||
// normal style, currently not using it for anything
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $dxfs;
|
||||
}
|
||||
|
||||
public function styles()
|
||||
{
|
||||
return $this->styles;
|
||||
}
|
||||
|
||||
private static function getArrayItem($array, $key = 0)
|
||||
{
|
||||
return isset($array[$key]) ? $array[$key] : null;
|
||||
}
|
||||
}
|
@ -39,6 +39,7 @@ class SampleTest extends TestCase
|
||||
if (version_compare(PHP_VERSION, '7.2.99') >= 0) {
|
||||
$skipped[] = 'Basic/26_Utf8.php';
|
||||
$skipped[] = 'Pdf/21_Pdf_Domdf.php';
|
||||
$skipped[] = 'Pdf/21_Pdf_mPDF.php';
|
||||
}
|
||||
|
||||
// Unfortunately some tests are too long be ran with code-coverage
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Reader;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||
use PhpOffice\PhpSpreadsheet\Document\Properties;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Ods;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Font;
|
||||
@ -222,4 +223,46 @@ class OdsTest extends TestCase
|
||||
self::assertTrue($style->getFont()->getBold());
|
||||
self::assertTrue($style->getFont()->getItalic());
|
||||
}
|
||||
|
||||
public function testLoadOdsWorkbookProperties()
|
||||
{
|
||||
$customPropertySet = [
|
||||
'Owner' => ['type' => Properties::PROPERTY_TYPE_STRING, 'value' => 'PHPOffice'],
|
||||
'Tested' => ['type' => Properties::PROPERTY_TYPE_BOOLEAN, 'value' => true],
|
||||
'Counter' => ['type' => Properties::PROPERTY_TYPE_FLOAT, 'value' => 10.0],
|
||||
'TestDate' => ['type' => Properties::PROPERTY_TYPE_DATE, 'value' => '2019-06-30'],
|
||||
'HereAndNow' => ['type' => Properties::PROPERTY_TYPE_DATE, 'value' => '2019-06-30'],
|
||||
];
|
||||
|
||||
$filename = './data/Reader/Ods/propertyTest.ods';
|
||||
$reader = new Ods();
|
||||
$spreadsheet = $reader->load($filename);
|
||||
|
||||
$properties = $spreadsheet->getProperties();
|
||||
// Core Properties
|
||||
// $this->assertSame('Mark Baker', $properties->getCreator());
|
||||
$this->assertSame('Property Test File', $properties->getTitle());
|
||||
$this->assertSame('Testing for Properties', $properties->getSubject());
|
||||
$this->assertSame('TEST ODS PHPSpreadsheet', $properties->getKeywords());
|
||||
|
||||
// Extended Properties
|
||||
// $this->assertSame('PHPOffice', $properties->getCompany());
|
||||
// $this->assertSame('The Big Boss', $properties->getManager());
|
||||
|
||||
// Custom Properties
|
||||
$customProperties = $properties->getCustomProperties();
|
||||
$this->assertInternalType('array', $customProperties);
|
||||
$customProperties = array_flip($customProperties);
|
||||
$this->assertArrayHasKey('TestDate', $customProperties);
|
||||
|
||||
foreach ($customPropertySet as $propertyName => $testData) {
|
||||
$this->assertTrue($properties->isCustomPropertySet($propertyName));
|
||||
$this->assertSame($testData['type'], $properties->getCustomPropertyType($propertyName));
|
||||
if ($properties->getCustomPropertyType($propertyName) == Properties::PROPERTY_TYPE_DATE) {
|
||||
$this->assertSame($testData['value'], date('Y-m-d', $properties->getCustomPropertyValue($propertyName)));
|
||||
} else {
|
||||
$this->assertSame($testData['value'], $properties->getCustomPropertyValue($propertyName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,39 +2,166 @@
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Reader;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Document\Properties;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\File;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Conditional;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Style;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class XlsxTest extends TestCase
|
||||
{
|
||||
public function testLoadWorkbookProperties()
|
||||
public function testLoadXlsxWorkbookProperties()
|
||||
{
|
||||
$customPropertySet = [
|
||||
'Publisher' => ['type' => Properties::PROPERTY_TYPE_STRING, 'value' => 'PHPOffice Suite'],
|
||||
'Tested' => ['type' => Properties::PROPERTY_TYPE_BOOLEAN, 'value' => true],
|
||||
'Counter' => ['type' => Properties::PROPERTY_TYPE_INTEGER, 'value' => 15],
|
||||
'Rate' => ['type' => Properties::PROPERTY_TYPE_FLOAT, 'value' => 1.15],
|
||||
'Refactor Date' => ['type' => Properties::PROPERTY_TYPE_DATE, 'value' => '2019-06-10'],
|
||||
];
|
||||
|
||||
$filename = './data/Reader/XLSX/propertyTest.xlsx';
|
||||
$reader = new Xlsx();
|
||||
$spreadsheet = $reader->load($filename);
|
||||
|
||||
$properties = $spreadsheet->getProperties();
|
||||
// Core Properties
|
||||
$this->assertEquals('Mark Baker', $properties->getCreator());
|
||||
$this->assertEquals('Unit Testing', $properties->getTitle());
|
||||
$this->assertEquals('Property Test', $properties->getSubject());
|
||||
$this->assertSame('Mark Baker', $properties->getCreator());
|
||||
$this->assertSame('Unit Testing', $properties->getTitle());
|
||||
$this->assertSame('Property Test', $properties->getSubject());
|
||||
|
||||
// Extended Properties
|
||||
$this->assertEquals('PHPOffice', $properties->getCompany());
|
||||
$this->assertEquals('The Big Boss', $properties->getManager());
|
||||
$this->assertSame('PHPOffice', $properties->getCompany());
|
||||
$this->assertSame('The Big Boss', $properties->getManager());
|
||||
|
||||
// Custom Properties
|
||||
$customProperties = $properties->getCustomProperties();
|
||||
$this->assertInternalType('array', $customProperties);
|
||||
$customProperties = array_flip($customProperties);
|
||||
$this->assertArrayHasKey('Publisher', $customProperties);
|
||||
$this->assertTrue($properties->isCustomPropertySet('Publisher'));
|
||||
$this->assertEquals(Properties::PROPERTY_TYPE_STRING, $properties->getCustomPropertyType('Publisher'));
|
||||
$this->assertEquals('PHPOffice Suite', $properties->getCustomPropertyValue('Publisher'));
|
||||
|
||||
foreach ($customPropertySet as $propertyName => $testData) {
|
||||
$this->assertTrue($properties->isCustomPropertySet($propertyName));
|
||||
$this->assertSame($testData['type'], $properties->getCustomPropertyType($propertyName));
|
||||
if ($properties->getCustomPropertyType($propertyName) == Properties::PROPERTY_TYPE_DATE) {
|
||||
$this->assertSame($testData['value'], date('Y-m-d', $properties->getCustomPropertyValue($propertyName)));
|
||||
} else {
|
||||
$this->assertSame($testData['value'], $properties->getCustomPropertyValue($propertyName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function testLoadXlsxRowColumnAttributes()
|
||||
{
|
||||
$filename = './data/Reader/XLSX/rowColumnAttributeTest.xlsx';
|
||||
$reader = new Xlsx();
|
||||
$spreadsheet = $reader->load($filename);
|
||||
|
||||
$worksheet = $spreadsheet->getActiveSheet();
|
||||
for ($row = 1; $row <= 4; ++$row) {
|
||||
$this->assertEquals($row * 5 + 10, floor($worksheet->getRowDimension($row)->getRowHeight()));
|
||||
}
|
||||
|
||||
$this->assertFalse($worksheet->getRowDimension(5)->getVisible());
|
||||
|
||||
for ($column = 1; $column <= 4; ++$column) {
|
||||
$columnAddress = Coordinate::stringFromColumnIndex($column);
|
||||
$this->assertEquals(
|
||||
$column * 2 + 2,
|
||||
floor($worksheet->getColumnDimension($columnAddress)->getWidth())
|
||||
);
|
||||
}
|
||||
|
||||
$this->assertFalse($worksheet->getColumnDimension('E')->getVisible());
|
||||
}
|
||||
|
||||
public function testLoadXlsxWithStyles()
|
||||
{
|
||||
$expectedColours = [
|
||||
1 => ['A' => 'C00000', 'C' => 'FF0000', 'E' => 'FFC000'],
|
||||
3 => ['A' => '7030A0', 'C' => '000000', 'E' => 'FFFF00'],
|
||||
5 => ['A' => '002060', 'C' => '000000', 'E' => '92D050'],
|
||||
7 => ['A' => '0070C0', 'C' => '00B0F0', 'E' => '00B050'],
|
||||
];
|
||||
|
||||
$filename = './data/Reader/XLSX/stylesTest.xlsx';
|
||||
$reader = new Xlsx();
|
||||
$spreadsheet = $reader->load($filename);
|
||||
|
||||
$worksheet = $spreadsheet->getActiveSheet();
|
||||
for ($row = 1; $row <= 8; $row += 2) {
|
||||
for ($column = 'A'; $column !== 'G'; ++$column, ++$column) {
|
||||
$this->assertEquals(
|
||||
$expectedColours[$row][$column],
|
||||
$worksheet->getStyle($column . $row)->getFill()->getStartColor()->getRGB()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function testLoadXlsxAutofilter()
|
||||
{
|
||||
$filename = './data/Reader/XLSX/autofilterTest.xlsx';
|
||||
$reader = new Xlsx();
|
||||
$spreadsheet = $reader->load($filename);
|
||||
|
||||
$worksheet = $spreadsheet->getActiveSheet();
|
||||
|
||||
$autofilter = $worksheet->getAutoFilter();
|
||||
$this->assertInstanceOf(AutoFilter::class, $autofilter);
|
||||
$this->assertEquals('A1:D57', $autofilter->getRange());
|
||||
$this->assertEquals(
|
||||
AutoFilter\Column::AUTOFILTER_FILTERTYPE_FILTER,
|
||||
$autofilter->getColumn('A')->getFilterType()
|
||||
);
|
||||
}
|
||||
|
||||
public function testLoadXlsxPageSetup()
|
||||
{
|
||||
$filename = './data/Reader/XLSX/pageSetupTest.xlsx';
|
||||
$reader = new Xlsx();
|
||||
$spreadsheet = $reader->load($filename);
|
||||
|
||||
$worksheet = $spreadsheet->getActiveSheet();
|
||||
|
||||
$pageMargins = $worksheet->getPageMargins();
|
||||
// Convert from inches to cm for testing
|
||||
$this->assertEquals(2.5, $pageMargins->getTop() * 2.54);
|
||||
$this->assertEquals(3.3, $pageMargins->getLeft() * 2.54);
|
||||
$this->assertEquals(3.3, $pageMargins->getRight() * 2.54);
|
||||
$this->assertEquals(1.3, $pageMargins->getHeader() * 2.54);
|
||||
|
||||
$this->assertEquals(PageSetup::PAPERSIZE_A4, $worksheet->getPageSetup()->getPaperSize());
|
||||
$this->assertEquals(['A10', 'A20', 'A30', 'A40', 'A50'], array_keys($worksheet->getBreaks()));
|
||||
}
|
||||
|
||||
public function testLoadXlsxConditionalFormatting()
|
||||
{
|
||||
$filename = './data/Reader/XLSX/conditionalFormattingTest.xlsx';
|
||||
$reader = new Xlsx();
|
||||
$spreadsheet = $reader->load($filename);
|
||||
|
||||
$worksheet = $spreadsheet->getActiveSheet();
|
||||
|
||||
$conditionalStyle = $worksheet->getCell('B2')->getStyle()->getConditionalStyles();
|
||||
|
||||
$this->assertNotEmpty($conditionalStyle);
|
||||
$conditionalRule = $conditionalStyle[0];
|
||||
$this->assertNotEmpty($conditionalRule->getConditions());
|
||||
$this->assertEquals(Conditional::CONDITION_CELLIS, $conditionalRule->getConditionType());
|
||||
$this->assertEquals(Conditional::OPERATOR_BETWEEN, $conditionalRule->getOperatorType());
|
||||
$this->assertEquals(['200', '400'], $conditionalRule->getConditions());
|
||||
$this->assertInstanceOf(Style::class, $conditionalRule->getStyle());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test load Xlsx file without cell reference.
|
||||
*
|
||||
* @doesNotPerformAssertions
|
||||
*/
|
||||
public function testLoadXlsxWithoutCellReference()
|
||||
{
|
||||
@ -61,6 +188,8 @@ class XlsxTest extends TestCase
|
||||
|
||||
/**
|
||||
* Test load Xlsx file with drawing having double attributes.
|
||||
*
|
||||
* @doesNotPerformAssertions
|
||||
*/
|
||||
public function testLoadXlsxWithDoubleAttrDrawing()
|
||||
{
|
||||
|
BIN
tests/data/Reader/Ods/propertyTest.ods
Normal file
BIN
tests/data/Reader/Ods/propertyTest.ods
Normal file
Binary file not shown.
BIN
tests/data/Reader/XLSX/autofilterTest.xlsx
Normal file
BIN
tests/data/Reader/XLSX/autofilterTest.xlsx
Normal file
Binary file not shown.
BIN
tests/data/Reader/XLSX/conditionalFormattingTest.xlsx
Normal file
BIN
tests/data/Reader/XLSX/conditionalFormattingTest.xlsx
Normal file
Binary file not shown.
BIN
tests/data/Reader/XLSX/pageSetupTest.xlsx
Normal file
BIN
tests/data/Reader/XLSX/pageSetupTest.xlsx
Normal file
Binary file not shown.
Binary file not shown.
BIN
tests/data/Reader/XLSX/rowColumnAttributeTest.xlsx
Normal file
BIN
tests/data/Reader/XLSX/rowColumnAttributeTest.xlsx
Normal file
Binary file not shown.
BIN
tests/data/Reader/XLSX/stylesTest.xlsx
Normal file
BIN
tests/data/Reader/XLSX/stylesTest.xlsx
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user