Merge branch 'master' into simple-cache-2
This commit is contained in:
commit
d93f1b2800
|
|
@ -26,7 +26,7 @@ $config
|
|||
'combine_consecutive_issets' => true,
|
||||
'combine_consecutive_unsets' => true,
|
||||
'combine_nested_dirname' => true,
|
||||
'comment_to_phpdoc' => true,
|
||||
'comment_to_phpdoc' => false, // interferes with annotations
|
||||
'compact_nullable_typehint' => true,
|
||||
'concat_space' => ['spacing' => 'one'],
|
||||
'constant_case' => true,
|
||||
|
|
@ -171,7 +171,7 @@ $config
|
|||
'phpdoc_separation' => true,
|
||||
'phpdoc_single_line_var_spacing' => true,
|
||||
'phpdoc_summary' => true,
|
||||
'phpdoc_to_comment' => true,
|
||||
'phpdoc_to_comment' => false, // interferes with annotations
|
||||
'phpdoc_to_param_type' => false, // Because experimental, but interesting for one shot use
|
||||
'phpdoc_to_return_type' => false, // idem
|
||||
'phpdoc_trim' => true,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
|||
|
||||
### Added
|
||||
|
||||
- Implementation of the ISREF() information function.
|
||||
- Implementation of the UNIQUE() Lookup/Reference (array) function
|
||||
- Implementation of the ISREF() Information function.
|
||||
- Added support for reading "formatted" numeric values from Csv files; although default behaviour of reading these values as strings is preserved.
|
||||
|
||||
(i.e a value of "12,345.67" can be read as numeric `1235.67`, not simply as a string `"12,345.67"`, if the `castFormattedNumberToNumeric()` setting is enabled.
|
||||
|
|
@ -40,6 +41,12 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
|||
|
||||
### Fixed
|
||||
|
||||
- Update Conditional Formatting ranges and rule conditions when inserting/deleting rows/columns [Issue #2678](https://github.com/PHPOffice/PhpSpreadsheet/issues/2678) [PR #2689](https://github.com/PHPOffice/PhpSpreadsheet/pull/2689)
|
||||
- Allow `INDIRECT()` to accept row/column ranges as well as cell ranges [PR #2687](https://github.com/PHPOffice/PhpSpreadsheet/pull/2687)
|
||||
- Fix bug when deleting cells with hyperlinks, where the hyperlink was then being "inherited" by whatever cell moved to that cell address.
|
||||
- Fix bug in Conditional Formatting in the Xls Writer that resulted in a broken file when there were multiple conditional ranges in a worksheet.
|
||||
- Fix Conditional Formatting in the Xls Writer to work with rules that contain string literals, cell references and formulae.
|
||||
- Fix for setting Active Sheet to the first loaded worksheet when bookViews element isn't defined [Issue #2666](https://github.com/PHPOffice/PhpSpreadsheet/issues/2666) [PR #2669](https://github.com/PHPOffice/PhpSpreadsheet/pull/2669)
|
||||
- Fixed behaviour of XLSX font style vertical align settings.
|
||||
- Resolved formula translations to handle separators (row and column) for array functions as well as for function argument separators; and cleanly handle nesting levels.
|
||||
|
||||
|
|
|
|||
|
|
@ -150,16 +150,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/Calculation.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$str of function trim expects string, int\\|string given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/Calculation.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$str of function trim expects string, null given\\.$#"
|
||||
count: 2
|
||||
path: src/PhpSpreadsheet/Calculation/Calculation.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$worksheet of static method PhpOffice\\\\PhpSpreadsheet\\\\DefinedName\\:\\:resolveName\\(\\) expects PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet, PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\|null given\\.$#"
|
||||
count: 1
|
||||
|
|
@ -355,21 +345,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/Engineering/BesselK.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Engineering\\\\BitWise\\:\\:validateBitwiseArgument\\(\\) never returns int so it can be removed from the return type\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/Engineering/BitWise.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$number of function floor expects float, float\\|int\\<0, 281474976710655\\>\\|string given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/Engineering/BitWise.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$number of function floor expects float, float\\|int\\|string given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/Engineering/BitWise.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Engineering\\\\ConvertBase\\:\\:validatePlaces\\(\\) has parameter \\$places with no type specified\\.$#"
|
||||
count: 1
|
||||
|
|
@ -820,16 +795,6 @@ parameters:
|
|||
count: 3
|
||||
path: src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$low of function range expects float\\|int\\|string, string\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$high of function range expects float\\|int\\|string, string\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\LookupRef\\\\VLookup\\:\\:vlookupSort\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
|
|
@ -1220,16 +1185,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Cell/Coordinate.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$input of function array_chunk expects array, array\\<int, string\\>\\|false given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Cell/Coordinate.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$str of function explode expects string, array\\<int, string\\>\\|string given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Cell/Coordinate.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#4 \\$currentRow of static method PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Coordinate\\:\\:validateRange\\(\\) expects int, string given\\.$#"
|
||||
count: 1
|
||||
|
|
@ -1910,11 +1865,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Helper/Html.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$function of function call_user_func expects callable\\(\\)\\: mixed, array\\{\\$this\\(PhpOffice\\\\PhpSpreadsheet\\\\Helper\\\\Html\\), mixed\\} given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Helper/Html.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$text of method PhpOffice\\\\PhpSpreadsheet\\\\RichText\\\\ITextElement\\:\\:setText\\(\\) expects string, string\\|null given\\.$#"
|
||||
count: 1
|
||||
|
|
@ -2485,11 +2435,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xls/MD5.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$input of function array_values expects array, array\\|false given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Reader/Xls/MD5.php
|
||||
|
||||
-
|
||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xls\\\\RC4\\:\\:\\$i has no type specified\\.$#"
|
||||
count: 1
|
||||
|
|
@ -3220,31 +3165,11 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/ReferenceHelper.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$index of method PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\RowDimension\\:\\:setRowIndex\\(\\) expects int, string given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/ReferenceHelper.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$callback of function uksort expects callable\\(\\(int\\|string\\), \\(int\\|string\\)\\)\\: int, array\\{'self', 'cellReverseSort'\\} given\\.$#"
|
||||
count: 4
|
||||
path: src/PhpSpreadsheet/ReferenceHelper.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$callback of function uksort expects callable\\(\\(int\\|string\\), \\(int\\|string\\)\\)\\: int, array\\{'self', 'cellSort'\\} given\\.$#"
|
||||
count: 4
|
||||
path: src/PhpSpreadsheet/ReferenceHelper.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$subject of function str_replace expects array\\|string, string\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/ReferenceHelper.php
|
||||
|
||||
-
|
||||
message: "#^Static property PhpOffice\\\\PhpSpreadsheet\\\\ReferenceHelper\\:\\:\\$instance \\(PhpOffice\\\\PhpSpreadsheet\\\\ReferenceHelper\\) in isset\\(\\) is not nullable\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/ReferenceHelper.php
|
||||
|
||||
-
|
||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\RichText\\\\Run\\:\\:\\$font \\(PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\) does not accept PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
||||
count: 1
|
||||
|
|
@ -3300,71 +3225,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Shared/Drawing.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Drawing\\:\\:imagecreatefrombmp\\(\\) should return GdImage\\|resource but returns resource\\|false\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Shared/Drawing.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$fp of function feof expects resource, resource\\|false given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Shared/Drawing.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$fp of function fread expects resource, resource\\|false given\\.$#"
|
||||
count: 2
|
||||
path: src/PhpSpreadsheet/Shared/Drawing.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$im of function imagecolorallocate expects resource, resource\\|false given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Shared/Drawing.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$im of function imagesetpixel expects resource, resource\\|false given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Shared/Drawing.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$x_size of function imagecreatetruecolor expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Shared/Drawing.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$data of function unpack expects string, string\\|false given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Shared/Drawing.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$red of function imagecolorallocate expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Shared/Drawing.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$y_size of function imagecreatetruecolor expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Shared/Drawing.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$green of function imagecolorallocate expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Shared/Drawing.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$y of function imagesetpixel expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Shared/Drawing.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#4 \\$blue of function imagecolorallocate expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Shared/Drawing.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#4 \\$col of function imagesetpixel expects int, int\\|false given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Shared/Drawing.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Escher\\\\DgContainer\\:\\:getDgId\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
|
|
@ -3560,11 +3420,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Shared/JAMA/Matrix.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$str of function trim expects string, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Shared/JAMA/Matrix.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$c of method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\JAMA\\\\Matrix\\:\\:set\\(\\) expects float\\|int\\|null, string given\\.$#"
|
||||
count: 2
|
||||
|
|
@ -3610,11 +3465,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Shared/OLE.php
|
||||
|
||||
-
|
||||
message: "#^Cannot use array destructuring on array\\|false\\.$#"
|
||||
count: 3
|
||||
path: src/PhpSpreadsheet/Shared/OLE.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\:\\:getData\\(\\) should return string but returns string\\|false\\.$#"
|
||||
count: 1
|
||||
|
|
@ -3640,11 +3490,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Shared/OLE.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$data of function unpack expects string, string\\|false given\\.$#"
|
||||
count: 3
|
||||
path: src/PhpSpreadsheet/Shared/OLE.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$name of class PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\OLE\\\\PPS constructor expects string, null given\\.$#"
|
||||
count: 1
|
||||
|
|
@ -3680,11 +3525,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Shared/OLE.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$var of function count expects array\\|Countable, string given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Shared/OLE/ChainedBlockStream.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$offset of function array_slice expects int, float given\\.$#"
|
||||
count: 1
|
||||
|
|
@ -4025,11 +3865,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Shared/Trend/PolynomialBestFit.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\.\\.\\.\\$args of function array_merge expects array, float given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Shared/Trend/PolynomialBestFit.php
|
||||
|
||||
-
|
||||
message: "#^Call to an undefined method object\\:\\:getGoodnessOfFit\\(\\)\\.$#"
|
||||
count: 1
|
||||
|
|
@ -4310,11 +4145,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Style/NumberFormat/DateFormatter.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$str of function explode expects string, string\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Style/NumberFormat/DateFormatter.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$subject of function preg_replace expects array\\|string, string\\|null given\\.$#"
|
||||
count: 1
|
||||
|
|
@ -4390,26 +4220,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Style/NumberFormat/PercentageFormatter.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getCell\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\|null\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Worksheet/BaseDrawing.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getDrawingCollection\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\|null\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Worksheet/BaseDrawing.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getHashCode\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\|null\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Worksheet/BaseDrawing.php
|
||||
|
||||
-
|
||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\BaseDrawing\\:\\:\\$shadow \\(PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Drawing\\\\Shadow\\) does not accept PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Drawing\\\\Shadow\\|null\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Worksheet/BaseDrawing.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\CellIterator\\:\\:adjustForExistingOnlyRange\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
|
|
@ -4435,11 +4245,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Worksheet/PageSetup.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$str of function explode expects string, string\\|null given\\.$#"
|
||||
count: 5
|
||||
path: src/PhpSpreadsheet/Worksheet/PageSetup.php
|
||||
|
||||
-
|
||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\PageSetup\\:\\:\\$pageOrder has no type specified\\.$#"
|
||||
count: 1
|
||||
|
|
@ -4485,11 +4290,6 @@ parameters:
|
|||
count: 4
|
||||
path: src/PhpSpreadsheet/Worksheet/Worksheet.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getValue\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\DefinedName\\|null\\.$#"
|
||||
count: 2
|
||||
path: src/PhpSpreadsheet/Worksheet/Worksheet.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getWorksheet\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\DefinedName\\|null\\.$#"
|
||||
count: 1
|
||||
|
|
@ -4530,11 +4330,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Worksheet/Worksheet.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$input of function array_splice expects array, ArrayObject\\<int, PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Chart\\> given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Worksheet/Worksheet.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$range of static method PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Coordinate\\:\\:rangeDimension\\(\\) expects string, string\\|false given\\.$#"
|
||||
count: 1
|
||||
|
|
@ -4555,11 +4350,6 @@ parameters:
|
|||
count: 2
|
||||
path: src/PhpSpreadsheet/Worksheet/Worksheet.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$start of function substr expects int, int\\<0, max\\>\\|false given\\.$#"
|
||||
count: 2
|
||||
path: src/PhpSpreadsheet/Worksheet/Worksheet.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$rotation of static method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Font\\:\\:calculateColumnWidth\\(\\) expects int, int\\|null given\\.$#"
|
||||
count: 1
|
||||
|
|
@ -4880,16 +4670,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Writer/Html.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$im of function imagepng expects resource, GdImage\\|resource given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Writer/Html.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$str of function base64_encode expects string, string\\|false given\\.$#"
|
||||
count: 2
|
||||
path: src/PhpSpreadsheet/Writer/Html.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$string of function htmlspecialchars expects string, string\\|null given\\.$#"
|
||||
count: 1
|
||||
|
|
@ -5015,16 +4795,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Writer/Xls.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$im of function imagepng expects resource, GdImage\\|resource given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Writer/Xls.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$im of function imagepng expects resource, resource\\|false given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Writer/Xls.php
|
||||
|
||||
-
|
||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xls\\:\\:\\$documentSummaryInformation \\(string\\) in isset\\(\\) is not nullable\\.$#"
|
||||
count: 1
|
||||
|
|
@ -5205,11 +4975,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$im of function imagecolorat expects resource, GdImage\\|resource given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$string of function strlen expects string, string\\|false given\\.$#"
|
||||
count: 1
|
||||
|
|
@ -5220,26 +4985,11 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$col of function imagecolorsforindex expects int, int\\|false given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$data of function unpack expects string, string\\|false given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$length of function fread expects int\\<0, max\\>, int\\<0, max\\>\\|false given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$pieces of function implode expects array, array\\<int, string\\>\\|false given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Writer/Xls/Worksheet.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$subject of function preg_match expects string, string\\|null given\\.$#"
|
||||
count: 2
|
||||
|
|
@ -5320,11 +5070,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Writer/Xlsx.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$function of function call_user_func expects callable\\(\\)\\: mixed, string given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Writer/Xlsx.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$path of function basename expects string, array\\|string\\|null given\\.$#"
|
||||
count: 1
|
||||
|
|
@ -5485,36 +5230,6 @@ parameters:
|
|||
count: 2
|
||||
path: src/PhpSpreadsheet/Writer/Xlsx/DocProps.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$coordinates of static method PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Coordinate\\:\\:indexesFromString\\(\\) expects string, string\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Writer/Xlsx/Drawing.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$index of method PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\:\\:getChartByIndex\\(\\) expects string, int\\<0, max\\> given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Writer/Xlsx/Drawing.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$chart of method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xlsx\\\\Drawing\\:\\:writeChart\\(\\) expects PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Chart, PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Chart\\|false given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Writer/Xlsx/Drawing.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$content of method XMLWriter\\:\\:writeElement\\(\\) expects string\\|null, int given\\.$#"
|
||||
count: 20
|
||||
path: src/PhpSpreadsheet/Writer/Xlsx/Drawing.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, int given\\.$#"
|
||||
count: 10
|
||||
path: src/PhpSpreadsheet/Writer/Xlsx/Drawing.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$value of method XMLWriter\\:\\:writeAttribute\\(\\) expects string, int\\<0, max\\> given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Writer/Xlsx/Drawing.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xlsx\\\\Rels\\:\\:writeUnparsedRelationship\\(\\) has parameter \\$relationship with no type specified\\.$#"
|
||||
count: 1
|
||||
|
|
@ -5769,248 +5484,3 @@ parameters:
|
|||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xlsx\\\\Xlfn\\:\\:addXlfn\\(\\) should return string but returns string\\|null\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Writer/Xlsx/Xlfn.php
|
||||
|
||||
-
|
||||
message: "#^Unreachable statement \\- code above always terminates\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Calculation/Engine/RangeTest.php
|
||||
|
||||
-
|
||||
message: "#^Call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertSame\\(\\) with arguments PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Cell, null and 'should get exact…' will always evaluate to false\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Collection/CellsTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getCoordinate\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Cell\\|null\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Collection/CellsTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getParent\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Cell\\\\Cell\\|null\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Collection/CellsTest.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheetTests\\\\Functional\\\\ColumnWidthTest\\:\\:testReadColumnWidth\\(\\) has parameter \\$format with no type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Functional/ColumnWidthTest.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheetTests\\\\Functional\\\\CommentsTest\\:\\:testComments\\(\\) has parameter \\$format with no type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Functional/CommentsTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getPageSetup\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\|null\\.$#"
|
||||
count: 5
|
||||
path: tests/PhpSpreadsheetTests/Functional/PrintAreaTest.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$expected of static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertInstanceOf\\(\\) expects class\\-string\\<object\\>, string given\\.$#"
|
||||
count: 3
|
||||
path: tests/PhpSpreadsheetTests/IOFactoryTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getValue\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\NamedFormula\\|null\\.$#"
|
||||
count: 5
|
||||
path: tests/PhpSpreadsheetTests/NamedFormulaTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getValue\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\NamedRange\\|null\\.$#"
|
||||
count: 5
|
||||
path: tests/PhpSpreadsheetTests/NamedRangeTest.php
|
||||
|
||||
-
|
||||
message: "#^Property PhpOffice\\\\PhpSpreadsheetTests\\\\Reader\\\\Ods\\\\OdsTest\\:\\:\\$spreadsheetData \\(PhpOffice\\\\PhpSpreadsheet\\\\Spreadsheet\\) in isset\\(\\) is not nullable\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Reader/Ods/OdsTest.php
|
||||
|
||||
-
|
||||
message: "#^Property PhpOffice\\\\PhpSpreadsheetTests\\\\Reader\\\\Ods\\\\OdsTest\\:\\:\\$spreadsheetOdsTest \\(PhpOffice\\\\PhpSpreadsheet\\\\Spreadsheet\\) in isset\\(\\) is not nullable\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Reader/Ods/OdsTest.php
|
||||
|
||||
-
|
||||
message: "#^Unreachable statement \\- code above always terminates\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Reader/Ods/OdsTest.php
|
||||
|
||||
-
|
||||
message: "#^Argument of an invalid type array\\<int, string\\>\\|false supplied for foreach, only iterables are supported\\.$#"
|
||||
count: 3
|
||||
path: tests/PhpSpreadsheetTests/Reader/Security/XmlScannerTest.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheetTests\\\\Reader\\\\Security\\\\XmlScannerTest\\:\\:testInvalidXML\\(\\) has parameter \\$libxmlDisableEntityLoader with no type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Reader/Security/XmlScannerTest.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheetTests\\\\Reader\\\\Security\\\\XmlScannerTest\\:\\:testValidXML\\(\\) has parameter \\$libxmlDisableEntityLoader with no type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Reader/Security/XmlScannerTest.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheetTests\\\\Reader\\\\Xlsx\\\\AutoFilterTest\\:\\:getAutoFilterInstance\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Reader/Xlsx/AutoFilterTest.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheetTests\\\\Reader\\\\Xlsx\\\\AutoFilterTest\\:\\:getWorksheetInstance\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Reader/Xlsx/AutoFilterTest.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheetTests\\\\Reader\\\\Xlsx\\\\AutoFilterTest\\:\\:getXMLInstance\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Reader/Xlsx/AutoFilterTest.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheetTests\\\\Reader\\\\Xlsx\\\\AutoFilterTest\\:\\:getXMLInstance\\(\\) has parameter \\$ref with no type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Reader/Xlsx/AutoFilterTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getTitle\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Chart\\|null\\.$#"
|
||||
count: 5
|
||||
path: tests/PhpSpreadsheetTests/Reader/Xlsx/ChartsTitleTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getXAxisLabel\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Chart\\|null\\.$#"
|
||||
count: 5
|
||||
path: tests/PhpSpreadsheetTests/Reader/Xlsx/ChartsTitleTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getYAxisLabel\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Chart\\|null\\.$#"
|
||||
count: 5
|
||||
path: tests/PhpSpreadsheetTests/Reader/Xlsx/ChartsTitleTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getColor\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalDataBar\\|null\\.$#"
|
||||
count: 5
|
||||
path: tests/PhpSpreadsheetTests/Reader/Xlsx/ConditionalFormattingDataBarXlsxTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getConditionalFormattingRuleExt\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalDataBar\\|null\\.$#"
|
||||
count: 8
|
||||
path: tests/PhpSpreadsheetTests/Reader/Xlsx/ConditionalFormattingDataBarXlsxTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getMaximumConditionalFormatValueObject\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalDataBar\\|null\\.$#"
|
||||
count: 13
|
||||
path: tests/PhpSpreadsheetTests/Reader/Xlsx/ConditionalFormattingDataBarXlsxTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getMinimumConditionalFormatValueObject\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalDataBar\\|null\\.$#"
|
||||
count: 13
|
||||
path: tests/PhpSpreadsheetTests/Reader/Xlsx/ConditionalFormattingDataBarXlsxTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getShowValue\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalDataBar\\|null\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Reader/Xlsx/ConditionalFormattingDataBarXlsxTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method setMinimumConditionalFormatValueObject\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\ConditionalFormatting\\\\ConditionalDataBar\\|null\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Reader/Xlsx/ConditionalFormattingDataBarXlsxTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getPlotArea\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Chart\\|null\\.$#"
|
||||
count: 2
|
||||
path: tests/PhpSpreadsheetTests/Reader/Xlsx/SheetsXlsxChartTest.php
|
||||
|
||||
-
|
||||
message: "#^Argument of an invalid type array\\<int, string\\>\\|false supplied for foreach, only iterables are supported\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Reader/Xml/XmlTest.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheetTests\\\\Reader\\\\Xml\\\\XmlTest\\:\\:testInvalidSimpleXML\\(\\) has parameter \\$filename with no type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Reader/Xml/XmlTest.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$currencyCode of static method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\StringHelper\\:\\:setCurrencyCode\\(\\) expects string, null given\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Shared/StringHelperTest.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheetTests\\\\SpreadsheetTest\\:\\:testGetSheetByName\\(\\) has parameter \\$index with no type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/SpreadsheetTest.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheetTests\\\\SpreadsheetTest\\:\\:testGetSheetByName\\(\\) has parameter \\$sheetName with no type specified\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/SpreadsheetTest.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$value of method PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\AutoFilter\\\\Column\\:\\:setAttribute\\(\\) expects string, int given\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Worksheet/AutoFilter/ColumnTest.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$rowIndex of class PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\RowCellIterator constructor expects int, string given\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Worksheet/RowCellIterator2Test.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheetTests\\\\Writer\\\\Html\\\\CallbackTest\\:\\:yellowBody\\(\\) should return string but returns string\\|null\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Writer/Html/CallbackTest.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$haystack of function strpos expects string, string\\|false given\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Writer/Html/CallbackTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getColor\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
||||
count: 3
|
||||
path: tests/PhpSpreadsheetTests/Writer/Html/GridlinesTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method setSubScript\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
||||
count: 3
|
||||
path: tests/PhpSpreadsheetTests/Writer/Html/GridlinesTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method setSuperScript\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Writer/Html/GridlinesTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method setBold\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Style\\\\Font\\|null\\.$#"
|
||||
count: 3
|
||||
path: tests/PhpSpreadsheetTests/Writer/Html/HtmlCommentsTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getCell\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\|null\\.$#"
|
||||
count: 4
|
||||
path: tests/PhpSpreadsheetTests/Writer/Xlsx/UnparsedDataCloneTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getDrawingCollection\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\Worksheet\\|null\\.$#"
|
||||
count: 4
|
||||
path: tests/PhpSpreadsheetTests/Writer/Xlsx/UnparsedDataCloneTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access property \\$pageSetup on SimpleXMLElement\\|false\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Writer/Xlsx/UnparsedDataTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access property \\$sheetProtection on SimpleXMLElement\\|false\\.$#"
|
||||
count: 5
|
||||
path: tests/PhpSpreadsheetTests/Writer/Xlsx/UnparsedDataTest.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$data of function simplexml_load_string expects string, string\\|false given\\.$#"
|
||||
count: 2
|
||||
path: tests/PhpSpreadsheetTests/Writer/Xlsx/UnparsedDataTest.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getExtension\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\BaseDrawing\\|null\\.$#"
|
||||
count: 2
|
||||
path: tests/PhpSpreadsheetTests/Writer/Xlsx/WmfTest.php
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
// Create new Spreadsheet object
|
||||
use PhpOffice\PhpSpreadsheet\Helper\Dimension;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
|
||||
|
||||
require __DIR__ . '/../Header.php';
|
||||
|
||||
$helper->log('Create new Spreadsheet object');
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$sheet->getCell('A1')->setValue('twocell');
|
||||
$sheet->getCell('A2')->setValue('twocell');
|
||||
$sheet->getCell('A3')->setValue('onecell');
|
||||
$sheet->getCell('A6')->setValue('absolute');
|
||||
|
||||
// Add a drawing to the worksheet
|
||||
$helper->log('Add a drawing to the worksheet two-cell anchor not resized');
|
||||
$drawing = new Drawing();
|
||||
$drawing->setName('PhpSpreadsheet');
|
||||
$drawing->setDescription('PhpSpreadsheet');
|
||||
$drawing->setPath(__DIR__ . '/../images/PhpSpreadsheet_logo.png');
|
||||
// anchor type will be two-cell because Coordinates2 is set
|
||||
//$drawing->setAnchorType(Drawing::ANCHORTYPE_TWOCELL);
|
||||
$drawing->setCoordinates('B1');
|
||||
$drawing->setCoordinates2('B1');
|
||||
$drawing->setOffsetX2($drawing->getImageWidth());
|
||||
$drawing->setOffsetY2($drawing->getImageHeight());
|
||||
$drawing->setWorksheet($spreadsheet->getActiveSheet());
|
||||
|
||||
// Add a drawing to the worksheet
|
||||
$helper->log('Add a drawing to the worksheet two-cell anchor resized');
|
||||
$drawing2 = new Drawing();
|
||||
$drawing2->setName('PhpSpreadsheet');
|
||||
$drawing2->setDescription('PhpSpreadsheet');
|
||||
$drawing2->setPath(__DIR__ . '/../images/PhpSpreadsheet_logo.png');
|
||||
// anchor type will be two-cell because Coordinates2 is set
|
||||
//$drawing->setAnchorType(Drawing::ANCHORTYPE_TWOCELL);
|
||||
$drawing2->setCoordinates('C2');
|
||||
$drawing2->setCoordinates2('C2');
|
||||
$drawing2->setOffsetX2($drawing->getImageWidth());
|
||||
$drawing2->setOffsetY2($drawing->getImageHeight());
|
||||
$drawing2->setWorksheet($spreadsheet->getActiveSheet());
|
||||
|
||||
$spreadsheet->getActiveSheet()->getColumnDimension('C')->setWidth($drawing->getImageWidth(), Dimension::UOM_PIXELS);
|
||||
$spreadsheet->getActiveSheet()->getRowDimension(2)->setRowHeight($drawing->getImageHeight(), Dimension::UOM_PIXELS);
|
||||
|
||||
// Add a drawing to the worksheet one cell anchor
|
||||
$helper->log('Add a drawing to the worksheet one-cell anchor');
|
||||
$drawing3 = new Drawing();
|
||||
$drawing3->setName('PhpSpreadsheet');
|
||||
$drawing3->setDescription('PhpSpreadsheet');
|
||||
$drawing3->setPath(__DIR__ . '/../images/PhpSpreadsheet_logo.png');
|
||||
// anchor type will be one-cell because Coordinates2 is not set
|
||||
//$drawing->setAnchorType(Drawing::ANCHORTYPE_ONECELL);
|
||||
$drawing3->setCoordinates('D3');
|
||||
$drawing3->setWorksheet($spreadsheet->getActiveSheet());
|
||||
|
||||
// Add a drawing to the worksheet
|
||||
$helper->log('Add a drawing to the worksheet two-cell anchor resized absolute');
|
||||
$drawing4 = new Drawing();
|
||||
$drawing4->setName('PhpSpreadsheet');
|
||||
$drawing4->setDescription('PhpSpreadsheet');
|
||||
$drawing4->setPath(__DIR__ . '/../images/PhpSpreadsheet_logo.png');
|
||||
// anchor type will be two-cell because Coordinates2 is set
|
||||
//$drawing->setAnchorType(Drawing::ANCHORTYPE_TWOCELL);
|
||||
$drawing4->setCoordinates('C6');
|
||||
$drawing4->setCoordinates2('C6');
|
||||
$drawing4->setOffsetX2($drawing->getImageWidth());
|
||||
$drawing4->setOffsetY2($drawing->getImageHeight());
|
||||
$drawing4->setWorksheet($spreadsheet->getActiveSheet());
|
||||
$drawing4->setEditAs(Drawing::EDIT_AS_ABSOLUTE);
|
||||
|
||||
//$spreadsheet->getActiveSheet()->getColumnDimension('C')->setWidth($drawing->getImageWidth(), Dimension::UOM_PIXELS);
|
||||
$spreadsheet->getActiveSheet()->getRowDimension(6)->setRowHeight($drawing->getImageHeight(), Dimension::UOM_PIXELS);
|
||||
|
||||
$helper->write($spreadsheet, __FILE__, ['Xlsx']);
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
|
|
@ -71,7 +71,7 @@ $series = new DataSeries(
|
|||
// Set the series in the plot area
|
||||
$plotArea = new PlotArea(null, [$series]);
|
||||
// Set the chart legend
|
||||
$legend = new Legend(Legend::POSITION_TOPRIGHT, null, false);
|
||||
$legend = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false);
|
||||
|
||||
$title = new Title('Test %age-Stacked Area Chart');
|
||||
$yAxisLabel = new Title('Value ($k)');
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
|
|
@ -74,7 +74,7 @@ $series->setPlotDirection(DataSeries::DIRECTION_BAR);
|
|||
// Set the series in the plot area
|
||||
$plotArea = new PlotArea(null, [$series]);
|
||||
// Set the chart legend
|
||||
$legend = new Legend(Legend::POSITION_RIGHT, null, false);
|
||||
$legend = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false);
|
||||
|
||||
$title = new Title('Test Chart');
|
||||
$yAxisLabel = new Title('Value ($k)');
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
|
|
@ -74,7 +74,7 @@ $series->setPlotDirection(DataSeries::DIRECTION_COL);
|
|||
// Set the series in the plot area
|
||||
$plotArea = new PlotArea(null, [$series]);
|
||||
// Set the chart legend
|
||||
$legend = new Legend(Legend::POSITION_RIGHT, null, false);
|
||||
$legend = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false);
|
||||
|
||||
$title = new Title('Test Column Chart');
|
||||
$yAxisLabel = new Title('Value ($k)');
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
|
|
@ -82,7 +82,7 @@ $series->setPlotDirection(DataSeries::DIRECTION_COL);
|
|||
// Set the series in the plot area
|
||||
$plotArea = new PlotArea(null, [$series]);
|
||||
// Set the chart legend
|
||||
$legend = new Legend(Legend::POSITION_BOTTOM, null, false);
|
||||
$legend = new ChartLegend(ChartLegend::POSITION_BOTTOM, null, false);
|
||||
|
||||
$title = new Title('Test Grouped Column Chart');
|
||||
$xAxisLabel = new Title('Financial Period');
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
|
|
@ -128,7 +128,7 @@ $series3 = new DataSeries(
|
|||
// Set the series in the plot area
|
||||
$plotArea = new PlotArea(null, [$series1, $series2, $series3]);
|
||||
// Set the chart legend
|
||||
$legend = new Legend(Legend::POSITION_RIGHT, null, false);
|
||||
$legend = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false);
|
||||
|
||||
$title = new Title('Average Weather Chart for Crete');
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
|
|
@ -72,7 +72,7 @@ $series = new DataSeries(
|
|||
// Set the series in the plot area
|
||||
$plotArea = new PlotArea(null, [$series]);
|
||||
// Set the chart legend
|
||||
$legend = new Legend(Legend::POSITION_TOPRIGHT, null, false);
|
||||
$legend = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false);
|
||||
|
||||
$title = new Title('Test Stacked Line Chart');
|
||||
$yAxisLabel = new Title('Value ($k)');
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
|
|
@ -71,7 +71,7 @@ $series1 = new DataSeries(
|
|||
// Set the series in the plot area
|
||||
$plotArea1 = new PlotArea(null, [$series1]);
|
||||
// Set the chart legend
|
||||
$legend1 = new Legend(Legend::POSITION_TOPRIGHT, null, false);
|
||||
$legend1 = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false);
|
||||
|
||||
$title1 = new Title('Test %age-Stacked Area Chart');
|
||||
$yAxisLabel1 = new Title('Value ($k)');
|
||||
|
|
@ -146,7 +146,7 @@ $series2->setPlotDirection(DataSeries::DIRECTION_COL);
|
|||
// Set the series in the plot area
|
||||
$plotArea2 = new PlotArea(null, [$series2]);
|
||||
// Set the chart legend
|
||||
$legend2 = new Legend(Legend::POSITION_RIGHT, null, false);
|
||||
$legend2 = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false);
|
||||
|
||||
$title2 = new Title('Test Column Chart');
|
||||
$yAxisLabel2 = new Title('Value ($k)');
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
|||
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Layout;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
|
|
@ -73,7 +73,7 @@ $layout1->setShowPercent(true);
|
|||
// Set the series in the plot area
|
||||
$plotArea1 = new PlotArea($layout1, [$series1]);
|
||||
// Set the chart legend
|
||||
$legend1 = new Legend(Legend::POSITION_RIGHT, null, false);
|
||||
$legend1 = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false);
|
||||
|
||||
$title1 = new Title('Test Pie Chart');
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
|||
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Layout;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
|
|
@ -79,7 +79,7 @@ $layout1->setShowPercent(true);
|
|||
// Set the series in the plot area
|
||||
$plotArea1 = new PlotArea($layout1, [$series1]);
|
||||
// Set the chart legend
|
||||
$legend1 = new Legend(Legend::POSITION_RIGHT, null, false);
|
||||
$legend1 = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false);
|
||||
|
||||
$title1 = new Title('Test Pie Chart');
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
|||
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Layout;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
|
|
@ -85,7 +85,7 @@ $layout = new Layout();
|
|||
// Set the series in the plot area
|
||||
$plotArea = new PlotArea($layout, [$series]);
|
||||
// Set the chart legend
|
||||
$legend = new Legend(Legend::POSITION_RIGHT, null, false);
|
||||
$legend = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false);
|
||||
|
||||
$title = new Title('Test Radar Chart');
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
|
|
@ -68,7 +68,7 @@ $series = new DataSeries(
|
|||
// Set the series in the plot area
|
||||
$plotArea = new PlotArea(null, [$series]);
|
||||
// Set the chart legend
|
||||
$legend = new Legend(Legend::POSITION_TOPRIGHT, null, false);
|
||||
$legend = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false);
|
||||
|
||||
$title = new Title('Test Scatter Chart');
|
||||
$yAxisLabel = new Title('Value ($k)');
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
|
|
@ -79,7 +79,7 @@ $series = new DataSeries(
|
|||
// Set the series in the plot area
|
||||
$plotArea = new PlotArea(null, [$series]);
|
||||
// Set the chart legend
|
||||
$legend = new Legend(Legend::POSITION_RIGHT, null, false);
|
||||
$legend = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false);
|
||||
|
||||
$title = new Title('Test Stock Chart');
|
||||
$xAxisLabel = new Title('Counts');
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@ $spreadsheet->getActiveSheet()
|
|||
->setCellValue('A1', 'Literal Value Comparison')
|
||||
->setCellValue('A9', 'Value Comparison with Absolute Cell Reference $H$9')
|
||||
->setCellValue('A17', 'Value Comparison with Relative Cell References')
|
||||
->setCellValue('A23', 'Value Comparison with Formula based on AVERAGE() ± STDEV()');
|
||||
->setCellValue('A23', 'Value Comparison with Formula based on AVERAGE() ± STDEV()')
|
||||
->setCellValue('A30', 'Literal String Value Comparison');
|
||||
|
||||
$dataArray = [
|
||||
[-2, -1, 0, 1, 2],
|
||||
|
|
@ -45,11 +46,18 @@ $betweenDataArray = [
|
|||
[4, 3, 8],
|
||||
];
|
||||
|
||||
$stringArray = [
|
||||
['I'],
|
||||
['Love'],
|
||||
['PHP'],
|
||||
];
|
||||
|
||||
$spreadsheet->getActiveSheet()
|
||||
->fromArray($dataArray, null, 'A2', true)
|
||||
->fromArray($dataArray, null, 'A10', true)
|
||||
->fromArray($betweenDataArray, null, 'A18', true)
|
||||
->fromArray($dataArray, null, 'A24', true)
|
||||
->fromArray($stringArray, null, 'A31', true)
|
||||
->setCellValue('H9', 1);
|
||||
|
||||
// Set title row bold
|
||||
|
|
@ -58,21 +66,31 @@ $spreadsheet->getActiveSheet()->getStyle('A1:E1')->getFont()->setBold(true);
|
|||
$spreadsheet->getActiveSheet()->getStyle('A9:E9')->getFont()->setBold(true);
|
||||
$spreadsheet->getActiveSheet()->getStyle('A17:E17')->getFont()->setBold(true);
|
||||
$spreadsheet->getActiveSheet()->getStyle('A23:E23')->getFont()->setBold(true);
|
||||
$spreadsheet->getActiveSheet()->getStyle('A30:E30')->getFont()->setBold(true);
|
||||
|
||||
// Define some styles for our Conditionals
|
||||
$helper->log('Define some styles for our Conditionals');
|
||||
$yellowStyle = new Style(false, true);
|
||||
$yellowStyle->getFill()
|
||||
->setFillType(Fill::FILL_SOLID)
|
||||
->getStartColor()->setARGB(Color::COLOR_YELLOW);
|
||||
$yellowStyle->getFill()
|
||||
->getEndColor()->setARGB(Color::COLOR_YELLOW);
|
||||
$yellowStyle->getFont()->setColor(new Color(Color::COLOR_BLUE));
|
||||
$greenStyle = new Style(false, true);
|
||||
$greenStyle->getFill()
|
||||
->setFillType(Fill::FILL_SOLID)
|
||||
->getStartColor()->setARGB(Color::COLOR_GREEN);
|
||||
$greenStyle->getFill()
|
||||
->getEndColor()->setARGB(Color::COLOR_GREEN);
|
||||
$greenStyle->getFont()->setColor(new Color(Color::COLOR_DARKRED));
|
||||
$redStyle = new Style(false, true);
|
||||
$redStyle->getFill()
|
||||
->setFillType(Fill::FILL_SOLID)
|
||||
->getStartColor()->setARGB(Color::COLOR_RED);
|
||||
$redStyle->getFill()
|
||||
->getEndColor()->setARGB(Color::COLOR_RED);
|
||||
$redStyle->getFont()->setColor(new Color(Color::COLOR_GREEN));
|
||||
|
||||
// Set conditional formatting rules and styles
|
||||
$helper->log('Define conditional formatting and set styles');
|
||||
|
|
@ -166,6 +184,32 @@ $cellWizard->lessThan('AVERAGE(' . $formulaRange . ')-STDEV(' . $formulaRange .
|
|||
->setStyle($redStyle);
|
||||
$conditionalStyles[] = $cellWizard->getConditional();
|
||||
|
||||
$spreadsheet->getActiveSheet()
|
||||
->getStyle($cellWizard->getCellRange())
|
||||
->setConditionalStyles($conditionalStyles);
|
||||
|
||||
// Set rules for Value Comparison with String Literal
|
||||
$cellRange = 'A31:A33';
|
||||
$formulaRange = implode(
|
||||
':',
|
||||
array_map(
|
||||
[Coordinate::class, 'absoluteCoordinate'],
|
||||
Coordinate::splitRange($cellRange)[0]
|
||||
)
|
||||
);
|
||||
$conditionalStyles = [];
|
||||
$wizardFactory = new Wizard($cellRange);
|
||||
/** @var Wizard\CellValue $cellWizard */
|
||||
$cellWizard = $wizardFactory->newRule(Wizard::CELL_VALUE);
|
||||
|
||||
$cellWizard->equals('LOVE')
|
||||
->setStyle($redStyle);
|
||||
$conditionalStyles[] = $cellWizard->getConditional();
|
||||
|
||||
$cellWizard->equals('PHP')
|
||||
->setStyle($greenStyle);
|
||||
$conditionalStyles[] = $cellWizard->getConditional();
|
||||
|
||||
$spreadsheet->getActiveSheet()
|
||||
->getStyle($cellWizard->getCellRange())
|
||||
->setConditionalStyles($conditionalStyles);
|
||||
|
|
|
|||
|
|
@ -74,14 +74,17 @@ $yellowStyle = new Style(false, true);
|
|||
$yellowStyle->getFill()
|
||||
->setFillType(Fill::FILL_SOLID)
|
||||
->getEndColor()->setARGB(Color::COLOR_YELLOW);
|
||||
$yellowStyle->getFont()->setColor(new Color(Color::COLOR_BLUE));
|
||||
$greenStyle = new Style(false, true);
|
||||
$greenStyle->getFill()
|
||||
->setFillType(Fill::FILL_SOLID)
|
||||
->getEndColor()->setARGB(Color::COLOR_GREEN);
|
||||
$greenStyle->getFont()->setColor(new Color(Color::COLOR_DARKRED));
|
||||
$redStyle = new Style(false, true);
|
||||
$redStyle->getFill()
|
||||
->setFillType(Fill::FILL_SOLID)
|
||||
->getEndColor()->setARGB(Color::COLOR_RED);
|
||||
$redStyle->getFont()->setColor(new Color(Color::COLOR_GREEN));
|
||||
|
||||
// Set conditional formatting rules and styles
|
||||
$helper->log('Define conditional formatting and set styles');
|
||||
|
|
|
|||
|
|
@ -46,10 +46,12 @@ $greenStyle = new Style(false, true);
|
|||
$greenStyle->getFill()
|
||||
->setFillType(Fill::FILL_SOLID)
|
||||
->getEndColor()->setARGB(Color::COLOR_GREEN);
|
||||
$greenStyle->getFont()->setColor(new Color(Color::COLOR_DARKRED));
|
||||
$redStyle = new Style(false, true);
|
||||
$redStyle->getFill()
|
||||
->setFillType(Fill::FILL_SOLID)
|
||||
->getEndColor()->setARGB(Color::COLOR_RED);
|
||||
$redStyle->getFont()->setColor(new Color(Color::COLOR_GREEN));
|
||||
|
||||
// Set conditional formatting rules and styles
|
||||
$helper->log('Define conditional formatting and set styles');
|
||||
|
|
|
|||
|
|
@ -49,10 +49,12 @@ $greenStyle = new Style(false, true);
|
|||
$greenStyle->getFill()
|
||||
->setFillType(Fill::FILL_SOLID)
|
||||
->getEndColor()->setARGB(Color::COLOR_GREEN);
|
||||
$greenStyle->getFont()->setColor(new Color(Color::COLOR_DARKRED));
|
||||
$redStyle = new Style(false, true);
|
||||
$redStyle->getFill()
|
||||
->setFillType(Fill::FILL_SOLID)
|
||||
->getEndColor()->setARGB(Color::COLOR_RED);
|
||||
$redStyle->getFont()->setColor(new Color(Color::COLOR_GREEN));
|
||||
|
||||
// Set conditional formatting rules and styles
|
||||
$helper->log('Define conditional formatting and set styles');
|
||||
|
|
|
|||
|
|
@ -108,12 +108,11 @@ $spreadsheet->getActiveSheet()->getStyle('B1:K1')->getAlignment()->setHorizontal
|
|||
|
||||
// Define some styles for our Conditionals
|
||||
$helper->log('Define some styles for our Conditionals');
|
||||
|
||||
$yellowStyle = new Style(false, true);
|
||||
$yellowStyle->getFill()
|
||||
->setFillType(Fill::FILL_SOLID)
|
||||
->getEndColor()->setARGB(Color::COLOR_YELLOW);
|
||||
$yellowStyle->getNumberFormat()->setFormatCode('ddd dd-mmm-yyyy');
|
||||
$yellowStyle->getFont()->setColor(new Color(Color::COLOR_BLUE));
|
||||
|
||||
// Set conditional formatting rules and styles
|
||||
$helper->log('Define conditional formatting and set styles');
|
||||
|
|
|
|||
|
|
@ -51,14 +51,16 @@ $spreadsheet->getActiveSheet()->getStyle('A1:C1')->getFont()->setBold(true);
|
|||
|
||||
// Define some styles for our Conditionals
|
||||
$helper->log('Define some styles for our Conditionals');
|
||||
$greenStyle = new Style(false, true);
|
||||
$greenStyle->getFill()
|
||||
->setFillType(Fill::FILL_SOLID)
|
||||
->getEndColor()->setARGB(Color::COLOR_GREEN);
|
||||
$yellowStyle = new Style(false, true);
|
||||
$yellowStyle->getFill()
|
||||
->setFillType(Fill::FILL_SOLID)
|
||||
->getEndColor()->setARGB(Color::COLOR_YELLOW);
|
||||
$yellowStyle->getFont()->setColor(new Color(Color::COLOR_BLUE));
|
||||
$greenStyle = new Style(false, true);
|
||||
$greenStyle->getFill()
|
||||
->setFillType(Fill::FILL_SOLID)
|
||||
->getEndColor()->setARGB(Color::COLOR_GREEN);
|
||||
$greenStyle->getFont()->setColor(new Color(Color::COLOR_DARKRED));
|
||||
|
||||
// Set conditional formatting rules and styles
|
||||
$helper->log('Define conditional formatting and set styles');
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ $helper->log('Add data');
|
|||
$spreadsheet->setActiveSheetIndex(0);
|
||||
$spreadsheet->getActiveSheet()
|
||||
->setCellValue('A1', 'Odd/Even Expression Comparison')
|
||||
->setCellValue('A4', 'Note that these functions are not available for Xls files')
|
||||
->setCellValue('A15', 'Sales Grid Expression Comparison')
|
||||
->setCellValue('A25', 'Sales Grid Multiple Expression Comparison');
|
||||
|
||||
|
|
@ -69,14 +70,16 @@ $spreadsheet->getActiveSheet()->getStyle('A25:D26')->getFont()->setBold(true);
|
|||
|
||||
// Define some styles for our Conditionals
|
||||
$helper->log('Define some styles for our Conditionals');
|
||||
$greenStyle = new Style(false, true);
|
||||
$greenStyle->getFill()
|
||||
->setFillType(Fill::FILL_SOLID)
|
||||
->getEndColor()->setARGB(Color::COLOR_GREEN);
|
||||
$yellowStyle = new Style(false, true);
|
||||
$yellowStyle->getFill()
|
||||
->setFillType(Fill::FILL_SOLID)
|
||||
->getEndColor()->setARGB(Color::COLOR_YELLOW);
|
||||
$yellowStyle->getFont()->setColor(new Color(Color::COLOR_BLUE));
|
||||
$greenStyle = new Style(false, true);
|
||||
$greenStyle->getFill()
|
||||
->setFillType(Fill::FILL_SOLID)
|
||||
->getEndColor()->setARGB(Color::COLOR_GREEN);
|
||||
$greenStyle->getFont()->setColor(new Color(Color::COLOR_DARKRED));
|
||||
|
||||
$greenStyleMoney = clone $greenStyle;
|
||||
$greenStyleMoney->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_ACCOUNTING_USD);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Title;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
|
|
@ -71,7 +71,7 @@ $series->setPlotDirection(DataSeries::DIRECTION_BAR);
|
|||
// Set the series in the plot area
|
||||
$plotArea = new PlotArea(null, [$series]);
|
||||
// Set the chart legend
|
||||
$legend = new Legend(Legend::POSITION_RIGHT, null, false);
|
||||
$legend = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false);
|
||||
|
||||
$title = new Title('Test Bar Chart');
|
||||
$yAxisLabel = new Title('Value ($k)');
|
||||
|
|
|
|||
|
|
@ -2583,7 +2583,7 @@ class Calculation
|
|||
],
|
||||
'UNIQUE' => [
|
||||
'category' => Category::CATEGORY_LOOKUP_AND_REFERENCE,
|
||||
'functionCall' => [Functions::class, 'DUMMY'],
|
||||
'functionCall' => [LookupRef\Unique::class, 'unique'],
|
||||
'argumentCount' => '1+',
|
||||
],
|
||||
'UPPER' => [
|
||||
|
|
@ -3226,6 +3226,7 @@ class Calculation
|
|||
if (self::$functionReplaceToExcel === null) {
|
||||
self::$functionReplaceToExcel = [];
|
||||
foreach (array_keys(self::$localeFunctions) as $excelFunctionName) {
|
||||
// @phpstan-ignore-next-line
|
||||
self::$functionReplaceToExcel[] = '$1' . trim($excelFunctionName) . '$2';
|
||||
}
|
||||
foreach (array_keys(self::$localeBoolean) as $excelBoolean) {
|
||||
|
|
@ -4490,6 +4491,7 @@ class Calculation
|
|||
if ($operand1Data['reference'] === null) {
|
||||
if ((trim($operand1Data['value']) != '') && (is_numeric($operand1Data['value']))) {
|
||||
$operand1Data['reference'] = $cell->getColumn() . $operand1Data['value'];
|
||||
// @phpstan-ignore-next-line
|
||||
} elseif (trim($operand1Data['reference']) == '') {
|
||||
$operand1Data['reference'] = $cell->getCoordinate();
|
||||
} else {
|
||||
|
|
@ -4499,6 +4501,7 @@ class Calculation
|
|||
if ($operand2Data['reference'] === null) {
|
||||
if ((trim($operand2Data['value']) != '') && (is_numeric($operand2Data['value']))) {
|
||||
$operand2Data['reference'] = $cell->getColumn() . $operand2Data['value'];
|
||||
// @phpstan-ignore-next-line
|
||||
} elseif (trim($operand2Data['reference']) == '') {
|
||||
$operand2Data['reference'] = $cell->getCoordinate();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -211,13 +211,14 @@ class BitWise
|
|||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return float|int
|
||||
* @return float
|
||||
*/
|
||||
private static function validateBitwiseArgument($value)
|
||||
{
|
||||
$value = self::nullFalseTrueToNumber($value);
|
||||
|
||||
if (is_numeric($value)) {
|
||||
$value = (float) $value;
|
||||
if ($value == floor($value)) {
|
||||
if (($value > 2 ** 48 - 1) || ($value < 0)) {
|
||||
throw new Exception(ExcelError::NAN());
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ class ErrorValue
|
|||
return false;
|
||||
}
|
||||
|
||||
return in_array($value, ExcelError::$errorCodes);
|
||||
return in_array($value, ExcelError::$errorCodes) || $value === ExcelError::CALC();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ class ExcelError
|
|||
'num' => '#NUM!',
|
||||
'na' => '#N/A',
|
||||
'gettingdata' => '#GETTING_DATA',
|
||||
'spill' => '#SPILL!',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -45,6 +46,10 @@ class ExcelError
|
|||
++$i;
|
||||
}
|
||||
|
||||
if ($value === self::CALC()) {
|
||||
return 14;
|
||||
}
|
||||
|
||||
return self::NA();
|
||||
}
|
||||
|
||||
|
|
@ -127,10 +132,20 @@ class ExcelError
|
|||
/**
|
||||
* DIV0.
|
||||
*
|
||||
* @return string #Not Yet Implemented
|
||||
* @return string #DIV/0!
|
||||
*/
|
||||
public static function DIV0()
|
||||
{
|
||||
return self::$errorCodes['divisionbyzero'];
|
||||
}
|
||||
|
||||
/**
|
||||
* CALC.
|
||||
*
|
||||
* @return string #Not Yet Implemented
|
||||
*/
|
||||
public static function CALC()
|
||||
{
|
||||
return '#CALC!';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,9 +32,10 @@ class HLookup extends LookupBase
|
|||
}
|
||||
|
||||
$notExactMatch = (bool) ($notExactMatch ?? true);
|
||||
$lookupArray = self::convertLiteralArray($lookupArray);
|
||||
|
||||
try {
|
||||
self::validateLookupArray($lookupArray);
|
||||
$lookupArray = self::convertLiteralArray($lookupArray);
|
||||
$indexNumber = self::validateIndexLookup($lookupArray, $indexNumber);
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
|
|
|
|||
|
|
@ -72,11 +72,17 @@ class Indirect
|
|||
|
||||
[$cellAddress, $worksheet, $sheetName] = Helpers::extractWorksheet($cellAddress, $cell);
|
||||
|
||||
if (preg_match('/^' . Calculation::CALCULATION_REGEXP_COLUMNRANGE_RELATIVE . '$/miu', $cellAddress, $matches)) {
|
||||
$cellAddress = self::handleRowColumnRanges($worksheet, ...explode(':', $cellAddress));
|
||||
} elseif (preg_match('/^' . Calculation::CALCULATION_REGEXP_ROWRANGE_RELATIVE . '$/miu', $cellAddress, $matches)) {
|
||||
$cellAddress = self::handleRowColumnRanges($worksheet, ...explode(':', $cellAddress));
|
||||
}
|
||||
|
||||
[$cellAddress1, $cellAddress2, $cellAddress] = Helpers::extractCellAddresses($cellAddress, $a1, $cell->getWorkSheet(), $sheetName);
|
||||
|
||||
if (
|
||||
(!preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $cellAddress1, $matches)) ||
|
||||
(($cellAddress2 !== null) && (!preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $cellAddress2, $matches)))
|
||||
(!preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/miu', $cellAddress1, $matches)) ||
|
||||
(($cellAddress2 !== null) && (!preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/miu', $cellAddress2, $matches)))
|
||||
) {
|
||||
return ExcelError::REF();
|
||||
}
|
||||
|
|
@ -95,4 +101,22 @@ class Indirect
|
|||
return Calculation::getInstance($worksheet !== null ? $worksheet->getParent() : null)
|
||||
->extractCellRange($cellAddress, $worksheet, false);
|
||||
}
|
||||
|
||||
private static function handleRowColumnRanges(?Worksheet $worksheet, string $start, string $end): string
|
||||
{
|
||||
// Being lazy, we're only checking a single row/column to get the max
|
||||
if (ctype_digit($start) && $start <= 1048576) {
|
||||
// Max 16,384 columns for Excel2007
|
||||
$endColRef = ($worksheet !== null) ? $worksheet->getHighestDataColumn((int) $start) : 'XFD';
|
||||
|
||||
return "A{$start}:{$endColRef}{$end}";
|
||||
} elseif (ctype_alpha($start) && strlen($start) <= 3) {
|
||||
// Max 1,048,576 rows for Excel2007
|
||||
$endRowRef = ($worksheet !== null) ? $worksheet->getHighestDataRow($start) : 1048576;
|
||||
|
||||
return "{$start}1:{$end}{$endRowRef}";
|
||||
}
|
||||
|
||||
return "{$start}:{$end}";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,16 @@ use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
|
|||
|
||||
abstract class LookupBase
|
||||
{
|
||||
/**
|
||||
* @param mixed $lookup_array
|
||||
*/
|
||||
protected static function validateLookupArray($lookup_array): void
|
||||
{
|
||||
if (!is_array($lookup_array)) {
|
||||
throw new Exception(ExcelError::REF());
|
||||
}
|
||||
}
|
||||
|
||||
protected static function validateIndexLookup(array $lookup_array, $index_number): int
|
||||
{
|
||||
// index_number must be a number greater than or equal to 1
|
||||
|
|
|
|||
|
|
@ -166,6 +166,7 @@ class RowColumnInformation
|
|||
function ($value) {
|
||||
return [$value];
|
||||
},
|
||||
// @phpstan-ignore-next-line
|
||||
range($startAddress, $endAddress)
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,141 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\LookupRef;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
|
||||
|
||||
class Unique
|
||||
{
|
||||
/**
|
||||
* UNIQUE
|
||||
* The UNIQUE function searches for value either from a one-row or one-column range or from an array.
|
||||
*
|
||||
* @param mixed $lookupVector The range of cells being searched
|
||||
* @param mixed $byColumn Whether the uniqueness should be determined by row (the default) or by column
|
||||
* @param mixed $exactlyOnce Whether the function should return only entries that occur just once in the list
|
||||
*
|
||||
* @return mixed The unique values from the search range
|
||||
*/
|
||||
public static function unique($lookupVector, $byColumn = false, $exactlyOnce = false)
|
||||
{
|
||||
if (!is_array($lookupVector)) {
|
||||
// Scalars are always returned "as is"
|
||||
return $lookupVector;
|
||||
}
|
||||
|
||||
$byColumn = (bool) $byColumn;
|
||||
$exactlyOnce = (bool) $exactlyOnce;
|
||||
|
||||
return ($byColumn === true)
|
||||
? self::uniqueByColumn($lookupVector, $exactlyOnce)
|
||||
: self::uniqueByRow($lookupVector, $exactlyOnce);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
private static function uniqueByRow(array $lookupVector, bool $exactlyOnce)
|
||||
{
|
||||
// When not $byColumn, we count whole rows or values, not individual values
|
||||
// so implode each row into a single string value
|
||||
array_walk(
|
||||
$lookupVector,
|
||||
function (array &$value): void {
|
||||
$value = implode(chr(0x00), $value);
|
||||
}
|
||||
);
|
||||
|
||||
$result = self::countValuesCaseInsensitive($lookupVector);
|
||||
|
||||
if ($exactlyOnce === true) {
|
||||
$result = self::exactlyOnceFilter($result);
|
||||
}
|
||||
|
||||
if (count($result) === 0) {
|
||||
return ExcelError::CALC();
|
||||
}
|
||||
|
||||
$result = array_keys($result);
|
||||
|
||||
// restore rows from their strings
|
||||
array_walk(
|
||||
$result,
|
||||
function (string &$value): void {
|
||||
$value = explode(chr(0x00), $value);
|
||||
}
|
||||
);
|
||||
|
||||
return (count($result) === 1) ? array_pop($result) : $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
private static function uniqueByColumn(array $lookupVector, bool $exactlyOnce)
|
||||
{
|
||||
$flattenedLookupVector = Functions::flattenArray($lookupVector);
|
||||
|
||||
if (count($lookupVector, COUNT_RECURSIVE) > count($flattenedLookupVector, COUNT_RECURSIVE) + 1) {
|
||||
// We're looking at a full column check (multiple rows)
|
||||
$transpose = Matrix::transpose($lookupVector);
|
||||
$result = self::uniqueByRow($transpose, $exactlyOnce);
|
||||
|
||||
return (is_array($result)) ? Matrix::transpose($result) : $result;
|
||||
}
|
||||
|
||||
$result = self::countValuesCaseInsensitive($flattenedLookupVector);
|
||||
|
||||
if ($exactlyOnce === true) {
|
||||
$result = self::exactlyOnceFilter($result);
|
||||
}
|
||||
|
||||
if (count($result) === 0) {
|
||||
return ExcelError::CALC();
|
||||
}
|
||||
|
||||
$result = array_keys($result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private static function countValuesCaseInsensitive(array $caseSensitiveLookupValues): array
|
||||
{
|
||||
$caseInsensitiveCounts = array_count_values(
|
||||
array_map(
|
||||
function (string $value) {
|
||||
return StringHelper::strToUpper($value);
|
||||
},
|
||||
$caseSensitiveLookupValues
|
||||
)
|
||||
);
|
||||
|
||||
$caseSensitiveCounts = [];
|
||||
foreach ($caseInsensitiveCounts as $caseInsensitiveKey => $count) {
|
||||
if (is_numeric($caseInsensitiveKey)) {
|
||||
$caseSensitiveCounts[$caseInsensitiveKey] = $count;
|
||||
} else {
|
||||
foreach ($caseSensitiveLookupValues as $caseSensitiveValue) {
|
||||
if ($caseInsensitiveKey === StringHelper::strToUpper($caseSensitiveValue)) {
|
||||
$caseSensitiveCounts[$caseSensitiveValue] = $count;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $caseSensitiveCounts;
|
||||
}
|
||||
|
||||
private static function exactlyOnceFilter(array $values): array
|
||||
{
|
||||
return array_filter(
|
||||
$values,
|
||||
function ($value) {
|
||||
return $value === 1;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -33,6 +33,7 @@ class VLookup extends LookupBase
|
|||
$notExactMatch = (bool) ($notExactMatch ?? true);
|
||||
|
||||
try {
|
||||
self::validateLookupArray($lookupArray);
|
||||
$indexNumber = self::validateIndexLookup($lookupArray, $indexNumber);
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ abstract class Coordinate
|
|||
$exploded = explode(',', $range);
|
||||
$counter = count($exploded);
|
||||
for ($i = 0; $i < $counter; ++$i) {
|
||||
// @phpstan-ignore-next-line
|
||||
$exploded[$i] = explode(':', $exploded[$i]);
|
||||
}
|
||||
|
||||
|
|
@ -544,7 +545,7 @@ abstract class Coordinate
|
|||
|
||||
// split range sets on intersection (space) or union (,) operators
|
||||
$tokens = preg_split('/([ ,])/', $rangeString, -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
// separate the range sets and the operators into arrays
|
||||
/** @phpstan-ignore-next-line */
|
||||
$split = array_chunk($tokens, 2);
|
||||
$ranges = array_column($split, 0);
|
||||
$operators = array_column($split, 1);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,119 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
|
||||
class CellReferenceHelper
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $beforeCellAddress;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $beforeColumn;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $beforeRow;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $numberOfColumns;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $numberOfRows;
|
||||
|
||||
public function __construct(string $beforeCellAddress = 'A1', int $numberOfColumns = 0, int $numberOfRows = 0)
|
||||
{
|
||||
$this->beforeCellAddress = str_replace('$', '', $beforeCellAddress);
|
||||
$this->numberOfColumns = $numberOfColumns;
|
||||
$this->numberOfRows = $numberOfRows;
|
||||
|
||||
// Get coordinate of $beforeCellAddress
|
||||
[$beforeColumn, $beforeRow] = Coordinate::coordinateFromString($beforeCellAddress);
|
||||
$this->beforeColumn = (int) Coordinate::columnIndexFromString($beforeColumn);
|
||||
$this->beforeRow = (int) $beforeRow;
|
||||
}
|
||||
|
||||
public function beforeCellAddress(): string
|
||||
{
|
||||
return $this->beforeCellAddress;
|
||||
}
|
||||
|
||||
public function refreshRequired(string $beforeCellAddress, int $numberOfColumns, int $numberOfRows): bool
|
||||
{
|
||||
return $this->beforeCellAddress !== $beforeCellAddress ||
|
||||
$this->numberOfColumns !== $numberOfColumns ||
|
||||
$this->numberOfRows !== $numberOfRows;
|
||||
}
|
||||
|
||||
public function updateCellReference(string $cellReference = 'A1', bool $includeAbsoluteReferences = false): string
|
||||
{
|
||||
if (Coordinate::coordinateIsRange($cellReference)) {
|
||||
throw new Exception('Only single cell references may be passed to this method.');
|
||||
}
|
||||
|
||||
// Get coordinate of $cellReference
|
||||
[$newColumn, $newRow] = Coordinate::coordinateFromString($cellReference);
|
||||
$newColumnIndex = (int) Coordinate::columnIndexFromString(str_replace('$', '', $newColumn));
|
||||
$newRowIndex = (int) str_replace('$', '', $newRow);
|
||||
|
||||
$absoluteColumn = $newColumn[0] === '$' ? '$' : '';
|
||||
$absoluteRow = $newRow[0] === '$' ? '$' : '';
|
||||
// Verify which parts should be updated
|
||||
if ($includeAbsoluteReferences === false) {
|
||||
$updateColumn = (($absoluteColumn !== '$') && $newColumnIndex >= $this->beforeColumn);
|
||||
$updateRow = (($absoluteRow !== '$') && $newRowIndex >= $this->beforeRow);
|
||||
} else {
|
||||
$updateColumn = ($newColumnIndex >= $this->beforeColumn);
|
||||
$updateRow = ($newRowIndex >= $this->beforeRow);
|
||||
}
|
||||
|
||||
// Create new column reference
|
||||
if ($updateColumn) {
|
||||
$newColumn = ($includeAbsoluteReferences === false)
|
||||
? Coordinate::stringFromColumnIndex($newColumnIndex + $this->numberOfColumns)
|
||||
: $absoluteColumn . Coordinate::stringFromColumnIndex($newColumnIndex + $this->numberOfColumns);
|
||||
}
|
||||
|
||||
// Create new row reference
|
||||
if ($updateRow) {
|
||||
$newRow = ($includeAbsoluteReferences === false)
|
||||
? $newRowIndex + $this->numberOfRows
|
||||
: $absoluteRow . (string) ($newRowIndex + $this->numberOfRows);
|
||||
}
|
||||
|
||||
// Return new reference
|
||||
return "{$newColumn}{$newRow}";
|
||||
}
|
||||
|
||||
public function cellAddressInDeleteRange(string $cellAddress): bool
|
||||
{
|
||||
[$cellColumn, $cellRow] = Coordinate::coordinateFromString($cellAddress);
|
||||
$cellColumnIndex = Coordinate::columnIndexFromString($cellColumn);
|
||||
// Is cell within the range of rows/columns if we're deleting
|
||||
if (
|
||||
$this->numberOfRows < 0 &&
|
||||
($cellRow >= ($this->beforeRow + $this->numberOfRows)) &&
|
||||
($cellRow < $this->beforeRow)
|
||||
) {
|
||||
return true;
|
||||
} elseif (
|
||||
$this->numberOfColumns < 0 &&
|
||||
($cellColumnIndex >= ($this->beforeColumn + $this->numberOfColumns)) &&
|
||||
($cellColumnIndex < $this->beforeColumn)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -619,6 +619,7 @@ class Html
|
|||
// Load the HTML file into the DOM object
|
||||
// Note the use of error suppression, because typically this will be an html fragment, so not fully valid markup
|
||||
$prefix = '<?xml encoding="UTF-8">';
|
||||
/** @scrutinizer ignore-unhandled */
|
||||
@$dom->loadHTML($prefix . $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
|
||||
// Discard excess white space
|
||||
$dom->preserveWhiteSpace = false;
|
||||
|
|
@ -808,6 +809,7 @@ class Html
|
|||
if (isset($callbacks[$callbackTag])) {
|
||||
$elementHandler = $callbacks[$callbackTag];
|
||||
if (method_exists($this, $elementHandler)) {
|
||||
/** @phpstan-ignore-next-line */
|
||||
call_user_func([$this, $elementHandler], $element);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ class MD5
|
|||
*/
|
||||
public function add(string $data): void
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
$words = array_values(unpack('V16', $data));
|
||||
|
||||
$A = $this->a;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ use PhpOffice\PhpSpreadsheet\Reader\Xlsx\SheetViewOptions;
|
|||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\SheetViews;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Styles;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Theme;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\WorkbookView;
|
||||
use PhpOffice\PhpSpreadsheet\ReferenceHelper;
|
||||
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
||||
use PhpOffice\PhpSpreadsheet\Settings;
|
||||
|
|
@ -1314,6 +1315,11 @@ class Xlsx extends BaseReader
|
|||
$outerShdw = $twoCellAnchor->pic->spPr->children(Namespaces::DRAWINGML)->effectLst->outerShdw;
|
||||
$hlinkClick = $twoCellAnchor->pic->nvPicPr->cNvPr->children(Namespaces::DRAWINGML)->hlinkClick;
|
||||
$objDrawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing();
|
||||
/** @scrutinizer ignore-call */
|
||||
$editAs = $twoCellAnchor->attributes();
|
||||
if (isset($editAs, $editAs['editAs'])) {
|
||||
$objDrawing->setEditAs($editAs['editAs']);
|
||||
}
|
||||
$objDrawing->setName((string) self::getArrayItem(self::getAttributes($twoCellAnchor->pic->nvPicPr->cNvPr), 'name'));
|
||||
$objDrawing->setDescription((string) self::getArrayItem(self::getAttributes($twoCellAnchor->pic->nvPicPr->cNvPr), 'descr'));
|
||||
$embedImageKey = (string) self::getArrayItem(
|
||||
|
|
@ -1564,62 +1570,7 @@ class Xlsx extends BaseReader
|
|||
}
|
||||
}
|
||||
|
||||
$workbookView = $xmlWorkbook->children($mainNS)->bookViews->workbookView;
|
||||
if ((!$this->readDataOnly || !empty($this->loadSheetsOnly)) && !empty($workbookView)) {
|
||||
$workbookViewAttributes = self::testSimpleXml(self::getAttributes($workbookView));
|
||||
// active sheet index
|
||||
$activeTab = (int) $workbookViewAttributes->activeTab; // refers to old sheet index
|
||||
|
||||
// keep active sheet index if sheet is still loaded, else first sheet is set as the active
|
||||
if (isset($mapSheetId[$activeTab]) && $mapSheetId[$activeTab] !== null) {
|
||||
$excel->setActiveSheetIndex($mapSheetId[$activeTab]);
|
||||
} else {
|
||||
if ($excel->getSheetCount() == 0) {
|
||||
$excel->createSheet();
|
||||
}
|
||||
$excel->setActiveSheetIndex(0);
|
||||
}
|
||||
|
||||
if (isset($workbookViewAttributes->showHorizontalScroll)) {
|
||||
$showHorizontalScroll = (string) $workbookViewAttributes->showHorizontalScroll;
|
||||
$excel->setShowHorizontalScroll($this->castXsdBooleanToBool($showHorizontalScroll));
|
||||
}
|
||||
|
||||
if (isset($workbookViewAttributes->showVerticalScroll)) {
|
||||
$showVerticalScroll = (string) $workbookViewAttributes->showVerticalScroll;
|
||||
$excel->setShowVerticalScroll($this->castXsdBooleanToBool($showVerticalScroll));
|
||||
}
|
||||
|
||||
if (isset($workbookViewAttributes->showSheetTabs)) {
|
||||
$showSheetTabs = (string) $workbookViewAttributes->showSheetTabs;
|
||||
$excel->setShowSheetTabs($this->castXsdBooleanToBool($showSheetTabs));
|
||||
}
|
||||
|
||||
if (isset($workbookViewAttributes->minimized)) {
|
||||
$minimized = (string) $workbookViewAttributes->minimized;
|
||||
$excel->setMinimized($this->castXsdBooleanToBool($minimized));
|
||||
}
|
||||
|
||||
if (isset($workbookViewAttributes->autoFilterDateGrouping)) {
|
||||
$autoFilterDateGrouping = (string) $workbookViewAttributes->autoFilterDateGrouping;
|
||||
$excel->setAutoFilterDateGrouping($this->castXsdBooleanToBool($autoFilterDateGrouping));
|
||||
}
|
||||
|
||||
if (isset($workbookViewAttributes->firstSheet)) {
|
||||
$firstSheet = (string) $workbookViewAttributes->firstSheet;
|
||||
$excel->setFirstSheetIndex((int) $firstSheet);
|
||||
}
|
||||
|
||||
if (isset($workbookViewAttributes->visibility)) {
|
||||
$visibility = (string) $workbookViewAttributes->visibility;
|
||||
$excel->setVisibility($visibility);
|
||||
}
|
||||
|
||||
if (isset($workbookViewAttributes->tabRatio)) {
|
||||
$tabRatio = (string) $workbookViewAttributes->tabRatio;
|
||||
$excel->setTabRatio((int) $tabRatio);
|
||||
}
|
||||
}
|
||||
(new WorkbookView($excel))->viewSettings($xmlWorkbook, $mainNS, $mapSheetId, $this->readDataOnly);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
@ -1978,29 +1929,6 @@ class Xlsx extends BaseReader
|
|||
unset($unparsedPrinterSettings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an 'xsd:boolean' XML value to a PHP boolean value.
|
||||
* A valid 'xsd:boolean' XML value can be one of the following
|
||||
* four values: 'true', 'false', '1', '0'. It is case sensitive.
|
||||
*
|
||||
* Note that just doing '(bool) $xsdBoolean' is not safe,
|
||||
* since '(bool) "false"' returns true.
|
||||
*
|
||||
* @see https://www.w3.org/TR/xmlschema11-2/#boolean
|
||||
*
|
||||
* @param string $xsdBoolean An XML string value of type 'xsd:boolean'
|
||||
*
|
||||
* @return bool Boolean value
|
||||
*/
|
||||
private function castXsdBooleanToBool($xsdBoolean)
|
||||
{
|
||||
if ($xsdBoolean === 'false') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (bool) $xsdBoolean;
|
||||
}
|
||||
|
||||
private function getWorkbookBaseName(): array
|
||||
{
|
||||
$workbookBasename = '';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,153 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use SimpleXMLElement;
|
||||
|
||||
class WorkbookView
|
||||
{
|
||||
/**
|
||||
* @var Spreadsheet
|
||||
*/
|
||||
private $spreadsheet;
|
||||
|
||||
public function __construct(Spreadsheet $spreadsheet)
|
||||
{
|
||||
$this->spreadsheet = $spreadsheet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $mainNS
|
||||
*/
|
||||
public function viewSettings(SimpleXMLElement $xmlWorkbook, $mainNS, array $mapSheetId, bool $readDataOnly): void
|
||||
{
|
||||
if ($this->spreadsheet->getSheetCount() == 0) {
|
||||
$this->spreadsheet->createSheet();
|
||||
}
|
||||
// Default active sheet index to the first loaded worksheet from the file
|
||||
$this->spreadsheet->setActiveSheetIndex(0);
|
||||
|
||||
$workbookView = $xmlWorkbook->children($mainNS)->bookViews->workbookView;
|
||||
if (($readDataOnly !== true || !empty($this->loadSheetsOnly)) && !empty($workbookView)) {
|
||||
$workbookViewAttributes = self::testSimpleXml(self::getAttributes($workbookView));
|
||||
// active sheet index
|
||||
$activeTab = (int) $workbookViewAttributes->activeTab; // refers to old sheet index
|
||||
// keep active sheet index if sheet is still loaded, else first sheet is set as the active worksheet
|
||||
if (isset($mapSheetId[$activeTab]) && $mapSheetId[$activeTab] !== null) {
|
||||
$this->spreadsheet->setActiveSheetIndex($mapSheetId[$activeTab]);
|
||||
}
|
||||
|
||||
$this->horizontalScroll($workbookViewAttributes);
|
||||
$this->verticalScroll($workbookViewAttributes);
|
||||
$this->sheetTabs($workbookViewAttributes);
|
||||
$this->minimized($workbookViewAttributes);
|
||||
$this->autoFilterDateGrouping($workbookViewAttributes);
|
||||
$this->firstSheet($workbookViewAttributes);
|
||||
$this->visibility($workbookViewAttributes);
|
||||
$this->tabRatio($workbookViewAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
public static function testSimpleXml($value): SimpleXMLElement
|
||||
{
|
||||
return ($value instanceof SimpleXMLElement)
|
||||
? $value
|
||||
: new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><root></root>');
|
||||
}
|
||||
|
||||
public static function getAttributes(?SimpleXMLElement $value, string $ns = ''): SimpleXMLElement
|
||||
{
|
||||
return self::testSimpleXml($value === null ? $value : $value->attributes($ns));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an 'xsd:boolean' XML value to a PHP boolean value.
|
||||
* A valid 'xsd:boolean' XML value can be one of the following
|
||||
* four values: 'true', 'false', '1', '0'. It is case sensitive.
|
||||
*
|
||||
* Note that just doing '(bool) $xsdBoolean' is not safe,
|
||||
* since '(bool) "false"' returns true.
|
||||
*
|
||||
* @see https://www.w3.org/TR/xmlschema11-2/#boolean
|
||||
*
|
||||
* @param string $xsdBoolean An XML string value of type 'xsd:boolean'
|
||||
*
|
||||
* @return bool Boolean value
|
||||
*/
|
||||
private function castXsdBooleanToBool(string $xsdBoolean): bool
|
||||
{
|
||||
if ($xsdBoolean === 'false') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (bool) $xsdBoolean;
|
||||
}
|
||||
|
||||
private function horizontalScroll(SimpleXMLElement $workbookViewAttributes): void
|
||||
{
|
||||
if (isset($workbookViewAttributes->showHorizontalScroll)) {
|
||||
$showHorizontalScroll = (string) $workbookViewAttributes->showHorizontalScroll;
|
||||
$this->spreadsheet->setShowHorizontalScroll($this->castXsdBooleanToBool($showHorizontalScroll));
|
||||
}
|
||||
}
|
||||
|
||||
private function verticalScroll(SimpleXMLElement $workbookViewAttributes): void
|
||||
{
|
||||
if (isset($workbookViewAttributes->showVerticalScroll)) {
|
||||
$showVerticalScroll = (string) $workbookViewAttributes->showVerticalScroll;
|
||||
$this->spreadsheet->setShowVerticalScroll($this->castXsdBooleanToBool($showVerticalScroll));
|
||||
}
|
||||
}
|
||||
|
||||
private function sheetTabs(SimpleXMLElement $workbookViewAttributes): void
|
||||
{
|
||||
if (isset($workbookViewAttributes->showSheetTabs)) {
|
||||
$showSheetTabs = (string) $workbookViewAttributes->showSheetTabs;
|
||||
$this->spreadsheet->setShowSheetTabs($this->castXsdBooleanToBool($showSheetTabs));
|
||||
}
|
||||
}
|
||||
|
||||
private function minimized(SimpleXMLElement $workbookViewAttributes): void
|
||||
{
|
||||
if (isset($workbookViewAttributes->minimized)) {
|
||||
$minimized = (string) $workbookViewAttributes->minimized;
|
||||
$this->spreadsheet->setMinimized($this->castXsdBooleanToBool($minimized));
|
||||
}
|
||||
}
|
||||
|
||||
private function autoFilterDateGrouping(SimpleXMLElement $workbookViewAttributes): void
|
||||
{
|
||||
if (isset($workbookViewAttributes->autoFilterDateGrouping)) {
|
||||
$autoFilterDateGrouping = (string) $workbookViewAttributes->autoFilterDateGrouping;
|
||||
$this->spreadsheet->setAutoFilterDateGrouping($this->castXsdBooleanToBool($autoFilterDateGrouping));
|
||||
}
|
||||
}
|
||||
|
||||
private function firstSheet(SimpleXMLElement $workbookViewAttributes): void
|
||||
{
|
||||
if (isset($workbookViewAttributes->firstSheet)) {
|
||||
$firstSheet = (string) $workbookViewAttributes->firstSheet;
|
||||
$this->spreadsheet->setFirstSheetIndex((int) $firstSheet);
|
||||
}
|
||||
}
|
||||
|
||||
private function visibility(SimpleXMLElement $workbookViewAttributes): void
|
||||
{
|
||||
if (isset($workbookViewAttributes->visibility)) {
|
||||
$visibility = (string) $workbookViewAttributes->visibility;
|
||||
$this->spreadsheet->setVisibility($visibility);
|
||||
}
|
||||
}
|
||||
|
||||
private function tabRatio(SimpleXMLElement $workbookViewAttributes): void
|
||||
{
|
||||
if (isset($workbookViewAttributes->tabRatio)) {
|
||||
$tabRatio = (string) $workbookViewAttributes->tabRatio;
|
||||
$this->spreadsheet->setTabRatio((int) $tabRatio);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,8 @@ namespace PhpOffice\PhpSpreadsheet;
|
|||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Conditional;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
|
||||
class ReferenceHelper
|
||||
|
|
@ -19,10 +21,15 @@ class ReferenceHelper
|
|||
/**
|
||||
* Instance of this class.
|
||||
*
|
||||
* @var ReferenceHelper
|
||||
* @var ?ReferenceHelper
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
/**
|
||||
* @var CellReferenceHelper
|
||||
*/
|
||||
private $cellReferenceHelper;
|
||||
|
||||
/**
|
||||
* Get an instance of this class.
|
||||
*
|
||||
|
|
@ -30,7 +37,7 @@ class ReferenceHelper
|
|||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
if (!isset(self::$instance) || (self::$instance === null)) {
|
||||
if (self::$instance === null) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
|
||||
|
|
@ -114,67 +121,32 @@ class ReferenceHelper
|
|||
return ($ar < $br) ? 1 : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether a cell address falls within a defined range of cells.
|
||||
*
|
||||
* @param string $cellAddress Address of the cell we're testing
|
||||
* @param int $beforeRow Number of the row we're inserting/deleting before
|
||||
* @param int $numberOfRows Number of rows to insert/delete (negative values indicate deletion)
|
||||
* @param int $beforeColumnIndex Index number of the column we're inserting/deleting before
|
||||
* @param int $numberOfCols Number of columns to insert/delete (negative values indicate deletion)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function cellAddressInDeleteRange($cellAddress, $beforeRow, $numberOfRows, $beforeColumnIndex, $numberOfCols)
|
||||
{
|
||||
[$cellColumn, $cellRow] = Coordinate::coordinateFromString($cellAddress);
|
||||
$cellColumnIndex = Coordinate::columnIndexFromString($cellColumn);
|
||||
// Is cell within the range of rows/columns if we're deleting
|
||||
if (
|
||||
$numberOfRows < 0 &&
|
||||
($cellRow >= ($beforeRow + $numberOfRows)) &&
|
||||
($cellRow < $beforeRow)
|
||||
) {
|
||||
return true;
|
||||
} elseif (
|
||||
$numberOfCols < 0 &&
|
||||
($cellColumnIndex >= ($beforeColumnIndex + $numberOfCols)) &&
|
||||
($cellColumnIndex < $beforeColumnIndex)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update page breaks when inserting/deleting rows/columns.
|
||||
*
|
||||
* @param Worksheet $worksheet The worksheet that we're editing
|
||||
* @param string $beforeCellAddress Insert/Delete before this cell address (e.g. 'A1')
|
||||
* @param int $beforeColumnIndex Index number of the column we're inserting/deleting before
|
||||
* @param int $numberOfColumns Number of columns to insert/delete (negative values indicate deletion)
|
||||
* @param int $beforeRow Number of the row we're inserting/deleting before
|
||||
* @param int $numberOfRows Number of rows to insert/delete (negative values indicate deletion)
|
||||
*/
|
||||
protected function adjustPageBreaks(Worksheet $worksheet, $beforeCellAddress, $beforeColumnIndex, $numberOfColumns, $beforeRow, $numberOfRows): void
|
||||
protected function adjustPageBreaks(Worksheet $worksheet, $numberOfColumns, $numberOfRows): void
|
||||
{
|
||||
$aBreaks = $worksheet->getBreaks();
|
||||
($numberOfColumns > 0 || $numberOfRows > 0) ?
|
||||
uksort($aBreaks, ['self', 'cellReverseSort']) : uksort($aBreaks, ['self', 'cellSort']);
|
||||
($numberOfColumns > 0 || $numberOfRows > 0)
|
||||
? uksort($aBreaks, [self::class, 'cellReverseSort'])
|
||||
: uksort($aBreaks, [self::class, 'cellSort']);
|
||||
|
||||
foreach ($aBreaks as $key => $value) {
|
||||
if (self::cellAddressInDeleteRange($key, $beforeRow, $numberOfRows, $beforeColumnIndex, $numberOfColumns)) {
|
||||
foreach ($aBreaks as $cellAddress => $value) {
|
||||
if ($this->cellReferenceHelper->cellAddressInDeleteRange($cellAddress) === true) {
|
||||
// If we're deleting, then clear any defined breaks that are within the range
|
||||
// of rows/columns that we're deleting
|
||||
$worksheet->setBreak($key, Worksheet::BREAK_NONE);
|
||||
$worksheet->setBreak($cellAddress, Worksheet::BREAK_NONE);
|
||||
} else {
|
||||
// Otherwise update any affected breaks by inserting a new break at the appropriate point
|
||||
// and removing the old affected break
|
||||
$newReference = $this->updateCellReference($key, $beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
if ($key != $newReference) {
|
||||
$newReference = $this->updateCellReference($cellAddress);
|
||||
if ($cellAddress !== $newReference) {
|
||||
$worksheet->setBreak($newReference, $value)
|
||||
->setBreak($key, Worksheet::BREAK_NONE);
|
||||
->setBreak($cellAddress, Worksheet::BREAK_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -184,22 +156,17 @@ class ReferenceHelper
|
|||
* Update cell comments when inserting/deleting rows/columns.
|
||||
*
|
||||
* @param Worksheet $worksheet The worksheet that we're editing
|
||||
* @param string $beforeCellAddress Insert/Delete before this cell address (e.g. 'A1')
|
||||
* @param int $beforeColumnIndex Index number of the column we're inserting/deleting before
|
||||
* @param int $numberOfColumns Number of columns to insert/delete (negative values indicate deletion)
|
||||
* @param int $beforeRow Number of the row we're inserting/deleting before
|
||||
* @param int $numberOfRows Number of rows to insert/delete (negative values indicate deletion)
|
||||
*/
|
||||
protected function adjustComments($worksheet, $beforeCellAddress, $beforeColumnIndex, $numberOfColumns, $beforeRow, $numberOfRows): void
|
||||
protected function adjustComments($worksheet): void
|
||||
{
|
||||
$aComments = $worksheet->getComments();
|
||||
$aNewComments = []; // the new array of all comments
|
||||
|
||||
foreach ($aComments as $key => &$value) {
|
||||
foreach ($aComments as $cellAddress => &$value) {
|
||||
// Any comments inside a deleted range will be ignored
|
||||
if (!self::cellAddressInDeleteRange($key, $beforeRow, $numberOfRows, $beforeColumnIndex, $numberOfColumns)) {
|
||||
if ($this->cellReferenceHelper->cellAddressInDeleteRange($cellAddress) === false) {
|
||||
// Otherwise build a new array of comments indexed by the adjusted cell reference
|
||||
$newReference = $this->updateCellReference($key, $beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
$newReference = $this->updateCellReference($cellAddress);
|
||||
$aNewComments[$newReference] = $value;
|
||||
}
|
||||
}
|
||||
|
|
@ -211,44 +178,85 @@ class ReferenceHelper
|
|||
* Update hyperlinks when inserting/deleting rows/columns.
|
||||
*
|
||||
* @param Worksheet $worksheet The worksheet that we're editing
|
||||
* @param string $beforeCellAddress Insert/Delete before this cell address (e.g. 'A1')
|
||||
* @param int $numberOfColumns Number of columns to insert/delete (negative values indicate deletion)
|
||||
* @param int $numberOfRows Number of rows to insert/delete (negative values indicate deletion)
|
||||
*/
|
||||
protected function adjustHyperlinks($worksheet, $beforeCellAddress, $numberOfColumns, $numberOfRows): void
|
||||
protected function adjustHyperlinks($worksheet, $numberOfColumns, $numberOfRows): void
|
||||
{
|
||||
$aHyperlinkCollection = $worksheet->getHyperlinkCollection();
|
||||
($numberOfColumns > 0 || $numberOfRows > 0) ?
|
||||
uksort($aHyperlinkCollection, ['self', 'cellReverseSort']) : uksort($aHyperlinkCollection, ['self', 'cellSort']);
|
||||
($numberOfColumns > 0 || $numberOfRows > 0)
|
||||
? uksort($aHyperlinkCollection, [self::class, 'cellReverseSort'])
|
||||
: uksort($aHyperlinkCollection, [self::class, 'cellSort']);
|
||||
|
||||
foreach ($aHyperlinkCollection as $key => $value) {
|
||||
$newReference = $this->updateCellReference($key, $beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
if ($key != $newReference) {
|
||||
foreach ($aHyperlinkCollection as $cellAddress => $value) {
|
||||
$newReference = $this->updateCellReference($cellAddress);
|
||||
if ($this->cellReferenceHelper->cellAddressInDeleteRange($cellAddress) === true) {
|
||||
$worksheet->setHyperlink($cellAddress, null);
|
||||
} elseif ($cellAddress !== $newReference) {
|
||||
$worksheet->setHyperlink($newReference, $value);
|
||||
$worksheet->setHyperlink($key, null);
|
||||
$worksheet->setHyperlink($cellAddress, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update conditional formatting styles when inserting/deleting rows/columns.
|
||||
*
|
||||
* @param Worksheet $worksheet The worksheet that we're editing
|
||||
* @param int $numberOfColumns Number of columns to insert/delete (negative values indicate deletion)
|
||||
* @param int $numberOfRows Number of rows to insert/delete (negative values indicate deletion)
|
||||
*/
|
||||
protected function adjustConditionalFormatting($worksheet, $numberOfColumns, $numberOfRows): void
|
||||
{
|
||||
$aStyles = $worksheet->getConditionalStylesCollection();
|
||||
($numberOfColumns > 0 || $numberOfRows > 0)
|
||||
? uksort($aStyles, [self::class, 'cellReverseSort'])
|
||||
: uksort($aStyles, [self::class, 'cellSort']);
|
||||
|
||||
foreach ($aStyles as $cellAddress => $cfRules) {
|
||||
$worksheet->removeConditionalStyles($cellAddress);
|
||||
$newReference = $this->updateCellReference($cellAddress);
|
||||
|
||||
foreach ($cfRules as &$cfRule) {
|
||||
/** @var Conditional $cfRule */
|
||||
$conditions = $cfRule->getConditions();
|
||||
foreach ($conditions as &$condition) {
|
||||
if (is_string($condition)) {
|
||||
$condition = $this->updateFormulaReferences(
|
||||
$condition,
|
||||
$this->cellReferenceHelper->beforeCellAddress(),
|
||||
$numberOfColumns,
|
||||
$numberOfRows,
|
||||
$worksheet->getTitle(),
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
$cfRule->setConditions($conditions);
|
||||
}
|
||||
$worksheet->setConditionalStyles($newReference, $cfRules);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update data validations when inserting/deleting rows/columns.
|
||||
*
|
||||
* @param Worksheet $worksheet The worksheet that we're editing
|
||||
* @param string $before Insert/Delete before this cell address (e.g. 'A1')
|
||||
* @param int $numberOfColumns Number of columns to insert/delete (negative values indicate deletion)
|
||||
* @param int $numberOfRows Number of rows to insert/delete (negative values indicate deletion)
|
||||
*/
|
||||
protected function adjustDataValidations(Worksheet $worksheet, $before, $numberOfColumns, $numberOfRows): void
|
||||
protected function adjustDataValidations(Worksheet $worksheet, $numberOfColumns, $numberOfRows): void
|
||||
{
|
||||
$aDataValidationCollection = $worksheet->getDataValidationCollection();
|
||||
($numberOfColumns > 0 || $numberOfRows > 0) ?
|
||||
uksort($aDataValidationCollection, ['self', 'cellReverseSort']) : uksort($aDataValidationCollection, ['self', 'cellSort']);
|
||||
($numberOfColumns > 0 || $numberOfRows > 0)
|
||||
? uksort($aDataValidationCollection, [self::class, 'cellReverseSort'])
|
||||
: uksort($aDataValidationCollection, [self::class, 'cellSort']);
|
||||
|
||||
foreach ($aDataValidationCollection as $key => $value) {
|
||||
$newReference = $this->updateCellReference($key, $before, $numberOfColumns, $numberOfRows);
|
||||
if ($key != $newReference) {
|
||||
foreach ($aDataValidationCollection as $cellAddress => $value) {
|
||||
$newReference = $this->updateCellReference($cellAddress);
|
||||
if ($cellAddress !== $newReference) {
|
||||
$worksheet->setDataValidation($newReference, $value);
|
||||
$worksheet->setDataValidation($key, null);
|
||||
$worksheet->setDataValidation($cellAddress, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -257,16 +265,13 @@ class ReferenceHelper
|
|||
* Update merged cells when inserting/deleting rows/columns.
|
||||
*
|
||||
* @param Worksheet $worksheet The worksheet that we're editing
|
||||
* @param string $beforeCellAddress Insert/Delete before this cell address (e.g. 'A1')
|
||||
* @param int $numberOfColumns Number of columns to insert/delete (negative values indicate deletion)
|
||||
* @param int $numberOfRows Number of rows to insert/delete (negative values indicate deletion)
|
||||
*/
|
||||
protected function adjustMergeCells(Worksheet $worksheet, $beforeCellAddress, $numberOfColumns, $numberOfRows): void
|
||||
protected function adjustMergeCells(Worksheet $worksheet): void
|
||||
{
|
||||
$aMergeCells = $worksheet->getMergeCells();
|
||||
$aNewMergeCells = []; // the new array of all merge cells
|
||||
foreach ($aMergeCells as $key => &$value) {
|
||||
$newReference = $this->updateCellReference($key, $beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
foreach ($aMergeCells as $cellAddress => &$value) {
|
||||
$newReference = $this->updateCellReference($cellAddress);
|
||||
$aNewMergeCells[$newReference] = $newReference;
|
||||
}
|
||||
$worksheet->setMergeCells($aNewMergeCells); // replace the merge cells array
|
||||
|
|
@ -276,20 +281,20 @@ class ReferenceHelper
|
|||
* Update protected cells when inserting/deleting rows/columns.
|
||||
*
|
||||
* @param Worksheet $worksheet The worksheet that we're editing
|
||||
* @param string $beforeCellAddress Insert/Delete before this cell address (e.g. 'A1')
|
||||
* @param int $numberOfColumns Number of columns to insert/delete (negative values indicate deletion)
|
||||
* @param int $numberOfRows Number of rows to insert/delete (negative values indicate deletion)
|
||||
*/
|
||||
protected function adjustProtectedCells(Worksheet $worksheet, $beforeCellAddress, $numberOfColumns, $numberOfRows): void
|
||||
protected function adjustProtectedCells(Worksheet $worksheet, $numberOfColumns, $numberOfRows): void
|
||||
{
|
||||
$aProtectedCells = $worksheet->getProtectedCells();
|
||||
($numberOfColumns > 0 || $numberOfRows > 0) ?
|
||||
uksort($aProtectedCells, ['self', 'cellReverseSort']) : uksort($aProtectedCells, ['self', 'cellSort']);
|
||||
foreach ($aProtectedCells as $key => $value) {
|
||||
$newReference = $this->updateCellReference($key, $beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
if ($key != $newReference) {
|
||||
($numberOfColumns > 0 || $numberOfRows > 0)
|
||||
? uksort($aProtectedCells, [self::class, 'cellReverseSort'])
|
||||
: uksort($aProtectedCells, [self::class, 'cellSort']);
|
||||
foreach ($aProtectedCells as $cellAddress => $value) {
|
||||
$newReference = $this->updateCellReference($cellAddress);
|
||||
if ($cellAddress !== $newReference) {
|
||||
$worksheet->protectCells($newReference, $value, true);
|
||||
$worksheet->unprotectCells($key);
|
||||
$worksheet->unprotectCells($cellAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -298,18 +303,15 @@ class ReferenceHelper
|
|||
* Update column dimensions when inserting/deleting rows/columns.
|
||||
*
|
||||
* @param Worksheet $worksheet The worksheet that we're editing
|
||||
* @param string $beforeCellAddress Insert/Delete before this cell address (e.g. 'A1')
|
||||
* @param int $numberOfColumns Number of columns to insert/delete (negative values indicate deletion)
|
||||
* @param int $numberOfRows Number of rows to insert/delete (negative values indicate deletion)
|
||||
*/
|
||||
protected function adjustColumnDimensions(Worksheet $worksheet, $beforeCellAddress, $numberOfColumns, $numberOfRows): void
|
||||
protected function adjustColumnDimensions(Worksheet $worksheet): void
|
||||
{
|
||||
$aColumnDimensions = array_reverse($worksheet->getColumnDimensions(), true);
|
||||
if (!empty($aColumnDimensions)) {
|
||||
foreach ($aColumnDimensions as $objColumnDimension) {
|
||||
$newReference = $this->updateCellReference($objColumnDimension->getColumnIndex() . '1', $beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
$newReference = $this->updateCellReference($objColumnDimension->getColumnIndex() . '1');
|
||||
[$newReference] = Coordinate::coordinateFromString($newReference);
|
||||
if ($objColumnDimension->getColumnIndex() != $newReference) {
|
||||
if ($objColumnDimension->getColumnIndex() !== $newReference) {
|
||||
$objColumnDimension->setColumnIndex($newReference);
|
||||
}
|
||||
}
|
||||
|
|
@ -321,20 +323,19 @@ class ReferenceHelper
|
|||
* Update row dimensions when inserting/deleting rows/columns.
|
||||
*
|
||||
* @param Worksheet $worksheet The worksheet that we're editing
|
||||
* @param string $beforeCellAddress Insert/Delete before this cell address (e.g. 'A1')
|
||||
* @param int $numberOfColumns Number of columns to insert/delete (negative values indicate deletion)
|
||||
* @param int $beforeRow Number of the row we're inserting/deleting before
|
||||
* @param int $numberOfRows Number of rows to insert/delete (negative values indicate deletion)
|
||||
*/
|
||||
protected function adjustRowDimensions(Worksheet $worksheet, $beforeCellAddress, $numberOfColumns, $beforeRow, $numberOfRows): void
|
||||
protected function adjustRowDimensions(Worksheet $worksheet, $beforeRow, $numberOfRows): void
|
||||
{
|
||||
$aRowDimensions = array_reverse($worksheet->getRowDimensions(), true);
|
||||
if (!empty($aRowDimensions)) {
|
||||
foreach ($aRowDimensions as $objRowDimension) {
|
||||
$newReference = $this->updateCellReference('A' . $objRowDimension->getRowIndex(), $beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
$newReference = $this->updateCellReference('A' . $objRowDimension->getRowIndex());
|
||||
[, $newReference] = Coordinate::coordinateFromString($newReference);
|
||||
if ($objRowDimension->getRowIndex() != $newReference) {
|
||||
$objRowDimension->setRowIndex($newReference);
|
||||
$newRoweference = (int) $newReference;
|
||||
if ($objRowDimension->getRowIndex() !== $newRoweference) {
|
||||
$objRowDimension->setRowIndex($newRoweference);
|
||||
}
|
||||
}
|
||||
$worksheet->refreshRowDimensions();
|
||||
|
|
@ -358,11 +359,22 @@ class ReferenceHelper
|
|||
* @param int $numberOfRows Number of rows to insert/delete (negative values indicate deletion)
|
||||
* @param Worksheet $worksheet The worksheet that we're editing
|
||||
*/
|
||||
public function insertNewBefore($beforeCellAddress, $numberOfColumns, $numberOfRows, Worksheet $worksheet): void
|
||||
{
|
||||
public function insertNewBefore(
|
||||
string $beforeCellAddress,
|
||||
int $numberOfColumns,
|
||||
int $numberOfRows,
|
||||
Worksheet $worksheet
|
||||
): void {
|
||||
$remove = ($numberOfColumns < 0 || $numberOfRows < 0);
|
||||
$allCoordinates = $worksheet->getCoordinates();
|
||||
|
||||
if (
|
||||
$this->cellReferenceHelper === null ||
|
||||
$this->cellReferenceHelper->refreshRequired($beforeCellAddress, $numberOfColumns, $numberOfRows)
|
||||
) {
|
||||
$this->cellReferenceHelper = new CellReferenceHelper($beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
}
|
||||
|
||||
// Get coordinate of $beforeCellAddress
|
||||
[$beforeColumn, $beforeRow] = Coordinate::indexesFromString($beforeCellAddress);
|
||||
|
||||
|
|
@ -372,30 +384,12 @@ class ReferenceHelper
|
|||
|
||||
// 1. Clear column strips if we are removing columns
|
||||
if ($numberOfColumns < 0 && $beforeColumn - 2 + $numberOfColumns > 0) {
|
||||
for ($i = 1; $i <= $highestRow - 1; ++$i) {
|
||||
for ($j = $beforeColumn - 1 + $numberOfColumns; $j <= $beforeColumn - 2; ++$j) {
|
||||
$coordinate = Coordinate::stringFromColumnIndex($j + 1) . $i;
|
||||
$worksheet->removeConditionalStyles($coordinate);
|
||||
if ($worksheet->cellExists($coordinate)) {
|
||||
$worksheet->getCell($coordinate)->setValueExplicit('', DataType::TYPE_NULL);
|
||||
$worksheet->getCell($coordinate)->setXfIndex(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->clearColumnStrips($highestRow, $beforeColumn, $numberOfColumns, $worksheet);
|
||||
}
|
||||
|
||||
// 2. Clear row strips if we are removing rows
|
||||
if ($numberOfRows < 0 && $beforeRow - 1 + $numberOfRows > 0) {
|
||||
for ($i = $beforeColumn - 1; $i <= Coordinate::columnIndexFromString($highestColumn) - 1; ++$i) {
|
||||
for ($j = $beforeRow + $numberOfRows; $j <= $beforeRow - 1; ++$j) {
|
||||
$coordinate = Coordinate::stringFromColumnIndex($i + 1) . $j;
|
||||
$worksheet->removeConditionalStyles($coordinate);
|
||||
if ($worksheet->cellExists($coordinate)) {
|
||||
$worksheet->getCell($coordinate)->setValueExplicit('', DataType::TYPE_NULL);
|
||||
$worksheet->getCell($coordinate)->setXfIndex(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->clearRowStrips($highestColumn, $beforeColumn, $beforeRow, $numberOfRows, $worksheet);
|
||||
}
|
||||
|
||||
// Find missing coordinates. This is important when inserting column before the last column
|
||||
|
|
@ -440,7 +434,7 @@ class ReferenceHelper
|
|||
$worksheet->getCell($newCoordinate)->setXfIndex($cell->getXfIndex());
|
||||
|
||||
// Insert this cell at its new location
|
||||
if ($cell->getDataType() == DataType::TYPE_FORMULA) {
|
||||
if ($cell->getDataType() === DataType::TYPE_FORMULA) {
|
||||
// Formula should be adjusted
|
||||
$worksheet->getCell($newCoordinate)
|
||||
->setValue($this->updateFormulaReferences($cell->getValue(), $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle()));
|
||||
|
|
@ -454,7 +448,7 @@ class ReferenceHelper
|
|||
} else {
|
||||
/* We don't need to update styles for rows/columns before our insertion position,
|
||||
but we do still need to adjust any formulae in those cells */
|
||||
if ($cell->getDataType() == DataType::TYPE_FORMULA) {
|
||||
if ($cell->getDataType() === DataType::TYPE_FORMULA) {
|
||||
// Formula should be adjusted
|
||||
$cell->setValue($this->updateFormulaReferences($cell->getValue(), $beforeCellAddress, $numberOfColumns, $numberOfRows, $worksheet->getTitle()));
|
||||
}
|
||||
|
|
@ -466,148 +460,65 @@ class ReferenceHelper
|
|||
$highestRow = $worksheet->getHighestRow();
|
||||
|
||||
if ($numberOfColumns > 0 && $beforeColumn - 2 > 0) {
|
||||
for ($i = $beforeRow; $i <= $highestRow - 1; ++$i) {
|
||||
// Style
|
||||
$coordinate = Coordinate::stringFromColumnIndex($beforeColumn - 1) . $i;
|
||||
if ($worksheet->cellExists($coordinate)) {
|
||||
$xfIndex = $worksheet->getCell($coordinate)->getXfIndex();
|
||||
$conditionalStyles = $worksheet->conditionalStylesExists($coordinate) ?
|
||||
$worksheet->getConditionalStyles($coordinate) : false;
|
||||
for ($j = $beforeColumn; $j <= $beforeColumn - 1 + $numberOfColumns; ++$j) {
|
||||
$worksheet->getCellByColumnAndRow($j, $i)->setXfIndex($xfIndex);
|
||||
if ($conditionalStyles) {
|
||||
$cloned = [];
|
||||
foreach ($conditionalStyles as $conditionalStyle) {
|
||||
$cloned[] = clone $conditionalStyle;
|
||||
}
|
||||
$worksheet->setConditionalStyles(Coordinate::stringFromColumnIndex($j) . $i, $cloned);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->duplicateStylesByColumn($worksheet, $beforeColumn, $beforeRow, $highestRow, $numberOfColumns);
|
||||
}
|
||||
|
||||
if ($numberOfRows > 0 && $beforeRow - 1 > 0) {
|
||||
for ($i = $beforeColumn; $i <= Coordinate::columnIndexFromString($highestColumn); ++$i) {
|
||||
// Style
|
||||
$coordinate = Coordinate::stringFromColumnIndex($i) . ($beforeRow - 1);
|
||||
if ($worksheet->cellExists($coordinate)) {
|
||||
$xfIndex = $worksheet->getCell($coordinate)->getXfIndex();
|
||||
$conditionalStyles = $worksheet->conditionalStylesExists($coordinate) ?
|
||||
$worksheet->getConditionalStyles($coordinate) : false;
|
||||
for ($j = $beforeRow; $j <= $beforeRow - 1 + $numberOfRows; ++$j) {
|
||||
$worksheet->getCell(Coordinate::stringFromColumnIndex($i) . $j)->setXfIndex($xfIndex);
|
||||
if ($conditionalStyles) {
|
||||
$cloned = [];
|
||||
foreach ($conditionalStyles as $conditionalStyle) {
|
||||
$cloned[] = clone $conditionalStyle;
|
||||
}
|
||||
$worksheet->setConditionalStyles(Coordinate::stringFromColumnIndex($i) . $j, $cloned);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->duplicateStylesByRow($worksheet, $beforeColumn, $beforeRow, $highestColumn, $numberOfRows);
|
||||
}
|
||||
|
||||
// Update worksheet: column dimensions
|
||||
$this->adjustColumnDimensions($worksheet, $beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
$this->adjustColumnDimensions($worksheet);
|
||||
|
||||
// Update worksheet: row dimensions
|
||||
$this->adjustRowDimensions($worksheet, $beforeCellAddress, $numberOfColumns, $beforeRow, $numberOfRows);
|
||||
$this->adjustRowDimensions($worksheet, $beforeRow, $numberOfRows);
|
||||
|
||||
// Update worksheet: page breaks
|
||||
$this->adjustPageBreaks($worksheet, $beforeCellAddress, $beforeColumn, $numberOfColumns, $beforeRow, $numberOfRows);
|
||||
$this->adjustPageBreaks($worksheet, $numberOfColumns, $numberOfRows);
|
||||
|
||||
// Update worksheet: comments
|
||||
$this->adjustComments($worksheet, $beforeCellAddress, $beforeColumn, $numberOfColumns, $beforeRow, $numberOfRows);
|
||||
$this->adjustComments($worksheet);
|
||||
|
||||
// Update worksheet: hyperlinks
|
||||
$this->adjustHyperlinks($worksheet, $beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
$this->adjustHyperlinks($worksheet, $numberOfColumns, $numberOfRows);
|
||||
|
||||
// Update worksheet: conditional formatting styles
|
||||
$this->adjustConditionalFormatting($worksheet, $numberOfColumns, $numberOfRows);
|
||||
|
||||
// Update worksheet: data validations
|
||||
$this->adjustDataValidations($worksheet, $beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
$this->adjustDataValidations($worksheet, $numberOfColumns, $numberOfRows);
|
||||
|
||||
// Update worksheet: merge cells
|
||||
$this->adjustMergeCells($worksheet, $beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
$this->adjustMergeCells($worksheet);
|
||||
|
||||
// Update worksheet: protected cells
|
||||
$this->adjustProtectedCells($worksheet, $beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
$this->adjustProtectedCells($worksheet, $numberOfColumns, $numberOfRows);
|
||||
|
||||
// Update worksheet: autofilter
|
||||
$autoFilter = $worksheet->getAutoFilter();
|
||||
$autoFilterRange = $autoFilter->getRange();
|
||||
if (!empty($autoFilterRange)) {
|
||||
if ($numberOfColumns != 0) {
|
||||
$autoFilterColumns = $autoFilter->getColumns();
|
||||
if (count($autoFilterColumns) > 0) {
|
||||
$column = '';
|
||||
$row = 0;
|
||||
sscanf($beforeCellAddress, '%[A-Z]%d', $column, $row);
|
||||
$columnIndex = Coordinate::columnIndexFromString($column);
|
||||
[$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($autoFilterRange);
|
||||
if ($columnIndex <= $rangeEnd[0]) {
|
||||
if ($numberOfColumns < 0) {
|
||||
// If we're actually deleting any columns that fall within the autofilter range,
|
||||
// then we delete any rules for those columns
|
||||
$deleteColumn = $columnIndex + $numberOfColumns - 1;
|
||||
$deleteCount = abs($numberOfColumns);
|
||||
for ($i = 1; $i <= $deleteCount; ++$i) {
|
||||
if (isset($autoFilterColumns[Coordinate::stringFromColumnIndex($deleteColumn + 1)])) {
|
||||
$autoFilter->clearColumn(Coordinate::stringFromColumnIndex($deleteColumn + 1));
|
||||
}
|
||||
++$deleteColumn;
|
||||
}
|
||||
}
|
||||
$startCol = ($columnIndex > $rangeStart[0]) ? $columnIndex : $rangeStart[0];
|
||||
|
||||
// Shuffle columns in autofilter range
|
||||
if ($numberOfColumns > 0) {
|
||||
$startColRef = $startCol;
|
||||
$endColRef = $rangeEnd[0];
|
||||
$toColRef = $rangeEnd[0] + $numberOfColumns;
|
||||
|
||||
do {
|
||||
$autoFilter->shiftColumn(Coordinate::stringFromColumnIndex($endColRef), Coordinate::stringFromColumnIndex($toColRef));
|
||||
--$endColRef;
|
||||
--$toColRef;
|
||||
} while ($startColRef <= $endColRef);
|
||||
} else {
|
||||
// For delete, we shuffle from beginning to end to avoid overwriting
|
||||
$startColID = Coordinate::stringFromColumnIndex($startCol);
|
||||
$toColID = Coordinate::stringFromColumnIndex($startCol + $numberOfColumns);
|
||||
$endColID = Coordinate::stringFromColumnIndex($rangeEnd[0] + 1);
|
||||
do {
|
||||
$autoFilter->shiftColumn($startColID, $toColID);
|
||||
++$startColID;
|
||||
++$toColID;
|
||||
} while ($startColID != $endColID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$worksheet->setAutoFilter($this->updateCellReference($autoFilterRange, $beforeCellAddress, $numberOfColumns, $numberOfRows));
|
||||
}
|
||||
$this->adjustAutoFilter($worksheet, $beforeCellAddress, $numberOfColumns);
|
||||
|
||||
// Update worksheet: freeze pane
|
||||
if ($worksheet->getFreezePane()) {
|
||||
$splitCell = $worksheet->getFreezePane() ?? '';
|
||||
$topLeftCell = $worksheet->getTopLeftCell() ?? '';
|
||||
|
||||
$splitCell = $this->updateCellReference($splitCell, $beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
$topLeftCell = $this->updateCellReference($topLeftCell, $beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
$splitCell = $this->updateCellReference($splitCell);
|
||||
$topLeftCell = $this->updateCellReference($topLeftCell);
|
||||
|
||||
$worksheet->freezePane($splitCell, $topLeftCell);
|
||||
}
|
||||
|
||||
// Page setup
|
||||
if ($worksheet->getPageSetup()->isPrintAreaSet()) {
|
||||
$worksheet->getPageSetup()->setPrintArea($this->updateCellReference($worksheet->getPageSetup()->getPrintArea(), $beforeCellAddress, $numberOfColumns, $numberOfRows));
|
||||
$worksheet->getPageSetup()->setPrintArea(
|
||||
$this->updateCellReference($worksheet->getPageSetup()->getPrintArea())
|
||||
);
|
||||
}
|
||||
|
||||
// Update worksheet: drawings
|
||||
$aDrawings = $worksheet->getDrawingCollection();
|
||||
foreach ($aDrawings as $objDrawing) {
|
||||
$newReference = $this->updateCellReference($objDrawing->getCoordinates(), $beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
$newReference = $this->updateCellReference($objDrawing->getCoordinates());
|
||||
if ($objDrawing->getCoordinates() != $newReference) {
|
||||
$objDrawing->setCoordinates($newReference);
|
||||
}
|
||||
|
|
@ -617,7 +528,7 @@ class ReferenceHelper
|
|||
if (count($worksheet->getParent()->getDefinedNames()) > 0) {
|
||||
foreach ($worksheet->getParent()->getDefinedNames() as $definedName) {
|
||||
if ($definedName->getWorksheet() !== null && $definedName->getWorksheet()->getHashCode() === $worksheet->getHashCode()) {
|
||||
$definedName->setValue($this->updateCellReference($definedName->getValue(), $beforeCellAddress, $numberOfColumns, $numberOfRows));
|
||||
$definedName->setValue($this->updateCellReference($definedName->getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -637,8 +548,21 @@ class ReferenceHelper
|
|||
*
|
||||
* @return string Updated formula
|
||||
*/
|
||||
public function updateFormulaReferences($formula = '', $beforeCellAddress = 'A1', $numberOfColumns = 0, $numberOfRows = 0, $worksheetName = '')
|
||||
{
|
||||
public function updateFormulaReferences(
|
||||
$formula = '',
|
||||
$beforeCellAddress = 'A1',
|
||||
$numberOfColumns = 0,
|
||||
$numberOfRows = 0,
|
||||
$worksheetName = '',
|
||||
bool $includeAbsoluteReferences = false
|
||||
) {
|
||||
if (
|
||||
$this->cellReferenceHelper === null ||
|
||||
$this->cellReferenceHelper->refreshRequired($beforeCellAddress, $numberOfColumns, $numberOfRows)
|
||||
) {
|
||||
$this->cellReferenceHelper = new CellReferenceHelper($beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
}
|
||||
|
||||
// Update cell references in the formula
|
||||
$formulaBlocks = explode('"', $formula);
|
||||
$i = false;
|
||||
|
|
@ -648,13 +572,13 @@ class ReferenceHelper
|
|||
$adjustCount = 0;
|
||||
$newCellTokens = $cellTokens = [];
|
||||
// Search for row ranges (e.g. 'Sheet1'!3:5 or 3:5) with or without $ absolutes (e.g. $3:5)
|
||||
$matchCount = preg_match_all('/' . self::REFHELPER_REGEXP_ROWRANGE . '/i', ' ' . $formulaBlock . ' ', $matches, PREG_SET_ORDER);
|
||||
$matchCount = preg_match_all('/' . self::REFHELPER_REGEXP_ROWRANGE . '/mui', ' ' . $formulaBlock . ' ', $matches, PREG_SET_ORDER);
|
||||
if ($matchCount > 0) {
|
||||
foreach ($matches as $match) {
|
||||
$fromString = ($match[2] > '') ? $match[2] . '!' : '';
|
||||
$fromString .= $match[3] . ':' . $match[4];
|
||||
$modified3 = substr($this->updateCellReference('$A' . $match[3], $beforeCellAddress, $numberOfColumns, $numberOfRows), 2);
|
||||
$modified4 = substr($this->updateCellReference('$A' . $match[4], $beforeCellAddress, $numberOfColumns, $numberOfRows), 2);
|
||||
$modified3 = substr($this->updateCellReference('$A' . $match[3], $includeAbsoluteReferences), 2);
|
||||
$modified4 = substr($this->updateCellReference('$A' . $match[4], $includeAbsoluteReferences), 2);
|
||||
|
||||
if ($match[3] . ':' . $match[4] !== $modified3 . ':' . $modified4) {
|
||||
if (($match[2] == '') || (trim($match[2], "'") == $worksheetName)) {
|
||||
|
|
@ -673,13 +597,13 @@ class ReferenceHelper
|
|||
}
|
||||
}
|
||||
// Search for column ranges (e.g. 'Sheet1'!C:E or C:E) with or without $ absolutes (e.g. $C:E)
|
||||
$matchCount = preg_match_all('/' . self::REFHELPER_REGEXP_COLRANGE . '/i', ' ' . $formulaBlock . ' ', $matches, PREG_SET_ORDER);
|
||||
$matchCount = preg_match_all('/' . self::REFHELPER_REGEXP_COLRANGE . '/mui', ' ' . $formulaBlock . ' ', $matches, PREG_SET_ORDER);
|
||||
if ($matchCount > 0) {
|
||||
foreach ($matches as $match) {
|
||||
$fromString = ($match[2] > '') ? $match[2] . '!' : '';
|
||||
$fromString .= $match[3] . ':' . $match[4];
|
||||
$modified3 = substr($this->updateCellReference($match[3] . '$1', $beforeCellAddress, $numberOfColumns, $numberOfRows), 0, -2);
|
||||
$modified4 = substr($this->updateCellReference($match[4] . '$1', $beforeCellAddress, $numberOfColumns, $numberOfRows), 0, -2);
|
||||
$modified3 = substr($this->updateCellReference($match[3] . '$1', $includeAbsoluteReferences), 0, -2);
|
||||
$modified4 = substr($this->updateCellReference($match[4] . '$1', $includeAbsoluteReferences), 0, -2);
|
||||
|
||||
if ($match[3] . ':' . $match[4] !== $modified3 . ':' . $modified4) {
|
||||
if (($match[2] == '') || (trim($match[2], "'") == $worksheetName)) {
|
||||
|
|
@ -698,13 +622,13 @@ class ReferenceHelper
|
|||
}
|
||||
}
|
||||
// Search for cell ranges (e.g. 'Sheet1'!A3:C5 or A3:C5) with or without $ absolutes (e.g. $A1:C$5)
|
||||
$matchCount = preg_match_all('/' . self::REFHELPER_REGEXP_CELLRANGE . '/i', ' ' . $formulaBlock . ' ', $matches, PREG_SET_ORDER);
|
||||
$matchCount = preg_match_all('/' . self::REFHELPER_REGEXP_CELLRANGE . '/mui', ' ' . $formulaBlock . ' ', $matches, PREG_SET_ORDER);
|
||||
if ($matchCount > 0) {
|
||||
foreach ($matches as $match) {
|
||||
$fromString = ($match[2] > '') ? $match[2] . '!' : '';
|
||||
$fromString .= $match[3] . ':' . $match[4];
|
||||
$modified3 = $this->updateCellReference($match[3], $beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
$modified4 = $this->updateCellReference($match[4], $beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
$modified3 = $this->updateCellReference($match[3], $includeAbsoluteReferences);
|
||||
$modified4 = $this->updateCellReference($match[4], $includeAbsoluteReferences);
|
||||
|
||||
if ($match[3] . $match[4] !== $modified3 . $modified4) {
|
||||
if (($match[2] == '') || (trim($match[2], "'") == $worksheetName)) {
|
||||
|
|
@ -724,14 +648,14 @@ class ReferenceHelper
|
|||
}
|
||||
}
|
||||
// Search for cell references (e.g. 'Sheet1'!A3 or C5) with or without $ absolutes (e.g. $A1 or C$5)
|
||||
$matchCount = preg_match_all('/' . self::REFHELPER_REGEXP_CELLREF . '/i', ' ' . $formulaBlock . ' ', $matches, PREG_SET_ORDER);
|
||||
$matchCount = preg_match_all('/' . self::REFHELPER_REGEXP_CELLREF . '/mui', ' ' . $formulaBlock . ' ', $matches, PREG_SET_ORDER);
|
||||
|
||||
if ($matchCount > 0) {
|
||||
foreach ($matches as $match) {
|
||||
$fromString = ($match[2] > '') ? $match[2] . '!' : '';
|
||||
$fromString .= $match[3];
|
||||
|
||||
$modified3 = $this->updateCellReference($match[3], $beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
$modified3 = $this->updateCellReference($match[3], $includeAbsoluteReferences);
|
||||
if ($match[3] !== $modified3) {
|
||||
if (($match[2] == '') || (trim($match[2], "'") == $worksheetName)) {
|
||||
$toString = ($match[2] > '') ? $match[2] . '!' : '';
|
||||
|
|
@ -908,13 +832,10 @@ class ReferenceHelper
|
|||
* Update cell reference.
|
||||
*
|
||||
* @param string $cellReference Cell address or range of addresses
|
||||
* @param string $beforeCellAddress Insert before this one
|
||||
* @param int $numberOfColumns Number of columns to increment
|
||||
* @param int $numberOfRows Number of rows to increment
|
||||
*
|
||||
* @return string Updated cell range
|
||||
*/
|
||||
public function updateCellReference($cellReference = 'A1', $beforeCellAddress = 'A1', $numberOfColumns = 0, $numberOfRows = 0)
|
||||
private function updateCellReference($cellReference = 'A1', bool $includeAbsoluteReferences = false)
|
||||
{
|
||||
// Is it in another worksheet? Will not have to update anything.
|
||||
if (strpos($cellReference, '!') !== false) {
|
||||
|
|
@ -922,10 +843,10 @@ class ReferenceHelper
|
|||
// Is it a range or a single cell?
|
||||
} elseif (!Coordinate::coordinateIsRange($cellReference)) {
|
||||
// Single cell
|
||||
return $this->updateSingleCellReference($cellReference, $beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
return $this->cellReferenceHelper->updateCellReference($cellReference, $includeAbsoluteReferences);
|
||||
} elseif (Coordinate::coordinateIsRange($cellReference)) {
|
||||
// Range
|
||||
return $this->updateCellRange($cellReference, $beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
return $this->updateCellRange($cellReference, $includeAbsoluteReferences);
|
||||
}
|
||||
|
||||
// Return original
|
||||
|
|
@ -948,7 +869,7 @@ class ReferenceHelper
|
|||
foreach ($spreadsheet->getWorksheetIterator() as $sheet) {
|
||||
foreach ($sheet->getCoordinates(false) as $coordinate) {
|
||||
$cell = $sheet->getCell($coordinate);
|
||||
if (($cell !== null) && ($cell->getDataType() == DataType::TYPE_FORMULA)) {
|
||||
if (($cell !== null) && ($cell->getDataType() === DataType::TYPE_FORMULA)) {
|
||||
$formula = $cell->getValue();
|
||||
if (strpos($formula, $oldName) !== false) {
|
||||
$formula = str_replace("'" . $oldName . "'!", "'" . $newName . "'!", $formula);
|
||||
|
|
@ -964,13 +885,10 @@ class ReferenceHelper
|
|||
* Update cell range.
|
||||
*
|
||||
* @param string $cellRange Cell range (e.g. 'B2:D4', 'B:C' or '2:3')
|
||||
* @param string $beforeCellAddress Insert before this one
|
||||
* @param int $numberOfColumns Number of columns to increment
|
||||
* @param int $numberOfRows Number of rows to increment
|
||||
*
|
||||
* @return string Updated cell range
|
||||
*/
|
||||
private function updateCellRange($cellRange = 'A1:A1', $beforeCellAddress = 'A1', $numberOfColumns = 0, $numberOfRows = 0)
|
||||
private function updateCellRange(string $cellRange = 'A1:A1', bool $includeAbsoluteReferences = false): string
|
||||
{
|
||||
if (!Coordinate::coordinateIsRange($cellRange)) {
|
||||
throw new Exception('Only cell ranges may be passed to this method.');
|
||||
|
|
@ -983,13 +901,15 @@ class ReferenceHelper
|
|||
$jc = count($range[$i]);
|
||||
for ($j = 0; $j < $jc; ++$j) {
|
||||
if (ctype_alpha($range[$i][$j])) {
|
||||
$r = Coordinate::coordinateFromString($this->updateSingleCellReference($range[$i][$j] . '1', $beforeCellAddress, $numberOfColumns, $numberOfRows));
|
||||
$range[$i][$j] = $r[0];
|
||||
$range[$i][$j] = Coordinate::coordinateFromString(
|
||||
$this->cellReferenceHelper->updateCellReference($range[$i][$j] . '1', $includeAbsoluteReferences)
|
||||
)[0];
|
||||
} elseif (ctype_digit($range[$i][$j])) {
|
||||
$r = Coordinate::coordinateFromString($this->updateSingleCellReference('A' . $range[$i][$j], $beforeCellAddress, $numberOfColumns, $numberOfRows));
|
||||
$range[$i][$j] = $r[1];
|
||||
$range[$i][$j] = Coordinate::coordinateFromString(
|
||||
$this->cellReferenceHelper->updateCellReference('A' . $range[$i][$j], $includeAbsoluteReferences)
|
||||
)[1];
|
||||
} else {
|
||||
$range[$i][$j] = $this->updateSingleCellReference($range[$i][$j], $beforeCellAddress, $numberOfColumns, $numberOfRows);
|
||||
$range[$i][$j] = $this->cellReferenceHelper->updateCellReference($range[$i][$j], $includeAbsoluteReferences);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -998,44 +918,142 @@ class ReferenceHelper
|
|||
return Coordinate::buildRange($range);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update single cell reference.
|
||||
*
|
||||
* @param string $cellReference Single cell reference
|
||||
* @param string $beforeCellAddress Insert before this one
|
||||
* @param int $numberOfColumns Number of columns to increment
|
||||
* @param int $numberOfRows Number of rows to increment
|
||||
*
|
||||
* @return string Updated cell reference
|
||||
*/
|
||||
private function updateSingleCellReference($cellReference = 'A1', $beforeCellAddress = 'A1', $numberOfColumns = 0, $numberOfRows = 0)
|
||||
private function clearColumnStrips(int $highestRow, int $beforeColumn, int $numberOfColumns, Worksheet $worksheet): void
|
||||
{
|
||||
if (Coordinate::coordinateIsRange($cellReference)) {
|
||||
throw new Exception('Only single cell references may be passed to this method.');
|
||||
for ($i = 1; $i <= $highestRow - 1; ++$i) {
|
||||
for ($j = $beforeColumn - 1 + $numberOfColumns; $j <= $beforeColumn - 2; ++$j) {
|
||||
$coordinate = Coordinate::stringFromColumnIndex($j + 1) . $i;
|
||||
$worksheet->removeConditionalStyles($coordinate);
|
||||
if ($worksheet->cellExists($coordinate)) {
|
||||
$worksheet->getCell($coordinate)->setValueExplicit('', DataType::TYPE_NULL);
|
||||
$worksheet->getCell($coordinate)->setXfIndex(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get coordinate of $beforeCellAddress
|
||||
[$beforeColumn, $beforeRow] = Coordinate::coordinateFromString($beforeCellAddress);
|
||||
private function clearRowStrips(string $highestColumn, int $beforeColumn, int $beforeRow, int $numberOfRows, Worksheet $worksheet): void
|
||||
{
|
||||
$lastColumnIndex = Coordinate::columnIndexFromString($highestColumn) - 1;
|
||||
|
||||
// Get coordinate of $cellReference
|
||||
[$newColumn, $newRow] = Coordinate::coordinateFromString($cellReference);
|
||||
|
||||
// Verify which parts should be updated
|
||||
$updateColumn = (($newColumn[0] != '$') && ($beforeColumn[0] != '$') && (Coordinate::columnIndexFromString($newColumn) >= Coordinate::columnIndexFromString($beforeColumn)));
|
||||
$updateRow = (($newRow[0] != '$') && ($beforeRow[0] != '$') && $newRow >= $beforeRow);
|
||||
|
||||
// Create new column reference
|
||||
if ($updateColumn) {
|
||||
$newColumn = Coordinate::stringFromColumnIndex(Coordinate::columnIndexFromString($newColumn) + $numberOfColumns);
|
||||
for ($i = $beforeColumn - 1; $i <= $lastColumnIndex; ++$i) {
|
||||
for ($j = $beforeRow + $numberOfRows; $j <= $beforeRow - 1; ++$j) {
|
||||
$coordinate = Coordinate::stringFromColumnIndex($i + 1) . $j;
|
||||
$worksheet->removeConditionalStyles($coordinate);
|
||||
if ($worksheet->cellExists($coordinate)) {
|
||||
$worksheet->getCell($coordinate)->setValueExplicit('', DataType::TYPE_NULL);
|
||||
$worksheet->getCell($coordinate)->setXfIndex(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create new row reference
|
||||
if ($updateRow) {
|
||||
$newRow = (int) $newRow + $numberOfRows;
|
||||
private function adjustAutoFilter(Worksheet $worksheet, string $beforeCellAddress, int $numberOfColumns): void
|
||||
{
|
||||
$autoFilter = $worksheet->getAutoFilter();
|
||||
$autoFilterRange = $autoFilter->getRange();
|
||||
if (!empty($autoFilterRange)) {
|
||||
if ($numberOfColumns !== 0) {
|
||||
$autoFilterColumns = $autoFilter->getColumns();
|
||||
if (count($autoFilterColumns) > 0) {
|
||||
$column = '';
|
||||
$row = 0;
|
||||
sscanf($beforeCellAddress, '%[A-Z]%d', $column, $row);
|
||||
$columnIndex = Coordinate::columnIndexFromString($column);
|
||||
[$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($autoFilterRange);
|
||||
if ($columnIndex <= $rangeEnd[0]) {
|
||||
if ($numberOfColumns < 0) {
|
||||
$this->adjustAutoFilterDeleteRules($columnIndex, $numberOfColumns, $autoFilterColumns, $autoFilter);
|
||||
}
|
||||
$startCol = ($columnIndex > $rangeStart[0]) ? $columnIndex : $rangeStart[0];
|
||||
|
||||
// Shuffle columns in autofilter range
|
||||
if ($numberOfColumns > 0) {
|
||||
$this->adjustAutoFilterInsert($startCol, $numberOfColumns, $rangeEnd[0], $autoFilter);
|
||||
} else {
|
||||
$this->adjustAutoFilterDelete($startCol, $numberOfColumns, $rangeEnd[0], $autoFilter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$worksheet->setAutoFilter(
|
||||
$this->updateCellReference($autoFilterRange)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Return new reference
|
||||
return $newColumn . $newRow;
|
||||
private function adjustAutoFilterDeleteRules(int $columnIndex, int $numberOfColumns, array $autoFilterColumns, AutoFilter $autoFilter): void
|
||||
{
|
||||
// If we're actually deleting any columns that fall within the autofilter range,
|
||||
// then we delete any rules for those columns
|
||||
$deleteColumn = $columnIndex + $numberOfColumns - 1;
|
||||
$deleteCount = abs($numberOfColumns);
|
||||
|
||||
for ($i = 1; $i <= $deleteCount; ++$i) {
|
||||
$columnName = Coordinate::stringFromColumnIndex($deleteColumn + 1);
|
||||
if (isset($autoFilterColumns[$columnName])) {
|
||||
$autoFilter->clearColumn($columnName);
|
||||
}
|
||||
++$deleteColumn;
|
||||
}
|
||||
}
|
||||
|
||||
private function adjustAutoFilterInsert(int $startCol, int $numberOfColumns, int $rangeEnd, AutoFilter $autoFilter): void
|
||||
{
|
||||
$startColRef = $startCol;
|
||||
$endColRef = $rangeEnd;
|
||||
$toColRef = $rangeEnd + $numberOfColumns;
|
||||
|
||||
do {
|
||||
$autoFilter->shiftColumn(Coordinate::stringFromColumnIndex($endColRef), Coordinate::stringFromColumnIndex($toColRef));
|
||||
--$endColRef;
|
||||
--$toColRef;
|
||||
} while ($startColRef <= $endColRef);
|
||||
}
|
||||
|
||||
private function adjustAutoFilterDelete(int $startCol, int $numberOfColumns, int $rangeEnd, AutoFilter $autoFilter): void
|
||||
{
|
||||
// For delete, we shuffle from beginning to end to avoid overwriting
|
||||
$startColID = Coordinate::stringFromColumnIndex($startCol);
|
||||
$toColID = Coordinate::stringFromColumnIndex($startCol + $numberOfColumns);
|
||||
$endColID = Coordinate::stringFromColumnIndex($rangeEnd + 1);
|
||||
|
||||
do {
|
||||
$autoFilter->shiftColumn($startColID, $toColID);
|
||||
++$startColID;
|
||||
++$toColID;
|
||||
} while ($startColID !== $endColID);
|
||||
}
|
||||
|
||||
private function duplicateStylesByColumn(Worksheet $worksheet, int $beforeColumn, int $beforeRow, int $highestRow, int $numberOfColumns): void
|
||||
{
|
||||
$beforeColumnName = Coordinate::stringFromColumnIndex($beforeColumn - 1);
|
||||
for ($i = $beforeRow; $i <= $highestRow - 1; ++$i) {
|
||||
// Style
|
||||
$coordinate = $beforeColumnName . $i;
|
||||
if ($worksheet->cellExists($coordinate)) {
|
||||
$xfIndex = $worksheet->getCell($coordinate)->getXfIndex();
|
||||
for ($j = $beforeColumn; $j <= $beforeColumn - 1 + $numberOfColumns; ++$j) {
|
||||
$worksheet->getCellByColumnAndRow($j, $i)->setXfIndex($xfIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function duplicateStylesByRow(Worksheet $worksheet, int $beforeColumn, int $beforeRow, string $highestColumn, int $numberOfRows): void
|
||||
{
|
||||
$highestColumnIndex = Coordinate::columnIndexFromString($highestColumn);
|
||||
for ($i = $beforeColumn; $i <= $highestColumnIndex; ++$i) {
|
||||
// Style
|
||||
$coordinate = Coordinate::stringFromColumnIndex($i) . ($beforeRow - 1);
|
||||
if ($worksheet->cellExists($coordinate)) {
|
||||
$xfIndex = $worksheet->getCell($coordinate)->getXfIndex();
|
||||
for ($j = $beforeRow; $j <= $beforeRow - 1 + $numberOfRows; ++$j) {
|
||||
$worksheet->getCell(Coordinate::stringFromColumnIndex($i) . $j)->setXfIndex($xfIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -164,11 +164,15 @@ class Drawing
|
|||
{
|
||||
// Load the image into a string
|
||||
$file = fopen($bmpFilename, 'rb');
|
||||
/** @phpstan-ignore-next-line */
|
||||
$read = fread($file, 10);
|
||||
// @phpstan-ignore-next-line
|
||||
while (!feof($file) && ($read != '')) {
|
||||
// @phpstan-ignore-next-line
|
||||
$read .= fread($file, 1024);
|
||||
}
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
$temp = unpack('H*', $read);
|
||||
$hex = $temp[1];
|
||||
$header = substr($hex, 0, 108);
|
||||
|
|
@ -196,6 +200,8 @@ class Drawing
|
|||
$y = 1;
|
||||
|
||||
// Create newimage
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
$image = imagecreatetruecolor($width, $height);
|
||||
|
||||
// Grab the body from the image
|
||||
|
|
@ -241,7 +247,10 @@ class Drawing
|
|||
$b = hexdec($body[$i_pos] . $body[$i_pos + 1]);
|
||||
|
||||
// Calculate and draw the pixel
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
$color = imagecolorallocate($image, $r, $g, $b);
|
||||
// @phpstan-ignore-next-line
|
||||
imagesetpixel($image, $x, $height - $y, $color);
|
||||
|
||||
// Raise the horizontal position
|
||||
|
|
@ -252,6 +261,7 @@ class Drawing
|
|||
unset($body);
|
||||
|
||||
// Return image-object
|
||||
// @phpstan-ignore-next-line
|
||||
return $image;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1134,6 +1134,7 @@ class Matrix
|
|||
$this->checkMatrixDimensions($M);
|
||||
for ($i = 0; $i < $this->m; ++$i) {
|
||||
for ($j = 0; $j < $this->n; ++$j) {
|
||||
// @phpstan-ignore-next-line
|
||||
$this->A[$i][$j] = trim($this->A[$i][$j], '"') . trim($M->get($i, $j), '"');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -251,6 +251,7 @@ class OLE
|
|||
*/
|
||||
private static function readInt1($fileHandle)
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
[, $tmp] = unpack('c', fread($fileHandle, 1));
|
||||
|
||||
return $tmp;
|
||||
|
|
@ -265,6 +266,7 @@ class OLE
|
|||
*/
|
||||
private static function readInt2($fileHandle)
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
[, $tmp] = unpack('v', fread($fileHandle, 2));
|
||||
|
||||
return $tmp;
|
||||
|
|
@ -279,6 +281,7 @@ class OLE
|
|||
*/
|
||||
private static function readInt4($fileHandle)
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
[, $tmp] = unpack('V', fread($fileHandle, 4));
|
||||
|
||||
return $tmp;
|
||||
|
|
|
|||
|
|
@ -160,6 +160,7 @@ class ChainedBlockStream
|
|||
$this->pos = $offset;
|
||||
} elseif ($whence == SEEK_CUR && -$offset <= $this->pos) {
|
||||
$this->pos += $offset;
|
||||
// @phpstan-ignore-next-line
|
||||
} elseif ($whence == SEEK_END && -$offset <= count($this->data)) {
|
||||
$this->pos = strlen($this->data) + $offset;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ class PolynomialBestFit extends BestFit
|
|||
|
||||
public function getCoefficients($dp = 0)
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
return array_merge([$this->getIntersect($dp)], $this->getSlope($dp));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,9 @@ class XMLWriter extends \XMLWriter
|
|||
public function __destruct()
|
||||
{
|
||||
// Unlink temporary files
|
||||
// There is nothing reasonable to do if unlink fails.
|
||||
if ($this->tempFileName != '') {
|
||||
/** @scrutinizer ignore-unhandled */
|
||||
@unlink($this->tempFileName);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ abstract class WizardAbstract
|
|||
return "{$worksheet}{$column}{$row}";
|
||||
}
|
||||
|
||||
protected static function reverseAdjustCellRef(string $condition, string $cellRange): string
|
||||
public static function reverseAdjustCellRef(string $condition, string $cellRange): string
|
||||
{
|
||||
$conditionalRange = Coordinate::splitRange(str_replace('$', '', strtoupper($cellRange)));
|
||||
[$referenceCell] = $conditionalRange[0];
|
||||
|
|
|
|||
|
|
@ -85,6 +85,8 @@ class DateFormatter
|
|||
$format = preg_replace_callback('/(?:^|")([^"]*)(?:$|")/', $callable, $format);
|
||||
|
||||
// Only process the non-quoted blocks for date format characters
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
$blocks = explode('"', $format);
|
||||
foreach ($blocks as $key => &$block) {
|
||||
if ($key % 2 == 0) {
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ class Column
|
|||
* Set An AutoFilter Attribute.
|
||||
*
|
||||
* @param string $name Attribute Name
|
||||
* @param string $value Attribute Value
|
||||
* @param int|string $value Attribute Value
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -8,6 +8,22 @@ use PhpOffice\PhpSpreadsheet\IComparable;
|
|||
|
||||
class BaseDrawing implements IComparable
|
||||
{
|
||||
const EDIT_AS_ABSOLUTE = 'absolute';
|
||||
const EDIT_AS_ONECELL = 'onecell';
|
||||
const EDIT_AS_TWOCELL = 'twocell';
|
||||
private const VALID_EDIT_AS = [
|
||||
self::EDIT_AS_ABSOLUTE,
|
||||
self::EDIT_AS_ONECELL,
|
||||
self::EDIT_AS_TWOCELL,
|
||||
];
|
||||
|
||||
/**
|
||||
* The editAs attribute, used only with two cell anchor.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $editAs = '';
|
||||
|
||||
/**
|
||||
* Image counter.
|
||||
*
|
||||
|
|
@ -27,14 +43,14 @@ class BaseDrawing implements IComparable
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name;
|
||||
protected $name = '';
|
||||
|
||||
/**
|
||||
* Description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description;
|
||||
protected $description = '';
|
||||
|
||||
/**
|
||||
* Worksheet.
|
||||
|
|
@ -48,70 +64,84 @@ class BaseDrawing implements IComparable
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $coordinates;
|
||||
protected $coordinates = 'A1';
|
||||
|
||||
/**
|
||||
* Offset X.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $offsetX;
|
||||
protected $offsetX = 0;
|
||||
|
||||
/**
|
||||
* Offset Y.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $offsetY;
|
||||
protected $offsetY = 0;
|
||||
|
||||
/**
|
||||
* Coordinates2.
|
||||
*
|
||||
* @var null|string
|
||||
* @var string
|
||||
*/
|
||||
protected $coordinates2;
|
||||
protected $coordinates2 = '';
|
||||
|
||||
/**
|
||||
* Offset X2.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $offsetX2;
|
||||
protected $offsetX2 = 0;
|
||||
|
||||
/**
|
||||
* Offset Y2.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $offsetY2;
|
||||
protected $offsetY2 = 0;
|
||||
|
||||
/**
|
||||
* Width.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $width;
|
||||
protected $width = 0;
|
||||
|
||||
/**
|
||||
* Height.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $height;
|
||||
protected $height = 0;
|
||||
|
||||
/**
|
||||
* Pixel width of image. See $width for the size the Drawing will be in the sheet.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $imageWidth = 0;
|
||||
|
||||
/**
|
||||
* Pixel width of image. See $height for the size the Drawing will be in the sheet.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $imageHeight = 0;
|
||||
|
||||
/**
|
||||
* Proportional resize.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $resizeProportional;
|
||||
protected $resizeProportional = true;
|
||||
|
||||
/**
|
||||
* Rotation.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $rotation;
|
||||
protected $rotation = 0;
|
||||
|
||||
/**
|
||||
* Shadow.
|
||||
|
|
@ -132,7 +162,7 @@ class BaseDrawing implements IComparable
|
|||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $type;
|
||||
protected $type = IMAGETYPE_UNKNOWN;
|
||||
|
||||
/**
|
||||
* Create a new BaseDrawing.
|
||||
|
|
@ -140,91 +170,43 @@ class BaseDrawing implements IComparable
|
|||
public function __construct()
|
||||
{
|
||||
// Initialise values
|
||||
$this->name = '';
|
||||
$this->description = '';
|
||||
$this->worksheet = null;
|
||||
$this->coordinates = 'A1';
|
||||
$this->offsetX = 0;
|
||||
$this->offsetY = 0;
|
||||
$this->coordinates2 = null;
|
||||
$this->offsetX2 = 0;
|
||||
$this->offsetY2 = 0;
|
||||
$this->width = 0;
|
||||
$this->height = 0;
|
||||
$this->resizeProportional = true;
|
||||
$this->rotation = 0;
|
||||
$this->shadow = new Drawing\Shadow();
|
||||
$this->type = IMAGETYPE_UNKNOWN;
|
||||
$this->setShadow();
|
||||
|
||||
// Set image index
|
||||
++self::$imageCounter;
|
||||
$this->imageIndex = self::$imageCounter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image index.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getImageIndex()
|
||||
public function getImageIndex(): int
|
||||
{
|
||||
return $this->imageIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Name.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setName($name)
|
||||
public function setName(string $name): self
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Description.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription()
|
||||
public function getDescription(): string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Description.
|
||||
*
|
||||
* @param string $description
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setDescription($description)
|
||||
public function setDescription(string $description): self
|
||||
{
|
||||
$this->description = $description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Worksheet.
|
||||
*
|
||||
* @return null|Worksheet
|
||||
*/
|
||||
public function getWorksheet()
|
||||
public function getWorksheet(): ?Worksheet
|
||||
{
|
||||
return $this->worksheet;
|
||||
}
|
||||
|
|
@ -233,16 +215,16 @@ class BaseDrawing implements IComparable
|
|||
* Set Worksheet.
|
||||
*
|
||||
* @param bool $overrideOld If a Worksheet has already been assigned, overwrite it and remove image from old Worksheet?
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setWorksheet(?Worksheet $worksheet = null, $overrideOld = false)
|
||||
public function setWorksheet(?Worksheet $worksheet = null, bool $overrideOld = false): self
|
||||
{
|
||||
if ($this->worksheet === null) {
|
||||
// Add drawing to \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet
|
||||
$this->worksheet = $worksheet;
|
||||
$this->worksheet->getCell($this->coordinates);
|
||||
$this->worksheet->getDrawingCollection()->append($this);
|
||||
if ($worksheet !== null) {
|
||||
$this->worksheet = $worksheet;
|
||||
$this->worksheet->getCell($this->coordinates);
|
||||
$this->worksheet->getDrawingCollection()->append($this);
|
||||
}
|
||||
} else {
|
||||
if ($overrideOld) {
|
||||
// Remove drawing from old \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet
|
||||
|
|
@ -267,168 +249,84 @@ class BaseDrawing implements IComparable
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Coordinates.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCoordinates()
|
||||
public function getCoordinates(): string
|
||||
{
|
||||
return $this->coordinates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Coordinates.
|
||||
*
|
||||
* @param string $coordinates eg: 'A1'
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setCoordinates($coordinates)
|
||||
public function setCoordinates(string $coordinates): self
|
||||
{
|
||||
$this->coordinates = $coordinates;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get OffsetX.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getOffsetX()
|
||||
public function getOffsetX(): int
|
||||
{
|
||||
return $this->offsetX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set OffsetX.
|
||||
*
|
||||
* @param int $offsetX
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setOffsetX($offsetX)
|
||||
public function setOffsetX(int $offsetX): self
|
||||
{
|
||||
$this->offsetX = $offsetX;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get OffsetY.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getOffsetY()
|
||||
public function getOffsetY(): int
|
||||
{
|
||||
return $this->offsetY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Coordinates2.
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function getCoordinates2()
|
||||
{
|
||||
return $this->coordinates2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Coordinates2.
|
||||
*
|
||||
* @param null|string $coordinates2 eg: 'A1'
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setCoordinates2($coordinates2)
|
||||
{
|
||||
$this->coordinates2 = $coordinates2;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get OffsetX2.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getOffsetX2()
|
||||
{
|
||||
return $this->offsetX2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set OffsetX2.
|
||||
*
|
||||
* @param int $offsetX2
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setOffsetX2($offsetX2)
|
||||
{
|
||||
$this->offsetX2 = $offsetX2;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get OffsetY2.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getOffsetY2()
|
||||
{
|
||||
return $this->offsetY2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set OffsetY2.
|
||||
*
|
||||
* @param int $offsetY2
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setOffsetY2($offsetY2)
|
||||
{
|
||||
$this->offsetY2 = $offsetY2;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set OffsetY.
|
||||
*
|
||||
* @param int $offsetY
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setOffsetY($offsetY)
|
||||
public function setOffsetY(int $offsetY): self
|
||||
{
|
||||
$this->offsetY = $offsetY;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Width.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getWidth()
|
||||
public function getCoordinates2(): string
|
||||
{
|
||||
return $this->coordinates2;
|
||||
}
|
||||
|
||||
public function setCoordinates2(string $coordinates2): self
|
||||
{
|
||||
$this->coordinates2 = $coordinates2;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOffsetX2(): int
|
||||
{
|
||||
return $this->offsetX2;
|
||||
}
|
||||
|
||||
public function setOffsetX2(int $offsetX2): self
|
||||
{
|
||||
$this->offsetX2 = $offsetX2;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOffsetY2(): int
|
||||
{
|
||||
return $this->offsetY2;
|
||||
}
|
||||
|
||||
public function setOffsetY2(int $offsetY2): self
|
||||
{
|
||||
$this->offsetY2 = $offsetY2;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getWidth(): int
|
||||
{
|
||||
return $this->width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Width.
|
||||
*
|
||||
* @param int $width
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setWidth($width)
|
||||
public function setWidth(int $width): self
|
||||
{
|
||||
// Resize proportional?
|
||||
if ($this->resizeProportional && $width != 0) {
|
||||
|
|
@ -442,24 +340,12 @@ class BaseDrawing implements IComparable
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Height.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHeight()
|
||||
public function getHeight(): int
|
||||
{
|
||||
return $this->height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Height.
|
||||
*
|
||||
* @param int $height
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setHeight($height)
|
||||
public function setHeight(int $height): self
|
||||
{
|
||||
// Resize proportional?
|
||||
if ($this->resizeProportional && $height != 0) {
|
||||
|
|
@ -482,14 +368,9 @@ class BaseDrawing implements IComparable
|
|||
* $objDrawing->setWidthAndHeight(160,120);
|
||||
* </code>
|
||||
*
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @author Vincent@luo MSN:kele_100@hotmail.com
|
||||
*/
|
||||
public function setWidthAndHeight($width, $height)
|
||||
public function setWidthAndHeight(int $width, int $height): self
|
||||
{
|
||||
$xratio = $width / ($this->width != 0 ? $this->width : 1);
|
||||
$yratio = $height / ($this->height != 0 ? $this->height : 1);
|
||||
|
|
@ -509,72 +390,38 @@ class BaseDrawing implements IComparable
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ResizeProportional.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getResizeProportional()
|
||||
public function getResizeProportional(): bool
|
||||
{
|
||||
return $this->resizeProportional;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ResizeProportional.
|
||||
*
|
||||
* @param bool $resizeProportional
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setResizeProportional($resizeProportional)
|
||||
public function setResizeProportional(bool $resizeProportional): self
|
||||
{
|
||||
$this->resizeProportional = $resizeProportional;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Rotation.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getRotation()
|
||||
public function getRotation(): int
|
||||
{
|
||||
return $this->rotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Rotation.
|
||||
*
|
||||
* @param int $rotation
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setRotation($rotation)
|
||||
public function setRotation(int $rotation): self
|
||||
{
|
||||
$this->rotation = $rotation;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Shadow.
|
||||
*
|
||||
* @return Drawing\Shadow
|
||||
*/
|
||||
public function getShadow()
|
||||
public function getShadow(): Drawing\Shadow
|
||||
{
|
||||
return $this->shadow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Shadow.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setShadow(?Drawing\Shadow $shadow = null)
|
||||
public function setShadow(?Drawing\Shadow $shadow = null): self
|
||||
{
|
||||
$this->shadow = $shadow;
|
||||
$this->shadow = $shadow ?? new Drawing\Shadow();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
@ -589,7 +436,7 @@ class BaseDrawing implements IComparable
|
|||
return md5(
|
||||
$this->name .
|
||||
$this->description .
|
||||
$this->worksheet->getHashCode() .
|
||||
(($this->worksheet === null) ? '' : $this->worksheet->getHashCode()) .
|
||||
$this->coordinates .
|
||||
$this->offsetX .
|
||||
$this->offsetY .
|
||||
|
|
@ -626,10 +473,7 @@ class BaseDrawing implements IComparable
|
|||
$this->hyperlink = $hyperlink;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|Hyperlink
|
||||
*/
|
||||
public function getHyperlink()
|
||||
public function getHyperlink(): ?Hyperlink
|
||||
{
|
||||
return $this->hyperlink;
|
||||
}
|
||||
|
|
@ -639,15 +483,19 @@ class BaseDrawing implements IComparable
|
|||
*/
|
||||
protected function setSizesAndType(string $path): void
|
||||
{
|
||||
if ($this->width == 0 && $this->height == 0 && $this->type == IMAGETYPE_UNKNOWN) {
|
||||
if ($this->imageWidth === 0 && $this->imageHeight === 0 && $this->type === IMAGETYPE_UNKNOWN) {
|
||||
$imageData = getimagesize($path);
|
||||
|
||||
if (is_array($imageData)) {
|
||||
$this->width = $imageData[0];
|
||||
$this->height = $imageData[1];
|
||||
$this->imageWidth = $imageData[0];
|
||||
$this->imageHeight = $imageData[1];
|
||||
$this->type = $imageData[2];
|
||||
}
|
||||
}
|
||||
if ($this->width === 0 && $this->height === 0) {
|
||||
$this->width = $this->imageWidth;
|
||||
$this->height = $this->imageHeight;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -657,4 +505,31 @@ class BaseDrawing implements IComparable
|
|||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function getImageWidth(): int
|
||||
{
|
||||
return $this->imageWidth;
|
||||
}
|
||||
|
||||
public function getImageHeight(): int
|
||||
{
|
||||
return $this->imageHeight;
|
||||
}
|
||||
|
||||
public function getEditAs(): string
|
||||
{
|
||||
return $this->editAs;
|
||||
}
|
||||
|
||||
public function setEditAs(string $editAs): self
|
||||
{
|
||||
$this->editAs = $editAs;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function validEditAs(): bool
|
||||
{
|
||||
return in_array($this->editAs, self::VALID_EDIT_AS);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,9 @@ class MemoryDrawing extends BaseDrawing
|
|||
*/
|
||||
private $uniqueName;
|
||||
|
||||
/** @var null|resource */
|
||||
private $alwaysNull;
|
||||
|
||||
/**
|
||||
* Create a new MemoryDrawing.
|
||||
*/
|
||||
|
|
@ -56,6 +59,7 @@ class MemoryDrawing extends BaseDrawing
|
|||
$this->renderingFunction = self::RENDERING_DEFAULT;
|
||||
$this->mimeType = self::MIMETYPE_DEFAULT;
|
||||
$this->uniqueName = md5(mt_rand(0, 9999) . time() . mt_rand(0, 9999));
|
||||
$this->alwaysNull = null;
|
||||
|
||||
// Initialize parent
|
||||
parent::__construct();
|
||||
|
|
@ -64,8 +68,9 @@ class MemoryDrawing extends BaseDrawing
|
|||
public function __destruct()
|
||||
{
|
||||
if ($this->imageResource) {
|
||||
imagedestroy($this->imageResource);
|
||||
$this->imageResource = null;
|
||||
$rslt = @imagedestroy($this->imageResource);
|
||||
// "Fix" for Scrutinizer
|
||||
$this->imageResource = $rslt ? null : $this->alwaysNull;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -640,6 +640,7 @@ class PageSetup
|
|||
if ($index == 0) {
|
||||
return $this->printArea;
|
||||
}
|
||||
/** @phpstan-ignore-next-line */
|
||||
$printAreas = explode(',', $this->printArea);
|
||||
if (isset($printAreas[$index - 1])) {
|
||||
return $printAreas[$index - 1];
|
||||
|
|
@ -663,6 +664,7 @@ class PageSetup
|
|||
if ($index == 0) {
|
||||
return $this->printArea !== null;
|
||||
}
|
||||
/** @phpstan-ignore-next-line */
|
||||
$printAreas = explode(',', $this->printArea);
|
||||
|
||||
return isset($printAreas[$index - 1]);
|
||||
|
|
@ -683,6 +685,7 @@ class PageSetup
|
|||
if ($index == 0) {
|
||||
$this->printArea = null;
|
||||
} else {
|
||||
/** @phpstan-ignore-next-line */
|
||||
$printAreas = explode(',', $this->printArea);
|
||||
if (isset($printAreas[$index - 1])) {
|
||||
unset($printAreas[$index - 1]);
|
||||
|
|
@ -731,6 +734,7 @@ class PageSetup
|
|||
if ($index == 0) {
|
||||
$this->printArea = $value;
|
||||
} else {
|
||||
/** @phpstan-ignore-next-line */
|
||||
$printAreas = explode(',', $this->printArea);
|
||||
if ($index < 0) {
|
||||
$index = count($printAreas) - abs($index) + 1;
|
||||
|
|
@ -745,6 +749,7 @@ class PageSetup
|
|||
if ($index == 0) {
|
||||
$this->printArea = $this->printArea ? ($this->printArea . ',' . $value) : $value;
|
||||
} else {
|
||||
/** @phpstan-ignore-next-line */
|
||||
$printAreas = explode(',', $this->printArea);
|
||||
if ($index < 0) {
|
||||
$index = abs($index) - 1;
|
||||
|
|
|
|||
|
|
@ -35,8 +35,7 @@ class Row
|
|||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
$this->worksheet = null;
|
||||
$this->worksheet = null; // @phpstan-ignore-line
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -567,6 +567,7 @@ class Worksheet implements IComparable
|
|||
$this->chartCollection[] = $chart;
|
||||
} else {
|
||||
// Insert the chart at the requested index
|
||||
// @phpstan-ignore-next-line
|
||||
array_splice($this->chartCollection, $chartIndex, 0, [$chart]);
|
||||
}
|
||||
|
||||
|
|
@ -1224,6 +1225,7 @@ class Worksheet implements IComparable
|
|||
throw new Exception('Sheet not found for named range: ' . $namedRange->getName());
|
||||
}
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
$cellCoordinate = ltrim(substr($namedRange->getValue(), strrpos($namedRange->getValue(), '!')), '!');
|
||||
$finalCoordinate = str_replace('$', '', $cellCoordinate);
|
||||
}
|
||||
|
|
@ -2217,16 +2219,18 @@ class Worksheet implements IComparable
|
|||
$highestColumnIndex = Coordinate::columnIndexFromString($highestColumn);
|
||||
$pColumnIndex = Coordinate::columnIndexFromString($column);
|
||||
|
||||
if ($pColumnIndex > $highestColumnIndex) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$holdColumnDimensions = $this->removeColumnDimensions($pColumnIndex, $numberOfColumns);
|
||||
|
||||
$column = Coordinate::stringFromColumnIndex($pColumnIndex + $numberOfColumns);
|
||||
$objReferenceHelper = ReferenceHelper::getInstance();
|
||||
$objReferenceHelper->insertNewBefore($column . '1', -$numberOfColumns, 0, $this);
|
||||
|
||||
$this->columnDimensions = $holdColumnDimensions;
|
||||
|
||||
if ($pColumnIndex > $highestColumnIndex) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$maxPossibleColumnsToBeRemoved = $highestColumnIndex - $pColumnIndex + 1;
|
||||
|
||||
for ($c = 0, $n = min($maxPossibleColumnsToBeRemoved, $numberOfColumns); $c < $n; ++$c) {
|
||||
|
|
@ -2234,8 +2238,6 @@ class Worksheet implements IComparable
|
|||
$highestColumn = Coordinate::stringFromColumnIndex(Coordinate::columnIndexFromString($highestColumn) - 1);
|
||||
}
|
||||
|
||||
$this->columnDimensions = $holdColumnDimensions;
|
||||
|
||||
$this->garbageCollect();
|
||||
|
||||
return $this;
|
||||
|
|
@ -2767,6 +2769,7 @@ class Worksheet implements IComparable
|
|||
{
|
||||
$namedRange = $this->validateNamedRange($definedName);
|
||||
$workSheet = $namedRange->getWorksheet();
|
||||
/** @phpstan-ignore-next-line */
|
||||
$cellRange = ltrim(substr($namedRange->getValue(), strrpos($namedRange->getValue(), '!')), '!');
|
||||
$cellRange = str_replace('$', '', $cellRange);
|
||||
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ abstract class BaseWriter implements IWriter
|
|||
return;
|
||||
}
|
||||
|
||||
$mode = 'wb+';
|
||||
$mode = 'wb';
|
||||
$scheme = parse_url($filename, PHP_URL_SCHEME);
|
||||
if ($scheme === 's3') {
|
||||
$mode = 'w';
|
||||
|
|
|
|||
|
|
@ -697,10 +697,12 @@ class Html extends BaseWriter
|
|||
$imageResource = $drawing->getImageResource();
|
||||
if ($imageResource) {
|
||||
ob_start(); // Let's start output buffering.
|
||||
// @phpstan-ignore-next-line
|
||||
imagepng($imageResource); // This will normally output the image, but because of ob_start(), it won't.
|
||||
$contents = ob_get_contents(); // Instead, output above is saved to $contents
|
||||
ob_end_clean(); // End the output buffer.
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
$dataUri = 'data:image/jpeg;base64,' . base64_encode($contents);
|
||||
|
||||
// Because of the nature of tables, width is more important than height.
|
||||
|
|
@ -748,7 +750,7 @@ class Html extends BaseWriter
|
|||
if ($fp = fopen($chartFileName, 'rb', 0)) {
|
||||
$picture = fread($fp, filesize($chartFileName));
|
||||
fclose($fp);
|
||||
// base64 encode the binary data
|
||||
/** @phpstan-ignore-next-line */
|
||||
$base64 = base64_encode($picture);
|
||||
$imageData = 'data:' . $imageDetails['mime'] . ';base64,' . $base64;
|
||||
|
||||
|
|
|
|||
|
|
@ -434,6 +434,7 @@ class Xls extends BaseWriter
|
|||
case 1: // GIF, not supported by BIFF8, we convert to PNG
|
||||
$blipType = BSE::BLIPTYPE_PNG;
|
||||
ob_start();
|
||||
// @phpstan-ignore-next-line
|
||||
imagepng(imagecreatefromgif($filename));
|
||||
$blipData = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
|
@ -452,6 +453,7 @@ class Xls extends BaseWriter
|
|||
case 6: // Windows DIB (BMP), we convert to PNG
|
||||
$blipType = BSE::BLIPTYPE_PNG;
|
||||
ob_start();
|
||||
// @phpstan-ignore-next-line
|
||||
imagepng(SharedDrawing::imagecreatefrombmp($filename));
|
||||
$blipData = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Writer\Xls;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
|
||||
use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\Wizard;
|
||||
|
||||
class ConditionalHelper
|
||||
{
|
||||
/**
|
||||
* Formula parser.
|
||||
*
|
||||
* @var Parser
|
||||
*/
|
||||
protected $parser;
|
||||
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
protected $condition;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $cellRange;
|
||||
|
||||
/**
|
||||
* @var null|string
|
||||
*/
|
||||
protected $tokens;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $size;
|
||||
|
||||
public function __construct(Parser $parser)
|
||||
{
|
||||
$this->parser = $parser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $condition
|
||||
*/
|
||||
public function processCondition($condition, string $cellRange): void
|
||||
{
|
||||
$this->condition = $condition;
|
||||
$this->cellRange = $cellRange;
|
||||
|
||||
if (is_int($condition) || is_float($condition)) {
|
||||
$this->size = ($condition <= 65535 ? 3 : 0x0000);
|
||||
$this->tokens = pack('Cv', 0x1E, $condition);
|
||||
} else {
|
||||
try {
|
||||
$formula = Wizard\WizardAbstract::reverseAdjustCellRef((string) $condition, $cellRange);
|
||||
$this->parser->parse($formula);
|
||||
$this->tokens = $this->parser->toReversePolish();
|
||||
$this->size = strlen($this->tokens ?? '');
|
||||
} catch (PhpSpreadsheetException $e) {
|
||||
// In the event of a parser error with a formula value, we set the expression to ptgInt + 0
|
||||
$this->tokens = pack('Cv', 0x1E, 0);
|
||||
$this->size = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function tokens(): ?string
|
||||
{
|
||||
return $this->tokens;
|
||||
}
|
||||
|
||||
public function size(): int
|
||||
{
|
||||
return $this->size;
|
||||
}
|
||||
}
|
||||
|
|
@ -539,37 +539,44 @@ class Worksheet extends BIFFwriter
|
|||
$this->writeSheetProtection();
|
||||
$this->writeRangeProtection();
|
||||
|
||||
$arrConditionalStyles = $phpSheet->getConditionalStylesCollection();
|
||||
// Write Conditional Formatting Rules and Styles
|
||||
$this->writeConditionalFormatting();
|
||||
|
||||
$this->storeEof();
|
||||
}
|
||||
|
||||
private function writeConditionalFormatting(): void
|
||||
{
|
||||
$conditionalFormulaHelper = new ConditionalHelper($this->parser);
|
||||
|
||||
$arrConditionalStyles = $this->phpSheet->getConditionalStylesCollection();
|
||||
if (!empty($arrConditionalStyles)) {
|
||||
$arrConditional = [];
|
||||
|
||||
$cfHeaderWritten = false;
|
||||
// Write ConditionalFormattingTable records
|
||||
foreach ($arrConditionalStyles as $cellCoordinate => $conditionalStyles) {
|
||||
$cfHeaderWritten = false;
|
||||
foreach ($conditionalStyles as $conditional) {
|
||||
/** @var Conditional $conditional */
|
||||
if (
|
||||
$conditional->getConditionType() == Conditional::CONDITION_EXPRESSION ||
|
||||
$conditional->getConditionType() == Conditional::CONDITION_CELLIS
|
||||
$conditional->getConditionType() === Conditional::CONDITION_EXPRESSION ||
|
||||
$conditional->getConditionType() === Conditional::CONDITION_CELLIS
|
||||
) {
|
||||
// Write CFHEADER record (only if there are Conditional Styles that we are able to write)
|
||||
if ($cfHeaderWritten === false) {
|
||||
$this->writeCFHeader();
|
||||
$cfHeaderWritten = true;
|
||||
$cfHeaderWritten = $this->writeCFHeader($cellCoordinate, $conditionalStyles);
|
||||
}
|
||||
if (!isset($arrConditional[$conditional->getHashCode()])) {
|
||||
if ($cfHeaderWritten === true && !isset($arrConditional[$conditional->getHashCode()])) {
|
||||
// This hash code has been handled
|
||||
$arrConditional[$conditional->getHashCode()] = true;
|
||||
|
||||
// Write CFRULE record
|
||||
$this->writeCFRule($conditional);
|
||||
$this->writeCFRule($conditionalFormulaHelper, $conditional, $cellCoordinate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->storeEof();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -989,6 +996,8 @@ class Worksheet extends BIFFwriter
|
|||
$options = pack('V', 0x03);
|
||||
|
||||
// Convert URL to a null terminated wchar string
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
$url = implode("\0", preg_split("''", $url, -1, PREG_SPLIT_NO_EMPTY));
|
||||
$url = $url . "\0\0\0";
|
||||
|
||||
|
|
@ -2387,6 +2396,7 @@ class Worksheet extends BIFFwriter
|
|||
$data = pack('Vvvvv', 0x000c, $width, $height, 0x01, 0x18);
|
||||
for ($j = $height; --$j;) {
|
||||
for ($i = 0; $i < $width; ++$i) {
|
||||
/** @phpstan-ignore-next-line */
|
||||
$color = imagecolorsforindex($image, imagecolorat($image, $i, $j));
|
||||
foreach (['red', 'green', 'blue'] as $key) {
|
||||
$color[$key] = $color[$key] + (int) round((255 - $color[$key]) * $color['alpha'] / 127);
|
||||
|
|
@ -2427,6 +2437,8 @@ class Worksheet extends BIFFwriter
|
|||
}
|
||||
|
||||
// The first 2 bytes are used to identify the bitmap.
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
$identity = unpack('A2ident', $data);
|
||||
if ($identity['ident'] != 'BM') {
|
||||
throw new WriterException("$bitmap doesn't appear to be a valid bitmap image.\n");
|
||||
|
|
@ -2769,11 +2781,14 @@ class Worksheet extends BIFFwriter
|
|||
/**
|
||||
* Write CFRule Record.
|
||||
*/
|
||||
private function writeCFRule(Conditional $conditional): void
|
||||
{
|
||||
private function writeCFRule(
|
||||
ConditionalHelper $conditionalFormulaHelper,
|
||||
Conditional $conditional,
|
||||
string $cellRange
|
||||
): void {
|
||||
$record = 0x01B1; // Record identifier
|
||||
$type = null; // Type of the CF
|
||||
$operatorType = null; // Comparison operator
|
||||
$type = null; // Type of the CF
|
||||
$operatorType = null; // Comparison operator
|
||||
|
||||
if ($conditional->getConditionType() == Conditional::CONDITION_EXPRESSION) {
|
||||
$type = 0x02;
|
||||
|
|
@ -2822,21 +2837,23 @@ class Worksheet extends BIFFwriter
|
|||
// $szValue2 : size of the formula data for second value or formula
|
||||
$arrConditions = $conditional->getConditions();
|
||||
$numConditions = count($arrConditions);
|
||||
if ($numConditions == 1) {
|
||||
$szValue1 = ($arrConditions[0] <= 65535 ? 3 : 0x0000);
|
||||
$szValue2 = 0x0000;
|
||||
$operand1 = pack('Cv', 0x1E, $arrConditions[0]);
|
||||
$operand2 = null;
|
||||
} elseif ($numConditions == 2 && ($conditional->getOperatorType() == Conditional::OPERATOR_BETWEEN)) {
|
||||
$szValue1 = ($arrConditions[0] <= 65535 ? 3 : 0x0000);
|
||||
$szValue2 = ($arrConditions[1] <= 65535 ? 3 : 0x0000);
|
||||
$operand1 = pack('Cv', 0x1E, $arrConditions[0]);
|
||||
$operand2 = pack('Cv', 0x1E, $arrConditions[1]);
|
||||
} else {
|
||||
$szValue1 = 0x0000;
|
||||
$szValue2 = 0x0000;
|
||||
$operand1 = null;
|
||||
$operand2 = null;
|
||||
|
||||
$szValue1 = 0x0000;
|
||||
$szValue2 = 0x0000;
|
||||
$operand1 = null;
|
||||
$operand2 = null;
|
||||
|
||||
if ($numConditions === 1) {
|
||||
$conditionalFormulaHelper->processCondition($arrConditions[0], $cellRange);
|
||||
$szValue1 = $conditionalFormulaHelper->size();
|
||||
$operand1 = $conditionalFormulaHelper->tokens();
|
||||
} elseif ($numConditions === 2 && ($conditional->getOperatorType() === Conditional::OPERATOR_BETWEEN)) {
|
||||
$conditionalFormulaHelper->processCondition($arrConditions[0], $cellRange);
|
||||
$szValue1 = $conditionalFormulaHelper->size();
|
||||
$operand1 = $conditionalFormulaHelper->tokens();
|
||||
$conditionalFormulaHelper->processCondition($arrConditions[1], $cellRange);
|
||||
$szValue2 = $conditionalFormulaHelper->size();
|
||||
$operand2 = $conditionalFormulaHelper->tokens();
|
||||
}
|
||||
|
||||
// $flags : Option flags
|
||||
|
|
@ -3122,8 +3139,10 @@ class Worksheet extends BIFFwriter
|
|||
|
||||
/**
|
||||
* Write CFHeader record.
|
||||
*
|
||||
* @param Conditional[] $conditionalStyles
|
||||
*/
|
||||
private function writeCFHeader(): void
|
||||
private function writeCFHeader(string $cellCoordinate, array $conditionalStyles): bool
|
||||
{
|
||||
$record = 0x01B0; // Record identifier
|
||||
$length = 0x0016; // Bytes to follow
|
||||
|
|
@ -3132,33 +3151,32 @@ class Worksheet extends BIFFwriter
|
|||
$numColumnMax = null;
|
||||
$numRowMin = null;
|
||||
$numRowMax = null;
|
||||
|
||||
$arrConditional = [];
|
||||
foreach ($this->phpSheet->getConditionalStylesCollection() as $cellCoordinate => $conditionalStyles) {
|
||||
foreach ($conditionalStyles as $conditional) {
|
||||
if (
|
||||
$conditional->getConditionType() == Conditional::CONDITION_EXPRESSION ||
|
||||
$conditional->getConditionType() == Conditional::CONDITION_CELLIS
|
||||
) {
|
||||
if (!in_array($conditional->getHashCode(), $arrConditional)) {
|
||||
$arrConditional[] = $conditional->getHashCode();
|
||||
}
|
||||
// Cells
|
||||
$rangeCoordinates = Coordinate::rangeBoundaries($cellCoordinate);
|
||||
if ($numColumnMin === null || ($numColumnMin > $rangeCoordinates[0][0])) {
|
||||
$numColumnMin = $rangeCoordinates[0][0];
|
||||
}
|
||||
if ($numColumnMax === null || ($numColumnMax < $rangeCoordinates[1][0])) {
|
||||
$numColumnMax = $rangeCoordinates[1][0];
|
||||
}
|
||||
if ($numRowMin === null || ($numRowMin > $rangeCoordinates[0][1])) {
|
||||
$numRowMin = (int) $rangeCoordinates[0][1];
|
||||
}
|
||||
if ($numRowMax === null || ($numRowMax < $rangeCoordinates[1][1])) {
|
||||
$numRowMax = (int) $rangeCoordinates[1][1];
|
||||
}
|
||||
}
|
||||
foreach ($conditionalStyles as $conditional) {
|
||||
if (!in_array($conditional->getHashCode(), $arrConditional)) {
|
||||
$arrConditional[] = $conditional->getHashCode();
|
||||
}
|
||||
// Cells
|
||||
$rangeCoordinates = Coordinate::rangeBoundaries($cellCoordinate);
|
||||
if ($numColumnMin === null || ($numColumnMin > $rangeCoordinates[0][0])) {
|
||||
$numColumnMin = $rangeCoordinates[0][0];
|
||||
}
|
||||
if ($numColumnMax === null || ($numColumnMax < $rangeCoordinates[1][0])) {
|
||||
$numColumnMax = $rangeCoordinates[1][0];
|
||||
}
|
||||
if ($numRowMin === null || ($numRowMin > $rangeCoordinates[0][1])) {
|
||||
$numRowMin = (int) $rangeCoordinates[0][1];
|
||||
}
|
||||
if ($numRowMax === null || ($numRowMax < $rangeCoordinates[1][1])) {
|
||||
$numRowMax = (int) $rangeCoordinates[1][1];
|
||||
}
|
||||
}
|
||||
|
||||
if (count($arrConditional) === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$needRedraw = 1;
|
||||
$cellRange = pack('vvvv', $numRowMin - 1, $numRowMax - 1, $numColumnMin - 1, $numColumnMax - 1);
|
||||
|
||||
|
|
@ -3168,6 +3186,8 @@ class Worksheet extends BIFFwriter
|
|||
$data .= pack('v', 0x0001);
|
||||
$data .= $cellRange;
|
||||
$this->append($header . $data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function getDataBlockProtection(Conditional $conditional): int
|
||||
|
|
|
|||
|
|
@ -501,8 +501,10 @@ class Xlsx extends BaseWriter
|
|||
$zipContent['xl/media/' . $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()] = $imageContents;
|
||||
} elseif ($this->getDrawingHashTable()->getByIndex($i) instanceof MemoryDrawing) {
|
||||
ob_start();
|
||||
/** @var callable */
|
||||
$callable = $this->getDrawingHashTable()->getByIndex($i)->getRenderingFunction();
|
||||
call_user_func(
|
||||
$this->getDrawingHashTable()->getByIndex($i)->getRenderingFunction(),
|
||||
$callable,
|
||||
$this->getDrawingHashTable()->getByIndex($i)->getImageResource()
|
||||
);
|
||||
$imageContents = ob_get_contents();
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Drawing as SharedDrawing;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing;
|
||||
|
|
@ -56,7 +57,10 @@ class Drawing extends WriterPart
|
|||
// Loop through charts and write the chart position
|
||||
if ($chartCount > 0) {
|
||||
for ($c = 0; $c < $chartCount; ++$c) {
|
||||
$this->writeChart($objWriter, $worksheet->getChartByIndex($c), $c + $i);
|
||||
$chart = $worksheet->getChartByIndex((string) $c);
|
||||
if ($chart !== false) {
|
||||
$this->writeChart($objWriter, $chart, $c + $i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -90,16 +94,16 @@ class Drawing extends WriterPart
|
|||
$objWriter->startElement('xdr:twoCellAnchor');
|
||||
|
||||
$objWriter->startElement('xdr:from');
|
||||
$objWriter->writeElement('xdr:col', $tlColRow[0] - 1);
|
||||
$objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($tl['xOffset']));
|
||||
$objWriter->writeElement('xdr:row', $tlColRow[1] - 1);
|
||||
$objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($tl['yOffset']));
|
||||
$objWriter->writeElement('xdr:col', (string) ($tlColRow[0] - 1));
|
||||
$objWriter->writeElement('xdr:colOff', self::stringEmu($tl['xOffset']));
|
||||
$objWriter->writeElement('xdr:row', (string) ($tlColRow[1] - 1));
|
||||
$objWriter->writeElement('xdr:rowOff', self::stringEmu($tl['yOffset']));
|
||||
$objWriter->endElement();
|
||||
$objWriter->startElement('xdr:to');
|
||||
$objWriter->writeElement('xdr:col', $brColRow[0] - 1);
|
||||
$objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($br['xOffset']));
|
||||
$objWriter->writeElement('xdr:row', $brColRow[1] - 1);
|
||||
$objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($br['yOffset']));
|
||||
$objWriter->writeElement('xdr:col', (string) ($brColRow[0] - 1));
|
||||
$objWriter->writeElement('xdr:colOff', self::stringEmu($br['xOffset']));
|
||||
$objWriter->writeElement('xdr:row', (string) ($brColRow[1] - 1));
|
||||
$objWriter->writeElement('xdr:rowOff', self::stringEmu($br['yOffset']));
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->startElement('xdr:graphicFrame');
|
||||
|
|
@ -107,7 +111,7 @@ class Drawing extends WriterPart
|
|||
$objWriter->startElement('xdr:nvGraphicFramePr');
|
||||
$objWriter->startElement('xdr:cNvPr');
|
||||
$objWriter->writeAttribute('name', 'Chart ' . $relationId);
|
||||
$objWriter->writeAttribute('id', 1025 * $relationId);
|
||||
$objWriter->writeAttribute('id', (string) (1025 * $relationId));
|
||||
$objWriter->endElement();
|
||||
$objWriter->startElement('xdr:cNvGraphicFramePr');
|
||||
$objWriter->startElement('a:graphicFrameLocks');
|
||||
|
|
@ -153,28 +157,31 @@ class Drawing extends WriterPart
|
|||
public function writeDrawing(XMLWriter $objWriter, BaseDrawing $drawing, $relationId = -1, $hlinkClickId = null): void
|
||||
{
|
||||
if ($relationId >= 0) {
|
||||
$isTwoCellAnchor = $drawing->getCoordinates2() !== null;
|
||||
$isTwoCellAnchor = $drawing->getCoordinates2() !== '';
|
||||
if ($isTwoCellAnchor) {
|
||||
// xdr:twoCellAnchor
|
||||
$objWriter->startElement('xdr:twoCellAnchor');
|
||||
if ($drawing->validEditAs()) {
|
||||
$objWriter->writeAttribute('editAs', $drawing->getEditAs());
|
||||
}
|
||||
// Image location
|
||||
$aCoordinates = Coordinate::indexesFromString($drawing->getCoordinates());
|
||||
$aCoordinates2 = Coordinate::indexesFromString($drawing->getCoordinates2());
|
||||
|
||||
// xdr:from
|
||||
$objWriter->startElement('xdr:from');
|
||||
$objWriter->writeElement('xdr:col', $aCoordinates[0] - 1);
|
||||
$objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getOffsetX()));
|
||||
$objWriter->writeElement('xdr:row', $aCoordinates[1] - 1);
|
||||
$objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getOffsetY()));
|
||||
$objWriter->writeElement('xdr:col', (string) ($aCoordinates[0] - 1));
|
||||
$objWriter->writeElement('xdr:colOff', self::stringEmu($drawing->getOffsetX()));
|
||||
$objWriter->writeElement('xdr:row', (string) ($aCoordinates[1] - 1));
|
||||
$objWriter->writeElement('xdr:rowOff', self::stringEmu($drawing->getOffsetY()));
|
||||
$objWriter->endElement();
|
||||
|
||||
// xdr:to
|
||||
$objWriter->startElement('xdr:to');
|
||||
$objWriter->writeElement('xdr:col', $aCoordinates2[0] - 1);
|
||||
$objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getOffsetX2()));
|
||||
$objWriter->writeElement('xdr:row', $aCoordinates2[1] - 1);
|
||||
$objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getOffsetY2()));
|
||||
$objWriter->writeElement('xdr:col', (string) ($aCoordinates2[0] - 1));
|
||||
$objWriter->writeElement('xdr:colOff', self::stringEmu($drawing->getOffsetX2()));
|
||||
$objWriter->writeElement('xdr:row', (string) ($aCoordinates2[1] - 1));
|
||||
$objWriter->writeElement('xdr:rowOff', self::stringEmu($drawing->getOffsetY2()));
|
||||
$objWriter->endElement();
|
||||
} else {
|
||||
// xdr:oneCellAnchor
|
||||
|
|
@ -184,16 +191,16 @@ class Drawing extends WriterPart
|
|||
|
||||
// xdr:from
|
||||
$objWriter->startElement('xdr:from');
|
||||
$objWriter->writeElement('xdr:col', $aCoordinates[0] - 1);
|
||||
$objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getOffsetX()));
|
||||
$objWriter->writeElement('xdr:row', $aCoordinates[1] - 1);
|
||||
$objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getOffsetY()));
|
||||
$objWriter->writeElement('xdr:col', (string) ($aCoordinates[0] - 1));
|
||||
$objWriter->writeElement('xdr:colOff', self::stringEmu($drawing->getOffsetX()));
|
||||
$objWriter->writeElement('xdr:row', (string) ($aCoordinates[1] - 1));
|
||||
$objWriter->writeElement('xdr:rowOff', self::stringEmu($drawing->getOffsetY()));
|
||||
$objWriter->endElement();
|
||||
|
||||
// xdr:ext
|
||||
$objWriter->startElement('xdr:ext');
|
||||
$objWriter->writeAttribute('cx', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getWidth()));
|
||||
$objWriter->writeAttribute('cy', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getHeight()));
|
||||
$objWriter->writeAttribute('cx', self::stringEmu($drawing->getWidth()));
|
||||
$objWriter->writeAttribute('cy', self::stringEmu($drawing->getHeight()));
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
|
|
@ -205,7 +212,7 @@ class Drawing extends WriterPart
|
|||
|
||||
// xdr:cNvPr
|
||||
$objWriter->startElement('xdr:cNvPr');
|
||||
$objWriter->writeAttribute('id', $relationId);
|
||||
$objWriter->writeAttribute('id', (string) $relationId);
|
||||
$objWriter->writeAttribute('name', $drawing->getName());
|
||||
$objWriter->writeAttribute('descr', $drawing->getDescription());
|
||||
|
||||
|
|
@ -247,11 +254,11 @@ class Drawing extends WriterPart
|
|||
|
||||
// a:xfrm
|
||||
$objWriter->startElement('a:xfrm');
|
||||
$objWriter->writeAttribute('rot', \PhpOffice\PhpSpreadsheet\Shared\Drawing::degreesToAngle($drawing->getRotation()));
|
||||
$objWriter->writeAttribute('rot', (string) SharedDrawing::degreesToAngle($drawing->getRotation()));
|
||||
if ($isTwoCellAnchor) {
|
||||
$objWriter->startElement('a:ext');
|
||||
$objWriter->writeAttribute('cx', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getWidth()));
|
||||
$objWriter->writeAttribute('cy', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getHeight()));
|
||||
$objWriter->writeAttribute('cx', self::stringEmu($drawing->getWidth()));
|
||||
$objWriter->writeAttribute('cy', self::stringEmu($drawing->getHeight()));
|
||||
$objWriter->endElement();
|
||||
}
|
||||
$objWriter->endElement();
|
||||
|
|
@ -271,9 +278,9 @@ class Drawing extends WriterPart
|
|||
|
||||
// a:outerShdw
|
||||
$objWriter->startElement('a:outerShdw');
|
||||
$objWriter->writeAttribute('blurRad', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getShadow()->getBlurRadius()));
|
||||
$objWriter->writeAttribute('dist', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($drawing->getShadow()->getDistance()));
|
||||
$objWriter->writeAttribute('dir', \PhpOffice\PhpSpreadsheet\Shared\Drawing::degreesToAngle($drawing->getShadow()->getDirection()));
|
||||
$objWriter->writeAttribute('blurRad', self::stringEmu($drawing->getShadow()->getBlurRadius()));
|
||||
$objWriter->writeAttribute('dist', self::stringEmu($drawing->getShadow()->getDistance()));
|
||||
$objWriter->writeAttribute('dir', (string) SharedDrawing::degreesToAngle($drawing->getShadow()->getDirection()));
|
||||
$objWriter->writeAttribute('algn', $drawing->getShadow()->getAlignment());
|
||||
$objWriter->writeAttribute('rotWithShape', '0');
|
||||
|
||||
|
|
@ -283,7 +290,7 @@ class Drawing extends WriterPart
|
|||
|
||||
// a:alpha
|
||||
$objWriter->startElement('a:alpha');
|
||||
$objWriter->writeAttribute('val', $drawing->getShadow()->getAlpha() * 1000);
|
||||
$objWriter->writeAttribute('val', (string) ($drawing->getShadow()->getAlpha() * 1000));
|
||||
$objWriter->endElement();
|
||||
|
||||
$objWriter->endElement();
|
||||
|
|
@ -528,4 +535,9 @@ class Drawing extends WriterPart
|
|||
$objWriter->writeAttribute('r:id', 'rId' . $hlinkClickId);
|
||||
$objWriter->endElement();
|
||||
}
|
||||
|
||||
private static function stringEmu(int $pixelValue): string
|
||||
{
|
||||
return (string) SharedDrawing::pixelsToEMU($pixelValue);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@ use PHPUnit\Framework\TestCase;
|
|||
|
||||
class RangeTest extends TestCase
|
||||
{
|
||||
/** @var string */
|
||||
private $incompleteMessage = 'Must be revisited';
|
||||
|
||||
/**
|
||||
* @var Spreadsheet
|
||||
*/
|
||||
|
|
@ -140,7 +143,9 @@ class RangeTest extends TestCase
|
|||
*/
|
||||
public function testCompositeNamedRangeEvaluation(string $composite, int $expectedSum, int $expectedCount): void
|
||||
{
|
||||
self::markTestSkipped('must be revisited.');
|
||||
if ($this->incompleteMessage !== '') {
|
||||
self::markTestIncomplete($this->incompleteMessage);
|
||||
}
|
||||
|
||||
$workSheet = $this->spreadSheet->getActiveSheet();
|
||||
$this->spreadSheet->addNamedRange(new NamedRange('COMPOSITE', $workSheet, $composite));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,157 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\LookupRef;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\LookupRef;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class UniqueTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider uniqueTestProvider
|
||||
*/
|
||||
public function testUnique(array $expectedResult, array $lookupRef, bool $byColumn = false, bool $exactlyOnce = false): void
|
||||
{
|
||||
$result = LookupRef\Unique::unique($lookupRef, $byColumn, $exactlyOnce);
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
public function testUniqueException(): void
|
||||
{
|
||||
$rowLookupData = [
|
||||
['Andrew', 'Brown'],
|
||||
['Betty', 'Johnson'],
|
||||
['Betty', 'Johnson'],
|
||||
['Andrew', 'Brown'],
|
||||
['David', 'White'],
|
||||
['Andrew', 'Brown'],
|
||||
['David', 'White'],
|
||||
];
|
||||
|
||||
$columnLookupData = [
|
||||
['PHP', 'Rocks', 'php', 'rocks'],
|
||||
];
|
||||
|
||||
$result = LookupRef\Unique::unique($rowLookupData, false, true);
|
||||
self::assertEquals(ExcelError::CALC(), $result);
|
||||
|
||||
$result = LookupRef\Unique::unique($columnLookupData, true, true);
|
||||
self::assertEquals(ExcelError::CALC(), $result);
|
||||
}
|
||||
|
||||
public function testUniqueWithScalar(): void
|
||||
{
|
||||
$lookupData = 123;
|
||||
|
||||
$result = LookupRef\Unique::unique($lookupData);
|
||||
self::assertSame($lookupData, $result);
|
||||
}
|
||||
|
||||
public function uniqueTestProvider(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
[['Red'], ['Green'], ['Blue'], ['Orange']],
|
||||
[
|
||||
['Red'],
|
||||
['Green'],
|
||||
['Green'],
|
||||
['Blue'],
|
||||
['Blue'],
|
||||
['Orange'],
|
||||
['Green'],
|
||||
['Blue'],
|
||||
['Red'],
|
||||
],
|
||||
],
|
||||
[
|
||||
[['Red'], ['Green'], ['Blue'], ['Orange']],
|
||||
[
|
||||
['Red'],
|
||||
['Green'],
|
||||
['GrEEn'],
|
||||
['Blue'],
|
||||
['BLUE'],
|
||||
['Orange'],
|
||||
['GReeN'],
|
||||
['blue'],
|
||||
['RED'],
|
||||
],
|
||||
],
|
||||
[
|
||||
['Orange'],
|
||||
[
|
||||
['Red'],
|
||||
['Green'],
|
||||
['Green'],
|
||||
['Blue'],
|
||||
['Blue'],
|
||||
['Orange'],
|
||||
['Green'],
|
||||
['Blue'],
|
||||
['Red'],
|
||||
],
|
||||
false,
|
||||
true,
|
||||
],
|
||||
[
|
||||
['Andrew', 'Betty', 'Robert', 'David'],
|
||||
[['Andrew', 'Betty', 'Robert', 'Andrew', 'Betty', 'Robert', 'David', 'Andrew']],
|
||||
true,
|
||||
],
|
||||
[
|
||||
['David'],
|
||||
[['Andrew', 'Betty', 'Robert', 'Andrew', 'Betty', 'Robert', 'David', 'Andrew']],
|
||||
true,
|
||||
true,
|
||||
],
|
||||
[
|
||||
[1, 1, 2, 2, 3],
|
||||
[[1, 1, 2, 2, 3]],
|
||||
],
|
||||
[
|
||||
[1, 2, 3],
|
||||
[[1, 1, 2, 2, 3]],
|
||||
true,
|
||||
],
|
||||
[
|
||||
[
|
||||
[1, 1, 2, 3],
|
||||
[1, 2, 2, 3],
|
||||
],
|
||||
[
|
||||
[1, 1, 2, 2, 3],
|
||||
[1, 2, 2, 2, 3],
|
||||
],
|
||||
true,
|
||||
],
|
||||
[
|
||||
[
|
||||
['Andrew', 'Brown'],
|
||||
['Betty', 'Johnson'],
|
||||
['David', 'White'],
|
||||
],
|
||||
[
|
||||
['Andrew', 'Brown'],
|
||||
['Betty', 'Johnson'],
|
||||
['Betty', 'Johnson'],
|
||||
['Andrew', 'Brown'],
|
||||
['David', 'White'],
|
||||
['Andrew', 'Brown'],
|
||||
['David', 'White'],
|
||||
],
|
||||
],
|
||||
[
|
||||
[[1.2], [2.1], [2.2], [3.0]],
|
||||
[
|
||||
[1.2],
|
||||
[1.2],
|
||||
[2.1],
|
||||
[2.2],
|
||||
[3.0],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\CellReferenceHelper;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class CellReferenceHelperTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider cellReferenceHelperInsertColumnsProvider
|
||||
*/
|
||||
public function testCellReferenceHelperInsertColumns(string $expectedResult, string $cellAddress): void
|
||||
{
|
||||
$cellReferenceHelper = new CellReferenceHelper('E5', 2, 0);
|
||||
$result = $cellReferenceHelper->updateCellReference($cellAddress);
|
||||
self::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
public function cellReferenceHelperInsertColumnsProvider(): array
|
||||
{
|
||||
return [
|
||||
['A1', 'A1'],
|
||||
['D5', 'D5'],
|
||||
['G5', 'E5'],
|
||||
['$E5', '$E5'],
|
||||
['G$5', 'E$5'],
|
||||
['I5', 'G5'],
|
||||
['$G$5', '$G$5'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider cellReferenceHelperDeleteColumnsProvider
|
||||
*/
|
||||
public function testCellReferenceHelperDeleteColumns(string $expectedResult, string $cellAddress): void
|
||||
{
|
||||
$cellReferenceHelper = new CellReferenceHelper('E5', -2, 0);
|
||||
$result = $cellReferenceHelper->updateCellReference($cellAddress);
|
||||
self::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
public function cellReferenceHelperDeleteColumnsProvider(): array
|
||||
{
|
||||
return [
|
||||
['A1', 'A1'],
|
||||
['D5', 'D5'],
|
||||
['C5', 'E5'],
|
||||
['$E5', '$E5'],
|
||||
['C$5', 'E$5'],
|
||||
['E5', 'G5'],
|
||||
['$G$5', '$G$5'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider cellReferenceHelperInsertRowsProvider
|
||||
*/
|
||||
public function testCellReferenceHelperInsertRows(string $expectedResult, string $cellAddress): void
|
||||
{
|
||||
$cellReferenceHelper = new CellReferenceHelper('E5', 0, 2);
|
||||
$result = $cellReferenceHelper->updateCellReference($cellAddress);
|
||||
self::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
public function cellReferenceHelperInsertRowsProvider(): array
|
||||
{
|
||||
return [
|
||||
['A1', 'A1'],
|
||||
['E4', 'E4'],
|
||||
['E7', 'E5'],
|
||||
['E$5', 'E$5'],
|
||||
['$E7', '$E5'],
|
||||
['E11', 'E9'],
|
||||
['$E$9', '$E$9'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider cellReferenceHelperDeleteRowsProvider
|
||||
*/
|
||||
public function testCellReferenceHelperDeleteRows(string $expectedResult, string $cellAddress): void
|
||||
{
|
||||
$cellReferenceHelper = new CellReferenceHelper('E5', 0, -2);
|
||||
$result = $cellReferenceHelper->updateCellReference($cellAddress);
|
||||
self::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
public function cellReferenceHelperDeleteRowsProvider(): array
|
||||
{
|
||||
return [
|
||||
['A1', 'A1'],
|
||||
['E4', 'E4'],
|
||||
['E3', 'E5'],
|
||||
['E$5', 'E$5'],
|
||||
['$E3', '$E5'],
|
||||
['E7', 'E9'],
|
||||
['$E$9', '$E$9'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider cellReferenceHelperInsertColumnsAbsoluteProvider
|
||||
*/
|
||||
public function testCellReferenceHelperInsertColumnsAbsolute(string $expectedResult, string $cellAddress): void
|
||||
{
|
||||
$cellReferenceHelper = new CellReferenceHelper('E5', 2, 0);
|
||||
$result = $cellReferenceHelper->updateCellReference($cellAddress, true);
|
||||
self::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
public function cellReferenceHelperInsertColumnsAbsoluteProvider(): array
|
||||
{
|
||||
return [
|
||||
['A1', 'A1'],
|
||||
['D5', 'D5'],
|
||||
['G5', 'E5'],
|
||||
['$G5', '$E5'],
|
||||
['G$5', 'E$5'],
|
||||
['I5', 'G5'],
|
||||
['$I$5', '$G$5'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider cellReferenceHelperDeleteColumnsAbsoluteProvider
|
||||
*/
|
||||
public function testCellReferenceHelperDeleteColumnsAbsolute(string $expectedResult, string $cellAddress): void
|
||||
{
|
||||
$cellReferenceHelper = new CellReferenceHelper('E5', -2, 0);
|
||||
$result = $cellReferenceHelper->updateCellReference($cellAddress, true);
|
||||
self::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
public function cellReferenceHelperDeleteColumnsAbsoluteProvider(): array
|
||||
{
|
||||
return [
|
||||
['A1', 'A1'],
|
||||
['D5', 'D5'],
|
||||
['C5', 'E5'],
|
||||
['$C5', '$E5'],
|
||||
['C$5', 'E$5'],
|
||||
['E5', 'G5'],
|
||||
['$E$5', '$G$5'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider cellReferenceHelperInsertRowsAbsoluteProvider
|
||||
*/
|
||||
public function testCellReferenceHelperInsertRowsAbsolute(string $expectedResult, string $cellAddress): void
|
||||
{
|
||||
$cellReferenceHelper = new CellReferenceHelper('E5', 0, 2);
|
||||
$result = $cellReferenceHelper->updateCellReference($cellAddress, true);
|
||||
self::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
public function cellReferenceHelperInsertRowsAbsoluteProvider(): array
|
||||
{
|
||||
return [
|
||||
['A1', 'A1'],
|
||||
['E4', 'E4'],
|
||||
['E7', 'E5'],
|
||||
['E$7', 'E$5'],
|
||||
['$E7', '$E5'],
|
||||
['E11', 'E9'],
|
||||
['$E$11', '$E$9'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider cellReferenceHelperDeleteRowsAbsoluteProvider
|
||||
*/
|
||||
public function testCellReferenceHelperDeleteRowsAbsolute(string $expectedResult, string $cellAddress): void
|
||||
{
|
||||
$cellReferenceHelper = new CellReferenceHelper('E5', 0, -2);
|
||||
$result = $cellReferenceHelper->updateCellReference($cellAddress, true);
|
||||
self::assertSame($expectedResult, $result);
|
||||
}
|
||||
|
||||
public function cellReferenceHelperDeleteRowsAbsoluteProvider(): array
|
||||
{
|
||||
return [
|
||||
['A1', 'A1'],
|
||||
['E4', 'E4'],
|
||||
['E3', 'E5'],
|
||||
['E$3', 'E$5'],
|
||||
['$E3', '$E5'],
|
||||
['E7', 'E9'],
|
||||
['$E$7', '$E$9'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -20,7 +20,8 @@ class CellsTest extends TestCase
|
|||
// Assert empty state
|
||||
self::assertEquals([], $collection->getCoordinates(), 'cell list should be empty');
|
||||
self::assertEquals([], $collection->getSortedCoordinates(), 'sorted cell list should be empty');
|
||||
self::assertNull($collection->get('B2'), 'getting non-existing cell must return null');
|
||||
$getB2 = $collection->get('B2');
|
||||
self::assertNull($getB2, 'getting non-existing cell must return null');
|
||||
self::assertFalse($collection->has('B2'), 'non-existing cell should be non-existent');
|
||||
|
||||
// Add one cell
|
||||
|
|
@ -44,6 +45,7 @@ class CellsTest extends TestCase
|
|||
$collection2 = $collection->cloneCellCollection($sheet2);
|
||||
self::assertTrue($collection2->has('A1'));
|
||||
$copiedCell2 = $collection2->get('A1');
|
||||
self::assertNotNull($copiedCell2);
|
||||
self::assertNotSame($cell2, $copiedCell2, 'copied cell should not be the same object any more');
|
||||
self::assertSame($collection2, $copiedCell2->getParent(), 'copied cell should be owned by the copied collection');
|
||||
self::assertSame('A1', $copiedCell2->getCoordinate(), 'copied cell should keep attributes');
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class ColumnWidthTest extends AbstractFunctional
|
|||
/**
|
||||
* @dataProvider providerFormats
|
||||
*/
|
||||
public function testReadColumnWidth($format): void
|
||||
public function testReadColumnWidth(string $format): void
|
||||
{
|
||||
// create new sheet with column width
|
||||
$spreadsheet = new Spreadsheet();
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class CommentsTest extends AbstractFunctional
|
|||
*
|
||||
* @dataProvider providerFormats
|
||||
*/
|
||||
public function testComments($format): void
|
||||
public function testComments(string $format): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
|
||||
|
|
|
|||
|
|
@ -44,15 +44,23 @@ class PrintAreaTest extends AbstractFunctional
|
|||
$reader->setLoadSheetsOnly(['Sheet 1', 'Sheet 3', 'Sheet 4', 'Sheet 5', 'Sheet 6']);
|
||||
});
|
||||
|
||||
$actual1 = $reloadedSpreadsheet->getSheetByName('Sheet 1')->getPageSetup()->getPrintArea();
|
||||
$actual3 = $reloadedSpreadsheet->getSheetByName('Sheet 3')->getPageSetup()->getPrintArea();
|
||||
$actual4 = $reloadedSpreadsheet->getSheetByName('Sheet 4')->getPageSetup()->getPrintArea();
|
||||
$actual5 = $reloadedSpreadsheet->getSheetByName('Sheet 5')->getPageSetup()->getPrintArea();
|
||||
$actual6 = $reloadedSpreadsheet->getSheetByName('Sheet 6')->getPageSetup()->getPrintArea();
|
||||
$actual1 = self::getPrintArea($reloadedSpreadsheet, 'Sheet 1');
|
||||
$actual3 = self::getPrintArea($reloadedSpreadsheet, 'Sheet 3');
|
||||
$actual4 = self::getPrintArea($reloadedSpreadsheet, 'Sheet 4');
|
||||
$actual5 = self::getPrintArea($reloadedSpreadsheet, 'Sheet 5');
|
||||
$actual6 = self::getPrintArea($reloadedSpreadsheet, 'Sheet 6');
|
||||
self::assertSame('A1:B1', $actual1, 'should be able to write and read normal page setup');
|
||||
self::assertSame('A3:B3', $actual3, 'should be able to write and read page setup even when skipping sheets');
|
||||
self::assertSame('A4:B4,D1:E4', $actual4, 'should be able to write and read page setup with multiple print areas');
|
||||
self::assertSame('A1:J10', $actual5, 'add by column and row');
|
||||
self::assertSame('A1:J10,L1:L10', $actual6, 'multiple add by column and row');
|
||||
}
|
||||
|
||||
private static function getPrintArea(Spreadsheet $spreadsheet, string $name): string
|
||||
{
|
||||
$sheet = $spreadsheet->getSheetByName($name);
|
||||
self::assertNotNull($sheet, "Unable to get sheet $name");
|
||||
|
||||
return $sheet->getPageSetup()->getPrintArea();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class IOFactoryTest extends TestCase
|
|||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$actual = IOFactory::createWriter($spreadsheet, $name);
|
||||
self::assertInstanceOf($expected, $actual);
|
||||
self::assertSame($expected, get_class($actual));
|
||||
}
|
||||
|
||||
public function providerCreateWriter(): array
|
||||
|
|
@ -55,7 +55,7 @@ class IOFactoryTest extends TestCase
|
|||
public function testCreateReader($name, $expected): void
|
||||
{
|
||||
$actual = IOFactory::createReader($name);
|
||||
self::assertInstanceOf($expected, $actual);
|
||||
self::assertSame($expected, get_class($actual));
|
||||
}
|
||||
|
||||
public function providerCreateReader(): array
|
||||
|
|
@ -102,7 +102,7 @@ class IOFactoryTest extends TestCase
|
|||
public function testCreateReaderForFile($file, $expectedName, $expectedClass): void
|
||||
{
|
||||
$actual = IOFactory::createReaderForFile($file);
|
||||
self::assertInstanceOf($expectedClass, $actual);
|
||||
self::assertSame($expectedClass, get_class($actual));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -48,9 +48,11 @@ class NamedFormulaTest extends TestCase
|
|||
);
|
||||
|
||||
self::assertCount(1, $this->spreadsheet->getNamedFormulae());
|
||||
$formula = $this->spreadsheet->getNamedFormula('foo', $this->spreadsheet->getActiveSheet());
|
||||
self::assertNotNull($formula);
|
||||
self::assertSame(
|
||||
'=16%',
|
||||
$this->spreadsheet->getNamedFormula('foo', $this->spreadsheet->getActiveSheet())->getValue()
|
||||
$formula->getValue()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -64,13 +66,17 @@ class NamedFormulaTest extends TestCase
|
|||
);
|
||||
|
||||
self::assertCount(2, $this->spreadsheet->getNamedFormulae());
|
||||
$formula = $this->spreadsheet->getNamedFormula('foo', $this->spreadsheet->getActiveSheet());
|
||||
self::assertNotNull($formula);
|
||||
self::assertSame(
|
||||
'=19%',
|
||||
$this->spreadsheet->getNamedFormula('foo', $this->spreadsheet->getActiveSheet())->getValue()
|
||||
$formula->getValue()
|
||||
);
|
||||
$formula = $this->spreadsheet->getNamedFormula('foo', $this->spreadsheet->getSheetByName('Sheet #2'));
|
||||
self::assertNotNull($formula);
|
||||
self::assertSame(
|
||||
'=16%',
|
||||
$this->spreadsheet->getNamedFormula('foo', $this->spreadsheet->getSheetByName('Sheet #2'))->getValue()
|
||||
$formula->getValue()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -100,9 +106,11 @@ class NamedFormulaTest extends TestCase
|
|||
$this->spreadsheet->removeNamedFormula('Foo', $this->spreadsheet->getActiveSheet());
|
||||
|
||||
self::assertCount(1, $this->spreadsheet->getNamedFormulae());
|
||||
$formula = $this->spreadsheet->getNamedFormula('foo', $this->spreadsheet->getSheetByName('Sheet #2'));
|
||||
self::assertNotNull($formula);
|
||||
self::assertSame(
|
||||
'=16%',
|
||||
$this->spreadsheet->getNamedFormula('foo', $this->spreadsheet->getSheetByName('Sheet #2'))->getValue()
|
||||
$formula->getValue()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -118,9 +126,11 @@ class NamedFormulaTest extends TestCase
|
|||
$this->spreadsheet->removeNamedFormula('Foo', $this->spreadsheet->getSheetByName('Sheet #2'));
|
||||
|
||||
self::assertCount(1, $this->spreadsheet->getNamedFormulae());
|
||||
$formula = $this->spreadsheet->getNamedFormula('foo');
|
||||
self::assertNotNull($formula);
|
||||
self::assertSame(
|
||||
'=19%',
|
||||
$this->spreadsheet->getNamedFormula('foo')->getValue()
|
||||
$formula->getValue()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,9 +48,11 @@ class NamedRangeTest extends TestCase
|
|||
);
|
||||
|
||||
self::assertCount(1, $this->spreadsheet->getNamedRanges());
|
||||
$range = $this->spreadsheet->getNamedRange('foo', $this->spreadsheet->getActiveSheet());
|
||||
self::assertNotNull($range);
|
||||
self::assertSame(
|
||||
'=B1',
|
||||
$this->spreadsheet->getNamedRange('foo', $this->spreadsheet->getActiveSheet())->getValue()
|
||||
$range->getValue()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -64,13 +66,17 @@ class NamedRangeTest extends TestCase
|
|||
);
|
||||
|
||||
self::assertCount(2, $this->spreadsheet->getNamedRanges());
|
||||
$range = $this->spreadsheet->getNamedRange('foo', $this->spreadsheet->getActiveSheet());
|
||||
self::assertNotNull($range);
|
||||
self::assertSame(
|
||||
'=A1',
|
||||
$this->spreadsheet->getNamedRange('foo', $this->spreadsheet->getActiveSheet())->getValue()
|
||||
$range->getValue()
|
||||
);
|
||||
$range = $this->spreadsheet->getNamedRange('foo', $this->spreadsheet->getSheetByName('Sheet #2'));
|
||||
self::assertNotNull($range);
|
||||
self::assertSame(
|
||||
'=B1',
|
||||
$this->spreadsheet->getNamedRange('foo', $this->spreadsheet->getSheetByName('Sheet #2'))->getValue()
|
||||
$range->getValue()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -100,9 +106,11 @@ class NamedRangeTest extends TestCase
|
|||
$this->spreadsheet->removeNamedRange('Foo', $this->spreadsheet->getActiveSheet());
|
||||
|
||||
self::assertCount(1, $this->spreadsheet->getNamedRanges());
|
||||
$sheet = $this->spreadsheet->getNamedRange('foo', $this->spreadsheet->getSheetByName('Sheet #2'));
|
||||
self::assertNotNull($sheet);
|
||||
self::assertSame(
|
||||
'=B1',
|
||||
$this->spreadsheet->getNamedRange('foo', $this->spreadsheet->getSheetByName('Sheet #2'))->getValue()
|
||||
$sheet->getValue()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -118,9 +126,11 @@ class NamedRangeTest extends TestCase
|
|||
$this->spreadsheet->removeNamedRange('Foo', $this->spreadsheet->getSheetByName('Sheet #2'));
|
||||
|
||||
self::assertCount(1, $this->spreadsheet->getNamedRanges());
|
||||
$range = $this->spreadsheet->getNamedRange('foo');
|
||||
self::AssertNotNull($range);
|
||||
self::assertSame(
|
||||
'=A1',
|
||||
$this->spreadsheet->getNamedRange('foo')->getValue()
|
||||
$range->getValue()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,6 +96,8 @@ class CsvNumberFormatLocaleTest extends TestCase
|
|||
* @dataProvider providerNumberValueConversionTest
|
||||
*
|
||||
* @param mixed $expectedValue
|
||||
*
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
public function testNumberValueConversion($expectedValue, string $cellAddress): void
|
||||
{
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ use PHPUnit\Framework\TestCase;
|
|||
*/
|
||||
class OdsTest extends TestCase
|
||||
{
|
||||
/** @var string */
|
||||
private $incompleteMessage = 'Features not implemented yet';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
|
|
@ -32,12 +35,12 @@ class OdsTest extends TestCase
|
|||
}
|
||||
|
||||
/**
|
||||
* @var Spreadsheet
|
||||
* @var ?Spreadsheet
|
||||
*/
|
||||
private $spreadsheetOdsTest;
|
||||
|
||||
/**
|
||||
* @var Spreadsheet
|
||||
* @var ?Spreadsheet
|
||||
*/
|
||||
private $spreadsheetData;
|
||||
|
||||
|
|
@ -46,13 +49,13 @@ class OdsTest extends TestCase
|
|||
*/
|
||||
private function loadOdsTestFile()
|
||||
{
|
||||
if (!isset($this->spreadsheetOdsTest)) {
|
||||
$filename = 'samples/templates/OOCalcTest.ods';
|
||||
|
||||
// Load into this instance
|
||||
$reader = new Ods();
|
||||
$this->spreadsheetOdsTest = $reader->loadIntoExisting($filename, new Spreadsheet());
|
||||
if (isset($this->spreadsheetOdsTest)) {
|
||||
return $this->spreadsheetOdsTest;
|
||||
}
|
||||
$filename = 'samples/templates/OOCalcTest.ods';
|
||||
// Load into this instance
|
||||
$reader = new Ods();
|
||||
$this->spreadsheetOdsTest = $reader->loadIntoExisting($filename, new Spreadsheet());
|
||||
|
||||
return $this->spreadsheetOdsTest;
|
||||
}
|
||||
|
|
@ -62,13 +65,13 @@ class OdsTest extends TestCase
|
|||
*/
|
||||
protected function loadDataFile()
|
||||
{
|
||||
if (!isset($this->spreadsheetData)) {
|
||||
$filename = 'tests/data/Reader/Ods/data.ods';
|
||||
|
||||
// Load into this instance
|
||||
$reader = new Ods();
|
||||
$this->spreadsheetData = $reader->load($filename);
|
||||
if (isset($this->spreadsheetData)) {
|
||||
return $this->spreadsheetData;
|
||||
}
|
||||
$filename = 'tests/data/Reader/Ods/data.ods';
|
||||
// Load into this instance
|
||||
$reader = new Ods();
|
||||
$this->spreadsheetData = $reader->load($filename);
|
||||
|
||||
return $this->spreadsheetData;
|
||||
}
|
||||
|
|
@ -271,8 +274,9 @@ class OdsTest extends TestCase
|
|||
|
||||
public function testReadBoldItalicUnderline(): void
|
||||
{
|
||||
self::markTestIncomplete('Features not implemented yet');
|
||||
|
||||
if ($this->incompleteMessage !== '') {
|
||||
self::markTestIncomplete($this->incompleteMessage);
|
||||
}
|
||||
$spreadsheet = $this->loadOdsTestFile();
|
||||
$firstSheet = $spreadsheet->getSheet(0);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class XmlScannerTest extends TestCase
|
|||
* @param mixed $filename
|
||||
* @param mixed $expectedResult
|
||||
*/
|
||||
public function testValidXML($filename, $expectedResult, $libxmlDisableEntityLoader): void
|
||||
public function testValidXML($filename, $expectedResult, bool $libxmlDisableEntityLoader): void
|
||||
{
|
||||
// php 8.+ deprecated libxml_disable_entity_loader() - It's on by default
|
||||
if (\PHP_VERSION_ID < 80000) {
|
||||
|
|
@ -44,7 +44,9 @@ class XmlScannerTest extends TestCase
|
|||
public function providerValidXML(): array
|
||||
{
|
||||
$tests = [];
|
||||
foreach (glob('tests/data/Reader/Xml/XEETestValid*.xml') as $file) {
|
||||
$glob = glob('tests/data/Reader/Xml/XEETestValid*.xml');
|
||||
self::assertNotFalse($glob);
|
||||
foreach ($glob as $file) {
|
||||
$filename = realpath($file);
|
||||
$expectedResult = file_get_contents($file);
|
||||
$tests[basename($file) . '_libxml_entity_loader_disabled'] = [$filename, $expectedResult, true];
|
||||
|
|
@ -59,7 +61,7 @@ class XmlScannerTest extends TestCase
|
|||
*
|
||||
* @param mixed $filename
|
||||
*/
|
||||
public function testInvalidXML($filename, $libxmlDisableEntityLoader): void
|
||||
public function testInvalidXML($filename, bool $libxmlDisableEntityLoader): void
|
||||
{
|
||||
$this->expectException(\PhpOffice\PhpSpreadsheet\Reader\Exception::class);
|
||||
|
||||
|
|
@ -81,7 +83,9 @@ class XmlScannerTest extends TestCase
|
|||
public function providerInvalidXML(): array
|
||||
{
|
||||
$tests = [];
|
||||
foreach (glob('tests/data/Reader/Xml/XEETestInvalidUTF*.xml') as $file) {
|
||||
$glob = glob('tests/data/Reader/Xml/XEETestInvalidUTF*.xml');
|
||||
self::assertNotFalse($glob);
|
||||
foreach ($glob as $file) {
|
||||
$filename = realpath($file);
|
||||
$tests[basename($file) . '_libxml_entity_loader_disabled'] = [$filename, true];
|
||||
$tests[basename($file) . '_libxml_entity_loader_enabled'] = [$filename, false];
|
||||
|
|
@ -128,7 +132,9 @@ class XmlScannerTest extends TestCase
|
|||
public function providerValidXMLForCallback(): array
|
||||
{
|
||||
$tests = [];
|
||||
foreach (glob('tests/data/Reader/Xml/SecurityScannerWithCallback*.xml') as $file) {
|
||||
$glob = glob('tests/data/Reader/Xml/SecurityScannerWithCallback*.xml');
|
||||
self::assertNotFalse($glob);
|
||||
foreach ($glob as $file) {
|
||||
$tests[basename($file)] = [realpath($file), file_get_contents($file)];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,14 +10,7 @@ use SimpleXMLElement;
|
|||
|
||||
class AutoFilterTest extends TestCase
|
||||
{
|
||||
private function getWorksheetInstance()
|
||||
{
|
||||
return $this->getMockBuilder(Worksheet::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
}
|
||||
|
||||
private function getXMLInstance($ref)
|
||||
private function getXMLInstance(string $ref): SimpleXMLElement
|
||||
{
|
||||
return new SimpleXMLElement(
|
||||
'<?xml version="1.0" encoding="UTF-8"?>' .
|
||||
|
|
@ -27,15 +20,6 @@ class AutoFilterTest extends TestCase
|
|||
);
|
||||
}
|
||||
|
||||
private function getAutoFilterInstance()
|
||||
{
|
||||
$instance = $this->getMockBuilder(WorksheetAutoFilter::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
public function loadDataProvider(): array
|
||||
{
|
||||
return [
|
||||
|
|
@ -53,12 +37,16 @@ class AutoFilterTest extends TestCase
|
|||
*/
|
||||
public function testLoad($ref, $expectedReadAutoFilterCalled, $expectedRef): void
|
||||
{
|
||||
$worksheetAutoFilter = $this->getAutoFilterInstance();
|
||||
$worksheetAutoFilter = $this->getMockBuilder(WorksheetAutoFilter::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$worksheetAutoFilter->expects(self::exactly($expectedReadAutoFilterCalled ? 1 : 0))
|
||||
->method('setRange')
|
||||
->with($expectedRef);
|
||||
|
||||
$worksheet = $this->getWorksheetInstance();
|
||||
$worksheet = $this->getMockBuilder(Worksheet::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$worksheet->expects(self::exactly($expectedReadAutoFilterCalled ? 1 : 0))
|
||||
->method('getAutoFilter')
|
||||
->willReturn($worksheetAutoFilter);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ class ChartsTitleTest extends TestCase
|
|||
|
||||
// No title or axis labels
|
||||
$chart1 = $charts[0];
|
||||
self::assertNotNull($chart1);
|
||||
$title = self::getTitleText($chart1->getTitle());
|
||||
self::assertEmpty($title);
|
||||
self::assertEmpty(self::getTitleText($chart1->getXAxisLabel()));
|
||||
|
|
@ -33,6 +34,7 @@ class ChartsTitleTest extends TestCase
|
|||
|
||||
// Title, no axis labels
|
||||
$chart2 = $charts[1];
|
||||
self::assertNotNull($chart2);
|
||||
|
||||
self::assertEquals('Chart with Title and no Axis Labels', self::getTitleText($chart2->getTitle()));
|
||||
self::assertEmpty(self::getTitleText($chart2->getXAxisLabel()));
|
||||
|
|
@ -40,18 +42,21 @@ class ChartsTitleTest extends TestCase
|
|||
|
||||
// No title, only horizontal axis label
|
||||
$chart3 = $charts[2];
|
||||
self::assertNotNull($chart3);
|
||||
self::assertEmpty(self::getTitleText($chart3->getTitle()));
|
||||
self::assertEquals('Horizontal Axis Title Only', self::getTitleText($chart3->getXAxisLabel()));
|
||||
self::assertEmpty(self::getTitleText($chart3->getYAxisLabel()));
|
||||
|
||||
// No title, only vertical axis label
|
||||
$chart4 = $charts[3];
|
||||
self::assertNotNull($chart4);
|
||||
self::assertEmpty(self::getTitleText($chart4->getTitle()));
|
||||
self::assertEquals('Vertical Axis Title Only', self::getTitleText($chart4->getYAxisLabel()));
|
||||
self::assertEmpty(self::getTitleText($chart4->getXAxisLabel()));
|
||||
|
||||
// Title and both axis labels
|
||||
$chart5 = $charts[4];
|
||||
self::assertNotNull($chart5);
|
||||
self::assertEquals('Complete Annotations', self::getTitleText($chart5->getTitle()));
|
||||
self::assertEquals('Horizontal Axis Title', self::getTitleText($chart5->getXAxisLabel()));
|
||||
self::assertEquals('Vertical Axis Title', self::getTitleText($chart5->getYAxisLabel()));
|
||||
|
|
|
|||
|
|
@ -60,7 +60,9 @@ class ConditionalFormattingDataBarXlsxTest extends TestCase
|
|||
$cond1 = new Conditional();
|
||||
$cond1->setConditionType(Conditional::CONDITION_DATABAR);
|
||||
$cond1->setDataBar(new ConditionalDataBar());
|
||||
$cond1->getDataBar()
|
||||
$dataBar = $cond1->getDataBar();
|
||||
self::assertNotNull($dataBar);
|
||||
$dataBar
|
||||
->setMinimumConditionalFormatValueObject(new ConditionalFormatValueObject('min'))
|
||||
->setMaximumConditionalFormatValueObject(new ConditionalFormatValueObject('max'))
|
||||
->setColor(Color::COLOR_GREEN);
|
||||
|
|
@ -83,6 +85,7 @@ class ConditionalFormattingDataBarXlsxTest extends TestCase
|
|||
self::assertNotEmpty($conditionalRule->getDataBar());
|
||||
|
||||
$dataBar = $conditionalRule->getDataBar();
|
||||
self::assertNotNull($dataBar);
|
||||
self::assertNotEmpty($dataBar->getMinimumConditionalFormatValueObject());
|
||||
self::assertNotEmpty($dataBar->getMaximumConditionalFormatValueObject());
|
||||
self::assertEquals('min', $dataBar->getMinimumConditionalFormatValueObject()->getType());
|
||||
|
|
@ -105,6 +108,7 @@ class ConditionalFormattingDataBarXlsxTest extends TestCase
|
|||
|
||||
self::assertNotEmpty($dataBar);
|
||||
self::assertEquals(Conditional::CONDITION_DATABAR, $conditionalRule->getConditionType());
|
||||
self::assertNotNull($dataBar);
|
||||
self::assertNotEmpty($dataBar->getMinimumConditionalFormatValueObject());
|
||||
self::assertNotEmpty($dataBar->getMaximumConditionalFormatValueObject());
|
||||
self::assertEquals('min', $dataBar->getMinimumConditionalFormatValueObject()->getType());
|
||||
|
|
@ -160,6 +164,7 @@ class ConditionalFormattingDataBarXlsxTest extends TestCase
|
|||
|
||||
self::assertNotEmpty($dataBar);
|
||||
self::assertEquals(Conditional::CONDITION_DATABAR, $conditionalRule->getConditionType());
|
||||
self::assertNotNull($dataBar);
|
||||
self::assertNotEmpty($dataBar->getMinimumConditionalFormatValueObject());
|
||||
self::assertNotEmpty($dataBar->getMaximumConditionalFormatValueObject());
|
||||
self::assertEquals('num', $dataBar->getMinimumConditionalFormatValueObject()->getType());
|
||||
|
|
@ -218,6 +223,7 @@ class ConditionalFormattingDataBarXlsxTest extends TestCase
|
|||
|
||||
self::assertNotEmpty($dataBar);
|
||||
self::assertEquals(Conditional::CONDITION_DATABAR, $conditionalRule->getConditionType());
|
||||
self::assertNotNull($dataBar);
|
||||
self::assertNotEmpty($dataBar->getMinimumConditionalFormatValueObject());
|
||||
self::assertNotEmpty($dataBar->getMaximumConditionalFormatValueObject());
|
||||
self::assertEquals('min', $dataBar->getMinimumConditionalFormatValueObject()->getType());
|
||||
|
|
@ -278,6 +284,7 @@ class ConditionalFormattingDataBarXlsxTest extends TestCase
|
|||
self::assertNotEmpty($dataBar);
|
||||
self::assertEquals(Conditional::CONDITION_DATABAR, $conditionalRule->getConditionType());
|
||||
|
||||
self::assertNotNull($dataBar);
|
||||
self::assertTrue($dataBar->getShowValue());
|
||||
self::assertNotEmpty($dataBar->getMinimumConditionalFormatValueObject());
|
||||
self::assertNotEmpty($dataBar->getMaximumConditionalFormatValueObject());
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ class SheetsXlsxChartTest extends TestCase
|
|||
self::assertCount(2, $charts);
|
||||
|
||||
$chart1 = $charts[0];
|
||||
self::assertNotNull($chart1);
|
||||
$pa1 = $chart1->getPlotArea();
|
||||
self::assertEquals(2, $pa1->getPlotSeriesCount());
|
||||
|
||||
|
|
@ -32,6 +33,7 @@ class SheetsXlsxChartTest extends TestCase
|
|||
self::assertCount(2, $pg1->getPlotCategories());
|
||||
|
||||
$chart2 = $charts[1];
|
||||
self::assertNotNull($chart2);
|
||||
$pa1 = $chart2->getPlotArea();
|
||||
self::assertEquals(2, $pa1->getPlotSeriesCount());
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ class XmlTest extends TestCase
|
|||
/**
|
||||
* @dataProvider providerInvalidSimpleXML
|
||||
*/
|
||||
public function testInvalidSimpleXML($filename): void
|
||||
public function testInvalidSimpleXML(string $filename): void
|
||||
{
|
||||
$this->expectException(\PhpOffice\PhpSpreadsheet\Reader\Exception::class);
|
||||
|
||||
|
|
@ -22,7 +22,9 @@ class XmlTest extends TestCase
|
|||
public function providerInvalidSimpleXML(): array
|
||||
{
|
||||
$tests = [];
|
||||
foreach (glob('tests/data/Reader/Xml/XEETestInvalidSimpleXML*.xml') as $file) {
|
||||
$glob = glob('tests/data/Reader/Xml/XEETestInvalidSimpleXML*.xml');
|
||||
self::assertNotFalse($glob);
|
||||
foreach ($glob as $file) {
|
||||
$tests[basename($file)] = [realpath($file)];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,12 @@
|
|||
namespace PhpOffice\PhpSpreadsheetTests;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Hyperlink;
|
||||
use PhpOffice\PhpSpreadsheet\Comment;
|
||||
use PhpOffice\PhpSpreadsheet\ReferenceHelper;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\Wizard;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ReferenceHelperTest extends TestCase
|
||||
|
|
@ -177,4 +181,357 @@ class ReferenceHelperTest extends TestCase
|
|||
self::assertNull($cells[1][1]);
|
||||
self::assertArrayNotHasKey(2, $cells[1]);
|
||||
}
|
||||
|
||||
public function testInsertRowsWithPageBreaks(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$sheet->fromArray([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]], null, 'A1', true);
|
||||
$sheet->setBreak('A2', Worksheet::BREAK_ROW);
|
||||
$sheet->setBreak('A5', Worksheet::BREAK_ROW);
|
||||
|
||||
$sheet->insertNewRowBefore(2, 2);
|
||||
|
||||
$breaks = $sheet->getBreaks();
|
||||
ksort($breaks);
|
||||
self::assertSame(['A4' => Worksheet::BREAK_ROW, 'A7' => Worksheet::BREAK_ROW], $breaks);
|
||||
}
|
||||
|
||||
public function testDeleteRowsWithPageBreaks(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$sheet->fromArray([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]], null, 'A1', true);
|
||||
$sheet->setBreak('A2', Worksheet::BREAK_ROW);
|
||||
$sheet->setBreak('A5', Worksheet::BREAK_ROW);
|
||||
|
||||
$sheet->removeRow(2, 2);
|
||||
|
||||
$breaks = $sheet->getBreaks();
|
||||
self::assertSame(['A3' => Worksheet::BREAK_ROW], $breaks);
|
||||
}
|
||||
|
||||
public function testInsertRowsWithComments(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$sheet->fromArray([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]], null, 'A1', true);
|
||||
$sheet->getComment('A2')->getText()->createText('First Comment');
|
||||
$sheet->getComment('A5')->getText()->createText('Second Comment');
|
||||
|
||||
$sheet->insertNewRowBefore(2, 2);
|
||||
|
||||
$comments = array_map(
|
||||
function (Comment $value) {
|
||||
return $value->getText()->getPlainText();
|
||||
},
|
||||
$sheet->getComments()
|
||||
);
|
||||
|
||||
self::assertSame(['A4' => 'First Comment', 'A7' => 'Second Comment'], $comments);
|
||||
}
|
||||
|
||||
public function testDeleteRowsWithComments(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$sheet->fromArray([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]], null, 'A1', true);
|
||||
$sheet->getComment('A2')->getText()->createText('First Comment');
|
||||
$sheet->getComment('A5')->getText()->createText('Second Comment');
|
||||
|
||||
$sheet->removeRow(2, 2);
|
||||
|
||||
$comments = array_map(
|
||||
function (Comment $value) {
|
||||
return $value->getText()->getPlainText();
|
||||
},
|
||||
$sheet->getComments()
|
||||
);
|
||||
|
||||
self::assertSame(['A3' => 'Second Comment'], $comments);
|
||||
}
|
||||
|
||||
public function testInsertRowsWithHyperlinks(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$sheet->fromArray([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]], null, 'A1', true);
|
||||
$sheet->getCell('A2')->getHyperlink()->setUrl('https://github.com/PHPOffice/PhpSpreadsheet');
|
||||
$sheet->getCell('A5')->getHyperlink()->setUrl('https://phpspreadsheet.readthedocs.io/en/latest/');
|
||||
|
||||
$sheet->insertNewRowBefore(2, 2);
|
||||
|
||||
$hyperlinks = array_map(
|
||||
function (Hyperlink $value) {
|
||||
return $value->getUrl();
|
||||
},
|
||||
$sheet->getHyperlinkCollection()
|
||||
);
|
||||
ksort($hyperlinks);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
'A4' => 'https://github.com/PHPOffice/PhpSpreadsheet',
|
||||
'A7' => 'https://phpspreadsheet.readthedocs.io/en/latest/',
|
||||
],
|
||||
$hyperlinks
|
||||
);
|
||||
}
|
||||
|
||||
public function testDeleteRowsWithHyperlinks(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$sheet->fromArray([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]], null, 'A1', true);
|
||||
$sheet->getCell('A2')->getHyperlink()->setUrl('https://github.com/PHPOffice/PhpSpreadsheet');
|
||||
$sheet->getCell('A5')->getHyperlink()->setUrl('https://phpspreadsheet.readthedocs.io/en/latest/');
|
||||
|
||||
$sheet->removeRow(2, 2);
|
||||
|
||||
$hyperlinks = array_map(
|
||||
function (Hyperlink $value) {
|
||||
return $value->getUrl();
|
||||
},
|
||||
$sheet->getHyperlinkCollection()
|
||||
);
|
||||
|
||||
self::assertSame(['A3' => 'https://phpspreadsheet.readthedocs.io/en/latest/'], $hyperlinks);
|
||||
}
|
||||
|
||||
public function testInsertRowsWithDataValidation(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
|
||||
$sheet->fromArray([['First'], ['Second'], ['Third'], ['Fourth']], null, 'A5', true);
|
||||
$cellAddress = 'E5';
|
||||
$this->setDataValidation($sheet, $cellAddress);
|
||||
|
||||
$sheet->insertNewRowBefore(2, 2);
|
||||
|
||||
self::assertFalse($sheet->getCell($cellAddress)->hasDataValidation());
|
||||
self::assertTrue($sheet->getCell('E7')->hasDataValidation());
|
||||
}
|
||||
|
||||
public function testDeleteRowsWithDataValidation(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
|
||||
$sheet->fromArray([['First'], ['Second'], ['Third'], ['Fourth']], null, 'A5', true);
|
||||
$cellAddress = 'E5';
|
||||
$this->setDataValidation($sheet, $cellAddress);
|
||||
|
||||
$sheet->removeRow(2, 2);
|
||||
|
||||
self::assertFalse($sheet->getCell($cellAddress)->hasDataValidation());
|
||||
self::assertTrue($sheet->getCell('E3')->hasDataValidation());
|
||||
}
|
||||
|
||||
public function testDeleteColumnsWithDataValidation(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
|
||||
$sheet->fromArray([['First'], ['Second'], ['Third'], ['Fourth']], null, 'A5', true);
|
||||
$cellAddress = 'E5';
|
||||
$this->setDataValidation($sheet, $cellAddress);
|
||||
|
||||
$sheet->removeColumn('B', 2);
|
||||
|
||||
self::assertFalse($sheet->getCell($cellAddress)->hasDataValidation());
|
||||
self::assertTrue($sheet->getCell('C5')->hasDataValidation());
|
||||
}
|
||||
|
||||
public function testInsertColumnsWithDataValidation(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
|
||||
$sheet->fromArray([['First'], ['Second'], ['Third'], ['Fourth']], null, 'A5', true);
|
||||
$cellAddress = 'E5';
|
||||
$this->setDataValidation($sheet, $cellAddress);
|
||||
|
||||
$sheet->insertNewColumnBefore('C', 2);
|
||||
|
||||
self::assertFalse($sheet->getCell($cellAddress)->hasDataValidation());
|
||||
self::assertTrue($sheet->getCell('G5')->hasDataValidation());
|
||||
}
|
||||
|
||||
private function setDataValidation(Worksheet $sheet, string $cellAddress): void
|
||||
{
|
||||
$validation = $sheet->getCell($cellAddress)
|
||||
->getDataValidation();
|
||||
$validation->setType(\PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_LIST);
|
||||
$validation->setErrorStyle(\PhpOffice\PhpSpreadsheet\Cell\DataValidation::STYLE_INFORMATION);
|
||||
$validation->setAllowBlank(false);
|
||||
$validation->setShowInputMessage(true);
|
||||
$validation->setShowErrorMessage(true);
|
||||
$validation->setShowDropDown(true);
|
||||
$validation->setErrorTitle('Input error');
|
||||
$validation->setError('Value is not in list.');
|
||||
$validation->setPromptTitle('Pick from list');
|
||||
$validation->setPrompt('Please pick a value from the drop-down list.');
|
||||
$validation->setFormula1('$A5:$A8');
|
||||
}
|
||||
|
||||
public function testInsertRowsWithConditionalFormatting(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$sheet->fromArray([[1, 2, 3, 4], [3, 4, 5, 6], [5, 6, 7, 8], [7, 8, 9, 10], [9, 10, 11, 12]], null, 'C3', true);
|
||||
$sheet->getCell('H5')->setValue(5);
|
||||
|
||||
$cellRange = 'C3:F7';
|
||||
$this->setConditionalFormatting($sheet, $cellRange);
|
||||
|
||||
$sheet->insertNewRowBefore(4, 2);
|
||||
|
||||
$styles = $sheet->getConditionalStylesCollection();
|
||||
// verify that the conditional range has been updated
|
||||
self::assertSame('C3:F9', array_keys($styles)[0]);
|
||||
// verify that the conditions have been updated
|
||||
foreach ($styles as $style) {
|
||||
foreach ($style as $conditions) {
|
||||
self::assertSame('$H$7', $conditions->getConditions()[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function testInsertColumnssWithConditionalFormatting(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$sheet->fromArray([[1, 2, 3, 4], [3, 4, 5, 6], [5, 6, 7, 8], [7, 8, 9, 10], [9, 10, 11, 12]], null, 'C3', true);
|
||||
$sheet->getCell('H5')->setValue(5);
|
||||
|
||||
$cellRange = 'C3:F7';
|
||||
$this->setConditionalFormatting($sheet, $cellRange);
|
||||
|
||||
$sheet->insertNewColumnBefore('C', 2);
|
||||
|
||||
$styles = $sheet->getConditionalStylesCollection();
|
||||
// verify that the conditional range has been updated
|
||||
self::assertSame('E3:H7', array_keys($styles)[0]);
|
||||
// verify that the conditions have been updated
|
||||
foreach ($styles as $style) {
|
||||
foreach ($style as $conditions) {
|
||||
self::assertSame('$J$5', $conditions->getConditions()[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function testDeleteRowsWithConditionalFormatting(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$sheet->fromArray([[1, 2, 3, 4], [3, 4, 5, 6], [5, 6, 7, 8], [7, 8, 9, 10], [9, 10, 11, 12]], null, 'C3', true);
|
||||
$sheet->getCell('H5')->setValue(5);
|
||||
|
||||
$cellRange = 'C3:F7';
|
||||
$this->setConditionalFormatting($sheet, $cellRange);
|
||||
|
||||
$sheet->removeRow(4, 2);
|
||||
|
||||
$styles = $sheet->getConditionalStylesCollection();
|
||||
// verify that the conditional range has been updated
|
||||
self::assertSame('C3:F5', array_keys($styles)[0]);
|
||||
// verify that the conditions have been updated
|
||||
foreach ($styles as $style) {
|
||||
foreach ($style as $conditions) {
|
||||
self::assertSame('$H$5', $conditions->getConditions()[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function testDeleteColumnsWithConditionalFormatting(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$sheet->fromArray([[1, 2, 3, 4], [3, 4, 5, 6], [5, 6, 7, 8], [7, 8, 9, 10], [9, 10, 11, 12]], null, 'C3', true);
|
||||
$sheet->getCell('H5')->setValue(5);
|
||||
|
||||
$cellRange = 'C3:F7';
|
||||
$this->setConditionalFormatting($sheet, $cellRange);
|
||||
|
||||
$sheet->removeColumn('D', 2);
|
||||
|
||||
$styles = $sheet->getConditionalStylesCollection();
|
||||
// verify that the conditional range has been updated
|
||||
self::assertSame('C3:D7', array_keys($styles)[0]);
|
||||
// verify that the conditions have been updated
|
||||
foreach ($styles as $style) {
|
||||
foreach ($style as $conditions) {
|
||||
self::assertSame('$F$5', $conditions->getConditions()[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function setConditionalFormatting(Worksheet $sheet, string $cellRange): void
|
||||
{
|
||||
$conditionalStyles = [];
|
||||
$wizardFactory = new Wizard($cellRange);
|
||||
/** @var Wizard\CellValue $cellWizard */
|
||||
$cellWizard = $wizardFactory->newRule(Wizard::CELL_VALUE);
|
||||
|
||||
$cellWizard->equals('$H$5', Wizard::VALUE_TYPE_CELL);
|
||||
$conditionalStyles[] = $cellWizard->getConditional();
|
||||
|
||||
$cellWizard->greaterThan('$H$5', Wizard::VALUE_TYPE_CELL);
|
||||
$conditionalStyles[] = $cellWizard->getConditional();
|
||||
|
||||
$cellWizard->lessThan('$H$5', Wizard::VALUE_TYPE_CELL);
|
||||
$conditionalStyles[] = $cellWizard->getConditional();
|
||||
|
||||
$sheet->getStyle($cellWizard->getCellRange())
|
||||
->setConditionalStyles($conditionalStyles);
|
||||
}
|
||||
|
||||
public function testInsertRowsWithPrintArea(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$sheet->getPageSetup()->setPrintArea('A1:J10');
|
||||
|
||||
$sheet->insertNewRowBefore(2, 2);
|
||||
|
||||
$printArea = $sheet->getPageSetup()->getPrintArea();
|
||||
self::assertSame('A1:J12', $printArea);
|
||||
}
|
||||
|
||||
public function testInsertColumnsWithPrintArea(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$sheet->getPageSetup()->setPrintArea('A1:J10');
|
||||
|
||||
$sheet->insertNewColumnBefore('B', 2);
|
||||
|
||||
$printArea = $sheet->getPageSetup()->getPrintArea();
|
||||
self::assertSame('A1:L10', $printArea);
|
||||
}
|
||||
|
||||
public function testDeleteRowsWithPrintArea(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$sheet->getPageSetup()->setPrintArea('A1:J10');
|
||||
|
||||
$sheet->removeRow(2, 2);
|
||||
|
||||
$printArea = $sheet->getPageSetup()->getPrintArea();
|
||||
self::assertSame('A1:J8', $printArea);
|
||||
}
|
||||
|
||||
public function testDeleteColumnsWithPrintArea(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$sheet->getPageSetup()->setPrintArea('A1:J10');
|
||||
|
||||
$sheet->removeColumn('B', 2);
|
||||
|
||||
$printArea = $sheet->getPageSetup()->getPrintArea();
|
||||
self::assertSame('A1:H10', $printArea);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,9 +28,6 @@ class StringHelperTest extends TestCase
|
|||
$this->currencyCode = StringHelper::getCurrencyCode();
|
||||
$this->decimalSeparator = StringHelper::getDecimalSeparator();
|
||||
$this->thousandsSeparator = StringHelper::getThousandsSeparator();
|
||||
|
||||
// Reset Currency Code
|
||||
StringHelper::setCurrencyCode(null);
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class SpreadsheetTest extends TestCase
|
|||
/**
|
||||
* @dataProvider dataProviderForSheetNames
|
||||
*/
|
||||
public function testGetSheetByName($index, $sheetName): void
|
||||
public function testGetSheetByName(int $index, string $sheetName): void
|
||||
{
|
||||
self::assertSame($this->object->getSheet($index), $this->object->getSheetByName($sheetName));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,6 +134,64 @@ class AutoFilterTest extends SetupTeardown
|
|||
}
|
||||
}
|
||||
|
||||
public function testRemoveColumns(): void
|
||||
{
|
||||
$sheet = $this->getSheet();
|
||||
$sheet->fromArray(range('H', 'O'), null, 'H2');
|
||||
$autoFilter = $sheet->getAutoFilter();
|
||||
$autoFilter->setRange(self::INITIAL_RANGE);
|
||||
$autoFilter->getColumn('L')->addRule((new Column\Rule())->setValue(5));
|
||||
|
||||
$sheet->removeColumn('K', 2);
|
||||
$result = $autoFilter->getRange();
|
||||
self::assertEquals('H2:M256', $result);
|
||||
|
||||
// Check that the rule that was set for column L is no longer set
|
||||
self::assertEmpty($autoFilter->getColumn('L')->getRule(0)->getValue());
|
||||
}
|
||||
|
||||
public function testRemoveRows(): void
|
||||
{
|
||||
$sheet = $this->getSheet();
|
||||
$sheet->fromArray(range('H', 'O'), null, 'H2');
|
||||
$autoFilter = $sheet->getAutoFilter();
|
||||
$autoFilter->setRange(self::INITIAL_RANGE);
|
||||
|
||||
$sheet->removeRow(42, 128);
|
||||
$result = $autoFilter->getRange();
|
||||
self::assertEquals('H2:O128', $result);
|
||||
}
|
||||
|
||||
public function testInsertColumns(): void
|
||||
{
|
||||
$sheet = $this->getSheet();
|
||||
$sheet->fromArray(range('H', 'O'), null, 'H2');
|
||||
$autoFilter = $sheet->getAutoFilter();
|
||||
$autoFilter->setRange(self::INITIAL_RANGE);
|
||||
$autoFilter->getColumn('N')->addRule((new Column\Rule())->setValue(5));
|
||||
|
||||
$sheet->insertNewColumnBefore('N', 3);
|
||||
$result = $autoFilter->getRange();
|
||||
self::assertEquals('H2:R256', $result);
|
||||
|
||||
// Check that column N no longer has a rule set
|
||||
self::assertEmpty($autoFilter->getColumn('N')->getRule(0)->getValue());
|
||||
// Check that the rule originally set in column N has been moved to column Q
|
||||
self::assertSame(5, $autoFilter->getColumn('Q')->getRule(0)->getValue());
|
||||
}
|
||||
|
||||
public function testInsertRows(): void
|
||||
{
|
||||
$sheet = $this->getSheet();
|
||||
$sheet->fromArray(range('H', 'O'), null, 'H2');
|
||||
$autoFilter = $sheet->getAutoFilter();
|
||||
$autoFilter->setRange(self::INITIAL_RANGE);
|
||||
|
||||
$sheet->insertNewRowBefore(3, 4);
|
||||
$result = $autoFilter->getRange();
|
||||
self::assertEquals('H2:O260', $result);
|
||||
}
|
||||
|
||||
public function testGetInvalidColumnOffset(): void
|
||||
{
|
||||
$this->expectException(PhpSpreadsheetException::class);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Worksheet;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\HeaderFooterDrawing;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
|
|
@ -41,4 +44,76 @@ class DrawingTest extends TestCase
|
|||
$spreadsheet->disconnectWorksheets();
|
||||
}
|
||||
}
|
||||
|
||||
public function testChangeWorksheet(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet1 = $spreadsheet->getActiveSheet();
|
||||
$sheet2 = $spreadsheet->createSheet();
|
||||
|
||||
$drawing = new Drawing();
|
||||
$drawing->setName('Green Square');
|
||||
$drawing->setPath('tests/data/Writer/XLSX/green_square.gif');
|
||||
self::assertEquals($drawing->getWidth(), 150);
|
||||
self::assertEquals($drawing->getHeight(), 150);
|
||||
$drawing->setCoordinates('A1');
|
||||
$drawing->setOffsetX(30);
|
||||
$drawing->setOffsetY(10);
|
||||
$drawing->setWorksheet($sheet1);
|
||||
|
||||
try {
|
||||
$drawing->setWorksheet($sheet2);
|
||||
self::fail('Should throw exception when attempting set worksheet without specifying override');
|
||||
} catch (PhpSpreadsheetException $e) {
|
||||
self::assertStringContainsString('A Worksheet has already been assigned.', $e->getMessage());
|
||||
}
|
||||
self::assertSame($sheet1, $drawing->getWorksheet());
|
||||
self::assertCount(1, $sheet1->getDrawingCollection());
|
||||
self::assertCount(0, $sheet2->getDrawingCollection());
|
||||
$drawing->setWorksheet($sheet2, true);
|
||||
self::assertSame($sheet2, $drawing->getWorksheet());
|
||||
self::assertCount(0, $sheet1->getDrawingCollection());
|
||||
self::assertCount(1, $sheet2->getDrawingCollection());
|
||||
}
|
||||
|
||||
public function testHeaderFooter(): void
|
||||
{
|
||||
$drawing1 = new HeaderFooterDrawing();
|
||||
$drawing1->setName('Blue Square');
|
||||
$drawing1->setPath('tests/data/Writer/XLSX/blue_square.png');
|
||||
self::assertEquals($drawing1->getWidth(), 100);
|
||||
self::assertEquals($drawing1->getHeight(), 100);
|
||||
$drawing2 = new HeaderFooterDrawing();
|
||||
$drawing2->setName('Blue Square');
|
||||
$drawing2->setPath('tests/data/Writer/XLSX/blue_square.png');
|
||||
self::assertSame($drawing1->getHashCode(), $drawing2->getHashCode());
|
||||
$drawing2->setOffsetX(100);
|
||||
self::assertNotEquals($drawing1->getHashCode(), $drawing2->getHashCode());
|
||||
}
|
||||
|
||||
public function testSetWidthAndHeight(): void
|
||||
{
|
||||
$drawing = new Drawing();
|
||||
$drawing->setName('Blue Square');
|
||||
$drawing->setPath('tests/data/Writer/XLSX/blue_square.png');
|
||||
self::assertSame(100, $drawing->getWidth());
|
||||
self::assertSame(100, $drawing->getHeight());
|
||||
self::assertTrue($drawing->getResizeProportional());
|
||||
$drawing->setResizeProportional(false);
|
||||
$drawing->setWidthAndHeight(150, 200);
|
||||
self::assertSame(150, $drawing->getWidth());
|
||||
self::assertSame(200, $drawing->getHeight());
|
||||
$drawing->setResizeProportional(true);
|
||||
$drawing->setWidthAndHeight(300, 250);
|
||||
// width increase% more than height, so scale width
|
||||
self::assertSame(188, $drawing->getWidth());
|
||||
self::assertSame(250, $drawing->getHeight());
|
||||
$drawing->setResizeProportional(false);
|
||||
$drawing->setWidthAndHeight(150, 200);
|
||||
$drawing->setResizeProportional(true);
|
||||
// height increase% more than width, so scale height
|
||||
$drawing->setWidthAndHeight(175, 350);
|
||||
self::assertSame(175, $drawing->getWidth());
|
||||
self::assertSame(234, $drawing->getHeight());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ class RowCellIterator2Test extends TestCase
|
|||
$sheet->getCell('B2')->setValue('cellb2');
|
||||
$sheet->getCell('F2')->setValue('cellf2');
|
||||
|
||||
$iterator = new RowCellIterator($sheet, '3');
|
||||
$iterator = new RowCellIterator($sheet, 3);
|
||||
if (isset($existing)) {
|
||||
$iterator->setIterateOnlyExistingCells($existing);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ body {
|
|||
|
||||
EOF;
|
||||
|
||||
return preg_replace('~</head>~', "$newstyle</head>", $html);
|
||||
return preg_replace('~</head>~', "$newstyle</head>", $html) ?? '';
|
||||
}
|
||||
|
||||
public function testSetAndReset(): void
|
||||
|
|
@ -46,6 +46,7 @@ EOF;
|
|||
$writer->save($oufil);
|
||||
$html4 = file_get_contents($oufil);
|
||||
unlink($oufil);
|
||||
self::assertNotFalse($html4);
|
||||
self::assertNotFalse(strpos($html4, 'background-color: yellow'));
|
||||
|
||||
$this->writeAndReload($spreadsheet, 'Html');
|
||||
|
|
|
|||
|
|
@ -101,9 +101,12 @@ class GridlinesTest extends Functional\AbstractFunctional
|
|||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$emc2 = new \PhpOffice\PhpSpreadsheet\RichText\RichText();
|
||||
$part1 = $emc2->createTextRun('e=mc');
|
||||
$part1->getFont()->getColor()->setARGB(Color::COLOR_BLUE);
|
||||
$font = $part1->getFont();
|
||||
self::assertNotNull($font);
|
||||
$font->getColor()->setARGB(Color::COLOR_BLUE);
|
||||
$part2 = $emc2->createTextRun('2');
|
||||
$font = $part2->getFont();
|
||||
self::assertNotNull($font);
|
||||
$font->getColor()->setARGB(Color::COLOR_DARKGREEN);
|
||||
$font->setSuperScript(true);
|
||||
$sheet->setCellValue('A1', $emc2);
|
||||
|
|
@ -111,6 +114,7 @@ class GridlinesTest extends Functional\AbstractFunctional
|
|||
$h2o->createTextRun('H');
|
||||
$part2 = $h2o->createTextRun('2');
|
||||
$font = $part2->getFont();
|
||||
self::assertNotNull($font);
|
||||
$font->setSubScript(true);
|
||||
$font->getColor()->setARGB(Color::COLOR_RED);
|
||||
$h2o->createTextRun('O');
|
||||
|
|
@ -119,10 +123,13 @@ class GridlinesTest extends Functional\AbstractFunctional
|
|||
$h2so4->createTextRun('H');
|
||||
$part2 = $h2so4->createTextRun('2');
|
||||
$font = $part2->getFont();
|
||||
self::assertNotNull($font);
|
||||
$font->setSubScript(true);
|
||||
$h2so4->createTextRun('SO');
|
||||
$part4 = $h2so4->createTextRun('4');
|
||||
$part4->getFont()->setSubScript(true);
|
||||
$font = $part4->getFont();
|
||||
self::assertNotNull($font);
|
||||
$font->setSubScript(true);
|
||||
$sheet->setCellValue('A3', $h2so4);
|
||||
$sheet->setCellValue('A4', '5');
|
||||
$sheet->getCell('A4')->getStyle()->getFont()->setSuperScript(true);
|
||||
|
|
|
|||
|
|
@ -25,14 +25,20 @@ class HtmlCommentsTest extends Functional\AbstractFunctional
|
|||
$plainMulti->createText($valueMulti);
|
||||
|
||||
$richSingle = new RichText();
|
||||
$richSingle->createTextRun($valueSingle)->getFont()->setBold(true);
|
||||
$font = $richSingle->createTextRun($valueSingle)->getFont();
|
||||
self::assertNotNull($font);
|
||||
$font->setBold(true);
|
||||
|
||||
$richMultiSimple = new RichText();
|
||||
$richMultiSimple->createTextRun($valueMulti)->getFont()->setBold(true);
|
||||
$font = $richMultiSimple->createTextRun($valueMulti)->getFont();
|
||||
self::assertNotNull($font);
|
||||
$font->setBold(true);
|
||||
|
||||
$richMultiMixed = new RichText();
|
||||
$richMultiMixed->createText('I am' . PHP_EOL);
|
||||
$richMultiMixed->createTextRun('multi-line')->getFont()->setBold(true);
|
||||
$font = $richMultiMixed->createTextRun('multi-line')->getFont();
|
||||
self::assertNotNull($font);
|
||||
$font->setBold(true);
|
||||
$richMultiMixed->createText(PHP_EOL . 'comment!');
|
||||
|
||||
return [
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@ use PhpOffice\PhpSpreadsheet\IOFactory;
|
|||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\File;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing;
|
||||
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
|
||||
|
||||
class DrawingsTest extends AbstractFunctional
|
||||
|
|
@ -28,6 +30,8 @@ class DrawingsTest extends AbstractFunctional
|
|||
|
||||
// Fake assert. The only thing we need is to ensure the file is loaded without exception
|
||||
self::assertNotNull($reloadedSpreadsheet);
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
$reloadedSpreadsheet->disconnectWorksheets();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -59,6 +63,8 @@ class DrawingsTest extends AbstractFunctional
|
|||
|
||||
// Fake assert. The only thing we need is to ensure the file is loaded without exception
|
||||
self::assertNotNull($reloadedSpreadsheet);
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
$reloadedSpreadsheet->disconnectWorksheets();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -96,6 +102,8 @@ class DrawingsTest extends AbstractFunctional
|
|||
unlink($tempFileName);
|
||||
|
||||
self::assertNotNull($reloadedSpreadsheet);
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
$reloadedSpreadsheet->disconnectWorksheets();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -173,7 +181,8 @@ class DrawingsTest extends AbstractFunctional
|
|||
self::assertEquals($comment->getBackgroundImage()->getType(), IMAGETYPE_PNG);
|
||||
|
||||
unlink($tempFileName);
|
||||
self::assertNotNull($reloadedSpreadsheet);
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
$reloadedSpreadsheet->disconnectWorksheets();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -287,6 +296,7 @@ class DrawingsTest extends AbstractFunctional
|
|||
$drawing->setPath('tests/data/Writer/XLSX/orange_square_24_bit.bmp');
|
||||
self::assertEquals($drawing->getWidth(), 70);
|
||||
self::assertEquals($drawing->getHeight(), 70);
|
||||
self::assertSame(IMAGETYPE_PNG, $drawing->getImageTypeForSave());
|
||||
$comment = $sheet->getComment('A6');
|
||||
$comment->setBackgroundImage($drawing);
|
||||
$comment->setSizeAsBackgroundImage();
|
||||
|
|
@ -304,6 +314,8 @@ class DrawingsTest extends AbstractFunctional
|
|||
$drawing = new Drawing();
|
||||
$drawing->setName('Purple Square');
|
||||
$drawing->setPath('tests/data/Writer/XLSX/purple_square.tiff');
|
||||
self::assertStringContainsString('purple_square.tiff', $drawing->getFilename());
|
||||
self::assertFalse($drawing->getIsUrl());
|
||||
$comment = $sheet->getComment('A7');
|
||||
self::assertTrue($comment instanceof Comment);
|
||||
self::assertFalse($comment->hasBackgroundImage());
|
||||
|
|
@ -326,6 +338,14 @@ class DrawingsTest extends AbstractFunctional
|
|||
self::assertEquals($e->getMessage(), 'Unsupported image type in comment background. Supported types: PNG, JPEG, BMP, GIF.');
|
||||
}
|
||||
|
||||
try {
|
||||
$drawing->getMediaFilename();
|
||||
self::fail('Should throw exception when attempting to get media file name for tiff');
|
||||
} catch (PhpSpreadsheetException $e) {
|
||||
self::assertTrue($e instanceof PhpSpreadsheetException);
|
||||
self::assertEquals($e->getMessage(), 'Unsupported image type in comment background. Supported types: PNG, JPEG, BMP, GIF.');
|
||||
}
|
||||
|
||||
try {
|
||||
$drawing->getImageFileExtensionForSave();
|
||||
self::fail('Should throw exception when attempting to get image file extention for tiff');
|
||||
|
|
@ -428,7 +448,8 @@ class DrawingsTest extends AbstractFunctional
|
|||
|
||||
unlink($tempFileName);
|
||||
|
||||
self::assertNotNull($reloadedSpreadsheet);
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
$reloadedSpreadsheet->disconnectWorksheets();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -436,7 +457,6 @@ class DrawingsTest extends AbstractFunctional
|
|||
*/
|
||||
public function testTwoCellAnchorDrawing(): void
|
||||
{
|
||||
$reader = new Xlsx();
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
|
||||
|
|
@ -455,31 +475,133 @@ class DrawingsTest extends AbstractFunctional
|
|||
$drawing->setWorksheet($sheet);
|
||||
|
||||
// Write file
|
||||
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
|
||||
$tempFileName = File::sysGetTempDir() . '/drawings_image_that_two_cell_anchor.xlsx';
|
||||
$writer->save($tempFileName);
|
||||
|
||||
// Read new file
|
||||
$reloadedSpreadsheet = $reader->load($tempFileName);
|
||||
$sheet = $reloadedSpreadsheet->getActiveSheet();
|
||||
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx');
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
$rsheet = $reloadedSpreadsheet->getActiveSheet();
|
||||
|
||||
// Check image coordinates.
|
||||
$drawingCollection = $sheet->getDrawingCollection();
|
||||
$drawingCollection = $rsheet->getDrawingCollection();
|
||||
self::assertCount(1, $drawingCollection);
|
||||
$drawing = $drawingCollection[0];
|
||||
self::assertNotNull($drawing);
|
||||
|
||||
self::assertSame(150, $drawing->getWidth());
|
||||
self::assertSame(150, $drawing->getHeight());
|
||||
self::assertSame('A1', $drawing->getCoordinates());
|
||||
self::assertSame(30, $drawing->getOffsetX());
|
||||
self::assertSame(10, $drawing->getOffsetY());
|
||||
self::assertSame('E8', $drawing->getCoordinates2());
|
||||
self::assertSame(-50, $drawing->getOffsetX2());
|
||||
self::assertSame(-20, $drawing->getOffsetY2());
|
||||
self::assertSame($rsheet, $drawing->getWorksheet());
|
||||
$reloadedSpreadsheet->disconnectWorksheets();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test editAs attribute for two-cell anchors.
|
||||
*
|
||||
* @dataProvider providerEditAs
|
||||
*/
|
||||
public function testTwoCellEditAs(string $editAs, ?string $expectedResult = null): void
|
||||
{
|
||||
if ($expectedResult === null) {
|
||||
$expectedResult = $editAs;
|
||||
}
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
|
||||
// Add gif image that coordinates is two cell anchor.
|
||||
$drawing = new Drawing();
|
||||
$drawing->setName('Green Square');
|
||||
$drawing->setPath('tests/data/Writer/XLSX/green_square.gif');
|
||||
self::assertEquals($drawing->getWidth(), 150);
|
||||
self::assertEquals($drawing->getHeight(), 150);
|
||||
self::assertEquals($drawing->getCoordinates(), 'A1');
|
||||
self::assertEquals($drawing->getOffsetX(), 30);
|
||||
self::assertEquals($drawing->getOffsetY(), 10);
|
||||
self::assertEquals($drawing->getCoordinates2(), 'E8');
|
||||
self::assertEquals($drawing->getOffsetX2(), -50);
|
||||
self::assertEquals($drawing->getOffsetY2(), -20);
|
||||
self::assertEquals($drawing->getWorksheet(), $sheet);
|
||||
$drawing->setCoordinates('A1');
|
||||
$drawing->setOffsetX(30);
|
||||
$drawing->setOffsetY(10);
|
||||
$drawing->setCoordinates2('E8');
|
||||
$drawing->setOffsetX2(-50);
|
||||
$drawing->setOffsetY2(-20);
|
||||
if ($editAs !== '') {
|
||||
$drawing->setEditAs($editAs);
|
||||
}
|
||||
$drawing->setWorksheet($sheet);
|
||||
|
||||
unlink($tempFileName);
|
||||
// Write file
|
||||
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx');
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
$rsheet = $reloadedSpreadsheet->getActiveSheet();
|
||||
|
||||
self::assertNotNull($reloadedSpreadsheet);
|
||||
// Check image coordinates.
|
||||
$drawingCollection = $rsheet->getDrawingCollection();
|
||||
$drawing = $drawingCollection[0];
|
||||
self::assertNotNull($drawing);
|
||||
|
||||
self::assertSame(150, $drawing->getWidth());
|
||||
self::assertSame(150, $drawing->getHeight());
|
||||
self::assertSame('A1', $drawing->getCoordinates());
|
||||
self::assertSame(30, $drawing->getOffsetX());
|
||||
self::assertSame(10, $drawing->getOffsetY());
|
||||
self::assertSame('E8', $drawing->getCoordinates2());
|
||||
self::assertSame(-50, $drawing->getOffsetX2());
|
||||
self::assertSame(-20, $drawing->getOffsetY2());
|
||||
self::assertSame($rsheet, $drawing->getWorksheet());
|
||||
self::assertSame($expectedResult, $drawing->getEditAs());
|
||||
$reloadedSpreadsheet->disconnectWorksheets();
|
||||
}
|
||||
|
||||
public function providerEditAs(): array
|
||||
{
|
||||
return [
|
||||
'absolute' => ['absolute'],
|
||||
'onecell' => ['onecell'],
|
||||
'twocell' => ['twocell'],
|
||||
'unset (will be treated as twocell)' => [''],
|
||||
'unknown (will be treated as twocell)' => ['unknown', ''],
|
||||
];
|
||||
}
|
||||
|
||||
public function testMemoryDrawingDuplicateResource(): void
|
||||
{
|
||||
$gdImage = imagecreatetruecolor(120, 20);
|
||||
$textColor = ($gdImage === false) ? false : imagecolorallocate($gdImage, 255, 255, 255);
|
||||
if ($gdImage === false || $textColor === false) {
|
||||
self::fail('imagecreatetruecolor or imagecolorallocate failed');
|
||||
} else {
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$aSheet = $spreadsheet->getActiveSheet();
|
||||
imagestring($gdImage, 1, 5, 5, 'Created with PhpSpreadsheet', $textColor);
|
||||
$listOfModes = [
|
||||
BaseDrawing::EDIT_AS_TWOCELL,
|
||||
BaseDrawing::EDIT_AS_ABSOLUTE,
|
||||
BaseDrawing::EDIT_AS_ONECELL,
|
||||
];
|
||||
|
||||
foreach ($listOfModes as $i => $mode) {
|
||||
$drawing = new MemoryDrawing();
|
||||
$drawing->setName('In-Memory image ' . $i);
|
||||
$drawing->setDescription('In-Memory image ' . $i);
|
||||
|
||||
$drawing->setCoordinates('A' . ((4 * $i) + 1));
|
||||
$drawing->setCoordinates2('D' . ((4 * $i) + 4));
|
||||
$drawing->setEditAs($mode);
|
||||
|
||||
$drawing->setImageResource($gdImage);
|
||||
$drawing->setRenderingFunction(
|
||||
MemoryDrawing::RENDERING_JPEG
|
||||
);
|
||||
|
||||
$drawing->setMimeType(MemoryDrawing::MIMETYPE_DEFAULT);
|
||||
|
||||
$drawing->setWorksheet($aSheet);
|
||||
}
|
||||
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx');
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
|
||||
foreach ($reloadedSpreadsheet->getActiveSheet()->getDrawingCollection() as $index => $pDrawing) {
|
||||
self::assertEquals($listOfModes[$index], $pDrawing->getEditAs(), 'functional test drawing twoCellAnchor');
|
||||
}
|
||||
$reloadedSpreadsheet->disconnectWorksheets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,14 +78,18 @@ class UnparsedDataCloneTest extends TestCase
|
|||
$spreadsheet1 = $reader1->load($resultFilename1);
|
||||
unlink($resultFilename1);
|
||||
$sheet1c = $spreadsheet1->getSheetByName('Clone');
|
||||
self::assertNotNull($sheet1c);
|
||||
$sheet1o = $spreadsheet1->getSheetByName('Original');
|
||||
self::assertNotNull($sheet1o);
|
||||
|
||||
$writer->save($resultFilename2);
|
||||
$reader2 = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
|
||||
$spreadsheet2 = $reader2->load($resultFilename2);
|
||||
unlink($resultFilename2);
|
||||
$sheet2c = $spreadsheet2->getSheetByName('Clone');
|
||||
self::assertNotNull($sheet2c);
|
||||
$sheet2o = $spreadsheet2->getSheetByName('Original');
|
||||
self::assertNotNull($sheet2o);
|
||||
|
||||
self::assertEquals($spreadsheet1->getSheetCount(), $spreadsheet2->getSheetCount());
|
||||
self::assertCount(1, $sheet1c->getDrawingCollection());
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ class UnparsedDataTest extends TestCase
|
|||
self::assertNotEmpty($resultVbaProjectRaw, 'vbaProject.bin not found!');
|
||||
|
||||
// xl/workbook.xml
|
||||
$xmlWorkbook = simplexml_load_string($resultWorkbookRaw, 'SimpleXMLElement', Settings::getLibXmlLoaderOptions());
|
||||
$xmlWorkbook = simplexml_load_string($resultWorkbookRaw ?: '', 'SimpleXMLElement', Settings::getLibXmlLoaderOptions());
|
||||
self::assertNotFalse($xmlWorkbook);
|
||||
if (!$xmlWorkbook->workbookProtection) {
|
||||
self::fail('workbook.xml/workbookProtection not found!');
|
||||
|
|
@ -86,7 +86,8 @@ class UnparsedDataTest extends TestCase
|
|||
|
||||
// xl/worksheets/sheet1.xml
|
||||
self::assertStringContainsString('<mc:AlternateContent', $resultSheet1Raw, 'AlternateContent at sheet1.xml not found!');
|
||||
$xmlWorksheet = simplexml_load_string($resultSheet1Raw, 'SimpleXMLElement', Settings::getLibXmlLoaderOptions());
|
||||
$xmlWorksheet = simplexml_load_string($resultSheet1Raw ?: '', 'SimpleXMLElement', Settings::getLibXmlLoaderOptions());
|
||||
self::assertNotFalse($xmlWorksheet);
|
||||
$pageSetupAttributes = $xmlWorksheet->pageSetup->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships');
|
||||
self::assertTrue(isset($pageSetupAttributes->id), 'sheet1.xml/pageSetup[r:id] not found!');
|
||||
if (!$xmlWorksheet->sheetProtection) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
|
||||
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
|
||||
|
||||
class WmfTest extends AbstractFunctional
|
||||
|
|
@ -19,6 +20,7 @@ class WmfTest extends AbstractFunctional
|
|||
$drawings = $spreadsheet->getActiveSheet()->getDrawingCollection();
|
||||
self::assertCount(1, $drawings);
|
||||
$drawing = $drawings[0];
|
||||
self::assertInstanceOf(Drawing::class, $drawing);
|
||||
self::assertSame('wmf', $drawing->getExtension());
|
||||
|
||||
// Save spreadsheet to file and read it back
|
||||
|
|
@ -26,6 +28,7 @@ class WmfTest extends AbstractFunctional
|
|||
$drawings = $reloadedSpreadsheet->getActiveSheet()->getDrawingCollection();
|
||||
self::assertCount(1, $drawings);
|
||||
$drawing = $drawings[0];
|
||||
self::assertInstanceOf(Drawing::class, $drawing);
|
||||
self::assertSame('wmf', $drawing->getExtension());
|
||||
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
|
|
|
|||
|
|
@ -53,4 +53,12 @@ return [
|
|||
7,
|
||||
'#N/A',
|
||||
],
|
||||
[
|
||||
9,
|
||||
'#SPILL!',
|
||||
],
|
||||
[
|
||||
14,
|
||||
'#CALC!',
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -49,6 +49,14 @@ return [
|
|||
true,
|
||||
'#N/A',
|
||||
],
|
||||
[
|
||||
true,
|
||||
'#SPILL!',
|
||||
],
|
||||
[
|
||||
true,
|
||||
'#CALC!',
|
||||
],
|
||||
[
|
||||
false,
|
||||
'TRUE',
|
||||
|
|
|
|||
|
|
@ -34,4 +34,8 @@ return [
|
|||
'supply a1 argument as int' => [900, 'A2:A4', 1],
|
||||
'supply a1 argument as float' => [900, 'A2:A4', 7.3],
|
||||
'supply a1 argument as string not permitted' => ['#VALUE!', 'A2:A4', '1'],
|
||||
'row range' => [600, '1:3'],
|
||||
'column range' => [1500, 'A:C'],
|
||||
'row range on different sheet' => [66, 'OtherSheet!1:3'],
|
||||
'column range on different sheet' => [165, 'OtherSheet!A:C'],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -24,6 +24,13 @@ return [
|
|||
2,
|
||||
false,
|
||||
],
|
||||
[
|
||||
'#REF!',
|
||||
1,
|
||||
'HELLO WORLD',
|
||||
2,
|
||||
false,
|
||||
],
|
||||
[
|
||||
100,
|
||||
1,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ return [
|
|||
],
|
||||
],
|
||||
[
|
||||
'incomplete', // 10,
|
||||
10, // fixed by PR #2561
|
||||
[
|
||||
['"text with quotes"'],
|
||||
[2],
|
||||
|
|
|
|||
|
|
@ -22,6 +22,34 @@ return [
|
|||
'2020',
|
||||
'=SUM(A1:C3)',
|
||||
],
|
||||
'column range' => [
|
||||
'=SUM(B:C)',
|
||||
2,
|
||||
0,
|
||||
'2020',
|
||||
'=SUM(D:E)',
|
||||
],
|
||||
'column range with absolute' => [
|
||||
'=SUM($B:C)',
|
||||
2,
|
||||
0,
|
||||
'2020',
|
||||
'=SUM($B:E)',
|
||||
],
|
||||
'row range' => [
|
||||
'=SUM(2:3)',
|
||||
0,
|
||||
2,
|
||||
'2020',
|
||||
'=SUM(4:5)',
|
||||
],
|
||||
'row range with absolute' => [
|
||||
'=SUM($2:3)',
|
||||
0,
|
||||
2,
|
||||
'2020',
|
||||
'=SUM($2:5)',
|
||||
],
|
||||
[
|
||||
'=SUM(2020!C3:E5,2019!C3:E5)',
|
||||
-2,
|
||||
|
|
|
|||
Loading…
Reference in New Issue