Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
namespace PhpOffice\PhpSpreadsheet\Writer;
4
 
5
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
6
use PhpOffice\PhpSpreadsheet\Spreadsheet;
7
 
8
class Csv extends BaseWriter
9
{
10
    /**
11
     * PhpSpreadsheet object.
12
     *
13
     * @var Spreadsheet
14
     */
15
    private $spreadsheet;
16
 
17
    /**
18
     * Delimiter.
19
     *
20
     * @var string
21
     */
22
    private $delimiter = ',';
23
 
24
    /**
25
     * Enclosure.
26
     *
27
     * @var string
28
     */
29
    private $enclosure = '"';
30
 
31
    /**
32
     * Line ending.
33
     *
34
     * @var string
35
     */
36
    private $lineEnding = PHP_EOL;
37
 
38
    /**
39
     * Sheet index to write.
40
     *
41
     * @var int
42
     */
43
    private $sheetIndex = 0;
44
 
45
    /**
46
     * Whether to write a UTF8 BOM.
47
     *
48
     * @var bool
49
     */
50
    private $useBOM = false;
51
 
52
    /**
53
     * Whether to write a Separator line as the first line of the file
54
     *     sep=x.
55
     *
56
     * @var bool
57
     */
58
    private $includeSeparatorLine = false;
59
 
60
    /**
61
     * Whether to write a fully Excel compatible CSV file.
62
     *
63
     * @var bool
64
     */
65
    private $excelCompatibility = false;
66
 
67
    /**
68
     * Output encoding.
69
     *
70
     * @var string
71
     */
72
    private $outputEncoding = '';
73
 
74
    /**
75
     * Create a new CSV.
76
     */
77
    public function __construct(Spreadsheet $spreadsheet)
78
    {
79
        $this->spreadsheet = $spreadsheet;
80
    }
81
 
82
    /**
83
     * Save PhpSpreadsheet to file.
84
     *
85
     * @param resource|string $filename
86
     */
87
    public function save($filename, int $flags = 0): void
88
    {
89
        $this->processFlags($flags);
90
 
91
        // Fetch sheet
92
        $sheet = $this->spreadsheet->getSheet($this->sheetIndex);
93
 
94
        $saveDebugLog = Calculation::getInstance($this->spreadsheet)->getDebugLog()->getWriteDebugLog();
95
        Calculation::getInstance($this->spreadsheet)->getDebugLog()->setWriteDebugLog(false);
96
        $saveArrayReturnType = Calculation::getArrayReturnType();
97
        Calculation::setArrayReturnType(Calculation::RETURN_ARRAY_AS_VALUE);
98
 
99
        // Open file
100
        $this->openFileHandle($filename);
101
 
102
        if ($this->excelCompatibility) {
103
            $this->setUseBOM(true); //  Enforce UTF-8 BOM Header
104
            $this->setIncludeSeparatorLine(true); //  Set separator line
105
            $this->setEnclosure('"'); //  Set enclosure to "
106
            $this->setDelimiter(';'); //  Set delimiter to a semi-colon
107
            $this->setLineEnding("\r\n");
108
        }
109
 
110
        if ($this->useBOM) {
111
            // Write the UTF-8 BOM code if required
112
            fwrite($this->fileHandle, "\xEF\xBB\xBF");
113
        }
114
 
115
        if ($this->includeSeparatorLine) {
116
            // Write the separator line if required
117
            fwrite($this->fileHandle, 'sep=' . $this->getDelimiter() . $this->lineEnding);
118
        }
119
 
120
        //    Identify the range that we need to extract from the worksheet
121
        $maxCol = $sheet->getHighestDataColumn();
122
        $maxRow = $sheet->getHighestDataRow();
123
 
124
        // Write rows to file
125
        for ($row = 1; $row <= $maxRow; ++$row) {
126
            // Convert the row to an array...
127
            $cellsArray = $sheet->rangeToArray('A' . $row . ':' . $maxCol . $row, '', $this->preCalculateFormulas);
128
            // ... and write to the file
129
            $this->writeLine($this->fileHandle, $cellsArray[0]);
130
        }
131
 
132
        $this->maybeCloseFileHandle();
133
        Calculation::setArrayReturnType($saveArrayReturnType);
134
        Calculation::getInstance($this->spreadsheet)->getDebugLog()->setWriteDebugLog($saveDebugLog);
135
    }
136
 
137
    public function getDelimiter(): string
138
    {
139
        return $this->delimiter;
140
    }
141
 
142
    public function setDelimiter(string $delimiter): self
143
    {
144
        $this->delimiter = $delimiter;
145
 
146
        return $this;
147
    }
148
 
149
    public function getEnclosure(): string
150
    {
151
        return $this->enclosure;
152
    }
153
 
154
    public function setEnclosure(string $enclosure = '"'): self
155
    {
156
        $this->enclosure = $enclosure;
157
 
158
        return $this;
159
    }
160
 
161
    public function getLineEnding(): string
162
    {
163
        return $this->lineEnding;
164
    }
165
 
166
    public function setLineEnding(string $lineEnding): self
167
    {
168
        $this->lineEnding = $lineEnding;
169
 
170
        return $this;
171
    }
172
 
173
    /**
174
     * Get whether BOM should be used.
175
     */
176
    public function getUseBOM(): bool
177
    {
178
        return $this->useBOM;
179
    }
180
 
181
    /**
182
     * Set whether BOM should be used, typically when non-ASCII characters are used.
183
     */
184
    public function setUseBOM(bool $useBOM): self
185
    {
186
        $this->useBOM = $useBOM;
187
 
188
        return $this;
189
    }
190
 
191
    /**
192
     * Get whether a separator line should be included.
193
     */
194
    public function getIncludeSeparatorLine(): bool
195
    {
196
        return $this->includeSeparatorLine;
197
    }
198
 
199
    /**
200
     * Set whether a separator line should be included as the first line of the file.
201
     */
202
    public function setIncludeSeparatorLine(bool $includeSeparatorLine): self
203
    {
204
        $this->includeSeparatorLine = $includeSeparatorLine;
205
 
206
        return $this;
207
    }
208
 
209
    /**
210
     * Get whether the file should be saved with full Excel Compatibility.
211
     */
212
    public function getExcelCompatibility(): bool
213
    {
214
        return $this->excelCompatibility;
215
    }
216
 
217
    /**
218
     * Set whether the file should be saved with full Excel Compatibility.
219
     *
220
     * @param bool $excelCompatibility Set the file to be written as a fully Excel compatible csv file
221
     *                                Note that this overrides other settings such as useBOM, enclosure and delimiter
222
     */
223
    public function setExcelCompatibility(bool $excelCompatibility): self
224
    {
225
        $this->excelCompatibility = $excelCompatibility;
226
 
227
        return $this;
228
    }
229
 
230
    public function getSheetIndex(): int
231
    {
232
        return $this->sheetIndex;
233
    }
234
 
235
    public function setSheetIndex(int $sheetIndex): self
236
    {
237
        $this->sheetIndex = $sheetIndex;
238
 
239
        return $this;
240
    }
241
 
242
    public function getOutputEncoding(): string
243
    {
244
        return $this->outputEncoding;
245
    }
246
 
247
    public function setOutputEncoding(string $outputEnconding): self
248
    {
249
        $this->outputEncoding = $outputEnconding;
250
 
251
        return $this;
252
    }
253
 
254
    /** @var bool */
255
    private $enclosureRequired = true;
256
 
257
    public function setEnclosureRequired(bool $value): self
258
    {
259
        $this->enclosureRequired = $value;
260
 
261
        return $this;
262
    }
263
 
264
    public function getEnclosureRequired(): bool
265
    {
266
        return $this->enclosureRequired;
267
    }
268
 
269
    /**
270
     * Convert boolean to TRUE/FALSE; otherwise return element cast to string.
271
     *
272
     * @param mixed $element
273
     */
274
    private static function elementToString($element): string
275
    {
276
        if (is_bool($element)) {
277
            return $element ? 'TRUE' : 'FALSE';
278
        }
279
 
280
        return (string) $element;
281
    }
282
 
283
    /**
284
     * Write line to CSV file.
285
     *
286
     * @param resource $fileHandle PHP filehandle
287
     * @param array $values Array containing values in a row
288
     */
289
    private function writeLine($fileHandle, array $values): void
290
    {
291
        // No leading delimiter
292
        $delimiter = '';
293
 
294
        // Build the line
295
        $line = '';
296
 
297
        foreach ($values as $element) {
298
            $element = self::elementToString($element);
299
            // Add delimiter
300
            $line .= $delimiter;
301
            $delimiter = $this->delimiter;
302
            // Escape enclosures
303
            $enclosure = $this->enclosure;
304
            if ($enclosure) {
305
                // If enclosure is not required, use enclosure only if
306
                // element contains newline, delimiter, or enclosure.
307
                if (!$this->enclosureRequired && strpbrk($element, "$delimiter$enclosure\n") === false) {
308
                    $enclosure = '';
309
                } else {
310
                    $element = str_replace($enclosure, $enclosure . $enclosure, $element);
311
                }
312
            }
313
            // Add enclosed string
314
            $line .= $enclosure . $element . $enclosure;
315
        }
316
 
317
        // Add line ending
318
        $line .= $this->lineEnding;
319
 
320
        // Write to file
321
        if ($this->outputEncoding != '') {
322
            $line = mb_convert_encoding($line, $this->outputEncoding);
323
        }
324
        fwrite($fileHandle, /** @scrutinizer ignore-type */ $line);
325
    }
326
}