CellReferenceHelper.php 4.3 KB

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