16    public const A1_COORDINATE_REGEX = 
'/^(?<absolute_col>\$?)(?<col_ref>[A-Z]{1,3})(?<absolute_row>\$?)(?<row_ref>\d{1,7})$/i';
 
   34        if (preg_match(self::A1_COORDINATE_REGEX, $pCoordinateString, $matches)) {
 
   35            return [$matches[
'absolute_col'] . $matches[
'col_ref'], $matches[
'absolute_row'] . $matches[
'row_ref']];
 
   36        } elseif (self::coordinateIsRange($pCoordinateString)) {
 
   37            throw new Exception(
'Cell coordinate string can not be a range of cells');
 
   38        } elseif ($pCoordinateString == 
'') {
 
   39            throw new Exception(
'Cell coordinate can not be zero-length string');
 
   42        throw new Exception(
'Invalid cell coordinate ' . $pCoordinateString);
 
   58            (int) ltrim(
$row, 
'$'),
 
   71        return (strpos($coord, 
':') !== 
false) || (strpos($coord, 
',') !== 
false);
 
   84        if (self::coordinateIsRange($pCoordinateString)) {
 
   85            throw new Exception(
'Cell coordinate string can not be a range of cells');
 
   89        [$worksheet, $pCoordinateString] = Worksheet::extractSheetTitle($pCoordinateString, 
true);
 
   90        if ($worksheet > 
'') {
 
   95        if (ctype_digit($pCoordinateString)) {
 
   96            return $worksheet . 
'$' . $pCoordinateString;
 
   97        } elseif (ctype_alpha($pCoordinateString)) {
 
   98            return $worksheet . 
'$' . strtoupper($pCoordinateString);
 
  113        if (self::coordinateIsRange($pCoordinateString)) {
 
  114            throw new Exception(
'Cell coordinate string can not be a range of cells');
 
  118        [$worksheet, $pCoordinateString] = Worksheet::extractSheetTitle($pCoordinateString, 
true);
 
  119        if ($worksheet > 
'') {
 
  125        $column = ltrim($column, 
'$');
 
  128        return $worksheet . 
'$' . $column . 
'$' . 
$row;
 
  143        if (empty($pRange)) {
 
  147        $exploded = explode(
',', $pRange);
 
  148        $counter = count($exploded);
 
  149        for (
$i = 0; 
$i < $counter; ++
$i) {
 
  150            $exploded[
$i] = explode(
':', $exploded[
$i]);
 
  166        if (empty($pRange) || !is_array($pRange[0])) {
 
  167            throw new Exception(
'Range does not contain any information');
 
  171        $counter = count($pRange);
 
  172        for (
$i = 0; 
$i < $counter; ++
$i) {
 
  173            $pRange[
$i] = implode(
':', $pRange[
$i]);
 
  176        return implode(
',', $pRange);
 
  190        if (empty($pRange)) {
 
  195        $pRange = strtoupper($pRange);
 
  198        if (strpos($pRange, 
':') === 
false) {
 
  199            $rangeA = $rangeB = $pRange;
 
  201            [$rangeA, $rangeB] = explode(
':', $pRange);
 
  212        return [$rangeStart, $rangeEnd];
 
  227        return [($rangeEnd[0] - $rangeStart[0] + 1), ($rangeEnd[1] - $rangeStart[1] + 1)];
 
  241        if (empty($pRange)) {
 
  246        $pRange = strtoupper($pRange);
 
  249        if (strpos($pRange, 
':') === 
false) {
 
  250            $rangeA = $rangeB = $pRange;
 
  252            [$rangeA, $rangeB] = explode(
':', $pRange);
 
  270        static $indexCache = [];
 
  272        if (isset($indexCache[$pString])) {
 
  273            return $indexCache[$pString];
 
  278        static $columnLookup = [
 
  279            'A' => 1, 
'B' => 2, 
'C' => 3, 
'D' => 4, 
'E' => 5, 
'F' => 6, 
'G' => 7, 
'H' => 8, 
'I' => 9, 
'J' => 10, 
'K' => 11, 
'L' => 12, 
'M' => 13,
 
  280            'N' => 14, 
'O' => 15, 
'P' => 16, 
'Q' => 17, 
'R' => 18, 
'S' => 19, 
'T' => 20, 
'U' => 21, 
'V' => 22, 
'W' => 23, 
'X' => 24, 
'Y' => 25, 
'Z' => 26,
 
  281            'a' => 1, 
'b' => 2, 
'c' => 3, 
'd' => 4, 
'e' => 5, 
'f' => 6, 
'g' => 7, 
'h' => 8, 
'i' => 9, 
'j' => 10, 
'k' => 11, 
'l' => 12, 
'm' => 13,
 
  282            'n' => 14, 
'o' => 15, 
'p' => 16, 
'q' => 17, 
'r' => 18, 
's' => 19, 
't' => 20, 
'u' => 21, 
'v' => 22, 
'w' => 23, 
'x' => 24, 
'y' => 25, 
'z' => 26,
 
  287        if (isset($pString[0])) {
 
  288            if (!isset($pString[1])) {
 
  289                $indexCache[$pString] = $columnLookup[$pString];
 
  291                return $indexCache[$pString];
 
  292            } elseif (!isset($pString[2])) {
 
  293                $indexCache[$pString] = $columnLookup[$pString[0]] * 26 + $columnLookup[$pString[1]];
 
  295                return $indexCache[$pString];
 
  296            } elseif (!isset($pString[3])) {
 
  297                $indexCache[$pString] = $columnLookup[$pString[0]] * 676 + $columnLookup[$pString[1]] * 26 + $columnLookup[$pString[2]];
 
  299                return $indexCache[$pString];
 
  303        throw new Exception(
'Column string index can not be ' . ((isset($pString[0])) ? 
'longer than 3 characters' : 
'empty'));
 
  315        static $indexCache = [];
 
  317        if (!isset($indexCache[$columnIndex])) {
 
  318            $indexValue = $columnIndex;
 
  321                $characterValue = ($indexValue % 26) ?: 26;
 
  322                $indexValue = ($indexValue - $characterValue) / 26;
 
  323                $base26 = chr($characterValue + 64) . ($base26 ?: 
'');
 
  324            } 
while ($indexValue > 0);
 
  325            $indexCache[$columnIndex] = $base26;
 
  328        return $indexCache[$columnIndex];
 
  343        foreach ($ranges as $range) {
 
  353        $cellList = array_merge(...$cells);
 
  361        $operatorCount = count($operators);
 
  362        for ($offset = 0; $offset < $operatorCount; ++$offset) {
 
  363            $operator = $operators[$offset];
 
  364            if ($operator !== 
' ') {
 
  368            $cells[$offset] = array_intersect($cells[$offset], $cells[$offset + 1]);
 
  369            unset($operators[$offset], $cells[$offset + 1]);
 
  370            $operators = array_values($operators);
 
  371            $cells = array_values($cells);
 
  383        foreach ($cellList as $coord) {
 
  384            [$column, 
$row] = sscanf($coord, 
'%[A-Z]%d');
 
  385            $sortKeys[sprintf(
'%3s%09d', $column, 
$row)] = $coord;
 
  389        return array_values($sortKeys);
 
  404        if (!self::coordinateIsRange($cellBlock)) {
 
  405            return (array) $cellBlock;
 
  410        foreach ($ranges as $range) {
 
  412            if (!isset($range[1])) {
 
  413                $returnValue[] = $range[0];
 
  419            [$rangeStart, $rangeEnd] = $range;
 
  427            $currentColumnIndex = $startColumnIndex;
 
  428            $currentRow = $startRow;
 
  433            while ($currentColumnIndex < $endColumnIndex) {
 
  434                while ($currentRow <= $endRow) {
 
  438                ++$currentColumnIndex;
 
  439                $currentRow = $startRow;
 
  466        $mergedCoordCollection = [];
 
  468        foreach ($pCoordCollection as $coord => $value) {
 
  469            if (self::coordinateIsRange($coord)) {
 
  470                $mergedCoordCollection[$coord] = $value;
 
  477            $hashCode = $column . 
'-' . (is_object($value) ? $value->getHashCode() : $value);
 
  479            if (!isset($hashedValues[$hashCode])) {
 
  480                $hashedValues[$hashCode] = (object) [
 
  486                $hashedValues[$hashCode]->rows[] = 
$row;
 
  490        ksort($hashedValues);
 
  492        foreach ($hashedValues as $hashedValue) {
 
  493            sort($hashedValue->rows);
 
  498            foreach ($hashedValue->rows as 
$row) {
 
  499                if ($rowStart === 
null) {
 
  502                } elseif ($rowEnd === 
$row - 1) {
 
  505                    if ($rowStart == $rowEnd) {
 
  506                        $ranges[] = $hashedValue->col . $rowStart;
 
  508                        $ranges[] = $hashedValue->col . $rowStart . 
':' . $hashedValue->col . $rowEnd;
 
  516            if ($rowStart !== 
null) {
 
  517                if ($rowStart == $rowEnd) {
 
  518                    $ranges[] = $hashedValue->col . $rowStart;
 
  520                    $ranges[] = $hashedValue->col . $rowStart . 
':' . $hashedValue->col . $rowEnd;
 
  524            foreach ($ranges as $range) {
 
  525                $mergedCoordCollection[$range] = $hashedValue->value;
 
  529        return $mergedCoordCollection;
 
  542        $rangeString = str_replace(
'$', 
'', strtoupper($rangeString));
 
  547        $split = array_chunk($tokens, 2);
 
  548        $ranges = array_column($split, 0);
 
  549        $operators = array_column($split, 1);
 
  551        return [$ranges, $operators];
 
  564    private static function validateRange($cellBlock, $startColumnIndex, $endColumnIndex, $currentRow, $endRow): void
 
  566        if ($startColumnIndex >= $endColumnIndex || $currentRow > $endRow) {
 
  567            throw new Exception(
'Invalid range: "' . $cellBlock . 
'"');
 
An exception for terminatinating execution or to throw for unit testing.
Helper class to manipulate cell coordinates.
static absoluteCoordinate($pCoordinateString)
Make string coordinate absolute.
const A1_COORDINATE_REGEX
static getCellBlocksFromRangeString($rangeString)
Get the individual cell blocks from a range string, removing any $ characters.
static sortCellReferenceArray(array $cellList)
static getRangeBoundaries($pRange)
Calculate range boundaries.
static coordinateFromString($pCoordinateString)
Coordinate from string.
static coordinateIsRange($coord)
Checks if a coordinate represents a range of cells.
static processRangeSetOperators(array $operators, array $cells)
static indexesFromString(string $coordinates)
Get indexes from a string coordinates.
static columnIndexFromString($pString)
Column index from string.
static mergeRangesInCollection(array $pCoordCollection)
Convert an associative array of single cell coordinates to values to an associative array of cell ran...
static stringFromColumnIndex($columnIndex)
String from column index.
static validateRange($cellBlock, $startColumnIndex, $endColumnIndex, $currentRow, $endRow)
Check that the given range is valid, i.e.
static splitRange($pRange)
Split range into coordinate strings.
static buildRange(array $pRange)
Build range from coordinate strings.
static rangeDimension($pRange)
Calculate range dimension.
static getReferencesForCellBlock($cellBlock)
Get all cell references for an individual cell block.
static rangeBoundaries($pRange)
Calculate range boundaries.
static extractAllCellReferencesInRange($cellRange)
Extract all cell references in range, which may be comprised of multiple cell ranges.
static absoluteReference($pCoordinateString)
Make string row, column or cell coordinate absolute.
echo;exit;}function LogoutNotification($SessionID){ global $ilDB;$q="SELECT session_id, data FROM usr_session WHERE expires > (\w+)\|/" PREG_SPLIT_NO_EMPTY PREG_SPLIT_DELIM_CAPTURE