Passed
Pull Request — master (#4447)
by Owen
15:42
created

ListFunctions::listWorksheetNames2()   B

Complexity

Conditions 6
Paths 9

Size

Total Lines 40
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 20
dl 0
loc 40
ccs 18
cts 18
cp 1
rs 8.9777
c 0
b 0
f 0
cc 6
nc 9
nop 2
crap 6
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Reader\Xls;
4
5
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
6
use PhpOffice\PhpSpreadsheet\Reader\Xls;
7
use PhpOffice\PhpSpreadsheet\Shared\File;
8
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
9
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
10
11
class ListFunctions extends Xls
12
{
13
    /**
14
     * Reads names of the worksheets from a file, without parsing the whole file to a PhpSpreadsheet object.
15 6
     *
16
     * @return string[]
17 6
     */
18
    protected function listWorksheetNames2(string $filename, Xls $xls): array
19 6
    {
20
        File::assertFile($filename);
21
22 6
        $worksheetNames = [];
23
24
        // Read the OLE file
25 6
        $xls->loadOLE($filename);
26
27 6
        // total byte size of Excel data (workbook global substream + sheet substreams)
28 6
        $xls->dataSize = strlen($xls->data);
29
30
        $xls->pos = 0;
31 6
        $xls->sheets = [];
32 6
33
        // Parse Workbook Global Substream
34
        while ($xls->pos < $xls->dataSize) {
35 6
            $code = self::getUInt2d($xls->data, $xls->pos);
36 6
37 6
            match ($code) {
38 6
                self::XLS_TYPE_BOF => $xls->readBof(),
39 6
                self::XLS_TYPE_SHEET => $xls->readSheet(),
40
                self::XLS_TYPE_EOF => $xls->readDefault(),
41
                self::XLS_TYPE_CODEPAGE => $xls->readCodepage(),
42 6
                default => $xls->readDefault(),
43 6
            };
44
45
            if ($code === self::XLS_TYPE_EOF) {
46
                break;
47 6
            }
48 6
        }
49
50 6
        foreach ($xls->sheets as $sheet) {
51
            if ($sheet['sheetType'] === 0x00 && is_string($sheet['name'])) {
52
                // 0x00: Worksheet, 0x02: Chart, 0x06: Visual Basic module
53
                $worksheetNames[] = $sheet['name'];
54 6
            }
55
        }
56
57
        return $worksheetNames;
58
    }
59
60 5
    /**
61
     * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns).
62 5
     *
63
     * @return array<int, array{worksheetName: string, lastColumnLetter: string, lastColumnIndex: int, totalRows: int, totalColumns: int, sheetState: string}>
64 5
     */
65
    protected function listWorksheetInfo2(string $filename, Xls $xls): array
66
    {
67 5
        File::assertFile($filename);
68
69
        $worksheetInfo = [];
70 5
71
        // Read the OLE file
72
        $xls->loadOLE($filename);
73 5
74 5
        // total byte size of Excel data (workbook global substream + sheet substreams)
75
        $xls->dataSize = strlen($xls->data);
76
77 5
        // initialize
78 5
        $xls->pos = 0;
79
        $xls->sheets = [];
80
81 5
        // Parse Workbook Global Substream
82 5
        while ($xls->pos < $xls->dataSize) {
83 5
            $code = self::getUInt2d($xls->data, $xls->pos);
84 5
85 5
            match ($code) {
86
                self::XLS_TYPE_BOF => $xls->readBof(),
87
                self::XLS_TYPE_SHEET => $xls->readSheet(),
88 5
                self::XLS_TYPE_EOF => $xls->readDefault(),
89 5
                self::XLS_TYPE_CODEPAGE => $xls->readCodepage(),
90
                default => $xls->readDefault(),
91
            };
92
93
            if ($code === self::XLS_TYPE_EOF) {
94 5
                break;
95 5
            }
96
        }
97
98
        // Parse the individual sheets
99
        foreach ($xls->sheets as $sheet) {
100
            if ($sheet['sheetType'] !== 0x00) {
101
                // 0x00: Worksheet
102 5
                // 0x02: Chart
103 5
                // 0x06: Visual Basic module
104 5
                continue;
105 5
            }
106 5
107 5
            $tmpInfo = [];
108 5
            $tmpInfo['worksheetName'] = StringHelper::convertToString($sheet['name']);
109
            $tmpInfo['lastColumnLetter'] = 'A';
110 5
            $tmpInfo['lastColumnIndex'] = 0;
111
            $tmpInfo['totalRows'] = 0;
112 5
            $tmpInfo['totalColumns'] = 0;
113 5
            $tmpInfo['sheetState'] = StringHelper::convertToString($sheet['sheetState']);
114
115
            $xls->pos = $sheet['offset'];
116 5
117 5
            while ($xls->pos <= $xls->dataSize - 4) {
118 5
                $code = self::getUInt2d($xls->data, $xls->pos);
119 5
120 5
                switch ($code) {
121 5
                    case self::XLS_TYPE_RK:
122 5
                    case self::XLS_TYPE_LABELSST:
123 5
                    case self::XLS_TYPE_NUMBER:
124
                    case self::XLS_TYPE_FORMULA:
125
                    case self::XLS_TYPE_BOOLERR:
126 5
                    case self::XLS_TYPE_LABEL:
127
                        $length = self::getUInt2d($xls->data, $xls->pos + 2);
128 5
                        $recordData = $xls->readRecordData($xls->data, $xls->pos + 4, $length);
129 5
130
                        // move stream pointer to next record
131 5
                        $xls->pos += 4 + $length;
132 5
133
                        $rowIndex = self::getUInt2d($recordData, 0) + 1;
134 5
                        $columnIndex = self::getUInt2d($recordData, 2);
135 5
136 5
                        $tmpInfo['totalRows'] = max($tmpInfo['totalRows'], $rowIndex);
137
                        $tmpInfo['lastColumnIndex'] = max($tmpInfo['lastColumnIndex'], $columnIndex);
138 5
139 5
                        break;
140 5
                    case self::XLS_TYPE_BOF:
141
                        $xls->readBof();
142 5
143
                        break;
144 5
                    case self::XLS_TYPE_EOF:
145
                        $xls->readDefault();
146 5
147
                        break 2;
148
                    default:
149
                        $xls->readDefault();
150 5
151 5
                        break;
152
                }
153 5
            }
154
155
            $tmpInfo['lastColumnLetter'] = Coordinate::stringFromColumnIndex($tmpInfo['lastColumnIndex'] + 1);
156 5
            $tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1;
157
158
            $worksheetInfo[] = $tmpInfo;
159
        }
160
161
        return $worksheetInfo;
162
    }
163
}
164