Xlsx Reader Better Namespace Handling Phase 1 Try2 (#2173)
* Xlsx Reader Better Namespace Handling Phase 1 Try2 This is a replacement for #2088, which has run into merge conflicts. I will close that PR in the near future, however the comments in that PR may prove useful for this one. While that PR has been in draft status all along, I am marking this one as ready. I will gladly add additional tests (and, of course, make code changes) that anyone has to suggest, but, with my most recent test files which I will describe in a separate comment, I have no further ideas on useful additions. As mentioned in the earlier ticket, this is a risky change. But, as has been demonstrated, delaying it comes with its own set of risks. It would be helpful to have a temporary moratorium on changes to Reader/Xlsx until this change is merged. The original commit message follows. There have been a number of issues concerning the handling of legitimate but unexpected namespace prefixes in Xlsx spreadsheets created by software other than Excel and PhpSpreadsheet/PhpExcel.I have studied them, but, till now, have not had a good idea on how to act on them. A recent comment https://github.com/PHPOffice/PhpSpreadsheet/issues/860#issuecomment-824926224 in issue #860 by @IMSoP has triggered an idea about how to proceed. Gnumeric Reader was recently changed to handle namespaces better. Using that as a model, this PR begins the process of doing the same for Xlsx. Xlsx is much larger and more complicated than Gnumeric, hence the need to tackle it in multiple phases. I believe that this PR handles all of: - listWorkSheetNames - listWorkSheetInfo. Note that there was a bug in this function which would cause it to count only used columns rather than all columns. That bug is corrected. - active sheet - selected cell and top left cell - cell content (formulas, numbers, text) - hyperlinks - comments (partial - see below) This PR does not address: - styles - images and charts - VBA and ribbons - many other items, I'm sure The issue for non-standard namespacing till now has been the use of unexpected prefixes. While I was working on this change, @Lambik introduced issue #2067 PR #2068 which introduced a completely different problem - the use of unexpected URLs. That PR and the issue associated with it were quite well documented, including the supplying of a test file and tests for it. I asked if I could take a look to see if it could be integrated with my change, and the result seems to be yes, so those changes are also part of this PR. While adding a comment to my test file, I discovered that Microsoft had added "threaded comments" as a new feature. I believe these are not yet supported by PhpSpreadsheet, and I am not going to add it, at least not now. I believe that, among other things, this will make identifying the author of a comment more difficult. Although there are a number of Phpstan baseline changes as part of this PR, I did not attempt to resolve all Phpstan reports for Reader/Xlsx. Nor did I do anything to increase coverage. This change is already large and complex enough without those efforts.
This commit is contained in:
parent
034ac5a7c7
commit
cd84020693
|
|
@ -2925,21 +2925,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Reader/Xls/RC4.php
|
path: src/PhpSpreadsheet/Reader/Xls/RC4.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot access property \\$Relationship on SimpleXMLElement\\|false\\.$#"
|
|
||||||
count: 12
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot access property \\$sheets on SimpleXMLElement\\|false\\.$#"
|
|
||||||
count: 6
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot call method registerXPathNamespace\\(\\) on SimpleXMLElement\\|false\\.$#"
|
|
||||||
count: 4
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\:\\:castToBoolean\\(\\) has no return typehint specified\\.$#"
|
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\:\\:castToBoolean\\(\\) has no return typehint specified\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
@ -3010,86 +2995,16 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Offset 'name' does not exist on SimpleXMLElement\\|null\\.$#"
|
|
||||||
count: 2
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot call method xpath\\(\\) on SimpleXMLElement\\|false\\.$#"
|
|
||||||
count: 4
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Parameter \\#1 \\$is of method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\:\\:parseRichText\\(\\) expects SimpleXMLElement\\|null, object given\\.$#"
|
message: "#^Parameter \\#1 \\$is of method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\:\\:parseRichText\\(\\) expects SimpleXMLElement\\|null, object given\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Parameter \\#1 \\$styleXml of class PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Styles constructor expects SimpleXMLElement, SimpleXMLElement\\|false given\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot access property \\$workbookPr on SimpleXMLElement\\|false\\.$#"
|
|
||||||
count: 2
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Parameter \\#2 \\$xmlWorkbook of method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\:\\:readProtection\\(\\) expects SimpleXMLElement, SimpleXMLElement\\|false given\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Parameter \\#1 \\$relsWorksheet of method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Hyperlinks\\:\\:readHyperlinks\\(\\) expects SimpleXMLElement, SimpleXMLElement\\|false given\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot access property \\$authors on SimpleXMLElement\\|false\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot access property \\$commentList on SimpleXMLElement\\|false\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Argument of an invalid type array\\<SimpleXMLElement\\>\\|false supplied for foreach, only iterables are supported\\.$#"
|
|
||||||
count: 2
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Negated boolean expression is always true\\.$#"
|
message: "#^Negated boolean expression is always true\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot access property \\$drawing on SimpleXMLElement\\|false\\.$#"
|
|
||||||
count: 2
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot call method children\\(\\) on SimpleXMLElement\\|false\\.$#"
|
|
||||||
count: 2
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot call method count\\(\\) on SimpleXMLElement\\|false\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot call method asXML\\(\\) on SimpleXMLElement\\|false\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot access property \\$definedNames on SimpleXMLElement\\|false\\.$#"
|
|
||||||
count: 4
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Argument of an invalid type array\\<int, string\\>\\|false supplied for foreach, only iterables are supported\\.$#"
|
message: "#^Argument of an invalid type array\\<int, string\\>\\|false supplied for foreach, only iterables are supported\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
@ -3105,26 +3020,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot access property \\$bookViews on SimpleXMLElement\\|false\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot access property \\$Default on SimpleXMLElement\\|false\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot access property \\$Override on SimpleXMLElement\\|false\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Parameter \\#1 \\$chartElements of static method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:readChart\\(\\) expects SimpleXMLElement, SimpleXMLElement\\|false given\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Cannot call method addChart\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\|null\\.$#"
|
message: "#^Cannot call method addChart\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\|null\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
@ -3265,11 +3160,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Offset 'id' does not exist on SimpleXMLElement\\|null\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\:\\:readFormControlProperties\\(\\) has parameter \\$dir with no typehint specified\\.$#"
|
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\:\\:readFormControlProperties\\(\\) has parameter \\$dir with no typehint specified\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
@ -3700,66 +3590,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/PageSetup.php
|
path: src/PhpSpreadsheet/Reader/Xlsx/PageSetup.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Properties\\:\\:\\$securityScanner has no typehint specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Properties.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Properties\\:\\:\\$docProps has no typehint specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Properties.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Properties\\:\\:extractPropertyData\\(\\) has no return typehint specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Properties.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Properties\\:\\:extractPropertyData\\(\\) has parameter \\$propertyData with no typehint specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Properties.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Properties\\:\\:readCoreProperties\\(\\) has parameter \\$propertyData with no typehint specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Properties.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Call to an undefined method object\\:\\:registerXPathNamespace\\(\\)\\.$#"
|
|
||||||
count: 3
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Properties.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Call to an undefined method object\\:\\:xpath\\(\\)\\.$#"
|
|
||||||
count: 9
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Properties.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Properties\\:\\:readExtendedProperties\\(\\) has parameter \\$propertyData with no typehint specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Properties.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Properties\\:\\:readCustomProperties\\(\\) has parameter \\$propertyData with no typehint specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Properties.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Argument of an invalid type object supplied for foreach, only iterables are supported\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Properties.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Properties\\:\\:getArrayItem\\(\\) has no return typehint specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Properties.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Properties\\:\\:getArrayItem\\(\\) has parameter \\$key with no typehint specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Properties.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\SheetViewOptions\\:\\:\\$worksheet has no typehint specified\\.$#"
|
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\SheetViewOptions\\:\\:\\$worksheet has no typehint specified\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
@ -3770,16 +3600,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/SheetViewOptions.php
|
path: src/PhpSpreadsheet/Reader/Xlsx/SheetViewOptions.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\SheetViews\\:\\:\\$sheetViewXml has no typehint specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/SheetViews.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\SheetViews\\:\\:\\$worksheet has no typehint specified\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/SheetViews.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Styles\\:\\:\\$styles has no typehint specified\\.$#"
|
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Styles\\:\\:\\$styles has no typehint specified\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
@ -3810,11 +3630,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Styles.php
|
path: src/PhpSpreadsheet/Reader/Xlsx/Styles.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Cannot call method count\\(\\) on SimpleXMLElement\\|null\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Reader/Xlsx/Styles.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Styles\\:\\:readStyle\\(\\) has parameter \\$style with no typehint specified\\.$#"
|
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Styles\\:\\:readStyle\\(\\) has parameter \\$style with no typehint specified\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
@ -3925,11 +3740,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/ReferenceHelper.php
|
path: src/PhpSpreadsheet/ReferenceHelper.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Parameter \\#1 \\$pCellRange of method PhpOffice\\\\PhpSpreadsheet\\\\ReferenceHelper\\:\\:updateCellReference\\(\\) expects string, string\\|null given\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/ReferenceHelper.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Parameter \\#3 \\$subject of function str_replace expects array\\|string, string\\|null given\\.$#"
|
message: "#^Parameter \\#3 \\$subject of function str_replace expects array\\|string, string\\|null given\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
@ -5485,11 +5295,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Worksheet/Worksheet.php
|
path: src/PhpSpreadsheet/Worksheet/Worksheet.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\:\\:getFreezePane\\(\\) should return string but returns string\\|null\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/PhpSpreadsheet/Worksheet/Worksheet.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Parameter \\#1 \\$row of method PhpOffice\\\\PhpSpreadsheet\\\\Collection\\\\Cells\\:\\:removeRow\\(\\) expects string, int given\\.$#"
|
message: "#^Parameter \\#1 \\$row of method PhpOffice\\\\PhpSpreadsheet\\\\Collection\\\\Cells\\:\\:removeRow\\(\\) expects string, int given\\.$#"
|
||||||
count: 2
|
count: 2
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -3,6 +3,7 @@
|
||||||
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
use SimpleXMLElement;
|
use SimpleXMLElement;
|
||||||
|
|
||||||
|
|
@ -19,16 +20,17 @@ class Hyperlinks
|
||||||
|
|
||||||
public function readHyperlinks(SimpleXMLElement $relsWorksheet): void
|
public function readHyperlinks(SimpleXMLElement $relsWorksheet): void
|
||||||
{
|
{
|
||||||
foreach ($relsWorksheet->Relationship as $element) {
|
foreach ($relsWorksheet->children(Namespaces::RELATIONSHIPS)->Relationship as $elementx) {
|
||||||
if ($element['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink') {
|
$element = Xlsx::getAttributes($elementx);
|
||||||
$this->hyperlinks[(string) $element['Id']] = (string) $element['Target'];
|
if ($element->Type == Namespaces::HYPERLINK) {
|
||||||
|
$this->hyperlinks[(string) $element->Id] = (string) $element->Target;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setHyperlinks(SimpleXMLElement $worksheetXml): void
|
public function setHyperlinks(SimpleXMLElement $worksheetXml): void
|
||||||
{
|
{
|
||||||
foreach ($worksheetXml->hyperlink as $hyperlink) {
|
foreach ($worksheetXml->children(Namespaces::MAIN)->hyperlink as $hyperlink) {
|
||||||
if ($hyperlink !== null) {
|
if ($hyperlink !== null) {
|
||||||
$this->setHyperlink($hyperlink, $this->worksheet);
|
$this->setHyperlink($hyperlink, $this->worksheet);
|
||||||
}
|
}
|
||||||
|
|
@ -38,9 +40,10 @@ class Hyperlinks
|
||||||
private function setHyperlink(SimpleXMLElement $hyperlink, Worksheet $worksheet): void
|
private function setHyperlink(SimpleXMLElement $hyperlink, Worksheet $worksheet): void
|
||||||
{
|
{
|
||||||
// Link url
|
// Link url
|
||||||
$linkRel = $hyperlink->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships');
|
$linkRel = Xlsx::getAttributes($hyperlink, Namespaces::SCHEMA_OFFICE_DOCUMENT);
|
||||||
|
|
||||||
foreach (Coordinate::extractAllCellReferencesInRange($hyperlink['ref']) as $cellReference) {
|
$attributes = Xlsx::getAttributes($hyperlink);
|
||||||
|
foreach (Coordinate::extractAllCellReferencesInRange($attributes->ref) as $cellReference) {
|
||||||
$cell = $worksheet->getCell($cellReference);
|
$cell = $worksheet->getCell($cellReference);
|
||||||
if (isset($linkRel['id'])) {
|
if (isset($linkRel['id'])) {
|
||||||
$hyperlinkUrl = $this->hyperlinks[(string) $linkRel['id']] ?? null;
|
$hyperlinkUrl = $this->hyperlinks[(string) $linkRel['id']] ?? null;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||||
|
|
||||||
|
class Namespaces
|
||||||
|
{
|
||||||
|
const SCHEMAS = 'http://schemas.openxmlformats.org';
|
||||||
|
|
||||||
|
const RELATIONSHIPS = 'http://schemas.openxmlformats.org/package/2006/relationships';
|
||||||
|
|
||||||
|
// This one used in Reader\Xlsx
|
||||||
|
const CORE_PROPERTIES = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties';
|
||||||
|
|
||||||
|
// This one used in Reader\Xlsx\Properties
|
||||||
|
const CORE_PROPERTIES2 = 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties';
|
||||||
|
|
||||||
|
const THEME = 'http://schemas.openxmlformats.org/package/2006/relationships/theme';
|
||||||
|
|
||||||
|
const COMPATIBILITY = 'http://schemas.openxmlformats.org/markup-compatibility/2006';
|
||||||
|
|
||||||
|
const MAIN = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main';
|
||||||
|
|
||||||
|
const DRAWINGML = 'http://schemas.openxmlformats.org/drawingml/2006/main';
|
||||||
|
|
||||||
|
const CHART = 'http://schemas.openxmlformats.org/drawingml/2006/chart';
|
||||||
|
|
||||||
|
const SPREADSHEET_DRAWING = 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing';
|
||||||
|
|
||||||
|
const SCHEMA_OFFICE_DOCUMENT = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships';
|
||||||
|
|
||||||
|
const COMMENTS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments';
|
||||||
|
|
||||||
|
//const CUSTOM_PROPERTIES = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties';
|
||||||
|
|
||||||
|
//const EXTENDED_PROPERTIES = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties';
|
||||||
|
|
||||||
|
const HYPERLINK = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink';
|
||||||
|
|
||||||
|
const OFFICE_DOCUMENT = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument';
|
||||||
|
|
||||||
|
const SHARED_STRINGS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings';
|
||||||
|
|
||||||
|
const STYLES = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles';
|
||||||
|
|
||||||
|
const IMAGE = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image';
|
||||||
|
|
||||||
|
const VML = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing';
|
||||||
|
|
||||||
|
const WORKSHEET = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet';
|
||||||
|
|
||||||
|
const SCHEMA_MICROSOFT = 'http://schemas.microsoft.com/office/2006/relationships';
|
||||||
|
|
||||||
|
const EXTENSIBILITY = 'http://schemas.microsoft.com/office/2006/relationships/ui/extensibility';
|
||||||
|
|
||||||
|
const VBA = 'http://schemas.microsoft.com/office/2006/relationships/vbaProject';
|
||||||
|
|
||||||
|
const DC_ELEMENTS = 'http://purl.org/dc/elements/1.1/';
|
||||||
|
|
||||||
|
const DC_TERMS = 'http://purl.org/dc/terms';
|
||||||
|
|
||||||
|
const URN_MSOFFICE = 'urn:schemas-microsoft-com:office:office';
|
||||||
|
|
||||||
|
const URN_VML = 'urn:schemas-microsoft-com:vml';
|
||||||
|
|
||||||
|
const SCHEMA_PURL = 'http://purl.oclc.org/ooxml';
|
||||||
|
|
||||||
|
const PURL_OFFICE_DOCUMENT = 'http://purl.oclc.org/ooxml/officeDocument/relationships/officeDocument';
|
||||||
|
|
||||||
|
const PURL_RELATIONSHIPS = 'http://purl.oclc.org/ooxml/officeDocument/relationships';
|
||||||
|
|
||||||
|
const PURL_MAIN = 'http://purl.oclc.org/ooxml/spreadsheetml/main';
|
||||||
|
|
||||||
|
const PURL_DRAWING = 'http://purl.oclc.org/ooxml/drawingml/main';
|
||||||
|
|
||||||
|
const PURL_WORKSHEET = 'http://purl.oclc.org/ooxml/officeDocument/relationships/worksheet';
|
||||||
|
}
|
||||||
|
|
@ -75,7 +75,7 @@ class PageSetup extends BaseParserClass
|
||||||
$docPageSetup->setPageOrder((string) $xmlSheet->pageSetup['pageOrder']);
|
$docPageSetup->setPageOrder((string) $xmlSheet->pageSetup['pageOrder']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$relAttributes = $xmlSheet->pageSetup->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships');
|
$relAttributes = $xmlSheet->pageSetup->attributes(Namespaces::SCHEMA_OFFICE_DOCUMENT);
|
||||||
if (isset($relAttributes['id'])) {
|
if (isset($relAttributes['id'])) {
|
||||||
$unparsedLoadedData['sheets'][$worksheet->getCodeName()]['pageSetupRelId'] = (string) $relAttributes['id'];
|
$unparsedLoadedData['sheets'][$worksheet->getCodeName()]['pageSetupRelId'] = (string) $relAttributes['id'];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,10 @@ use SimpleXMLElement;
|
||||||
|
|
||||||
class Properties
|
class Properties
|
||||||
{
|
{
|
||||||
|
/** @var XmlScanner */
|
||||||
private $securityScanner;
|
private $securityScanner;
|
||||||
|
|
||||||
|
/** @var DocumentProperties */
|
||||||
private $docProps;
|
private $docProps;
|
||||||
|
|
||||||
public function __construct(XmlScanner $securityScanner, DocumentProperties $docProps)
|
public function __construct(XmlScanner $securityScanner, DocumentProperties $docProps)
|
||||||
|
|
@ -19,30 +21,39 @@ class Properties
|
||||||
$this->docProps = $docProps;
|
$this->docProps = $docProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function extractPropertyData($propertyData)
|
/**
|
||||||
|
* @param mixed $obj
|
||||||
|
*/
|
||||||
|
private static function nullOrSimple($obj): ?SimpleXMLElement
|
||||||
{
|
{
|
||||||
return simplexml_load_string(
|
return ($obj instanceof SimpleXMLElement) ? $obj : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function extractPropertyData(string $propertyData): ?SimpleXMLElement
|
||||||
|
{
|
||||||
|
// okay to omit namespace because everything will be processed by xpath
|
||||||
|
$obj = simplexml_load_string(
|
||||||
$this->securityScanner->scan($propertyData),
|
$this->securityScanner->scan($propertyData),
|
||||||
'SimpleXMLElement',
|
'SimpleXMLElement',
|
||||||
Settings::getLibXmlLoaderOptions()
|
Settings::getLibXmlLoaderOptions()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return self::nullOrSimple($obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function readCoreProperties($propertyData): void
|
public function readCoreProperties(string $propertyData): void
|
||||||
{
|
{
|
||||||
$xmlCore = $this->extractPropertyData($propertyData);
|
$xmlCore = $this->extractPropertyData($propertyData);
|
||||||
|
|
||||||
if (is_object($xmlCore)) {
|
if (is_object($xmlCore)) {
|
||||||
$xmlCore->registerXPathNamespace('dc', 'http://purl.org/dc/elements/1.1/');
|
$xmlCore->registerXPathNamespace('dc', Namespaces::DC_ELEMENTS);
|
||||||
$xmlCore->registerXPathNamespace('dcterms', 'http://purl.org/dc/terms/');
|
$xmlCore->registerXPathNamespace('dcterms', Namespaces::DC_TERMS);
|
||||||
$xmlCore->registerXPathNamespace('cp', 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties');
|
$xmlCore->registerXPathNamespace('cp', Namespaces::CORE_PROPERTIES2);
|
||||||
|
|
||||||
$this->docProps->setCreator((string) self::getArrayItem($xmlCore->xpath('dc:creator')));
|
$this->docProps->setCreator((string) self::getArrayItem($xmlCore->xpath('dc:creator')));
|
||||||
$this->docProps->setLastModifiedBy((string) self::getArrayItem($xmlCore->xpath('cp:lastModifiedBy')));
|
$this->docProps->setLastModifiedBy((string) self::getArrayItem($xmlCore->xpath('cp:lastModifiedBy')));
|
||||||
$created = (string) self::getArrayItem($xmlCore->xpath('dcterms:created')); //! respect xsi:type
|
$this->docProps->setCreated((int) strtotime((string) self::getArrayItem($xmlCore->xpath('dcterms:created')))); //! respect xsi:type
|
||||||
$this->docProps->setCreated($created);
|
$this->docProps->setModified((int) strtotime((string) self::getArrayItem($xmlCore->xpath('dcterms:modified')))); //! respect xsi:type
|
||||||
$modified = (string) self::getArrayItem($xmlCore->xpath('dcterms:modified')); //! respect xsi:type
|
|
||||||
$this->docProps->setModified($modified); //! respect xsi:type
|
|
||||||
$this->docProps->setTitle((string) self::getArrayItem($xmlCore->xpath('dc:title')));
|
$this->docProps->setTitle((string) self::getArrayItem($xmlCore->xpath('dc:title')));
|
||||||
$this->docProps->setDescription((string) self::getArrayItem($xmlCore->xpath('dc:description')));
|
$this->docProps->setDescription((string) self::getArrayItem($xmlCore->xpath('dc:description')));
|
||||||
$this->docProps->setSubject((string) self::getArrayItem($xmlCore->xpath('dc:subject')));
|
$this->docProps->setSubject((string) self::getArrayItem($xmlCore->xpath('dc:subject')));
|
||||||
|
|
@ -51,7 +62,7 @@ class Properties
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function readExtendedProperties($propertyData): void
|
public function readExtendedProperties(string $propertyData): void
|
||||||
{
|
{
|
||||||
$xmlCore = $this->extractPropertyData($propertyData);
|
$xmlCore = $this->extractPropertyData($propertyData);
|
||||||
|
|
||||||
|
|
@ -65,7 +76,7 @@ class Properties
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function readCustomProperties($propertyData): void
|
public function readCustomProperties(string $propertyData): void
|
||||||
{
|
{
|
||||||
$xmlCore = $this->extractPropertyData($propertyData);
|
$xmlCore = $this->extractPropertyData($propertyData);
|
||||||
|
|
||||||
|
|
@ -87,8 +98,12 @@ class Properties
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function getArrayItem(array $array, $key = 0)
|
/**
|
||||||
|
* @param array|false $array
|
||||||
|
* @param mixed $key
|
||||||
|
*/
|
||||||
|
private static function getArrayItem($array, $key = 0): ?SimpleXMLElement
|
||||||
{
|
{
|
||||||
return $array[$key] ?? null;
|
return is_array($array) ? ($array[$key] ?? null) : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,25 @@
|
||||||
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
use SimpleXMLElement;
|
use SimpleXMLElement;
|
||||||
|
|
||||||
class SheetViews extends BaseParserClass
|
class SheetViews extends BaseParserClass
|
||||||
{
|
{
|
||||||
|
/** @var SimpleXMLElement */
|
||||||
private $sheetViewXml;
|
private $sheetViewXml;
|
||||||
|
|
||||||
|
/** @var SimpleXMLElement */
|
||||||
|
private $sheetViewAttributes;
|
||||||
|
|
||||||
|
/** @var Worksheet */
|
||||||
private $worksheet;
|
private $worksheet;
|
||||||
|
|
||||||
public function __construct(SimpleXMLElement $sheetViewXml, Worksheet $workSheet)
|
public function __construct(SimpleXMLElement $sheetViewXml, Worksheet $workSheet)
|
||||||
{
|
{
|
||||||
$this->sheetViewXml = $sheetViewXml;
|
$this->sheetViewXml = $sheetViewXml;
|
||||||
|
$this->sheetViewAttributes = Xlsx::testSimpleXml($sheetViewXml->attributes());
|
||||||
$this->worksheet = $workSheet;
|
$this->worksheet = $workSheet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -30,15 +37,15 @@ class SheetViews extends BaseParserClass
|
||||||
if (isset($this->sheetViewXml->pane)) {
|
if (isset($this->sheetViewXml->pane)) {
|
||||||
$this->pane();
|
$this->pane();
|
||||||
}
|
}
|
||||||
if (isset($this->sheetViewXml->selection, $this->sheetViewXml->selection['sqref'])) {
|
if (isset($this->sheetViewXml->selection, $this->sheetViewXml->selection->attributes()->sqref)) {
|
||||||
$this->selection();
|
$this->selection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function zoomScale(): void
|
private function zoomScale(): void
|
||||||
{
|
{
|
||||||
if (isset($this->sheetViewXml['zoomScale'])) {
|
if (isset($this->sheetViewAttributes->zoomScale)) {
|
||||||
$zoomScale = (int) ($this->sheetViewXml['zoomScale']);
|
$zoomScale = (int) ($this->sheetViewAttributes->zoomScale);
|
||||||
if ($zoomScale <= 0) {
|
if ($zoomScale <= 0) {
|
||||||
// setZoomScale will throw an Exception if the scale is less than or equals 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
|
// that is OK when manually creating documents, but we should be able to read all documents
|
||||||
|
|
@ -48,8 +55,8 @@ class SheetViews extends BaseParserClass
|
||||||
$this->worksheet->getSheetView()->setZoomScale($zoomScale);
|
$this->worksheet->getSheetView()->setZoomScale($zoomScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($this->sheetViewXml['zoomScaleNormal'])) {
|
if (isset($this->sheetViewAttributes->zoomScaleNormal)) {
|
||||||
$zoomScaleNormal = (int) ($this->sheetViewXml['zoomScaleNormal']);
|
$zoomScaleNormal = (int) ($this->sheetViewAttributes->zoomScaleNormal);
|
||||||
if ($zoomScaleNormal <= 0) {
|
if ($zoomScaleNormal <= 0) {
|
||||||
// setZoomScaleNormal will throw an Exception if the scale is less than or equals 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
|
// that is OK when manually creating documents, but we should be able to read all documents
|
||||||
|
|
@ -62,43 +69,43 @@ class SheetViews extends BaseParserClass
|
||||||
|
|
||||||
private function view(): void
|
private function view(): void
|
||||||
{
|
{
|
||||||
if (isset($this->sheetViewXml['view'])) {
|
if (isset($this->sheetViewAttributes->view)) {
|
||||||
$this->worksheet->getSheetView()->setView((string) $this->sheetViewXml['view']);
|
$this->worksheet->getSheetView()->setView((string) $this->sheetViewAttributes->view);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function gridLines(): void
|
private function gridLines(): void
|
||||||
{
|
{
|
||||||
if (isset($this->sheetViewXml['showGridLines'])) {
|
if (isset($this->sheetViewAttributes->showGridLines)) {
|
||||||
$this->worksheet->setShowGridLines(
|
$this->worksheet->setShowGridLines(
|
||||||
self::boolean((string) $this->sheetViewXml['showGridLines'])
|
self::boolean((string) $this->sheetViewAttributes->showGridLines)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function headers(): void
|
private function headers(): void
|
||||||
{
|
{
|
||||||
if (isset($this->sheetViewXml['showRowColHeaders'])) {
|
if (isset($this->sheetViewAttributes->showRowColHeaders)) {
|
||||||
$this->worksheet->setShowRowColHeaders(
|
$this->worksheet->setShowRowColHeaders(
|
||||||
self::boolean((string) $this->sheetViewXml['showRowColHeaders'])
|
self::boolean((string) $this->sheetViewAttributes->showRowColHeaders)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function direction(): void
|
private function direction(): void
|
||||||
{
|
{
|
||||||
if (isset($this->sheetViewXml['rightToLeft'])) {
|
if (isset($this->sheetViewAttributes->rightToLeft)) {
|
||||||
$this->worksheet->setRightToLeft(
|
$this->worksheet->setRightToLeft(
|
||||||
self::boolean((string) $this->sheetViewXml['rightToLeft'])
|
self::boolean((string) $this->sheetViewAttributes->rightToLeft)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function showZeros(): void
|
private function showZeros(): void
|
||||||
{
|
{
|
||||||
if (isset($this->sheetViewXml['showZeros'])) {
|
if (isset($this->sheetViewAttributes->showZeros)) {
|
||||||
$this->worksheet->getSheetView()->setShowZeros(
|
$this->worksheet->getSheetView()->setShowZeros(
|
||||||
self::boolean((string) $this->sheetViewXml['showZeros'])
|
self::boolean((string) $this->sheetViewAttributes->showZeros)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -108,17 +115,18 @@ class SheetViews extends BaseParserClass
|
||||||
$xSplit = 0;
|
$xSplit = 0;
|
||||||
$ySplit = 0;
|
$ySplit = 0;
|
||||||
$topLeftCell = null;
|
$topLeftCell = null;
|
||||||
|
$paneAttributes = $this->sheetViewXml->pane->attributes();
|
||||||
|
|
||||||
if (isset($this->sheetViewXml->pane['xSplit'])) {
|
if (isset($paneAttributes->xSplit)) {
|
||||||
$xSplit = (int) ($this->sheetViewXml->pane['xSplit']);
|
$xSplit = (int) ($paneAttributes->xSplit);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($this->sheetViewXml->pane['ySplit'])) {
|
if (isset($paneAttributes->ySplit)) {
|
||||||
$ySplit = (int) ($this->sheetViewXml->pane['ySplit']);
|
$ySplit = (int) ($paneAttributes->ySplit);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($this->sheetViewXml->pane['topLeftCell'])) {
|
if (isset($paneAttributes->topLeftCell)) {
|
||||||
$topLeftCell = (string) $this->sheetViewXml->pane['topLeftCell'];
|
$topLeftCell = (string) $paneAttributes->topLeftCell;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->worksheet->freezePane(
|
$this->worksheet->freezePane(
|
||||||
|
|
@ -129,10 +137,12 @@ class SheetViews extends BaseParserClass
|
||||||
|
|
||||||
private function selection(): void
|
private function selection(): void
|
||||||
{
|
{
|
||||||
$sqref = (string) $this->sheetViewXml->selection['sqref'];
|
$attributes = $this->sheetViewXml->selection->attributes();
|
||||||
$sqref = explode(' ', $sqref);
|
if ($attributes !== null) {
|
||||||
$sqref = $sqref[0];
|
$sqref = (string) $attributes->sqref;
|
||||||
|
$sqref = explode(' ', $sqref);
|
||||||
$this->worksheet->setSelectedCells($sqref);
|
$sqref = $sqref[0];
|
||||||
|
$this->worksheet->setSelectedCells($sqref);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Border;
|
use PhpOffice\PhpSpreadsheet\Style\Border;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Borders;
|
use PhpOffice\PhpSpreadsheet\Style\Borders;
|
||||||
|
|
@ -82,7 +83,7 @@ class Styles extends BaseParserClass
|
||||||
if ($numfmtStyleXml->count() === 0) {
|
if ($numfmtStyleXml->count() === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$numfmt = $numfmtStyleXml->attributes();
|
$numfmt = Xlsx::getAttributes($numfmtStyleXml);
|
||||||
if ($numfmt->count() > 0 && isset($numfmt['formatCode'])) {
|
if ($numfmt->count() > 0 && isset($numfmt['formatCode'])) {
|
||||||
$numfmtStyle->setFormatCode((string) $numfmt['formatCode']);
|
$numfmtStyle->setFormatCode((string) $numfmt['formatCode']);
|
||||||
}
|
}
|
||||||
|
|
@ -97,13 +98,9 @@ class Styles extends BaseParserClass
|
||||||
$fillStyle->setFillType((string) $gradientFill['type']);
|
$fillStyle->setFillType((string) $gradientFill['type']);
|
||||||
}
|
}
|
||||||
$fillStyle->setRotation((float) ($gradientFill['degree']));
|
$fillStyle->setRotation((float) ($gradientFill['degree']));
|
||||||
$gradientFill->registerXPathNamespace('sml', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main');
|
$gradientFill->registerXPathNamespace('sml', Namespaces::MAIN);
|
||||||
$fillStyle->getStartColor()->setARGB(
|
$fillStyle->getStartColor()->setARGB(self::readColor(self::getArrayItem($gradientFill->xpath('sml:stop[@position=0]'))->color));
|
||||||
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));
|
||||||
);
|
|
||||||
$fillStyle->getEndColor()->setARGB(
|
|
||||||
self::readColor(self::getArrayItem($gradientFill->xpath('sml:stop[@position=1]'))->color)
|
|
||||||
);
|
|
||||||
} elseif ($fillStyleXml->patternFill) {
|
} elseif ($fillStyleXml->patternFill) {
|
||||||
$defaultFillStyle = Fill::FILL_NONE;
|
$defaultFillStyle = Fill::FILL_NONE;
|
||||||
if ($fillStyleXml->patternFill->fgColor) {
|
if ($fillStyleXml->patternFill->fgColor) {
|
||||||
|
|
@ -270,7 +267,8 @@ class Styles extends BaseParserClass
|
||||||
}
|
}
|
||||||
// Cell Styles
|
// Cell Styles
|
||||||
if ($this->styleXml->cellStyles) {
|
if ($this->styleXml->cellStyles) {
|
||||||
foreach ($this->styleXml->cellStyles->cellStyle as $cellStyle) {
|
foreach ($this->styleXml->cellStyles->cellStyle as $cellStylex) {
|
||||||
|
$cellStyle = Xlsx::getAttributes($cellStylex);
|
||||||
if ((int) ($cellStyle['builtinId']) == 0) {
|
if ((int) ($cellStyle['builtinId']) == 0) {
|
||||||
if (isset($this->cellStyles[(int) ($cellStyle['xfId'])])) {
|
if (isset($this->cellStyles[(int) ($cellStyle['xfId'])])) {
|
||||||
// Set default style
|
// Set default style
|
||||||
|
|
|
||||||
|
|
@ -581,8 +581,8 @@ class ReferenceHelper
|
||||||
|
|
||||||
// Update worksheet: freeze pane
|
// Update worksheet: freeze pane
|
||||||
if ($pSheet->getFreezePane()) {
|
if ($pSheet->getFreezePane()) {
|
||||||
$splitCell = $pSheet->getFreezePane();
|
$splitCell = $pSheet->getFreezePane() ?? '';
|
||||||
$topLeftCell = $pSheet->getTopLeftCell();
|
$topLeftCell = $pSheet->getTopLeftCell() ?? '';
|
||||||
|
|
||||||
$splitCell = $this->updateCellReference($splitCell, $pBefore, $pNumCols, $pNumRows);
|
$splitCell = $this->updateCellReference($splitCell, $pBefore, $pNumCols, $pNumRows);
|
||||||
$topLeftCell = $this->updateCellReference($topLeftCell, $pBefore, $pNumCols, $pNumRows);
|
$topLeftCell = $this->updateCellReference($topLeftCell, $pBefore, $pNumCols, $pNumRows);
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
namespace PhpOffice\PhpSpreadsheet\Shared;
|
namespace PhpOffice\PhpSpreadsheet\Shared;
|
||||||
|
|
||||||
use GdImage;
|
use GdImage;
|
||||||
|
use SimpleXMLElement;
|
||||||
|
|
||||||
class Drawing
|
class Drawing
|
||||||
{
|
{
|
||||||
|
|
@ -21,12 +22,13 @@ class Drawing
|
||||||
/**
|
/**
|
||||||
* Convert EMU to pixels.
|
* Convert EMU to pixels.
|
||||||
*
|
*
|
||||||
* @param int $emuValue Value in EMU
|
* @param int|SimpleXMLElement $emuValue Value in EMU
|
||||||
*
|
*
|
||||||
* @return int Value in pixels
|
* @return int Value in pixels
|
||||||
*/
|
*/
|
||||||
public static function EMUToPixels($emuValue)
|
public static function EMUToPixels($emuValue)
|
||||||
{
|
{
|
||||||
|
$emuValue = (int) $emuValue;
|
||||||
if ($emuValue != 0) {
|
if ($emuValue != 0) {
|
||||||
return (int) round($emuValue / 9525);
|
return (int) round($emuValue / 9525);
|
||||||
}
|
}
|
||||||
|
|
@ -136,12 +138,13 @@ class Drawing
|
||||||
/**
|
/**
|
||||||
* Convert angle to degrees.
|
* Convert angle to degrees.
|
||||||
*
|
*
|
||||||
* @param int $pValue Angle
|
* @param int|SimpleXMLElement $pValue Angle
|
||||||
*
|
*
|
||||||
* @return int Degrees
|
* @return int Degrees
|
||||||
*/
|
*/
|
||||||
public static function angleToDegrees($pValue)
|
public static function angleToDegrees($pValue)
|
||||||
{
|
{
|
||||||
|
$pValue = (int) $pValue;
|
||||||
if ($pValue != 0) {
|
if ($pValue != 0) {
|
||||||
return (int) round($pValue / 60000);
|
return (int) round($pValue / 60000);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1928,7 +1928,7 @@ class Worksheet implements IComparable
|
||||||
/**
|
/**
|
||||||
* Get Freeze Pane.
|
* Get Freeze Pane.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return null|string
|
||||||
*/
|
*/
|
||||||
public function getFreezePane()
|
public function getFreezePane()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1584,7 +1584,7 @@ class Worksheet extends BIFFwriter
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[$column, $row] = Coordinate::indexesFromString($this->phpSheet->getFreezePane());
|
[$column, $row] = Coordinate::indexesFromString($this->phpSheet->getFreezePane() ?? '');
|
||||||
$x = $column - 1;
|
$x = $column - 1;
|
||||||
$y = $row - 1;
|
$y = $row - 1;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -253,7 +253,7 @@ class Worksheet extends WriterPart
|
||||||
// Pane
|
// Pane
|
||||||
$pane = '';
|
$pane = '';
|
||||||
if ($pSheet->getFreezePane()) {
|
if ($pSheet->getFreezePane()) {
|
||||||
[$xSplit, $ySplit] = Coordinate::coordinateFromString($pSheet->getFreezePane());
|
[$xSplit, $ySplit] = Coordinate::coordinateFromString($pSheet->getFreezePane() ?? '');
|
||||||
$xSplit = Coordinate::columnIndexFromString($xSplit);
|
$xSplit = Coordinate::columnIndexFromString($xSplit);
|
||||||
--$xSplit;
|
--$xSplit;
|
||||||
--$ySplit;
|
--$ySplit;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Reader;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
|
|
||||||
|
class NamespaceIssue2109bTest extends \PHPUnit\Framework\TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private static $testbook = 'tests/data/Reader/XLSX/issue2109b.xlsx';
|
||||||
|
|
||||||
|
public function testPreliminaries(): void
|
||||||
|
{
|
||||||
|
$file = 'zip://';
|
||||||
|
$file .= self::$testbook;
|
||||||
|
$file .= '#xl/workbook.xml';
|
||||||
|
$data = file_get_contents($file);
|
||||||
|
// confirm that file contains expected namespaced xml tag
|
||||||
|
if ($data === false) {
|
||||||
|
self::fail('Unable to read file');
|
||||||
|
} else {
|
||||||
|
self::assertStringContainsString('<x:workbook ', $data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInfo(): void
|
||||||
|
{
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$workSheetInfo = $reader->listWorkSheetInfo(self::$testbook);
|
||||||
|
$info0 = $workSheetInfo[0];
|
||||||
|
self::assertEquals('Sheet1', $info0['worksheetName']);
|
||||||
|
self::assertEquals('AF', $info0['lastColumnLetter']);
|
||||||
|
self::assertEquals(31, $info0['lastColumnIndex']);
|
||||||
|
self::assertEquals(4, $info0['totalRows']);
|
||||||
|
self::assertEquals(32, $info0['totalColumns']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSheetNames(): void
|
||||||
|
{
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$worksheetNames = $reader->listWorksheetNames(self::$testbook);
|
||||||
|
self::assertEquals(['Sheet1'], $worksheetNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testActive(): void
|
||||||
|
{
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$spreadsheet = $reader->load(self::$testbook);
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
self::assertSame('Sheet1', $sheet->getTitle());
|
||||||
|
self::assertNull($sheet->getFreezePane());
|
||||||
|
self::assertNull($sheet->getTopLeftCell());
|
||||||
|
self::assertSame('A1', $sheet->getSelectedCells());
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getCellValue(Worksheet $sheet, string $cell): string
|
||||||
|
{
|
||||||
|
$result = $sheet->getCell($cell)->getValue();
|
||||||
|
|
||||||
|
return (string) $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLoadXlsx(): void
|
||||||
|
{
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$spreadsheet = $reader->load(self::$testbook);
|
||||||
|
$sheet = $spreadsheet->getSheet(0);
|
||||||
|
self::assertEquals('Sheet1', $sheet->getTitle());
|
||||||
|
$expectedArray = [
|
||||||
|
'A1' => 'Channel Name = Cartoon Network RSE',
|
||||||
|
'B2' => 'Event ID',
|
||||||
|
'C3' => '2021-05-17 03:00',
|
||||||
|
'F4' => 'The Internet',
|
||||||
|
'AF3' => '902476',
|
||||||
|
'AF4' => '902477',
|
||||||
|
'J2' => 'Episode Synopsis',
|
||||||
|
'J3' => 'Gumball and Darwin\'s reputation is challenged and they really couldn\'t care less...',
|
||||||
|
'J4' => 'Gumball accidentally uploads a video of himself and wants it gone.',
|
||||||
|
];
|
||||||
|
foreach ($expectedArray as $key => $value) {
|
||||||
|
self::assertSame($value, self::getCellValue($sheet, $key), "error in cell $key");
|
||||||
|
}
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Reader;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
|
|
||||||
|
class NamespaceOpenpyxl35Test extends \PHPUnit\Framework\TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private static $testbook = 'tests/data/Reader/XLSX/namespaces.openpyxl35.xlsx';
|
||||||
|
|
||||||
|
public function testPreliminaries(): void
|
||||||
|
{
|
||||||
|
$file = 'zip://';
|
||||||
|
$file .= self::$testbook;
|
||||||
|
$file .= '#xl/workbook.xml';
|
||||||
|
$data = file_get_contents($file);
|
||||||
|
// confirm that file contains expected namespaced xml tag
|
||||||
|
if ($data === false) {
|
||||||
|
self::fail('Unable to read file');
|
||||||
|
} else {
|
||||||
|
self::assertStringContainsString('<s:workbook ', $data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInfo(): void
|
||||||
|
{
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$workSheetInfo = $reader->listWorkSheetInfo(self::$testbook);
|
||||||
|
$info0 = $workSheetInfo[0];
|
||||||
|
self::assertEquals('Shofar 5781', $info0['worksheetName']);
|
||||||
|
self::assertEquals('D', $info0['lastColumnLetter']);
|
||||||
|
self::assertEquals(3, $info0['lastColumnIndex']);
|
||||||
|
self::assertEquals(30, $info0['totalRows']);
|
||||||
|
self::assertEquals(4, $info0['totalColumns']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSheetNames(): void
|
||||||
|
{
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$worksheetNames = $reader->listWorksheetNames(self::$testbook);
|
||||||
|
self::assertEquals(['Shofar 5781', 'Shofar 5782', 'Shofar 5783'], $worksheetNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testActive(): void
|
||||||
|
{
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$spreadsheet = $reader->load(self::$testbook);
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
self::assertSame('Shofar 5781', $sheet->getTitle());
|
||||||
|
self::assertSame('A2', $sheet->getFreezePane());
|
||||||
|
self::assertSame('A2', $sheet->getTopLeftCell());
|
||||||
|
self::assertSame('D2', $sheet->getSelectedCells());
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getCellValue(Worksheet $sheet, string $cell): string
|
||||||
|
{
|
||||||
|
$result = $sheet->getCell($cell)->getValue();
|
||||||
|
|
||||||
|
return (string) $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLoadXlsx(): void
|
||||||
|
{
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$spreadsheet = $reader->load(self::$testbook);
|
||||||
|
$sheet = $spreadsheet->getSheet(0);
|
||||||
|
self::assertEquals('Shofar 5781', $sheet->getTitle());
|
||||||
|
$expectedArray = [
|
||||||
|
'Shofar 5781' => [
|
||||||
|
'A1' => 'Weekday',
|
||||||
|
'B6' => 'August 13',
|
||||||
|
'A14' => 'Saturday',
|
||||||
|
'C14' => 'Elul 13',
|
||||||
|
'D30' => 'N/A',
|
||||||
|
'B30' => 'September 6',
|
||||||
|
],
|
||||||
|
'Shofar 5782' => [
|
||||||
|
'C1' => 'Jewish Date',
|
||||||
|
'B6' => 'September 1',
|
||||||
|
'A14' => 'Friday',
|
||||||
|
'C14' => 'Elul 13',
|
||||||
|
'D28' => '',
|
||||||
|
'B30' => 'September 25',
|
||||||
|
],
|
||||||
|
'Shofar 5783' => [
|
||||||
|
'B1' => 'Civil Date',
|
||||||
|
'B6' => 'August 22',
|
||||||
|
'A14' => 'Wednesday',
|
||||||
|
'C14' => 'Elul 13',
|
||||||
|
'D30' => 'N/A',
|
||||||
|
'B30' => 'September 15',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
foreach ($expectedArray as $sheetName => $array1) {
|
||||||
|
$sheet = $spreadsheet->getSheetByName($sheetName);
|
||||||
|
if ($sheet === null) {
|
||||||
|
self::fail("Unable to find sheet $sheetName");
|
||||||
|
} else {
|
||||||
|
foreach ($array1 as $key => $value) {
|
||||||
|
self::assertSame($value, self::getCellValue($sheet, $key), "error in sheet $sheetName cell $key");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$spreadsheet->disconnectWorksheets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,179 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Reader;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Style\Border;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Style\Fill;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Style\Font;
|
||||||
|
|
||||||
|
class NamespaceNonStdTest extends \PHPUnit\Framework\TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private static $testbook = 'tests/data/Reader/XLSX/namespacenonstd.xlsx';
|
||||||
|
|
||||||
|
public function testPreliminaries(): void
|
||||||
|
{
|
||||||
|
$file = 'zip://';
|
||||||
|
$file .= self::$testbook;
|
||||||
|
$file .= '#xl/workbook.xml';
|
||||||
|
$data = file_get_contents($file);
|
||||||
|
// confirm that file contains expected namespaced xml tag
|
||||||
|
if ($data === false) {
|
||||||
|
self::fail('Unable to read file');
|
||||||
|
} else {
|
||||||
|
if (strpos(__FILE__, 'NonStd') === false) {
|
||||||
|
self::assertStringNotContainsString('nonstd', self::$testbook);
|
||||||
|
self::assertStringContainsString('<workbook ', $data);
|
||||||
|
} else {
|
||||||
|
self::assertStringContainsString('nonstd', self::$testbook);
|
||||||
|
self::assertStringContainsString('<x:workbook ', $data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInfo(): void
|
||||||
|
{
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$workSheetInfo = $reader->listWorkSheetInfo(self::$testbook);
|
||||||
|
$info0 = $workSheetInfo[0];
|
||||||
|
self::assertEquals('SylkTest', $info0['worksheetName']);
|
||||||
|
self::assertEquals('J', $info0['lastColumnLetter']);
|
||||||
|
self::assertEquals(9, $info0['lastColumnIndex']);
|
||||||
|
self::assertEquals(18, $info0['totalRows']);
|
||||||
|
self::assertEquals(10, $info0['totalColumns']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSheetNames(): void
|
||||||
|
{
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$worksheetNames = $reader->listWorksheetNames(self::$testbook);
|
||||||
|
self::assertEquals(['SylkTest', 'Second'], $worksheetNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testActive(): void
|
||||||
|
{
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$spreadsheet = $reader->load(self::$testbook);
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
self::assertSame('Second', $sheet->getTitle());
|
||||||
|
self::assertSame('A2', $sheet->getFreezePane());
|
||||||
|
self::assertSame('A2', $sheet->getTopLeftCell());
|
||||||
|
self::assertSame('B3', $sheet->getSelectedCells());
|
||||||
|
$sheet = $spreadsheet->getSheetByName('SylkTest');
|
||||||
|
if ($sheet === null) {
|
||||||
|
self::fail('Unable to load expected sheet');
|
||||||
|
} else {
|
||||||
|
self::assertNull($sheet->getFreezePane());
|
||||||
|
self::assertNull($sheet->getTopLeftCell());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLoadXlsx(): void
|
||||||
|
{
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$spreadsheet = $reader->load(self::$testbook);
|
||||||
|
$sheet = $spreadsheet->getSheet(0);
|
||||||
|
self::assertEquals('SylkTest', $sheet->getTitle());
|
||||||
|
if (strpos(__FILE__, 'NonStd') !== false) {
|
||||||
|
self::markTestIncomplete('Not yet ready');
|
||||||
|
}
|
||||||
|
|
||||||
|
self::assertEquals('FFFF0000', $sheet->getCell('A1')->getStyle()->getFont()->getColor()->getARGB());
|
||||||
|
self::assertEquals(Fill::FILL_PATTERN_GRAY125, $sheet->getCell('A2')->getStyle()->getFill()->getFillType());
|
||||||
|
self::assertEquals(Font::UNDERLINE_SINGLE, $sheet->getCell('A4')->getStyle()->getFont()->getUnderline());
|
||||||
|
self::assertEquals('Test with (;) in string', $sheet->getCell('A4')->getValue());
|
||||||
|
|
||||||
|
self::assertEquals(22269, $sheet->getCell('A10')->getValue());
|
||||||
|
self::assertEquals('dd/mm/yyyy', $sheet->getCell('A10')->getStyle()->getNumberFormat()->getFormatCode());
|
||||||
|
self::assertEquals('19/12/1960', $sheet->getCell('A10')->getFormattedValue());
|
||||||
|
self::assertEquals(1.5, $sheet->getCell('A11')->getValue());
|
||||||
|
self::assertEquals('# ?/?', $sheet->getCell('A11')->getStyle()->getNumberFormat()->getFormatCode());
|
||||||
|
self::assertEquals('1 1/2', $sheet->getCell('A11')->getFormattedValue());
|
||||||
|
|
||||||
|
self::assertEquals('=B1+C1', $sheet->getCell('H1')->getValue());
|
||||||
|
self::assertEquals('=E2&F2', $sheet->getCell('J2')->getValue());
|
||||||
|
self::assertEquals('=SUM(C1:C4)', $sheet->getCell('I5')->getValue());
|
||||||
|
self::assertEquals('=MEDIAN(B6:B8)', $sheet->getCell('B9')->getValue());
|
||||||
|
|
||||||
|
self::assertEquals(11, $sheet->getCell('E1')->getStyle()->getFont()->getSize());
|
||||||
|
self::assertTrue($sheet->getCell('E1')->getStyle()->getFont()->getBold());
|
||||||
|
self::assertTrue($sheet->getCell('E1')->getStyle()->getFont()->getItalic());
|
||||||
|
self::assertEquals(Font::UNDERLINE_SINGLE, $sheet->getCell('E1')->getStyle()->getFont()->getUnderline());
|
||||||
|
self::assertFalse($sheet->getCell('E2')->getStyle()->getFont()->getBold());
|
||||||
|
self::assertFalse($sheet->getCell('E2')->getStyle()->getFont()->getItalic());
|
||||||
|
self::assertEquals(Font::UNDERLINE_NONE, $sheet->getCell('E2')->getStyle()->getFont()->getUnderline());
|
||||||
|
self::assertTrue($sheet->getCell('E3')->getStyle()->getFont()->getBold());
|
||||||
|
self::assertFalse($sheet->getCell('E3')->getStyle()->getFont()->getItalic());
|
||||||
|
self::assertEquals(Font::UNDERLINE_NONE, $sheet->getCell('E3')->getStyle()->getFont()->getUnderline());
|
||||||
|
self::assertFalse($sheet->getCell('E4')->getStyle()->getFont()->getBold());
|
||||||
|
self::assertTrue($sheet->getCell('E4')->getStyle()->getFont()->getItalic());
|
||||||
|
self::assertEquals(Font::UNDERLINE_NONE, $sheet->getCell('E4')->getStyle()->getFont()->getUnderline());
|
||||||
|
|
||||||
|
self::assertTrue($sheet->getCell('F1')->getStyle()->getFont()->getBold());
|
||||||
|
self::assertFalse($sheet->getCell('F1')->getStyle()->getFont()->getItalic());
|
||||||
|
self::assertEquals(Font::UNDERLINE_SINGLE, $sheet->getCell('F1')->getStyle()->getFont()->getUnderline());
|
||||||
|
self::assertFalse($sheet->getCell('F2')->getStyle()->getFont()->getBold());
|
||||||
|
self::assertFalse($sheet->getCell('F2')->getStyle()->getFont()->getItalic());
|
||||||
|
self::assertEquals(Font::UNDERLINE_NONE, $sheet->getCell('F2')->getStyle()->getFont()->getUnderline());
|
||||||
|
self::assertTrue($sheet->getCell('F3')->getStyle()->getFont()->getBold());
|
||||||
|
self::assertTrue($sheet->getCell('F3')->getStyle()->getFont()->getItalic());
|
||||||
|
self::assertEquals(Font::UNDERLINE_NONE, $sheet->getCell('F3')->getStyle()->getFont()->getUnderline());
|
||||||
|
self::assertFalse($sheet->getCell('F4')->getStyle()->getFont()->getBold());
|
||||||
|
self::assertFalse($sheet->getCell('F4')->getStyle()->getFont()->getItalic());
|
||||||
|
self::assertEquals(Font::UNDERLINE_NONE, $sheet->getCell('F4')->getStyle()->getFont()->getUnderline());
|
||||||
|
|
||||||
|
self::assertEquals(Border::BORDER_THIN, $sheet->getCell('C10')->getStyle()->getBorders()->getTop()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C10')->getStyle()->getBorders()->getRight()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C10')->getStyle()->getBorders()->getBottom()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C10')->getStyle()->getBorders()->getLeft()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C12')->getStyle()->getBorders()->getTop()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C12')->getStyle()->getBorders()->getRight()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_THIN, $sheet->getCell('C12')->getStyle()->getBorders()->getBottom()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C12')->getStyle()->getBorders()->getLeft()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C14')->getStyle()->getBorders()->getTop()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C14')->getStyle()->getBorders()->getRight()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C14')->getStyle()->getBorders()->getBottom()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_THIN, $sheet->getCell('C14')->getStyle()->getBorders()->getLeft()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C16')->getStyle()->getBorders()->getTop()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_THIN, $sheet->getCell('C16')->getStyle()->getBorders()->getRight()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C16')->getStyle()->getBorders()->getBottom()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C16')->getStyle()->getBorders()->getLeft()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_THIN, $sheet->getCell('C18')->getStyle()->getBorders()->getTop()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_THIN, $sheet->getCell('C18')->getStyle()->getBorders()->getRight()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_THIN, $sheet->getCell('C18')->getStyle()->getBorders()->getBottom()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_THIN, $sheet->getCell('C18')->getStyle()->getBorders()->getLeft()->getBorderStyle());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLoadXlsxSheet2Contents(): void
|
||||||
|
{
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$spreadsheet = $reader->load(self::$testbook);
|
||||||
|
$sheet = $spreadsheet->getSheet(1);
|
||||||
|
self::assertEquals('Second', $sheet->getTitle());
|
||||||
|
self::assertSame('Hyperlink', $sheet->getCell('B2')->getValue());
|
||||||
|
$hyper = $sheet->getCell('B2')->getHyperlink();
|
||||||
|
self::assertSame('http://www.example.com/', $hyper->getUrl());
|
||||||
|
self::assertSame('Comment', $sheet->getCell('B3')->getValue());
|
||||||
|
$comment = $sheet->getComment('B3');
|
||||||
|
// Created as "threaded comment" with Excel 365, not quite as expected.
|
||||||
|
self::assertStringContainsString('This is a comment', (string) $comment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLoadXlsxSheet2Styles(): void
|
||||||
|
{
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$spreadsheet = $reader->load(self::$testbook);
|
||||||
|
$sheet = $spreadsheet->getSheet(1);
|
||||||
|
self::assertEquals('Second', $sheet->getTitle());
|
||||||
|
if (strpos(__FILE__, 'NonStd') !== false) {
|
||||||
|
self::markTestIncomplete('Not yet ready');
|
||||||
|
}
|
||||||
|
self::assertEquals('center', $sheet->getCell('A2')->getStyle()->getAlignment()->getHorizontal());
|
||||||
|
self::assertSame('inherit', $sheet->getCell('A2')->getStyle()->getProtection()->getLocked());
|
||||||
|
self::assertEquals('top', $sheet->getCell('A3')->getStyle()->getAlignment()->getVertical());
|
||||||
|
self::assertSame('unprotected', $sheet->getCell('A3')->getStyle()->getProtection()->getLocked());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Reader;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||||
|
|
||||||
|
class NamespacePurlTest extends \PHPUnit\Framework\TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private static $testbook = 'tests/data/Reader/XLSX/namespacepurl.xlsx';
|
||||||
|
|
||||||
|
public function testPreliminaries(): void
|
||||||
|
{
|
||||||
|
$file = 'zip://';
|
||||||
|
$file .= self::$testbook;
|
||||||
|
$file .= '#xl/workbook.xml';
|
||||||
|
$data = file_get_contents($file);
|
||||||
|
// confirm that file contains expected namespaced xml tag
|
||||||
|
if ($data === false) {
|
||||||
|
self::fail('Unable to read file');
|
||||||
|
} else {
|
||||||
|
self::assertStringContainsString('http://purl.oclc.org/ooxml/', $data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testPurlNamespace(): void
|
||||||
|
{
|
||||||
|
$filename = self::$testbook;
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$actual = $reader->canRead($filename);
|
||||||
|
self::assertTrue($actual);
|
||||||
|
|
||||||
|
$sheets = $reader->listWorksheetNames($filename);
|
||||||
|
self::assertEquals(['ml_out'], $sheets);
|
||||||
|
|
||||||
|
$actual = $reader->listWorksheetInfo($filename);
|
||||||
|
$expected = [
|
||||||
|
[
|
||||||
|
'worksheetName' => 'ml_out',
|
||||||
|
'lastColumnLetter' => 'R',
|
||||||
|
'lastColumnIndex' => 17,
|
||||||
|
'totalRows' => '76',
|
||||||
|
'totalColumns' => 18,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
self::assertEquals($expected, $actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testPurlLoad(): void
|
||||||
|
{
|
||||||
|
$filename = self::$testbook;
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$spreadsheet = $reader->load($filename);
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
self::assertSame('ml_out', $sheet->getTitle());
|
||||||
|
self::assertSame('Item', $sheet->getCell('A1')->getValue());
|
||||||
|
self::assertEquals(97.91, $sheet->getCell('G3')->getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,179 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Reader;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Style\Border;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Style\Fill;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Style\Font;
|
||||||
|
|
||||||
|
class NamespaceStdTest extends \PHPUnit\Framework\TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private static $testbook = 'tests/data/Reader/XLSX/namespacestd.xlsx';
|
||||||
|
|
||||||
|
public function testPreliminaries(): void
|
||||||
|
{
|
||||||
|
$file = 'zip://';
|
||||||
|
$file .= self::$testbook;
|
||||||
|
$file .= '#xl/workbook.xml';
|
||||||
|
$data = file_get_contents($file);
|
||||||
|
// confirm that file contains expected namespaced xml tag
|
||||||
|
if ($data === false) {
|
||||||
|
self::fail('Unable to read file');
|
||||||
|
} else {
|
||||||
|
if (strpos(__FILE__, 'NonStd') === false) {
|
||||||
|
self::assertStringNotContainsString('nonstd', self::$testbook);
|
||||||
|
self::assertStringContainsString('<workbook ', $data);
|
||||||
|
} else {
|
||||||
|
self::assertStringContainsString('nonstd', self::$testbook);
|
||||||
|
self::assertStringContainsString('<x:workbook ', $data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInfo(): void
|
||||||
|
{
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$workSheetInfo = $reader->listWorkSheetInfo(self::$testbook);
|
||||||
|
$info0 = $workSheetInfo[0];
|
||||||
|
self::assertEquals('SylkTest', $info0['worksheetName']);
|
||||||
|
self::assertEquals('J', $info0['lastColumnLetter']);
|
||||||
|
self::assertEquals(9, $info0['lastColumnIndex']);
|
||||||
|
self::assertEquals(18, $info0['totalRows']);
|
||||||
|
self::assertEquals(10, $info0['totalColumns']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSheetNames(): void
|
||||||
|
{
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$worksheetNames = $reader->listWorksheetNames(self::$testbook);
|
||||||
|
self::assertEquals(['SylkTest', 'Second'], $worksheetNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testActive(): void
|
||||||
|
{
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$spreadsheet = $reader->load(self::$testbook);
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
self::assertSame('Second', $sheet->getTitle());
|
||||||
|
self::assertSame('A2', $sheet->getFreezePane());
|
||||||
|
self::assertSame('A2', $sheet->getTopLeftCell());
|
||||||
|
self::assertSame('B3', $sheet->getSelectedCells());
|
||||||
|
$sheet = $spreadsheet->getSheetByName('SylkTest');
|
||||||
|
if ($sheet === null) {
|
||||||
|
self::fail('Unable to load expected sheet');
|
||||||
|
} else {
|
||||||
|
self::assertNull($sheet->getFreezePane());
|
||||||
|
self::assertNull($sheet->getTopLeftCell());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLoadXlsx(): void
|
||||||
|
{
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$spreadsheet = $reader->load(self::$testbook);
|
||||||
|
$sheet = $spreadsheet->getSheet(0);
|
||||||
|
self::assertEquals('SylkTest', $sheet->getTitle());
|
||||||
|
if (strpos(__FILE__, 'NonStd') !== false) {
|
||||||
|
self::markTestIncomplete('Not yet ready');
|
||||||
|
}
|
||||||
|
|
||||||
|
self::assertEquals('FFFF0000', $sheet->getCell('A1')->getStyle()->getFont()->getColor()->getARGB());
|
||||||
|
self::assertEquals(Fill::FILL_PATTERN_GRAY125, $sheet->getCell('A2')->getStyle()->getFill()->getFillType());
|
||||||
|
self::assertEquals(Font::UNDERLINE_SINGLE, $sheet->getCell('A4')->getStyle()->getFont()->getUnderline());
|
||||||
|
self::assertEquals('Test with (;) in string', $sheet->getCell('A4')->getValue());
|
||||||
|
|
||||||
|
self::assertEquals(22269, $sheet->getCell('A10')->getValue());
|
||||||
|
self::assertEquals('dd/mm/yyyy', $sheet->getCell('A10')->getStyle()->getNumberFormat()->getFormatCode());
|
||||||
|
self::assertEquals('19/12/1960', $sheet->getCell('A10')->getFormattedValue());
|
||||||
|
self::assertEquals(1.5, $sheet->getCell('A11')->getValue());
|
||||||
|
self::assertEquals('# ?/?', $sheet->getCell('A11')->getStyle()->getNumberFormat()->getFormatCode());
|
||||||
|
self::assertEquals('1 1/2', $sheet->getCell('A11')->getFormattedValue());
|
||||||
|
|
||||||
|
self::assertEquals('=B1+C1', $sheet->getCell('H1')->getValue());
|
||||||
|
self::assertEquals('=E2&F2', $sheet->getCell('J2')->getValue());
|
||||||
|
self::assertEquals('=SUM(C1:C4)', $sheet->getCell('I5')->getValue());
|
||||||
|
self::assertEquals('=MEDIAN(B6:B8)', $sheet->getCell('B9')->getValue());
|
||||||
|
|
||||||
|
self::assertEquals(11, $sheet->getCell('E1')->getStyle()->getFont()->getSize());
|
||||||
|
self::assertTrue($sheet->getCell('E1')->getStyle()->getFont()->getBold());
|
||||||
|
self::assertTrue($sheet->getCell('E1')->getStyle()->getFont()->getItalic());
|
||||||
|
self::assertEquals(Font::UNDERLINE_SINGLE, $sheet->getCell('E1')->getStyle()->getFont()->getUnderline());
|
||||||
|
self::assertFalse($sheet->getCell('E2')->getStyle()->getFont()->getBold());
|
||||||
|
self::assertFalse($sheet->getCell('E2')->getStyle()->getFont()->getItalic());
|
||||||
|
self::assertEquals(Font::UNDERLINE_NONE, $sheet->getCell('E2')->getStyle()->getFont()->getUnderline());
|
||||||
|
self::assertTrue($sheet->getCell('E3')->getStyle()->getFont()->getBold());
|
||||||
|
self::assertFalse($sheet->getCell('E3')->getStyle()->getFont()->getItalic());
|
||||||
|
self::assertEquals(Font::UNDERLINE_NONE, $sheet->getCell('E3')->getStyle()->getFont()->getUnderline());
|
||||||
|
self::assertFalse($sheet->getCell('E4')->getStyle()->getFont()->getBold());
|
||||||
|
self::assertTrue($sheet->getCell('E4')->getStyle()->getFont()->getItalic());
|
||||||
|
self::assertEquals(Font::UNDERLINE_NONE, $sheet->getCell('E4')->getStyle()->getFont()->getUnderline());
|
||||||
|
|
||||||
|
self::assertTrue($sheet->getCell('F1')->getStyle()->getFont()->getBold());
|
||||||
|
self::assertFalse($sheet->getCell('F1')->getStyle()->getFont()->getItalic());
|
||||||
|
self::assertEquals(Font::UNDERLINE_SINGLE, $sheet->getCell('F1')->getStyle()->getFont()->getUnderline());
|
||||||
|
self::assertFalse($sheet->getCell('F2')->getStyle()->getFont()->getBold());
|
||||||
|
self::assertFalse($sheet->getCell('F2')->getStyle()->getFont()->getItalic());
|
||||||
|
self::assertEquals(Font::UNDERLINE_NONE, $sheet->getCell('F2')->getStyle()->getFont()->getUnderline());
|
||||||
|
self::assertTrue($sheet->getCell('F3')->getStyle()->getFont()->getBold());
|
||||||
|
self::assertTrue($sheet->getCell('F3')->getStyle()->getFont()->getItalic());
|
||||||
|
self::assertEquals(Font::UNDERLINE_NONE, $sheet->getCell('F3')->getStyle()->getFont()->getUnderline());
|
||||||
|
self::assertFalse($sheet->getCell('F4')->getStyle()->getFont()->getBold());
|
||||||
|
self::assertFalse($sheet->getCell('F4')->getStyle()->getFont()->getItalic());
|
||||||
|
self::assertEquals(Font::UNDERLINE_NONE, $sheet->getCell('F4')->getStyle()->getFont()->getUnderline());
|
||||||
|
|
||||||
|
self::assertEquals(Border::BORDER_THIN, $sheet->getCell('C10')->getStyle()->getBorders()->getTop()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C10')->getStyle()->getBorders()->getRight()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C10')->getStyle()->getBorders()->getBottom()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C10')->getStyle()->getBorders()->getLeft()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C12')->getStyle()->getBorders()->getTop()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C12')->getStyle()->getBorders()->getRight()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_THIN, $sheet->getCell('C12')->getStyle()->getBorders()->getBottom()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C12')->getStyle()->getBorders()->getLeft()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C14')->getStyle()->getBorders()->getTop()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C14')->getStyle()->getBorders()->getRight()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C14')->getStyle()->getBorders()->getBottom()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_THIN, $sheet->getCell('C14')->getStyle()->getBorders()->getLeft()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C16')->getStyle()->getBorders()->getTop()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_THIN, $sheet->getCell('C16')->getStyle()->getBorders()->getRight()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C16')->getStyle()->getBorders()->getBottom()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_NONE, $sheet->getCell('C16')->getStyle()->getBorders()->getLeft()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_THIN, $sheet->getCell('C18')->getStyle()->getBorders()->getTop()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_THIN, $sheet->getCell('C18')->getStyle()->getBorders()->getRight()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_THIN, $sheet->getCell('C18')->getStyle()->getBorders()->getBottom()->getBorderStyle());
|
||||||
|
self::assertEquals(Border::BORDER_THIN, $sheet->getCell('C18')->getStyle()->getBorders()->getLeft()->getBorderStyle());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLoadXlsxSheet2Contents(): void
|
||||||
|
{
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$spreadsheet = $reader->load(self::$testbook);
|
||||||
|
$sheet = $spreadsheet->getSheet(1);
|
||||||
|
self::assertEquals('Second', $sheet->getTitle());
|
||||||
|
self::assertSame('Hyperlink', $sheet->getCell('B2')->getValue());
|
||||||
|
$hyper = $sheet->getCell('B2')->getHyperlink();
|
||||||
|
self::assertSame('http://www.example.com/', $hyper->getUrl());
|
||||||
|
self::assertSame('Comment', $sheet->getCell('B3')->getValue());
|
||||||
|
$comment = $sheet->getComment('B3');
|
||||||
|
// Created as "threaded comment" with Excel 365, not quite as expected.
|
||||||
|
self::assertStringContainsString('This is a comment', (string) $comment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLoadXlsxSheet2Styles(): void
|
||||||
|
{
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$spreadsheet = $reader->load(self::$testbook);
|
||||||
|
$sheet = $spreadsheet->getSheet(1);
|
||||||
|
self::assertEquals('Second', $sheet->getTitle());
|
||||||
|
if (strpos(__FILE__, 'NonStd') !== false) {
|
||||||
|
self::markTestIncomplete('Not yet ready');
|
||||||
|
}
|
||||||
|
self::assertEquals('center', $sheet->getCell('A2')->getStyle()->getAlignment()->getHorizontal());
|
||||||
|
self::assertSame('inherit', $sheet->getCell('A2')->getStyle()->getProtection()->getLocked());
|
||||||
|
self::assertEquals('top', $sheet->getCell('A3')->getStyle()->getAlignment()->getVertical());
|
||||||
|
self::assertSame('unprotected', $sheet->getCell('A3')->getStyle()->getProtection()->getLocked());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Reader\Xlsx;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Shared\File;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class WorksheetInfoNamesTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testListWorksheetInfo(): void
|
||||||
|
{
|
||||||
|
$filename = 'tests/data/Reader/XLSX/rowColumnAttributeTest.xlsx';
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$actual = $reader->listWorksheetInfo($filename);
|
||||||
|
|
||||||
|
$expected = [
|
||||||
|
[
|
||||||
|
'worksheetName' => 'Sheet1',
|
||||||
|
'lastColumnLetter' => 'F',
|
||||||
|
'lastColumnIndex' => 5,
|
||||||
|
'totalRows' => '6',
|
||||||
|
'totalColumns' => 6,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
self::assertEquals($expected, $actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testListWorksheetInfoNamespace(): void
|
||||||
|
{
|
||||||
|
$filename = 'tests/data/Reader/XLSX/namespaces.xlsx';
|
||||||
|
$file = 'zip://';
|
||||||
|
$file .= $filename;
|
||||||
|
$file .= '#xl/workbook.xml';
|
||||||
|
$data = file_get_contents($file);
|
||||||
|
// confirm that file contains expected namespaced xml tag
|
||||||
|
if ($data === false) {
|
||||||
|
self::fail('Unable to read file');
|
||||||
|
} else {
|
||||||
|
self::assertStringContainsString('<x:workbook ', $data);
|
||||||
|
}
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$actual = $reader->listWorksheetInfo($filename);
|
||||||
|
|
||||||
|
$expected = [
|
||||||
|
[
|
||||||
|
'worksheetName' => 'transactions',
|
||||||
|
'lastColumnLetter' => 'K',
|
||||||
|
'lastColumnIndex' => 10,
|
||||||
|
'totalRows' => 2,
|
||||||
|
'totalColumns' => 11,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
self::assertEquals($expected, $actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testListWorksheetNames(): void
|
||||||
|
{
|
||||||
|
$filename = 'tests/data/Reader/XLSX/rowColumnAttributeTest.xlsx';
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$actual = $reader->listWorksheetNames($filename);
|
||||||
|
|
||||||
|
$expected = ['Sheet1'];
|
||||||
|
|
||||||
|
self::assertEquals($expected, $actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testListWorksheetNamesNamespace(): void
|
||||||
|
{
|
||||||
|
$filename = 'tests/data/Reader/XLSX/namespaces.xlsx';
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$actual = $reader->listWorksheetNames($filename);
|
||||||
|
|
||||||
|
$expected = ['transactions'];
|
||||||
|
|
||||||
|
self::assertEquals($expected, $actual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -15,25 +15,6 @@ use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
class XlsxTest extends TestCase
|
class XlsxTest extends TestCase
|
||||||
{
|
{
|
||||||
public function testListWorksheetInfo(): void
|
|
||||||
{
|
|
||||||
$filename = 'tests/data/Reader/XLSX/rowColumnAttributeTest.xlsx';
|
|
||||||
$reader = new Xlsx();
|
|
||||||
$actual = $reader->listWorksheetInfo($filename);
|
|
||||||
|
|
||||||
$expected = [
|
|
||||||
[
|
|
||||||
'worksheetName' => 'Sheet1',
|
|
||||||
'lastColumnLetter' => 'F',
|
|
||||||
'lastColumnIndex' => 5,
|
|
||||||
'totalRows' => '6',
|
|
||||||
'totalColumns' => 6,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
self::assertEquals($expected, $actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testLoadXlsxRowColumnAttributes(): void
|
public function testLoadXlsxRowColumnAttributes(): void
|
||||||
{
|
{
|
||||||
$filename = 'tests/data/Reader/XLSX/rowColumnAttributeTest.xlsx';
|
$filename = 'tests/data/Reader/XLSX/rowColumnAttributeTest.xlsx';
|
||||||
|
|
|
||||||
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