提交的内容

This commit is contained in:
2025-05-12 15:45:02 +08:00
parent 629c4750da
commit b48c692775
3043 changed files with 34732 additions and 60810 deletions

View File

@ -0,0 +1,177 @@
<?php
namespace PhpOffice\PhpSpreadsheet\Reader\Xml;
use PhpOffice\PhpSpreadsheet\Cell\AddressHelper;
use PhpOffice\PhpSpreadsheet\Cell\AddressRange;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Cell\DataValidation;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use SimpleXMLElement;
class DataValidations
{
private const OPERATOR_MAPPINGS = [
'between' => DataValidation::OPERATOR_BETWEEN,
'equal' => DataValidation::OPERATOR_EQUAL,
'greater' => DataValidation::OPERATOR_GREATERTHAN,
'greaterorequal' => DataValidation::OPERATOR_GREATERTHANOREQUAL,
'less' => DataValidation::OPERATOR_LESSTHAN,
'lessorequal' => DataValidation::OPERATOR_LESSTHANOREQUAL,
'notbetween' => DataValidation::OPERATOR_NOTBETWEEN,
'notequal' => DataValidation::OPERATOR_NOTEQUAL,
];
private const TYPE_MAPPINGS = [
'textlength' => DataValidation::TYPE_TEXTLENGTH,
];
private int $thisRow = 0;
private int $thisColumn = 0;
private function replaceR1C1(array $matches): string
{
return AddressHelper::convertToA1($matches[0], $this->thisRow, $this->thisColumn, false);
}
public function loadDataValidations(SimpleXMLElement $worksheet, Spreadsheet $spreadsheet): void
{
$xmlX = $worksheet->children(Namespaces::URN_EXCEL);
$sheet = $spreadsheet->getActiveSheet();
/** @var callable */
$pregCallback = [$this, 'replaceR1C1'];
foreach ($xmlX->DataValidation as $dataValidation) {
$cells = [];
$validation = new DataValidation();
// set defaults
$validation->setShowDropDown(true);
$validation->setShowInputMessage(true);
$validation->setShowErrorMessage(true);
$validation->setShowDropDown(true);
$this->thisRow = 1;
$this->thisColumn = 1;
foreach ($dataValidation as $tagName => $tagValue) {
$tagValue = (string) $tagValue;
$tagValueLower = strtolower($tagValue);
switch ($tagName) {
case 'Range':
foreach (explode(',', $tagValue) as $range) {
$cell = '';
if (preg_match('/^R(\d+)C(\d+):R(\d+)C(\d+)$/', (string) $range, $selectionMatches) === 1) {
// range
$firstCell = Coordinate::stringFromColumnIndex((int) $selectionMatches[2])
. $selectionMatches[1];
$cell = $firstCell
. ':'
. Coordinate::stringFromColumnIndex((int) $selectionMatches[4])
. $selectionMatches[3];
$this->thisRow = (int) $selectionMatches[1];
$this->thisColumn = (int) $selectionMatches[2];
$sheet->getCell($firstCell);
} elseif (preg_match('/^R(\d+)C(\d+)$/', (string) $range, $selectionMatches) === 1) {
// cell
$cell = Coordinate::stringFromColumnIndex((int) $selectionMatches[2])
. $selectionMatches[1];
$sheet->getCell($cell);
$this->thisRow = (int) $selectionMatches[1];
$this->thisColumn = (int) $selectionMatches[2];
} elseif (preg_match('/^C(\d+)$/', (string) $range, $selectionMatches) === 1) {
// column
$firstCell = Coordinate::stringFromColumnIndex((int) $selectionMatches[1])
. '1';
$cell = $firstCell
. ':'
. Coordinate::stringFromColumnIndex((int) $selectionMatches[1])
. ((string) AddressRange::MAX_ROW);
$this->thisColumn = (int) $selectionMatches[1];
$sheet->getCell($firstCell);
} elseif (preg_match('/^R(\d+)$/', (string) $range, $selectionMatches)) {
// row
$firstCell = 'A'
. $selectionMatches[1];
$cell = $firstCell
. ':'
. AddressRange::MAX_COLUMN
. $selectionMatches[1];
$this->thisRow = (int) $selectionMatches[1];
$sheet->getCell($firstCell);
}
$validation->setSqref($cell);
$stRange = $sheet->shrinkRangeToFit($cell);
$cells = array_merge($cells, Coordinate::extractAllCellReferencesInRange($stRange));
}
break;
case 'Type':
$validation->setType(self::TYPE_MAPPINGS[$tagValueLower] ?? $tagValueLower);
break;
case 'Qualifier':
$validation->setOperator(self::OPERATOR_MAPPINGS[$tagValueLower] ?? $tagValueLower);
break;
case 'InputTitle':
$validation->setPromptTitle($tagValue);
break;
case 'InputMessage':
$validation->setPrompt($tagValue);
break;
case 'InputHide':
$validation->setShowInputMessage(false);
break;
case 'ErrorStyle':
$validation->setErrorStyle($tagValueLower);
break;
case 'ErrorTitle':
$validation->setErrorTitle($tagValue);
break;
case 'ErrorMessage':
$validation->setError($tagValue);
break;
case 'ErrorHide':
$validation->setShowErrorMessage(false);
break;
case 'ComboHide':
$validation->setShowDropDown(false);
break;
case 'UseBlank':
$validation->setAllowBlank(true);
break;
case 'CellRangeList':
// FIXME missing FIXME
break;
case 'Min':
case 'Value':
$tagValue = (string) preg_replace_callback(AddressHelper::R1C1_COORDINATE_REGEX, $pregCallback, $tagValue);
$validation->setFormula1($tagValue);
break;
case 'Max':
$tagValue = (string) preg_replace_callback(AddressHelper::R1C1_COORDINATE_REGEX, $pregCallback, $tagValue);
$validation->setFormula2($tagValue);
break;
}
}
foreach ($cells as $cell) {
$sheet->getCell($cell)->setDataValidation(clone $validation);
}
}
}
}

View File

@ -2,6 +2,7 @@
namespace PhpOffice\PhpSpreadsheet\Reader\Xml;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup;
use SimpleXMLElement;
@ -14,9 +15,9 @@ class PageSettings
*/
private $printSettings;
public function __construct(SimpleXMLElement $xmlX, array $namespaces)
public function __construct(SimpleXMLElement $xmlX)
{
$printSettings = $this->pageSetup($xmlX, $namespaces, $this->getPrintDefaults());
$printSettings = $this->pageSetup($xmlX, $this->getPrintDefaults());
$this->printSettings = $this->printSetup($xmlX, $printSettings);
}
@ -56,13 +57,13 @@ class PageSettings
];
}
private function pageSetup(SimpleXMLElement $xmlX, array $namespaces, stdClass $printDefaults): stdClass
private function pageSetup(SimpleXMLElement $xmlX, stdClass $printDefaults): stdClass
{
if (isset($xmlX->WorksheetOptions->PageSetup)) {
foreach ($xmlX->WorksheetOptions->PageSetup as $pageSetupData) {
foreach ($pageSetupData as $pageSetupKey => $pageSetupValue) {
/** @scrutinizer ignore-call */
$pageSetupAttributes = $pageSetupValue->attributes($namespaces['x']);
$pageSetupAttributes = $pageSetupValue->attributes(Namespaces::URN_EXCEL);
if ($pageSetupAttributes !== null) {
switch ($pageSetupKey) {
case 'Layout':

View File

@ -92,6 +92,10 @@ class Properties
case 'Manager':
$docProps->setManager($stringValue);
break;
case 'HyperlinkBase':
$docProps->setHyperlinkBase($stringValue);
break;
case 'Keywords':
$docProps->setKeywords($stringValue);
@ -110,17 +114,10 @@ class Properties
?SimpleXMLElement $propertyValue,
SimpleXMLElement $propertyAttributes
): void {
$propertyType = DocumentProperties::PROPERTY_TYPE_UNKNOWN;
switch ((string) $propertyAttributes) {
case 'string':
$propertyType = DocumentProperties::PROPERTY_TYPE_STRING;
$propertyValue = trim((string) $propertyValue);
break;
case 'boolean':
$propertyType = DocumentProperties::PROPERTY_TYPE_BOOLEAN;
$propertyValue = (bool) $propertyValue;
$propertyValue = (bool) (string) $propertyValue;
break;
case 'integer':
@ -134,9 +131,15 @@ class Properties
break;
case 'dateTime.tz':
case 'dateTime.iso8601tz':
$propertyType = DocumentProperties::PROPERTY_TYPE_DATE;
$propertyValue = trim((string) $propertyValue);
break;
default:
$propertyType = DocumentProperties::PROPERTY_TYPE_STRING;
$propertyValue = trim((string) $propertyValue);
break;
}

View File

@ -2,6 +2,7 @@
namespace PhpOffice\PhpSpreadsheet\Reader\Xml;
use PhpOffice\PhpSpreadsheet\Style\Protection;
use SimpleXMLElement;
class Style
@ -30,7 +31,7 @@ class Style
$styleID = (string) $style_ss['ID'];
$this->styles[$styleID] = $this->styles['Default'] ?? [];
$alignment = $border = $font = $fill = $numberFormat = [];
$alignment = $border = $font = $fill = $numberFormat = $protection = [];
foreach ($style as $styleType => $styleDatax) {
$styleData = self::getSxml($styleDatax);
@ -64,11 +65,31 @@ class Style
$numberFormat = $numberFormatStyleParser->parseStyle($styleAttributes);
}
break;
case 'Protection':
$locked = $hidden = null;
$styleAttributesP = $styleData->attributes($namespaces['x']);
if (isset($styleAttributes['Protected'])) {
$locked = ((bool) (string) $styleAttributes['Protected']) ? Protection::PROTECTION_PROTECTED : Protection::PROTECTION_UNPROTECTED;
}
if (isset($styleAttributesP['HideFormula'])) {
$hidden = ((bool) (string) $styleAttributesP['HideFormula']) ? Protection::PROTECTION_PROTECTED : Protection::PROTECTION_UNPROTECTED;
}
if ($locked !== null || $hidden !== null) {
$protection['protection'] = [];
if ($locked !== null) {
$protection['protection']['locked'] = $locked;
}
if ($hidden !== null) {
$protection['protection']['hidden'] = $hidden;
}
}
break;
}
}
$this->styles[$styleID] = array_merge($alignment, $border, $font, $fill, $numberFormat);
$this->styles[$styleID] = array_merge($alignment, $border, $font, $fill, $numberFormat, $protection);
}
return $this->styles;

View File

View File

View File

View File

@ -56,11 +56,11 @@ class Font extends StyleBase
break;
case 'Bold':
$style['font']['bold'] = true;
$style['font']['bold'] = $styleAttributeValue === '1';
break;
case 'Italic':
$style['font']['italic'] = true;
$style['font']['italic'] = $styleAttributeValue === '1';
break;
case 'Underline':

View File

View File