CellReferenceHelper.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. <?php
  2. namespace PhpOffice\PhpSpreadsheet;
  3. use PhpOffice\PhpSpreadsheet\Cell\AddressRange;
  4. use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
  5. class CellReferenceHelper
  6. {
  7. protected string $beforeCellAddress;
  8. protected int $beforeColumn;
  9. protected int $beforeRow;
  10. protected int $numberOfColumns;
  11. protected int $numberOfRows;
  12. public function __construct(string $beforeCellAddress = 'A1', int $numberOfColumns = 0, int $numberOfRows = 0)
  13. {
  14. $this->beforeCellAddress = str_replace('$', '', $beforeCellAddress);
  15. $this->numberOfColumns = $numberOfColumns;
  16. $this->numberOfRows = $numberOfRows;
  17. // Get coordinate of $beforeCellAddress
  18. [$beforeColumn, $beforeRow] = Coordinate::coordinateFromString($beforeCellAddress);
  19. $this->beforeColumn = Coordinate::columnIndexFromString($beforeColumn);
  20. $this->beforeRow = (int) $beforeRow;
  21. }
  22. public function beforeCellAddress(): string
  23. {
  24. return $this->beforeCellAddress;
  25. }
  26. public function refreshRequired(string $beforeCellAddress, int $numberOfColumns, int $numberOfRows): bool
  27. {
  28. return $this->beforeCellAddress !== $beforeCellAddress
  29. || $this->numberOfColumns !== $numberOfColumns
  30. || $this->numberOfRows !== $numberOfRows;
  31. }
  32. public function updateCellReference(string $cellReference = 'A1', bool $includeAbsoluteReferences = false, bool $onlyAbsoluteReferences = false): string
  33. {
  34. if (Coordinate::coordinateIsRange($cellReference)) {
  35. throw new Exception('Only single cell references may be passed to this method.');
  36. }
  37. // Get coordinate of $cellReference
  38. [$newColumn, $newRow] = Coordinate::coordinateFromString($cellReference);
  39. $newColumnIndex = Coordinate::columnIndexFromString(str_replace('$', '', $newColumn));
  40. $newRowIndex = (int) str_replace('$', '', $newRow);
  41. $absoluteColumn = $newColumn[0] === '$' ? '$' : '';
  42. $absoluteRow = $newRow[0] === '$' ? '$' : '';
  43. // Verify which parts should be updated
  44. if ($onlyAbsoluteReferences === true) {
  45. $updateColumn = (($absoluteColumn === '$') && $newColumnIndex >= $this->beforeColumn);
  46. $updateRow = (($absoluteRow === '$') && $newRowIndex >= $this->beforeRow);
  47. } elseif ($includeAbsoluteReferences === false) {
  48. $updateColumn = (($absoluteColumn !== '$') && $newColumnIndex >= $this->beforeColumn);
  49. $updateRow = (($absoluteRow !== '$') && $newRowIndex >= $this->beforeRow);
  50. } else {
  51. $updateColumn = ($newColumnIndex >= $this->beforeColumn);
  52. $updateRow = ($newRowIndex >= $this->beforeRow);
  53. }
  54. // Create new column reference
  55. if ($updateColumn) {
  56. $newColumn = $this->updateColumnReference($newColumnIndex, $absoluteColumn);
  57. }
  58. // Create new row reference
  59. if ($updateRow) {
  60. $newRow = $this->updateRowReference($newRowIndex, $absoluteRow);
  61. }
  62. // Return new reference
  63. return "{$newColumn}{$newRow}";
  64. }
  65. public function cellAddressInDeleteRange(string $cellAddress): bool
  66. {
  67. [$cellColumn, $cellRow] = Coordinate::coordinateFromString($cellAddress);
  68. $cellColumnIndex = Coordinate::columnIndexFromString($cellColumn);
  69. // Is cell within the range of rows/columns if we're deleting
  70. if (
  71. $this->numberOfRows < 0
  72. && ($cellRow >= ($this->beforeRow + $this->numberOfRows))
  73. && ($cellRow < $this->beforeRow)
  74. ) {
  75. return true;
  76. } elseif (
  77. $this->numberOfColumns < 0
  78. && ($cellColumnIndex >= ($this->beforeColumn + $this->numberOfColumns))
  79. && ($cellColumnIndex < $this->beforeColumn)
  80. ) {
  81. return true;
  82. }
  83. return false;
  84. }
  85. protected function updateColumnReference(int $newColumnIndex, string $absoluteColumn): string
  86. {
  87. $newColumn = Coordinate::stringFromColumnIndex(min($newColumnIndex + $this->numberOfColumns, AddressRange::MAX_COLUMN_INT));
  88. return "{$absoluteColumn}{$newColumn}";
  89. }
  90. protected function updateRowReference(int $newRowIndex, string $absoluteRow): string
  91. {
  92. $newRow = $newRowIndex + $this->numberOfRows;
  93. $newRow = ($newRow > AddressRange::MAX_ROW) ? AddressRange::MAX_ROW : $newRow;
  94. return "{$absoluteRow}{$newRow}";
  95. }
  96. }