ILIAS  Release_4_0_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
Style.php
Go to the documentation of this file.
1 <?php
30 if (!defined('PHPEXCEL_ROOT')) {
34  define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../');
35 }
36 
38 require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Color.php';
39 
41 require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Font.php';
42 
44 require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Fill.php';
45 
47 require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Borders.php';
48 
50 require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Alignment.php';
51 
53 require_once PHPEXCEL_ROOT . 'PHPExcel/Style/NumberFormat.php';
54 
56 require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Conditional.php';
57 
59 require_once PHPEXCEL_ROOT . 'PHPExcel/Style/Protection.php';
60 
62 require_once PHPEXCEL_ROOT . 'PHPExcel/IComparable.php';
63 
72 {
78  private $_font;
79 
85  private $_fill;
86 
92  private $_borders;
93 
99  private $_alignment;
100 
106  private $_numberFormat;
107 
114 
120  private $_protection;
121 
127  private $_isSupervisor;
128 
134  private $_parent;
135 
141  private $_index;
142 
148  public function __construct($isSupervisor = false)
149  {
150  // Supervisor?
151  $this->_isSupervisor = $isSupervisor;
152 
153  // Initialise values
154  $this->_conditionalStyles = array();
155  $this->_font = new PHPExcel_Style_Font($isSupervisor);
156  $this->_fill = new PHPExcel_Style_Fill($isSupervisor);
157  $this->_borders = new PHPExcel_Style_Borders($isSupervisor);
158  $this->_alignment = new PHPExcel_Style_Alignment($isSupervisor);
159  $this->_numberFormat = new PHPExcel_Style_NumberFormat($isSupervisor);
160  $this->_protection = new PHPExcel_Style_Protection($isSupervisor);
161 
162  // bind parent if we are a supervisor
163  if ($isSupervisor) {
164  $this->_font->bindParent($this);
165  $this->_fill->bindParent($this);
166  $this->_borders->bindParent($this);
167  $this->_alignment->bindParent($this);
168  $this->_numberFormat->bindParent($this);
169  $this->_protection->bindParent($this);
170  }
171  }
172 
179  public function bindParent($parent)
180  {
181  $this->_parent = $parent;
182  return $this;
183  }
184 
190  public function getIsSupervisor()
191  {
192  return $this->_isSupervisor;
193  }
194 
201  public function getSharedComponent()
202  {
203  $activeSheet = $this->getActiveSheet();
204  $selectedCell = $this->getXActiveCell(); // e.g. 'A1'
205 
206  if ($activeSheet->cellExists($selectedCell)) {
207  $cell = $activeSheet->getCell($selectedCell);
208  $xfIndex = $cell->getXfIndex();
209  } else {
210  $xfIndex = 0;
211  }
212 
213  $activeStyle = $this->_parent->getCellXfByIndex($xfIndex);
214  return $activeStyle;
215  }
216 
222  public function getActiveSheet()
223  {
224  return $this->_parent->getActiveSheet();
225  }
226 
233  public function getXSelectedCells()
234  {
235  return $this->_parent->getActiveSheet()->getXSelectedCells();
236  }
237 
244  public function getXActiveCell()
245  {
246  return $this->_parent->getActiveSheet()->getXActiveCell();
247  }
248 
254  public function getParent()
255  {
256  return $this->_parent;
257  }
258 
298  public function applyFromArray($pStyles = null, $pAdvanced = true) {
299  if (is_array($pStyles)) {
300  if ($this->_isSupervisor) {
301 
302  $pRange = $this->getXSelectedCells();
303 
304  if (is_array($pStyles)) {
305  // Uppercase coordinate
306  $pRange = strtoupper($pRange);
307 
308  // Is it a cell range or a single cell?
309  $rangeA = '';
310  $rangeB = '';
311  if (strpos($pRange, ':') === false) {
312  $rangeA = $pRange;
313  $rangeB = $pRange;
314  } else {
315  list($rangeA, $rangeB) = explode(':', $pRange);
316  }
317 
318  // Calculate range outer borders
319  $rangeStart = PHPExcel_Cell::coordinateFromString($rangeA);
320  $rangeEnd = PHPExcel_Cell::coordinateFromString($rangeB);
321 
322  // Translate column into index
323  $rangeStart[0] = PHPExcel_Cell::columnIndexFromString($rangeStart[0]) - 1;
324  $rangeEnd[0] = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]) - 1;
325 
326  // Make sure we can loop upwards on rows and columns
327  if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) {
328  $tmp = $rangeStart;
329  $rangeStart = $rangeEnd;
330  $rangeEnd = $tmp;
331  }
332 
333  // Advanced mode
334  if ($pAdvanced && isset($pStyles['borders'])) {
335 
336  // 'allborders' is a shorthand property for 'outline' and 'inside' and
337  // it applies to components that have not been set explicitly
338  if (isset($pStyles['borders']['allborders'])) {
339  foreach (array('outline', 'inside') as $component) {
340  if (!isset($pStyles['borders'][$component])) {
341  $pStyles['borders'][$component] = $pStyles['borders']['allborders'];
342  }
343  }
344  unset($pStyles['borders']['allborders']); // not needed any more
345  }
346 
347  // 'outline' is a shorthand property for 'top', 'right', 'bottom', 'left'
348  // it applies to components that have not been set explicitly
349  if (isset($pStyles['borders']['outline'])) {
350  foreach (array('top', 'right', 'bottom', 'left') as $component) {
351  if (!isset($pStyles['borders'][$component])) {
352  $pStyles['borders'][$component] = $pStyles['borders']['outline'];
353  }
354  }
355  unset($pStyles['borders']['outline']); // not needed any more
356  }
357 
358  // 'inside' is a shorthand property for 'vertical' and 'horizontal'
359  // it applies to components that have not been set explicitly
360  if (isset($pStyles['borders']['inside'])) {
361  foreach (array('vertical', 'horizontal') as $component) {
362  if (!isset($pStyles['borders'][$component])) {
363  $pStyles['borders'][$component] = $pStyles['borders']['inside'];
364  }
365  }
366  unset($pStyles['borders']['inside']); // not needed any more
367  }
368 
369  // width and height characteristics of selection, 1, 2, or 3 (for 3 or more)
370  $xMax = min($rangeEnd[0] - $rangeStart[0] + 1, 3);
371  $yMax = min($rangeEnd[1] - $rangeStart[1] + 1, 3);
372 
373  // loop through up to 3 x 3 = 9 regions
374  for ($x = 1; $x <= $xMax; ++$x) {
375  // start column index for region
376  $colStart = ($x == 3) ?
378  : PHPExcel_Cell::stringFromColumnIndex($rangeStart[0] + $x - 1);
379 
380  // end column index for region
381  $colEnd = ($x == 1) ?
383  : PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0] - $xMax + $x);
384 
385  for ($y = 1; $y <= $yMax; ++$y) {
386 
387  // which edges are touching the region
388  $edges = array();
389 
390  // are we at left edge
391  if ($x == 1) {
392  $edges[] = 'left';
393  }
394 
395  // are we at right edge
396  if ($x == $xMax) {
397  $edges[] = 'right';
398  }
399 
400  // are we at top edge?
401  if ($y == 1) {
402  $edges[] = 'top';
403  }
404 
405  // are we at bottom edge?
406  if ($y == $yMax) {
407  $edges[] = 'bottom';
408  }
409 
410  // start row index for region
411  $rowStart = ($y == 3) ?
412  $rangeEnd[1] : $rangeStart[1] + $y - 1;
413 
414  // end row index for region
415  $rowEnd = ($y == 1) ?
416  $rangeStart[1] : $rangeEnd[1] - $yMax + $y;
417 
418  // build range for region
419  $range = $colStart . $rowStart . ':' . $colEnd . $rowEnd;
420 
421  // retrieve relevant style array for region
422  $regionStyles = $pStyles;
423  unset($regionStyles['borders']['inside']);
424 
425  // what are the inner edges of the region when looking at the selection
426  $innerEdges = array_diff( array('top', 'right', 'bottom', 'left'), $edges );
427 
428  // inner edges that are not touching the region should take the 'inside' border properties if they have been set
429  foreach ($innerEdges as $innerEdge) {
430  switch ($innerEdge) {
431  case 'top':
432  case 'bottom':
433  // should pick up 'horizontal' border property if set
434  if (isset($pStyles['borders']['horizontal'])) {
435  $regionStyles['borders'][$innerEdge] = $pStyles['borders']['horizontal'];
436  } else {
437  unset($regionStyles['borders'][$innerEdge]);
438  }
439  break;
440  case 'left':
441  case 'right':
442  // should pick up 'vertical' border property if set
443  if (isset($pStyles['borders']['vertical'])) {
444  $regionStyles['borders'][$innerEdge] = $pStyles['borders']['vertical'];
445  } else {
446  unset($regionStyles['borders'][$innerEdge]);
447  }
448  break;
449  }
450  }
451 
452  // apply region style to region by calling applyFromArray() in simple mode
453  $this->getActiveSheet()->getStyle($range)->applyFromArray($regionStyles, false);
454  }
455  }
456  return;
457  }
458 
459  // Simple mode
460 
461  // First loop through cells to find out which styles are affected by this operation
462  $oldXfIndexes = array();
463  for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) {
464  for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) {
465  $oldXfIndexes[$this->getActiveSheet()->getCellByColumnAndRow($col, $row)->getXfIndex()] = true;
466  }
467  }
468 
469  // clone each of the affected styles, apply the style arrray, and add the new styles to the workbook
470  $workbook = $this->getActiveSheet()->getParent();
471  foreach ($oldXfIndexes as $oldXfIndex => $dummy) {
472  $style = $workbook->getCellXfByIndex($oldXfIndex);
473  $newStyle = clone $style;
474  $newStyle->applyFromArray($pStyles);
475 
476  if ($existingStyle = $workbook->getCellXfByHashCode($newStyle->getHashCode())) {
477  // there is already such cell Xf in our collection
478  $newXfIndexes[$oldXfIndex] = $existingStyle->getIndex();
479  } else {
480  // we don't have such a cell Xf, need to add
481  $workbook->addCellXf($newStyle);
482  $newXfIndexes[$oldXfIndex] = $newStyle->getIndex();
483  }
484  }
485 
486  // Loop through cells again and update the XF index
487  for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) {
488  for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) {
489  $cell = $this->getActiveSheet()->getCellByColumnAndRow($col, $row);
490  $oldXfIndex = $cell->getXfIndex();
491  $cell->setXfIndex($newXfIndexes[$oldXfIndex]);
492  }
493  }
494 
495  } else {
496  throw new Exception("Invalid style array passed.");
497  }
498 
499  } else {
500  if (array_key_exists('fill', $pStyles)) {
501  $this->getFill()->applyFromArray($pStyles['fill']);
502  }
503  if (array_key_exists('font', $pStyles)) {
504  $this->getFont()->applyFromArray($pStyles['font']);
505  }
506  if (array_key_exists('borders', $pStyles)) {
507  $this->getBorders()->applyFromArray($pStyles['borders']);
508  }
509  if (array_key_exists('alignment', $pStyles)) {
510  $this->getAlignment()->applyFromArray($pStyles['alignment']);
511  }
512  if (array_key_exists('numberformat', $pStyles)) {
513  $this->getNumberFormat()->applyFromArray($pStyles['numberformat']);
514  }
515  if (array_key_exists('protection', $pStyles)) {
516  $this->getProtection()->applyFromArray($pStyles['protection']);
517  }
518  }
519  } else {
520  throw new Exception("Invalid style array passed.");
521  }
522  return $this;
523  }
524 
530  public function getFill() {
531  return $this->_fill;
532  }
533 
539  public function getFont() {
540  return $this->_font;
541  }
542 
549  public function setFont(PHPExcel_Style_Font $font)
550  {
551  $this->_font = $font;
552  return $this;
553  }
554 
560  public function getBorders() {
561  return $this->_borders;
562  }
563 
569  public function getAlignment() {
570  return $this->_alignment;
571  }
572 
578  public function getNumberFormat() {
579  return $this->_numberFormat;
580  }
581 
587  public function getConditionalStyles() {
588  return $this->getActiveSheet()->getConditionalStyles($this->getXActiveCell());
589  }
590 
597  public function setConditionalStyles($pValue = null) {
598  if (is_array($pValue)) {
599  foreach (PHPExcel_Cell::extractAllCellReferencesInRange($this->getXSelectedCells()) as $cellReference) {
600  $this->getActiveSheet()->setConditionalStyles($cellReference, $pValue);
601  }
602  }
603  return $this;
604  }
605 
611  public function getProtection() {
612  return $this->_protection;
613  }
614 
620  public function getHashCode() {
621  $hashConditionals = '';
622  foreach ($this->_conditionalStyles as $conditional) {
623  $hashConditionals .= $conditional->getHashCode();
624  }
625 
626  return md5(
627  $this->getFill()->getHashCode()
628  . $this->getFont()->getHashCode()
629  . $this->getBorders()->getHashCode()
630  . $this->getAlignment()->getHashCode()
631  . $this->getNumberFormat()->getHashCode()
632  . $hashConditionals
633  . $this->getProtection()->getHashCode()
634  . __CLASS__
635  );
636  }
637 
643  private $_hashIndex;
644 
653  public function getHashIndex() {
654  return $this->_hashIndex;
655  }
656 
665  public function setHashIndex($value) {
666  $this->_hashIndex = $value;
667  }
668 
674  public function getIndex()
675  {
676  return $this->_index;
677  }
678 
684  public function setIndex($pValue)
685  {
686  $this->_index = $pValue;
687  }
688 
692  public function __clone() {
693  $vars = get_object_vars($this);
694  foreach ($vars as $key => $value) {
695  if (is_object($value)) {
696  $this->$key = clone $value;
697  } else {
698  $this->$key = $value;
699  }
700  }
701  }
702 }