Completed
Push — develop ( 148bee...a089a8 )
by Adrien
32:42
created

Worksheet::writeMergeCells()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 3
nop 2
dl 0
loc 15
ccs 8
cts 8
cp 1
crap 3
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
4
5
use PhpOffice\PhpSpreadsheet\Cell\Cell;
6
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
7
use PhpOffice\PhpSpreadsheet\RichText\RichText;
8
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
9
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
10
use PhpOffice\PhpSpreadsheet\Style\Conditional;
11
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column;
12
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule;
13
use PhpOffice\PhpSpreadsheet\Worksheet\SheetView;
14
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet as PhpspreadsheetWorksheet;
15
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
16
17
/**
18
 * @category   PhpSpreadsheet
19
 *
20
 * @copyright  Copyright (c) 2006 - 2015 PhpSpreadsheet (https://github.com/PHPOffice/PhpSpreadsheet)
21
 */
22
class Worksheet extends WriterPart
23
{
24
    /**
25
     * Write worksheet to XML format.
26
     *
27
     * @param PhpspreadsheetWorksheet $pSheet
28
     * @param string[] $pStringTable
29
     * @param bool $includeCharts Flag indicating if we should write charts
30
     *
31
     * @throws WriterException
32
     *
33
     * @return string XML Output
34
     */
35 73
    public function writeWorksheet(PhpspreadsheetWorksheet $pSheet, $pStringTable = null, $includeCharts = false)
36
    {
37
        // Create XML writer
38 73
        $objWriter = null;
39 73
        if ($this->getParentWriter()->getUseDiskCaching()) {
40
            $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
41
        } else {
42 73
            $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
43
        }
44
45
        // XML header
46 73
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
47
48
        // Worksheet
49 73
        $objWriter->startElement('worksheet');
50 73
        $objWriter->writeAttribute('xml:space', 'preserve');
51 73
        $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main');
52 73
        $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
53
54
        // sheetPr
55 73
        $this->writeSheetPr($objWriter, $pSheet);
56
57
        // Dimension
58 73
        $this->writeDimension($objWriter, $pSheet);
59
60
        // sheetViews
61 73
        $this->writeSheetViews($objWriter, $pSheet);
62
63
        // sheetFormatPr
64 73
        $this->writeSheetFormatPr($objWriter, $pSheet);
65
66
        // cols
67 73
        $this->writeCols($objWriter, $pSheet);
68
69
        // sheetData
70 73
        $this->writeSheetData($objWriter, $pSheet, $pStringTable);
1 ignored issue
show
Bug introduced by
It seems like $pStringTable can also be of type null; however, parameter $pStringTable of PhpOffice\PhpSpreadsheet...sheet::writeSheetData() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

70
        $this->writeSheetData($objWriter, $pSheet, /** @scrutinizer ignore-type */ $pStringTable);
Loading history...
71
72
        // sheetProtection
73 73
        $this->writeSheetProtection($objWriter, $pSheet);
74
75
        // protectedRanges
76 73
        $this->writeProtectedRanges($objWriter, $pSheet);
77
78
        // autoFilter
79 73
        $this->writeAutoFilter($objWriter, $pSheet);
80
81
        // mergeCells
82 73
        $this->writeMergeCells($objWriter, $pSheet);
83
84
        // conditionalFormatting
85 73
        $this->writeConditionalFormatting($objWriter, $pSheet);
86
87
        // dataValidations
88 73
        $this->writeDataValidations($objWriter, $pSheet);
89
90
        // hyperlinks
91 73
        $this->writeHyperlinks($objWriter, $pSheet);
92
93
        // Print options
94 73
        $this->writePrintOptions($objWriter, $pSheet);
95
96
        // Page margins
97 73
        $this->writePageMargins($objWriter, $pSheet);
98
99
        // Page setup
100 73
        $this->writePageSetup($objWriter, $pSheet);
101
102
        // Header / footer
103 73
        $this->writeHeaderFooter($objWriter, $pSheet);
104
105
        // Breaks
106 73
        $this->writeBreaks($objWriter, $pSheet);
107
108
        // Drawings and/or Charts
109 73
        $this->writeDrawings($objWriter, $pSheet, $includeCharts);
110
111
        // LegacyDrawing
112 73
        $this->writeLegacyDrawing($objWriter, $pSheet);
113
114
        // LegacyDrawingHF
115 73
        $this->writeLegacyDrawingHF($objWriter, $pSheet);
116
117 73
        $objWriter->endElement();
118
119
        // Return
120 73
        return $objWriter->getData();
121
    }
122
123
    /**
124
     * Write SheetPr.
125
     *
126
     * @param XMLWriter $objWriter XML Writer
127
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
128
     */
129 73
    private function writeSheetPr(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
130
    {
131
        // sheetPr
132 73
        $objWriter->startElement('sheetPr');
133 73
        if ($pSheet->getParent()->hasMacros()) {
134
            //if the workbook have macros, we need to have codeName for the sheet
135
            if ($pSheet->hasCodeName() == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
136
                $pSheet->setCodeName($pSheet->getTitle());
137
            }
138
            $objWriter->writeAttribute('codeName', $pSheet->getCodeName());
139
        }
140 73
        $autoFilterRange = $pSheet->getAutoFilter()->getRange();
141 73
        if (!empty($autoFilterRange)) {
142 3
            $objWriter->writeAttribute('filterMode', 1);
143 3
            $pSheet->getAutoFilter()->showHideRows();
144
        }
145
146
        // tabColor
147 73
        if ($pSheet->isTabColorSet()) {
148 6
            $objWriter->startElement('tabColor');
149 6
            $objWriter->writeAttribute('rgb', $pSheet->getTabColor()->getARGB());
150 6
            $objWriter->endElement();
151
        }
152
153
        // outlinePr
154 73
        $objWriter->startElement('outlinePr');
155 73
        $objWriter->writeAttribute('summaryBelow', ($pSheet->getShowSummaryBelow() ? '1' : '0'));
156 73
        $objWriter->writeAttribute('summaryRight', ($pSheet->getShowSummaryRight() ? '1' : '0'));
157 73
        $objWriter->endElement();
158
159
        // pageSetUpPr
160 73
        if ($pSheet->getPageSetup()->getFitToPage()) {
161
            $objWriter->startElement('pageSetUpPr');
162
            $objWriter->writeAttribute('fitToPage', '1');
163
            $objWriter->endElement();
164
        }
165
166 73
        $objWriter->endElement();
167 73
    }
168
169
    /**
170
     * Write Dimension.
171
     *
172
     * @param XMLWriter $objWriter XML Writer
173
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
174
     */
175 73
    private function writeDimension(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
176
    {
177
        // dimension
178 73
        $objWriter->startElement('dimension');
179 73
        $objWriter->writeAttribute('ref', $pSheet->calculateWorksheetDimension());
180 73
        $objWriter->endElement();
181 73
    }
182
183
    /**
184
     * Write SheetViews.
185
     *
186
     * @param XMLWriter $objWriter XML Writer
187
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
188
     *
189
     * @throws WriterException
190
     */
191 73
    private function writeSheetViews(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
192
    {
193
        // sheetViews
194 73
        $objWriter->startElement('sheetViews');
195
196
        // Sheet selected?
197 73
        $sheetSelected = false;
198 73
        if ($this->getParentWriter()->getSpreadsheet()->getIndex($pSheet) == $this->getParentWriter()->getSpreadsheet()->getActiveSheetIndex()) {
199 73
            $sheetSelected = true;
200
        }
201
202
        // sheetView
203 73
        $objWriter->startElement('sheetView');
204 73
        $objWriter->writeAttribute('tabSelected', $sheetSelected ? '1' : '0');
205 73
        $objWriter->writeAttribute('workbookViewId', '0');
206
207
        // Zoom scales
208 73
        if ($pSheet->getSheetView()->getZoomScale() != 100) {
209
            $objWriter->writeAttribute('zoomScale', $pSheet->getSheetView()->getZoomScale());
210
        }
211 73
        if ($pSheet->getSheetView()->getZoomScaleNormal() != 100) {
212
            $objWriter->writeAttribute('zoomScaleNormal', $pSheet->getSheetView()->getZoomScaleNormal());
213
        }
214
215
        // View Layout Type
216 73
        if ($pSheet->getSheetView()->getView() !== SheetView::SHEETVIEW_NORMAL) {
217 1
            $objWriter->writeAttribute('view', $pSheet->getSheetView()->getView());
218
        }
219
220
        // Gridlines
221 73
        if ($pSheet->getShowGridlines()) {
222 73
            $objWriter->writeAttribute('showGridLines', 'true');
223
        } else {
224
            $objWriter->writeAttribute('showGridLines', 'false');
225
        }
226
227
        // Row and column headers
228 73
        if ($pSheet->getShowRowColHeaders()) {
229 73
            $objWriter->writeAttribute('showRowColHeaders', '1');
230
        } else {
231
            $objWriter->writeAttribute('showRowColHeaders', '0');
232
        }
233
234
        // Right-to-left
235 73
        if ($pSheet->getRightToLeft()) {
236
            $objWriter->writeAttribute('rightToLeft', 'true');
237
        }
238
239 73
        $activeCell = $pSheet->getActiveCell();
240
241
        // Pane
242 73
        $pane = '';
243 73
        if ($pSheet->getFreezePane()) {
244 4
            list($xSplit, $ySplit) = Coordinate::coordinateFromString($pSheet->getFreezePane());
245 4
            $xSplit = Coordinate::columnIndexFromString($xSplit);
246 4
            --$xSplit;
247 4
            --$ySplit;
248
249 4
            $topLeftCell = $pSheet->getTopLeftCell();
250 4
            $activeCell = $topLeftCell;
251
252
            // pane
253 4
            $pane = 'topRight';
254 4
            $objWriter->startElement('pane');
255 4
            if ($xSplit > 0) {
256 1
                $objWriter->writeAttribute('xSplit', $xSplit);
257
            }
258 4
            if ($ySplit > 0) {
259 4
                $objWriter->writeAttribute('ySplit', $ySplit);
260 4
                $pane = ($xSplit > 0) ? 'bottomRight' : 'bottomLeft';
261
            }
262 4
            $objWriter->writeAttribute('topLeftCell', $topLeftCell);
263 4
            $objWriter->writeAttribute('activePane', $pane);
264 4
            $objWriter->writeAttribute('state', 'frozen');
265 4
            $objWriter->endElement();
266
267 4
            if (($xSplit > 0) && ($ySplit > 0)) {
268
                //    Write additional selections if more than two panes (ie both an X and a Y split)
269 1
                $objWriter->startElement('selection');
270 1
                $objWriter->writeAttribute('pane', 'topRight');
271 1
                $objWriter->endElement();
272 1
                $objWriter->startElement('selection');
273 1
                $objWriter->writeAttribute('pane', 'bottomLeft');
274 1
                $objWriter->endElement();
275
            }
276
        }
277
278
        // Selection
279
        // Only need to write selection element if we have a split pane
280
        // We cheat a little by over-riding the active cell selection, setting it to the split cell
281 73
        $objWriter->startElement('selection');
282 73
        if ($pane != '') {
283 4
            $objWriter->writeAttribute('pane', $pane);
284
        }
285 73
        $objWriter->writeAttribute('activeCell', $activeCell);
286 73
        $objWriter->writeAttribute('sqref', $activeCell);
287 73
        $objWriter->endElement();
288
289 73
        $objWriter->endElement();
290
291 73
        $objWriter->endElement();
292 73
    }
293
294
    /**
295
     * Write SheetFormatPr.
296
     *
297
     * @param XMLWriter $objWriter XML Writer
298
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
299
     */
300 73
    private function writeSheetFormatPr(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
301
    {
302
        // sheetFormatPr
303 73
        $objWriter->startElement('sheetFormatPr');
304
305
        // Default row height
306 73
        if ($pSheet->getDefaultRowDimension()->getRowHeight() >= 0) {
307 2
            $objWriter->writeAttribute('customHeight', 'true');
308 2
            $objWriter->writeAttribute('defaultRowHeight', StringHelper::formatNumber($pSheet->getDefaultRowDimension()->getRowHeight()));
309
        } else {
310 71
            $objWriter->writeAttribute('defaultRowHeight', '14.4');
311
        }
312
313
        // Set Zero Height row
314 73
        if ((string) $pSheet->getDefaultRowDimension()->getZeroHeight() == '1' ||
315 73
            strtolower((string) $pSheet->getDefaultRowDimension()->getZeroHeight()) == 'true') {
316
            $objWriter->writeAttribute('zeroHeight', '1');
317
        }
318
319
        // Default column width
320 73
        if ($pSheet->getDefaultColumnDimension()->getWidth() >= 0) {
321 1
            $objWriter->writeAttribute('defaultColWidth', StringHelper::formatNumber($pSheet->getDefaultColumnDimension()->getWidth()));
322
        }
323
324
        // Outline level - row
325 73
        $outlineLevelRow = 0;
326 73
        foreach ($pSheet->getRowDimensions() as $dimension) {
327 11
            if ($dimension->getOutlineLevel() > $outlineLevelRow) {
328 11
                $outlineLevelRow = $dimension->getOutlineLevel();
329
            }
330
        }
331 73
        $objWriter->writeAttribute('outlineLevelRow', (int) $outlineLevelRow);
332
333
        // Outline level - column
334 73
        $outlineLevelCol = 0;
335 73
        foreach ($pSheet->getColumnDimensions() as $dimension) {
336 21
            if ($dimension->getOutlineLevel() > $outlineLevelCol) {
337 21
                $outlineLevelCol = $dimension->getOutlineLevel();
338
            }
339
        }
340 73
        $objWriter->writeAttribute('outlineLevelCol', (int) $outlineLevelCol);
341
342 73
        $objWriter->endElement();
343 73
    }
344
345
    /**
346
     * Write Cols.
347
     *
348
     * @param XMLWriter $objWriter XML Writer
349
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
350
     */
351 73
    private function writeCols(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
352
    {
353
        // cols
354 73
        if (count($pSheet->getColumnDimensions()) > 0) {
355 21
            $objWriter->startElement('cols');
356
357 21
            $pSheet->calculateColumnWidths();
358
359
            // Loop through column dimensions
360 21
            foreach ($pSheet->getColumnDimensions() as $colDimension) {
361
                // col
362 21
                $objWriter->startElement('col');
363 21
                $objWriter->writeAttribute('min', Coordinate::columnIndexFromString($colDimension->getColumnIndex()));
364 21
                $objWriter->writeAttribute('max', Coordinate::columnIndexFromString($colDimension->getColumnIndex()));
365
366 21
                if ($colDimension->getWidth() < 0) {
367
                    // No width set, apply default of 10
368 2
                    $objWriter->writeAttribute('width', '9.10');
369
                } else {
370
                    // Width set
371 21
                    $objWriter->writeAttribute('width', StringHelper::formatNumber($colDimension->getWidth()));
372
                }
373
374
                // Column visibility
375 21
                if ($colDimension->getVisible() == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
376 3
                    $objWriter->writeAttribute('hidden', 'true');
377
                }
378
379
                // Auto size?
380 21
                if ($colDimension->getAutoSize()) {
381 8
                    $objWriter->writeAttribute('bestFit', 'true');
382
                }
383
384
                // Custom width?
385 21
                if ($colDimension->getWidth() != $pSheet->getDefaultColumnDimension()->getWidth()) {
386 21
                    $objWriter->writeAttribute('customWidth', 'true');
387
                }
388
389
                // Collapsed
390 21
                if ($colDimension->getCollapsed() == true) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
391 1
                    $objWriter->writeAttribute('collapsed', 'true');
392
                }
393
394
                // Outline level
395 21
                if ($colDimension->getOutlineLevel() > 0) {
396 1
                    $objWriter->writeAttribute('outlineLevel', $colDimension->getOutlineLevel());
397
                }
398
399
                // Style
400 21
                $objWriter->writeAttribute('style', $colDimension->getXfIndex());
401
402 21
                $objWriter->endElement();
403
            }
404
405 21
            $objWriter->endElement();
406
        }
407 73
    }
408
409
    /**
410
     * Write SheetProtection.
411
     *
412
     * @param XMLWriter $objWriter XML Writer
413
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
414
     */
415 73
    private function writeSheetProtection(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
416
    {
417
        // sheetProtection
418 73
        $objWriter->startElement('sheetProtection');
419
420 73
        if ($pSheet->getProtection()->getPassword() != '') {
421 1
            $objWriter->writeAttribute('password', $pSheet->getProtection()->getPassword());
422
        }
423
424 73
        $objWriter->writeAttribute('sheet', ($pSheet->getProtection()->getSheet() ? 'true' : 'false'));
425 73
        $objWriter->writeAttribute('objects', ($pSheet->getProtection()->getObjects() ? 'true' : 'false'));
426 73
        $objWriter->writeAttribute('scenarios', ($pSheet->getProtection()->getScenarios() ? 'true' : 'false'));
427 73
        $objWriter->writeAttribute('formatCells', ($pSheet->getProtection()->getFormatCells() ? 'true' : 'false'));
428 73
        $objWriter->writeAttribute('formatColumns', ($pSheet->getProtection()->getFormatColumns() ? 'true' : 'false'));
429 73
        $objWriter->writeAttribute('formatRows', ($pSheet->getProtection()->getFormatRows() ? 'true' : 'false'));
430 73
        $objWriter->writeAttribute('insertColumns', ($pSheet->getProtection()->getInsertColumns() ? 'true' : 'false'));
431 73
        $objWriter->writeAttribute('insertRows', ($pSheet->getProtection()->getInsertRows() ? 'true' : 'false'));
432 73
        $objWriter->writeAttribute('insertHyperlinks', ($pSheet->getProtection()->getInsertHyperlinks() ? 'true' : 'false'));
433 73
        $objWriter->writeAttribute('deleteColumns', ($pSheet->getProtection()->getDeleteColumns() ? 'true' : 'false'));
434 73
        $objWriter->writeAttribute('deleteRows', ($pSheet->getProtection()->getDeleteRows() ? 'true' : 'false'));
435 73
        $objWriter->writeAttribute('selectLockedCells', ($pSheet->getProtection()->getSelectLockedCells() ? 'true' : 'false'));
436 73
        $objWriter->writeAttribute('sort', ($pSheet->getProtection()->getSort() ? 'true' : 'false'));
437 73
        $objWriter->writeAttribute('autoFilter', ($pSheet->getProtection()->getAutoFilter() ? 'true' : 'false'));
438 73
        $objWriter->writeAttribute('pivotTables', ($pSheet->getProtection()->getPivotTables() ? 'true' : 'false'));
439 73
        $objWriter->writeAttribute('selectUnlockedCells', ($pSheet->getProtection()->getSelectUnlockedCells() ? 'true' : 'false'));
440 73
        $objWriter->endElement();
441 73
    }
442
443
    /**
444
     * Write ConditionalFormatting.
445
     *
446
     * @param XMLWriter $objWriter XML Writer
447
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
448
     *
449
     * @throws WriterException
450
     */
451 73
    private function writeConditionalFormatting(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
452
    {
453
        // Conditional id
454 73
        $id = 1;
455
456
        // Loop through styles in the current worksheet
457 73
        foreach ($pSheet->getConditionalStylesCollection() as $cellCoordinate => $conditionalStyles) {
458 3
            foreach ($conditionalStyles as $conditional) {
459
                // WHY was this again?
460
                // if ($this->getParentWriter()->getStylesConditionalHashTable()->getIndexForHashCode($conditional->getHashCode()) == '') {
0 ignored issues
show
Unused Code Comprehensibility introduced by
66% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
461
                //    continue;
462
                // }
463 3
                if ($conditional->getConditionType() != Conditional::CONDITION_NONE) {
464
                    // conditionalFormatting
465 3
                    $objWriter->startElement('conditionalFormatting');
466 3
                    $objWriter->writeAttribute('sqref', $cellCoordinate);
467
468
                    // cfRule
469 3
                    $objWriter->startElement('cfRule');
470 3
                    $objWriter->writeAttribute('type', $conditional->getConditionType());
471 3
                    $objWriter->writeAttribute('dxfId', $this->getParentWriter()->getStylesConditionalHashTable()->getIndexForHashCode($conditional->getHashCode()));
472 3
                    $objWriter->writeAttribute('priority', $id++);
473
474 3
                    if (($conditional->getConditionType() == Conditional::CONDITION_CELLIS || $conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT)
475 3
                        && $conditional->getOperatorType() != Conditional::OPERATOR_NONE) {
476 3
                        $objWriter->writeAttribute('operator', $conditional->getOperatorType());
477
                    }
478
479 3
                    if ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
480 3
                        && $conditional->getText() !== null) {
481
                        $objWriter->writeAttribute('text', $conditional->getText());
482
                    }
483
484 3
                    if ($conditional->getStopIfTrue()) {
485 1
                        $objWriter->writeAttribute('stopIfTrue', '1');
486
                    }
487
488 3
                    if ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
489 3
                        && $conditional->getOperatorType() == Conditional::OPERATOR_CONTAINSTEXT
490 3
                        && $conditional->getText() !== null) {
491
                        $objWriter->writeElement('formula', 'NOT(ISERROR(SEARCH("' . $conditional->getText() . '",' . $cellCoordinate . ')))');
492 3
                    } elseif ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
493 3
                        && $conditional->getOperatorType() == Conditional::OPERATOR_BEGINSWITH
494 3
                        && $conditional->getText() !== null) {
495
                        $objWriter->writeElement('formula', 'LEFT(' . $cellCoordinate . ',' . strlen($conditional->getText()) . ')="' . $conditional->getText() . '"');
496 3
                    } elseif ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
497 3
                        && $conditional->getOperatorType() == Conditional::OPERATOR_ENDSWITH
498 3
                        && $conditional->getText() !== null) {
499
                        $objWriter->writeElement('formula', 'RIGHT(' . $cellCoordinate . ',' . strlen($conditional->getText()) . ')="' . $conditional->getText() . '"');
500 3
                    } elseif ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
501 3
                        && $conditional->getOperatorType() == Conditional::OPERATOR_NOTCONTAINS
502 3
                        && $conditional->getText() !== null) {
503
                        $objWriter->writeElement('formula', 'ISERROR(SEARCH("' . $conditional->getText() . '",' . $cellCoordinate . '))');
504 3
                    } elseif ($conditional->getConditionType() == Conditional::CONDITION_CELLIS
505 1
                        || $conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
506 3
                        || $conditional->getConditionType() == Conditional::CONDITION_EXPRESSION) {
507 3
                        foreach ($conditional->getConditions() as $formula) {
508
                            // Formula
509 3
                            $objWriter->writeElement('formula', $formula);
510
                        }
511
                    }
512
513 3
                    $objWriter->endElement();
514
515 3
                    $objWriter->endElement();
516
                }
517
            }
518
        }
519 73
    }
520
521
    /**
522
     * Write DataValidations.
523
     *
524
     * @param XMLWriter $objWriter XML Writer
525
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
526
     */
527 73
    private function writeDataValidations(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
528
    {
529
        // Datavalidation collection
530 73
        $dataValidationCollection = $pSheet->getDataValidationCollection();
531
532
        // Write data validations?
533 73
        if (!empty($dataValidationCollection)) {
534 2
            $dataValidationCollection = Coordinate::mergeRangesInCollection($dataValidationCollection);
535 2
            $objWriter->startElement('dataValidations');
536 2
            $objWriter->writeAttribute('count', count($dataValidationCollection));
537
538 2
            foreach ($dataValidationCollection as $coordinate => $dv) {
539 2
                $objWriter->startElement('dataValidation');
540
541 2
                if ($dv->getType() != '') {
542 2
                    $objWriter->writeAttribute('type', $dv->getType());
543
                }
544
545 2
                if ($dv->getErrorStyle() != '') {
546 2
                    $objWriter->writeAttribute('errorStyle', $dv->getErrorStyle());
547
                }
548
549 2
                if ($dv->getOperator() != '') {
550 2
                    $objWriter->writeAttribute('operator', $dv->getOperator());
551
                }
552
553 2
                $objWriter->writeAttribute('allowBlank', ($dv->getAllowBlank() ? '1' : '0'));
554 2
                $objWriter->writeAttribute('showDropDown', (!$dv->getShowDropDown() ? '1' : '0'));
555 2
                $objWriter->writeAttribute('showInputMessage', ($dv->getShowInputMessage() ? '1' : '0'));
556 2
                $objWriter->writeAttribute('showErrorMessage', ($dv->getShowErrorMessage() ? '1' : '0'));
557
558 2
                if ($dv->getErrorTitle() !== '') {
559 2
                    $objWriter->writeAttribute('errorTitle', $dv->getErrorTitle());
560
                }
561 2
                if ($dv->getError() !== '') {
562 2
                    $objWriter->writeAttribute('error', $dv->getError());
563
                }
564 2
                if ($dv->getPromptTitle() !== '') {
565 2
                    $objWriter->writeAttribute('promptTitle', $dv->getPromptTitle());
566
                }
567 2
                if ($dv->getPrompt() !== '') {
568 2
                    $objWriter->writeAttribute('prompt', $dv->getPrompt());
569
                }
570
571 2
                $objWriter->writeAttribute('sqref', $coordinate);
572
573 2
                if ($dv->getFormula1() !== '') {
574 2
                    $objWriter->writeElement('formula1', $dv->getFormula1());
575
                }
576 2
                if ($dv->getFormula2() !== '') {
577 1
                    $objWriter->writeElement('formula2', $dv->getFormula2());
578
                }
579
580 2
                $objWriter->endElement();
581
            }
582
583 2
            $objWriter->endElement();
584
        }
585 73
    }
586
587
    /**
588
     * Write Hyperlinks.
589
     *
590
     * @param XMLWriter $objWriter XML Writer
591
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
592
     */
593 73
    private function writeHyperlinks(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
594
    {
595
        // Hyperlink collection
596 73
        $hyperlinkCollection = $pSheet->getHyperlinkCollection();
597
598
        // Relation ID
599 73
        $relationId = 1;
600
601
        // Write hyperlinks?
602 73
        if (!empty($hyperlinkCollection)) {
603 10
            $objWriter->startElement('hyperlinks');
604
605 10
            foreach ($hyperlinkCollection as $coordinate => $hyperlink) {
606 10
                $objWriter->startElement('hyperlink');
607
608 10
                $objWriter->writeAttribute('ref', $coordinate);
609 10
                if (!$hyperlink->isInternal()) {
610 10
                    $objWriter->writeAttribute('r:id', 'rId_hyperlink_' . $relationId);
611 10
                    ++$relationId;
612
                } else {
613 7
                    $objWriter->writeAttribute('location', str_replace('sheet://', '', $hyperlink->getUrl()));
614
                }
615
616 10
                if ($hyperlink->getTooltip() != '') {
617 6
                    $objWriter->writeAttribute('tooltip', $hyperlink->getTooltip());
618
                }
619
620 10
                $objWriter->endElement();
621
            }
622
623 10
            $objWriter->endElement();
624
        }
625 73
    }
626
627
    /**
628
     * Write ProtectedRanges.
629
     *
630
     * @param XMLWriter $objWriter XML Writer
631
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
632
     */
633 73
    private function writeProtectedRanges(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
634
    {
635 73
        if (count($pSheet->getProtectedCells()) > 0) {
636
            // protectedRanges
637 6
            $objWriter->startElement('protectedRanges');
638
639
            // Loop protectedRanges
640 6
            foreach ($pSheet->getProtectedCells() as $protectedCell => $passwordHash) {
641
                // protectedRange
642 6
                $objWriter->startElement('protectedRange');
643 6
                $objWriter->writeAttribute('name', 'p' . md5($protectedCell));
644 6
                $objWriter->writeAttribute('sqref', $protectedCell);
645 6
                if (!empty($passwordHash)) {
646 6
                    $objWriter->writeAttribute('password', $passwordHash);
0 ignored issues
show
Bug introduced by
$passwordHash of type array is incompatible with the type string expected by parameter $value of XMLWriter::writeAttribute(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

646
                    $objWriter->writeAttribute('password', /** @scrutinizer ignore-type */ $passwordHash);
Loading history...
647
                }
648 6
                $objWriter->endElement();
649
            }
650
651 6
            $objWriter->endElement();
652
        }
653 73
    }
654
655
    /**
656
     * Write MergeCells.
657
     *
658
     * @param XMLWriter $objWriter XML Writer
659
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
660
     */
661 73
    private function writeMergeCells(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
662
    {
663 73
        if (count($pSheet->getMergeCells()) > 0) {
664
            // mergeCells
665 13
            $objWriter->startElement('mergeCells');
666
667
            // Loop mergeCells
668 13
            foreach ($pSheet->getMergeCells() as $mergeCell) {
669
                // mergeCell
670 13
                $objWriter->startElement('mergeCell');
671 13
                $objWriter->writeAttribute('ref', $mergeCell);
0 ignored issues
show
Bug introduced by
$mergeCell of type array is incompatible with the type string expected by parameter $value of XMLWriter::writeAttribute(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

671
                $objWriter->writeAttribute('ref', /** @scrutinizer ignore-type */ $mergeCell);
Loading history...
672 13
                $objWriter->endElement();
673
            }
674
675 13
            $objWriter->endElement();
676
        }
677 73
    }
678
679
    /**
680
     * Write PrintOptions.
681
     *
682
     * @param XMLWriter $objWriter XML Writer
683
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
684
     */
685 73
    private function writePrintOptions(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
686
    {
687
        // printOptions
688 73
        $objWriter->startElement('printOptions');
689
690 73
        $objWriter->writeAttribute('gridLines', ($pSheet->getPrintGridlines() ? 'true' : 'false'));
691 73
        $objWriter->writeAttribute('gridLinesSet', 'true');
692
693 73
        if ($pSheet->getPageSetup()->getHorizontalCentered()) {
694
            $objWriter->writeAttribute('horizontalCentered', 'true');
695
        }
696
697 73
        if ($pSheet->getPageSetup()->getVerticalCentered()) {
698
            $objWriter->writeAttribute('verticalCentered', 'true');
699
        }
700
701 73
        $objWriter->endElement();
702 73
    }
703
704
    /**
705
     * Write PageMargins.
706
     *
707
     * @param XMLWriter $objWriter XML Writer
708
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
709
     */
710 73
    private function writePageMargins(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
711
    {
712
        // pageMargins
713 73
        $objWriter->startElement('pageMargins');
714 73
        $objWriter->writeAttribute('left', StringHelper::formatNumber($pSheet->getPageMargins()->getLeft()));
715 73
        $objWriter->writeAttribute('right', StringHelper::formatNumber($pSheet->getPageMargins()->getRight()));
716 73
        $objWriter->writeAttribute('top', StringHelper::formatNumber($pSheet->getPageMargins()->getTop()));
717 73
        $objWriter->writeAttribute('bottom', StringHelper::formatNumber($pSheet->getPageMargins()->getBottom()));
718 73
        $objWriter->writeAttribute('header', StringHelper::formatNumber($pSheet->getPageMargins()->getHeader()));
719 73
        $objWriter->writeAttribute('footer', StringHelper::formatNumber($pSheet->getPageMargins()->getFooter()));
720 73
        $objWriter->endElement();
721 73
    }
722
723
    /**
724
     * Write AutoFilter.
725
     *
726
     * @param XMLWriter $objWriter XML Writer
727
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
728
     */
729 73
    private function writeAutoFilter(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
730
    {
731 73
        $autoFilterRange = $pSheet->getAutoFilter()->getRange();
732 73
        if (!empty($autoFilterRange)) {
733
            // autoFilter
734 3
            $objWriter->startElement('autoFilter');
735
736
            // Strip any worksheet reference from the filter coordinates
737 3
            $range = Coordinate::splitRange($autoFilterRange);
738 3
            $range = $range[0];
739
            //    Strip any worksheet ref
740 3
            if (strpos($range[0], '!') !== false) {
741
                list($ws, $range[0]) = explode('!', $range[0]);
742
            }
743 3
            $range = implode(':', $range);
744
745 3
            $objWriter->writeAttribute('ref', str_replace('$', '', $range));
746
747 3
            $columns = $pSheet->getAutoFilter()->getColumns();
748 3
            if (count($columns) > 0) {
749 2
                foreach ($columns as $columnID => $column) {
750 2
                    $rules = $column->getRules();
751 2
                    if (count($rules) > 0) {
752 2
                        $objWriter->startElement('filterColumn');
753 2
                        $objWriter->writeAttribute('colId', $pSheet->getAutoFilter()->getColumnOffset($columnID));
754
755 2
                        $objWriter->startElement($column->getFilterType());
756 2
                        if ($column->getJoin() == Column::AUTOFILTER_COLUMN_JOIN_AND) {
757 1
                            $objWriter->writeAttribute('and', 1);
758
                        }
759
760 2
                        foreach ($rules as $rule) {
761 2
                            if (($column->getFilterType() === Column::AUTOFILTER_FILTERTYPE_FILTER) &&
762 2
                                ($rule->getOperator() === Rule::AUTOFILTER_COLUMN_RULE_EQUAL) &&
763 2
                                ($rule->getValue() === '')) {
764
                                //    Filter rule for Blanks
765 1
                                $objWriter->writeAttribute('blank', 1);
766 2
                            } elseif ($rule->getRuleType() === Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER) {
767
                                //    Dynamic Filter Rule
768 1
                                $objWriter->writeAttribute('type', $rule->getGrouping());
769 1
                                $val = $column->getAttribute('val');
770 1
                                if ($val !== null) {
771 1
                                    $objWriter->writeAttribute('val', $val);
772
                                }
773 1
                                $maxVal = $column->getAttribute('maxVal');
774 1
                                if ($maxVal !== null) {
775 1
                                    $objWriter->writeAttribute('maxVal', $maxVal);
776
                                }
777 2
                            } elseif ($rule->getRuleType() === Rule::AUTOFILTER_RULETYPE_TOPTENFILTER) {
778
                                //    Top 10 Filter Rule
779
                                $objWriter->writeAttribute('val', $rule->getValue());
780
                                $objWriter->writeAttribute('percent', (($rule->getOperator() === Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT) ? '1' : '0'));
781
                                $objWriter->writeAttribute('top', (($rule->getGrouping() === Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP) ? '1' : '0'));
782
                            } else {
783
                                //    Filter, DateGroupItem or CustomFilter
784 2
                                $objWriter->startElement($rule->getRuleType());
785
786 2
                                if ($rule->getOperator() !== Rule::AUTOFILTER_COLUMN_RULE_EQUAL) {
787 1
                                    $objWriter->writeAttribute('operator', $rule->getOperator());
788
                                }
789 2
                                if ($rule->getRuleType() === Rule::AUTOFILTER_RULETYPE_DATEGROUP) {
790
                                    // Date Group filters
791 1
                                    foreach ($rule->getValue() as $key => $value) {
0 ignored issues
show
Bug introduced by
The expression $rule->getValue() of type string is not traversable.
Loading history...
792 1
                                        if ($value > '') {
793 1
                                            $objWriter->writeAttribute($key, $value);
794
                                        }
795
                                    }
796 1
                                    $objWriter->writeAttribute('dateTimeGrouping', $rule->getGrouping());
797
                                } else {
798 2
                                    $objWriter->writeAttribute('val', $rule->getValue());
799
                                }
800
801 2
                                $objWriter->endElement();
802
                            }
803
                        }
804
805 2
                        $objWriter->endElement();
806
807 2
                        $objWriter->endElement();
808
                    }
809
                }
810
            }
811 3
            $objWriter->endElement();
812
        }
813 73
    }
814
815
    /**
816
     * Write PageSetup.
817
     *
818
     * @param XMLWriter $objWriter XML Writer
819
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
820
     */
821 73
    private function writePageSetup(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
822
    {
823
        // pageSetup
824 73
        $objWriter->startElement('pageSetup');
825 73
        $objWriter->writeAttribute('paperSize', $pSheet->getPageSetup()->getPaperSize());
826 73
        $objWriter->writeAttribute('orientation', $pSheet->getPageSetup()->getOrientation());
827
828 73
        if ($pSheet->getPageSetup()->getScale() !== null) {
0 ignored issues
show
introduced by
The condition $pSheet->getPageSetup()->getScale() !== null can never be false.
Loading history...
829 73
            $objWriter->writeAttribute('scale', $pSheet->getPageSetup()->getScale());
830
        }
831 73
        if ($pSheet->getPageSetup()->getFitToHeight() !== null) {
0 ignored issues
show
introduced by
The condition $pSheet->getPageSetup()-...tFitToHeight() !== null can never be false.
Loading history...
832 73
            $objWriter->writeAttribute('fitToHeight', $pSheet->getPageSetup()->getFitToHeight());
833
        } else {
834
            $objWriter->writeAttribute('fitToHeight', '0');
835
        }
836 73
        if ($pSheet->getPageSetup()->getFitToWidth() !== null) {
0 ignored issues
show
introduced by
The condition $pSheet->getPageSetup()->getFitToWidth() !== null can never be false.
Loading history...
837 73
            $objWriter->writeAttribute('fitToWidth', $pSheet->getPageSetup()->getFitToWidth());
838
        } else {
839
            $objWriter->writeAttribute('fitToWidth', '0');
840
        }
841 73
        if ($pSheet->getPageSetup()->getFirstPageNumber() !== null) {
0 ignored issues
show
introduced by
The condition $pSheet->getPageSetup()-...stPageNumber() !== null can never be false.
Loading history...
842
            $objWriter->writeAttribute('firstPageNumber', $pSheet->getPageSetup()->getFirstPageNumber());
843
            $objWriter->writeAttribute('useFirstPageNumber', '1');
844
        }
845
846 73
        $objWriter->endElement();
847 73
    }
848
849
    /**
850
     * Write Header / Footer.
851
     *
852
     * @param XMLWriter $objWriter XML Writer
853
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
854
     */
855 73
    private function writeHeaderFooter(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
856
    {
857
        // headerFooter
858 73
        $objWriter->startElement('headerFooter');
859 73
        $objWriter->writeAttribute('differentOddEven', ($pSheet->getHeaderFooter()->getDifferentOddEven() ? 'true' : 'false'));
860 73
        $objWriter->writeAttribute('differentFirst', ($pSheet->getHeaderFooter()->getDifferentFirst() ? 'true' : 'false'));
861 73
        $objWriter->writeAttribute('scaleWithDoc', ($pSheet->getHeaderFooter()->getScaleWithDocument() ? 'true' : 'false'));
862 73
        $objWriter->writeAttribute('alignWithMargins', ($pSheet->getHeaderFooter()->getAlignWithMargins() ? 'true' : 'false'));
863
864 73
        $objWriter->writeElement('oddHeader', $pSheet->getHeaderFooter()->getOddHeader());
865 73
        $objWriter->writeElement('oddFooter', $pSheet->getHeaderFooter()->getOddFooter());
866 73
        $objWriter->writeElement('evenHeader', $pSheet->getHeaderFooter()->getEvenHeader());
867 73
        $objWriter->writeElement('evenFooter', $pSheet->getHeaderFooter()->getEvenFooter());
868 73
        $objWriter->writeElement('firstHeader', $pSheet->getHeaderFooter()->getFirstHeader());
869 73
        $objWriter->writeElement('firstFooter', $pSheet->getHeaderFooter()->getFirstFooter());
870 73
        $objWriter->endElement();
871 73
    }
872
873
    /**
874
     * Write Breaks.
875
     *
876
     * @param XMLWriter $objWriter XML Writer
877
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
878
     */
879 73
    private function writeBreaks(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
880
    {
881
        // Get row and column breaks
882 73
        $aRowBreaks = [];
883 73
        $aColumnBreaks = [];
884 73
        foreach ($pSheet->getBreaks() as $cell => $breakType) {
885 1
            if ($breakType == PhpspreadsheetWorksheet::BREAK_ROW) {
886 1
                $aRowBreaks[] = $cell;
887
            } elseif ($breakType == PhpspreadsheetWorksheet::BREAK_COLUMN) {
888 1
                $aColumnBreaks[] = $cell;
889
            }
890
        }
891
892
        // rowBreaks
893 73
        if (!empty($aRowBreaks)) {
894 1
            $objWriter->startElement('rowBreaks');
895 1
            $objWriter->writeAttribute('count', count($aRowBreaks));
896 1
            $objWriter->writeAttribute('manualBreakCount', count($aRowBreaks));
897
898 1
            foreach ($aRowBreaks as $cell) {
899 1
                $coords = Coordinate::coordinateFromString($cell);
900
901 1
                $objWriter->startElement('brk');
902 1
                $objWriter->writeAttribute('id', $coords[1]);
903 1
                $objWriter->writeAttribute('man', '1');
904 1
                $objWriter->endElement();
905
            }
906
907 1
            $objWriter->endElement();
908
        }
909
910
        // Second, write column breaks
911 73
        if (!empty($aColumnBreaks)) {
912
            $objWriter->startElement('colBreaks');
913
            $objWriter->writeAttribute('count', count($aColumnBreaks));
914
            $objWriter->writeAttribute('manualBreakCount', count($aColumnBreaks));
915
916
            foreach ($aColumnBreaks as $cell) {
917
                $coords = Coordinate::coordinateFromString($cell);
918
919
                $objWriter->startElement('brk');
920
                $objWriter->writeAttribute('id', Coordinate::columnIndexFromString($coords[0]) - 1);
921
                $objWriter->writeAttribute('man', '1');
922
                $objWriter->endElement();
923
            }
924
925
            $objWriter->endElement();
926
        }
927 73
    }
928
929
    /**
930
     * Write SheetData.
931
     *
932
     * @param XMLWriter $objWriter XML Writer
933
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
934
     * @param string[] $pStringTable String table
935
     *
936
     * @throws WriterException
937
     */
938 73
    private function writeSheetData(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet, array $pStringTable)
939
    {
940
        // Flipped stringtable, for faster index searching
941 73
        $aFlippedStringTable = $this->getParentWriter()->getWriterPart('stringtable')->flipStringTable($pStringTable);
0 ignored issues
show
Bug introduced by
The method flipStringTable() does not exist on PhpOffice\PhpSpreadsheet\Writer\Xlsx\WriterPart. It seems like you code against a sub-type of PhpOffice\PhpSpreadsheet\Writer\Xlsx\WriterPart such as PhpOffice\PhpSpreadsheet\Writer\Xlsx\StringTable. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

941
        $aFlippedStringTable = $this->getParentWriter()->getWriterPart('stringtable')->/** @scrutinizer ignore-call */ flipStringTable($pStringTable);
Loading history...
942
943
        // sheetData
944 73
        $objWriter->startElement('sheetData');
945
946
        // Get column count
947 73
        $colCount = Coordinate::columnIndexFromString($pSheet->getHighestColumn());
948
949
        // Highest row number
950 73
        $highestRow = $pSheet->getHighestRow();
951
952
        // Loop through cells
953 73
        $cellsByRow = [];
954 73
        foreach ($pSheet->getCoordinates() as $coordinate) {
955 68
            $cellAddress = Coordinate::coordinateFromString($coordinate);
956 68
            $cellsByRow[$cellAddress[1]][] = $coordinate;
957
        }
958
959 73
        $currentRow = 0;
960 73
        while ($currentRow++ < $highestRow) {
961
            // Get row dimension
962 73
            $rowDimension = $pSheet->getRowDimension($currentRow);
963
964
            // Write current row?
965 73
            $writeCurrentRow = isset($cellsByRow[$currentRow]) || $rowDimension->getRowHeight() >= 0 || $rowDimension->getVisible() == false || $rowDimension->getCollapsed() == true || $rowDimension->getOutlineLevel() > 0 || $rowDimension->getXfIndex() !== null;
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
966
967 73
            if ($writeCurrentRow) {
968
                // Start a new row
969 68
                $objWriter->startElement('row');
970 68
                $objWriter->writeAttribute('r', $currentRow);
971 68
                $objWriter->writeAttribute('spans', '1:' . $colCount);
972
973
                // Row dimensions
974 68
                if ($rowDimension->getRowHeight() >= 0) {
975 5
                    $objWriter->writeAttribute('customHeight', '1');
976 5
                    $objWriter->writeAttribute('ht', StringHelper::formatNumber($rowDimension->getRowHeight()));
977
                }
978
979
                // Row visibility
980 68
                if ($rowDimension->getVisible() == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
981 2
                    $objWriter->writeAttribute('hidden', 'true');
982
                }
983
984
                // Collapsed
985 68
                if ($rowDimension->getCollapsed() == true) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
986
                    $objWriter->writeAttribute('collapsed', 'true');
987
                }
988
989
                // Outline level
990 68
                if ($rowDimension->getOutlineLevel() > 0) {
991
                    $objWriter->writeAttribute('outlineLevel', $rowDimension->getOutlineLevel());
992
                }
993
994
                // Style
995 68
                if ($rowDimension->getXfIndex() !== null) {
996
                    $objWriter->writeAttribute('s', $rowDimension->getXfIndex());
997
                    $objWriter->writeAttribute('customFormat', '1');
998
                }
999
1000
                // Write cells
1001 68
                if (isset($cellsByRow[$currentRow])) {
1002 68
                    foreach ($cellsByRow[$currentRow] as $cellAddress) {
1003
                        // Write cell
1004 68
                        $this->writeCell($objWriter, $pSheet, $cellAddress, $aFlippedStringTable);
1005
                    }
1006
                }
1007
1008
                // End row
1009 68
                $objWriter->endElement();
1010
            }
1011
        }
1012
1013 73
        $objWriter->endElement();
1014 73
    }
1015
1016
    /**
1017
     * Write Cell.
1018
     *
1019
     * @param XMLWriter $objWriter XML Writer
1020
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
1021
     * @param Cell $pCellAddress Cell Address
1022
     * @param string[] $pFlippedStringTable String table (flipped), for faster index searching
1023
     *
1024
     * @throws WriterException
1025
     */
1026 68
    private function writeCell(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet, $pCellAddress, array $pFlippedStringTable)
1027
    {
1028
        // Cell
1029 68
        $pCell = $pSheet->getCell($pCellAddress);
1030 68
        $objWriter->startElement('c');
1031 68
        $objWriter->writeAttribute('r', $pCellAddress);
1032
1033
        // Sheet styles
1034 68
        if ($pCell->getXfIndex() != '') {
1035 32
            $objWriter->writeAttribute('s', $pCell->getXfIndex());
1036
        }
1037
1038
        // If cell value is supplied, write cell value
1039 68
        $cellValue = $pCell->getValue();
1040 68
        if (is_object($cellValue) || $cellValue !== '') {
1041
            // Map type
1042 68
            $mappedType = $pCell->getDataType();
1043
1044
            // Write data type depending on its type
1045 68
            switch (strtolower($mappedType)) {
1046 68
                case 'inlinestr':    // Inline string
1047 67
                case 's':            // String
1048 57
                case 'b':            // Boolean
1049 55
                    $objWriter->writeAttribute('t', $mappedType);
1050
1051 55
                    break;
1052 54
                case 'f':            // Formula
1053 21
                    $calculatedValue = ($this->getParentWriter()->getPreCalculateFormulas()) ?
1054 21
                        $pCell->getCalculatedValue() : $cellValue;
1055 21
                    if (is_string($calculatedValue)) {
1056 14
                        $objWriter->writeAttribute('t', 'str');
1057 18
                    } elseif (is_bool($calculatedValue)) {
1058 5
                        $objWriter->writeAttribute('t', 'b');
1059
                    }
1060
1061 21
                    break;
1062 50
                case 'e':            // Error
1063
                    $objWriter->writeAttribute('t', $mappedType);
1064
            }
1065
1066
            // Write data depending on its type
1067 68
            switch (strtolower($mappedType)) {
1068 68
                case 'inlinestr':    // Inline string
1069 8
                    if (!$cellValue instanceof RichText) {
1070
                        $objWriter->writeElement('t', StringHelper::controlCharacterPHP2OOXML(htmlspecialchars($cellValue)));
1071 8
                    } elseif ($cellValue instanceof RichText) {
0 ignored issues
show
introduced by
The condition $cellValue instanceof Ph...sheet\RichText\RichText can never be false since $cellValue is always a sub-type of PhpOffice\PhpSpreadsheet\RichText\RichText.
Loading history...
1072 8
                        $objWriter->startElement('is');
1073 8
                        $this->getParentWriter()->getWriterPart('stringtable')->writeRichText($objWriter, $cellValue);
0 ignored issues
show
Bug introduced by
The method writeRichText() does not exist on PhpOffice\PhpSpreadsheet\Writer\Xlsx\WriterPart. It seems like you code against a sub-type of PhpOffice\PhpSpreadsheet\Writer\Xlsx\WriterPart such as PhpOffice\PhpSpreadsheet\Writer\Xlsx\StringTable. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1073
                        $this->getParentWriter()->getWriterPart('stringtable')->/** @scrutinizer ignore-call */ writeRichText($objWriter, $cellValue);
Loading history...
1074 8
                        $objWriter->endElement();
1075
                    }
1076
1077 8
                    break;
1078 67
                case 's':            // String
1079 53
                    if (!$cellValue instanceof RichText) {
1080 53
                        if (isset($pFlippedStringTable[$cellValue])) {
1081 53
                            $objWriter->writeElement('v', $pFlippedStringTable[$cellValue]);
1082
                        }
1083 2
                    } elseif ($cellValue instanceof RichText) {
0 ignored issues
show
introduced by
The condition $cellValue instanceof Ph...sheet\RichText\RichText can never be false since $cellValue is always a sub-type of PhpOffice\PhpSpreadsheet\RichText\RichText.
Loading history...
1084 2
                        $objWriter->writeElement('v', $pFlippedStringTable[$cellValue->getHashCode()]);
1085
                    }
1086
1087 53
                    break;
1088 57
                case 'f':            // Formula
1089 21
                    $attributes = $pCell->getFormulaAttributes();
1090 21
                    if ($attributes['t'] == 'array') {
1091
                        $objWriter->startElement('f');
1092
                        $objWriter->writeAttribute('t', 'array');
1093
                        $objWriter->writeAttribute('ref', $pCellAddress);
1094
                        $objWriter->writeAttribute('aca', '1');
1095
                        $objWriter->writeAttribute('ca', '1');
1096
                        $objWriter->text(substr($cellValue, 1));
1097
                        $objWriter->endElement();
1098
                    } else {
1099 21
                        $objWriter->writeElement('f', substr($cellValue, 1));
1100
                    }
1101 21
                    if ($this->getParentWriter()->getOffice2003Compatibility() === false) {
1102 21
                        if ($this->getParentWriter()->getPreCalculateFormulas()) {
1103 21
                            if (!is_array($calculatedValue) && substr($calculatedValue, 0, 1) != '#') {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $calculatedValue does not seem to be defined for all execution paths leading up to this point.
Loading history...
1104 21
                                $objWriter->writeElement('v', StringHelper::formatNumber($calculatedValue));
1105
                            } else {
1106 21
                                $objWriter->writeElement('v', '0');
1107
                            }
1108
                        } else {
1109
                            $objWriter->writeElement('v', '0');
1110
                        }
1111
                    }
1112
1113 21
                    break;
1114 53
                case 'n':            // Numeric
1115
                    // force point as decimal separator in case current locale uses comma
1116 44
                    $objWriter->writeElement('v', str_replace(',', '.', $cellValue));
1117
1118 44
                    break;
1119 27
                case 'b':            // Boolean
1120 9
                    $objWriter->writeElement('v', ($cellValue ? '1' : '0'));
1121
1122 9
                    break;
1123 22
                case 'e':            // Error
1124
                    if (substr($cellValue, 0, 1) == '=') {
1125
                        $objWriter->writeElement('f', substr($cellValue, 1));
1126
                        $objWriter->writeElement('v', substr($cellValue, 1));
1127
                    } else {
1128
                        $objWriter->writeElement('v', $cellValue);
1129
                    }
1130
1131
                    break;
1132
            }
1133
        }
1134
1135 68
        $objWriter->endElement();
1136 68
    }
1137
1138
    /**
1139
     * Write Drawings.
1140
     *
1141
     * @param XMLWriter $objWriter XML Writer
1142
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
1143
     * @param bool $includeCharts Flag indicating if we should include drawing details for charts
1144
     */
1145 73
    private function writeDrawings(XMLWriter $objWriter = null, PhpspreadsheetWorksheet $pSheet = null, $includeCharts = false)
1146
    {
1147 73
        $chartCount = ($includeCharts) ? $pSheet->getChartCollection()->count() : 0;
1 ignored issue
show
Bug introduced by
The method getChartCollection() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1147
        $chartCount = ($includeCharts) ? $pSheet->/** @scrutinizer ignore-call */ getChartCollection()->count() : 0;

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1148
        // If sheet contains drawings, add the relationships
1149 73
        if (($pSheet->getDrawingCollection()->count() > 0) ||
1150 73
            ($chartCount > 0)) {
1151 22
            $objWriter->startElement('drawing');
1 ignored issue
show
Bug introduced by
The method startElement() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1151
            $objWriter->/** @scrutinizer ignore-call */ 
1152
                        startElement('drawing');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1152 22
            $objWriter->writeAttribute('r:id', 'rId1');
1153 22
            $objWriter->endElement();
1154
        }
1155 73
    }
1156
1157
    /**
1158
     * Write LegacyDrawing.
1159
     *
1160
     * @param XMLWriter $objWriter XML Writer
1161
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
1162
     */
1163 73
    private function writeLegacyDrawing(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
1164
    {
1165
        // If sheet contains comments, add the relationships
1166 73
        if (count($pSheet->getComments()) > 0) {
1167 9
            $objWriter->startElement('legacyDrawing');
1168 9
            $objWriter->writeAttribute('r:id', 'rId_comments_vml1');
1169 9
            $objWriter->endElement();
1170
        }
1171 73
    }
1172
1173
    /**
1174
     * Write LegacyDrawingHF.
1175
     *
1176
     * @param XMLWriter $objWriter XML Writer
1177
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
1178
     */
1179 73
    private function writeLegacyDrawingHF(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
1180
    {
1181
        // If sheet contains images, add the relationships
1182 73
        if (count($pSheet->getHeaderFooter()->getImages()) > 0) {
1183 1
            $objWriter->startElement('legacyDrawingHF');
1184 1
            $objWriter->writeAttribute('r:id', 'rId_headerfooter_vml1');
1185 1
            $objWriter->endElement();
1186
        }
1187 73
    }
1188
}
1189