New file |
0,0 → 1,613 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
* Lesser General Public License for more details. |
* |
* You should have received a copy of the GNU Lesser General Public |
* License along with this library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Style |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
|
|
/** |
* PHPExcel_Style |
* |
* @category PHPExcel |
* @package PHPExcel_Style |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Style extends PHPExcel_Style_Supervisor implements PHPExcel_IComparable |
{ |
/** |
* Font |
* |
* @var PHPExcel_Style_Font |
*/ |
protected $_font; |
|
/** |
* Fill |
* |
* @var PHPExcel_Style_Fill |
*/ |
protected $_fill; |
|
/** |
* Borders |
* |
* @var PHPExcel_Style_Borders |
*/ |
protected $_borders; |
|
/** |
* Alignment |
* |
* @var PHPExcel_Style_Alignment |
*/ |
protected $_alignment; |
|
/** |
* Number Format |
* |
* @var PHPExcel_Style_NumberFormat |
*/ |
protected $_numberFormat; |
|
/** |
* Conditional styles |
* |
* @var PHPExcel_Style_Conditional[] |
*/ |
protected $_conditionalStyles; |
|
/** |
* Protection |
* |
* @var PHPExcel_Style_Protection |
*/ |
protected $_protection; |
|
/** |
* Index of style in collection. Only used for real style. |
* |
* @var int |
*/ |
protected $_index; |
|
/** |
* Create a new PHPExcel_Style |
* |
* @param boolean $isSupervisor Flag indicating if this is a supervisor or not |
* Leave this value at default unless you understand exactly what |
* its ramifications are |
* @param boolean $isConditional Flag indicating if this is a conditional style or not |
* Leave this value at default unless you understand exactly what |
* its ramifications are |
*/ |
public function __construct($isSupervisor = false, $isConditional = false) |
{ |
// Supervisor? |
$this->_isSupervisor = $isSupervisor; |
|
// Initialise values |
$this->_conditionalStyles = array(); |
$this->_font = new PHPExcel_Style_Font($isSupervisor, $isConditional); |
$this->_fill = new PHPExcel_Style_Fill($isSupervisor, $isConditional); |
$this->_borders = new PHPExcel_Style_Borders($isSupervisor, $isConditional); |
$this->_alignment = new PHPExcel_Style_Alignment($isSupervisor, $isConditional); |
$this->_numberFormat = new PHPExcel_Style_NumberFormat($isSupervisor, $isConditional); |
$this->_protection = new PHPExcel_Style_Protection($isSupervisor, $isConditional); |
|
// bind parent if we are a supervisor |
if ($isSupervisor) { |
$this->_font->bindParent($this); |
$this->_fill->bindParent($this); |
$this->_borders->bindParent($this); |
$this->_alignment->bindParent($this); |
$this->_numberFormat->bindParent($this); |
$this->_protection->bindParent($this); |
} |
} |
|
/** |
* Get the shared style component for the currently active cell in currently active sheet. |
* Only used for style supervisor |
* |
* @return PHPExcel_Style |
*/ |
public function getSharedComponent() |
{ |
$activeSheet = $this->getActiveSheet(); |
$selectedCell = $this->getActiveCell(); // e.g. 'A1' |
|
if ($activeSheet->cellExists($selectedCell)) { |
$xfIndex = $activeSheet->getCell($selectedCell)->getXfIndex(); |
} else { |
$xfIndex = 0; |
} |
|
return $this->_parent->getCellXfByIndex($xfIndex); |
} |
|
/** |
* Get parent. Only used for style supervisor |
* |
* @return PHPExcel |
*/ |
public function getParent() |
{ |
return $this->_parent; |
} |
|
/** |
* Apply styles from array |
* |
* <code> |
* $objPHPExcel->getActiveSheet()->getStyle('B2')->applyFromArray( |
* array( |
* 'font' => array( |
* 'name' => 'Arial', |
* 'bold' => true, |
* 'italic' => false, |
* 'underline' => PHPExcel_Style_Font::UNDERLINE_DOUBLE, |
* 'strike' => false, |
* 'color' => array( |
* 'rgb' => '808080' |
* ) |
* ), |
* 'borders' => array( |
* 'bottom' => array( |
* 'style' => PHPExcel_Style_Border::BORDER_DASHDOT, |
* 'color' => array( |
* 'rgb' => '808080' |
* ) |
* ), |
* 'top' => array( |
* 'style' => PHPExcel_Style_Border::BORDER_DASHDOT, |
* 'color' => array( |
* 'rgb' => '808080' |
* ) |
* ) |
* ) |
* ) |
* ); |
* </code> |
* |
* @param array $pStyles Array containing style information |
* @param boolean $pAdvanced Advanced mode for setting borders. |
* @throws PHPExcel_Exception |
* @return PHPExcel_Style |
*/ |
public function applyFromArray($pStyles = null, $pAdvanced = true) |
{ |
if (is_array($pStyles)) { |
if ($this->_isSupervisor) { |
|
$pRange = $this->getSelectedCells(); |
|
// Uppercase coordinate |
$pRange = strtoupper($pRange); |
|
// Is it a cell range or a single cell? |
if (strpos($pRange, ':') === false) { |
$rangeA = $pRange; |
$rangeB = $pRange; |
} else { |
list($rangeA, $rangeB) = explode(':', $pRange); |
} |
|
// Calculate range outer borders |
$rangeStart = PHPExcel_Cell::coordinateFromString($rangeA); |
$rangeEnd = PHPExcel_Cell::coordinateFromString($rangeB); |
|
// Translate column into index |
$rangeStart[0] = PHPExcel_Cell::columnIndexFromString($rangeStart[0]) - 1; |
$rangeEnd[0] = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]) - 1; |
|
// Make sure we can loop upwards on rows and columns |
if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) { |
$tmp = $rangeStart; |
$rangeStart = $rangeEnd; |
$rangeEnd = $tmp; |
} |
|
// ADVANCED MODE: |
|
if ($pAdvanced && isset($pStyles['borders'])) { |
|
// 'allborders' is a shorthand property for 'outline' and 'inside' and |
// it applies to components that have not been set explicitly |
if (isset($pStyles['borders']['allborders'])) { |
foreach (array('outline', 'inside') as $component) { |
if (!isset($pStyles['borders'][$component])) { |
$pStyles['borders'][$component] = $pStyles['borders']['allborders']; |
} |
} |
unset($pStyles['borders']['allborders']); // not needed any more |
} |
|
// 'outline' is a shorthand property for 'top', 'right', 'bottom', 'left' |
// it applies to components that have not been set explicitly |
if (isset($pStyles['borders']['outline'])) { |
foreach (array('top', 'right', 'bottom', 'left') as $component) { |
if (!isset($pStyles['borders'][$component])) { |
$pStyles['borders'][$component] = $pStyles['borders']['outline']; |
} |
} |
unset($pStyles['borders']['outline']); // not needed any more |
} |
|
// 'inside' is a shorthand property for 'vertical' and 'horizontal' |
// it applies to components that have not been set explicitly |
if (isset($pStyles['borders']['inside'])) { |
foreach (array('vertical', 'horizontal') as $component) { |
if (!isset($pStyles['borders'][$component])) { |
$pStyles['borders'][$component] = $pStyles['borders']['inside']; |
} |
} |
unset($pStyles['borders']['inside']); // not needed any more |
} |
|
// width and height characteristics of selection, 1, 2, or 3 (for 3 or more) |
$xMax = min($rangeEnd[0] - $rangeStart[0] + 1, 3); |
$yMax = min($rangeEnd[1] - $rangeStart[1] + 1, 3); |
|
// loop through up to 3 x 3 = 9 regions |
for ($x = 1; $x <= $xMax; ++$x) { |
// start column index for region |
$colStart = ($x == 3) ? |
PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]) |
: PHPExcel_Cell::stringFromColumnIndex($rangeStart[0] + $x - 1); |
|
// end column index for region |
$colEnd = ($x == 1) ? |
PHPExcel_Cell::stringFromColumnIndex($rangeStart[0]) |
: PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0] - $xMax + $x); |
|
for ($y = 1; $y <= $yMax; ++$y) { |
|
// which edges are touching the region |
$edges = array(); |
|
// are we at left edge |
if ($x == 1) { |
$edges[] = 'left'; |
} |
|
// are we at right edge |
if ($x == $xMax) { |
$edges[] = 'right'; |
} |
|
// are we at top edge? |
if ($y == 1) { |
$edges[] = 'top'; |
} |
|
// are we at bottom edge? |
if ($y == $yMax) { |
$edges[] = 'bottom'; |
} |
|
// start row index for region |
$rowStart = ($y == 3) ? |
$rangeEnd[1] : $rangeStart[1] + $y - 1; |
|
// end row index for region |
$rowEnd = ($y == 1) ? |
$rangeStart[1] : $rangeEnd[1] - $yMax + $y; |
|
// build range for region |
$range = $colStart . $rowStart . ':' . $colEnd . $rowEnd; |
|
// retrieve relevant style array for region |
$regionStyles = $pStyles; |
unset($regionStyles['borders']['inside']); |
|
// what are the inner edges of the region when looking at the selection |
$innerEdges = array_diff( array('top', 'right', 'bottom', 'left'), $edges ); |
|
// inner edges that are not touching the region should take the 'inside' border properties if they have been set |
foreach ($innerEdges as $innerEdge) { |
switch ($innerEdge) { |
case 'top': |
case 'bottom': |
// should pick up 'horizontal' border property if set |
if (isset($pStyles['borders']['horizontal'])) { |
$regionStyles['borders'][$innerEdge] = $pStyles['borders']['horizontal']; |
} else { |
unset($regionStyles['borders'][$innerEdge]); |
} |
break; |
case 'left': |
case 'right': |
// should pick up 'vertical' border property if set |
if (isset($pStyles['borders']['vertical'])) { |
$regionStyles['borders'][$innerEdge] = $pStyles['borders']['vertical']; |
} else { |
unset($regionStyles['borders'][$innerEdge]); |
} |
break; |
} |
} |
|
// apply region style to region by calling applyFromArray() in simple mode |
$this->getActiveSheet()->getStyle($range)->applyFromArray($regionStyles, false); |
} |
} |
return $this; |
} |
|
// SIMPLE MODE: |
|
// Selection type, inspect |
if (preg_match('/^[A-Z]+1:[A-Z]+1048576$/', $pRange)) { |
$selectionType = 'COLUMN'; |
} else if (preg_match('/^A[0-9]+:XFD[0-9]+$/', $pRange)) { |
$selectionType = 'ROW'; |
} else { |
$selectionType = 'CELL'; |
} |
|
// First loop through columns, rows, or cells to find out which styles are affected by this operation |
switch ($selectionType) { |
case 'COLUMN': |
$oldXfIndexes = array(); |
for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { |
$oldXfIndexes[$this->getActiveSheet()->getColumnDimensionByColumn($col)->getXfIndex()] = true; |
} |
break; |
|
case 'ROW': |
$oldXfIndexes = array(); |
for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { |
if ($this->getActiveSheet()->getRowDimension($row)->getXfIndex() == null) { |
$oldXfIndexes[0] = true; // row without explicit style should be formatted based on default style |
} else { |
$oldXfIndexes[$this->getActiveSheet()->getRowDimension($row)->getXfIndex()] = true; |
} |
} |
break; |
|
case 'CELL': |
$oldXfIndexes = array(); |
for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { |
for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { |
$oldXfIndexes[$this->getActiveSheet()->getCellByColumnAndRow($col, $row)->getXfIndex()] = true; |
} |
} |
break; |
} |
|
// clone each of the affected styles, apply the style array, and add the new styles to the workbook |
$workbook = $this->getActiveSheet()->getParent(); |
foreach ($oldXfIndexes as $oldXfIndex => $dummy) { |
$style = $workbook->getCellXfByIndex($oldXfIndex); |
$newStyle = clone $style; |
$newStyle->applyFromArray($pStyles); |
|
if ($workbook->cellXfExists($newStyle)) { |
// there is already such cell Xf in our collection |
$newXfIndexes[$oldXfIndex] = $existingStyle->getIndex(); |
} else { |
// we don't have such a cell Xf, need to add |
$workbook->addCellXf($newStyle); |
$newXfIndexes[$oldXfIndex] = $newStyle->getIndex(); |
} |
} |
|
// Loop through columns, rows, or cells again and update the XF index |
switch ($selectionType) { |
case 'COLUMN': |
for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { |
$columnDimension = $this->getActiveSheet()->getColumnDimensionByColumn($col); |
$oldXfIndex = $columnDimension->getXfIndex(); |
$columnDimension->setXfIndex($newXfIndexes[$oldXfIndex]); |
} |
break; |
|
case 'ROW': |
for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { |
$rowDimension = $this->getActiveSheet()->getRowDimension($row); |
$oldXfIndex = $rowDimension->getXfIndex() === null ? |
0 : $rowDimension->getXfIndex(); // row without explicit style should be formatted based on default style |
$rowDimension->setXfIndex($newXfIndexes[$oldXfIndex]); |
} |
break; |
|
case 'CELL': |
for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { |
for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { |
$cell = $this->getActiveSheet()->getCellByColumnAndRow($col, $row); |
$oldXfIndex = $cell->getXfIndex(); |
$cell->setXfIndex($newXfIndexes[$oldXfIndex]); |
} |
} |
break; |
} |
|
} else { |
// not a supervisor, just apply the style array directly on style object |
if (array_key_exists('fill', $pStyles)) { |
$this->getFill()->applyFromArray($pStyles['fill']); |
} |
if (array_key_exists('font', $pStyles)) { |
$this->getFont()->applyFromArray($pStyles['font']); |
} |
if (array_key_exists('borders', $pStyles)) { |
$this->getBorders()->applyFromArray($pStyles['borders']); |
} |
if (array_key_exists('alignment', $pStyles)) { |
$this->getAlignment()->applyFromArray($pStyles['alignment']); |
} |
if (array_key_exists('numberformat', $pStyles)) { |
$this->getNumberFormat()->applyFromArray($pStyles['numberformat']); |
} |
if (array_key_exists('protection', $pStyles)) { |
$this->getProtection()->applyFromArray($pStyles['protection']); |
} |
} |
} else { |
throw new PHPExcel_Exception("Invalid style array passed."); |
} |
return $this; |
} |
|
/** |
* Get Fill |
* |
* @return PHPExcel_Style_Fill |
*/ |
public function getFill() |
{ |
return $this->_fill; |
} |
|
/** |
* Get Font |
* |
* @return PHPExcel_Style_Font |
*/ |
public function getFont() |
{ |
return $this->_font; |
} |
|
/** |
* Set font |
* |
* @param PHPExcel_Style_Font $font |
* @return PHPExcel_Style |
*/ |
public function setFont(PHPExcel_Style_Font $font) |
{ |
$this->_font = $font; |
return $this; |
} |
|
/** |
* Get Borders |
* |
* @return PHPExcel_Style_Borders |
*/ |
public function getBorders() |
{ |
return $this->_borders; |
} |
|
/** |
* Get Alignment |
* |
* @return PHPExcel_Style_Alignment |
*/ |
public function getAlignment() |
{ |
return $this->_alignment; |
} |
|
/** |
* Get Number Format |
* |
* @return PHPExcel_Style_NumberFormat |
*/ |
public function getNumberFormat() |
{ |
return $this->_numberFormat; |
} |
|
/** |
* Get Conditional Styles. Only used on supervisor. |
* |
* @return PHPExcel_Style_Conditional[] |
*/ |
public function getConditionalStyles() |
{ |
return $this->getActiveSheet()->getConditionalStyles($this->getActiveCell()); |
} |
|
/** |
* Set Conditional Styles. Only used on supervisor. |
* |
* @param PHPExcel_Style_Conditional[] $pValue Array of condtional styles |
* @return PHPExcel_Style |
*/ |
public function setConditionalStyles($pValue = null) |
{ |
if (is_array($pValue)) { |
$this->getActiveSheet()->setConditionalStyles($this->getSelectedCells(), $pValue); |
} |
return $this; |
} |
|
/** |
* Get Protection |
* |
* @return PHPExcel_Style_Protection |
*/ |
public function getProtection() |
{ |
return $this->_protection; |
} |
|
/** |
* Get hash code |
* |
* @return string Hash code |
*/ |
public function getHashCode() |
{ |
$hashConditionals = ''; |
foreach ($this->_conditionalStyles as $conditional) { |
$hashConditionals .= $conditional->getHashCode(); |
} |
|
return md5( |
$this->_fill->getHashCode() |
. $this->_font->getHashCode() |
. $this->_borders->getHashCode() |
. $this->_alignment->getHashCode() |
. $this->_numberFormat->getHashCode() |
. $hashConditionals |
. $this->_protection->getHashCode() |
. __CLASS__ |
); |
} |
|
/** |
* Get own index in style collection |
* |
* @return int |
*/ |
public function getIndex() |
{ |
return $this->_index; |
} |
|
/** |
* Set own index in style collection |
* |
* @param int $pValue |
*/ |
public function setIndex($pValue) |
{ |
$this->_index = $pValue; |
} |
|
} |