Converting number of Excel column names no longer limited
[phpmyadmin/arisferyanto.git] / libraries / PHPExcel / PHPExcel.php
blob8b9c71f5e2690d614d0b13e96957ffe74b88f3ec
1 <?php
2 /**
3 * PHPExcel
5 * Copyright (c) 2006 - 2010 PHPExcel
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.
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.
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
21 * @category PHPExcel
22 * @package PHPExcel
23 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
24 * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
25 * @version 1.7.3c, 2010-06-01
29 /** PHPExcel root directory */
30 if (!defined('PHPEXCEL_ROOT')) {
31 define('PHPEXCEL_ROOT', dirname(__FILE__) . '/');
32 require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
33 PHPExcel_Autoloader::Register();
34 PHPExcel_Shared_ZipStreamWrapper::register();
35 // check mbstring.func_overload
36 if (ini_get('mbstring.func_overload') & 2) {
37 throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).');
42 /**
43 * PHPExcel
45 * @category PHPExcel
46 * @package PHPExcel
47 * @copyright Copyright (c) 2006 - 2010 PHPExcel (http://www.codeplex.com/PHPExcel)
49 class PHPExcel
51 /**
52 * Document properties
54 * @var PHPExcel_DocumentProperties
56 private $_properties;
58 /**
59 * Document security
61 * @var PHPExcel_DocumentSecurity
63 private $_security;
65 /**
66 * Collection of Worksheet objects
68 * @var PHPExcel_Worksheet[]
70 private $_workSheetCollection = array();
72 /**
73 * Active sheet index
75 * @var int
77 private $_activeSheetIndex = 0;
79 /**
80 * Named ranges
82 * @var PHPExcel_NamedRange[]
84 private $_namedRanges = array();
86 /**
87 * CellXf supervisor
89 * @var PHPExcel_Style
91 private $_cellXfSupervisor;
93 /**
94 * CellXf collection
96 * @var PHPExcel_Style[]
98 private $_cellXfCollection = array();
101 * CellStyleXf collection
103 * @var PHPExcel_Style[]
105 private $_cellStyleXfCollection = array();
108 * Create a new PHPExcel with one Worksheet
110 public function __construct()
112 // Initialise worksheet collection and add one worksheet
113 $this->_workSheetCollection = array();
114 $this->_workSheetCollection[] = new PHPExcel_Worksheet($this);
115 $this->_activeSheetIndex = 0;
117 // Create document properties
118 $this->_properties = new PHPExcel_DocumentProperties();
120 // Create document security
121 $this->_security = new PHPExcel_DocumentSecurity();
123 // Set named ranges
124 $this->_namedRanges = array();
126 // Create the cellXf supervisor
127 $this->_cellXfSupervisor = new PHPExcel_Style(true);
128 $this->_cellXfSupervisor->bindParent($this);
130 // Create the default style
131 $this->addCellXf(new PHPExcel_Style);
132 $this->addCellStyleXf(new PHPExcel_Style);
136 public function disconnectWorksheets() {
137 foreach($this->_workSheetCollection as $k => &$worksheet) {
138 $worksheet->disconnectCells();
139 $this->_workSheetCollection[$k] = null;
141 unset($worksheet);
142 $this->_workSheetCollection = array();
146 * Get properties
148 * @return PHPExcel_DocumentProperties
150 public function getProperties()
152 return $this->_properties;
156 * Set properties
158 * @param PHPExcel_DocumentProperties $pValue
160 public function setProperties(PHPExcel_DocumentProperties $pValue)
162 $this->_properties = $pValue;
166 * Get security
168 * @return PHPExcel_DocumentSecurity
170 public function getSecurity()
172 return $this->_security;
176 * Set security
178 * @param PHPExcel_DocumentSecurity $pValue
180 public function setSecurity(PHPExcel_DocumentSecurity $pValue)
182 $this->_security = $pValue;
186 * Get active sheet
188 * @return PHPExcel_Worksheet
190 public function getActiveSheet()
192 return $this->_workSheetCollection[$this->_activeSheetIndex];
196 * Create sheet and add it to this workbook
198 * @return PHPExcel_Worksheet
200 public function createSheet($iSheetIndex = null)
202 $newSheet = new PHPExcel_Worksheet($this);
203 $this->addSheet($newSheet, $iSheetIndex);
204 return $newSheet;
208 * Add sheet
210 * @param PHPExcel_Worksheet $pSheet
211 * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last)
212 * @return PHPExcel_Worksheet
213 * @throws Exception
215 public function addSheet(PHPExcel_Worksheet $pSheet = null, $iSheetIndex = null)
217 if(is_null($iSheetIndex))
219 $this->_workSheetCollection[] = $pSheet;
221 else
223 // Insert the sheet at the requested index
224 array_splice(
225 $this->_workSheetCollection,
226 $iSheetIndex,
228 array($pSheet)
231 // Adjust active sheet index if necessary
232 if ($this->_activeSheetIndex >= $iSheetIndex) {
233 ++$this->_activeSheetIndex;
237 return $pSheet;
241 * Remove sheet by index
243 * @param int $pIndex Active sheet index
244 * @throws Exception
246 public function removeSheetByIndex($pIndex = 0)
248 if ($pIndex > count($this->_workSheetCollection) - 1) {
249 throw new Exception("Sheet index is out of bounds.");
250 } else {
251 array_splice($this->_workSheetCollection, $pIndex, 1);
256 * Get sheet by index
258 * @param int $pIndex Sheet index
259 * @return PHPExcel_Worksheet
260 * @throws Exception
262 public function getSheet($pIndex = 0)
264 if ($pIndex > count($this->_workSheetCollection) - 1) {
265 throw new Exception("Sheet index is out of bounds.");
266 } else {
267 return $this->_workSheetCollection[$pIndex];
272 * Get all sheets
274 * @return PHPExcel_Worksheet[]
276 public function getAllSheets()
278 return $this->_workSheetCollection;
282 * Get sheet by name
284 * @param string $pName Sheet name
285 * @return PHPExcel_Worksheet
286 * @throws Exception
288 public function getSheetByName($pName = '')
290 $worksheetCount = count($this->_workSheetCollection);
291 for ($i = 0; $i < $worksheetCount; ++$i) {
292 if ($this->_workSheetCollection[$i]->getTitle() == $pName) {
293 return $this->_workSheetCollection[$i];
297 return null;
301 * Get index for sheet
303 * @param PHPExcel_Worksheet $pSheet
304 * @return Sheet index
305 * @throws Exception
307 public function getIndex(PHPExcel_Worksheet $pSheet)
309 foreach ($this->_workSheetCollection as $key => $value) {
310 if ($value->getHashCode() == $pSheet->getHashCode()) {
311 return $key;
317 * Set index for sheet by sheet name.
319 * @param string $sheetName Sheet name to modify index for
320 * @param int $newIndex New index for the sheet
321 * @return New sheet index
322 * @throws Exception
324 public function setIndexByName($sheetName, $newIndex)
326 $oldIndex = $this->getIndex($this->getSheetByName($sheetName));
327 $pSheet = array_splice(
328 $this->_workSheetCollection,
329 $oldIndex,
332 array_splice(
333 $this->_workSheetCollection,
334 $newIndex,
336 $pSheet
338 return $newIndex;
342 * Get sheet count
344 * @return int
346 public function getSheetCount()
348 return count($this->_workSheetCollection);
352 * Get active sheet index
354 * @return int Active sheet index
356 public function getActiveSheetIndex()
358 return $this->_activeSheetIndex;
362 * Set active sheet index
364 * @param int $pIndex Active sheet index
365 * @throws Exception
366 * @return PHPExcel_Worksheet
368 public function setActiveSheetIndex($pIndex = 0)
370 if ($pIndex > count($this->_workSheetCollection) - 1) {
371 throw new Exception("Active sheet index is out of bounds.");
372 } else {
373 $this->_activeSheetIndex = $pIndex;
375 return $this->getActiveSheet();
379 * Set active sheet index by name
381 * @param string $pValue Sheet title
382 * @return PHPExcel_Worksheet
383 * @throws Exception
385 public function setActiveSheetIndexByName($pValue = '')
387 if (($worksheet = $this->getSheetByName($pValue)) instanceof PHPExcel_Worksheet) {
388 $this->setActiveSheetIndex($worksheet->getParent()->getIndex($worksheet));
389 return $worksheet;
392 throw new Exception('Workbook does not contain sheet:' . $pValue);
396 * Get sheet names
398 * @return string[]
400 public function getSheetNames()
402 $returnValue = array();
403 $worksheetCount = $this->getSheetCount();
404 for ($i = 0; $i < $worksheetCount; ++$i) {
405 array_push($returnValue, $this->getSheet($i)->getTitle());
408 return $returnValue;
412 * Add external sheet
414 * @param PHPExcel_Worksheet $pSheet External sheet to add
415 * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last)
416 * @throws Exception
417 * @return PHPExcel_Worksheet
419 public function addExternalSheet(PHPExcel_Worksheet $pSheet, $iSheetIndex = null) {
420 if (!is_null($this->getSheetByName($pSheet->getTitle()))) {
421 throw new Exception("Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename the external sheet first.");
424 // count how many cellXfs there are in this workbook currently, we will need this below
425 $countCellXfs = count($this->_cellXfCollection);
427 // copy all the shared cellXfs from the external workbook and append them to the current
428 foreach ($pSheet->getParent()->getCellXfCollection() as $cellXf) {
429 $this->addCellXf(clone $cellXf);
432 // move sheet to this workbook
433 $pSheet->rebindParent($this);
435 // update the cellXfs
436 foreach ($pSheet->getCellCollection(false) as $cellID) {
437 $cell = $sheet->getCell($cellID);
438 $cell->setXfIndex( $cell->getXfIndex() + $countCellXfs );
441 return $this->addSheet($pSheet, $iSheetIndex);
445 * Get named ranges
447 * @return PHPExcel_NamedRange[]
449 public function getNamedRanges() {
450 return $this->_namedRanges;
454 * Add named range
456 * @param PHPExcel_NamedRange $namedRange
457 * @return PHPExcel
459 public function addNamedRange(PHPExcel_NamedRange $namedRange) {
460 if ($namedRange->getScope() == null) {
461 // global scope
462 $this->_namedRanges[$namedRange->getName()] = $namedRange;
463 } else {
464 // local scope
465 $this->_namedRanges[$namedRange->getScope()->getTitle().'!'.$namedRange->getName()] = $namedRange;
467 return true;
471 * Get named range
473 * @param string $namedRange
474 * @param PHPExcel_Worksheet|null $pSheet Scope. Use null for global scope
475 * @return PHPExcel_NamedRange|null
477 public function getNamedRange($namedRange, PHPExcel_Worksheet $pSheet = null) {
478 $returnValue = null;
480 if ($namedRange != '' && !is_null($namedRange)) {
481 // first look for global defined name
482 if (isset($this->_namedRanges[$namedRange])) {
483 $returnValue = $this->_namedRanges[$namedRange];
486 // then look for local defined name (has priority over global defined name if both names exist)
487 if (!is_null($pSheet) && isset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange])) {
488 $returnValue = $this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange];
492 return $returnValue;
496 * Remove named range
498 * @param string $namedRange
499 * @param PHPExcel_Worksheet|null $pSheet. Scope. Use null for global scope.
500 * @return PHPExcel
502 public function removeNamedRange($namedRange, PHPExcel_Worksheet $pSheet = null) {
503 if (is_null($pSheet)) {
504 if (isset($this->_namedRanges[$namedRange])) {
505 unset($this->_namedRanges[$namedRange]);
507 } else {
508 if (isset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange])) {
509 unset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange]);
512 return $this;
516 * Get worksheet iterator
518 * @return PHPExcel_WorksheetIterator
520 public function getWorksheetIterator() {
521 return new PHPExcel_WorksheetIterator($this);
525 * Copy workbook (!= clone!)
527 * @return PHPExcel
529 public function copy() {
530 $copied = clone $this;
532 $worksheetCount = count($this->_workSheetCollection);
533 for ($i = 0; $i < $worksheetCount; ++$i) {
534 $this->_workSheetCollection[$i] = $this->_workSheetCollection[$i]->copy();
535 $this->_workSheetCollection[$i]->rebindParent($this);
538 return $copied;
542 * Implement PHP __clone to create a deep clone, not just a shallow copy.
544 public function __clone() {
545 foreach($this as $key => $val) {
546 if (is_object($val) || (is_array($val))) {
547 $this->{$key} = unserialize(serialize($val));
553 * Get the workbook collection of cellXfs
555 * @return PHPExcel_Style[]
557 public function getCellXfCollection()
559 return $this->_cellXfCollection;
563 * Get cellXf by index
565 * @param int $index
566 * @return PHPExcel_Style
568 public function getCellXfByIndex($pIndex = 0)
570 return $this->_cellXfCollection[$pIndex];
574 * Get cellXf by hash code
576 * @param string $pValue
577 * @return PHPExcel_Style|false
579 public function getCellXfByHashCode($pValue = '')
581 foreach ($this->_cellXfCollection as $cellXf) {
582 if ($cellXf->getHashCode() == $pValue) {
583 return $cellXf;
586 return false;
590 * Get default style
592 * @return PHPExcel_Style
593 * @throws Exception
595 public function getDefaultStyle()
597 if (isset($this->_cellXfCollection[0])) {
598 return $this->_cellXfCollection[0];
600 throw new Exception('No default style found for this workbook');
604 * Add a cellXf to the workbook
606 * @param PHPExcel_Style
608 public function addCellXf(PHPExcel_Style $style)
610 $this->_cellXfCollection[] = $style;
611 $style->setIndex(count($this->_cellXfCollection) - 1);
615 * Remove cellXf by index. It is ensured that all cells get their xf index updated.
617 * @param int $pIndex Index to cellXf
618 * @throws Exception
620 public function removeCellXfByIndex($pIndex = 0)
622 if ($pIndex > count($this->_cellXfCollection) - 1) {
623 throw new Exception("CellXf index is out of bounds.");
624 } else {
625 // first remove the cellXf
626 array_splice($this->_cellXfCollection, $pIndex, 1);
628 // then update cellXf indexes for cells
629 foreach ($this->_workSheetCollection as $worksheet) {
630 foreach ($worksheet->getCellCollection(false) as $cellID) {
631 $cell = $sheet->getCell($cellID);
632 $xfIndex = $cell->getXfIndex();
633 if ($xfIndex > $pIndex ) {
634 // decrease xf index by 1
635 $cell->setXfIndex($xfIndex - 1);
636 } else if ($xfIndex == $pIndex) {
637 // set to default xf index 0
638 $cell->setXfIndex(0);
646 * Get the cellXf supervisor
648 * @return PHPExcel_Style
650 public function getCellXfSupervisor()
652 return $this->_cellXfSupervisor;
656 * Get the workbook collection of cellStyleXfs
658 * @return PHPExcel_Style[]
660 public function getCellStyleXfCollection()
662 return $this->_cellStyleXfCollection;
666 * Get cellStyleXf by index
668 * @param int $pIndex
669 * @return PHPExcel_Style
671 public function getCellStyleXfByIndex($pIndex = 0)
673 return $this->_cellStyleXfCollection[$pIndex];
677 * Get cellStyleXf by hash code
679 * @param string $pValue
680 * @return PHPExcel_Style|false
682 public function getCellStyleXfByHashCode($pValue = '')
684 foreach ($this->_cellXfStyleCollection as $cellStyleXf) {
685 if ($cellStyleXf->getHashCode() == $pValue) {
686 return $cellStyleXf;
689 return false;
693 * Add a cellStyleXf to the workbook
695 * @param PHPExcel_Style $pStyle
697 public function addCellStyleXf(PHPExcel_Style $pStyle)
699 $this->_cellStyleXfCollection[] = $pStyle;
700 $pStyle->setIndex(count($this->_cellStyleXfCollection) - 1);
704 * Remove cellStyleXf by index
706 * @param int $pIndex
707 * @throws Exception
709 public function removeCellStyleXfByIndex($pIndex = 0)
711 if ($pIndex > count($this->_cellStyleXfCollection) - 1) {
712 throw new Exception("CellStyleXf index is out of bounds.");
713 } else {
714 array_splice($this->_cellStyleXfCollection, $pIndex, 1);
719 * Eliminate all unneeded cellXf and afterwards update the xfIndex for all cells
720 * and columns in the workbook
722 public function garbageCollect()
724 // how many references are there to each cellXf ?
725 $countReferencesCellXf = array();
726 foreach ($this->_cellXfCollection as $index => $cellXf) {
727 $countReferencesCellXf[$index] = 0;
730 foreach ($this->getWorksheetIterator() as $sheet) {
732 // from cells
733 foreach ($sheet->getCellCollection(false) as $cellID) {
734 $cell = $sheet->getCell($cellID);
735 ++$countReferencesCellXf[$cell->getXfIndex()];
738 // from row dimensions
739 foreach ($sheet->getRowDimensions() as $rowDimension) {
740 if ($rowDimension->getXfIndex() !== null) {
741 ++$countReferencesCellXf[$rowDimension->getXfIndex()];
745 // from column dimensions
746 foreach ($sheet->getColumnDimensions() as $columnDimension) {
747 ++$countReferencesCellXf[$columnDimension->getXfIndex()];
751 // remove cellXfs without references and create mapping so we can update xfIndex
752 // for all cells and columns
753 $countNeededCellXfs = 0;
754 foreach ($this->_cellXfCollection as $index => $cellXf) {
755 if ($countReferencesCellXf[$index] > 0 || $index == 0) { // we must never remove the first cellXf
756 ++$countNeededCellXfs;
757 } else {
758 unset($this->_cellXfCollection[$index]);
760 $map[$index] = $countNeededCellXfs - 1;
762 $this->_cellXfCollection = array_values($this->_cellXfCollection);
764 // update the index for all cellXfs
765 foreach ($this->_cellXfCollection as $i => $cellXf) {
766 $cellXf->setIndex($i);
769 // make sure there is always at least one cellXf (there should be)
770 if (count($this->_cellXfCollection) == 0) {
771 $this->_cellXfCollection[] = new PHPExcel_Style();
774 // update the xfIndex for all cells, row dimensions, column dimensions
775 foreach ($this->getWorksheetIterator() as $sheet) {
777 // for all cells
778 foreach ($sheet->getCellCollection(false) as $cellID) {
779 $cell = $sheet->getCell($cellID);
780 $cell->setXfIndex( $map[$cell->getXfIndex()] );
783 // for all row dimensions
784 foreach ($sheet->getRowDimensions() as $rowDimension) {
785 if ($rowDimension->getXfIndex() !== null) {
786 $rowDimension->setXfIndex( $map[$rowDimension->getXfIndex()] );
790 // for all column dimensions
791 foreach ($sheet->getColumnDimensions() as $columnDimension) {
792 $columnDimension->setXfIndex( $map[$columnDimension->getXfIndex()] );
796 // also do garbage collection for all the sheets
797 foreach ($this->getWorksheetIterator() as $sheet) {
798 $sheet->garbageCollect();