Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
declare(strict_types=1);
4
 
5
namespace OpenSpout\Reader\XLSX\Helper;
6
 
7
use OpenSpout\Common\Exception\InvalidArgumentException;
8
 
9
/**
10
 * @internal
11
 */
12
final class CellHelper
13
{
14
    // Using ord() is super slow... Using a pre-computed hash table instead.
15
    private const columnLetterToIndexMapping = [
16
        'A' => 0, 'B' => 1, 'C' => 2, 'D' => 3, 'E' => 4, 'F' => 5, 'G' => 6,
17
        'H' => 7, 'I' => 8, 'J' => 9, 'K' => 10, 'L' => 11, 'M' => 12, 'N' => 13,
18
        'O' => 14, 'P' => 15, 'Q' => 16, 'R' => 17, 'S' => 18, 'T' => 19, 'U' => 20,
19
        'V' => 21, 'W' => 22, 'X' => 23, 'Y' => 24, 'Z' => 25,
20
    ];
21
 
22
    /**
23
     * Returns the base 10 column index associated to the cell index (base 26).
24
     * Excel uses A to Z letters for column indexing, where A is the 1st column,
25
     * Z is the 26th and AA is the 27th.
26
     * The mapping is zero based, so that A1 maps to 0, B2 maps to 1, Z13 to 25 and AA4 to 26.
27
     *
28
     * @param string $cellIndex The Excel cell index ('A1', 'BC13', ...)
29
     *
30
     * @throws InvalidArgumentException When the given cell index is invalid
31
     */
32
    public static function getColumnIndexFromCellIndex(string $cellIndex): int
33
    {
34
        if (!self::isValidCellIndex($cellIndex)) {
35
            throw new InvalidArgumentException('Cannot get column index from an invalid cell index.');
36
        }
37
 
38
        $columnIndex = 0;
39
 
40
        // Remove row information
41
        $columnLetters = preg_replace('/\d/', '', $cellIndex);
42
 
43
        // strlen() is super slow too... Using isset() is way faster and not too unreadable,
44
        // since we checked before that there are between 1 and 3 letters.
45
        $columnLength = isset($columnLetters[1]) ? (isset($columnLetters[2]) ? 3 : 2) : 1;
46
 
47
        // Looping over the different letters of the column is slower than this method.
48
        // Also, not using the pow() function because it's slooooow...
49
        switch ($columnLength) {
50
            case 1:
51
                $columnIndex = self::columnLetterToIndexMapping[$columnLetters];
52
 
53
                break;
54
 
55
            case 2:
56
                $firstLetterIndex = (self::columnLetterToIndexMapping[$columnLetters[0]] + 1) * 26;
57
                $secondLetterIndex = self::columnLetterToIndexMapping[$columnLetters[1]];
58
                $columnIndex = $firstLetterIndex + $secondLetterIndex;
59
 
60
                break;
61
 
62
            case 3:
63
                $firstLetterIndex = (self::columnLetterToIndexMapping[$columnLetters[0]] + 1) * 676;
64
                $secondLetterIndex = (self::columnLetterToIndexMapping[$columnLetters[1]] + 1) * 26;
65
                $thirdLetterIndex = self::columnLetterToIndexMapping[$columnLetters[2]];
66
                $columnIndex = $firstLetterIndex + $secondLetterIndex + $thirdLetterIndex;
67
 
68
                break;
69
        }
70
 
71
        return $columnIndex;
72
    }
73
 
74
    /**
75
     * Returns whether a cell index is valid, in an Excel world.
76
     * To be valid, the cell index should start with capital letters and be followed by numbers.
77
     * There can only be 3 letters, as there can only be 16,384 rows, which is equivalent to 'XFE'.
78
     *
79
     * @param string $cellIndex The Excel cell index ('A1', 'BC13', ...)
80
     */
81
    private static function isValidCellIndex(string $cellIndex): bool
82
    {
83
        return 1 === preg_match('/^[A-Z]{1,3}\d+$/', $cellIndex);
84
    }
85
}