PluginProbe
TablePress – Tables in WordPress made easy / 3.4
TablePress – Tables in WordPress made easy v3.4
3.4 3.3.4 3.3.3 3.3.2 3.3.1 trunk 1.12 1.14 1.9.2 2.0.4 2.1.7 2.1.8 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3 2.3.1 2.3.2 2.4 2.4.1 2.4.2 2.4.3 All 45 releases
← All changes | libraries/vendor/PhpSpreadsheet/Worksheet/Worksheet.php +248 -14 3.3.1 → 3.4 View file →
@@ -31,8 +31,12 @@
31 31 use TablePress\PhpOffice\PhpSpreadsheet\Style\Conditional;
32 32 use TablePress\PhpOffice\PhpSpreadsheet\Style\NumberFormat;
33 33 use TablePress\PhpOffice\PhpSpreadsheet\Style\Protection as StyleProtection;
34 34 use TablePress\PhpOffice\PhpSpreadsheet\Style\Style;
35 +use TablePress\PhpOffice\PhpSpreadsheet\Worksheet\PivotTable\PivotTable;
36 +use TablePress\PhpOffice\PhpSpreadsheet\Worksheet\Sparkline\Sparkline;
37 +use TablePress\PhpOffice\PhpSpreadsheet\Worksheet\Sparkline\SparklineGroup;
38 +use TablePress\PhpOffice\PhpSpreadsheet\Worksheet\Sparkline\SparklineType;
35 39
36 40 class Worksheet
37 41 {
38 42 // Break types
@@ -129,8 +133,22 @@
129 133 */
130 134 private ArrayObject $tableCollection;
131 135
132 136 /**
137 + * Collection of SparklineGroup objects.
138 + *
139 + * @var ArrayObject<int, SparklineGroup>
140 + */
141 + private ArrayObject $sparklineGroupCollection;
142 +
143 + /**
144 + * Collection of PivotTable objects.
145 + *
146 + * @var ArrayObject<int, PivotTable>
147 + */
148 + private ArrayObject $pivotTableCollection;
149 +
150 + /**
133 151 * Worksheet title.
134 152 */
135 153 private string $title = '';
136 154
@@ -324,9 +342,11 @@
324 342 public function __construct(?Spreadsheet $parent = null, string $title = 'Worksheet')
325 343 {
326 344 // Set parent and title
327 345 $this->parent = $parent;
328 - $this->setTitle($title, false);
346 + // Chart collection must be set before title
347 + $this->chartCollection = new ArrayObject();
348 + $this->setTitle($title, false, true, false);
329 349 // setTitle can change $pTitle
330 350 $this->setCodeName($this->getTitle());
331 351 $this->setSheetState(self::SHEETSTATE_VISIBLE);
332 352
@@ -342,10 +362,8 @@
342 362 // Drawing collection
343 363 $this->drawingCollection = new ArrayObject();
344 364 // In Cell Drawing collection
345 365 $this->inCellDrawingCollection = new ArrayObject();
346 - // Chart collection
347 - $this->chartCollection = new ArrayObject();
348 366 // Protection
349 367 $this->protection = new Protection();
350 368 // Default row dimension
351 369 $this->defaultRowDimension = new RowDimension(null);
@@ -354,17 +372,24 @@
354 372 // AutoFilter
355 373 $this->autoFilter = new AutoFilter('', $this);
356 374 // Table collection
357 375 $this->tableCollection = new ArrayObject();
376 + // Sparkline group collection
377 + $this->sparklineGroupCollection = new ArrayObject();
378 +
379 + // Pivot table collection
380 + $this->pivotTableCollection = new ArrayObject();
358 381 }
359 382
360 383 /**
361 384 * Disconnect all cells from this Worksheet object,
362 385 * typically so that the worksheet object can be unset.
386 + * The worksheet will be in an unusable state after
387 + * this method has completed.
363 388 */
364 389 public function disconnectCells(): void
365 390 {
366 - if (isset($this->cellCollection)) { //* @phpstan-ignore-line
391 + if (isset($this->cellCollection)) { //* @phpstan-ignore isset.initializedProperty (may be null at destruct time)
367 392 $this->cellCollection->unsetWorksheetCells();
368 393 unset($this->cellCollection);
369 394 }
370 395 // detach ourself from the workbook, so that it can then delete this worksheet successfully
@@ -378,9 +403,9 @@
378 403 {
379 404 ($nullsafeVariable1 = Calculation::getInstanceOrNull($this->parent)) ? $nullsafeVariable1->clearCalculationCacheForWorksheet($this->title) : null;
380 405
381 406 $this->disconnectCells();
382 - unset($this->rowDimensions, $this->columnDimensions, $this->tableCollection, $this->drawingCollection, $this->inCellDrawingCollection, $this->chartCollection, $this->autoFilter);
407 + unset($this->rowDimensions, $this->columnDimensions, $this->tableCollection, $this->sparklineGroupCollection, $this->drawingCollection, $this->inCellDrawingCollection, $this->chartCollection, $this->autoFilter, $this->pivotTableCollection);
383 408 }
384 409
385 410 /**
386 411 * Return the cell collection.
@@ -460,9 +485,9 @@
460 485 * @return string[]
461 486 */
462 487 public function getCoordinates(bool $sorted = true): array
463 488 {
464 - if (!isset($this->cellCollection)) { //* @phpstan-ignore-line
489 + if (!isset($this->cellCollection)) { //* @phpstan-ignore isset.initializedProperty (may be null at destruct time)
465 490 return [];
466 491 }
467 492
468 493 if ($sorted) {
@@ -567,16 +592,16 @@
567 592
568 593 /**
569 594 * Get a chart by its index position.
570 595 *
571 - * @param ?string $index Chart index position
596 + * @param null|int|string $index Chart index position
572 597 *
573 598 * @return Chart|false
574 599 */
575 - public function getChartByIndex(?string $index)
600 + public function getChartByIndex($index)
576 601 {
577 602 $chartCount = count($this->chartCollection);
578 - if ($chartCount == 0) {
603 + if ($chartCount === 0 || (is_string($index) && $index !== (string) (int) $index)) {
579 604 return false;
580 605 }
581 606 if ($index === null) {
582 607 $index = --$chartCount;
@@ -794,9 +819,11 @@
794 819 }
795 820 $this->activePane = $holdActivePane;
796 821 }
797 822 if ($activeSheet !== null && $activeSheet >= 0) {
798 - ($nullsafeVariable3 = $this->getParent()) ? $nullsafeVariable3->setActiveSheetIndex($activeSheet) : null;
823 + // Okay, I get it now - if $activeSheet is not null,
824 + // then $this->getParent() must also be non-null.
825 + $this->getParent()->setActiveSheetIndex($activeSheet);
799 826 }
800 827 $this->setSelectedCells($selectedCells);
801 828
802 829 return $this;
@@ -872,9 +899,9 @@
872 899 * at parse time (by Readers), where titles can be assumed to be valid.
873 900 *
874 901 * @return $this
875 902 */
876 - public function setTitle(string $title, bool $updateFormulaCellReferences = true, bool $validate = true)
903 + public function setTitle(string $title, bool $updateFormulaCellReferences = true, bool $validate = true, bool $changeChartSheetNames = true)
877 904 {
878 905 // Is this a 'rename' or not?
879 906 if ($this->getTitle() == $title) {
880 907 return $this;
@@ -925,12 +952,63 @@
925 952 if ($updateFormulaCellReferences) {
926 953 ReferenceHelper::getInstance()->updateNamedFormulae($this->parent, $oldTitle, $newTitle);
927 954 }
928 955 }
956 + if ($changeChartSheetNames) {
957 + $this->changeChartSheetNames($oldTitle, $title);
958 + }
929 959
930 960 return $this;
931 961 }
932 962
963 + private function changeChartSheetNames(string $oldTitle, string $title): void
964 + {
965 + $worksheets = [$this];
966 + if ($this->parent !== null) {
967 + $sheets = $this->parent->getAllSheets();
968 + if (in_array($this, $sheets, true)) {
969 + $worksheets = $sheets;
970 + }
971 + }
972 + $titleq = "'$title'!";
973 + $oldTitleq1 = preg_quote("'$oldTitle'!");
974 + $oldTitleq2 = preg_quote("$oldTitle!");
975 + $preg1 = "/$oldTitleq1|\\b$oldTitleq2/";
976 + foreach ($worksheets as $sheet) {
977 + foreach ($sheet->getChartCollection() as $chart) {
978 + foreach (((($nullsafeVariable3 = $chart->getPlotArea()) ? $nullsafeVariable3->getPlotGroup() : null) ?? []) as $plotGroup) {
979 + foreach ($plotGroup->getPlotCategories() as $plotCategory) {
980 + $dataSource = (string) $plotCategory->getDataSource();
981 + $dataSource2 = Preg::replace($preg1, $titleq, $dataSource);
982 + if ($dataSource2 !== $dataSource) {
983 + $plotCategory->setDataSource(
984 + $dataSource2
985 + );
986 + }
987 + }
988 + foreach ($plotGroup->getPlotLabels() as $plotLabel) {
989 + $dataSource = (string) $plotLabel->getDataSource();
990 + $dataSource2 = Preg::replace($preg1, $titleq, $dataSource);
991 + if ($dataSource2 !== $dataSource) {
992 + $plotLabel->setDataSource(
993 + $dataSource2
994 + );
995 + }
996 + }
997 + foreach ($plotGroup->getPlotValues() as $plotValue) {
998 + $dataSource = (string) $plotValue->getDataSource();
999 + $dataSource2 = Preg::replace($preg1, $titleq, $dataSource);
1000 + if ($dataSource2 !== $dataSource) {
1001 + $plotValue->setDataSource(
1002 + $dataSource2
1003 + );
1004 + }
1005 + }
1006 + }
1007 + }
1008 + }
1009 + }
1010 +
933 1011 /**
934 1012 * Get sheet state.
935 1013 *
936 1014 * @return string Sheet state (visible, hidden, veryHidden)
@@ -1231,10 +1309,9 @@
1231 1309 if ($sheet === null) {
1232 1310 throw new Exception('Sheet not found for named range: ' . $namedRange->getName());
1233 1311 }
1234 1312
1235 - /** @phpstan-ignore-next-line */
1236 - $cellCoordinate = ltrim((string) substr($namedRange->getValue(), strrpos($namedRange->getValue(), '!')), '!');
1313 + $cellCoordinate = ltrim((string) substr($namedRange->getValue(), (int) strrpos($namedRange->getValue(), '!')), '!');
1237 1314 $finalCoordinate = str_replace('$', '', $cellCoordinate);
1238 1315 }
1239 1316 }
1240 1317
@@ -1676,9 +1753,9 @@
1676 1753 */
1677 1754 public function duplicateConditionalStyle(array $styles, string $range = '')
1678 1755 {
1679 1756 foreach ($styles as $cellStyle) {
1680 - if (!($cellStyle instanceof Conditional)) { // @phpstan-ignore-line
1757 + if (!($cellStyle instanceof Conditional)) {
1681 1758 throw new Exception('Style is not a conditional style');
1682 1759 }
1683 1760 }
1684 1761
@@ -2165,8 +2242,136 @@
2165 2242 return $this;
2166 2243 }
2167 2244
2168 2245 /**
2246 + * Get collection of SparklineGroups.
2247 + *
2248 + * @return ArrayObject<int, SparklineGroup>
2249 + */
2250 + public function getSparklineGroupCollection(): ArrayObject
2251 + {
2252 + return $this->sparklineGroupCollection;
2253 + }
2254 +
2255 + /**
2256 + * Add a SparklineGroup.
2257 + *
2258 + * @return $this
2259 + */
2260 + public function addSparklineGroup(SparklineGroup $sparklineGroup): self
2261 + {
2262 + $this->sparklineGroupCollection[] = $sparklineGroup;
2263 +
2264 + return $this;
2265 + }
2266 +
2267 + /**
2268 + * Add a single Sparkline, wrapping it in its own SparklineGroup.
2269 + *
2270 + * This is a convenience method for the common case of adding one sparkline
2271 + * with default formatting; the created group is returned so its formatting
2272 + * can be adjusted.
2273 + *
2274 + * @param mixed $type the type of sparkline (defaults to line)
2275 + * @param \TablePress\PhpOffice\PhpSpreadsheet\Worksheet\Sparkline\SparklineType::* $type
2276 + */
2277 + public function addSparkline(Sparkline $sparkline, $type = SparklineType::Line): SparklineGroup
2278 + {
2279 + $group = new SparklineGroup();
2280 + $group->setType($type);
2281 + $group->addSparkline($sparkline);
2282 + $this->addSparklineGroup($group);
2283 +
2284 + return $group;
2285 + }
2286 +
2287 + /**
2288 + * Remove all SparklineGroups.
2289 + *
2290 + * @return $this
2291 + */
2292 + public function removeSparklineGroupCollection(): self
2293 + {
2294 + $this->sparklineGroupCollection = new ArrayObject();
2295 +
2296 + return $this;
2297 + }
2298 +
2299 + /**
2300 + * Get collection of PivotTables.
2301 + *
2302 + * @return ArrayObject<int, PivotTable>
2303 + */
2304 + public function getPivotTableCollection(): ArrayObject
2305 + {
2306 + return $this->pivotTableCollection;
2307 + }
2308 +
2309 + /**
2310 + * Get collection of PivotTables (alias of getPivotTableCollection()).
2311 + *
2312 + * @return ArrayObject<int, PivotTable>
2313 + */
2314 + public function getPivotTables(): ArrayObject
2315 + {
2316 + return $this->pivotTableCollection;
2317 + }
2318 +
2319 + /**
2320 + * Add a PivotTable to this worksheet.
2321 + *
2322 + * @return $this
2323 + */
2324 + public function addPivotTable(PivotTable $pivotTable): self
2325 + {
2326 + $pivotTable->setWorksheet($this);
2327 + $this->pivotTableCollection[] = $pivotTable;
2328 +
2329 + return $this;
2330 + }
2331 +
2332 + /**
2333 + * @return string[] array of PivotTable names
2334 + */
2335 + public function getPivotTableNames(): array
2336 + {
2337 + $pivotTableNames = [];
2338 +
2339 + foreach ($this->pivotTableCollection as $pivotTable) {
2340 + $pivotTableNames[] = $pivotTable->getName();
2341 + }
2342 +
2343 + return $pivotTableNames;
2344 + }
2345 +
2346 + /**
2347 + * @param string $name the pivot table name to search
2348 + *
2349 + * @return null|PivotTable The pivot table from the collection, or null if not found
2350 + */
2351 + public function getPivotTableByName(string $name): ?PivotTable
2352 + {
2353 + $name = StringHelper::strToUpper($name);
2354 + foreach ($this->pivotTableCollection as $pivotTable) {
2355 + if (StringHelper::strToUpper($pivotTable->getName()) === $name) {
2356 + return $pivotTable;
2357 + }
2358 + }
2359 +
2360 + return null;
2361 + }
2362 +
2363 + /**
2364 + * Remove collection of PivotTables.
2365 + */
2366 + public function removePivotTableCollection(): self
2367 + {
2368 + $this->pivotTableCollection = new ArrayObject();
2369 +
2370 + return $this;
2371 + }
2372 +
2373 + /**
2169 2374 * Get Freeze Pane.
2170 2375 */
2171 2376 public function getFreezePane(): ?string
2172 2377 {
@@ -2436,8 +2641,20 @@
2436 2641 {
2437 2642 if ($row < 1) {
2438 2643 throw new Exception('Rows to be deleted should at least start from row 1.');
2439 2644 }
2645 + if ($numberOfRows === 0) {
2646 + return $this;
2647 + }
2648 + if ($numberOfRows < 0) {
2649 + $newRow = max(1, $row + $numberOfRows + 1);
2650 + $numberOfRows = $row - $newRow + 1;
2651 + $row = $newRow;
2652 + }
2653 + $newHighestRow = $this->cachedHighestRow;
2654 + if ($newHighestRow >= $row) {
2655 + $newHighestRow = max($row - 1, $this->cachedHighestRow - $numberOfRows);
2656 + }
2440 2657 $startRow = $row;
2441 2658 $endRow = $startRow + $numberOfRows - 1;
2442 2659 $removeKeys = [];
2443 2660 $addKeys = [];
@@ -2492,8 +2709,9 @@
2492 2709 --$highestRow;
2493 2710 }
2494 2711
2495 2712 $this->rowDimensions = $holdRowDimensions;
2713 + $this->cachedHighestRow = $newHighestRow;
2496 2714
2497 2715 return $this;
2498 2716 }
2499 2717
@@ -2530,8 +2748,21 @@
2530 2748 if (is_numeric($column)) {
2531 2749 throw new Exception('Column references should not be numeric.');
2532 2750 }
2533 2751 $startColumnInt = Coordinate::columnIndexFromString($column);
2752 + if ($numberOfColumns === 0) {
2753 + return $this;
2754 + }
2755 + if ($numberOfColumns < 0) {
2756 + $newStartColumnInt = max(1, $startColumnInt + $numberOfColumns + 1);
2757 + $numberOfColumns = $startColumnInt - $newStartColumnInt + 1;
2758 + $startColumnInt = $newStartColumnInt;
2759 + $column = Coordinate::stringFromColumnIndex($startColumnInt);
2760 + }
2761 + $newHighestColumn = $this->cachedHighestColumn;
2762 + if ($newHighestColumn >= $startColumnInt) {
2763 + $newHighestColumn = max($startColumnInt - 1, $this->cachedHighestColumn - $numberOfColumns);
2764 + }
2534 2765 $endColumnInt = $startColumnInt + $numberOfColumns - 1;
2535 2766 $removeKeys = [];
2536 2767 $addKeys = [];
2537 2768 foreach ($this->mergeCells as $key => $value) {
@@ -2580,8 +2811,10 @@
2580 2811
2581 2812 $this->columnDimensions = $holdColumnDimensions;
2582 2813
2583 2814 if ($pColumnIndex > $highestColumnIndex) {
2815 + $this->cachedHighestColumn = $newHighestColumn;
2816 +
2584 2817 return $this;
2585 2818 }
2586 2819
2587 2820 $maxPossibleColumnsToBeRemoved = $highestColumnIndex - $pColumnIndex + 1;
@@ -2589,8 +2822,9 @@
2589 2822 for ($c = 0, $n = min($maxPossibleColumnsToBeRemoved, $numberOfColumns); $c < $n; ++$c) {
2590 2823 $this->cellCollection->removeColumn($highestColumn);
2591 2824 $highestColumn = Coordinate::stringFromColumnIndex(Coordinate::columnIndexFromString($highestColumn) - 1);
2592 2825 }
2826 + $this->cachedHighestColumn = $newHighestColumn;
2593 2827
2594 2828 $this->garbageCollect();
2595 2829
2596 2830 return $this;