[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/phpexcel/PHPExcel/ -> Style.php (source)

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


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1