Completed
Push — develop ( e1f81f...539a89 )
by Adrien
16:11
created

Worksheet::writeMarginBottom()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 15
Ratio 100 %

Importance

Changes 0
Metric Value
cc 2
eloc 9
nc 2
nop 0
dl 15
loc 15
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace PhpSpreadsheet\Writer\Excel5;
4
5
/**
6
 * \PhpSpreadsheet\Writer\Excel5\Worksheet
7
 *
8
 * Copyright (c) 2006 - 2015 PhpSpreadsheet
9
 *
10
 * This library is free software; you can redistribute it and/or
11
 * modify it under the terms of the GNU Lesser General Public
12
 * License as published by the Free Software Foundation; either
13
 * version 2.1 of the License, or (at your option) any later version.
14
 *
15
 * This library is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
 * Lesser General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Lesser General Public
21
 * License along with this library; if not, write to the Free Software
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23
 *
24
 * @category   PhpSpreadsheet
25
 * @copyright  Copyright (c) 2006 - 2015 PhpSpreadsheet (https://github.com/PHPOffice/PhpSpreadsheet)
26
 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
27
 * @version    ##VERSION##, ##DATE##
28
 */
29
30
// Original file header of PEAR::Spreadsheet_Excel_Writer_Worksheet (used as the base for this class):
31
// -----------------------------------------------------------------------------------------
32
// /*
33
// *  Module written/ported by Xavier Noguer <[email protected]>
34
// *
35
// *  The majority of this is _NOT_ my code.  I simply ported it from the
36
// *  PERL Spreadsheet::WriteExcel module.
37
// *
38
// *  The author of the Spreadsheet::WriteExcel module is John McNamara
39
// *  <[email protected]>
40
// *
41
// *  I _DO_ maintain this code, and John McNamara has nothing to do with the
42
// *  porting of this code to PHP.  Any questions directly related to this
43
// *  class library should be directed to me.
44
// *
45
// *  License Information:
46
// *
47
// *    Spreadsheet_Excel_Writer:  A library for generating Excel Spreadsheets
48
// *    Copyright (c) 2002-2003 Xavier Noguer [email protected]
49
// *
50
// *    This library is free software; you can redistribute it and/or
51
// *    modify it under the terms of the GNU Lesser General Public
52
// *    License as published by the Free Software Foundation; either
53
// *    version 2.1 of the License, or (at your option) any later version.
54
// *
55
// *    This library is distributed in the hope that it will be useful,
56
// *    but WITHOUT ANY WARRANTY; without even the implied warranty of
57
// *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
58
// *    Lesser General Public License for more details.
59
// *
60
// *    You should have received a copy of the GNU Lesser General Public
61
// *    License along with this library; if not, write to the Free Software
62
// *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
63
// */
64
class Worksheet extends BIFFwriter
65
{
66
    /**
67
     * Formula parser
68
     *
69
     * @var \PhpSpreadsheet\Writer\Excel5\Parser
70
     */
71
    private $parser;
72
73
    /**
74
     * Maximum number of characters for a string (LABEL record in BIFF5)
75
     * @var integer
76
     */
77
    private $xlsStringMaxLength;
78
79
    /**
80
     * Array containing format information for columns
81
     * @var array
82
     */
83
    private $columnInfo;
84
85
    /**
86
     * Array containing the selected area for the worksheet
87
     * @var array
88
     */
89
    private $selection;
90
91
    /**
92
     * The active pane for the worksheet
93
     * @var integer
94
     */
95
    private $activePane;
96
97
    /**
98
     * Whether to use outline.
99
     * @var integer
100
     */
101
    private $outlineOn;
102
103
    /**
104
     * Auto outline styles.
105
     * @var bool
106
     */
107
    private $outlineStyle;
108
109
    /**
110
     * Whether to have outline summary below.
111
     * @var bool
112
     */
113
    private $outlineBelow;
114
115
    /**
116
     * Whether to have outline summary at the right.
117
     * @var bool
118
     */
119
    private $outlineRight;
120
121
    /**
122
     * Reference to the total number of strings in the workbook
123
     * @var integer
124
     */
125
    private $stringTotal;
126
127
    /**
128
     * Reference to the number of unique strings in the workbook
129
     * @var integer
130
     */
131
    private $stringUnique;
132
133
    /**
134
     * Reference to the array containing all the unique strings in the workbook
135
     * @var array
136
     */
137
    private $stringTable;
138
139
    /**
140
     * Color cache
141
     */
142
    private $colors;
143
144
    /**
145
     * Index of first used row (at least 0)
146
     * @var int
147
     */
148
    private $firstRowIndex;
149
150
    /**
151
     * Index of last used row. (no used rows means -1)
152
     * @var int
153
     */
154
    private $lastRowIndex;
155
156
    /**
157
     * Index of first used column (at least 0)
158
     * @var int
159
     */
160
    private $firstColumnIndex;
161
162
    /**
163
     * Index of last used column (no used columns means -1)
164
     * @var int
165
     */
166
    private $lastColumnIndex;
167
168
    /**
169
     * Sheet object
170
     * @var \PhpSpreadsheet\Worksheet
171
     */
172
    public $phpSheet;
173
174
    /**
175
     * Count cell style Xfs
176
     *
177
     * @var int
178
     */
179
    private $countCellStyleXfs;
180
181
    /**
182
     * Escher object corresponding to MSODRAWING
183
     *
184
     * @var \PhpSpreadsheet\Shared\Escher
185
     */
186
    private $escher;
187
188
    /**
189
     * Array of font hashes associated to FONT records index
190
     *
191
     * @var array
192
     */
193
    public $fontHashIndex;
194
195
    /**
196
     * Constructor
197
     *
198
     * @param int        &$str_total        Total number of strings
199
     * @param int        &$str_unique    Total number of unique strings
200
     * @param array        &$str_table        String Table
201
     * @param array        &$colors        Colour Table
202
     * @param mixed        $parser            The formula parser created for the Workbook
203
     * @param boolean    $preCalculateFormulas    Flag indicating whether formulas should be calculated or just written
204
     * @param string    $phpSheet        The worksheet to write
205
     * @param \PhpSpreadsheet\Worksheet $phpSheet
206
     */
207
    public function __construct(&$str_total, &$str_unique, &$str_table, &$colors, $parser, $preCalculateFormulas, $phpSheet)
208
    {
209
        // It needs to call its parent's constructor explicitly
210
        parent::__construct();
211
212
        // change BIFFwriter limit for CONTINUE records
213
//        $this->_limit = 8224;
214
215
216
        $this->_preCalculateFormulas = $preCalculateFormulas;
0 ignored issues
show
Bug introduced by
The property _preCalculateFormulas does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
217
        $this->stringTotal        = &$str_total;
218
        $this->stringUnique        = &$str_unique;
219
        $this->stringTable        = &$str_table;
220
        $this->colors            = &$colors;
221
        $this->parser            = $parser;
222
223
        $this->phpSheet = $phpSheet;
0 ignored issues
show
Documentation Bug introduced by
It seems like $phpSheet of type string is incompatible with the declared type object<PhpSpreadsheet\Worksheet> of property $phpSheet.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
224
225
        //$this->ext_sheets        = array();
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% 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...
226
        //$this->offset            = 0;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% 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...
227
        $this->xlsStringMaxLength = 255;
228
        $this->columnInfo  = array();
229
        $this->selection   = array(0,0,0,0);
230
        $this->activePane  = 3;
231
232
        $this->_print_headers = 0;
0 ignored issues
show
Bug introduced by
The property _print_headers does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
233
234
        $this->outlineStyle  = 0;
0 ignored issues
show
Documentation Bug introduced by
The property $outlineStyle was declared of type boolean, but 0 is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
235
        $this->outlineBelow  = 1;
0 ignored issues
show
Documentation Bug introduced by
The property $outlineBelow was declared of type boolean, but 1 is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
236
        $this->outlineRight  = 1;
0 ignored issues
show
Documentation Bug introduced by
The property $outlineRight was declared of type boolean, but 1 is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
237
        $this->outlineOn     = 1;
238
239
        $this->fontHashIndex = array();
240
241
        // calculate values for DIMENSIONS record
242
        $minR = 1;
0 ignored issues
show
Unused Code introduced by
$minR is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
243
        $minC = 'A';
244
245
        $maxR  = $this->phpSheet->getHighestRow();
0 ignored issues
show
Bug introduced by
The method getHighestRow cannot be called on $this->phpSheet (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
246
        $maxC = $this->phpSheet->getHighestColumn();
0 ignored issues
show
Bug introduced by
The method getHighestColumn cannot be called on $this->phpSheet (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
247
248
        // Determine lowest and highest column and row
249
//        $this->firstRowIndex = ($minR > 65535) ? 65535 : $minR;
250
        $this->lastRowIndex = ($maxR > 65535) ? 65535 : $maxR ;
251
252
        $this->firstColumnIndex = \PhpSpreadsheet\Cell::columnIndexFromString($minC);
253
        $this->lastColumnIndex  = \PhpSpreadsheet\Cell::columnIndexFromString($maxC);
254
255
//        if ($this->firstColumnIndex > 255) $this->firstColumnIndex = 255;
0 ignored issues
show
Unused Code Comprehensibility introduced by
48% 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...
256
        if ($this->lastColumnIndex > 255) {
257
            $this->lastColumnIndex = 255;
258
        }
259
260
        $this->countCellStyleXfs = count($phpSheet->getParent()->getCellStyleXfCollection());
0 ignored issues
show
Bug introduced by
The method getParent cannot be called on $phpSheet (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
261
    }
262
263
    /**
264
     * Add data to the beginning of the workbook (note the reverse order)
265
     * and to the end of the workbook.
266
     *
267
     * @access public
268
     * @see \PhpSpreadsheet\Writer\Excel5\Workbook::storeWorkbook()
269
     */
270
    public function close()
271
    {
272
        $phpSheet = $this->phpSheet;
273
274
        $num_sheets = $phpSheet->getParent()->getSheetCount();
0 ignored issues
show
Unused Code introduced by
$num_sheets is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
275
276
        // Write BOF record
277
        $this->storeBof(0x0010);
278
279
        // Write PRINTHEADERS
280
        $this->writePrintHeaders();
281
282
        // Write PRINTGRIDLINES
283
        $this->writePrintGridlines();
284
285
        // Write GRIDSET
286
        $this->writeGridset();
287
288
        // Calculate column widths
289
        $phpSheet->calculateColumnWidths();
290
291
        // Column dimensions
292
        if (($defaultWidth = $phpSheet->getDefaultColumnDimension()->getWidth()) < 0) {
293
            $defaultWidth = \PhpSpreadsheet\Shared\Font::getDefaultColumnWidthByFont($phpSheet->getParent()->getDefaultStyle()->getFont());
294
        }
295
296
        $columnDimensions = $phpSheet->getColumnDimensions();
297
        $maxCol = $this->lastColumnIndex -1;
298
        for ($i = 0; $i <= $maxCol; ++$i) {
299
            $hidden = 0;
300
            $level = 0;
301
            $xfIndex = 15; // there are 15 cell style Xfs
302
303
            $width = $defaultWidth;
304
305
            $columnLetter = \PhpSpreadsheet\Cell::stringFromColumnIndex($i);
306
            if (isset($columnDimensions[$columnLetter])) {
307
                $columnDimension = $columnDimensions[$columnLetter];
308
                if ($columnDimension->getWidth() >= 0) {
309
                    $width = $columnDimension->getWidth();
310
                }
311
                $hidden = $columnDimension->getVisible() ? 0 : 1;
312
                $level = $columnDimension->getOutlineLevel();
313
                $xfIndex = $columnDimension->getXfIndex() + 15; // there are 15 cell style Xfs
314
            }
315
316
            // Components of columnInfo:
317
            // $firstcol first column on the range
318
            // $lastcol  last column on the range
319
            // $width    width to set
320
            // $xfIndex  The optional cell style Xf index to apply to the columns
321
            // $hidden   The optional hidden atribute
322
            // $level    The optional outline level
323
            $this->columnInfo[] = array($i, $i, $width, $xfIndex, $hidden, $level);
324
        }
325
326
        // Write GUTS
327
        $this->writeGuts();
328
329
        // Write DEFAULTROWHEIGHT
330
        $this->writeDefaultRowHeight();
331
        // Write WSBOOL
332
        $this->writeWsbool();
333
        // Write horizontal and vertical page breaks
334
        $this->writeBreaks();
335
        // Write page header
336
        $this->writeHeader();
337
        // Write page footer
338
        $this->writeFooter();
339
        // Write page horizontal centering
340
        $this->writeHcenter();
341
        // Write page vertical centering
342
        $this->writeVcenter();
343
        // Write left margin
344
        $this->writeMarginLeft();
345
        // Write right margin
346
        $this->writeMarginRight();
347
        // Write top margin
348
        $this->writeMarginTop();
349
        // Write bottom margin
350
        $this->writeMarginBottom();
351
        // Write page setup
352
        $this->writeSetup();
353
        // Write sheet protection
354
        $this->writeProtect();
355
        // Write SCENPROTECT
356
        $this->writeScenProtect();
357
        // Write OBJECTPROTECT
358
        $this->writeObjectProtect();
359
        // Write sheet password
360
        $this->writePassword();
361
        // Write DEFCOLWIDTH record
362
        $this->writeDefcol();
363
364
        // Write the COLINFO records if they exist
365
        if (!empty($this->columnInfo)) {
366
            $colcount = count($this->columnInfo);
367
            for ($i = 0; $i < $colcount; ++$i) {
368
                $this->writeColinfo($this->columnInfo[$i]);
369
            }
370
        }
371
        $autoFilterRange = $phpSheet->getAutoFilter()->getRange();
372
        if (!empty($autoFilterRange)) {
373
            // Write AUTOFILTERINFO
374
            $this->writeAutoFilterInfo();
375
        }
376
377
        // Write sheet dimensions
378
        $this->writeDimensions();
379
380
        // Row dimensions
381
        foreach ($phpSheet->getRowDimensions() as $rowDimension) {
382
            $xfIndex = $rowDimension->getXfIndex() + 15; // there are 15 cellXfs
383
            $this->writeRow($rowDimension->getRowIndex() - 1, $rowDimension->getRowHeight(), $xfIndex, ($rowDimension->getVisible() ? '0' : '1'), $rowDimension->getOutlineLevel());
0 ignored issues
show
Documentation introduced by
$rowDimension->getVisible() ? '0' : '1' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
384
        }
385
386
        // Write Cells
387
        foreach ($phpSheet->getCellCollection() as $cellID) {
388
            $cell = $phpSheet->getCell($cellID);
389
            $row = $cell->getRow() - 1;
390
            $column = \PhpSpreadsheet\Cell::columnIndexFromString($cell->getColumn()) - 1;
391
392
            // Don't break Excel!
393
//            if ($row + 1 > 65536 or $column + 1 > 256) {
394
            if ($row > 65535 || $column > 255) {
395
                break;
396
            }
397
398
            // Write cell value
399
            $xfIndex = $cell->getXfIndex() + 15; // there are 15 cell style Xfs
400
401
            $cVal = $cell->getValue();
402
            if ($cVal instanceof \PhpSpreadsheet\RichText) {
403
                // $this->writeString($row, $column, $cVal->getPlainText(), $xfIndex);
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% 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...
404
                $arrcRun = array();
405
                $str_len = \PhpSpreadsheet\Shared\StringHelper::countCharacters($cVal->getPlainText(), 'UTF-8');
0 ignored issues
show
Unused Code introduced by
$str_len is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
406
                $str_pos = 0;
407
                $elements = $cVal->getRichTextElements();
408
                foreach ($elements as $element) {
409
                    // FONT Index
410
                    if ($element instanceof \PhpSpreadsheet\RichText\Run) {
411
                        $str_fontidx = $this->fontHashIndex[$element->getFont()->getHashCode()];
412
                    } else {
413
                        $str_fontidx = 0;
414
                    }
415
                    $arrcRun[] = array('strlen' => $str_pos, 'fontidx' => $str_fontidx);
416
                    // Position FROM
417
                    $str_pos += \PhpSpreadsheet\Shared\StringHelper::countCharacters($element->getText(), 'UTF-8');
418
                }
419
                $this->writeRichTextString($row, $column, $cVal->getPlainText(), $xfIndex, $arrcRun);
420
            } else {
421
                switch ($cell->getDatatype()) {
422
                    case \PhpSpreadsheet\Cell\DataType::TYPE_STRING:
423
                    case \PhpSpreadsheet\Cell\DataType::TYPE_NULL:
424
                        if ($cVal === '' || $cVal === null) {
425
                            $this->writeBlank($row, $column, $xfIndex);
426
                        } else {
427
                            $this->writeString($row, $column, $cVal, $xfIndex);
428
                        }
429
                        break;
430
431
                    case \PhpSpreadsheet\Cell\DataType::TYPE_NUMERIC:
432
                        $this->writeNumber($row, $column, $cVal, $xfIndex);
433
                        break;
434
435
                    case \PhpSpreadsheet\Cell\DataType::TYPE_FORMULA:
436
                        $calculatedValue = $this->_preCalculateFormulas ?
437
                            $cell->getCalculatedValue() : null;
438
                        $this->writeFormula($row, $column, $cVal, $xfIndex, $calculatedValue);
439
                        break;
440
441
                    case \PhpSpreadsheet\Cell\DataType::TYPE_BOOL:
442
                        $this->writeBoolErr($row, $column, $cVal, 0, $xfIndex);
0 ignored issues
show
Documentation introduced by
0 is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
443
                        break;
444
445
                    case \PhpSpreadsheet\Cell\DataType::TYPE_ERROR:
446
                        $this->writeBoolErr($row, $column, self::mapErrorCode($cVal), 1, $xfIndex);
0 ignored issues
show
Documentation introduced by
1 is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
447
                        break;
448
                }
449
            }
450
        }
451
452
        // Append
453
        $this->writeMsoDrawing();
454
455
        // Write WINDOW2 record
456
        $this->writeWindow2();
457
458
        // Write PLV record
459
        $this->writePageLayoutView();
460
461
        // Write ZOOM record
462
        $this->writeZoom();
463
        if ($phpSheet->getFreezePane()) {
464
            $this->writePanes();
465
        }
466
467
        // Write SELECTION record
468
        $this->writeSelection();
469
470
        // Write MergedCellsTable Record
471
        $this->writeMergedCells();
472
473
        // Hyperlinks
474
        foreach ($phpSheet->getHyperLinkCollection() as $coordinate => $hyperlink) {
475
            list($column, $row) = \PhpSpreadsheet\Cell::coordinateFromString($coordinate);
476
477
            $url = $hyperlink->getUrl();
478
479
            if (strpos($url, 'sheet://') !== false) {
480
                // internal to current workbook
481
                $url = str_replace('sheet://', 'internal:', $url);
482
            } elseif (preg_match('/^(http:|https:|ftp:|mailto:)/', $url)) {
0 ignored issues
show
Unused Code introduced by
This elseif statement is empty, and could be removed.

This check looks for the bodies of elseif statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These elseif bodies can be removed. If you have an empty elseif but statements in the else branch, consider inverting the condition.

Loading history...
483
                // URL
484
                // $url = $url;
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% 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...
485
            } else {
486
                // external (local file)
487
                $url = 'external:' . $url;
488
            }
489
490
            $this->writeUrl($row - 1, \PhpSpreadsheet\Cell::columnIndexFromString($column) - 1, $url);
491
        }
492
493
        $this->writeDataValidity();
494
        $this->writeSheetLayout();
495
496
        // Write SHEETPROTECTION record
497
        $this->writeSheetProtection();
498
        $this->writeRangeProtection();
499
500
        $arrConditionalStyles = $phpSheet->getConditionalStylesCollection();
501
        if (!empty($arrConditionalStyles)) {
502
            $arrConditional = array();
503
            // @todo CFRule & CFHeader
504
            // Write CFHEADER record
505
            $this->writeCFHeader();
506
            // Write ConditionalFormattingTable records
507
            foreach ($arrConditionalStyles as $cellCoordinate => $conditionalStyles) {
508
                foreach ($conditionalStyles as $conditional) {
509
                    if ($conditional->getConditionType() == \PhpSpreadsheet\Style\Conditional::CONDITION_EXPRESSION
510
                        || $conditional->getConditionType() == \PhpSpreadsheet\Style\Conditional::CONDITION_CELLIS) {
511
                        if (!in_array($conditional->getHashCode(), $arrConditional)) {
512
                            $arrConditional[] = $conditional->getHashCode();
513
                            // Write CFRULE record
514
                            $this->writeCFRule($conditional);
515
                        }
516
                    }
517
                }
518
            }
519
        }
520
521
        $this->storeEof();
522
    }
523
524
    /**
525
     * Write a cell range address in BIFF8
526
     * always fixed range
527
     * See section 2.5.14 in OpenOffice.org's Documentation of the Microsoft Excel File Format
528
     *
529
     * @param string $range E.g. 'A1' or 'A1:B6'
530
     * @return string Binary data
531
     */
532
    private function writeBIFF8CellRangeAddressFixed($range = 'A1')
533
    {
534
        $explodes = explode(':', $range);
535
536
        // extract first cell, e.g. 'A1'
537
        $firstCell = $explodes[0];
538
539
        // extract last cell, e.g. 'B6'
540
        if (count($explodes) == 1) {
541
            $lastCell = $firstCell;
542
        } else {
543
            $lastCell = $explodes[1];
544
        }
545
546
        $firstCellCoordinates = \PhpSpreadsheet\Cell::coordinateFromString($firstCell); // e.g. array(0, 1)
0 ignored issues
show
Unused Code Comprehensibility introduced by
47% 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...
547
        $lastCellCoordinates  = \PhpSpreadsheet\Cell::coordinateFromString($lastCell);  // e.g. array(1, 6)
0 ignored issues
show
Unused Code Comprehensibility introduced by
47% 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...
548
549
        return pack('vvvv', $firstCellCoordinates[1] - 1, $lastCellCoordinates[1] - 1, \PhpSpreadsheet\Cell::columnIndexFromString($firstCellCoordinates[0]) - 1, \PhpSpreadsheet\Cell::columnIndexFromString($lastCellCoordinates[0]) - 1);
550
    }
551
552
    /**
553
     * Retrieves data from memory in one chunk, or from disk in $buffer
554
     * sized chunks.
555
     *
556
     * @return string The data
557
     */
558
    public function getData()
559
    {
560
        $buffer = 4096;
0 ignored issues
show
Unused Code introduced by
$buffer is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
561
562
        // Return data stored in memory
563
        if (isset($this->_data)) {
564
            $tmp   = $this->_data;
565
            unset($this->_data);
566
            return $tmp;
567
        }
568
        // No data to return
569
        return false;
570
    }
571
572
    /**
573
     * Set the option to print the row and column headers on the printed page.
574
     *
575
     * @access public
576
     * @param integer $print Whether to print the headers or not. Defaults to 1 (print).
577
     */
578
    public function printRowColHeaders($print = 1)
579
    {
580
        $this->_print_headers = $print;
581
    }
582
583
    /**
584
     * This method sets the properties for outlining and grouping. The defaults
585
     * correspond to Excel's defaults.
586
     *
587
     * @param bool $visible
588
     * @param bool $symbols_below
589
     * @param bool $symbols_right
590
     * @param bool $auto_style
591
     */
592
    public function setOutline($visible = true, $symbols_below = true, $symbols_right = true, $auto_style = false)
593
    {
594
        $this->outlineOn    = $visible;
0 ignored issues
show
Documentation Bug introduced by
The property $outlineOn was declared of type integer, but $visible is of type boolean. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
595
        $this->outlineBelow = $symbols_below;
596
        $this->outlineRight = $symbols_right;
597
        $this->outlineStyle = $auto_style;
598
599
        // Ensure this is a boolean vale for Window2
600
        if ($this->outlineOn) {
601
            $this->outlineOn = 1;
602
        }
603
    }
604
605
    /**
606
     * Write a double to the specified row and column (zero indexed).
607
     * An integer can be written as a double. Excel will display an
608
     * integer. $format is optional.
609
     *
610
     * Returns  0 : normal termination
611
     *         -2 : row or column out of range
612
     *
613
     * @param integer $row    Zero indexed row
614
     * @param integer $col    Zero indexed column
615
     * @param float   $num    The number to write
616
     * @param mixed   $xfIndex The optional XF format
617
     * @return integer
618
     */
619
    private function writeNumber($row, $col, $num, $xfIndex)
620
    {
621
        $record    = 0x0203;                 // Record identifier
622
        $length    = 0x000E;                 // Number of bytes to follow
623
624
        $header        = pack("vv", $record, $length);
625
        $data        = pack("vvv", $row, $col, $xfIndex);
626
        $xl_double    = pack("d", $num);
627
        if (self::getByteOrder()) { // if it's Big Endian
628
            $xl_double = strrev($xl_double);
629
        }
630
631
        $this->append($header.$data.$xl_double);
632
        return(0);
633
    }
634
635
    /**
636
     * Write a LABELSST record or a LABEL record. Which one depends on BIFF version
637
     *
638
     * @param int $row Row index (0-based)
639
     * @param int $col Column index (0-based)
640
     * @param string $str The string
641
     * @param int $xfIndex Index to XF record
642
     */
643
    private function writeString($row, $col, $str, $xfIndex)
644
    {
645
        $this->writeLabelSst($row, $col, $str, $xfIndex);
646
    }
647
648
    /**
649
     * Write a LABELSST record or a LABEL record. Which one depends on BIFF version
650
     * It differs from writeString by the writing of rich text strings.
651
     * @param int $row Row index (0-based)
652
     * @param int $col Column index (0-based)
653
     * @param string $str The string
654
     * @param mixed   $xfIndex The XF format index for the cell
655
     * @param array $arrcRun Index to Font record and characters beginning
656
     */
657 View Code Duplication
    private function writeRichTextString($row, $col, $str, $xfIndex, $arrcRun)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
658
    {
659
        $record    = 0x00FD;                   // Record identifier
660
        $length    = 0x000A;                   // Bytes to follow
661
        $str = \PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeShort($str, $arrcRun);
662
663
        /* check if string is already present */
664
        if (!isset($this->stringTable[$str])) {
665
            $this->stringTable[$str] = $this->stringUnique++;
666
        }
667
        $this->stringTotal++;
668
669
        $header    = pack('vv', $record, $length);
670
        $data    = pack('vvvV', $row, $col, $xfIndex, $this->stringTable[$str]);
671
        $this->append($header.$data);
672
    }
673
674
    /**
675
     * Write a string to the specified row and column (zero indexed).
676
     * NOTE: there is an Excel 5 defined limit of 255 characters.
677
     * $format is optional.
678
     * Returns  0 : normal termination
679
     *         -2 : row or column out of range
680
     *         -3 : long string truncated to 255 chars
681
     *
682
     * @access public
683
     * @param integer $row    Zero indexed row
684
     * @param integer $col    Zero indexed column
685
     * @param string  $str    The string to write
686
     * @param mixed   $xfIndex The XF format index for the cell
687
     * @return integer
688
     */
689
    private function writeLabel($row, $col, $str, $xfIndex)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
690
    {
691
        $strlen    = strlen($str);
692
        $record    = 0x0204;                   // Record identifier
693
        $length    = 0x0008 + $strlen;         // Bytes to follow
694
695
        $str_error = 0;
696
697
        if ($strlen > $this->xlsStringMaxLength) { // LABEL must be < 255 chars
698
            $str    = substr($str, 0, $this->xlsStringMaxLength);
699
            $length    = 0x0008 + $this->xlsStringMaxLength;
700
            $strlen    = $this->xlsStringMaxLength;
701
            $str_error = -3;
702
        }
703
704
        $header    = pack("vv", $record, $length);
705
        $data    = pack("vvvv", $row, $col, $xfIndex, $strlen);
706
        $this->append($header . $data . $str);
707
        return($str_error);
708
    }
709
710
    /**
711
     * Write a string to the specified row and column (zero indexed).
712
     * This is the BIFF8 version (no 255 chars limit).
713
     * $format is optional.
714
     * Returns  0 : normal termination
715
     *         -2 : row or column out of range
716
     *         -3 : long string truncated to 255 chars
717
     *
718
     * @access public
719
     * @param integer $row    Zero indexed row
720
     * @param integer $col    Zero indexed column
721
     * @param string  $str    The string to write
722
     * @param mixed   $xfIndex The XF format index for the cell
723
     * @return integer
724
     */
725 View Code Duplication
    private function writeLabelSst($row, $col, $str, $xfIndex)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
726
    {
727
        $record    = 0x00FD;                   // Record identifier
728
        $length    = 0x000A;                   // Bytes to follow
729
730
        $str = \PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($str);
731
732
        /* check if string is already present */
733
        if (!isset($this->stringTable[$str])) {
734
            $this->stringTable[$str] = $this->stringUnique++;
735
        }
736
        $this->stringTotal++;
737
738
        $header    = pack('vv', $record, $length);
739
        $data    = pack('vvvV', $row, $col, $xfIndex, $this->stringTable[$str]);
740
        $this->append($header.$data);
741
    }
742
743
    /**
744
     * Writes a note associated with the cell given by the row and column.
745
     * NOTE records don't have a length limit.
746
     *
747
     * @param integer $row    Zero indexed row
748
     * @param integer $col    Zero indexed column
749
     * @param string  $note   The note to write
750
     */
751
    private function writeNote($row, $col, $note)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
752
    {
753
        $note_length    = strlen($note);
754
        $record            = 0x001C;            // Record identifier
755
        $max_length        = 2048;                // Maximun length for a NOTE record
756
757
        // Length for this record is no more than 2048 + 6
758
        $length    = 0x0006 + min($note_length, 2048);
759
        $header    = pack("vv", $record, $length);
760
        $data    = pack("vvv", $row, $col, $note_length);
761
        $this->append($header . $data . substr($note, 0, 2048));
762
763
        for ($i = $max_length; $i < $note_length; $i += $max_length) {
764
            $chunk  = substr($note, $i, $max_length);
765
            $length = 0x0006 + strlen($chunk);
766
            $header = pack("vv", $record, $length);
767
            $data   = pack("vvv", -1, 0, strlen($chunk));
768
            $this->append($header.$data.$chunk);
769
        }
770
        return(0);
771
    }
772
773
    /**
774
     * Write a blank cell to the specified row and column (zero indexed).
775
     * A blank cell is used to specify formatting without adding a string
776
     * or a number.
777
     *
778
     * A blank cell without a format serves no purpose. Therefore, we don't write
779
     * a BLANK record unless a format is specified.
780
     *
781
     * Returns  0 : normal termination (including no format)
782
     *         -1 : insufficient number of arguments
783
     *         -2 : row or column out of range
784
     *
785
     * @param integer $row    Zero indexed row
786
     * @param integer $col    Zero indexed column
787
     * @param mixed   $xfIndex The XF format index
788
     */
789 View Code Duplication
    public function writeBlank($row, $col, $xfIndex)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
790
    {
791
        $record    = 0x0201;                 // Record identifier
792
        $length    = 0x0006;                 // Number of bytes to follow
793
794
        $header    = pack("vv", $record, $length);
795
        $data      = pack("vvv", $row, $col, $xfIndex);
796
        $this->append($header . $data);
797
        return 0;
798
    }
799
800
    /**
801
     * Write a boolean or an error type to the specified row and column (zero indexed)
802
     *
803
     * @param int $row Row index (0-based)
804
     * @param int $col Column index (0-based)
805
     * @param int $value
806
     * @param boolean $isError Error or Boolean?
807
     * @param int $xfIndex
808
     */
809 View Code Duplication
    private function writeBoolErr($row, $col, $value, $isError, $xfIndex)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
810
    {
811
        $record = 0x0205;
812
        $length = 8;
813
814
        $header    = pack("vv", $record, $length);
815
        $data      = pack("vvvCC", $row, $col, $xfIndex, $value, $isError);
816
        $this->append($header . $data);
817
        return 0;
818
    }
819
820
    /**
821
     * Write a formula to the specified row and column (zero indexed).
822
     * The textual representation of the formula is passed to the parser in
823
     * Parser.php which returns a packed binary string.
824
     *
825
     * Returns  0 : normal termination
826
     *         -1 : formula errors (bad formula)
827
     *         -2 : row or column out of range
828
     *
829
     * @param integer $row     Zero indexed row
830
     * @param integer $col     Zero indexed column
831
     * @param string  $formula The formula text string
832
     * @param mixed   $xfIndex  The XF format index
833
     * @param mixed   $calculatedValue  Calculated value
834
     * @return integer
835
     */
836
    private function writeFormula($row, $col, $formula, $xfIndex, $calculatedValue)
837
    {
838
        $record    = 0x0006;     // Record identifier
839
840
        // Initialize possible additional value for STRING record that should be written after the FORMULA record?
841
        $stringValue = null;
842
843
        // calculated value
844
        if (isset($calculatedValue)) {
845
            // Since we can't yet get the data type of the calculated value,
846
            // we use best effort to determine data type
847
            if (is_bool($calculatedValue)) {
848
                // Boolean value
849
                $num = pack('CCCvCv', 0x01, 0x00, (int)$calculatedValue, 0x00, 0x00, 0xFFFF);
850
            } elseif (is_int($calculatedValue) || is_float($calculatedValue)) {
851
                // Numeric value
852
                $num = pack('d', $calculatedValue);
853
            } elseif (is_string($calculatedValue)) {
854
                if (array_key_exists($calculatedValue, \PhpSpreadsheet\Cell\DataType::getErrorCodes())) {
855
                    // Error value
856
                    $num = pack('CCCvCv', 0x02, 0x00, self::mapErrorCode($calculatedValue), 0x00, 0x00, 0xFFFF);
857
                } elseif ($calculatedValue === '') {
858
                    // Empty string (and BIFF8)
0 ignored issues
show
Unused Code Comprehensibility introduced by
40% 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...
859
                    $num = pack('CCCvCv', 0x03, 0x00, 0x00, 0x00, 0x00, 0xFFFF);
860
                } else {
861
                    // Non-empty string value (or empty string BIFF5)
862
                    $stringValue = $calculatedValue;
863
                    $num = pack('CCCvCv', 0x00, 0x00, 0x00, 0x00, 0x00, 0xFFFF);
864
                }
865
            } else {
866
                // We are really not supposed to reach here
867
                $num = pack('d', 0x00);
868
            }
869
        } else {
870
            $num = pack('d', 0x00);
871
        }
872
873
        $grbit        = 0x03;                // Option flags
874
        $unknown    = 0x0000;            // Must be zero
875
876
        // Strip the '=' or '@' sign at the beginning of the formula string
877
        if ($formula{0} == '=') {
878
            $formula = substr($formula, 1);
879
        } else {
880
            // Error handling
881
            $this->writeString($row, $col, 'Unrecognised character for formula');
0 ignored issues
show
Bug introduced by
The call to writeString() misses a required argument $xfIndex.

This check looks for function calls that miss required arguments.

Loading history...
882
            return -1;
883
        }
884
885
        // Parse the formula using the parser in Parser.php
886
        try {
887
            $error = $this->parser->parse($formula);
0 ignored issues
show
Unused Code introduced by
$error is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
888
            $formula = $this->parser->toReversePolish();
889
890
            $formlen    = strlen($formula);    // Length of the binary string
891
            $length     = 0x16 + $formlen;     // Length of the record data
892
893
            $header    = pack("vv", $record, $length);
894
895
            $data      = pack("vvv", $row, $col, $xfIndex)
896
                        . $num
897
                        . pack("vVv", $grbit, $unknown, $formlen);
898
            $this->append($header . $data . $formula);
899
900
            // Append also a STRING record if necessary
901
            if ($stringValue !== null) {
902
                $this->writeStringRecord($stringValue);
903
            }
904
            return 0;
905
        } catch (\PhpSpreadsheet\Exception $e) {
906
            // do nothing
907
        }
908
    }
909
910
    /**
911
     * Write a STRING record. This
912
     *
913
     * @param string $stringValue
914
     */
915 View Code Duplication
    private function writeStringRecord($stringValue)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
916
    {
917
        $record = 0x0207;     // Record identifier
918
        $data = \PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($stringValue);
919
920
        $length = strlen($data);
921
        $header = pack('vv', $record, $length);
922
923
        $this->append($header . $data);
924
    }
925
926
    /**
927
     * Write a hyperlink.
928
     * This is comprised of two elements: the visible label and
929
     * the invisible link. The visible label is the same as the link unless an
930
     * alternative string is specified. The label is written using the
931
     * writeString() method. Therefore the 255 characters string limit applies.
932
     * $string and $format are optional.
933
     *
934
     * The hyperlink can be to a http, ftp, mail, internal sheet (not yet), or external
935
     * directory url.
936
     *
937
     * Returns  0 : normal termination
938
     *         -2 : row or column out of range
939
     *         -3 : long string truncated to 255 chars
940
     *
941
     * @param integer $row    Row
942
     * @param integer $col    Column
943
     * @param string  $url    URL string
944
     * @return integer
945
     */
946
    private function writeUrl($row, $col, $url)
947
    {
948
        // Add start row and col to arg list
949
        return($this->writeUrlRange($row, $col, $row, $col, $url));
950
    }
951
952
    /**
953
     * This is the more general form of writeUrl(). It allows a hyperlink to be
954
     * written to a range of cells. This function also decides the type of hyperlink
955
     * to be written. These are either, Web (http, ftp, mailto), Internal
956
     * (Sheet1!A1) or external ('c:\temp\foo.xls#Sheet1!A1').
957
     *
958
     * @access private
959
     * @see writeUrl()
960
     * @param integer $row1   Start row
961
     * @param integer $col1   Start column
962
     * @param integer $row2   End row
963
     * @param integer $col2   End column
964
     * @param string  $url    URL string
965
     * @return integer
966
     */
967
    public function writeUrlRange($row1, $col1, $row2, $col2, $url)
968
    {
969
        // Check for internal/external sheet links or default to web link
970
        if (preg_match('[^internal:]', $url)) {
971
            return($this->writeUrlInternal($row1, $col1, $row2, $col2, $url));
972
        }
973
        if (preg_match('[^external:]', $url)) {
974
            return($this->writeUrlExternal($row1, $col1, $row2, $col2, $url));
975
        }
976
        return($this->writeUrlWeb($row1, $col1, $row2, $col2, $url));
977
    }
978
979
    /**
980
     * Used to write http, ftp and mailto hyperlinks.
981
     * The link type ($options) is 0x03 is the same as absolute dir ref without
982
     * sheet. However it is differentiated by the $unknown2 data stream.
983
     *
984
     * @access private
985
     * @see writeUrl()
986
     * @param integer $row1   Start row
987
     * @param integer $col1   Start column
988
     * @param integer $row2   End row
989
     * @param integer $col2   End column
990
     * @param string  $url    URL string
991
     * @return integer
992
     */
993
    public function writeUrlWeb($row1, $col1, $row2, $col2, $url)
994
    {
995
        $record      = 0x01B8;                       // Record identifier
996
        $length      = 0x00000;                      // Bytes to follow
0 ignored issues
show
Unused Code introduced by
$length is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
997
998
        // Pack the undocumented parts of the hyperlink stream
999
        $unknown1    = pack("H*", "D0C9EA79F9BACE118C8200AA004BA90B02000000");
1000
        $unknown2    = pack("H*", "E0C9EA79F9BACE118C8200AA004BA90B");
1001
1002
        // Pack the option flags
1003
        $options     = pack("V", 0x03);
1004
1005
        // Convert URL to a null terminated wchar string
1006
        $url         = join("\0", preg_split("''", $url, -1, PREG_SPLIT_NO_EMPTY));
1007
        $url         = $url . "\0\0\0";
1008
1009
        // Pack the length of the URL
1010
        $url_len     = pack("V", strlen($url));
1011
1012
        // Calculate the data length
1013
        $length      = 0x34 + strlen($url);
1014
1015
        // Pack the header data
1016
        $header      = pack("vv", $record, $length);
1017
        $data        = pack("vvvv", $row1, $row2, $col1, $col2);
1018
1019
        // Write the packed data
1020
        $this->append($header . $data .
1021
                       $unknown1 . $options .
1022
                       $unknown2 . $url_len . $url);
1023
        return 0;
1024
    }
1025
1026
    /**
1027
     * Used to write internal reference hyperlinks such as "Sheet1!A1".
1028
     *
1029
     * @access private
1030
     * @see writeUrl()
1031
     * @param integer $row1   Start row
1032
     * @param integer $col1   Start column
1033
     * @param integer $row2   End row
1034
     * @param integer $col2   End column
1035
     * @param string  $url    URL string
1036
     * @return integer
1037
     */
1038
    public function writeUrlInternal($row1, $col1, $row2, $col2, $url)
1039
    {
1040
        $record      = 0x01B8;                       // Record identifier
1041
        $length      = 0x00000;                      // Bytes to follow
0 ignored issues
show
Unused Code introduced by
$length is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1042
1043
        // Strip URL type
1044
        $url = preg_replace('/^internal:/', '', $url);
1045
1046
        // Pack the undocumented parts of the hyperlink stream
1047
        $unknown1    = pack("H*", "D0C9EA79F9BACE118C8200AA004BA90B02000000");
1048
1049
        // Pack the option flags
1050
        $options     = pack("V", 0x08);
1051
1052
        // Convert the URL type and to a null terminated wchar string
1053
        $url .= "\0";
1054
1055
        // character count
1056
        $url_len = \PhpSpreadsheet\Shared\StringHelper::countCharacters($url);
1057
        $url_len = pack('V', $url_len);
1058
1059
        $url = \PhpSpreadsheet\Shared\StringHelper::convertEncoding($url, 'UTF-16LE', 'UTF-8');
1060
1061
        // Calculate the data length
1062
        $length      = 0x24 + strlen($url);
1063
1064
        // Pack the header data
1065
        $header      = pack("vv", $record, $length);
1066
        $data        = pack("vvvv", $row1, $row2, $col1, $col2);
1067
1068
        // Write the packed data
1069
        $this->append($header . $data .
1070
                       $unknown1 . $options .
1071
                       $url_len . $url);
1072
        return 0;
1073
    }
1074
1075
    /**
1076
     * Write links to external directory names such as 'c:\foo.xls',
1077
     * c:\foo.xls#Sheet1!A1', '../../foo.xls'. and '../../foo.xls#Sheet1!A1'.
1078
     *
1079
     * Note: Excel writes some relative links with the $dir_long string. We ignore
1080
     * these cases for the sake of simpler code.
1081
     *
1082
     * @access private
1083
     * @see writeUrl()
1084
     * @param integer $row1   Start row
1085
     * @param integer $col1   Start column
1086
     * @param integer $row2   End row
1087
     * @param integer $col2   End column
1088
     * @param string  $url    URL string
1089
     * @return integer
1090
     */
1091
    public function writeUrlExternal($row1, $col1, $row2, $col2, $url)
1092
    {
1093
        // Network drives are different. We will handle them separately
1094
        // MS/Novell network drives and shares start with \\
1095
        if (preg_match('[^external:\\\\]', $url)) {
1096
            return; //($this->writeUrlExternal_net($row1, $col1, $row2, $col2, $url, $str, $format));
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% 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...
1097
        }
1098
1099
        $record      = 0x01B8;                       // Record identifier
1100
        $length      = 0x00000;                      // Bytes to follow
0 ignored issues
show
Unused Code introduced by
$length is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1101
1102
        // Strip URL type and change Unix dir separator to Dos style (if needed)
1103
        //
1104
        $url = preg_replace('/^external:/', '', $url);
1105
        $url = preg_replace('/\//', "\\", $url);
1106
1107
        // Determine if the link is relative or absolute:
1108
        //   relative if link contains no dir separator, "somefile.xls"
1109
        //   relative if link starts with up-dir, "..\..\somefile.xls"
1110
        //   otherwise, absolute
1111
1112
        $absolute = 0x00; // relative path
1113
        if (preg_match('/^[A-Z]:/', $url)) {
1114
            $absolute = 0x02; // absolute path on Windows, e.g. C:\...
1115
        }
1116
        $link_type               = 0x01 | $absolute;
1117
1118
        // Determine if the link contains a sheet reference and change some of the
1119
        // parameters accordingly.
1120
        // Split the dir name and sheet name (if it exists)
1121
        $dir_long = $url;
1122
        if (preg_match("/\#/", $url)) {
1123
            $link_type |= 0x08;
1124
        }
1125
1126
1127
        // Pack the link type
1128
        $link_type   = pack("V", $link_type);
1129
1130
        // Calculate the up-level dir count e.g.. (..\..\..\ == 3)
1131
        $up_count    = preg_match_all("/\.\.\\\/", $dir_long, $useless);
1132
        $up_count    = pack("v", $up_count);
1133
1134
        // Store the short dos dir name (null terminated)
1135
        $dir_short   = preg_replace("/\.\.\\\/", '', $dir_long) . "\0";
1136
1137
        // Store the long dir name as a wchar string (non-null terminated)
1138
        $dir_long       = $dir_long . "\0";
1139
1140
        // Pack the lengths of the dir strings
1141
        $dir_short_len = pack("V", strlen($dir_short));
1142
        $dir_long_len  = pack("V", strlen($dir_long));
0 ignored issues
show
Unused Code introduced by
$dir_long_len is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1143
        $stream_len    = pack("V", 0); //strlen($dir_long) + 0x06);
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% 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...
1144
1145
        // Pack the undocumented parts of the hyperlink stream
1146
        $unknown1 = pack("H*", 'D0C9EA79F9BACE118C8200AA004BA90B02000000');
1147
        $unknown2 = pack("H*", '0303000000000000C000000000000046');
1148
        $unknown3 = pack("H*", 'FFFFADDE000000000000000000000000000000000000000');
1149
        $unknown4 = pack("v", 0x03);
0 ignored issues
show
Unused Code introduced by
$unknown4 is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1150
1151
        // Pack the main data stream
1152
        $data        = pack("vvvv", $row1, $row2, $col1, $col2) .
1153
                          $unknown1     .
1154
                          $link_type    .
1155
                          $unknown2     .
1156
                          $up_count     .
1157
                          $dir_short_len.
1158
                          $dir_short    .
1159
                          $unknown3     .
1160
                          $stream_len   ;/*.
1161
                          $dir_long_len .
1162
                          $unknown4     .
1163
                          $dir_long     .
1164
                          $sheet_len    .
1165
                          $sheet        ;*/
1166
1167
        // Pack the header data
1168
        $length   = strlen($data);
1169
        $header   = pack("vv", $record, $length);
1170
1171
        // Write the packed data
1172
        $this->append($header. $data);
1173
        return 0;
1174
    }
1175
1176
    /**
1177
     * This method is used to set the height and format for a row.
1178
     *
1179
     * @param integer $row    The row to set
1180
     * @param integer $height Height we are giving to the row.
1181
     *                        Use null to set XF without setting height
1182
     * @param integer $xfIndex  The optional cell style Xf index to apply to the columns
1183
     * @param bool    $hidden The optional hidden attribute
1184
     * @param integer $level  The optional outline level for row, in range [0,7]
1185
     */
1186
    private function writeRow($row, $height, $xfIndex, $hidden = false, $level = 0)
1187
    {
1188
        $record      = 0x0208;               // Record identifier
1189
        $length      = 0x0010;               // Number of bytes to follow
1190
1191
        $colMic      = 0x0000;               // First defined column
1192
        $colMac      = 0x0000;               // Last defined column
1193
        $irwMac      = 0x0000;               // Used by Excel to optimise loading
1194
        $reserved    = 0x0000;               // Reserved
1195
        $grbit       = 0x0000;               // Option flags
1196
        $ixfe        = $xfIndex;
1197
1198
        if ($height < 0) {
1199
            $height = null;
1200
        }
1201
1202
        // Use writeRow($row, null, $XF) to set XF format without setting height
1203
        if ($height != null) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $height of type null|integer against null; this is ambiguous if the integer can be zero. Consider using a strict comparison !== instead.
Loading history...
1204
            $miyRw = $height * 20;  // row height
1205
        } else {
1206
            $miyRw = 0xff;          // default row height is 256
1207
        }
1208
1209
        // Set the options flags. fUnsynced is used to show that the font and row
1210
        // heights are not compatible. This is usually the case for WriteExcel.
1211
        // The collapsed flag 0x10 doesn't seem to be used to indicate that a row
1212
        // is collapsed. Instead it is used to indicate that the previous row is
1213
        // collapsed. The zero height flag, 0x20, is used to collapse a row.
1214
1215
        $grbit |= $level;
1216
        if ($hidden) {
1217
            $grbit |= 0x0030;
1218
        }
1219
        if ($height !== null) {
1220
            $grbit |= 0x0040; // fUnsynced
1221
        }
1222
        if ($xfIndex !== 0xF) {
1223
            $grbit |= 0x0080;
1224
        }
1225
        $grbit |= 0x0100;
1226
1227
        $header   = pack("vv", $record, $length);
1228
        $data     = pack("vvvvvvvv", $row, $colMic, $colMac, $miyRw, $irwMac, $reserved, $grbit, $ixfe);
1229
        $this->append($header.$data);
1230
    }
1231
1232
    /**
1233
     * Writes Excel DIMENSIONS to define the area in which there is data.
1234
     */
1235
    private function writeDimensions()
1236
    {
1237
        $record = 0x0200; // Record identifier
1238
1239
        $length = 0x000E;
1240
        $data = pack('VVvvv', $this->firstRowIndex, $this->lastRowIndex + 1, $this->firstColumnIndex, $this->lastColumnIndex + 1, 0x0000); // reserved
1241
1242
        $header = pack("vv", $record, $length);
1243
        $this->append($header.$data);
1244
    }
1245
1246
    /**
1247
     * Write BIFF record Window2.
1248
     */
1249
    private function writeWindow2()
1250
    {
1251
        $record         = 0x023E;     // Record identifier
1252
        $length         = 0x0012;
1253
1254
        $grbit          = 0x00B6;     // Option flags
0 ignored issues
show
Unused Code introduced by
$grbit is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1255
        $rwTop          = 0x0000;     // Top row visible in window
1256
        $colLeft        = 0x0000;     // Leftmost column visible in window
1257
1258
1259
        // The options flags that comprise $grbit
1260
        $fDspFmla       = 0;                     // 0 - bit
1261
        $fDspGrid       = $this->phpSheet->getShowGridlines() ? 1 : 0; // 1
1262
        $fDspRwCol      = $this->phpSheet->getShowRowColHeaders() ? 1 : 0; // 2
1263
        $fFrozen        = $this->phpSheet->getFreezePane() ? 1 : 0;        // 3
1264
        $fDspZeros      = 1;                     // 4
1265
        $fDefaultHdr    = 1;                     // 5
1266
        $fArabic        = $this->phpSheet->getRightToLeft() ? 1 : 0; // 6
1267
        $fDspGuts       = $this->outlineOn;    // 7
1268
        $fFrozenNoSplit = 0;                     // 0 - bit
1269
        // no support in PhpSpreadsheet for selected sheet, therefore sheet is only selected if it is the active sheet
1270
        $fSelected      = ($this->phpSheet === $this->phpSheet->getParent()->getActiveSheet()) ? 1 : 0;
1271
        $fPaged         = 1;                     // 2
1272
        $fPageBreakPreview = $this->phpSheet->getSheetView()->getView() === \PhpSpreadsheet\Worksheet\SheetView::SHEETVIEW_PAGE_BREAK_PREVIEW;
1273
1274
        $grbit             = $fDspFmla;
1275
        $grbit            |= $fDspGrid       << 1;
1276
        $grbit            |= $fDspRwCol       << 2;
1277
        $grbit            |= $fFrozen           << 3;
1278
        $grbit            |= $fDspZeros       << 4;
1279
        $grbit            |= $fDefaultHdr       << 5;
1280
        $grbit            |= $fArabic           << 6;
1281
        $grbit            |= $fDspGuts       << 7;
1282
        $grbit            |= $fFrozenNoSplit << 8;
1283
        $grbit            |= $fSelected       << 9;
1284
        $grbit            |= $fPaged           << 10;
1285
        $grbit            |= $fPageBreakPreview << 11;
1286
1287
        $header  = pack("vv", $record, $length);
1288
        $data    = pack("vvv", $grbit, $rwTop, $colLeft);
1289
1290
        // FIXME !!!
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% 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...
1291
        $rgbHdr       = 0x0040; // Row/column heading and gridline color index
1292
        $zoom_factor_page_break = ($fPageBreakPreview ? $this->phpSheet->getSheetView()->getZoomScale() : 0x0000);
1293
        $zoom_factor_normal =  $this->phpSheet->getSheetView()->getZoomScaleNormal();
1294
1295
        $data .= pack("vvvvV", $rgbHdr, 0x0000, $zoom_factor_page_break, $zoom_factor_normal, 0x00000000);
1296
1297
        $this->append($header.$data);
1298
    }
1299
1300
    /**
1301
     * Write BIFF record DEFAULTROWHEIGHT.
1302
     */
1303
    private function writeDefaultRowHeight()
1304
    {
1305
        $defaultRowHeight = $this->phpSheet->getDefaultRowDimension()->getRowHeight();
1306
1307
        if ($defaultRowHeight < 0) {
1308
            return;
1309
        }
1310
1311
        // convert to twips
1312
        $defaultRowHeight = (int) 20 * $defaultRowHeight;
1313
1314
        $record   = 0x0225;      // Record identifier
1315
        $length   = 0x0004;      // Number of bytes to follow
1316
1317
        $header   = pack("vv", $record, $length);
1318
        $data     = pack("vv", 1, $defaultRowHeight);
1319
        $this->append($header . $data);
1320
    }
1321
1322
    /**
1323
     * Write BIFF record DEFCOLWIDTH if COLINFO records are in use.
1324
     */
1325
    private function writeDefcol()
1326
    {
1327
        $defaultColWidth = 8;
1328
1329
        $record   = 0x0055;      // Record identifier
1330
        $length   = 0x0002;      // Number of bytes to follow
1331
1332
        $header = pack("vv", $record, $length);
1333
        $data = pack("v", $defaultColWidth);
1334
        $this->append($header . $data);
1335
    }
1336
1337
    /**
1338
     * Write BIFF record COLINFO to define column widths
1339
     *
1340
     * Note: The SDK says the record length is 0x0B but Excel writes a 0x0C
1341
     * length record.
1342
     *
1343
     * @param array $col_array This is the only parameter received and is composed of the following:
1344
     *                0 => First formatted column,
1345
     *                1 => Last formatted column,
1346
     *                2 => Col width (8.43 is Excel default),
1347
     *                3 => The optional XF format of the column,
1348
     *                4 => Option flags.
1349
     *                5 => Optional outline level
1350
     */
1351
    private function writeColinfo($col_array)
1352
    {
1353
        if (isset($col_array[0])) {
1354
            $colFirst = $col_array[0];
1355
        }
1356
        if (isset($col_array[1])) {
1357
            $colLast = $col_array[1];
1358
        }
1359
        if (isset($col_array[2])) {
1360
            $coldx = $col_array[2];
1361
        } else {
1362
            $coldx = 8.43;
1363
        }
1364
        if (isset($col_array[3])) {
1365
            $xfIndex = $col_array[3];
1366
        } else {
1367
            $xfIndex = 15;
1368
        }
1369
        if (isset($col_array[4])) {
1370
            $grbit = $col_array[4];
1371
        } else {
1372
            $grbit = 0;
1373
        }
1374
        if (isset($col_array[5])) {
1375
            $level = $col_array[5];
1376
        } else {
1377
            $level = 0;
1378
        }
1379
        $record   = 0x007D;          // Record identifier
1380
        $length   = 0x000C;          // Number of bytes to follow
1381
1382
        $coldx   *= 256;             // Convert to units of 1/256 of a char
1383
1384
        $ixfe     = $xfIndex;
1385
        $reserved = 0x0000;            // Reserved
1386
1387
        $level = max(0, min($level, 7));
1388
        $grbit |= $level << 8;
1389
1390
        $header   = pack("vv", $record, $length);
1391
        $data     = pack("vvvvvv", $colFirst, $colLast, $coldx, $ixfe, $grbit, $reserved);
0 ignored issues
show
Bug introduced by
The variable $colFirst does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug introduced by
The variable $colLast does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1392
        $this->append($header.$data);
1393
    }
1394
1395
    /**
1396
     * Write BIFF record SELECTION.
1397
     */
1398
    private function writeSelection()
1399
    {
1400
        // look up the selected cell range
1401
        $selectedCells = $this->phpSheet->getSelectedCells();
0 ignored issues
show
Unused Code introduced by
$selectedCells is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1402
        $selectedCells = \PhpSpreadsheet\Cell::splitRange($this->phpSheet->getSelectedCells());
1403
        $selectedCells = $selectedCells[0];
1404
        if (count($selectedCells) == 2) {
1405
            list($first, $last) = $selectedCells;
1406
        } else {
1407
            $first = $selectedCells[0];
1408
            $last  = $selectedCells[0];
1409
        }
1410
1411
        list($colFirst, $rwFirst) = \PhpSpreadsheet\Cell::coordinateFromString($first);
1412
        $colFirst = \PhpSpreadsheet\Cell::columnIndexFromString($colFirst) - 1; // base 0 column index
1413
        --$rwFirst; // base 0 row index
1414
1415
        list($colLast, $rwLast) = \PhpSpreadsheet\Cell::coordinateFromString($last);
1416
        $colLast = \PhpSpreadsheet\Cell::columnIndexFromString($colLast) - 1; // base 0 column index
1417
        --$rwLast; // base 0 row index
1418
1419
        // make sure we are not out of bounds
1420
        $colFirst = min($colFirst, 255);
1421
        $colLast  = min($colLast, 255);
1422
1423
        $rwFirst = min($rwFirst, 65535);
1424
        $rwLast  = min($rwLast, 65535);
1425
1426
        $record   = 0x001D;                  // Record identifier
1427
        $length   = 0x000F;                  // Number of bytes to follow
1428
1429
        $pnn      = $this->activePane;     // Pane position
1430
        $rwAct    = $rwFirst;                // Active row
1431
        $colAct   = $colFirst;               // Active column
1432
        $irefAct  = 0;                       // Active cell ref
1433
        $cref     = 1;                       // Number of refs
1434
1435
        if (!isset($rwLast)) {
1436
            $rwLast   = $rwFirst;       // Last  row in reference
1437
        }
1438
        if (!isset($colLast)) {
1439
            $colLast  = $colFirst;      // Last  col in reference
1440
        }
1441
1442
        // Swap last row/col for first row/col as necessary
1443
        if ($rwFirst > $rwLast) {
1444
            list($rwFirst, $rwLast) = array($rwLast, $rwFirst);
1445
        }
1446
1447
        if ($colFirst > $colLast) {
1448
            list($colFirst, $colLast) = array($colLast, $colFirst);
1449
        }
1450
1451
        $header   = pack("vv", $record, $length);
1452
        $data     = pack("CvvvvvvCC", $pnn, $rwAct, $colAct, $irefAct, $cref, $rwFirst, $rwLast, $colFirst, $colLast);
1453
        $this->append($header . $data);
1454
    }
1455
1456
    /**
1457
     * Store the MERGEDCELLS records for all ranges of merged cells
1458
     */
1459
    private function writeMergedCells()
1460
    {
1461
        $mergeCells = $this->phpSheet->getMergeCells();
1462
        $countMergeCells = count($mergeCells);
1463
1464
        if ($countMergeCells == 0) {
1465
            return;
1466
        }
1467
1468
        // maximum allowed number of merged cells per record
1469
        $maxCountMergeCellsPerRecord = 1027;
1470
1471
        // record identifier
1472
        $record = 0x00E5;
1473
1474
        // counter for total number of merged cells treated so far by the writer
1475
        $i = 0;
1476
1477
        // counter for number of merged cells written in record currently being written
1478
        $j = 0;
1479
1480
        // initialize record data
1481
        $recordData = '';
1482
1483
        // loop through the merged cells
1484
        foreach ($mergeCells as $mergeCell) {
1485
            ++$i;
1486
            ++$j;
1487
1488
            // extract the row and column indexes
1489
            $range = \PhpSpreadsheet\Cell::splitRange($mergeCell);
0 ignored issues
show
Documentation introduced by
$mergeCell is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1490
            list($first, $last) = $range[0];
1491
            list($firstColumn, $firstRow) = \PhpSpreadsheet\Cell::coordinateFromString($first);
1492
            list($lastColumn, $lastRow) = \PhpSpreadsheet\Cell::coordinateFromString($last);
1493
1494
            $recordData .= pack('vvvv', $firstRow - 1, $lastRow - 1, \PhpSpreadsheet\Cell::columnIndexFromString($firstColumn) - 1, \PhpSpreadsheet\Cell::columnIndexFromString($lastColumn) - 1);
1495
1496
            // flush record if we have reached limit for number of merged cells, or reached final merged cell
1497
            if ($j == $maxCountMergeCellsPerRecord or $i == $countMergeCells) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
1498
                $recordData = pack('v', $j) . $recordData;
1499
                $length = strlen($recordData);
1500
                $header = pack('vv', $record, $length);
1501
                $this->append($header . $recordData);
1502
1503
                // initialize for next record, if any
1504
                $recordData = '';
1505
                $j = 0;
1506
            }
1507
        }
1508
    }
1509
1510
    /**
1511
     * Write SHEETLAYOUT record
1512
     */
1513
    private function writeSheetLayout()
1514
    {
1515
        if (!$this->phpSheet->isTabColorSet()) {
1516
            return;
1517
        }
1518
1519
        $recordData = pack(
1520
            'vvVVVvv',
1521
            0x0862,
1522
            0x0000, // unused
1523
            0x00000000, // unused
1524
            0x00000000, // unused
1525
            0x00000014, // size of record data
1526
            $this->colors[$this->phpSheet->getTabColor()->getRGB()], // color index
1527
            0x0000        // unused
1528
        );
1529
1530
        $length = strlen($recordData);
1531
1532
        $record = 0x0862; // Record identifier
1533
        $header = pack('vv', $record, $length);
1534
        $this->append($header . $recordData);
1535
    }
1536
1537
    /**
1538
     * Write SHEETPROTECTION
1539
     */
1540
    private function writeSheetProtection()
1541
    {
1542
        // record identifier
1543
        $record = 0x0867;
1544
1545
        // prepare options
1546
        $options  =   (int) !$this->phpSheet->getProtection()->getObjects()
1547
                    | (int) !$this->phpSheet->getProtection()->getScenarios()           << 1
1548
                    | (int) !$this->phpSheet->getProtection()->getFormatCells()         << 2
1549
                    | (int) !$this->phpSheet->getProtection()->getFormatColumns()       << 3
1550
                    | (int) !$this->phpSheet->getProtection()->getFormatRows()          << 4
1551
                    | (int) !$this->phpSheet->getProtection()->getInsertColumns()       << 5
1552
                    | (int) !$this->phpSheet->getProtection()->getInsertRows()          << 6
1553
                    | (int) !$this->phpSheet->getProtection()->getInsertHyperlinks()    << 7
1554
                    | (int) !$this->phpSheet->getProtection()->getDeleteColumns()       << 8
1555
                    | (int) !$this->phpSheet->getProtection()->getDeleteRows()          << 9
1556
                    | (int) !$this->phpSheet->getProtection()->getSelectLockedCells()   << 10
1557
                    | (int) !$this->phpSheet->getProtection()->getSort()                << 11
1558
                    | (int) !$this->phpSheet->getProtection()->getAutoFilter()          << 12
1559
                    | (int) !$this->phpSheet->getProtection()->getPivotTables()         << 13
1560
                    | (int) !$this->phpSheet->getProtection()->getSelectUnlockedCells() << 14 ;
1561
1562
        // record data
1563
        $recordData = pack(
1564
            'vVVCVVvv',
1565
            0x0867, // repeated record identifier
1566
            0x0000, // not used
1567
            0x0000, // not used
1568
            0x00, // not used
1569
            0x01000200, // unknown data
1570
            0xFFFFFFFF, // unknown data
1571
            $options, // options
1572
            0x0000 // not used
1573
        );
1574
1575
        $length = strlen($recordData);
1576
        $header = pack('vv', $record, $length);
1577
1578
        $this->append($header . $recordData);
1579
    }
1580
1581
    /**
1582
     * Write BIFF record RANGEPROTECTION
1583
     *
1584
     * Openoffice.org's Documentaion of the Microsoft Excel File Format uses term RANGEPROTECTION for these records
1585
     * Microsoft Office Excel 97-2007 Binary File Format Specification uses term FEAT for these records
1586
     */
1587
    private function writeRangeProtection()
1588
    {
1589
        foreach ($this->phpSheet->getProtectedCells() as $range => $password) {
1590
            // number of ranges, e.g. 'A1:B3 C20:D25'
1591
            $cellRanges = explode(' ', $range);
1592
            $cref = count($cellRanges);
1593
1594
            $recordData = pack(
1595
                'vvVVvCVvVv',
1596
                0x0868,
1597
                0x00,
1598
                0x0000,
1599
                0x0000,
1600
                0x02,
1601
                0x0,
1602
                0x0000,
1603
                $cref,
1604
                0x0000,
1605
                0x00
1606
            );
1607
1608
            foreach ($cellRanges as $cellRange) {
1609
                $recordData .= $this->writeBIFF8CellRangeAddressFixed($cellRange);
1610
            }
1611
1612
            // the rgbFeat structure
1613
            $recordData .= pack(
1614
                'VV',
1615
                0x0000,
1616
                hexdec($password)
1617
            );
1618
1619
            $recordData .= \PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong('p' . md5($recordData));
1620
1621
            $length = strlen($recordData);
1622
1623
            $record = 0x0868;        // Record identifier
1624
            $header = pack("vv", $record, $length);
1625
            $this->append($header . $recordData);
1626
        }
1627
    }
1628
1629
    /**
1630
     * Write BIFF record EXTERNCOUNT to indicate the number of external sheet
1631
     * references in a worksheet.
1632
     *
1633
     * Excel only stores references to external sheets that are used in formulas.
1634
     * For simplicity we store references to all the sheets in the workbook
1635
     * regardless of whether they are used or not. This reduces the overall
1636
     * complexity and eliminates the need for a two way dialogue between the formula
1637
     * parser the worksheet objects.
1638
     *
1639
     * @param integer $count The number of external sheet references in this worksheet
1640
     */
1641 View Code Duplication
    private function writeExterncount($count)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1642
    {
1643
        $record = 0x0016;          // Record identifier
1644
        $length = 0x0002;          // Number of bytes to follow
1645
1646
        $header = pack("vv", $record, $length);
1647
        $data   = pack("v", $count);
1648
        $this->append($header . $data);
1649
    }
1650
1651
    /**
1652
     * Writes the Excel BIFF EXTERNSHEET record. These references are used by
1653
     * formulas. A formula references a sheet name via an index. Since we store a
1654
     * reference to all of the external worksheets the EXTERNSHEET index is the same
1655
     * as the worksheet index.
1656
     *
1657
     * @param string $sheetname The name of a external worksheet
1658
     */
1659
    private function writeExternsheet($sheetname)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
1660
    {
1661
        $record    = 0x0017;         // Record identifier
1662
1663
        // References to the current sheet are encoded differently to references to
1664
        // external sheets.
1665
        //
1666
        if ($this->phpSheet->getTitle() == $sheetname) {
1667
            $sheetname = '';
1668
            $length    = 0x02;  // The following 2 bytes
1669
            $cch       = 1;     // The following byte
1670
            $rgch      = 0x02;  // Self reference
1671
        } else {
1672
            $length    = 0x02 + strlen($sheetname);
1673
            $cch       = strlen($sheetname);
1674
            $rgch      = 0x03;  // Reference to a sheet in the current workbook
1675
        }
1676
1677
        $header = pack("vv", $record, $length);
1678
        $data   = pack("CC", $cch, $rgch);
1679
        $this->append($header . $data . $sheetname);
1680
    }
1681
1682
    /**
1683
     * Writes the Excel BIFF PANE record.
1684
     * The panes can either be frozen or thawed (unfrozen).
1685
     * Frozen panes are specified in terms of an integer number of rows and columns.
1686
     * Thawed panes are specified in terms of Excel's units for rows and columns.
1687
     */
1688
    private function writePanes()
1689
    {
1690
        $panes = array();
1691
        if ($freezePane = $this->phpSheet->getFreezePane()) {
1692
            list($column, $row) = \PhpSpreadsheet\Cell::coordinateFromString($freezePane);
1693
            $panes[0] = $row - 1;
1694
            $panes[1] = \PhpSpreadsheet\Cell::columnIndexFromString($column) - 1;
1695
        } else {
1696
            // thaw panes
1697
            return;
1698
        }
1699
1700
        $y       = isset($panes[0]) ? $panes[0] : null;
1701
        $x       = isset($panes[1]) ? $panes[1] : null;
1702
        $rwTop   = isset($panes[2]) ? $panes[2] : null;
1703
        $colLeft = isset($panes[3]) ? $panes[3] : null;
1704
        if (count($panes) > 4) { // if Active pane was received
1705
            $pnnAct = $panes[4];
1706
        } else {
1707
            $pnnAct = null;
1708
        }
1709
        $record  = 0x0041;       // Record identifier
1710
        $length  = 0x000A;       // Number of bytes to follow
1711
1712
        // Code specific to frozen or thawed panes.
1713
        if ($this->phpSheet->getFreezePane()) {
1714
            // Set default values for $rwTop and $colLeft
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% 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...
1715
            if (!isset($rwTop)) {
1716
                $rwTop   = $y;
1717
            }
1718
            if (!isset($colLeft)) {
1719
                $colLeft = $x;
1720
            }
1721
        } else {
1722
            // Set default values for $rwTop and $colLeft
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% 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...
1723
            if (!isset($rwTop)) {
1724
                $rwTop   = 0;
1725
            }
1726
            if (!isset($colLeft)) {
1727
                $colLeft = 0;
1728
            }
1729
1730
            // Convert Excel's row and column units to the internal units.
1731
            // The default row height is 12.75
1732
            // The default column width is 8.43
1733
            // The following slope and intersection values were interpolated.
1734
            //
1735
            $y = 20*$y + 255;
1736
            $x = 113.879*$x + 390;
1737
        }
1738
1739
1740
        // Determine which pane should be active. There is also the undocumented
1741
        // option to override this should it be necessary: may be removed later.
1742
        //
1743
        if (!isset($pnnAct)) {
1744
            if ($x != 0 && $y != 0) {
1745
                $pnnAct = 0; // Bottom right
1746
            }
1747
            if ($x != 0 && $y == 0) {
1748
                $pnnAct = 1; // Top right
1749
            }
1750
            if ($x == 0 && $y != 0) {
1751
                $pnnAct = 2; // Bottom left
1752
            }
1753
            if ($x == 0 && $y == 0) {
1754
                $pnnAct = 3; // Top left
1755
            }
1756
        }
1757
1758
        $this->activePane = $pnnAct; // Used in writeSelection
1759
1760
        $header = pack("vv", $record, $length);
1761
        $data = pack("vvvvv", $x, $y, $rwTop, $colLeft, $pnnAct);
1762
        $this->append($header . $data);
1763
    }
1764
1765
    /**
1766
     * Store the page setup SETUP BIFF record.
1767
     */
1768
    private function writeSetup()
1769
    {
1770
        $record       = 0x00A1;                  // Record identifier
1771
        $length       = 0x0022;                  // Number of bytes to follow
1772
1773
        $iPaperSize   = $this->phpSheet->getPageSetup()->getPaperSize();    // Paper size
1774
1775
        $iScale = $this->phpSheet->getPageSetup()->getScale() ?
1776
            $this->phpSheet->getPageSetup()->getScale() : 100;   // Print scaling factor
1777
1778
        $iPageStart   = 0x01;                 // Starting page number
1779
        $iFitWidth    = (int) $this->phpSheet->getPageSetup()->getFitToWidth();    // Fit to number of pages wide
1780
        $iFitHeight    = (int) $this->phpSheet->getPageSetup()->getFitToHeight();    // Fit to number of pages high
1781
        $grbit        = 0x00;                 // Option flags
0 ignored issues
show
Unused Code introduced by
$grbit is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1782
        $iRes         = 0x0258;               // Print resolution
1783
        $iVRes        = 0x0258;               // Vertical print resolution
1784
1785
        $numHdr       = $this->phpSheet->getPageMargins()->getHeader();  // Header Margin
1786
1787
        $numFtr       = $this->phpSheet->getPageMargins()->getFooter();   // Footer Margin
1788
        $iCopies      = 0x01;                 // Number of copies
1789
1790
        $fLeftToRight = 0x0;                     // Print over then down
1791
1792
        // Page orientation
1793
        $fLandscape = ($this->phpSheet->getPageSetup()->getOrientation() == \PhpSpreadsheet\Worksheet\PageSetup::ORIENTATION_LANDSCAPE) ?
1794
            0x0 : 0x1;
1795
1796
        $fNoPls       = 0x0;                     // Setup not read from printer
1797
        $fNoColor     = 0x0;                     // Print black and white
1798
        $fDraft       = 0x0;                     // Print draft quality
1799
        $fNotes       = 0x0;                     // Print notes
1800
        $fNoOrient    = 0x0;                     // Orientation not set
1801
        $fUsePage     = 0x0;                     // Use custom starting page
1802
1803
        $grbit           = $fLeftToRight;
1804
        $grbit          |= $fLandscape    << 1;
1805
        $grbit          |= $fNoPls        << 2;
1806
        $grbit          |= $fNoColor      << 3;
1807
        $grbit          |= $fDraft        << 4;
1808
        $grbit          |= $fNotes        << 5;
1809
        $grbit          |= $fNoOrient     << 6;
1810
        $grbit          |= $fUsePage      << 7;
1811
1812
        $numHdr = pack("d", $numHdr);
1813
        $numFtr = pack("d", $numFtr);
1814
        if (self::getByteOrder()) { // if it's Big Endian
1815
            $numHdr = strrev($numHdr);
1816
            $numFtr = strrev($numFtr);
1817
        }
1818
1819
        $header = pack("vv", $record, $length);
1820
        $data1  = pack("vvvvvvvv", $iPaperSize, $iScale, $iPageStart, $iFitWidth, $iFitHeight, $grbit, $iRes, $iVRes);
1821
        $data2  = $numHdr.$numFtr;
1822
        $data3  = pack("v", $iCopies);
1823
        $this->append($header . $data1 . $data2 . $data3);
1824
    }
1825
1826
    /**
1827
     * Store the header caption BIFF record.
1828
     */
1829 View Code Duplication
    private function writeHeader()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1830
    {
1831
        $record  = 0x0014;               // Record identifier
1832
1833
        /* removing for now
0 ignored issues
show
Unused Code Comprehensibility introduced by
45% 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...
1834
        // need to fix character count (multibyte!)
1835
        if (strlen($this->phpSheet->getHeaderFooter()->getOddHeader()) <= 255) {
1836
            $str      = $this->phpSheet->getHeaderFooter()->getOddHeader();       // header string
1837
        } else {
1838
            $str = '';
1839
        }
1840
        */
1841
1842
        $recordData = \PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($this->phpSheet->getHeaderFooter()->getOddHeader());
1843
        $length = strlen($recordData);
1844
1845
        $header   = pack("vv", $record, $length);
1846
1847
        $this->append($header . $recordData);
1848
    }
1849
1850
    /**
1851
     * Store the footer caption BIFF record.
1852
     */
1853 View Code Duplication
    private function writeFooter()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1854
    {
1855
        $record  = 0x0015;               // Record identifier
1856
1857
        /* removing for now
0 ignored issues
show
Unused Code Comprehensibility introduced by
45% 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...
1858
        // need to fix character count (multibyte!)
1859
        if (strlen($this->phpSheet->getHeaderFooter()->getOddFooter()) <= 255) {
1860
            $str = $this->phpSheet->getHeaderFooter()->getOddFooter();
1861
        } else {
1862
            $str = '';
1863
        }
1864
        */
1865
1866
        $recordData = \PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($this->phpSheet->getHeaderFooter()->getOddFooter());
1867
        $length = strlen($recordData);
1868
1869
        $header    = pack("vv", $record, $length);
1870
1871
        $this->append($header . $recordData);
1872
    }
1873
1874
    /**
1875
     * Store the horizontal centering HCENTER BIFF record.
1876
     *
1877
     * @access private
1878
     */
1879 View Code Duplication
    private function writeHcenter()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1880
    {
1881
        $record   = 0x0083;              // Record identifier
1882
        $length   = 0x0002;              // Bytes to follow
1883
1884
        $fHCenter = $this->phpSheet->getPageSetup()->getHorizontalCentered() ? 1 : 0;     // Horizontal centering
1885
1886
        $header    = pack("vv", $record, $length);
1887
        $data      = pack("v", $fHCenter);
1888
1889
        $this->append($header.$data);
1890
    }
1891
1892
    /**
1893
     * Store the vertical centering VCENTER BIFF record.
1894
     */
1895 View Code Duplication
    private function writeVcenter()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1896
    {
1897
        $record   = 0x0084;              // Record identifier
1898
        $length   = 0x0002;              // Bytes to follow
1899
1900
        $fVCenter = $this->phpSheet->getPageSetup()->getVerticalCentered() ? 1 : 0;     // Horizontal centering
1901
1902
        $header    = pack("vv", $record, $length);
1903
        $data      = pack("v", $fVCenter);
1904
        $this->append($header . $data);
1905
    }
1906
1907
    /**
1908
     * Store the LEFTMARGIN BIFF record.
1909
     */
1910 View Code Duplication
    private function writeMarginLeft()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1911
    {
1912
        $record  = 0x0026;                   // Record identifier
1913
        $length  = 0x0008;                   // Bytes to follow
1914
1915
        $margin  = $this->phpSheet->getPageMargins()->getLeft();     // Margin in inches
1916
1917
        $header    = pack("vv", $record, $length);
1918
        $data      = pack("d", $margin);
1919
        if (self::getByteOrder()) { // if it's Big Endian
1920
            $data = strrev($data);
1921
        }
1922
1923
        $this->append($header . $data);
1924
    }
1925
1926
    /**
1927
     * Store the RIGHTMARGIN BIFF record.
1928
     */
1929 View Code Duplication
    private function writeMarginRight()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1930
    {
1931
        $record  = 0x0027;                   // Record identifier
1932
        $length  = 0x0008;                   // Bytes to follow
1933
1934
        $margin  = $this->phpSheet->getPageMargins()->getRight();     // Margin in inches
1935
1936
        $header    = pack("vv", $record, $length);
1937
        $data      = pack("d", $margin);
1938
        if (self::getByteOrder()) { // if it's Big Endian
1939
            $data = strrev($data);
1940
        }
1941
1942
        $this->append($header . $data);
1943
    }
1944
1945
    /**
1946
     * Store the TOPMARGIN BIFF record.
1947
     */
1948 View Code Duplication
    private function writeMarginTop()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1949
    {
1950
        $record  = 0x0028;                   // Record identifier
1951
        $length  = 0x0008;                   // Bytes to follow
1952
1953
        $margin  = $this->phpSheet->getPageMargins()->getTop();     // Margin in inches
1954
1955
        $header    = pack("vv", $record, $length);
1956
        $data      = pack("d", $margin);
1957
        if (self::getByteOrder()) { // if it's Big Endian
1958
            $data = strrev($data);
1959
        }
1960
1961
        $this->append($header . $data);
1962
    }
1963
1964
    /**
1965
     * Store the BOTTOMMARGIN BIFF record.
1966
     */
1967 View Code Duplication
    private function writeMarginBottom()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1968
    {
1969
        $record  = 0x0029;                   // Record identifier
1970
        $length  = 0x0008;                   // Bytes to follow
1971
1972
        $margin  = $this->phpSheet->getPageMargins()->getBottom();     // Margin in inches
1973
1974
        $header    = pack("vv", $record, $length);
1975
        $data      = pack("d", $margin);
1976
        if (self::getByteOrder()) { // if it's Big Endian
1977
            $data = strrev($data);
1978
        }
1979
1980
        $this->append($header . $data);
1981
    }
1982
1983
    /**
1984
     * Write the PRINTHEADERS BIFF record.
1985
     */
1986
    private function writePrintHeaders()
1987
    {
1988
        $record      = 0x002a;                   // Record identifier
1989
        $length      = 0x0002;                   // Bytes to follow
1990
1991
        $fPrintRwCol = $this->_print_headers;     // Boolean flag
1992
1993
        $header      = pack("vv", $record, $length);
1994
        $data        = pack("v", $fPrintRwCol);
1995
        $this->append($header . $data);
1996
    }
1997
1998
    /**
1999
     * Write the PRINTGRIDLINES BIFF record. Must be used in conjunction with the
2000
     * GRIDSET record.
2001
     */
2002 View Code Duplication
    private function writePrintGridlines()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2003
    {
2004
        $record      = 0x002b;                    // Record identifier
2005
        $length      = 0x0002;                    // Bytes to follow
2006
2007
        $fPrintGrid  = $this->phpSheet->getPrintGridlines() ? 1 : 0;    // Boolean flag
2008
2009
        $header      = pack("vv", $record, $length);
2010
        $data      = pack("v", $fPrintGrid);
2011
        $this->append($header . $data);
2012
    }
2013
2014
    /**
2015
     * Write the GRIDSET BIFF record. Must be used in conjunction with the
2016
     * PRINTGRIDLINES record.
2017
     */
2018
    private function writeGridset()
2019
    {
2020
        $record      = 0x0082;                        // Record identifier
2021
        $length      = 0x0002;                        // Bytes to follow
2022
2023
        $fGridSet    = !$this->phpSheet->getPrintGridlines();     // Boolean flag
2024
2025
        $header      = pack("vv", $record, $length);
2026
        $data        = pack("v", $fGridSet);
2027
        $this->append($header . $data);
2028
    }
2029
2030
    /**
2031
     * Write the AUTOFILTERINFO BIFF record. This is used to configure the number of autofilter select used in the sheet.
2032
     */
2033
    private function writeAutoFilterInfo()
2034
    {
2035
        $record      = 0x009D;                        // Record identifier
2036
        $length      = 0x0002;                        // Bytes to follow
2037
2038
        $rangeBounds = \PhpSpreadsheet\Cell::rangeBoundaries($this->phpSheet->getAutoFilter()->getRange());
2039
        $iNumFilters = 1 + $rangeBounds[1][0] - $rangeBounds[0][0];
2040
2041
        $header   = pack("vv", $record, $length);
2042
        $data     = pack("v", $iNumFilters);
2043
        $this->append($header . $data);
2044
    }
2045
2046
    /**
2047
     * Write the GUTS BIFF record. This is used to configure the gutter margins
2048
     * where Excel outline symbols are displayed. The visibility of the gutters is
2049
     * controlled by a flag in WSBOOL.
2050
     *
2051
     * @see writeWsbool()
2052
     */
2053
    private function writeGuts()
2054
    {
2055
        $record      = 0x0080;   // Record identifier
2056
        $length      = 0x0008;   // Bytes to follow
2057
2058
        $dxRwGut     = 0x0000;   // Size of row gutter
2059
        $dxColGut    = 0x0000;   // Size of col gutter
2060
2061
        // determine maximum row outline level
2062
        $maxRowOutlineLevel = 0;
2063
        foreach ($this->phpSheet->getRowDimensions() as $rowDimension) {
2064
            $maxRowOutlineLevel = max($maxRowOutlineLevel, $rowDimension->getOutlineLevel());
2065
        }
2066
2067
        $col_level   = 0;
2068
2069
        // Calculate the maximum column outline level. The equivalent calculation
2070
        // for the row outline level is carried out in writeRow().
2071
        $colcount = count($this->columnInfo);
2072
        for ($i = 0; $i < $colcount; ++$i) {
2073
            $col_level = max($this->columnInfo[$i][5], $col_level);
2074
        }
2075
2076
        // Set the limits for the outline levels (0 <= x <= 7).
2077
        $col_level = max(0, min($col_level, 7));
2078
2079
        // The displayed level is one greater than the max outline levels
2080
        if ($maxRowOutlineLevel) {
2081
            ++$maxRowOutlineLevel;
2082
        }
2083
        if ($col_level) {
2084
            ++$col_level;
2085
        }
2086
2087
        $header      = pack("vv", $record, $length);
2088
        $data        = pack("vvvv", $dxRwGut, $dxColGut, $maxRowOutlineLevel, $col_level);
2089
2090
        $this->append($header.$data);
2091
    }
2092
2093
    /**
2094
     * Write the WSBOOL BIFF record, mainly for fit-to-page. Used in conjunction
2095
     * with the SETUP record.
2096
     */
2097
    private function writeWsbool()
2098
    {
2099
        $record      = 0x0081;   // Record identifier
2100
        $length      = 0x0002;   // Bytes to follow
2101
        $grbit       = 0x0000;
2102
2103
        // The only option that is of interest is the flag for fit to page. So we
2104
        // set all the options in one go.
2105
        //
2106
        // Set the option flags
2107
        $grbit |= 0x0001;                           // Auto page breaks visible
2108
        if ($this->outlineStyle) {
2109
            $grbit |= 0x0020; // Auto outline styles
2110
        }
2111
        if ($this->phpSheet->getShowSummaryBelow()) {
2112
            $grbit |= 0x0040; // Outline summary below
2113
        }
2114
        if ($this->phpSheet->getShowSummaryRight()) {
2115
            $grbit |= 0x0080; // Outline summary right
2116
        }
2117
        if ($this->phpSheet->getPageSetup()->getFitToPage()) {
2118
            $grbit |= 0x0100; // Page setup fit to page
2119
        }
2120
        if ($this->outlineOn) {
2121
            $grbit |= 0x0400; // Outline symbols displayed
2122
        }
2123
2124
        $header      = pack("vv", $record, $length);
2125
        $data        = pack("v", $grbit);
2126
        $this->append($header . $data);
2127
    }
2128
2129
    /**
2130
     * Write the HORIZONTALPAGEBREAKS and VERTICALPAGEBREAKS BIFF records.
2131
     */
2132
    private function writeBreaks()
2133
    {
2134
        // initialize
2135
        $vbreaks = array();
2136
        $hbreaks = array();
2137
2138
        foreach ($this->phpSheet->getBreaks() as $cell => $breakType) {
2139
            // Fetch coordinates
2140
            $coordinates = \PhpSpreadsheet\Cell::coordinateFromString($cell);
2141
2142
            // Decide what to do by the type of break
2143
            switch ($breakType) {
2144
                case \PhpSpreadsheet\Worksheet::BREAK_COLUMN:
2145
                    // Add to list of vertical breaks
2146
                    $vbreaks[] = \PhpSpreadsheet\Cell::columnIndexFromString($coordinates[0]) - 1;
2147
                    break;
2148
                case \PhpSpreadsheet\Worksheet::BREAK_ROW:
2149
                    // Add to list of horizontal breaks
2150
                    $hbreaks[] = $coordinates[1];
2151
                    break;
2152
                case \PhpSpreadsheet\Worksheet::BREAK_NONE:
2153
                default:
2154
                    // Nothing to do
2155
                    break;
2156
            }
2157
        }
2158
2159
        //horizontal page breaks
2160
        if (!empty($hbreaks)) {
2161
            // Sort and filter array of page breaks
2162
            sort($hbreaks, SORT_NUMERIC);
2163
            if ($hbreaks[0] == 0) { // don't use first break if it's 0
2164
                array_shift($hbreaks);
2165
            }
2166
2167
            $record  = 0x001b;               // Record identifier
2168
            $cbrk    = count($hbreaks);       // Number of page breaks
2169
            $length  = 2 + 6 * $cbrk;      // Bytes to follow
2170
2171
            $header  = pack("vv", $record, $length);
2172
            $data    = pack("v", $cbrk);
2173
2174
            // Append each page break
2175
            foreach ($hbreaks as $hbreak) {
2176
                $data .= pack("vvv", $hbreak, 0x0000, 0x00ff);
2177
            }
2178
2179
            $this->append($header . $data);
2180
        }
2181
2182
        // vertical page breaks
2183
        if (!empty($vbreaks)) {
2184
            // 1000 vertical pagebreaks appears to be an internal Excel 5 limit.
2185
            // It is slightly higher in Excel 97/200, approx. 1026
2186
            $vbreaks = array_slice($vbreaks, 0, 1000);
2187
2188
            // Sort and filter array of page breaks
2189
            sort($vbreaks, SORT_NUMERIC);
2190
            if ($vbreaks[0] == 0) { // don't use first break if it's 0
2191
                array_shift($vbreaks);
2192
            }
2193
2194
            $record  = 0x001a;               // Record identifier
2195
            $cbrk    = count($vbreaks);       // Number of page breaks
2196
            $length  = 2 + 6 * $cbrk;      // Bytes to follow
2197
2198
            $header  = pack("vv", $record, $length);
2199
            $data    = pack("v", $cbrk);
2200
2201
            // Append each page break
2202
            foreach ($vbreaks as $vbreak) {
2203
                $data .= pack("vvv", $vbreak, 0x0000, 0xffff);
2204
            }
2205
2206
            $this->append($header . $data);
2207
        }
2208
    }
2209
2210
    /**
2211
     * Set the Biff PROTECT record to indicate that the worksheet is protected.
2212
     */
2213 View Code Duplication
    private function writeProtect()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2214
    {
2215
        // Exit unless sheet protection has been specified
2216
        if (!$this->phpSheet->getProtection()->getSheet()) {
2217
            return;
2218
        }
2219
2220
        $record      = 0x0012;             // Record identifier
2221
        $length      = 0x0002;             // Bytes to follow
2222
2223
        $fLock      = 1;    // Worksheet is protected
2224
2225
        $header      = pack("vv", $record, $length);
2226
        $data      = pack("v", $fLock);
2227
2228
        $this->append($header.$data);
2229
    }
2230
2231
    /**
2232
     * Write SCENPROTECT
2233
     */
2234 View Code Duplication
    private function writeScenProtect()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2235
    {
2236
        // Exit if sheet protection is not active
2237
        if (!$this->phpSheet->getProtection()->getSheet()) {
2238
            return;
2239
        }
2240
2241
        // Exit if scenarios are not protected
2242
        if (!$this->phpSheet->getProtection()->getScenarios()) {
2243
            return;
2244
        }
2245
2246
        $record = 0x00DD; // Record identifier
2247
        $length = 0x0002; // Bytes to follow
2248
2249
        $header = pack('vv', $record, $length);
2250
        $data = pack('v', 1);
2251
2252
        $this->append($header . $data);
2253
    }
2254
2255
    /**
2256
     * Write OBJECTPROTECT
2257
     */
2258 View Code Duplication
    private function writeObjectProtect()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2259
    {
2260
        // Exit if sheet protection is not active
2261
        if (!$this->phpSheet->getProtection()->getSheet()) {
2262
            return;
2263
        }
2264
2265
        // Exit if objects are not protected
2266
        if (!$this->phpSheet->getProtection()->getObjects()) {
2267
            return;
2268
        }
2269
2270
        $record = 0x0063; // Record identifier
2271
        $length = 0x0002; // Bytes to follow
2272
2273
        $header = pack('vv', $record, $length);
2274
        $data = pack('v', 1);
2275
2276
        $this->append($header . $data);
2277
    }
2278
2279
    /**
2280
     * Write the worksheet PASSWORD record.
2281
     */
2282
    private function writePassword()
2283
    {
2284
        // Exit unless sheet protection and password have been specified
2285
        if (!$this->phpSheet->getProtection()->getSheet() || !$this->phpSheet->getProtection()->getPassword()) {
2286
            return;
2287
        }
2288
2289
        $record      = 0x0013;               // Record identifier
2290
        $length      = 0x0002;               // Bytes to follow
2291
2292
        $wPassword   = hexdec($this->phpSheet->getProtection()->getPassword());     // Encoded password
2293
2294
        $header      = pack("vv", $record, $length);
2295
        $data        = pack("v", $wPassword);
2296
2297
        $this->append($header . $data);
2298
    }
2299
2300
    /**
2301
     * Insert a 24bit bitmap image in a worksheet.
2302
     *
2303
     * @access public
2304
     * @param integer $row     The row we are going to insert the bitmap into
2305
     * @param integer $col     The column we are going to insert the bitmap into
2306
     * @param mixed   $bitmap  The bitmap filename or GD-image resource
2307
     * @param integer $x       The horizontal position (offset) of the image inside the cell.
2308
     * @param integer $y       The vertical position (offset) of the image inside the cell.
2309
     * @param float   $scale_x The horizontal scale
2310
     * @param float   $scale_y The vertical scale
2311
     */
2312
    public function insertBitmap($row, $col, $bitmap, $x = 0, $y = 0, $scale_x = 1, $scale_y = 1)
2313
    {
2314
        $bitmap_array = (is_resource($bitmap) ? $this->processBitmapGd($bitmap) : $this->processBitmap($bitmap));
2315
        list($width, $height, $size, $data) = $bitmap_array; //$this->processBitmap($bitmap);
0 ignored issues
show
Unused Code Comprehensibility introduced by
86% 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...
2316
2317
        // Scale the frame of the image.
2318
        $width  *= $scale_x;
2319
        $height *= $scale_y;
2320
2321
        // Calculate the vertices of the image and write the OBJ record
2322
        $this->positionImage($col, $row, $x, $y, $width, $height);
2323
2324
        // Write the IMDATA record to store the bitmap data
2325
        $record      = 0x007f;
2326
        $length      = 8 + $size;
2327
        $cf          = 0x09;
2328
        $env         = 0x01;
2329
        $lcb         = $size;
2330
2331
        $header      = pack("vvvvV", $record, $length, $cf, $env, $lcb);
2332
        $this->append($header.$data);
2333
    }
2334
2335
    /**
2336
     * Calculate the vertices that define the position of the image as required by
2337
     * the OBJ record.
2338
     *
2339
     *         +------------+------------+
2340
     *         |     A      |      B     |
2341
     *   +-----+------------+------------+
2342
     *   |     |(x1,y1)     |            |
2343
     *   |  1  |(A1)._______|______      |
2344
     *   |     |    |              |     |
2345
     *   |     |    |              |     |
2346
     *   +-----+----|    BITMAP    |-----+
2347
     *   |     |    |              |     |
2348
     *   |  2  |    |______________.     |
2349
     *   |     |            |        (B2)|
2350
     *   |     |            |     (x2,y2)|
2351
     *   +---- +------------+------------+
2352
     *
2353
     * Example of a bitmap that covers some of the area from cell A1 to cell B2.
2354
     *
2355
     * Based on the width and height of the bitmap we need to calculate 8 vars:
2356
     *     $col_start, $row_start, $col_end, $row_end, $x1, $y1, $x2, $y2.
2357
     * The width and height of the cells are also variable and have to be taken into
2358
     * account.
2359
     * The values of $col_start and $row_start are passed in from the calling
2360
     * function. The values of $col_end and $row_end are calculated by subtracting
2361
     * the width and height of the bitmap from the width and height of the
2362
     * underlying cells.
2363
     * The vertices are expressed as a percentage of the underlying cell width as
2364
     * follows (rhs values are in pixels):
2365
     *
2366
     *       x1 = X / W *1024
2367
     *       y1 = Y / H *256
2368
     *       x2 = (X-1) / W *1024
2369
     *       y2 = (Y-1) / H *256
2370
     *
2371
     *       Where:  X is distance from the left side of the underlying cell
2372
     *               Y is distance from the top of the underlying cell
2373
     *               W is the width of the cell
2374
     *               H is the height of the cell
2375
     * The SDK incorrectly states that the height should be expressed as a
2376
     *        percentage of 1024.
2377
     *
2378
     * @access private
2379
     * @param integer $col_start Col containing upper left corner of object
2380
     * @param integer $row_start Row containing top left corner of object
2381
     * @param integer $x1        Distance to left side of object
2382
     * @param integer $y1        Distance to top of object
2383
     * @param integer $width     Width of image frame
2384
     * @param integer $height    Height of image frame
2385
     */
2386
    public function positionImage($col_start, $row_start, $x1, $y1, $width, $height)
2387
    {
2388
        // Initialise end cell to the same as the start cell
2389
        $col_end    = $col_start;  // Col containing lower right corner of object
2390
        $row_end    = $row_start;  // Row containing bottom right corner of object
2391
2392
        // Zero the specified offset if greater than the cell dimensions
2393
        if ($x1 >= \PhpSpreadsheet\Shared\Excel5::sizeCol($this->phpSheet, \PhpSpreadsheet\Cell::stringFromColumnIndex($col_start))) {
2394
            $x1 = 0;
2395
        }
2396
        if ($y1 >= \PhpSpreadsheet\Shared\Excel5::sizeRow($this->phpSheet, $row_start + 1)) {
2397
            $y1 = 0;
2398
        }
2399
2400
        $width      = $width  + $x1 -1;
2401
        $height     = $height + $y1 -1;
2402
2403
        // Subtract the underlying cell widths to find the end cell of the image
2404
        while ($width >= \PhpSpreadsheet\Shared\Excel5::sizeCol($this->phpSheet, \PhpSpreadsheet\Cell::stringFromColumnIndex($col_end))) {
2405
            $width -= \PhpSpreadsheet\Shared\Excel5::sizeCol($this->phpSheet, \PhpSpreadsheet\Cell::stringFromColumnIndex($col_end));
2406
            ++$col_end;
2407
        }
2408
2409
        // Subtract the underlying cell heights to find the end cell of the image
2410
        while ($height >= \PhpSpreadsheet\Shared\Excel5::sizeRow($this->phpSheet, $row_end + 1)) {
2411
            $height -= \PhpSpreadsheet\Shared\Excel5::sizeRow($this->phpSheet, $row_end + 1);
2412
            ++$row_end;
2413
        }
2414
2415
        // Bitmap isn't allowed to start or finish in a hidden cell, i.e. a cell
2416
        // with zero eight or width.
2417
        //
2418
        if (\PhpSpreadsheet\Shared\Excel5::sizeCol($this->phpSheet, \PhpSpreadsheet\Cell::stringFromColumnIndex($col_start)) == 0) {
2419
            return;
2420
        }
2421
        if (\PhpSpreadsheet\Shared\Excel5::sizeCol($this->phpSheet, \PhpSpreadsheet\Cell::stringFromColumnIndex($col_end))   == 0) {
2422
            return;
2423
        }
2424
        if (\PhpSpreadsheet\Shared\Excel5::sizeRow($this->phpSheet, $row_start + 1) == 0) {
2425
            return;
2426
        }
2427
        if (\PhpSpreadsheet\Shared\Excel5::sizeRow($this->phpSheet, $row_end + 1)   == 0) {
2428
            return;
2429
        }
2430
2431
        // Convert the pixel values to the percentage value expected by Excel
2432
        $x1 = $x1     / \PhpSpreadsheet\Shared\Excel5::sizeCol($this->phpSheet, \PhpSpreadsheet\Cell::stringFromColumnIndex($col_start))   * 1024;
2433
        $y1 = $y1     / \PhpSpreadsheet\Shared\Excel5::sizeRow($this->phpSheet, $row_start + 1)   *  256;
2434
        $x2 = $width  / \PhpSpreadsheet\Shared\Excel5::sizeCol($this->phpSheet, \PhpSpreadsheet\Cell::stringFromColumnIndex($col_end))     * 1024; // Distance to right side of object
2435
        $y2 = $height / \PhpSpreadsheet\Shared\Excel5::sizeRow($this->phpSheet, $row_end + 1)     *  256; // Distance to bottom of object
2436
2437
        $this->writeObjPicture($col_start, $x1, $row_start, $y1, $col_end, $x2, $row_end, $y2);
2438
    }
2439
2440
    /**
2441
     * Store the OBJ record that precedes an IMDATA record. This could be generalise
2442
     * to support other Excel objects.
2443
     *
2444
     * @param integer $colL Column containing upper left corner of object
2445
     * @param integer $dxL  Distance from left side of cell
2446
     * @param integer $rwT  Row containing top left corner of object
2447
     * @param integer $dyT  Distance from top of cell
2448
     * @param integer $colR Column containing lower right corner of object
2449
     * @param integer $dxR  Distance from right of cell
2450
     * @param integer $rwB  Row containing bottom right corner of object
2451
     * @param integer $dyB  Distance from bottom of cell
2452
     */
2453
    private function writeObjPicture($colL, $dxL, $rwT, $dyT, $colR, $dxR, $rwB, $dyB)
2454
    {
2455
        $record      = 0x005d;   // Record identifier
2456
        $length      = 0x003c;   // Bytes to follow
2457
2458
        $cObj        = 0x0001;   // Count of objects in file (set to 1)
2459
        $OT          = 0x0008;   // Object type. 8 = Picture
2460
        $id          = 0x0001;   // Object ID
2461
        $grbit       = 0x0614;   // Option flags
2462
2463
        $cbMacro     = 0x0000;   // Length of FMLA structure
2464
        $Reserved1   = 0x0000;   // Reserved
2465
        $Reserved2   = 0x0000;   // Reserved
2466
2467
        $icvBack     = 0x09;     // Background colour
2468
        $icvFore     = 0x09;     // Foreground colour
2469
        $fls         = 0x00;     // Fill pattern
2470
        $fAuto       = 0x00;     // Automatic fill
2471
        $icv         = 0x08;     // Line colour
2472
        $lns         = 0xff;     // Line style
2473
        $lnw         = 0x01;     // Line weight
2474
        $fAutoB      = 0x00;     // Automatic border
2475
        $frs         = 0x0000;   // Frame style
2476
        $cf          = 0x0009;   // Image format, 9 = bitmap
2477
        $Reserved3   = 0x0000;   // Reserved
2478
        $cbPictFmla  = 0x0000;   // Length of FMLA structure
2479
        $Reserved4   = 0x0000;   // Reserved
2480
        $grbit2      = 0x0001;   // Option flags
2481
        $Reserved5   = 0x0000;   // Reserved
2482
2483
2484
        $header      = pack("vv", $record, $length);
2485
        $data        = pack("V", $cObj);
2486
        $data       .= pack("v", $OT);
2487
        $data       .= pack("v", $id);
2488
        $data       .= pack("v", $grbit);
2489
        $data       .= pack("v", $colL);
2490
        $data       .= pack("v", $dxL);
2491
        $data       .= pack("v", $rwT);
2492
        $data       .= pack("v", $dyT);
2493
        $data       .= pack("v", $colR);
2494
        $data       .= pack("v", $dxR);
2495
        $data       .= pack("v", $rwB);
2496
        $data       .= pack("v", $dyB);
2497
        $data       .= pack("v", $cbMacro);
2498
        $data       .= pack("V", $Reserved1);
2499
        $data       .= pack("v", $Reserved2);
2500
        $data       .= pack("C", $icvBack);
2501
        $data       .= pack("C", $icvFore);
2502
        $data       .= pack("C", $fls);
2503
        $data       .= pack("C", $fAuto);
2504
        $data       .= pack("C", $icv);
2505
        $data       .= pack("C", $lns);
2506
        $data       .= pack("C", $lnw);
2507
        $data       .= pack("C", $fAutoB);
2508
        $data       .= pack("v", $frs);
2509
        $data       .= pack("V", $cf);
2510
        $data       .= pack("v", $Reserved3);
2511
        $data       .= pack("v", $cbPictFmla);
2512
        $data       .= pack("v", $Reserved4);
2513
        $data       .= pack("v", $grbit2);
2514
        $data       .= pack("V", $Reserved5);
2515
2516
        $this->append($header . $data);
2517
    }
2518
2519
    /**
2520
     * Convert a GD-image into the internal format.
2521
     *
2522
     * @access private
2523
     * @param resource $image The image to process
2524
     * @return array Array with data and properties of the bitmap
2525
     */
2526
    public function processBitmapGd($image)
2527
    {
2528
        $width = imagesx($image);
2529
        $height = imagesy($image);
2530
2531
        $data = pack("Vvvvv", 0x000c, $width, $height, 0x01, 0x18);
2532
        for ($j=$height; $j--;) {
2533
            for ($i=0; $i < $width; ++$i) {
2534
                $color = imagecolorsforindex($image, imagecolorat($image, $i, $j));
2535
                foreach (array("red", "green", "blue") as $key) {
2536
                    $color[$key] = $color[$key] + round((255 - $color[$key]) * $color["alpha"] / 127);
2537
                }
2538
                $data .= chr($color["blue"]) . chr($color["green"]) . chr($color["red"]);
2539
            }
2540
            if (3*$width % 4) {
2541
                $data .= str_repeat("\x00", 4 - 3*$width % 4);
2542
            }
2543
        }
2544
2545
        return array($width, $height, strlen($data), $data);
2546
    }
2547
2548
    /**
2549
     * Convert a 24 bit bitmap into the modified internal format used by Windows.
2550
     * This is described in BITMAPCOREHEADER and BITMAPCOREINFO structures in the
2551
     * MSDN library.
2552
     *
2553
     * @access private
2554
     * @param string $bitmap The bitmap to process
2555
     * @return array Array with data and properties of the bitmap
2556
     */
2557
    public function processBitmap($bitmap)
2558
    {
2559
        // Open file.
2560
        $bmp_fd = @fopen($bitmap, "rb");
2561
        if (!$bmp_fd) {
2562
            throw new \PhpSpreadsheet\Writer\Exception("Couldn't import $bitmap");
2563
        }
2564
2565
        // Slurp the file into a string.
2566
        $data = fread($bmp_fd, filesize($bitmap));
2567
2568
        // Check that the file is big enough to be a bitmap.
2569
        if (strlen($data) <= 0x36) {
2570
            throw new \PhpSpreadsheet\Writer\Exception("$bitmap doesn't contain enough data.\n");
2571
        }
2572
2573
        // The first 2 bytes are used to identify the bitmap.
2574
        $identity = unpack("A2ident", $data);
2575
        if ($identity['ident'] != "BM") {
2576
            throw new \PhpSpreadsheet\Writer\Exception("$bitmap doesn't appear to be a valid bitmap image.\n");
2577
        }
2578
2579
        // Remove bitmap data: ID.
2580
        $data = substr($data, 2);
2581
2582
        // Read and remove the bitmap size. This is more reliable than reading
2583
        // the data size at offset 0x22.
2584
        //
2585
        $size_array   = unpack("Vsa", substr($data, 0, 4));
2586
        $size   = $size_array['sa'];
2587
        $data   = substr($data, 4);
2588
        $size  -= 0x36; // Subtract size of bitmap header.
2589
        $size  += 0x0C; // Add size of BIFF header.
2590
2591
        // Remove bitmap data: reserved, offset, header length.
2592
        $data = substr($data, 12);
2593
2594
        // Read and remove the bitmap width and height. Verify the sizes.
2595
        $width_and_height = unpack("V2", substr($data, 0, 8));
2596
        $width  = $width_and_height[1];
2597
        $height = $width_and_height[2];
2598
        $data   = substr($data, 8);
2599
        if ($width > 0xFFFF) {
2600
            throw new \PhpSpreadsheet\Writer\Exception("$bitmap: largest image width supported is 65k.\n");
2601
        }
2602
        if ($height > 0xFFFF) {
2603
            throw new \PhpSpreadsheet\Writer\Exception("$bitmap: largest image height supported is 65k.\n");
2604
        }
2605
2606
        // Read and remove the bitmap planes and bpp data. Verify them.
2607
        $planes_and_bitcount = unpack("v2", substr($data, 0, 4));
2608
        $data = substr($data, 4);
2609
        if ($planes_and_bitcount[2] != 24) { // Bitcount
2610
            throw new \PhpSpreadsheet\Writer\Exception("$bitmap isn't a 24bit true color bitmap.\n");
2611
        }
2612
        if ($planes_and_bitcount[1] != 1) {
2613
            throw new \PhpSpreadsheet\Writer\Exception("$bitmap: only 1 plane supported in bitmap image.\n");
2614
        }
2615
2616
        // Read and remove the bitmap compression. Verify compression.
2617
        $compression = unpack("Vcomp", substr($data, 0, 4));
2618
        $data = substr($data, 4);
2619
2620
        //$compression = 0;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% 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...
2621
        if ($compression['comp'] != 0) {
2622
            throw new \PhpSpreadsheet\Writer\Exception("$bitmap: compression not supported in bitmap image.\n");
2623
        }
2624
2625
        // Remove bitmap data: data size, hres, vres, colours, imp. colours.
2626
        $data = substr($data, 20);
2627
2628
        // Add the BITMAPCOREHEADER data
2629
        $header  = pack("Vvvvv", 0x000c, $width, $height, 0x01, 0x18);
2630
        $data    = $header . $data;
2631
2632
        return (array($width, $height, $size, $data));
2633
    }
2634
2635
    /**
2636
     * Store the window zoom factor. This should be a reduced fraction but for
2637
     * simplicity we will store all fractions with a numerator of 100.
2638
     */
2639 View Code Duplication
    private function writeZoom()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2640
    {
2641
        // If scale is 100 we don't need to write a record
2642
        if ($this->phpSheet->getSheetView()->getZoomScale() == 100) {
2643
            return;
2644
        }
2645
2646
        $record      = 0x00A0;               // Record identifier
2647
        $length      = 0x0004;               // Bytes to follow
2648
2649
        $header      = pack("vv", $record, $length);
2650
        $data        = pack("vv", $this->phpSheet->getSheetView()->getZoomScale(), 100);
2651
        $this->append($header . $data);
2652
    }
2653
2654
    /**
2655
     * Get Escher object
2656
     *
2657
     * @return \PhpSpreadsheet\Shared\Escher
2658
     */
2659
    public function getEscher()
2660
    {
2661
        return $this->escher;
2662
    }
2663
2664
    /**
2665
     * Set Escher object
2666
     *
2667
     * @param \PhpSpreadsheet\Shared\Escher $pValue
2668
     */
2669
    public function setEscher(\PhpSpreadsheet\Shared\Escher $pValue = null)
2670
    {
2671
        $this->escher = $pValue;
2672
    }
2673
2674
    /**
2675
     * Write MSODRAWING record
2676
     */
2677
    private function writeMsoDrawing()
2678
    {
2679
        // write the Escher stream if necessary
2680
        if (isset($this->escher)) {
2681
            $writer = new \PhpSpreadsheet\Writer\Excel5\Escher($this->escher);
2682
            $data = $writer->close();
2683
            $spOffsets = $writer->getSpOffsets();
2684
            $spTypes = $writer->getSpTypes();
2685
            // write the neccesary MSODRAWING, OBJ records
2686
2687
            // split the Escher stream
2688
            $spOffsets[0] = 0;
2689
            $nm = count($spOffsets) - 1; // number of shapes excluding first shape
2690
            for ($i = 1; $i <= $nm; ++$i) {
2691
                // MSODRAWING record
2692
                $record = 0x00EC;            // Record identifier
2693
2694
                // chunk of Escher stream for one shape
2695
                $dataChunk = substr($data, $spOffsets[$i -1], $spOffsets[$i] - $spOffsets[$i - 1]);
2696
2697
                $length = strlen($dataChunk);
2698
                $header = pack("vv", $record, $length);
2699
2700
                $this->append($header . $dataChunk);
2701
2702
                // OBJ record
2703
                $record = 0x005D; // record identifier
2704
                $objData = '';
2705
2706
                // ftCmo
2707
                if ($spTypes[$i] == 0x00C9) {
2708
                    // Add ftCmo (common object data) subobject
2709
                    $objData .=
2710
                        pack(
2711
                            'vvvvvVVV',
2712
                            0x0015, // 0x0015 = ftCmo
2713
                            0x0012, // length of ftCmo data
2714
                            0x0014, // object type, 0x0014 = filter
2715
                            $i, // object id number, Excel seems to use 1-based index, local for the sheet
2716
                            0x2101, // option flags, 0x2001 is what OpenOffice.org uses
2717
                            0, // reserved
2718
                            0, // reserved
2719
                            0  // reserved
2720
                        );
2721
2722
                    // Add ftSbs Scroll bar subobject
2723
                    $objData .= pack('vv', 0x00C, 0x0014);
2724
                    $objData .= pack('H*', '0000000000000000640001000A00000010000100');
2725
                    // Add ftLbsData (List box data) subobject
2726
                    $objData .= pack('vv', 0x0013, 0x1FEE);
2727
                    $objData .= pack('H*', '00000000010001030000020008005700');
2728
                } else {
2729
                    // Add ftCmo (common object data) subobject
2730
                    $objData .=
2731
                        pack(
2732
                            'vvvvvVVV',
2733
                            0x0015, // 0x0015 = ftCmo
2734
                            0x0012, // length of ftCmo data
2735
                            0x0008, // object type, 0x0008 = picture
2736
                            $i, // object id number, Excel seems to use 1-based index, local for the sheet
2737
                            0x6011, // option flags, 0x6011 is what OpenOffice.org uses
2738
                            0, // reserved
2739
                            0, // reserved
2740
                            0  // reserved
2741
                        );
2742
                }
2743
2744
                // ftEnd
2745
                $objData .=
2746
                    pack(
2747
                        'vv',
2748
                        0x0000, // 0x0000 = ftEnd
2749
                        0x0000  // length of ftEnd data
2750
                    );
2751
2752
                $length = strlen($objData);
2753
                $header = pack('vv', $record, $length);
2754
                $this->append($header . $objData);
2755
            }
2756
        }
2757
    }
2758
2759
    /**
2760
     * Store the DATAVALIDATIONS and DATAVALIDATION records.
2761
     */
2762
    private function writeDataValidity()
2763
    {
2764
        // Datavalidation collection
2765
        $dataValidationCollection = $this->phpSheet->getDataValidationCollection();
2766
2767
        // Write data validations?
2768
        if (!empty($dataValidationCollection)) {
2769
            // DATAVALIDATIONS record
2770
            $record = 0x01B2;      // Record identifier
2771
            $length = 0x0012;      // Bytes to follow
2772
2773
            $grbit  = 0x0000;       // Prompt box at cell, no cached validity data at DV records
2774
            $horPos = 0x00000000;  // Horizontal position of prompt box, if fixed position
2775
            $verPos = 0x00000000;  // Vertical position of prompt box, if fixed position
2776
            $objId  = 0xFFFFFFFF;  // Object identifier of drop down arrow object, or -1 if not visible
2777
2778
            $header = pack('vv', $record, $length);
2779
            $data   = pack('vVVVV', $grbit, $horPos, $verPos, $objId, count($dataValidationCollection));
2780
            $this->append($header.$data);
2781
2782
            // DATAVALIDATION records
2783
            $record = 0x01BE;              // Record identifier
2784
2785
            foreach ($dataValidationCollection as $cellCoordinate => $dataValidation) {
2786
                // initialize record data
2787
                $data = '';
0 ignored issues
show
Unused Code introduced by
$data is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2788
2789
                // options
2790
                $options = 0x00000000;
2791
2792
                // data type
2793
                $type = $dataValidation->getType();
2794 View Code Duplication
                switch ($type) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2795
                    case \PhpSpreadsheet\Cell\DataValidation::TYPE_NONE:
2796
                        $type = 0x00;
2797
                        break;
2798
                    case \PhpSpreadsheet\Cell\DataValidation::TYPE_WHOLE:
2799
                        $type = 0x01;
2800
                        break;
2801
                    case \PhpSpreadsheet\Cell\DataValidation::TYPE_DECIMAL:
2802
                        $type = 0x02;
2803
                        break;
2804
                    case \PhpSpreadsheet\Cell\DataValidation::TYPE_LIST:
2805
                        $type = 0x03;
2806
                        break;
2807
                    case \PhpSpreadsheet\Cell\DataValidation::TYPE_DATE:
2808
                        $type = 0x04;
2809
                        break;
2810
                    case \PhpSpreadsheet\Cell\DataValidation::TYPE_TIME:
2811
                        $type = 0x05;
2812
                        break;
2813
                    case \PhpSpreadsheet\Cell\DataValidation::TYPE_TEXTLENGTH:
2814
                        $type = 0x06;
2815
                        break;
2816
                    case \PhpSpreadsheet\Cell\DataValidation::TYPE_CUSTOM:
2817
                        $type = 0x07;
2818
                        break;
2819
                }
2820
                $options |= $type << 0;
2821
2822
                // error style
2823
                $errorStyle = $dataValidation->getType();
2824 View Code Duplication
                switch ($errorStyle) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2825
                    case \PhpSpreadsheet\Cell\DataValidation::STYLE_STOP:
2826
                        $errorStyle = 0x00;
2827
                        break;
2828
                    case \PhpSpreadsheet\Cell\DataValidation::STYLE_WARNING:
2829
                        $errorStyle = 0x01;
2830
                        break;
2831
                    case \PhpSpreadsheet\Cell\DataValidation::STYLE_INFORMATION:
2832
                        $errorStyle = 0x02;
2833
                        break;
2834
                }
2835
                $options |= $errorStyle << 4;
2836
2837
                // explicit formula?
2838
                if ($type == 0x03 && preg_match('/^\".*\"$/', $dataValidation->getFormula1())) {
2839
                    $options |= 0x01 << 7;
2840
                }
2841
2842
                // empty cells allowed
2843
                $options |= $dataValidation->getAllowBlank() << 8;
2844
2845
                // show drop down
2846
                $options |= (!$dataValidation->getShowDropDown()) << 9;
2847
2848
                // show input message
2849
                $options |= $dataValidation->getShowInputMessage() << 18;
2850
2851
                // show error message
2852
                $options |= $dataValidation->getShowErrorMessage() << 19;
2853
2854
                // condition operator
2855
                $operator = $dataValidation->getOperator();
2856 View Code Duplication
                switch ($operator) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2857
                    case \PhpSpreadsheet\Cell\DataValidation::OPERATOR_BETWEEN:
2858
                        $operator = 0x00;
2859
                        break;
2860
                    case \PhpSpreadsheet\Cell\DataValidation::OPERATOR_NOTBETWEEN:
2861
                        $operator = 0x01;
2862
                        break;
2863
                    case \PhpSpreadsheet\Cell\DataValidation::OPERATOR_EQUAL:
2864
                        $operator = 0x02;
2865
                        break;
2866
                    case \PhpSpreadsheet\Cell\DataValidation::OPERATOR_NOTEQUAL:
2867
                        $operator = 0x03;
2868
                        break;
2869
                    case \PhpSpreadsheet\Cell\DataValidation::OPERATOR_GREATERTHAN:
2870
                        $operator = 0x04;
2871
                        break;
2872
                    case \PhpSpreadsheet\Cell\DataValidation::OPERATOR_LESSTHAN:
2873
                        $operator = 0x05;
2874
                        break;
2875
                    case \PhpSpreadsheet\Cell\DataValidation::OPERATOR_GREATERTHANOREQUAL:
2876
                        $operator = 0x06;
2877
                        break;
2878
                    case \PhpSpreadsheet\Cell\DataValidation::OPERATOR_LESSTHANOREQUAL:
2879
                        $operator = 0x07;
2880
                        break;
2881
                }
2882
                $options |= $operator << 20;
2883
2884
                $data        = pack('V', $options);
2885
2886
                // prompt title
2887
                $promptTitle = $dataValidation->getPromptTitle() !== '' ?
2888
                    $dataValidation->getPromptTitle() : chr(0);
2889
                $data .= \PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($promptTitle);
2890
2891
                // error title
2892
                $errorTitle = $dataValidation->getErrorTitle() !== '' ?
2893
                    $dataValidation->getErrorTitle() : chr(0);
2894
                $data .= \PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($errorTitle);
2895
2896
                // prompt text
2897
                $prompt = $dataValidation->getPrompt() !== '' ?
2898
                    $dataValidation->getPrompt() : chr(0);
2899
                $data .= \PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($prompt);
2900
2901
                // error text
2902
                $error = $dataValidation->getError() !== '' ?
2903
                    $dataValidation->getError() : chr(0);
2904
                $data .= \PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($error);
2905
2906
                // formula 1
2907
                try {
2908
                    $formula1 = $dataValidation->getFormula1();
2909
                    if ($type == 0x03) { // list type
2910
                        $formula1 = str_replace(',', chr(0), $formula1);
2911
                    }
2912
                    $this->parser->parse($formula1);
2913
                    $formula1 = $this->parser->toReversePolish();
2914
                    $sz1 = strlen($formula1);
2915
                } catch (\PhpSpreadsheet\Exception $e) {
2916
                    $sz1 = 0;
2917
                    $formula1 = '';
2918
                }
2919
                $data .= pack('vv', $sz1, 0x0000);
2920
                $data .= $formula1;
2921
2922
                // formula 2
2923
                try {
2924
                    $formula2 = $dataValidation->getFormula2();
2925
                    if ($formula2 === '') {
2926
                        throw new \PhpSpreadsheet\Writer\Exception('No formula2');
2927
                    }
2928
                    $this->parser->parse($formula2);
2929
                    $formula2 = $this->parser->toReversePolish();
2930
                    $sz2 = strlen($formula2);
2931
                } catch (\PhpSpreadsheet\Exception $e) {
2932
                    $sz2 = 0;
2933
                    $formula2 = '';
2934
                }
2935
                $data .= pack('vv', $sz2, 0x0000);
2936
                $data .= $formula2;
2937
2938
                // cell range address list
2939
                $data .= pack('v', 0x0001);
2940
                $data .= $this->writeBIFF8CellRangeAddressFixed($cellCoordinate);
2941
2942
                $length = strlen($data);
2943
                $header = pack("vv", $record, $length);
2944
2945
                $this->append($header . $data);
2946
            }
2947
        }
2948
    }
2949
2950
    /**
2951
     * Map Error code
2952
     *
2953
     * @param string $errorCode
2954
     * @return int
2955
     */
2956
    private static function mapErrorCode($errorCode)
2957
    {
2958
        switch ($errorCode) {
2959
            case '#NULL!':
2960
                return 0x00;
2961
            case '#DIV/0!':
2962
                return 0x07;
2963
            case '#VALUE!':
2964
                return 0x0F;
2965
            case '#REF!':
2966
                return 0x17;
2967
            case '#NAME?':
2968
                return 0x1D;
2969
            case '#NUM!':
2970
                return 0x24;
2971
            case '#N/A':
2972
                return 0x2A;
2973
        }
2974
2975
        return 0;
2976
    }
2977
2978
    /**
2979
     * Write PLV Record
2980
     */
2981
    private function writePageLayoutView()
2982
    {
2983
        $record      = 0x088B;               // Record identifier
2984
        $length      = 0x0010;               // Bytes to follow
2985
2986
        $rt         = 0x088B; // 2
2987
        $grbitFrt   = 0x0000; // 2
2988
        $reserved   = 0x0000000000000000; // 8
0 ignored issues
show
Unused Code introduced by
$reserved is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2989
        $wScalvePLV = $this->phpSheet->getSheetView()->getZoomScale(); // 2
2990
2991
        // The options flags that comprise $grbit
2992
        if ($this->phpSheet->getSheetView()->getView() == \PhpSpreadsheet\Worksheet\SheetView::SHEETVIEW_PAGE_LAYOUT) {
2993
            $fPageLayoutView   = 1;
2994
        } else {
2995
            $fPageLayoutView   = 0;
2996
        }
2997
        $fRulerVisible     = 0;
2998
        $fWhitespaceHidden = 0;
2999
3000
        $grbit      = $fPageLayoutView; // 2
3001
        $grbit        |= $fRulerVisible       << 1;
3002
        $grbit        |= $fWhitespaceHidden  << 3;
3003
3004
        $header      = pack("vv", $record, $length);
3005
        $data      = pack("vvVVvv", $rt, $grbitFrt, 0x00000000, 0x00000000, $wScalvePLV, $grbit);
3006
        $this->append($header . $data);
3007
    }
3008
3009
    /**
3010
     * Write CFRule Record
3011
     * @param \PhpSpreadsheet\Style\Conditional $conditional
3012
     */
3013
    private function writeCFRule(\PhpSpreadsheet\Style\Conditional $conditional)
3014
    {
3015
        $record      = 0x01B1;               // Record identifier
3016
3017
        // $type : Type of the CF
3018
        // $operatorType : Comparison operator
3019
        if ($conditional->getConditionType() == \PhpSpreadsheet\Style\Conditional::CONDITION_EXPRESSION) {
3020
            $type = 0x02;
3021
            $operatorType = 0x00;
3022
        } elseif ($conditional->getConditionType() == \PhpSpreadsheet\Style\Conditional::CONDITION_CELLIS) {
3023
            $type = 0x01;
3024
3025
            switch ($conditional->getOperatorType()) {
3026
                case \PhpSpreadsheet\Style\Conditional::OPERATOR_NONE:
3027
                    $operatorType = 0x00;
3028
                    break;
3029
                case \PhpSpreadsheet\Style\Conditional::OPERATOR_EQUAL:
3030
                    $operatorType = 0x03;
3031
                    break;
3032
                case \PhpSpreadsheet\Style\Conditional::OPERATOR_GREATERTHAN:
3033
                    $operatorType = 0x05;
3034
                    break;
3035
                case \PhpSpreadsheet\Style\Conditional::OPERATOR_GREATERTHANOREQUAL:
3036
                    $operatorType = 0x07;
3037
                    break;
3038
                case \PhpSpreadsheet\Style\Conditional::OPERATOR_LESSTHAN:
3039
                    $operatorType = 0x06;
3040
                    break;
3041
                case \PhpSpreadsheet\Style\Conditional::OPERATOR_LESSTHANOREQUAL:
3042
                    $operatorType = 0x08;
3043
                    break;
3044
                case \PhpSpreadsheet\Style\Conditional::OPERATOR_NOTEQUAL:
3045
                    $operatorType = 0x04;
3046
                    break;
3047
                case \PhpSpreadsheet\Style\Conditional::OPERATOR_BETWEEN:
3048
                    $operatorType = 0x01;
3049
                    break;
3050
                    // not OPERATOR_NOTBETWEEN 0x02
3051
            }
3052
        }
3053
3054
        // $szValue1 : size of the formula data for first value or formula
3055
        // $szValue2 : size of the formula data for second value or formula
3056
        $arrConditions = $conditional->getConditions();
3057
        $numConditions = sizeof($arrConditions);
3058
        if ($numConditions == 1) {
3059
            $szValue1 = ($arrConditions[0] <= 65535 ? 3 : 0x0000);
3060
            $szValue2 = 0x0000;
3061
            $operand1 = pack('Cv', 0x1E, $arrConditions[0]);
3062
            $operand2 = null;
3063
        } elseif ($numConditions == 2 && ($conditional->getOperatorType() == \PhpSpreadsheet\Style\Conditional::OPERATOR_BETWEEN)) {
3064
            $szValue1 = ($arrConditions[0] <= 65535 ? 3 : 0x0000);
3065
            $szValue2 = ($arrConditions[1] <= 65535 ? 3 : 0x0000);
3066
            $operand1 = pack('Cv', 0x1E, $arrConditions[0]);
3067
            $operand2 = pack('Cv', 0x1E, $arrConditions[1]);
3068
        } else {
3069
            $szValue1 = 0x0000;
3070
            $szValue2 = 0x0000;
3071
            $operand1 = null;
3072
            $operand2 = null;
3073
        }
3074
3075
        // $flags : Option flags
3076
        // Alignment
3077
        $bAlignHz = ($conditional->getStyle()->getAlignment()->getHorizontal() == null ? 1 : 0);
3078
        $bAlignVt = ($conditional->getStyle()->getAlignment()->getVertical() == null ? 1 : 0);
3079
        $bAlignWrapTx = ($conditional->getStyle()->getAlignment()->getWrapText() == false ? 1 : 0);
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...
3080
        $bTxRotation = ($conditional->getStyle()->getAlignment()->getTextRotation() == null ? 1 : 0);
3081
        $bIndent = ($conditional->getStyle()->getAlignment()->getIndent() == 0 ? 1 : 0);
3082
        $bShrinkToFit = ($conditional->getStyle()->getAlignment()->getShrinkToFit() == false ? 1 : 0);
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...
3083
        if ($bAlignHz == 0 || $bAlignVt == 0 || $bAlignWrapTx == 0 || $bTxRotation == 0 || $bIndent == 0 || $bShrinkToFit == 0) {
3084
            $bFormatAlign = 1;
3085
        } else {
3086
            $bFormatAlign = 0;
3087
        }
3088
        // Protection
3089
        $bProtLocked = ($conditional->getStyle()->getProtection()->getLocked() == null ? 1 : 0);
3090
        $bProtHidden = ($conditional->getStyle()->getProtection()->getHidden() == null ? 1 : 0);
3091
        if ($bProtLocked == 0 || $bProtHidden == 0) {
3092
            $bFormatProt = 1;
3093
        } else {
3094
            $bFormatProt = 0;
3095
        }
3096
        // Border
3097
        $bBorderLeft = ($conditional->getStyle()->getBorders()->getLeft()->getColor()->getARGB() == \PhpSpreadsheet\Style\Color::COLOR_BLACK
3098
                        && $conditional->getStyle()->getBorders()->getLeft()->getBorderStyle() == \PhpSpreadsheet\Style\Border::BORDER_NONE ? 1 : 0);
3099
        $bBorderRight = ($conditional->getStyle()->getBorders()->getRight()->getColor()->getARGB() == \PhpSpreadsheet\Style\Color::COLOR_BLACK
3100
                        && $conditional->getStyle()->getBorders()->getRight()->getBorderStyle() == \PhpSpreadsheet\Style\Border::BORDER_NONE ? 1 : 0);
3101
        $bBorderTop = ($conditional->getStyle()->getBorders()->getTop()->getColor()->getARGB() == \PhpSpreadsheet\Style\Color::COLOR_BLACK
3102
                        && $conditional->getStyle()->getBorders()->getTop()->getBorderStyle() == \PhpSpreadsheet\Style\Border::BORDER_NONE ? 1 : 0);
3103
        $bBorderBottom = ($conditional->getStyle()->getBorders()->getBottom()->getColor()->getARGB() == \PhpSpreadsheet\Style\Color::COLOR_BLACK
3104
                        && $conditional->getStyle()->getBorders()->getBottom()->getBorderStyle() == \PhpSpreadsheet\Style\Border::BORDER_NONE ? 1 : 0);
3105
        if ($bBorderLeft == 0 || $bBorderRight == 0 || $bBorderTop == 0 || $bBorderBottom == 0) {
3106
            $bFormatBorder = 1;
3107
        } else {
3108
            $bFormatBorder = 0;
3109
        }
3110
        // Pattern
3111
        $bFillStyle = ($conditional->getStyle()->getFill()->getFillType() == null ? 0 : 1);
3112
        $bFillColor = ($conditional->getStyle()->getFill()->getStartColor()->getARGB() == null ? 0 : 1);
3113
        $bFillColorBg = ($conditional->getStyle()->getFill()->getEndColor()->getARGB() == null ? 0 : 1);
3114
        if ($bFillStyle == 0 || $bFillColor == 0 || $bFillColorBg == 0) {
3115
            $bFormatFill = 1;
3116
        } else {
3117
            $bFormatFill = 0;
3118
        }
3119
        // Font
3120
        if ($conditional->getStyle()->getFont()->getName() != null
3121
            || $conditional->getStyle()->getFont()->getSize() != null
3122
            || $conditional->getStyle()->getFont()->getBold() != null
3123
            || $conditional->getStyle()->getFont()->getItalic() != null
3124
            || $conditional->getStyle()->getFont()->getSuperScript() != null
3125
            || $conditional->getStyle()->getFont()->getSubScript() != null
3126
            || $conditional->getStyle()->getFont()->getUnderline() != null
3127
            || $conditional->getStyle()->getFont()->getStrikethrough() != null
3128
            || $conditional->getStyle()->getFont()->getColor()->getARGB() != null) {
3129
            $bFormatFont = 1;
3130
        } else {
3131
            $bFormatFont = 0;
3132
        }
3133
        // Alignment
3134
        $flags = 0;
3135
        $flags |= (1 == $bAlignHz      ? 0x00000001 : 0);
3136
        $flags |= (1 == $bAlignVt      ? 0x00000002 : 0);
3137
        $flags |= (1 == $bAlignWrapTx  ? 0x00000004 : 0);
3138
        $flags |= (1 == $bTxRotation   ? 0x00000008 : 0);
3139
        // Justify last line flag
3140
        $flags |= (1 == 1              ? 0x00000010 : 0);
3141
        $flags |= (1 == $bIndent       ? 0x00000020 : 0);
3142
        $flags |= (1 == $bShrinkToFit  ? 0x00000040 : 0);
3143
        // Default
3144
        $flags |= (1 == 1              ? 0x00000080 : 0);
3145
        // Protection
3146
        $flags |= (1 == $bProtLocked   ? 0x00000100 : 0);
3147
        $flags |= (1 == $bProtHidden   ? 0x00000200 : 0);
3148
        // Border
3149
        $flags |= (1 == $bBorderLeft   ? 0x00000400 : 0);
3150
        $flags |= (1 == $bBorderRight  ? 0x00000800 : 0);
3151
        $flags |= (1 == $bBorderTop    ? 0x00001000 : 0);
3152
        $flags |= (1 == $bBorderBottom ? 0x00002000 : 0);
3153
        $flags |= (1 == 1              ? 0x00004000 : 0); // Top left to Bottom right border
3154
        $flags |= (1 == 1              ? 0x00008000 : 0); // Bottom left to Top right border
3155
        // Pattern
3156
        $flags |= (1 == $bFillStyle    ? 0x00010000 : 0);
3157
        $flags |= (1 == $bFillColor    ? 0x00020000 : 0);
3158
        $flags |= (1 == $bFillColorBg  ? 0x00040000 : 0);
3159
        $flags |= (1 == 1              ? 0x00380000 : 0);
3160
        // Font
3161
        $flags |= (1 == $bFormatFont   ? 0x04000000 : 0);
3162
        // Alignment:
3163
        $flags |= (1 == $bFormatAlign  ? 0x08000000 : 0);
3164
        // Border
3165
        $flags |= (1 == $bFormatBorder ? 0x10000000 : 0);
3166
        // Pattern
3167
        $flags |= (1 == $bFormatFill   ? 0x20000000 : 0);
3168
        // Protection
3169
        $flags |= (1 == $bFormatProt   ? 0x40000000 : 0);
3170
        // Text direction
3171
        $flags |= (1 == 0              ? 0x80000000 : 0);
3172
3173
        // Data Blocks
3174
        if ($bFormatFont == 1) {
3175
            // Font Name
3176
            if ($conditional->getStyle()->getFont()->getName() == null) {
3177
                $dataBlockFont =  pack('VVVVVVVV', 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000);
3178
                $dataBlockFont .= pack('VVVVVVVV', 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000);
3179
            } else {
3180
                $dataBlockFont = \PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($conditional->getStyle()->getFont()->getName());
3181
            }
3182
            // Font Size
3183
            if ($conditional->getStyle()->getFont()->getSize() == null) {
3184
                $dataBlockFont .= pack('V', 20 * 11);
3185
            } else {
3186
                $dataBlockFont .= pack('V', 20 * $conditional->getStyle()->getFont()->getSize());
3187
            }
3188
            // Font Options
3189
            $dataBlockFont .= pack('V', 0);
3190
            // Font weight
3191
            if ($conditional->getStyle()->getFont()->getBold() == 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...
3192
                $dataBlockFont .= pack('v', 0x02BC);
3193
            } else {
3194
                $dataBlockFont .= pack('v', 0x0190);
3195
            }
3196
            // Escapement type
3197
            if ($conditional->getStyle()->getFont()->getSubScript() == 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...
3198
                $dataBlockFont .= pack('v', 0x02);
3199
                $fontEscapement = 0;
3200
            } elseif ($conditional->getStyle()->getFont()->getSuperScript() == 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...
3201
                $dataBlockFont .= pack('v', 0x01);
3202
                $fontEscapement = 0;
3203
            } else {
3204
                $dataBlockFont .= pack('v', 0x00);
3205
                $fontEscapement = 1;
3206
            }
3207
            // Underline type
3208
            switch ($conditional->getStyle()->getFont()->getUnderline()) {
3209
                case \PhpSpreadsheet\Style\Font::UNDERLINE_NONE:
3210
                    $dataBlockFont .= pack('C', 0x00);
3211
                    $fontUnderline = 0;
3212
                    break;
3213
                case \PhpSpreadsheet\Style\Font::UNDERLINE_DOUBLE:
3214
                    $dataBlockFont .= pack('C', 0x02);
3215
                    $fontUnderline = 0;
3216
                    break;
3217
                case \PhpSpreadsheet\Style\Font::UNDERLINE_DOUBLEACCOUNTING:
3218
                    $dataBlockFont .= pack('C', 0x22);
3219
                    $fontUnderline = 0;
3220
                    break;
3221
                case \PhpSpreadsheet\Style\Font::UNDERLINE_SINGLE:
3222
                    $dataBlockFont .= pack('C', 0x01);
3223
                    $fontUnderline = 0;
3224
                    break;
3225
                case \PhpSpreadsheet\Style\Font::UNDERLINE_SINGLEACCOUNTING:
3226
                    $dataBlockFont .= pack('C', 0x21);
3227
                    $fontUnderline = 0;
3228
                    break;
3229
                default:
3230
                    $dataBlockFont .= pack('C', 0x00);
3231
                    $fontUnderline = 1;
3232
                    break;
3233
            }
3234
            // Not used (3)
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% 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...
3235
            $dataBlockFont .= pack('vC', 0x0000, 0x00);
3236
            // Font color index
3237 View Code Duplication
            switch ($conditional->getStyle()->getFont()->getColor()->getRGB()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
3238
                case '000000':
3239
                    $colorIdx = 0x08;
3240
                    break;
3241
                case 'FFFFFF':
3242
                    $colorIdx = 0x09;
3243
                    break;
3244
                case 'FF0000':
3245
                    $colorIdx = 0x0A;
3246
                    break;
3247
                case '00FF00':
3248
                    $colorIdx = 0x0B;
3249
                    break;
3250
                case '0000FF':
3251
                    $colorIdx = 0x0C;
3252
                    break;
3253
                case 'FFFF00':
3254
                    $colorIdx = 0x0D;
3255
                    break;
3256
                case 'FF00FF':
3257
                    $colorIdx = 0x0E;
3258
                    break;
3259
                case '00FFFF':
3260
                    $colorIdx = 0x0F;
3261
                    break;
3262
                case '800000':
3263
                    $colorIdx = 0x10;
3264
                    break;
3265
                case '008000':
3266
                    $colorIdx = 0x11;
3267
                    break;
3268
                case '000080':
3269
                    $colorIdx = 0x12;
3270
                    break;
3271
                case '808000':
3272
                    $colorIdx = 0x13;
3273
                    break;
3274
                case '800080':
3275
                    $colorIdx = 0x14;
3276
                    break;
3277
                case '008080':
3278
                    $colorIdx = 0x15;
3279
                    break;
3280
                case 'C0C0C0':
3281
                    $colorIdx = 0x16;
3282
                    break;
3283
                case '808080':
3284
                    $colorIdx = 0x17;
3285
                    break;
3286
                case '9999FF':
3287
                    $colorIdx = 0x18;
3288
                    break;
3289
                case '993366':
3290
                    $colorIdx = 0x19;
3291
                    break;
3292
                case 'FFFFCC':
3293
                    $colorIdx = 0x1A;
3294
                    break;
3295
                case 'CCFFFF':
3296
                    $colorIdx = 0x1B;
3297
                    break;
3298
                case '660066':
3299
                    $colorIdx = 0x1C;
3300
                    break;
3301
                case 'FF8080':
3302
                    $colorIdx = 0x1D;
3303
                    break;
3304
                case '0066CC':
3305
                    $colorIdx = 0x1E;
3306
                    break;
3307
                case 'CCCCFF':
3308
                    $colorIdx = 0x1F;
3309
                    break;
3310
                case '000080':
3311
                    $colorIdx = 0x20;
3312
                    break;
3313
                case 'FF00FF':
3314
                    $colorIdx = 0x21;
3315
                    break;
3316
                case 'FFFF00':
3317
                    $colorIdx = 0x22;
3318
                    break;
3319
                case '00FFFF':
3320
                    $colorIdx = 0x23;
3321
                    break;
3322
                case '800080':
3323
                    $colorIdx = 0x24;
3324
                    break;
3325
                case '800000':
3326
                    $colorIdx = 0x25;
3327
                    break;
3328
                case '008080':
3329
                    $colorIdx = 0x26;
3330
                    break;
3331
                case '0000FF':
3332
                    $colorIdx = 0x27;
3333
                    break;
3334
                case '00CCFF':
3335
                    $colorIdx = 0x28;
3336
                    break;
3337
                case 'CCFFFF':
3338
                    $colorIdx = 0x29;
3339
                    break;
3340
                case 'CCFFCC':
3341
                    $colorIdx = 0x2A;
3342
                    break;
3343
                case 'FFFF99':
3344
                    $colorIdx = 0x2B;
3345
                    break;
3346
                case '99CCFF':
3347
                    $colorIdx = 0x2C;
3348
                    break;
3349
                case 'FF99CC':
3350
                    $colorIdx = 0x2D;
3351
                    break;
3352
                case 'CC99FF':
3353
                    $colorIdx = 0x2E;
3354
                    break;
3355
                case 'FFCC99':
3356
                    $colorIdx = 0x2F;
3357
                    break;
3358
                case '3366FF':
3359
                    $colorIdx = 0x30;
3360
                    break;
3361
                case '33CCCC':
3362
                    $colorIdx = 0x31;
3363
                    break;
3364
                case '99CC00':
3365
                    $colorIdx = 0x32;
3366
                    break;
3367
                case 'FFCC00':
3368
                    $colorIdx = 0x33;
3369
                    break;
3370
                case 'FF9900':
3371
                    $colorIdx = 0x34;
3372
                    break;
3373
                case 'FF6600':
3374
                    $colorIdx = 0x35;
3375
                    break;
3376
                case '666699':
3377
                    $colorIdx = 0x36;
3378
                    break;
3379
                case '969696':
3380
                    $colorIdx = 0x37;
3381
                    break;
3382
                case '003366':
3383
                    $colorIdx = 0x38;
3384
                    break;
3385
                case '339966':
3386
                    $colorIdx = 0x39;
3387
                    break;
3388
                case '003300':
3389
                    $colorIdx = 0x3A;
3390
                    break;
3391
                case '333300':
3392
                    $colorIdx = 0x3B;
3393
                    break;
3394
                case '993300':
3395
                    $colorIdx = 0x3C;
3396
                    break;
3397
                case '993366':
3398
                    $colorIdx = 0x3D;
3399
                    break;
3400
                case '333399':
3401
                    $colorIdx = 0x3E;
3402
                    break;
3403
                case '333333':
3404
                    $colorIdx = 0x3F;
3405
                    break;
3406
                default:
3407
                    $colorIdx = 0x00;
3408
                    break;
3409
            }
3410
            $dataBlockFont .= pack('V', $colorIdx);
3411
            // Not used (4)
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% 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...
3412
            $dataBlockFont .= pack('V', 0x00000000);
3413
            // Options flags for modified font attributes
3414
            $optionsFlags = 0;
3415
            $optionsFlagsBold = ($conditional->getStyle()->getFont()->getBold() == null ? 1 : 0);
3416
            $optionsFlags |= (1 == $optionsFlagsBold  ? 0x00000002 : 0);
3417
            $optionsFlags |= (1 == 1                  ? 0x00000008 : 0);
3418
            $optionsFlags |= (1 == 1                  ? 0x00000010 : 0);
3419
            $optionsFlags |= (1 == 0                  ? 0x00000020 : 0);
3420
            $optionsFlags |= (1 == 1                  ? 0x00000080 : 0);
3421
            $dataBlockFont .= pack('V', $optionsFlags);
3422
            // Escapement type
3423
            $dataBlockFont .= pack('V', $fontEscapement);
3424
            // Underline type
3425
            $dataBlockFont .= pack('V', $fontUnderline);
3426
            // Always
3427
            $dataBlockFont .= pack('V', 0x00000000);
3428
            // Always
3429
            $dataBlockFont .= pack('V', 0x00000000);
3430
            // Not used (8)
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% 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...
3431
            $dataBlockFont .= pack('VV', 0x00000000, 0x00000000);
3432
            // Always
3433
            $dataBlockFont .= pack('v', 0x0001);
3434
        }
3435
        if ($bFormatAlign == 1) {
3436
            $blockAlign = 0;
3437
            // Alignment and text break
3438
            switch ($conditional->getStyle()->getAlignment()->getHorizontal()) {
3439
                case \PhpSpreadsheet\Style\Alignment::HORIZONTAL_GENERAL:
3440
                    $blockAlign = 0;
3441
                    break;
3442
                case \PhpSpreadsheet\Style\Alignment::HORIZONTAL_LEFT:
3443
                    $blockAlign = 1;
3444
                    break;
3445
                case \PhpSpreadsheet\Style\Alignment::HORIZONTAL_RIGHT:
3446
                    $blockAlign = 3;
3447
                    break;
3448
                case \PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER:
3449
                    $blockAlign = 2;
3450
                    break;
3451
                case \PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER_CONTINUOUS:
3452
                    $blockAlign = 6;
3453
                    break;
3454
                case \PhpSpreadsheet\Style\Alignment::HORIZONTAL_JUSTIFY:
3455
                    $blockAlign = 5;
3456
                    break;
3457
            }
3458
            if ($conditional->getStyle()->getAlignment()->getWrapText() == 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...
3459
                $blockAlign |= 1 << 3;
3460
            } else {
3461
                $blockAlign |= 0 << 3;
3462
            }
3463
            switch ($conditional->getStyle()->getAlignment()->getVertical()) {
3464
                case \PhpSpreadsheet\Style\Alignment::VERTICAL_BOTTOM:
3465
                    $blockAlign = 2 << 4;
3466
                    break;
3467
                case \PhpSpreadsheet\Style\Alignment::VERTICAL_TOP:
3468
                    $blockAlign = 0 << 4;
3469
                    break;
3470
                case \PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER:
3471
                    $blockAlign = 1 << 4;
3472
                    break;
3473
                case \PhpSpreadsheet\Style\Alignment::VERTICAL_JUSTIFY:
3474
                    $blockAlign = 3 << 4;
3475
                    break;
3476
            }
3477
            $blockAlign |= 0 << 7;
3478
3479
            // Text rotation angle
3480
            $blockRotation = $conditional->getStyle()->getAlignment()->getTextRotation();
3481
3482
            // Indentation
3483
            $blockIndent = $conditional->getStyle()->getAlignment()->getIndent();
3484
            if ($conditional->getStyle()->getAlignment()->getShrinkToFit() == 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...
3485
                $blockIndent |= 1 << 4;
3486
            } else {
3487
                $blockIndent |= 0 << 4;
3488
            }
3489
            $blockIndent |= 0 << 6;
3490
3491
            // Relative indentation
3492
            $blockIndentRelative = 255;
3493
3494
            $dataBlockAlign = pack('CCvvv', $blockAlign, $blockRotation, $blockIndent, $blockIndentRelative, 0x0000);
3495
        }
3496
        if ($bFormatBorder == 1) {
3497
            $blockLineStyle = 0;
3498
            switch ($conditional->getStyle()->getBorders()->getLeft()->getBorderStyle()) {
3499
                case \PhpSpreadsheet\Style\Border::BORDER_NONE:
3500
                    $blockLineStyle |= 0x00;
3501
                    break;
3502
                case \PhpSpreadsheet\Style\Border::BORDER_THIN:
3503
                    $blockLineStyle |= 0x01;
3504
                    break;
3505
                case \PhpSpreadsheet\Style\Border::BORDER_MEDIUM:
3506
                    $blockLineStyle |= 0x02;
3507
                    break;
3508
                case \PhpSpreadsheet\Style\Border::BORDER_DASHED:
3509
                    $blockLineStyle |= 0x03;
3510
                    break;
3511
                case \PhpSpreadsheet\Style\Border::BORDER_DOTTED:
3512
                    $blockLineStyle |= 0x04;
3513
                    break;
3514
                case \PhpSpreadsheet\Style\Border::BORDER_THICK:
3515
                    $blockLineStyle |= 0x05;
3516
                    break;
3517
                case \PhpSpreadsheet\Style\Border::BORDER_DOUBLE:
3518
                    $blockLineStyle |= 0x06;
3519
                    break;
3520
                case \PhpSpreadsheet\Style\Border::BORDER_HAIR:
3521
                    $blockLineStyle |= 0x07;
3522
                    break;
3523
                case \PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHED:
3524
                    $blockLineStyle |= 0x08;
3525
                    break;
3526
                case \PhpSpreadsheet\Style\Border::BORDER_DASHDOT:
3527
                    $blockLineStyle |= 0x09;
3528
                    break;
3529
                case \PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOT:
3530
                    $blockLineStyle |= 0x0A;
3531
                    break;
3532
                case \PhpSpreadsheet\Style\Border::BORDER_DASHDOTDOT:
3533
                    $blockLineStyle |= 0x0B;
3534
                    break;
3535
                case \PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOTDOT:
3536
                    $blockLineStyle |= 0x0C;
3537
                    break;
3538
                case \PhpSpreadsheet\Style\Border::BORDER_SLANTDASHDOT:
3539
                    $blockLineStyle |= 0x0D;
3540
                    break;
3541
            }
3542 View Code Duplication
            switch ($conditional->getStyle()->getBorders()->getRight()->getBorderStyle()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
3543
                case \PhpSpreadsheet\Style\Border::BORDER_NONE:
3544
                    $blockLineStyle |= 0x00 << 4;
3545
                    break;
3546
                case \PhpSpreadsheet\Style\Border::BORDER_THIN:
3547
                    $blockLineStyle |= 0x01 << 4;
3548
                    break;
3549
                case \PhpSpreadsheet\Style\Border::BORDER_MEDIUM:
3550
                    $blockLineStyle |= 0x02 << 4;
3551
                    break;
3552
                case \PhpSpreadsheet\Style\Border::BORDER_DASHED:
3553
                    $blockLineStyle |= 0x03 << 4;
3554
                    break;
3555
                case \PhpSpreadsheet\Style\Border::BORDER_DOTTED:
3556
                    $blockLineStyle |= 0x04 << 4;
3557
                    break;
3558
                case \PhpSpreadsheet\Style\Border::BORDER_THICK:
3559
                    $blockLineStyle |= 0x05 << 4;
3560
                    break;
3561
                case \PhpSpreadsheet\Style\Border::BORDER_DOUBLE:
3562
                    $blockLineStyle |= 0x06 << 4;
3563
                    break;
3564
                case \PhpSpreadsheet\Style\Border::BORDER_HAIR:
3565
                    $blockLineStyle |= 0x07 << 4;
3566
                    break;
3567
                case \PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHED:
3568
                    $blockLineStyle |= 0x08 << 4;
3569
                    break;
3570
                case \PhpSpreadsheet\Style\Border::BORDER_DASHDOT:
3571
                    $blockLineStyle |= 0x09 << 4;
3572
                    break;
3573
                case \PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOT:
3574
                    $blockLineStyle |= 0x0A << 4;
3575
                    break;
3576
                case \PhpSpreadsheet\Style\Border::BORDER_DASHDOTDOT:
3577
                    $blockLineStyle |= 0x0B << 4;
3578
                    break;
3579
                case \PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOTDOT:
3580
                    $blockLineStyle |= 0x0C << 4;
3581
                    break;
3582
                case \PhpSpreadsheet\Style\Border::BORDER_SLANTDASHDOT:
3583
                    $blockLineStyle |= 0x0D << 4;
3584
                    break;
3585
            }
3586 View Code Duplication
            switch ($conditional->getStyle()->getBorders()->getTop()->getBorderStyle()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
3587
                case \PhpSpreadsheet\Style\Border::BORDER_NONE:
3588
                    $blockLineStyle |= 0x00 << 8;
3589
                    break;
3590
                case \PhpSpreadsheet\Style\Border::BORDER_THIN:
3591
                    $blockLineStyle |= 0x01 << 8;
3592
                    break;
3593
                case \PhpSpreadsheet\Style\Border::BORDER_MEDIUM:
3594
                    $blockLineStyle |= 0x02 << 8;
3595
                    break;
3596
                case \PhpSpreadsheet\Style\Border::BORDER_DASHED:
3597
                    $blockLineStyle |= 0x03 << 8;
3598
                    break;
3599
                case \PhpSpreadsheet\Style\Border::BORDER_DOTTED:
3600
                    $blockLineStyle |= 0x04 << 8;
3601
                    break;
3602
                case \PhpSpreadsheet\Style\Border::BORDER_THICK:
3603
                    $blockLineStyle |= 0x05 << 8;
3604
                    break;
3605
                case \PhpSpreadsheet\Style\Border::BORDER_DOUBLE:
3606
                    $blockLineStyle |= 0x06 << 8;
3607
                    break;
3608
                case \PhpSpreadsheet\Style\Border::BORDER_HAIR:
3609
                    $blockLineStyle |= 0x07 << 8;
3610
                    break;
3611
                case \PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHED:
3612
                    $blockLineStyle |= 0x08 << 8;
3613
                    break;
3614
                case \PhpSpreadsheet\Style\Border::BORDER_DASHDOT:
3615
                    $blockLineStyle |= 0x09 << 8;
3616
                    break;
3617
                case \PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOT:
3618
                    $blockLineStyle |= 0x0A << 8;
3619
                    break;
3620
                case \PhpSpreadsheet\Style\Border::BORDER_DASHDOTDOT:
3621
                    $blockLineStyle |= 0x0B << 8;
3622
                    break;
3623
                case \PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOTDOT:
3624
                    $blockLineStyle |= 0x0C << 8;
3625
                    break;
3626
                case \PhpSpreadsheet\Style\Border::BORDER_SLANTDASHDOT:
3627
                    $blockLineStyle |= 0x0D << 8;
3628
                    break;
3629
            }
3630 View Code Duplication
            switch ($conditional->getStyle()->getBorders()->getBottom()->getBorderStyle()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
3631
                case \PhpSpreadsheet\Style\Border::BORDER_NONE:
3632
                    $blockLineStyle |= 0x00 << 12;
3633
                    break;
3634
                case \PhpSpreadsheet\Style\Border::BORDER_THIN:
3635
                    $blockLineStyle |= 0x01 << 12;
3636
                    break;
3637
                case \PhpSpreadsheet\Style\Border::BORDER_MEDIUM:
3638
                    $blockLineStyle |= 0x02 << 12;
3639
                    break;
3640
                case \PhpSpreadsheet\Style\Border::BORDER_DASHED:
3641
                    $blockLineStyle |= 0x03 << 12;
3642
                    break;
3643
                case \PhpSpreadsheet\Style\Border::BORDER_DOTTED:
3644
                    $blockLineStyle |= 0x04 << 12;
3645
                    break;
3646
                case \PhpSpreadsheet\Style\Border::BORDER_THICK:
3647
                    $blockLineStyle |= 0x05 << 12;
3648
                    break;
3649
                case \PhpSpreadsheet\Style\Border::BORDER_DOUBLE:
3650
                    $blockLineStyle |= 0x06 << 12;
3651
                    break;
3652
                case \PhpSpreadsheet\Style\Border::BORDER_HAIR:
3653
                    $blockLineStyle |= 0x07 << 12;
3654
                    break;
3655
                case \PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHED:
3656
                    $blockLineStyle |= 0x08 << 12;
3657
                    break;
3658
                case \PhpSpreadsheet\Style\Border::BORDER_DASHDOT:
3659
                    $blockLineStyle |= 0x09 << 12;
3660
                    break;
3661
                case \PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOT:
3662
                    $blockLineStyle |= 0x0A << 12;
3663
                    break;
3664
                case \PhpSpreadsheet\Style\Border::BORDER_DASHDOTDOT:
3665
                    $blockLineStyle |= 0x0B << 12;
3666
                    break;
3667
                case \PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOTDOT:
3668
                    $blockLineStyle |= 0x0C << 12;
3669
                    break;
3670
                case \PhpSpreadsheet\Style\Border::BORDER_SLANTDASHDOT:
3671
                    $blockLineStyle |= 0x0D << 12;
3672
                    break;
3673
            }
3674
            //@todo writeCFRule() => $blockLineStyle => Index Color for left line
3675
            //@todo writeCFRule() => $blockLineStyle => Index Color for right line
3676
            //@todo writeCFRule() => $blockLineStyle => Top-left to bottom-right on/off
3677
            //@todo writeCFRule() => $blockLineStyle => Bottom-left to top-right on/off
3678
            $blockColor = 0;
3679
            //@todo writeCFRule() => $blockColor => Index Color for top line
3680
            //@todo writeCFRule() => $blockColor => Index Color for bottom line
3681
            //@todo writeCFRule() => $blockColor => Index Color for diagonal line
3682 View Code Duplication
            switch ($conditional->getStyle()->getBorders()->getDiagonal()->getBorderStyle()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
3683
                case \PhpSpreadsheet\Style\Border::BORDER_NONE:
3684
                    $blockColor |= 0x00 << 21;
3685
                    break;
3686
                case \PhpSpreadsheet\Style\Border::BORDER_THIN:
3687
                    $blockColor |= 0x01 << 21;
3688
                    break;
3689
                case \PhpSpreadsheet\Style\Border::BORDER_MEDIUM:
3690
                    $blockColor |= 0x02 << 21;
3691
                    break;
3692
                case \PhpSpreadsheet\Style\Border::BORDER_DASHED:
3693
                    $blockColor |= 0x03 << 21;
3694
                    break;
3695
                case \PhpSpreadsheet\Style\Border::BORDER_DOTTED:
3696
                    $blockColor |= 0x04 << 21;
3697
                    break;
3698
                case \PhpSpreadsheet\Style\Border::BORDER_THICK:
3699
                    $blockColor |= 0x05 << 21;
3700
                    break;
3701
                case \PhpSpreadsheet\Style\Border::BORDER_DOUBLE:
3702
                    $blockColor |= 0x06 << 21;
3703
                    break;
3704
                case \PhpSpreadsheet\Style\Border::BORDER_HAIR:
3705
                    $blockColor |= 0x07 << 21;
3706
                    break;
3707
                case \PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHED:
3708
                    $blockColor |= 0x08 << 21;
3709
                    break;
3710
                case \PhpSpreadsheet\Style\Border::BORDER_DASHDOT:
3711
                    $blockColor |= 0x09 << 21;
3712
                    break;
3713
                case \PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOT:
3714
                    $blockColor |= 0x0A << 21;
3715
                    break;
3716
                case \PhpSpreadsheet\Style\Border::BORDER_DASHDOTDOT:
3717
                    $blockColor |= 0x0B << 21;
3718
                    break;
3719
                case \PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOTDOT:
3720
                    $blockColor |= 0x0C << 21;
3721
                    break;
3722
                case \PhpSpreadsheet\Style\Border::BORDER_SLANTDASHDOT:
3723
                    $blockColor |= 0x0D << 21;
3724
                    break;
3725
            }
3726
            $dataBlockBorder = pack('vv', $blockLineStyle, $blockColor);
3727
        }
3728
        if ($bFormatFill == 1) {
3729
            // Fill Patern Style
3730
            $blockFillPatternStyle = 0;
0 ignored issues
show
Unused Code introduced by
$blockFillPatternStyle is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
3731
            switch ($conditional->getStyle()->getFill()->getFillType()) {
3732
                case \PhpSpreadsheet\Style\Fill::FILL_NONE:
3733
                    $blockFillPatternStyle = 0x00;
3734
                    break;
3735
                case \PhpSpreadsheet\Style\Fill::FILL_SOLID:
3736
                    $blockFillPatternStyle = 0x01;
3737
                    break;
3738
                case \PhpSpreadsheet\Style\Fill::FILL_PATTERN_MEDIUMGRAY:
3739
                    $blockFillPatternStyle = 0x02;
3740
                    break;
3741
                case \PhpSpreadsheet\Style\Fill::FILL_PATTERN_DARKGRAY:
3742
                    $blockFillPatternStyle = 0x03;
3743
                    break;
3744
                case \PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTGRAY:
3745
                    $blockFillPatternStyle = 0x04;
3746
                    break;
3747
                case \PhpSpreadsheet\Style\Fill::FILL_PATTERN_DARKHORIZONTAL:
3748
                    $blockFillPatternStyle = 0x05;
3749
                    break;
3750
                case \PhpSpreadsheet\Style\Fill::FILL_PATTERN_DARKVERTICAL:
3751
                    $blockFillPatternStyle = 0x06;
3752
                    break;
3753
                case \PhpSpreadsheet\Style\Fill::FILL_PATTERN_DARKDOWN:
3754
                    $blockFillPatternStyle = 0x07;
3755
                    break;
3756
                case \PhpSpreadsheet\Style\Fill::FILL_PATTERN_DARKUP:
3757
                    $blockFillPatternStyle = 0x08;
3758
                    break;
3759
                case \PhpSpreadsheet\Style\Fill::FILL_PATTERN_DARKGRID:
3760
                    $blockFillPatternStyle = 0x09;
3761
                    break;
3762
                case \PhpSpreadsheet\Style\Fill::FILL_PATTERN_DARKTRELLIS:
3763
                    $blockFillPatternStyle = 0x0A;
3764
                    break;
3765
                case \PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTHORIZONTAL:
3766
                    $blockFillPatternStyle = 0x0B;
3767
                    break;
3768
                case \PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTVERTICAL:
3769
                    $blockFillPatternStyle = 0x0C;
3770
                    break;
3771
                case \PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTDOWN:
3772
                    $blockFillPatternStyle = 0x0D;
3773
                    break;
3774
                case \PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTUP:
3775
                    $blockFillPatternStyle = 0x0E;
3776
                    break;
3777
                case \PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTGRID:
3778
                    $blockFillPatternStyle = 0x0F;
3779
                    break;
3780
                case \PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTTRELLIS:
3781
                    $blockFillPatternStyle = 0x10;
3782
                    break;
3783
                case \PhpSpreadsheet\Style\Fill::FILL_PATTERN_GRAY125:
3784
                    $blockFillPatternStyle = 0x11;
3785
                    break;
3786
                case \PhpSpreadsheet\Style\Fill::FILL_PATTERN_GRAY0625:
3787
                    $blockFillPatternStyle = 0x12;
3788
                    break;
3789
                case \PhpSpreadsheet\Style\Fill::FILL_GRADIENT_LINEAR:
3790
                    $blockFillPatternStyle = 0x00;
3791
                    break;    // does not exist in BIFF8
3792
                case \PhpSpreadsheet\Style\Fill::FILL_GRADIENT_PATH:
3793
                    $blockFillPatternStyle = 0x00;
3794
                    break;    // does not exist in BIFF8
3795
                default:
3796
                    $blockFillPatternStyle = 0x00;
3797
                    break;
3798
            }
3799
            // Color
3800 View Code Duplication
            switch ($conditional->getStyle()->getFill()->getStartColor()->getRGB()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
3801
                case '000000':
3802
                    $colorIdxBg = 0x08;
3803
                    break;
3804
                case 'FFFFFF':
3805
                    $colorIdxBg = 0x09;
3806
                    break;
3807
                case 'FF0000':
3808
                    $colorIdxBg = 0x0A;
3809
                    break;
3810
                case '00FF00':
3811
                    $colorIdxBg = 0x0B;
3812
                    break;
3813
                case '0000FF':
3814
                    $colorIdxBg = 0x0C;
3815
                    break;
3816
                case 'FFFF00':
3817
                    $colorIdxBg = 0x0D;
3818
                    break;
3819
                case 'FF00FF':
3820
                    $colorIdxBg = 0x0E;
3821
                    break;
3822
                case '00FFFF':
3823
                    $colorIdxBg = 0x0F;
3824
                    break;
3825
                case '800000':
3826
                    $colorIdxBg = 0x10;
3827
                    break;
3828
                case '008000':
3829
                    $colorIdxBg = 0x11;
3830
                    break;
3831
                case '000080':
3832
                    $colorIdxBg = 0x12;
3833
                    break;
3834
                case '808000':
3835
                    $colorIdxBg = 0x13;
3836
                    break;
3837
                case '800080':
3838
                    $colorIdxBg = 0x14;
3839
                    break;
3840
                case '008080':
3841
                    $colorIdxBg = 0x15;
3842
                    break;
3843
                case 'C0C0C0':
3844
                    $colorIdxBg = 0x16;
3845
                    break;
3846
                case '808080':
3847
                    $colorIdxBg = 0x17;
3848
                    break;
3849
                case '9999FF':
3850
                    $colorIdxBg = 0x18;
3851
                    break;
3852
                case '993366':
3853
                    $colorIdxBg = 0x19;
3854
                    break;
3855
                case 'FFFFCC':
3856
                    $colorIdxBg = 0x1A;
3857
                    break;
3858
                case 'CCFFFF':
3859
                    $colorIdxBg = 0x1B;
3860
                    break;
3861
                case '660066':
3862
                    $colorIdxBg = 0x1C;
3863
                    break;
3864
                case 'FF8080':
3865
                    $colorIdxBg = 0x1D;
3866
                    break;
3867
                case '0066CC':
3868
                    $colorIdxBg = 0x1E;
3869
                    break;
3870
                case 'CCCCFF':
3871
                    $colorIdxBg = 0x1F;
3872
                    break;
3873
                case '000080':
3874
                    $colorIdxBg = 0x20;
3875
                    break;
3876
                case 'FF00FF':
3877
                    $colorIdxBg = 0x21;
3878
                    break;
3879
                case 'FFFF00':
3880
                    $colorIdxBg = 0x22;
3881
                    break;
3882
                case '00FFFF':
3883
                    $colorIdxBg = 0x23;
3884
                    break;
3885
                case '800080':
3886
                    $colorIdxBg = 0x24;
3887
                    break;
3888
                case '800000':
3889
                    $colorIdxBg = 0x25;
3890
                    break;
3891
                case '008080':
3892
                    $colorIdxBg = 0x26;
3893
                    break;
3894
                case '0000FF':
3895
                    $colorIdxBg = 0x27;
3896
                    break;
3897
                case '00CCFF':
3898
                    $colorIdxBg = 0x28;
3899
                    break;
3900
                case 'CCFFFF':
3901
                    $colorIdxBg = 0x29;
3902
                    break;
3903
                case 'CCFFCC':
3904
                    $colorIdxBg = 0x2A;
3905
                    break;
3906
                case 'FFFF99':
3907
                    $colorIdxBg = 0x2B;
3908
                    break;
3909
                case '99CCFF':
3910
                    $colorIdxBg = 0x2C;
3911
                    break;
3912
                case 'FF99CC':
3913
                    $colorIdxBg = 0x2D;
3914
                    break;
3915
                case 'CC99FF':
3916
                    $colorIdxBg = 0x2E;
3917
                    break;
3918
                case 'FFCC99':
3919
                    $colorIdxBg = 0x2F;
3920
                    break;
3921
                case '3366FF':
3922
                    $colorIdxBg = 0x30;
3923
                    break;
3924
                case '33CCCC':
3925
                    $colorIdxBg = 0x31;
3926
                    break;
3927
                case '99CC00':
3928
                    $colorIdxBg = 0x32;
3929
                    break;
3930
                case 'FFCC00':
3931
                    $colorIdxBg = 0x33;
3932
                    break;
3933
                case 'FF9900':
3934
                    $colorIdxBg = 0x34;
3935
                    break;
3936
                case 'FF6600':
3937
                    $colorIdxBg = 0x35;
3938
                    break;
3939
                case '666699':
3940
                    $colorIdxBg = 0x36;
3941
                    break;
3942
                case '969696':
3943
                    $colorIdxBg = 0x37;
3944
                    break;
3945
                case '003366':
3946
                    $colorIdxBg = 0x38;
3947
                    break;
3948
                case '339966':
3949
                    $colorIdxBg = 0x39;
3950
                    break;
3951
                case '003300':
3952
                    $colorIdxBg = 0x3A;
3953
                    break;
3954
                case '333300':
3955
                    $colorIdxBg = 0x3B;
3956
                    break;
3957
                case '993300':
3958
                    $colorIdxBg = 0x3C;
3959
                    break;
3960
                case '993366':
3961
                    $colorIdxBg = 0x3D;
3962
                    break;
3963
                case '333399':
3964
                    $colorIdxBg = 0x3E;
3965
                    break;
3966
                case '333333':
3967
                    $colorIdxBg = 0x3F;
3968
                    break;
3969
                default:
3970
                          $colorIdxBg = 0x41;
3971
                    break;
3972
            }
3973
            // Fg Color
3974 View Code Duplication
            switch ($conditional->getStyle()->getFill()->getEndColor()->getRGB()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
3975
                case '000000':
3976
                    $colorIdxFg = 0x08;
3977
                    break;
3978
                case 'FFFFFF':
3979
                    $colorIdxFg = 0x09;
3980
                    break;
3981
                case 'FF0000':
3982
                    $colorIdxFg = 0x0A;
3983
                    break;
3984
                case '00FF00':
3985
                    $colorIdxFg = 0x0B;
3986
                    break;
3987
                case '0000FF':
3988
                    $colorIdxFg = 0x0C;
3989
                    break;
3990
                case 'FFFF00':
3991
                    $colorIdxFg = 0x0D;
3992
                    break;
3993
                case 'FF00FF':
3994
                    $colorIdxFg = 0x0E;
3995
                    break;
3996
                case '00FFFF':
3997
                    $colorIdxFg = 0x0F;
3998
                    break;
3999
                case '800000':
4000
                    $colorIdxFg = 0x10;
4001
                    break;
4002
                case '008000':
4003
                    $colorIdxFg = 0x11;
4004
                    break;
4005
                case '000080':
4006
                    $colorIdxFg = 0x12;
4007
                    break;
4008
                case '808000':
4009
                    $colorIdxFg = 0x13;
4010
                    break;
4011
                case '800080':
4012
                    $colorIdxFg = 0x14;
4013
                    break;
4014
                case '008080':
4015
                    $colorIdxFg = 0x15;
4016
                    break;
4017
                case 'C0C0C0':
4018
                    $colorIdxFg = 0x16;
4019
                    break;
4020
                case '808080':
4021
                    $colorIdxFg = 0x17;
4022
                    break;
4023
                case '9999FF':
4024
                    $colorIdxFg = 0x18;
4025
                    break;
4026
                case '993366':
4027
                    $colorIdxFg = 0x19;
4028
                    break;
4029
                case 'FFFFCC':
4030
                    $colorIdxFg = 0x1A;
4031
                    break;
4032
                case 'CCFFFF':
4033
                    $colorIdxFg = 0x1B;
4034
                    break;
4035
                case '660066':
4036
                    $colorIdxFg = 0x1C;
4037
                    break;
4038
                case 'FF8080':
4039
                    $colorIdxFg = 0x1D;
4040
                    break;
4041
                case '0066CC':
4042
                    $colorIdxFg = 0x1E;
4043
                    break;
4044
                case 'CCCCFF':
4045
                    $colorIdxFg = 0x1F;
4046
                    break;
4047
                case '000080':
4048
                    $colorIdxFg = 0x20;
4049
                    break;
4050
                case 'FF00FF':
4051
                    $colorIdxFg = 0x21;
4052
                    break;
4053
                case 'FFFF00':
4054
                    $colorIdxFg = 0x22;
4055
                    break;
4056
                case '00FFFF':
4057
                    $colorIdxFg = 0x23;
4058
                    break;
4059
                case '800080':
4060
                    $colorIdxFg = 0x24;
4061
                    break;
4062
                case '800000':
4063
                    $colorIdxFg = 0x25;
4064
                    break;
4065
                case '008080':
4066
                    $colorIdxFg = 0x26;
4067
                    break;
4068
                case '0000FF':
4069
                    $colorIdxFg = 0x27;
4070
                    break;
4071
                case '00CCFF':
4072
                    $colorIdxFg = 0x28;
4073
                    break;
4074
                case 'CCFFFF':
4075
                    $colorIdxFg = 0x29;
4076
                    break;
4077
                case 'CCFFCC':
4078
                    $colorIdxFg = 0x2A;
4079
                    break;
4080
                case 'FFFF99':
4081
                    $colorIdxFg = 0x2B;
4082
                    break;
4083
                case '99CCFF':
4084
                    $colorIdxFg = 0x2C;
4085
                    break;
4086
                case 'FF99CC':
4087
                    $colorIdxFg = 0x2D;
4088
                    break;
4089
                case 'CC99FF':
4090
                    $colorIdxFg = 0x2E;
4091
                    break;
4092
                case 'FFCC99':
4093
                    $colorIdxFg = 0x2F;
4094
                    break;
4095
                case '3366FF':
4096
                    $colorIdxFg = 0x30;
4097
                    break;
4098
                case '33CCCC':
4099
                    $colorIdxFg = 0x31;
4100
                    break;
4101
                case '99CC00':
4102
                    $colorIdxFg = 0x32;
4103
                    break;
4104
                case 'FFCC00':
4105
                    $colorIdxFg = 0x33;
4106
                    break;
4107
                case 'FF9900':
4108
                    $colorIdxFg = 0x34;
4109
                    break;
4110
                case 'FF6600':
4111
                    $colorIdxFg = 0x35;
4112
                    break;
4113
                case '666699':
4114
                    $colorIdxFg = 0x36;
4115
                    break;
4116
                case '969696':
4117
                    $colorIdxFg = 0x37;
4118
                    break;
4119
                case '003366':
4120
                    $colorIdxFg = 0x38;
4121
                    break;
4122
                case '339966':
4123
                    $colorIdxFg = 0x39;
4124
                    break;
4125
                case '003300':
4126
                    $colorIdxFg = 0x3A;
4127
                    break;
4128
                case '333300':
4129
                    $colorIdxFg = 0x3B;
4130
                    break;
4131
                case '993300':
4132
                    $colorIdxFg = 0x3C;
4133
                    break;
4134
                case '993366':
4135
                    $colorIdxFg = 0x3D;
4136
                    break;
4137
                case '333399':
4138
                    $colorIdxFg = 0x3E;
4139
                    break;
4140
                case '333333':
4141
                    $colorIdxFg = 0x3F;
4142
                    break;
4143
                default:
4144
                          $colorIdxFg = 0x40;
4145
                    break;
4146
            }
4147
            $dataBlockFill = pack('v', $blockFillPatternStyle);
4148
            $dataBlockFill .= pack('v', $colorIdxFg | ($colorIdxBg << 7));
4149
        }
4150
        if ($bFormatProt == 1) {
4151
            $dataBlockProtection = 0;
4152
            if ($conditional->getStyle()->getProtection()->getLocked() == \PhpSpreadsheet\Style\Protection::PROTECTION_PROTECTED) {
4153
                $dataBlockProtection = 1;
4154
            }
4155
            if ($conditional->getStyle()->getProtection()->getHidden() == \PhpSpreadsheet\Style\Protection::PROTECTION_PROTECTED) {
4156
                $dataBlockProtection = 1 << 1;
4157
            }
4158
        }
4159
4160
        $data      = pack('CCvvVv', $type, $operatorType, $szValue1, $szValue2, $flags, 0x0000);
0 ignored issues
show
Bug introduced by
The variable $type does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug introduced by
The variable $operatorType does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
4161
        if ($bFormatFont == 1) { // Block Formatting : OK
4162
            $data .= $dataBlockFont;
0 ignored issues
show
Bug introduced by
The variable $dataBlockFont does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
4163
        }
4164
        if ($bFormatAlign == 1) {
4165
            $data .= $dataBlockAlign;
0 ignored issues
show
Bug introduced by
The variable $dataBlockAlign does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
4166
        }
4167
        if ($bFormatBorder == 1) {
4168
            $data .= $dataBlockBorder;
0 ignored issues
show
Bug introduced by
The variable $dataBlockBorder does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
4169
        }
4170
        if ($bFormatFill == 1) { // Block Formatting : OK
4171
            $data .= $dataBlockFill;
0 ignored issues
show
Bug introduced by
The variable $dataBlockFill does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
4172
        }
4173
        if ($bFormatProt == 1) {
4174
            $data .= $dataBlockProtection;
0 ignored issues
show
Bug introduced by
The variable $dataBlockProtection does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
4175
        }
4176
        if (!is_null($operand1)) {
4177
            $data .= $operand1;
4178
        }
4179
        if (!is_null($operand2)) {
4180
            $data .= $operand2;
4181
        }
4182
        $header      = pack('vv', $record, strlen($data));
4183
        $this->append($header . $data);
4184
    }
4185
4186
    /**
4187
     * Write CFHeader record
4188
     */
4189
    private function writeCFHeader()
4190
    {
4191
        $record      = 0x01B0;               // Record identifier
4192
        $length      = 0x0016;               // Bytes to follow
4193
4194
        $numColumnMin = null;
4195
        $numColumnMax = null;
4196
        $numRowMin = null;
4197
        $numRowMax = null;
4198
        $arrConditional = array();
4199
        foreach ($this->phpSheet->getConditionalStylesCollection() as $cellCoordinate => $conditionalStyles) {
4200
            foreach ($conditionalStyles as $conditional) {
4201
                if ($conditional->getConditionType() == \PhpSpreadsheet\Style\Conditional::CONDITION_EXPRESSION
4202
                        || $conditional->getConditionType() == \PhpSpreadsheet\Style\Conditional::CONDITION_CELLIS) {
4203
                    if (!in_array($conditional->getHashCode(), $arrConditional)) {
4204
                        $arrConditional[] = $conditional->getHashCode();
4205
                    }
4206
                    // Cells
4207
                    $arrCoord = \PhpSpreadsheet\Cell::coordinateFromString($cellCoordinate);
4208
                    if (!is_numeric($arrCoord[0])) {
4209
                        $arrCoord[0] = \PhpSpreadsheet\Cell::columnIndexFromString($arrCoord[0]);
4210
                    }
4211
                    if (is_null($numColumnMin) || ($numColumnMin > $arrCoord[0])) {
4212
                        $numColumnMin = $arrCoord[0];
4213
                    }
4214
                    if (is_null($numColumnMax) || ($numColumnMax < $arrCoord[0])) {
4215
                        $numColumnMax = $arrCoord[0];
4216
                    }
4217
                    if (is_null($numRowMin) || ($numRowMin > $arrCoord[1])) {
4218
                        $numRowMin = $arrCoord[1];
4219
                    }
4220
                    if (is_null($numRowMax) || ($numRowMax < $arrCoord[1])) {
4221
                        $numRowMax = $arrCoord[1];
4222
                    }
4223
                }
4224
            }
4225
        }
4226
        $needRedraw = 1;
4227
        $cellRange = pack('vvvv', $numRowMin-1, $numRowMax-1, $numColumnMin-1, $numColumnMax-1);
4228
4229
        $header      = pack('vv', $record, $length);
4230
        $data      = pack('vv', count($arrConditional), $needRedraw);
4231
        $data     .= $cellRange;
4232
        $data     .= pack('v', 0x0001);
4233
        $data     .= $cellRange;
4234
        $this->append($header . $data);
4235
    }
4236
}
4237