Subversion Repositories eFlore/Applications.cel

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2388 jpm 1
<?php
2
/**
3
 * PHPExcel
4
 *
5
 * Copyright (c) 2006 - 2013 PHPExcel
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20
 *
21
 * @category   PHPExcel
22
 * @package    PHPExcel_Style
23
 * @copyright  Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel)
24
 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
25
 * @version    ##VERSION##, ##DATE##
26
 */
27
 
28
 
29
/**
30
 * PHPExcel_Style
31
 *
32
 * @category   PHPExcel
33
 * @package    PHPExcel_Style
34
 * @copyright  Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel)
35
 */
36
class PHPExcel_Style extends PHPExcel_Style_Supervisor implements PHPExcel_IComparable
37
{
38
    /**
39
     * Font
40
     *
41
     * @var PHPExcel_Style_Font
42
     */
43
    protected $_font;
44
 
45
    /**
46
     * Fill
47
     *
48
     * @var PHPExcel_Style_Fill
49
     */
50
    protected $_fill;
51
 
52
    /**
53
     * Borders
54
     *
55
     * @var PHPExcel_Style_Borders
56
     */
57
    protected $_borders;
58
 
59
    /**
60
     * Alignment
61
     *
62
     * @var PHPExcel_Style_Alignment
63
     */
64
    protected $_alignment;
65
 
66
    /**
67
     * Number Format
68
     *
69
     * @var PHPExcel_Style_NumberFormat
70
     */
71
    protected $_numberFormat;
72
 
73
    /**
74
     * Conditional styles
75
     *
76
     * @var PHPExcel_Style_Conditional[]
77
     */
78
    protected $_conditionalStyles;
79
 
80
    /**
81
     * Protection
82
     *
83
     * @var PHPExcel_Style_Protection
84
     */
85
    protected $_protection;
86
 
87
    /**
88
     * Index of style in collection. Only used for real style.
89
     *
90
     * @var int
91
     */
92
    protected $_index;
93
 
94
    /**
95
     * Create a new PHPExcel_Style
96
     *
97
     * @param boolean $isSupervisor Flag indicating if this is a supervisor or not
98
     * 		Leave this value at default unless you understand exactly what
99
     *    its ramifications are
100
     * @param boolean $isConditional Flag indicating if this is a conditional style or not
101
     *   	Leave this value at default unless you understand exactly what
102
     *    its ramifications are
103
     */
104
    public function __construct($isSupervisor = false, $isConditional = false)
105
    {
106
        // Supervisor?
107
        $this->_isSupervisor = $isSupervisor;
108
 
109
        // Initialise values
110
        $this->_conditionalStyles	= array();
111
        $this->_font              = new PHPExcel_Style_Font($isSupervisor, $isConditional);
112
        $this->_fill              = new PHPExcel_Style_Fill($isSupervisor, $isConditional);
113
        $this->_borders           = new PHPExcel_Style_Borders($isSupervisor, $isConditional);
114
        $this->_alignment         = new PHPExcel_Style_Alignment($isSupervisor, $isConditional);
115
        $this->_numberFormat      = new PHPExcel_Style_NumberFormat($isSupervisor, $isConditional);
116
        $this->_protection        = new PHPExcel_Style_Protection($isSupervisor, $isConditional);
117
 
118
        // bind parent if we are a supervisor
119
        if ($isSupervisor) {
120
            $this->_font->bindParent($this);
121
            $this->_fill->bindParent($this);
122
            $this->_borders->bindParent($this);
123
            $this->_alignment->bindParent($this);
124
            $this->_numberFormat->bindParent($this);
125
            $this->_protection->bindParent($this);
126
        }
127
    }
128
 
129
    /**
130
     * Get the shared style component for the currently active cell in currently active sheet.
131
     * Only used for style supervisor
132
     *
133
     * @return PHPExcel_Style
134
     */
135
    public function getSharedComponent()
136
    {
137
        $activeSheet = $this->getActiveSheet();
138
        $selectedCell = $this->getActiveCell(); // e.g. 'A1'
139
 
140
        if ($activeSheet->cellExists($selectedCell)) {
141
            $xfIndex = $activeSheet->getCell($selectedCell)->getXfIndex();
142
        } else {
143
            $xfIndex = 0;
144
        }
145
 
146
        return $this->_parent->getCellXfByIndex($xfIndex);
147
    }
148
 
149
    /**
150
     * Get parent. Only used for style supervisor
151
     *
152
     * @return PHPExcel
153
     */
154
    public function getParent()
155
    {
156
        return $this->_parent;
157
    }
158
 
159
    /**
160
     * Apply styles from array
161
     *
162
     * <code>
163
     * $objPHPExcel->getActiveSheet()->getStyle('B2')->applyFromArray(
164
     *         array(
165
     *             'font'    => array(
166
     *                 'name'      => 'Arial',
167
     *                 'bold'      => true,
168
     *                 'italic'    => false,
169
     *                 'underline' => PHPExcel_Style_Font::UNDERLINE_DOUBLE,
170
     *                 'strike'    => false,
171
     *                 'color'     => array(
172
     *                     'rgb' => '808080'
173
     *                 )
174
     *             ),
175
     *             'borders' => array(
176
     *                 'bottom'     => array(
177
     *                     'style' => PHPExcel_Style_Border::BORDER_DASHDOT,
178
     *                     'color' => array(
179
     *                         'rgb' => '808080'
180
     *                     )
181
     *                 ),
182
     *                 'top'     => array(
183
     *                     'style' => PHPExcel_Style_Border::BORDER_DASHDOT,
184
     *                     'color' => array(
185
     *                         'rgb' => '808080'
186
     *                     )
187
     *                 )
188
     *             )
189
     *         )
190
     * );
191
     * </code>
192
     *
193
     * @param    array    $pStyles    Array containing style information
194
     * @param     boolean        $pAdvanced    Advanced mode for setting borders.
195
     * @throws    PHPExcel_Exception
196
     * @return PHPExcel_Style
197
     */
198
    public function applyFromArray($pStyles = null, $pAdvanced = true)
199
    {
200
        if (is_array($pStyles)) {
201
            if ($this->_isSupervisor) {
202
 
203
                $pRange = $this->getSelectedCells();
204
 
205
                // Uppercase coordinate
206
                $pRange = strtoupper($pRange);
207
 
208
                // Is it a cell range or a single cell?
209
                if (strpos($pRange, ':') === false) {
210
                    $rangeA = $pRange;
211
                    $rangeB = $pRange;
212
                } else {
213
                    list($rangeA, $rangeB) = explode(':', $pRange);
214
                }
215
 
216
                // Calculate range outer borders
217
                $rangeStart = PHPExcel_Cell::coordinateFromString($rangeA);
218
                $rangeEnd     = PHPExcel_Cell::coordinateFromString($rangeB);
219
 
220
                // Translate column into index
221
                $rangeStart[0]    = PHPExcel_Cell::columnIndexFromString($rangeStart[0]) - 1;
222
                $rangeEnd[0]    = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]) - 1;
223
 
224
                // Make sure we can loop upwards on rows and columns
225
                if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) {
226
                    $tmp = $rangeStart;
227
                    $rangeStart = $rangeEnd;
228
                    $rangeEnd = $tmp;
229
                }
230
 
231
                // ADVANCED MODE:
232
 
233
                if ($pAdvanced && isset($pStyles['borders'])) {
234
 
235
                    // 'allborders' is a shorthand property for 'outline' and 'inside' and
236
                    //        it applies to components that have not been set explicitly
237
                    if (isset($pStyles['borders']['allborders'])) {
238
                        foreach (array('outline', 'inside') as $component) {
239
                            if (!isset($pStyles['borders'][$component])) {
240
                                $pStyles['borders'][$component] = $pStyles['borders']['allborders'];
241
                            }
242
                        }
243
                        unset($pStyles['borders']['allborders']); // not needed any more
244
                    }
245
 
246
                    // 'outline' is a shorthand property for 'top', 'right', 'bottom', 'left'
247
                    //        it applies to components that have not been set explicitly
248
                    if (isset($pStyles['borders']['outline'])) {
249
                        foreach (array('top', 'right', 'bottom', 'left') as $component) {
250
                            if (!isset($pStyles['borders'][$component])) {
251
                                $pStyles['borders'][$component] = $pStyles['borders']['outline'];
252
                            }
253
                        }
254
                        unset($pStyles['borders']['outline']); // not needed any more
255
                    }
256
 
257
                    // 'inside' is a shorthand property for 'vertical' and 'horizontal'
258
                    //        it applies to components that have not been set explicitly
259
                    if (isset($pStyles['borders']['inside'])) {
260
                        foreach (array('vertical', 'horizontal') as $component) {
261
                            if (!isset($pStyles['borders'][$component])) {
262
                                $pStyles['borders'][$component] = $pStyles['borders']['inside'];
263
                            }
264
                        }
265
                        unset($pStyles['borders']['inside']); // not needed any more
266
                    }
267
 
268
                    // width and height characteristics of selection, 1, 2, or 3 (for 3 or more)
269
                    $xMax = min($rangeEnd[0] - $rangeStart[0] + 1, 3);
270
                    $yMax = min($rangeEnd[1] - $rangeStart[1] + 1, 3);
271
 
272
                    // loop through up to 3 x 3 = 9 regions
273
                    for ($x = 1; $x <= $xMax; ++$x) {
274
                        // start column index for region
275
                        $colStart = ($x == 3) ?
276
                            PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0])
277
                                : PHPExcel_Cell::stringFromColumnIndex($rangeStart[0] + $x - 1);
278
 
279
                        // end column index for region
280
                        $colEnd = ($x == 1) ?
281
                            PHPExcel_Cell::stringFromColumnIndex($rangeStart[0])
282
                                : PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0] - $xMax + $x);
283
 
284
                        for ($y = 1; $y <= $yMax; ++$y) {
285
 
286
                            // which edges are touching the region
287
                            $edges = array();
288
 
289
                            // are we at left edge
290
                            if ($x == 1) {
291
                                $edges[] = 'left';
292
                            }
293
 
294
                            // are we at right edge
295
                            if ($x == $xMax) {
296
                                $edges[] = 'right';
297
                            }
298
 
299
                            // are we at top edge?
300
                            if ($y == 1) {
301
                                $edges[] = 'top';
302
                            }
303
 
304
                            // are we at bottom edge?
305
                            if ($y == $yMax) {
306
                                $edges[] = 'bottom';
307
                            }
308
 
309
                            // start row index for region
310
                            $rowStart = ($y == 3) ?
311
                                $rangeEnd[1] : $rangeStart[1] + $y - 1;
312
 
313
                            // end row index for region
314
                            $rowEnd = ($y == 1) ?
315
                                $rangeStart[1] : $rangeEnd[1] - $yMax + $y;
316
 
317
                            // build range for region
318
                            $range = $colStart . $rowStart . ':' . $colEnd . $rowEnd;
319
 
320
                            // retrieve relevant style array for region
321
                            $regionStyles = $pStyles;
322
                            unset($regionStyles['borders']['inside']);
323
 
324
                            // what are the inner edges of the region when looking at the selection
325
                            $innerEdges = array_diff( array('top', 'right', 'bottom', 'left'), $edges );
326
 
327
                            // inner edges that are not touching the region should take the 'inside' border properties if they have been set
328
                            foreach ($innerEdges as $innerEdge) {
329
                                switch ($innerEdge) {
330
                                    case 'top':
331
                                    case 'bottom':
332
                                        // should pick up 'horizontal' border property if set
333
                                        if (isset($pStyles['borders']['horizontal'])) {
334
                                            $regionStyles['borders'][$innerEdge] = $pStyles['borders']['horizontal'];
335
                                        } else {
336
                                            unset($regionStyles['borders'][$innerEdge]);
337
                                        }
338
                                        break;
339
                                    case 'left':
340
                                    case 'right':
341
                                        // should pick up 'vertical' border property if set
342
                                        if (isset($pStyles['borders']['vertical'])) {
343
                                            $regionStyles['borders'][$innerEdge] = $pStyles['borders']['vertical'];
344
                                        } else {
345
                                            unset($regionStyles['borders'][$innerEdge]);
346
                                        }
347
                                        break;
348
                                }
349
                            }
350
 
351
                            // apply region style to region by calling applyFromArray() in simple mode
352
                            $this->getActiveSheet()->getStyle($range)->applyFromArray($regionStyles, false);
353
                        }
354
                    }
355
                    return $this;
356
                }
357
 
358
                // SIMPLE MODE:
359
 
360
                // Selection type, inspect
361
                if (preg_match('/^[A-Z]+1:[A-Z]+1048576$/', $pRange)) {
362
                    $selectionType = 'COLUMN';
363
                } else if (preg_match('/^A[0-9]+:XFD[0-9]+$/', $pRange)) {
364
                    $selectionType = 'ROW';
365
                } else {
366
                    $selectionType = 'CELL';
367
                }
368
 
369
                // First loop through columns, rows, or cells to find out which styles are affected by this operation
370
                switch ($selectionType) {
371
                    case 'COLUMN':
372
                        $oldXfIndexes = array();
373
                        for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) {
374
                            $oldXfIndexes[$this->getActiveSheet()->getColumnDimensionByColumn($col)->getXfIndex()] = true;
375
                        }
376
                        break;
377
 
378
                    case 'ROW':
379
                        $oldXfIndexes = array();
380
                        for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) {
381
                            if ($this->getActiveSheet()->getRowDimension($row)->getXfIndex() == null) {
382
                                $oldXfIndexes[0] = true; // row without explicit style should be formatted based on default style
383
                            } else {
384
                                $oldXfIndexes[$this->getActiveSheet()->getRowDimension($row)->getXfIndex()] = true;
385
                            }
386
                        }
387
                        break;
388
 
389
                    case 'CELL':
390
                        $oldXfIndexes = array();
391
                        for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) {
392
                            for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) {
393
                                $oldXfIndexes[$this->getActiveSheet()->getCellByColumnAndRow($col, $row)->getXfIndex()] = true;
394
                            }
395
                        }
396
                        break;
397
                }
398
 
399
                // clone each of the affected styles, apply the style array, and add the new styles to the workbook
400
                $workbook = $this->getActiveSheet()->getParent();
401
                foreach ($oldXfIndexes as $oldXfIndex => $dummy) {
402
                    $style = $workbook->getCellXfByIndex($oldXfIndex);
403
                    $newStyle = clone $style;
404
                    $newStyle->applyFromArray($pStyles);
405
 
406
                    if ($workbook->cellXfExists($newStyle)) {
407
                        // there is already such cell Xf in our collection
408
                        $newXfIndexes[$oldXfIndex] = $existingStyle->getIndex();
409
                    } else {
410
                        // we don't have such a cell Xf, need to add
411
                        $workbook->addCellXf($newStyle);
412
                        $newXfIndexes[$oldXfIndex] = $newStyle->getIndex();
413
                    }
414
                }
415
 
416
                // Loop through columns, rows, or cells again and update the XF index
417
                switch ($selectionType) {
418
                    case 'COLUMN':
419
                        for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) {
420
                            $columnDimension = $this->getActiveSheet()->getColumnDimensionByColumn($col);
421
                            $oldXfIndex = $columnDimension->getXfIndex();
422
                            $columnDimension->setXfIndex($newXfIndexes[$oldXfIndex]);
423
                        }
424
                        break;
425
 
426
                    case 'ROW':
427
                        for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) {
428
                            $rowDimension = $this->getActiveSheet()->getRowDimension($row);
429
                            $oldXfIndex = $rowDimension->getXfIndex() === null ?
430
 
431
                            $rowDimension->setXfIndex($newXfIndexes[$oldXfIndex]);
432
                        }
433
                        break;
434
 
435
                    case 'CELL':
436
                        for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) {
437
                            for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) {
438
                                $cell = $this->getActiveSheet()->getCellByColumnAndRow($col, $row);
439
                                $oldXfIndex = $cell->getXfIndex();
440
                                $cell->setXfIndex($newXfIndexes[$oldXfIndex]);
441
                            }
442
                        }
443
                        break;
444
                }
445
 
446
            } else {
447
                // not a supervisor, just apply the style array directly on style object
448
                if (array_key_exists('fill', $pStyles)) {
449
                    $this->getFill()->applyFromArray($pStyles['fill']);
450
                }
451
                if (array_key_exists('font', $pStyles)) {
452
                    $this->getFont()->applyFromArray($pStyles['font']);
453
                }
454
                if (array_key_exists('borders', $pStyles)) {
455
                    $this->getBorders()->applyFromArray($pStyles['borders']);
456
                }
457
                if (array_key_exists('alignment', $pStyles)) {
458
                    $this->getAlignment()->applyFromArray($pStyles['alignment']);
459
                }
460
                if (array_key_exists('numberformat', $pStyles)) {
461
                    $this->getNumberFormat()->applyFromArray($pStyles['numberformat']);
462
                }
463
                if (array_key_exists('protection', $pStyles)) {
464
                    $this->getProtection()->applyFromArray($pStyles['protection']);
465
                }
466
            }
467
        } else {
468
            throw new PHPExcel_Exception("Invalid style array passed.");
469
        }
470
        return $this;
471
    }
472
 
473
    /**
474
     * Get Fill
475
     *
476
     * @return PHPExcel_Style_Fill
477
     */
478
    public function getFill()
479
    {
480
        return $this->_fill;
481
    }
482
 
483
    /**
484
     * Get Font
485
     *
486
     * @return PHPExcel_Style_Font
487
     */
488
    public function getFont()
489
    {
490
        return $this->_font;
491
    }
492
 
493
    /**
494
     * Set font
495
     *
496
     * @param PHPExcel_Style_Font $font
497
     * @return PHPExcel_Style
498
     */
499
    public function setFont(PHPExcel_Style_Font $font)
500
    {
501
        $this->_font = $font;
502
        return $this;
503
    }
504
 
505
    /**
506
     * Get Borders
507
     *
508
     * @return PHPExcel_Style_Borders
509
     */
510
    public function getBorders()
511
    {
512
        return $this->_borders;
513
    }
514
 
515
    /**
516
     * Get Alignment
517
     *
518
     * @return PHPExcel_Style_Alignment
519
     */
520
    public function getAlignment()
521
    {
522
        return $this->_alignment;
523
    }
524
 
525
    /**
526
     * Get Number Format
527
     *
528
     * @return PHPExcel_Style_NumberFormat
529
     */
530
    public function getNumberFormat()
531
    {
532
        return $this->_numberFormat;
533
    }
534
 
535
    /**
536
     * Get Conditional Styles. Only used on supervisor.
537
     *
538
     * @return PHPExcel_Style_Conditional[]
539
     */
540
    public function getConditionalStyles()
541
    {
542
        return $this->getActiveSheet()->getConditionalStyles($this->getActiveCell());
543
    }
544
 
545
    /**
546
     * Set Conditional Styles. Only used on supervisor.
547
     *
548
     * @param PHPExcel_Style_Conditional[] $pValue Array of condtional styles
549
     * @return PHPExcel_Style
550
     */
551
    public function setConditionalStyles($pValue = null)
552
    {
553
        if (is_array($pValue)) {
554
            $this->getActiveSheet()->setConditionalStyles($this->getSelectedCells(), $pValue);
555
        }
556
        return $this;
557
    }
558
 
559
    /**
560
     * Get Protection
561
     *
562
     * @return PHPExcel_Style_Protection
563
     */
564
    public function getProtection()
565
    {
566
        return $this->_protection;
567
    }
568
 
569
    /**
570
     * Get hash code
571
     *
572
     * @return string Hash code
573
     */
574
    public function getHashCode()
575
    {
576
        $hashConditionals = '';
577
        foreach ($this->_conditionalStyles as $conditional) {
578
            $hashConditionals .= $conditional->getHashCode();
579
        }
580
 
581
        return md5(
582
              $this->_fill->getHashCode()
583
            . $this->_font->getHashCode()
584
            . $this->_borders->getHashCode()
585
            . $this->_alignment->getHashCode()
586
            . $this->_numberFormat->getHashCode()
587
            . $hashConditionals
588
            . $this->_protection->getHashCode()
589
            . __CLASS__
590
        );
591
    }
592
 
593
    /**
594
     * Get own index in style collection
595
     *
596
     * @return int
597
     */
598
    public function getIndex()
599
    {
600
        return $this->_index;
601
    }
602
 
603
    /**
604
     * Set own index in style collection
605
     *
606
     * @param int $pValue
607
     */
608
    public function setIndex($pValue)
609
    {
610
        $this->_index = $pValue;
611
    }
612
 
613
}