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": {
|
"require": {
|
||||||
"php": "5.6|^7.0",
|
"php": "^5.6|^7.0",
|
||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
"ext-dom": "*",
|
"ext-dom": "*",
|
||||||
"ext-gd": "*",
|
"ext-gd": "*",
|
||||||
|
|
|
@ -418,7 +418,7 @@ class Properties
|
||||||
*
|
*
|
||||||
* @param string $propertyName
|
* @param string $propertyName
|
||||||
*
|
*
|
||||||
* @return string
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function getCustomPropertyValue($propertyName)
|
public function getCustomPropertyValue($propertyName)
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,7 +7,7 @@ use DateTimeZone;
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
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\Reader\Security\XmlScanner;
|
||||||
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
||||||
use PhpOffice\PhpSpreadsheet\Settings;
|
use PhpOffice\PhpSpreadsheet\Settings;
|
||||||
|
@ -265,7 +265,7 @@ class Ods extends BaseReader
|
||||||
|
|
||||||
$zip = new ZipArchive();
|
$zip = new ZipArchive();
|
||||||
if (!$zip->open($pFilename)) {
|
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
|
// Meta
|
||||||
|
@ -275,97 +275,13 @@ class Ods extends BaseReader
|
||||||
'SimpleXMLElement',
|
'SimpleXMLElement',
|
||||||
Settings::getLibXmlLoaderOptions()
|
Settings::getLibXmlLoaderOptions()
|
||||||
);
|
);
|
||||||
|
if ($xml === false) {
|
||||||
|
throw new Exception('Unable to read data from {$pFilename}');
|
||||||
|
}
|
||||||
|
|
||||||
$namespacesMeta = $xml->getNamespaces(true);
|
$namespacesMeta = $xml->getNamespaces(true);
|
||||||
|
|
||||||
$docProps = $spreadsheet->getProperties();
|
(new DocumentProperties($spreadsheet))->load($xml, $namespacesMeta);
|
||||||
$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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Content
|
// Content
|
||||||
|
|
||||||
|
|
|
@ -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\Coordinate;
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\Hyperlink;
|
use PhpOffice\PhpSpreadsheet\Cell\Hyperlink;
|
||||||
use PhpOffice\PhpSpreadsheet\Document\Properties;
|
|
||||||
use PhpOffice\PhpSpreadsheet\NamedRange;
|
use PhpOffice\PhpSpreadsheet\NamedRange;
|
||||||
use PhpOffice\PhpSpreadsheet\Reader\Security\XmlScanner;
|
use PhpOffice\PhpSpreadsheet\Reader\Security\XmlScanner;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\AutoFilter;
|
||||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Chart;
|
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\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\ReferenceHelper;
|
||||||
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
||||||
use PhpOffice\PhpSpreadsheet\Settings;
|
use PhpOffice\PhpSpreadsheet\Settings;
|
||||||
|
@ -21,7 +29,6 @@ use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Border;
|
use PhpOffice\PhpSpreadsheet\Style\Border;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Borders;
|
use PhpOffice\PhpSpreadsheet\Style\Borders;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Color;
|
use PhpOffice\PhpSpreadsheet\Style\Color;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Conditional;
|
|
||||||
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Protection;
|
use PhpOffice\PhpSpreadsheet\Style\Protection;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Style;
|
use PhpOffice\PhpSpreadsheet\Style\Style;
|
||||||
|
@ -324,60 +331,6 @@ class Xlsx extends BaseReader
|
||||||
return $contents;
|
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.
|
* 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']"));
|
$xpath = self::getArrayItem($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles']"));
|
||||||
//~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
|
//~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
|
||||||
$xmlStyles = simplexml_load_string(
|
$xmlStyles = simplexml_load_string(
|
||||||
|
@ -546,6 +498,9 @@ class Xlsx extends BaseReader
|
||||||
'SimpleXMLElement',
|
'SimpleXMLElement',
|
||||||
Settings::getLibXmlLoaderOptions()
|
Settings::getLibXmlLoaderOptions()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$styles = [];
|
||||||
|
$cellStyles = [];
|
||||||
$numFmts = null;
|
$numFmts = null;
|
||||||
if ($xmlStyles && $xmlStyles->numFmts[0]) {
|
if ($xmlStyles && $xmlStyles->numFmts[0]) {
|
||||||
$numFmts = $xmlStyles->numFmts[0];
|
$numFmts = $xmlStyles->numFmts[0];
|
||||||
|
@ -625,31 +580,10 @@ class Xlsx extends BaseReader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$dxfs = [];
|
$styleReader = new Styles($xmlStyles);
|
||||||
if (!$this->readDataOnly && $xmlStyles) {
|
$styleReader->setStyleBaseData(self::$theme, $styles, $cellStyles);
|
||||||
// Conditional Styles
|
$dxfs = $styleReader->dxfs($this->readDataOnly);
|
||||||
if ($xmlStyles->dxfs) {
|
$styles = $styleReader->styles();
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
|
//~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
|
||||||
$xmlWorkbook = simplexml_load_string(
|
$xmlWorkbook = simplexml_load_string(
|
||||||
|
@ -716,134 +650,19 @@ class Xlsx extends BaseReader
|
||||||
$docSheet->setSheetState((string) $eleSheet['state']);
|
$docSheet->setSheetState((string) $eleSheet['state']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($xmlSheet->sheetViews, $xmlSheet->sheetViews->sheetView)) {
|
if ($xmlSheet) {
|
||||||
if (isset($xmlSheet->sheetViews->sheetView['zoomScale'])) {
|
if (isset($xmlSheet->sheetViews, $xmlSheet->sheetViews->sheetView)) {
|
||||||
$zoomScale = (int) ($xmlSheet->sheetViews->sheetView['zoomScale']);
|
$sheetViews = new SheetViews($xmlSheet->sheetViews->sheetView, $docSheet);
|
||||||
if ($zoomScale <= 0) {
|
$sheetViews->load();
|
||||||
// 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 (isset($xmlSheet->sheetViews->sheetView->selection)) {
|
$sheetViewOptions = new SheetViewOptions($docSheet, $xmlSheet);
|
||||||
if (isset($xmlSheet->sheetViews->sheetView->selection['sqref'])) {
|
$sheetViewOptions->load($this->getReadDataOnly());
|
||||||
$sqref = (string) $xmlSheet->sheetViews->sheetView->selection['sqref'];
|
|
||||||
$sqref = explode(' ', $sqref);
|
(new ColumnAndRowAttributes($docSheet, $xmlSheet))
|
||||||
$sqref = $sqref[0];
|
->load($this->getReadFilter(), $this->getReadDataOnly());
|
||||||
$docSheet->setSelectedCells($sqref);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
if ($xmlSheet && $xmlSheet->sheetData && $xmlSheet->sheetData->row) {
|
||||||
$cIndex = 1; // Cell Start from 1
|
$cIndex = 1; // Cell Start from 1
|
||||||
foreach ($xmlSheet->sheetData->row as $row) {
|
foreach ($xmlSheet->sheetData->row as $row) {
|
||||||
|
@ -963,49 +782,8 @@ class Xlsx extends BaseReader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$conditionals = [];
|
|
||||||
if (!$this->readDataOnly && $xmlSheet && $xmlSheet->conditionalFormatting) {
|
if (!$this->readDataOnly && $xmlSheet && $xmlSheet->conditionalFormatting) {
|
||||||
foreach ($xmlSheet->conditionalFormatting as $conditional) {
|
(new ConditionalStyles($docSheet, $xmlSheet, $dxfs))->load();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$aKeys = ['sheet', 'objects', 'scenarios', 'formatCells', 'formatColumns', 'formatRows', 'insertColumns', 'insertRows', 'insertHyperlinks', 'deleteColumns', 'deleteRows', 'selectLockedCells', 'sort', 'autoFilter', 'pivotTables', 'selectUnlockedCells'];
|
$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) {
|
if ($xmlSheet && $xmlSheet->autoFilter && !$this->readDataOnly) {
|
||||||
$autoFilterRange = (string) $xmlSheet->autoFilter['ref'];
|
(new AutoFilter($docSheet, $xmlSheet))->load();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($xmlSheet && $xmlSheet->mergeCells && $xmlSheet->mergeCells->mergeCell && !$this->readDataOnly) {
|
if ($xmlSheet && $xmlSheet->mergeCells && $xmlSheet->mergeCells->mergeCell && !$this->readDataOnly) {
|
||||||
|
@ -1134,124 +816,12 @@ class Xlsx extends BaseReader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($xmlSheet && $xmlSheet->pageMargins && !$this->readDataOnly) {
|
if ($xmlSheet && !$this->readDataOnly) {
|
||||||
$docPageMargins = $docSheet->getPageMargins();
|
$unparsedLoadedData = (new PageSetup($docSheet, $xmlSheet))->load($unparsedLoadedData);
|
||||||
$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 && $xmlSheet->dataValidations && !$this->readDataOnly) {
|
if ($xmlSheet && $xmlSheet->dataValidations && !$this->readDataOnly) {
|
||||||
foreach ($xmlSheet->dataValidations->dataValidation as $dataValidation) {
|
(new DataValidations($docSheet, $xmlSheet))->load();
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// unparsed sheet AlternateContent
|
// unparsed sheet AlternateContent
|
||||||
|
@ -1265,50 +835,25 @@ class Xlsx extends BaseReader
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add hyperlinks
|
// Add hyperlinks
|
||||||
$hyperlinks = [];
|
|
||||||
if (!$this->readDataOnly) {
|
if (!$this->readDataOnly) {
|
||||||
|
$hyperlinkReader = new Hyperlinks($docSheet);
|
||||||
// Locate hyperlink relations
|
// 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"
|
//~ http://schemas.openxmlformats.org/package/2006/relationships"
|
||||||
$relsWorksheet = simplexml_load_string(
|
$relsWorksheet = simplexml_load_string(
|
||||||
$this->securityScanner->scan(
|
$this->securityScanner->scan(
|
||||||
$this->getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels')
|
$this->getFromZipArchive($zip, $relationsFileName)
|
||||||
),
|
),
|
||||||
'SimpleXMLElement',
|
'SimpleXMLElement',
|
||||||
Settings::getLibXmlLoaderOptions()
|
Settings::getLibXmlLoaderOptions()
|
||||||
);
|
);
|
||||||
foreach ($relsWorksheet->Relationship as $ele) {
|
$hyperlinkReader->readHyperlinks($relsWorksheet);
|
||||||
if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink') {
|
|
||||||
$hyperlinks[(string) $ele['Id']] = (string) $ele['Target'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop through hyperlinks
|
// Loop through hyperlinks
|
||||||
if ($xmlSheet && $xmlSheet->hyperlinks) {
|
if ($xmlSheet && $xmlSheet->hyperlinks) {
|
||||||
/** @var SimpleXMLElement $hyperlink */
|
$hyperlinkReader->setHyperlinks($xmlSheet->hyperlinks);
|
||||||
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']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2482,94 +2027,4 @@ class Xlsx extends BaseReader
|
||||||
|
|
||||||
return (bool) $xsdBoolean;
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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');
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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) {
|
if (version_compare(PHP_VERSION, '7.2.99') >= 0) {
|
||||||
$skipped[] = 'Basic/26_Utf8.php';
|
$skipped[] = 'Basic/26_Utf8.php';
|
||||||
$skipped[] = 'Pdf/21_Pdf_Domdf.php';
|
$skipped[] = 'Pdf/21_Pdf_Domdf.php';
|
||||||
|
$skipped[] = 'Pdf/21_Pdf_mPDF.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unfortunately some tests are too long be ran with code-coverage
|
// Unfortunately some tests are too long be ran with code-coverage
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Reader;
|
namespace PhpOffice\PhpSpreadsheetTests\Reader;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Document\Properties;
|
||||||
use PhpOffice\PhpSpreadsheet\Reader\Ods;
|
use PhpOffice\PhpSpreadsheet\Reader\Ods;
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Font;
|
use PhpOffice\PhpSpreadsheet\Style\Font;
|
||||||
|
@ -222,4 +223,46 @@ class OdsTest extends TestCase
|
||||||
self::assertTrue($style->getFont()->getBold());
|
self::assertTrue($style->getFont()->getBold());
|
||||||
self::assertTrue($style->getFont()->getItalic());
|
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;
|
namespace PhpOffice\PhpSpreadsheetTests\Reader;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||||
use PhpOffice\PhpSpreadsheet\Document\Properties;
|
use PhpOffice\PhpSpreadsheet\Document\Properties;
|
||||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||||
use PhpOffice\PhpSpreadsheet\Shared\File;
|
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;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
class XlsxTest extends 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';
|
$filename = './data/Reader/XLSX/propertyTest.xlsx';
|
||||||
$reader = new Xlsx();
|
$reader = new Xlsx();
|
||||||
$spreadsheet = $reader->load($filename);
|
$spreadsheet = $reader->load($filename);
|
||||||
|
|
||||||
$properties = $spreadsheet->getProperties();
|
$properties = $spreadsheet->getProperties();
|
||||||
// Core Properties
|
// Core Properties
|
||||||
$this->assertEquals('Mark Baker', $properties->getCreator());
|
$this->assertSame('Mark Baker', $properties->getCreator());
|
||||||
$this->assertEquals('Unit Testing', $properties->getTitle());
|
$this->assertSame('Unit Testing', $properties->getTitle());
|
||||||
$this->assertEquals('Property Test', $properties->getSubject());
|
$this->assertSame('Property Test', $properties->getSubject());
|
||||||
|
|
||||||
// Extended Properties
|
// Extended Properties
|
||||||
$this->assertEquals('PHPOffice', $properties->getCompany());
|
$this->assertSame('PHPOffice', $properties->getCompany());
|
||||||
$this->assertEquals('The Big Boss', $properties->getManager());
|
$this->assertSame('The Big Boss', $properties->getManager());
|
||||||
|
|
||||||
// Custom Properties
|
// Custom Properties
|
||||||
$customProperties = $properties->getCustomProperties();
|
$customProperties = $properties->getCustomProperties();
|
||||||
$this->assertInternalType('array', $customProperties);
|
$this->assertInternalType('array', $customProperties);
|
||||||
$customProperties = array_flip($customProperties);
|
$customProperties = array_flip($customProperties);
|
||||||
$this->assertArrayHasKey('Publisher', $customProperties);
|
$this->assertArrayHasKey('Publisher', $customProperties);
|
||||||
$this->assertTrue($properties->isCustomPropertySet('Publisher'));
|
|
||||||
$this->assertEquals(Properties::PROPERTY_TYPE_STRING, $properties->getCustomPropertyType('Publisher'));
|
foreach ($customPropertySet as $propertyName => $testData) {
|
||||||
$this->assertEquals('PHPOffice Suite', $properties->getCustomPropertyValue('Publisher'));
|
$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.
|
* Test load Xlsx file without cell reference.
|
||||||
|
*
|
||||||
|
* @doesNotPerformAssertions
|
||||||
*/
|
*/
|
||||||
public function testLoadXlsxWithoutCellReference()
|
public function testLoadXlsxWithoutCellReference()
|
||||||
{
|
{
|
||||||
|
@ -61,6 +188,8 @@ class XlsxTest extends TestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test load Xlsx file with drawing having double attributes.
|
* Test load Xlsx file with drawing having double attributes.
|
||||||
|
*
|
||||||
|
* @doesNotPerformAssertions
|
||||||
*/
|
*/
|
||||||
public function testLoadXlsxWithDoubleAttrDrawing()
|
public function testLoadXlsxWithDoubleAttrDrawing()
|
||||||
{
|
{
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue