ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
AddressHelper.php
Go to the documentation of this file.
1 <?php
2 
4 
6 
8 {
9  public const R1C1_COORDINATE_REGEX = '/(R((?:\[-?\d*\])|(?:\d*))?)(C((?:\[-?\d*\])|(?:\d*))?)/i';
10 
14  public static function convertToA1(
15  string $address,
16  int $currentRowNumber = 1,
17  int $currentColumnNumber = 1
18  ): string {
19  $validityCheck = preg_match('/^(R(\[?-?\d*\]?))(C(\[?-?\d*\]?))$/i', $address, $cellReference);
20 
21  if ($validityCheck === 0) {
22  throw new Exception('Invalid R1C1-format Cell Reference');
23  }
24 
25  $rowReference = $cellReference[2];
26  // Empty R reference is the current row
27  if ($rowReference === '') {
28  $rowReference = (string) $currentRowNumber;
29  }
30  // Bracketed R references are relative to the current row
31  if ($rowReference[0] === '[') {
32  $rowReference = $currentRowNumber + (int) trim($rowReference, '[]');
33  }
34  $columnReference = $cellReference[4];
35  // Empty C reference is the current column
36  if ($columnReference === '') {
37  $columnReference = (string) $currentColumnNumber;
38  }
39  // Bracketed C references are relative to the current column
40  if (is_string($columnReference) && $columnReference[0] === '[') {
41  $columnReference = $currentColumnNumber + (int) trim($columnReference, '[]');
42  }
43 
44  if ($columnReference <= 0 || $rowReference <= 0) {
45  throw new Exception('Invalid R1C1-format Cell Reference, Value out of range');
46  }
47  $A1CellReference = Coordinate::stringFromColumnIndex($columnReference) . $rowReference;
48 
49  return $A1CellReference;
50  }
51 
52  protected static function convertSpreadsheetMLFormula(string $formula): string
53  {
54  $formula = substr($formula, 3);
55  $temp = explode('"', $formula);
56  $key = false;
57  foreach ($temp as &$value) {
58  // Only replace in alternate array entries (i.e. non-quoted blocks)
59  if ($key = !$key) {
60  $value = str_replace(['[.', ':.', ']'], ['', ':', ''], $value);
61  }
62  }
63  unset($value);
64 
65  return implode('"', $temp);
66  }
67 
71  public static function convertFormulaToA1(
72  string $formula,
73  int $currentRowNumber = 1,
74  int $currentColumnNumber = 1
75  ): string {
76  if (substr($formula, 0, 3) == 'of:') {
77  // We have an old-style SpreadsheetML Formula
78  return self::convertSpreadsheetMLFormula($formula);
79  }
80 
81  // Convert R1C1 style references to A1 style references (but only when not quoted)
82  $temp = explode('"', $formula);
83  $key = false;
84  foreach ($temp as &$value) {
85  // Only replace in alternate array entries (i.e. non-quoted blocks)
86  if ($key = !$key) {
87  preg_match_all(self::R1C1_COORDINATE_REGEX, $value, $cellReferences, PREG_SET_ORDER + PREG_OFFSET_CAPTURE);
88  // Reverse the matches array, otherwise all our offsets will become incorrect if we modify our way
89  // through the formula from left to right. Reversing means that we work right to left.through
90  // the formula
91  $cellReferences = array_reverse($cellReferences);
92  // Loop through each R1C1 style reference in turn, converting it to its A1 style equivalent,
93  // then modify the formula to use that new reference
94  foreach ($cellReferences as $cellReference) {
95  $A1CellReference = self::convertToA1($cellReference[0][0], $currentRowNumber, $currentColumnNumber);
96  $value = substr_replace($value, $A1CellReference, $cellReference[0][1], strlen($cellReference[0][0]));
97  }
98  }
99  }
100  unset($value);
101 
102  // Then rebuild the formula string
103  return implode('"', $temp);
104  }
105 
110  public static function convertToR1C1(
111  string $address,
112  ?int $currentRowNumber = null,
113  ?int $currentColumnNumber = null
114  ): string {
115  $validityCheck = preg_match(Coordinate::A1_COORDINATE_REGEX, $address, $cellReference);
116 
117  if ($validityCheck === 0) {
118  throw new Exception('Invalid A1-format Cell Reference');
119  }
120 
121  $columnId = Coordinate::columnIndexFromString($cellReference['col_ref']);
122  if ($cellReference['absolute_col'] === '$') {
123  // Column must be absolute address
124  $currentColumnNumber = null;
125  }
126 
127  $rowId = (int) $cellReference['row_ref'];
128  if ($cellReference['absolute_row'] === '$') {
129  // Row must be absolute address
130  $currentRowNumber = null;
131  }
132 
133  if ($currentRowNumber !== null) {
134  if ($rowId === $currentRowNumber) {
135  $rowId = '';
136  } else {
137  $rowId = '[' . ($rowId - $currentRowNumber) . ']';
138  }
139  }
140 
141  if ($currentColumnNumber !== null) {
142  if ($columnId === $currentColumnNumber) {
143  $columnId = '';
144  } else {
145  $columnId = '[' . ($columnId - $currentColumnNumber) . ']';
146  }
147  }
148 
149  $R1C1Address = "R{$rowId}C{$columnId}";
150 
151  return $R1C1Address;
152  }
153 }
static convertFormulaToA1(string $formula, int $currentRowNumber=1, int $currentColumnNumber=1)
Converts a formula that uses R1C1/SpreadsheetXML format cell address to an A1 format cell address...
static convertToR1C1(string $address, ?int $currentRowNumber=null, ?int $currentColumnNumber=null)
Converts an A1 format cell address to an R1C1 format cell address.
static convertToA1(string $address, int $currentRowNumber=1, int $currentColumnNumber=1)
Converts an R1C1 format cell address to an A1 format cell address.
static convertSpreadsheetMLFormula(string $formula)
static columnIndexFromString($pString)
Column index from string.
Definition: Coordinate.php:265
$key
Definition: croninfo.php:18
static stringFromColumnIndex($columnIndex)
String from column index.
Definition: Coordinate.php:313