From 10cc7db76bb3289079120206f021cbdd7841189e Mon Sep 17 00:00:00 2001
From: wanghongjun <1445693971@qq,com>
Date: Tue, 24 Oct 2023 11:14:37 +0800
Subject: [PATCH] =?UTF-8?q?=E9=83=A8=E7=BD=B2=E5=88=B0git?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
framework/library/phpexcel/PHPExcel.php | 895 ++++++++++
.../library/phpexcel/PHPExcel/NamedRange.php | 246 +++
.../phpexcel/PHPExcel/ReferenceHelper.php | 918 ++++++++++
.../phpexcel/PHPExcel/Style/NumberFormat.php | 708 ++++++++
.../phpexcel/PHPExcel/Style/Protection.php | 207 +++
.../PHPExcel/Worksheet/PageMargins.php | 220 +++
.../phpexcel/PHPExcel/Worksheet/PageSetup.php | 798 +++++++++
.../PHPExcel/Worksheet/Protection.php | 545 ++++++
.../PHPExcel/Writer/Excel5/Parser.php | 1582 +++++++++++++++++
.../phpexcel/PHPExcel/Writer/OpenDocument.php | 190 ++
.../library/phpexcel/PHPExcel/Writer/PDF.php | 90 +
web/common/permission.inc.php | 943 ++++++++++
.../kindeditor/plugins/code/prettify.css | 13 +
.../kindeditor/plugins/code/prettify.js | 28 +
.../plugins/image/images/refresh.png | Bin 0 -> 800 bytes
.../plugins/multiimage/multiimage.js | 1384 ++++++++++++++
.../kindeditor/plugins/pagebreak/pagebreak.js | 27 +
.../plugins/plainpaste/plainpaste.js | 41 +
.../kindeditor/plugins/preview/preview.js | 31 +
.../plugins/quickformat/quickformat.js | 81 +
.../components/kindeditor/themes/qq/qq.css | 143 ++
.../components/tinymce/langs/readme.md | 3 +
.../tinymce/plugins/advlist/plugin.min.js | 1 +
.../tinymce/plugins/anchor/plugin.min.js | 1 +
.../tinymce/plugins/autolink/plugin.min.js | 1 +
.../tinymce/plugins/autoresize/plugin.min.js | 1 +
.../tinymce/plugins/autosave/plugin.min.js | 1 +
.../tinymce/plugins/bbcode/plugin.min.js | 1 +
.../tinymce/plugins/charmap/plugin.min.js | 1 +
.../tinymce/plugins/code/plugin.min.js | 1 +
.../tinymce/plugins/contextmenu/plugin.min.js | 1 +
.../plugins/directionality/plugin.min.js | 1 +
.../tinymce/plugins/emoticons/plugin.min.js | 1 +
.../tinymce/plugins/example/plugin.min.js | 1 +
.../plugins/example_dependency/plugin.min.js | 1 +
.../tinymce/plugins/fullpage/plugin.min.js | 1 +
.../tinymce/plugins/fullscreen/plugin.min.js | 1 +
.../tinymce/plugins/hr/plugin.min.js | 1 +
.../tinymce/plugins/image/plugin.min.js | 48 +
.../tinymce/plugins/importcss/plugin.min.js | 1 +
.../plugins/insertdatetime/plugin.min.js | 1 +
.../tinymce/plugins/layer/plugin.min.js | 1 +
.../plugins/legacyoutput/plugin.min.js | 1 +
.../tinymce/plugins/link/plugin.min.js | 1 +
.../tinymce/plugins/lists/plugin.min.js | 1 +
.../tinymce/plugins/media/plugin.min.js | 779 ++++++++
.../tinymce/plugins/multiimage/plugin.min.js | 38 +
.../tinymce/plugins/nonbreaking/plugin.min.js | 1 +
.../tinymce/plugins/noneditable/plugin.min.js | 1 +
.../tinymce/plugins/pagebreak/plugin.min.js | 1 +
.../tinymce/plugins/paste/plugin.min.js | 1 +
.../tinymce/plugins/preview/plugin.min.js | 1 +
.../tinymce/plugins/print/plugin.min.js | 1 +
.../tinymce/plugins/save/plugin.min.js | 1 +
.../plugins/searchreplace/plugin.min.js | 1 +
.../plugins/spellchecker/plugin.min.js | 1 +
.../tinymce/plugins/tabfocus/plugin.min.js | 1 +
.../tinymce/plugins/table/plugin.min.js | 1 +
.../tinymce/plugins/template/plugin.min.js | 1 +
.../tinymce/plugins/textcolor/plugin.min.js | 1 +
.../plugins/visualblocks/plugin.min.js | 1 +
.../tinymce/plugins/visualchars/plugin.min.js | 1 +
.../tinymce/plugins/wordcount/plugin.min.js | 1 +
.../tinymce/skins/lightgray/fonts/readme.md | 1 +
.../tinymce/skins/lightgray/img/object.gif | Bin 0 -> 152 bytes
.../dialogs/attachment/images/progress.png | Bin 0 -> 1269 bytes
.../emotion/images/neweditor-tab-bg.png | Bin 0 -> 216 bytes
.../ueditor/dialogs/image/images/progress.png | Bin 0 -> 1269 bytes
.../ueditor/dialogs/music/music.css | 1 +
.../ueditor/dialogs/music/music.html | 32 +
.../components/ueditor/dialogs/music/music.js | 192 ++
.../ueditor/dialogs/preview/preview.html | 40 +
.../ueditor/dialogs/scrawl/images/redo.png | Bin 0 -> 454 bytes
.../ueditor/dialogs/scrawl/images/redoH.png | Bin 0 -> 536 bytes
.../ueditor/dialogs/template/images/pre0.png | Bin 0 -> 250 bytes
.../ueditor/dialogs/template/images/pre1.png | Bin 0 -> 291 bytes
.../ueditor/dialogs/template/images/pre2.png | Bin 0 -> 394 bytes
.../ueditor/dialogs/template/images/pre3.png | Bin 0 -> 485 bytes
.../ueditor/dialogs/template/images/pre4.png | Bin 0 -> 393 bytes
.../dialogs/video/images/none_focus.jpg | Bin 0 -> 11546 bytes
.../ueditor/dialogs/video/images/progress.png | Bin 0 -> 1269 bytes
.../ueditor/lang/en/images/music.png | Bin 0 -> 91561 bytes
.../ueditor/lang/zh-cn/images/music.png | Bin 0 -> 23106 bytes
.../default/images/neweditor-tab-bg.png | Bin 0 -> 216 bytes
.../themes/default/images/pagebreak.gif | Bin 0 -> 54 bytes
.../highcharts/adapters/prototype-adapter.js | 15 +
.../adapters/prototype-adapter.src.js | 316 ++++
.../highcharts/modules/no-data-to-display.js | 12 +
.../modules/no-data-to-display.src.js | 128 ++
web/resource/components/webuploader/README.md | 26 +
.../components/webuploader/progress.png | Bin 0 -> 1269 bytes
web/resource/images/msg-tab-z25df2d.png | Bin 0 -> 1914 bytes
web/resource/images/music-icon.png | Bin 0 -> 1386 bytes
web/resource/images/noavatar_middle.gif | Bin 0 -> 3972 bytes
web/resource/images/nopic-107.png | Bin 0 -> 1955 bytes
web/resource/images/nopic-203.png | Bin 0 -> 11245 bytes
web/resource/images/nopic-account.png | Bin 0 -> 290 bytes
web/resource/images/nopic-module.png | Bin 0 -> 340 bytes
web/resource/images/nopic-small.jpg | Bin 0 -> 9785 bytes
web/resource/images/nopic-template.png | Bin 0 -> 142 bytes
web/resource/images/nopic-user.png | Bin 0 -> 15456 bytes
web/resource/images/nopic.jpg | Bin 0 -> 10262 bytes
web/resource/images/nopic1.jpg | Bin 0 -> 11634 bytes
web/resource/images/pen.png | Bin 0 -> 3408 bytes
web/resource/images/player.jpg | Bin 0 -> 10990 bytes
web/resource/images/radio-icon.png | Bin 0 -> 637 bytes
web/resource/js/app/order.min.js | 1 +
web/resource/js/lib/raty.min.js | 1 +
web/source/account/post-user.ctrl.php | 532 ++++++
web/source/account/post.ctrl.php | 253 +++
web/source/system/optimize.ctrl.php | 79 +
web/source/user/profile.ctrl.php | 450 +++++
web/themes/default/system/optimize.html | 49 +
web/themes/default/user/post.html | 89 +
web/themes/default/user/profile.html | 347 ++++
115 files changed, 12560 insertions(+)
create mode 100644 framework/library/phpexcel/PHPExcel.php
create mode 100644 framework/library/phpexcel/PHPExcel/NamedRange.php
create mode 100644 framework/library/phpexcel/PHPExcel/ReferenceHelper.php
create mode 100644 framework/library/phpexcel/PHPExcel/Style/NumberFormat.php
create mode 100644 framework/library/phpexcel/PHPExcel/Style/Protection.php
create mode 100644 framework/library/phpexcel/PHPExcel/Worksheet/PageMargins.php
create mode 100644 framework/library/phpexcel/PHPExcel/Worksheet/PageSetup.php
create mode 100644 framework/library/phpexcel/PHPExcel/Worksheet/Protection.php
create mode 100644 framework/library/phpexcel/PHPExcel/Writer/Excel5/Parser.php
create mode 100644 framework/library/phpexcel/PHPExcel/Writer/OpenDocument.php
create mode 100644 framework/library/phpexcel/PHPExcel/Writer/PDF.php
create mode 100644 web/common/permission.inc.php
create mode 100644 web/resource/components/kindeditor/plugins/code/prettify.css
create mode 100644 web/resource/components/kindeditor/plugins/code/prettify.js
create mode 100644 web/resource/components/kindeditor/plugins/image/images/refresh.png
create mode 100644 web/resource/components/kindeditor/plugins/multiimage/multiimage.js
create mode 100644 web/resource/components/kindeditor/plugins/pagebreak/pagebreak.js
create mode 100644 web/resource/components/kindeditor/plugins/plainpaste/plainpaste.js
create mode 100644 web/resource/components/kindeditor/plugins/preview/preview.js
create mode 100644 web/resource/components/kindeditor/plugins/quickformat/quickformat.js
create mode 100644 web/resource/components/kindeditor/themes/qq/qq.css
create mode 100644 web/resource/components/tinymce/langs/readme.md
create mode 100644 web/resource/components/tinymce/plugins/advlist/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/anchor/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/autolink/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/autoresize/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/autosave/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/bbcode/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/charmap/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/code/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/contextmenu/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/directionality/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/emoticons/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/example/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/example_dependency/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/fullpage/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/fullscreen/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/hr/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/image/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/importcss/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/insertdatetime/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/layer/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/legacyoutput/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/link/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/lists/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/media/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/multiimage/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/nonbreaking/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/noneditable/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/pagebreak/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/paste/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/preview/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/print/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/save/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/searchreplace/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/spellchecker/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/tabfocus/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/table/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/template/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/textcolor/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/visualblocks/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/visualchars/plugin.min.js
create mode 100644 web/resource/components/tinymce/plugins/wordcount/plugin.min.js
create mode 100644 web/resource/components/tinymce/skins/lightgray/fonts/readme.md
create mode 100644 web/resource/components/tinymce/skins/lightgray/img/object.gif
create mode 100644 web/resource/components/ueditor/dialogs/attachment/images/progress.png
create mode 100644 web/resource/components/ueditor/dialogs/emotion/images/neweditor-tab-bg.png
create mode 100644 web/resource/components/ueditor/dialogs/image/images/progress.png
create mode 100644 web/resource/components/ueditor/dialogs/music/music.css
create mode 100644 web/resource/components/ueditor/dialogs/music/music.html
create mode 100644 web/resource/components/ueditor/dialogs/music/music.js
create mode 100644 web/resource/components/ueditor/dialogs/preview/preview.html
create mode 100644 web/resource/components/ueditor/dialogs/scrawl/images/redo.png
create mode 100644 web/resource/components/ueditor/dialogs/scrawl/images/redoH.png
create mode 100644 web/resource/components/ueditor/dialogs/template/images/pre0.png
create mode 100644 web/resource/components/ueditor/dialogs/template/images/pre1.png
create mode 100644 web/resource/components/ueditor/dialogs/template/images/pre2.png
create mode 100644 web/resource/components/ueditor/dialogs/template/images/pre3.png
create mode 100644 web/resource/components/ueditor/dialogs/template/images/pre4.png
create mode 100644 web/resource/components/ueditor/dialogs/video/images/none_focus.jpg
create mode 100644 web/resource/components/ueditor/dialogs/video/images/progress.png
create mode 100644 web/resource/components/ueditor/lang/en/images/music.png
create mode 100644 web/resource/components/ueditor/lang/zh-cn/images/music.png
create mode 100644 web/resource/components/ueditor/themes/default/images/neweditor-tab-bg.png
create mode 100644 web/resource/components/ueditor/themes/default/images/pagebreak.gif
create mode 100644 web/resource/components/ueditor/third-party/highcharts/adapters/prototype-adapter.js
create mode 100644 web/resource/components/ueditor/third-party/highcharts/adapters/prototype-adapter.src.js
create mode 100644 web/resource/components/ueditor/third-party/highcharts/modules/no-data-to-display.js
create mode 100644 web/resource/components/ueditor/third-party/highcharts/modules/no-data-to-display.src.js
create mode 100644 web/resource/components/webuploader/README.md
create mode 100644 web/resource/components/webuploader/progress.png
create mode 100644 web/resource/images/msg-tab-z25df2d.png
create mode 100644 web/resource/images/music-icon.png
create mode 100644 web/resource/images/noavatar_middle.gif
create mode 100644 web/resource/images/nopic-107.png
create mode 100644 web/resource/images/nopic-203.png
create mode 100644 web/resource/images/nopic-account.png
create mode 100644 web/resource/images/nopic-module.png
create mode 100644 web/resource/images/nopic-small.jpg
create mode 100644 web/resource/images/nopic-template.png
create mode 100644 web/resource/images/nopic-user.png
create mode 100644 web/resource/images/nopic.jpg
create mode 100644 web/resource/images/nopic1.jpg
create mode 100644 web/resource/images/pen.png
create mode 100644 web/resource/images/player.jpg
create mode 100644 web/resource/images/radio-icon.png
create mode 100644 web/resource/js/app/order.min.js
create mode 100644 web/resource/js/lib/raty.min.js
create mode 100644 web/source/account/post-user.ctrl.php
create mode 100644 web/source/account/post.ctrl.php
create mode 100644 web/source/system/optimize.ctrl.php
create mode 100644 web/source/user/profile.ctrl.php
create mode 100644 web/themes/default/system/optimize.html
create mode 100644 web/themes/default/user/post.html
create mode 100644 web/themes/default/user/profile.html
diff --git a/framework/library/phpexcel/PHPExcel.php b/framework/library/phpexcel/PHPExcel.php
new file mode 100644
index 0000000..abacb97
--- /dev/null
+++ b/framework/library/phpexcel/PHPExcel.php
@@ -0,0 +1,895 @@
+_uniqueID = uniqid();
+ $this->_calculationEngine = PHPExcel_Calculation::getInstance($this);
+
+ // Initialise worksheet collection and add one worksheet
+ $this->_workSheetCollection = array();
+ $this->_workSheetCollection[] = new PHPExcel_Worksheet($this);
+ $this->_activeSheetIndex = 0;
+
+ // Create document properties
+ $this->_properties = new PHPExcel_DocumentProperties();
+
+ // Create document security
+ $this->_security = new PHPExcel_DocumentSecurity();
+
+ // Set named ranges
+ $this->_namedRanges = array();
+
+ // Create the cellXf supervisor
+ $this->_cellXfSupervisor = new PHPExcel_Style(true);
+ $this->_cellXfSupervisor->bindParent($this);
+
+ // Create the default style
+ $this->addCellXf(new PHPExcel_Style);
+ $this->addCellStyleXf(new PHPExcel_Style);
+ }
+
+ /**
+ * Code to execute when this worksheet is unset()
+ *
+ */
+ public function __destruct() {
+ PHPExcel_Calculation::unsetInstance($this);
+ $this->disconnectWorksheets();
+ } // function __destruct()
+
+ /**
+ * Disconnect all worksheets from this PHPExcel workbook object,
+ * typically so that the PHPExcel object can be unset
+ *
+ */
+ public function disconnectWorksheets()
+ {
+ $worksheet = NULL;
+ foreach($this->_workSheetCollection as $k => &$worksheet) {
+ $worksheet->disconnectCells();
+ $this->_workSheetCollection[$k] = null;
+ }
+ unset($worksheet);
+ $this->_workSheetCollection = array();
+ }
+
+ /**
+ * Return the calculation engine for this worksheet
+ *
+ * @return PHPExcel_Calculation
+ */
+ public function getCalculationEngine()
+ {
+ return $this->_calculationEngine;
+ } // function getCellCacheController()
+
+ /**
+ * Get properties
+ *
+ * @return PHPExcel_DocumentProperties
+ */
+ public function getProperties()
+ {
+ return $this->_properties;
+ }
+
+ /**
+ * Set properties
+ *
+ * @param PHPExcel_DocumentProperties $pValue
+ */
+ public function setProperties(PHPExcel_DocumentProperties $pValue)
+ {
+ $this->_properties = $pValue;
+ }
+
+ /**
+ * Get security
+ *
+ * @return PHPExcel_DocumentSecurity
+ */
+ public function getSecurity()
+ {
+ return $this->_security;
+ }
+
+ /**
+ * Set security
+ *
+ * @param PHPExcel_DocumentSecurity $pValue
+ */
+ public function setSecurity(PHPExcel_DocumentSecurity $pValue)
+ {
+ $this->_security = $pValue;
+ }
+
+ /**
+ * Get active sheet
+ *
+ * @return PHPExcel_Worksheet
+ */
+ public function getActiveSheet()
+ {
+ return $this->_workSheetCollection[$this->_activeSheetIndex];
+ }
+
+ /**
+ * Create sheet and add it to this workbook
+ *
+ * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last)
+ * @return PHPExcel_Worksheet
+ * @throws PHPExcel_Exception
+ */
+ public function createSheet($iSheetIndex = NULL)
+ {
+ $newSheet = new PHPExcel_Worksheet($this);
+ $this->addSheet($newSheet, $iSheetIndex);
+ return $newSheet;
+ }
+
+ /**
+ * Check if a sheet with a specified name already exists
+ *
+ * @param string $pSheetName Name of the worksheet to check
+ * @return boolean
+ */
+ public function sheetNameExists($pSheetName)
+ {
+ return ($this->getSheetByName($pSheetName) !== NULL);
+ }
+
+ /**
+ * Add sheet
+ *
+ * @param PHPExcel_Worksheet $pSheet
+ * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last)
+ * @return PHPExcel_Worksheet
+ * @throws PHPExcel_Exception
+ */
+ public function addSheet(PHPExcel_Worksheet $pSheet, $iSheetIndex = NULL)
+ {
+ if ($this->sheetNameExists($pSheet->getTitle())) {
+ throw new PHPExcel_Exception(
+ "Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename this worksheet first."
+ );
+ }
+
+ if($iSheetIndex === NULL) {
+ if ($this->_activeSheetIndex < 0) {
+ $this->_activeSheetIndex = 0;
+ }
+ $this->_workSheetCollection[] = $pSheet;
+ } else {
+ // Insert the sheet at the requested index
+ array_splice(
+ $this->_workSheetCollection,
+ $iSheetIndex,
+ 0,
+ array($pSheet)
+ );
+
+ // Adjust active sheet index if necessary
+ if ($this->_activeSheetIndex >= $iSheetIndex) {
+ ++$this->_activeSheetIndex;
+ }
+ }
+ return $pSheet;
+ }
+
+ /**
+ * Remove sheet by index
+ *
+ * @param int $pIndex Active sheet index
+ * @throws PHPExcel_Exception
+ */
+ public function removeSheetByIndex($pIndex = 0)
+ {
+
+ $numSheets = count($this->_workSheetCollection);
+
+ if ($pIndex > $numSheets - 1) {
+ throw new PHPExcel_Exception(
+ "You tried to remove a sheet by the out of bounds index: {$pIndex}. The actual number of sheets is {$numSheets}."
+ );
+ } else {
+ array_splice($this->_workSheetCollection, $pIndex, 1);
+ }
+ // Adjust active sheet index if necessary
+ if (($this->_activeSheetIndex >= $pIndex) &&
+ ($pIndex > count($this->_workSheetCollection) - 1)) {
+ --$this->_activeSheetIndex;
+ }
+
+ }
+
+ /**
+ * Get sheet by index
+ *
+ * @param int $pIndex Sheet index
+ * @return PHPExcel_Worksheet
+ * @throws PHPExcel_Exception
+ */
+ public function getSheet($pIndex = 0)
+ {
+
+ $numSheets = count($this->_workSheetCollection);
+
+ if ($pIndex > $numSheets - 1) {
+ throw new PHPExcel_Exception(
+ "Your requested sheet index: {$pIndex} is out of bounds. The actual number of sheets is {$numSheets}."
+ );
+ } else {
+ return $this->_workSheetCollection[$pIndex];
+ }
+ }
+
+ /**
+ * Get all sheets
+ *
+ * @return PHPExcel_Worksheet[]
+ */
+ public function getAllSheets()
+ {
+ return $this->_workSheetCollection;
+ }
+
+ /**
+ * Get sheet by name
+ *
+ * @param string $pName Sheet name
+ * @return PHPExcel_Worksheet
+ */
+ public function getSheetByName($pName = '')
+ {
+ $worksheetCount = count($this->_workSheetCollection);
+ for ($i = 0; $i < $worksheetCount; ++$i) {
+ if ($this->_workSheetCollection[$i]->getTitle() === $pName) {
+ return $this->_workSheetCollection[$i];
+ }
+ }
+
+ return NULL;
+ }
+
+ /**
+ * Get index for sheet
+ *
+ * @param PHPExcel_Worksheet $pSheet
+ * @return Sheet index
+ * @throws PHPExcel_Exception
+ */
+ public function getIndex(PHPExcel_Worksheet $pSheet)
+ {
+ foreach ($this->_workSheetCollection as $key => $value) {
+ if ($value->getHashCode() == $pSheet->getHashCode()) {
+ return $key;
+ }
+ }
+
+ throw new PHPExcel_Exception("Sheet does not exist.");
+ }
+
+ /**
+ * Set index for sheet by sheet name.
+ *
+ * @param string $sheetName Sheet name to modify index for
+ * @param int $newIndex New index for the sheet
+ * @return New sheet index
+ * @throws PHPExcel_Exception
+ */
+ public function setIndexByName($sheetName, $newIndex)
+ {
+ $oldIndex = $this->getIndex($this->getSheetByName($sheetName));
+ $pSheet = array_splice(
+ $this->_workSheetCollection,
+ $oldIndex,
+ 1
+ );
+ array_splice(
+ $this->_workSheetCollection,
+ $newIndex,
+ 0,
+ $pSheet
+ );
+ return $newIndex;
+ }
+
+ /**
+ * Get sheet count
+ *
+ * @return int
+ */
+ public function getSheetCount()
+ {
+ return count($this->_workSheetCollection);
+ }
+
+ /**
+ * Get active sheet index
+ *
+ * @return int Active sheet index
+ */
+ public function getActiveSheetIndex()
+ {
+ return $this->_activeSheetIndex;
+ }
+
+ /**
+ * Set active sheet index
+ *
+ * @param int $pIndex Active sheet index
+ * @throws PHPExcel_Exception
+ * @return PHPExcel_Worksheet
+ */
+ public function setActiveSheetIndex($pIndex = 0)
+ {
+ $numSheets = count($this->_workSheetCollection);
+
+ if ($pIndex > $numSheets - 1) {
+ throw new PHPExcel_Exception(
+ "You tried to set a sheet active by the out of bounds index: {$pIndex}. The actual number of sheets is {$numSheets}."
+ );
+ } else {
+ $this->_activeSheetIndex = $pIndex;
+ }
+ return $this->getActiveSheet();
+ }
+
+ /**
+ * Set active sheet index by name
+ *
+ * @param string $pValue Sheet title
+ * @return PHPExcel_Worksheet
+ * @throws PHPExcel_Exception
+ */
+ public function setActiveSheetIndexByName($pValue = '')
+ {
+ if (($worksheet = $this->getSheetByName($pValue)) instanceof PHPExcel_Worksheet) {
+ $this->setActiveSheetIndex($this->getIndex($worksheet));
+ return $worksheet;
+ }
+
+ throw new PHPExcel_Exception('Workbook does not contain sheet:' . $pValue);
+ }
+
+ /**
+ * Get sheet names
+ *
+ * @return string[]
+ */
+ public function getSheetNames()
+ {
+ $returnValue = array();
+ $worksheetCount = $this->getSheetCount();
+ for ($i = 0; $i < $worksheetCount; ++$i) {
+ $returnValue[] = $this->getSheet($i)->getTitle();
+ }
+
+ return $returnValue;
+ }
+
+ /**
+ * Add external sheet
+ *
+ * @param PHPExcel_Worksheet $pSheet External sheet to add
+ * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last)
+ * @throws PHPExcel_Exception
+ * @return PHPExcel_Worksheet
+ */
+ public function addExternalSheet(PHPExcel_Worksheet $pSheet, $iSheetIndex = null) {
+ if ($this->sheetNameExists($pSheet->getTitle())) {
+ throw new PHPExcel_Exception("Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename the external sheet first.");
+ }
+
+ // count how many cellXfs there are in this workbook currently, we will need this below
+ $countCellXfs = count($this->_cellXfCollection);
+
+ // copy all the shared cellXfs from the external workbook and append them to the current
+ foreach ($pSheet->getParent()->getCellXfCollection() as $cellXf) {
+ $this->addCellXf(clone $cellXf);
+ }
+
+ // move sheet to this workbook
+ $pSheet->rebindParent($this);
+
+ // update the cellXfs
+ foreach ($pSheet->getCellCollection(false) as $cellID) {
+ $cell = $pSheet->getCell($cellID);
+ $cell->setXfIndex( $cell->getXfIndex() + $countCellXfs );
+ }
+
+ return $this->addSheet($pSheet, $iSheetIndex);
+ }
+
+ /**
+ * Get named ranges
+ *
+ * @return PHPExcel_NamedRange[]
+ */
+ public function getNamedRanges() {
+ return $this->_namedRanges;
+ }
+
+ /**
+ * Add named range
+ *
+ * @param PHPExcel_NamedRange $namedRange
+ * @return PHPExcel
+ */
+ public function addNamedRange(PHPExcel_NamedRange $namedRange) {
+ if ($namedRange->getScope() == null) {
+ // global scope
+ $this->_namedRanges[$namedRange->getName()] = $namedRange;
+ } else {
+ // local scope
+ $this->_namedRanges[$namedRange->getScope()->getTitle().'!'.$namedRange->getName()] = $namedRange;
+ }
+ return true;
+ }
+
+ /**
+ * Get named range
+ *
+ * @param string $namedRange
+ * @param PHPExcel_Worksheet|null $pSheet Scope. Use null for global scope
+ * @return PHPExcel_NamedRange|null
+ */
+ public function getNamedRange($namedRange, PHPExcel_Worksheet $pSheet = null) {
+ $returnValue = null;
+
+ if ($namedRange != '' && ($namedRange !== NULL)) {
+ // first look for global defined name
+ if (isset($this->_namedRanges[$namedRange])) {
+ $returnValue = $this->_namedRanges[$namedRange];
+ }
+
+ // then look for local defined name (has priority over global defined name if both names exist)
+ if (($pSheet !== NULL) && isset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange])) {
+ $returnValue = $this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange];
+ }
+ }
+
+ return $returnValue;
+ }
+
+ /**
+ * Remove named range
+ *
+ * @param string $namedRange
+ * @param PHPExcel_Worksheet|null $pSheet Scope: use null for global scope.
+ * @return PHPExcel
+ */
+ public function removeNamedRange($namedRange, PHPExcel_Worksheet $pSheet = null) {
+ if ($pSheet === NULL) {
+ if (isset($this->_namedRanges[$namedRange])) {
+ unset($this->_namedRanges[$namedRange]);
+ }
+ } else {
+ if (isset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange])) {
+ unset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange]);
+ }
+ }
+ return $this;
+ }
+
+ /**
+ * Get worksheet iterator
+ *
+ * @return PHPExcel_WorksheetIterator
+ */
+ public function getWorksheetIterator() {
+ return new PHPExcel_WorksheetIterator($this);
+ }
+
+ /**
+ * Copy workbook (!= clone!)
+ *
+ * @return PHPExcel
+ */
+ public function copy() {
+ $copied = clone $this;
+
+ $worksheetCount = count($this->_workSheetCollection);
+ for ($i = 0; $i < $worksheetCount; ++$i) {
+ $this->_workSheetCollection[$i] = $this->_workSheetCollection[$i]->copy();
+ $this->_workSheetCollection[$i]->rebindParent($this);
+ }
+
+ return $copied;
+ }
+
+ /**
+ * Implement PHP __clone to create a deep clone, not just a shallow copy.
+ */
+ public function __clone() {
+ foreach($this as $key => $val) {
+ if (is_object($val) || (is_array($val))) {
+ $this->{$key} = unserialize(serialize($val));
+ }
+ }
+ }
+
+ /**
+ * Get the workbook collection of cellXfs
+ *
+ * @return PHPExcel_Style[]
+ */
+ public function getCellXfCollection()
+ {
+ return $this->_cellXfCollection;
+ }
+
+ /**
+ * Get cellXf by index
+ *
+ * @param int $pIndex
+ * @return PHPExcel_Style
+ */
+ public function getCellXfByIndex($pIndex = 0)
+ {
+ return $this->_cellXfCollection[$pIndex];
+ }
+
+ /**
+ * Get cellXf by hash code
+ *
+ * @param string $pValue
+ * @return PHPExcel_Style|false
+ */
+ public function getCellXfByHashCode($pValue = '')
+ {
+ foreach ($this->_cellXfCollection as $cellXf) {
+ if ($cellXf->getHashCode() == $pValue) {
+ return $cellXf;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Check if style exists in style collection
+ *
+ * @param PHPExcel_Style $pCellStyle
+ * @return boolean
+ */
+ public function cellXfExists($pCellStyle = null)
+ {
+ return in_array($pCellStyle, $this->_cellXfCollection, true);
+ }
+
+ /**
+ * Get default style
+ *
+ * @return PHPExcel_Style
+ * @throws PHPExcel_Exception
+ */
+ public function getDefaultStyle()
+ {
+ if (isset($this->_cellXfCollection[0])) {
+ return $this->_cellXfCollection[0];
+ }
+ throw new PHPExcel_Exception('No default style found for this workbook');
+ }
+
+ /**
+ * Add a cellXf to the workbook
+ *
+ * @param PHPExcel_Style $style
+ */
+ public function addCellXf(PHPExcel_Style $style)
+ {
+ $this->_cellXfCollection[] = $style;
+ $style->setIndex(count($this->_cellXfCollection) - 1);
+ }
+
+ /**
+ * Remove cellXf by index. It is ensured that all cells get their xf index updated.
+ *
+ * @param int $pIndex Index to cellXf
+ * @throws PHPExcel_Exception
+ */
+ public function removeCellXfByIndex($pIndex = 0)
+ {
+ if ($pIndex > count($this->_cellXfCollection) - 1) {
+ throw new PHPExcel_Exception("CellXf index is out of bounds.");
+ } else {
+ // first remove the cellXf
+ array_splice($this->_cellXfCollection, $pIndex, 1);
+
+ // then update cellXf indexes for cells
+ foreach ($this->_workSheetCollection as $worksheet) {
+ foreach ($worksheet->getCellCollection(false) as $cellID) {
+ $cell = $worksheet->getCell($cellID);
+ $xfIndex = $cell->getXfIndex();
+ if ($xfIndex > $pIndex ) {
+ // decrease xf index by 1
+ $cell->setXfIndex($xfIndex - 1);
+ } else if ($xfIndex == $pIndex) {
+ // set to default xf index 0
+ $cell->setXfIndex(0);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Get the cellXf supervisor
+ *
+ * @return PHPExcel_Style
+ */
+ public function getCellXfSupervisor()
+ {
+ return $this->_cellXfSupervisor;
+ }
+
+ /**
+ * Get the workbook collection of cellStyleXfs
+ *
+ * @return PHPExcel_Style[]
+ */
+ public function getCellStyleXfCollection()
+ {
+ return $this->_cellStyleXfCollection;
+ }
+
+ /**
+ * Get cellStyleXf by index
+ *
+ * @param int $pIndex
+ * @return PHPExcel_Style
+ */
+ public function getCellStyleXfByIndex($pIndex = 0)
+ {
+ return $this->_cellStyleXfCollection[$pIndex];
+ }
+
+ /**
+ * Get cellStyleXf by hash code
+ *
+ * @param string $pValue
+ * @return PHPExcel_Style|false
+ */
+ public function getCellStyleXfByHashCode($pValue = '')
+ {
+ foreach ($this->_cellXfStyleCollection as $cellStyleXf) {
+ if ($cellStyleXf->getHashCode() == $pValue) {
+ return $cellStyleXf;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Add a cellStyleXf to the workbook
+ *
+ * @param PHPExcel_Style $pStyle
+ */
+ public function addCellStyleXf(PHPExcel_Style $pStyle)
+ {
+ $this->_cellStyleXfCollection[] = $pStyle;
+ $pStyle->setIndex(count($this->_cellStyleXfCollection) - 1);
+ }
+
+ /**
+ * Remove cellStyleXf by index
+ *
+ * @param int $pIndex
+ * @throws PHPExcel_Exception
+ */
+ public function removeCellStyleXfByIndex($pIndex = 0)
+ {
+ if ($pIndex > count($this->_cellStyleXfCollection) - 1) {
+ throw new PHPExcel_Exception("CellStyleXf index is out of bounds.");
+ } else {
+ array_splice($this->_cellStyleXfCollection, $pIndex, 1);
+ }
+ }
+
+ /**
+ * Eliminate all unneeded cellXf and afterwards update the xfIndex for all cells
+ * and columns in the workbook
+ */
+ public function garbageCollect()
+ {
+ // how many references are there to each cellXf ?
+ $countReferencesCellXf = array();
+ foreach ($this->_cellXfCollection as $index => $cellXf) {
+ $countReferencesCellXf[$index] = 0;
+ }
+
+ foreach ($this->getWorksheetIterator() as $sheet) {
+
+ // from cells
+ foreach ($sheet->getCellCollection(false) as $cellID) {
+ $cell = $sheet->getCell($cellID);
+ ++$countReferencesCellXf[$cell->getXfIndex()];
+ }
+
+ // from row dimensions
+ foreach ($sheet->getRowDimensions() as $rowDimension) {
+ if ($rowDimension->getXfIndex() !== null) {
+ ++$countReferencesCellXf[$rowDimension->getXfIndex()];
+ }
+ }
+
+ // from column dimensions
+ foreach ($sheet->getColumnDimensions() as $columnDimension) {
+ ++$countReferencesCellXf[$columnDimension->getXfIndex()];
+ }
+ }
+
+ // remove cellXfs without references and create mapping so we can update xfIndex
+ // for all cells and columns
+ $countNeededCellXfs = 0;
+ foreach ($this->_cellXfCollection as $index => $cellXf) {
+ if ($countReferencesCellXf[$index] > 0 || $index == 0) { // we must never remove the first cellXf
+ ++$countNeededCellXfs;
+ } else {
+ unset($this->_cellXfCollection[$index]);
+ }
+ $map[$index] = $countNeededCellXfs - 1;
+ }
+ $this->_cellXfCollection = array_values($this->_cellXfCollection);
+
+ // update the index for all cellXfs
+ foreach ($this->_cellXfCollection as $i => $cellXf) {
+ $cellXf->setIndex($i);
+ }
+
+ // make sure there is always at least one cellXf (there should be)
+ if (empty($this->_cellXfCollection)) {
+ $this->_cellXfCollection[] = new PHPExcel_Style();
+ }
+
+ // update the xfIndex for all cells, row dimensions, column dimensions
+ foreach ($this->getWorksheetIterator() as $sheet) {
+
+ // for all cells
+ foreach ($sheet->getCellCollection(false) as $cellID) {
+ $cell = $sheet->getCell($cellID);
+ $cell->setXfIndex( $map[$cell->getXfIndex()] );
+ }
+
+ // for all row dimensions
+ foreach ($sheet->getRowDimensions() as $rowDimension) {
+ if ($rowDimension->getXfIndex() !== null) {
+ $rowDimension->setXfIndex( $map[$rowDimension->getXfIndex()] );
+ }
+ }
+
+ // for all column dimensions
+ foreach ($sheet->getColumnDimensions() as $columnDimension) {
+ $columnDimension->setXfIndex( $map[$columnDimension->getXfIndex()] );
+ }
+
+ // also do garbage collection for all the sheets
+ $sheet->garbageCollect();
+ }
+ }
+
+ /**
+ * Return the unique ID value assigned to this spreadsheet workbook
+ *
+ * @return string
+ */
+ public function getID() {
+ return $this->_uniqueID;
+ }
+
+}
diff --git a/framework/library/phpexcel/PHPExcel/NamedRange.php b/framework/library/phpexcel/PHPExcel/NamedRange.php
new file mode 100644
index 0000000..9e7d41e
--- /dev/null
+++ b/framework/library/phpexcel/PHPExcel/NamedRange.php
@@ -0,0 +1,246 @@
+_worksheet)
+ *
+ * @var bool
+ */
+ private $_localOnly;
+
+ /**
+ * Scope
+ *
+ * @var PHPExcel_Worksheet
+ */
+ private $_scope;
+
+ /**
+ * Create a new NamedRange
+ *
+ * @param string $pName
+ * @param PHPExcel_Worksheet $pWorksheet
+ * @param string $pRange
+ * @param bool $pLocalOnly
+ * @param PHPExcel_Worksheet|null $pScope Scope. Only applies when $pLocalOnly = true. Null for global scope.
+ * @throws PHPExcel_Exception
+ */
+ public function __construct($pName = null, PHPExcel_Worksheet $pWorksheet, $pRange = 'A1', $pLocalOnly = false, $pScope = null)
+ {
+ // Validate data
+ if (($pName === NULL) || ($pWorksheet === NULL) || ($pRange === NULL)) {
+ throw new PHPExcel_Exception('Parameters can not be null.');
+ }
+
+ // Set local members
+ $this->_name = $pName;
+ $this->_worksheet = $pWorksheet;
+ $this->_range = $pRange;
+ $this->_localOnly = $pLocalOnly;
+ $this->_scope = ($pLocalOnly == true) ?
+ (($pScope == null) ? $pWorksheet : $pScope) : null;
+ }
+
+ /**
+ * Get name
+ *
+ * @return string
+ */
+ public function getName() {
+ return $this->_name;
+ }
+
+ /**
+ * Set name
+ *
+ * @param string $value
+ * @return PHPExcel_NamedRange
+ */
+ public function setName($value = null) {
+ if ($value !== NULL) {
+ // Old title
+ $oldTitle = $this->_name;
+
+ // Re-attach
+ if ($this->_worksheet !== NULL) {
+ $this->_worksheet->getParent()->removeNamedRange($this->_name,$this->_worksheet);
+ }
+ $this->_name = $value;
+
+ if ($this->_worksheet !== NULL) {
+ $this->_worksheet->getParent()->addNamedRange($this);
+ }
+
+ // New title
+ $newTitle = $this->_name;
+ PHPExcel_ReferenceHelper::getInstance()->updateNamedFormulas($this->_worksheet->getParent(), $oldTitle, $newTitle);
+ }
+ return $this;
+ }
+
+ /**
+ * Get worksheet
+ *
+ * @return PHPExcel_Worksheet
+ */
+ public function getWorksheet() {
+ return $this->_worksheet;
+ }
+
+ /**
+ * Set worksheet
+ *
+ * @param PHPExcel_Worksheet $value
+ * @return PHPExcel_NamedRange
+ */
+ public function setWorksheet(PHPExcel_Worksheet $value = null) {
+ if ($value !== NULL) {
+ $this->_worksheet = $value;
+ }
+ return $this;
+ }
+
+ /**
+ * Get range
+ *
+ * @return string
+ */
+ public function getRange() {
+ return $this->_range;
+ }
+
+ /**
+ * Set range
+ *
+ * @param string $value
+ * @return PHPExcel_NamedRange
+ */
+ public function setRange($value = null) {
+ if ($value !== NULL) {
+ $this->_range = $value;
+ }
+ return $this;
+ }
+
+ /**
+ * Get localOnly
+ *
+ * @return bool
+ */
+ public function getLocalOnly() {
+ return $this->_localOnly;
+ }
+
+ /**
+ * Set localOnly
+ *
+ * @param bool $value
+ * @return PHPExcel_NamedRange
+ */
+ public function setLocalOnly($value = false) {
+ $this->_localOnly = $value;
+ $this->_scope = $value ? $this->_worksheet : null;
+ return $this;
+ }
+
+ /**
+ * Get scope
+ *
+ * @return PHPExcel_Worksheet|null
+ */
+ public function getScope() {
+ return $this->_scope;
+ }
+
+ /**
+ * Set scope
+ *
+ * @param PHPExcel_Worksheet|null $value
+ * @return PHPExcel_NamedRange
+ */
+ public function setScope(PHPExcel_Worksheet $value = null) {
+ $this->_scope = $value;
+ $this->_localOnly = ($value == null) ? false : true;
+ return $this;
+ }
+
+ /**
+ * Resolve a named range to a regular cell range
+ *
+ * @param string $pNamedRange Named range
+ * @param PHPExcel_Worksheet|null $pSheet Scope. Use null for global scope
+ * @return PHPExcel_NamedRange
+ */
+ public static function resolveRange($pNamedRange = '', PHPExcel_Worksheet $pSheet) {
+ return $pSheet->getParent()->getNamedRange($pNamedRange, $pSheet);
+ }
+
+ /**
+ * Implement PHP __clone to create a deep clone, not just a shallow copy.
+ */
+ public function __clone() {
+ $vars = get_object_vars($this);
+ foreach ($vars as $key => $value) {
+ if (is_object($value)) {
+ $this->$key = clone $value;
+ } else {
+ $this->$key = $value;
+ }
+ }
+ }
+}
diff --git a/framework/library/phpexcel/PHPExcel/ReferenceHelper.php b/framework/library/phpexcel/PHPExcel/ReferenceHelper.php
new file mode 100644
index 0000000..bf7771a
--- /dev/null
+++ b/framework/library/phpexcel/PHPExcel/ReferenceHelper.php
@@ -0,0 +1,918 @@
+= ($beforeRow + $pNumRows)) &&
+ ($cellRow < $beforeRow)) {
+ return TRUE;
+ } elseif ($pNumCols < 0 &&
+ ($cellColumnIndex >= ($beforeColumnIndex + $pNumCols)) &&
+ ($cellColumnIndex < $beforeColumnIndex)) {
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ /**
+ * Update page breaks when inserting/deleting rows/columns
+ *
+ * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing
+ * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1')
+ * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before
+ * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion)
+ * @param integer $beforeRow Number of the row we're inserting/deleting before
+ * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion)
+ */
+ protected function _adjustPageBreaks(PHPExcel_Worksheet $pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows)
+ {
+ $aBreaks = $pSheet->getBreaks();
+ ($pNumCols > 0 || $pNumRows > 0) ?
+ uksort($aBreaks, array('PHPExcel_ReferenceHelper','cellReverseSort')) :
+ uksort($aBreaks, array('PHPExcel_ReferenceHelper','cellSort'));
+
+ foreach ($aBreaks as $key => $value) {
+ if (self::cellAddressInDeleteRange($key, $beforeRow, $pNumRows, $beforeColumnIndex, $pNumCols)) {
+ // If we're deleting, then clear any defined breaks that are within the range
+ // of rows/columns that we're deleting
+ $pSheet->setBreak($key, PHPExcel_Worksheet::BREAK_NONE);
+ } else {
+ // Otherwise update any affected breaks by inserting a new break at the appropriate point
+ // and removing the old affected break
+ $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows);
+ if ($key != $newReference) {
+ $pSheet->setBreak($newReference, $value)
+ ->setBreak($key, PHPExcel_Worksheet::BREAK_NONE);
+ }
+ }
+ }
+ }
+
+ /**
+ * Update cell comments when inserting/deleting rows/columns
+ *
+ * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing
+ * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1')
+ * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before
+ * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion)
+ * @param integer $beforeRow Number of the row we're inserting/deleting before
+ * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion)
+ */
+ protected function _adjustComments($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows)
+ {
+ $aComments = $pSheet->getComments();
+ $aNewComments = array(); // the new array of all comments
+
+ foreach ($aComments as $key => &$value) {
+ // Any comments inside a deleted range will be ignored
+ if (!self::cellAddressInDeleteRange($key, $beforeRow, $pNumRows, $beforeColumnIndex, $pNumCols)) {
+ // Otherwise build a new array of comments indexed by the adjusted cell reference
+ $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows);
+ $aNewComments[$newReference] = $value;
+ }
+ }
+ // Replace the comments array with the new set of comments
+ $pSheet->setComments($aNewComments);
+ }
+
+ /**
+ * Update hyperlinks when inserting/deleting rows/columns
+ *
+ * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing
+ * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1')
+ * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before
+ * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion)
+ * @param integer $beforeRow Number of the row we're inserting/deleting before
+ * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion)
+ */
+ protected function _adjustHyperlinks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows)
+ {
+ $aHyperlinkCollection = $pSheet->getHyperlinkCollection();
+ ($pNumCols > 0 || $pNumRows > 0) ?
+ uksort($aHyperlinkCollection, array('PHPExcel_ReferenceHelper','cellReverseSort')) :
+ uksort($aHyperlinkCollection, array('PHPExcel_ReferenceHelper','cellSort'));
+
+ foreach ($aHyperlinkCollection as $key => $value) {
+ $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows);
+ if ($key != $newReference) {
+ $pSheet->setHyperlink( $newReference, $value );
+ $pSheet->setHyperlink( $key, null );
+ }
+ }
+ }
+
+ /**
+ * Update data validations when inserting/deleting rows/columns
+ *
+ * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing
+ * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1')
+ * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before
+ * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion)
+ * @param integer $beforeRow Number of the row we're inserting/deleting before
+ * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion)
+ */
+ protected function _adjustDataValidations($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows)
+ {
+ $aDataValidationCollection = $pSheet->getDataValidationCollection();
+ ($pNumCols > 0 || $pNumRows > 0) ?
+ uksort($aDataValidationCollection, array('PHPExcel_ReferenceHelper','cellReverseSort')) :
+ uksort($aDataValidationCollection, array('PHPExcel_ReferenceHelper','cellSort'));
+ foreach ($aDataValidationCollection as $key => $value) {
+ $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows);
+ if ($key != $newReference) {
+ $pSheet->setDataValidation( $newReference, $value );
+ $pSheet->setDataValidation( $key, null );
+ }
+ }
+ }
+
+ /**
+ * Update merged cells when inserting/deleting rows/columns
+ *
+ * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing
+ * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1')
+ * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before
+ * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion)
+ * @param integer $beforeRow Number of the row we're inserting/deleting before
+ * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion)
+ */
+ protected function _adjustMergeCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows)
+ {
+ $aMergeCells = $pSheet->getMergeCells();
+ $aNewMergeCells = array(); // the new array of all merge cells
+ foreach ($aMergeCells as $key => &$value) {
+ $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows);
+ $aNewMergeCells[$newReference] = $newReference;
+ }
+ $pSheet->setMergeCells($aNewMergeCells); // replace the merge cells array
+ }
+
+ /**
+ * Update protected cells when inserting/deleting rows/columns
+ *
+ * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing
+ * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1')
+ * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before
+ * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion)
+ * @param integer $beforeRow Number of the row we're inserting/deleting before
+ * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion)
+ */
+ protected function _adjustProtectedCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows)
+ {
+ $aProtectedCells = $pSheet->getProtectedCells();
+ ($pNumCols > 0 || $pNumRows > 0) ?
+ uksort($aProtectedCells, array('PHPExcel_ReferenceHelper','cellReverseSort')) :
+ uksort($aProtectedCells, array('PHPExcel_ReferenceHelper','cellSort'));
+ foreach ($aProtectedCells as $key => $value) {
+ $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows);
+ if ($key != $newReference) {
+ $pSheet->protectCells( $newReference, $value, true );
+ $pSheet->unprotectCells( $key );
+ }
+ }
+ }
+
+ /**
+ * Update column dimensions when inserting/deleting rows/columns
+ *
+ * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing
+ * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1')
+ * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before
+ * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion)
+ * @param integer $beforeRow Number of the row we're inserting/deleting before
+ * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion)
+ */
+ protected function _adjustColumnDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows)
+ {
+ $aColumnDimensions = array_reverse($pSheet->getColumnDimensions(), true);
+ if (!empty($aColumnDimensions)) {
+ foreach ($aColumnDimensions as $objColumnDimension) {
+ $newReference = $this->updateCellReference($objColumnDimension->getColumnIndex() . '1', $pBefore, $pNumCols, $pNumRows);
+ list($newReference) = PHPExcel_Cell::coordinateFromString($newReference);
+ if ($objColumnDimension->getColumnIndex() != $newReference) {
+ $objColumnDimension->setColumnIndex($newReference);
+ }
+ }
+ $pSheet->refreshColumnDimensions();
+ }
+ }
+
+ /**
+ * Update row dimensions when inserting/deleting rows/columns
+ *
+ * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing
+ * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1')
+ * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before
+ * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion)
+ * @param integer $beforeRow Number of the row we're inserting/deleting before
+ * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion)
+ */
+ protected function _adjustRowDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows)
+ {
+ $aRowDimensions = array_reverse($pSheet->getRowDimensions(), true);
+ if (!empty($aRowDimensions)) {
+ foreach ($aRowDimensions as $objRowDimension) {
+ $newReference = $this->updateCellReference('A' . $objRowDimension->getRowIndex(), $pBefore, $pNumCols, $pNumRows);
+ list(, $newReference) = PHPExcel_Cell::coordinateFromString($newReference);
+ if ($objRowDimension->getRowIndex() != $newReference) {
+ $objRowDimension->setRowIndex($newReference);
+ }
+ }
+ $pSheet->refreshRowDimensions();
+
+ $copyDimension = $pSheet->getRowDimension($beforeRow - 1);
+ for ($i = $beforeRow; $i <= $beforeRow - 1 + $pNumRows; ++$i) {
+ $newDimension = $pSheet->getRowDimension($i);
+ $newDimension->setRowHeight($copyDimension->getRowHeight());
+ $newDimension->setVisible($copyDimension->getVisible());
+ $newDimension->setOutlineLevel($copyDimension->getOutlineLevel());
+ $newDimension->setCollapsed($copyDimension->getCollapsed());
+ }
+ }
+ }
+
+ /**
+ * Insert a new column or row, updating all possible related data
+ *
+ * @param string $pBefore Insert before this cell address (e.g. 'A1')
+ * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion)
+ * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion)
+ * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing
+ * @throws PHPExcel_Exception
+ */
+ public function insertNewBefore($pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, PHPExcel_Worksheet $pSheet = NULL)
+ {
+ $remove = ($pNumCols < 0 || $pNumRows < 0);
+ $aCellCollection = $pSheet->getCellCollection();
+
+ // Get coordinates of $pBefore
+ $beforeColumn = 'A';
+ $beforeRow = 1;
+ list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString($pBefore);
+ $beforeColumnIndex = PHPExcel_Cell::columnIndexFromString($beforeColumn);
+
+ // Clear cells if we are removing columns or rows
+ $highestColumn = $pSheet->getHighestColumn();
+ $highestRow = $pSheet->getHighestRow();
+
+ // 1. Clear column strips if we are removing columns
+ if ($pNumCols < 0 && $beforeColumnIndex - 2 + $pNumCols > 0) {
+ for ($i = 1; $i <= $highestRow - 1; ++$i) {
+ for ($j = $beforeColumnIndex - 1 + $pNumCols; $j <= $beforeColumnIndex - 2; ++$j) {
+ $coordinate = PHPExcel_Cell::stringFromColumnIndex($j) . $i;
+ $pSheet->removeConditionalStyles($coordinate);
+ if ($pSheet->cellExists($coordinate)) {
+ $pSheet->getCell($coordinate)->setValueExplicit('', PHPExcel_Cell_DataType::TYPE_NULL);
+ $pSheet->getCell($coordinate)->setXfIndex(0);
+ }
+ }
+ }
+ }
+
+ // 2. Clear row strips if we are removing rows
+ if ($pNumRows < 0 && $beforeRow - 1 + $pNumRows > 0) {
+ for ($i = $beforeColumnIndex - 1; $i <= PHPExcel_Cell::columnIndexFromString($highestColumn) - 1; ++$i) {
+ for ($j = $beforeRow + $pNumRows; $j <= $beforeRow - 1; ++$j) {
+ $coordinate = PHPExcel_Cell::stringFromColumnIndex($i) . $j;
+ $pSheet->removeConditionalStyles($coordinate);
+ if ($pSheet->cellExists($coordinate)) {
+ $pSheet->getCell($coordinate)->setValueExplicit('', PHPExcel_Cell_DataType::TYPE_NULL);
+ $pSheet->getCell($coordinate)->setXfIndex(0);
+ }
+ }
+ }
+ }
+
+ // Loop through cells, bottom-up, and change cell coordinates
+ while (($cellID = $remove ? array_shift($aCellCollection) : array_pop($aCellCollection))) {
+ $cell = $pSheet->getCell($cellID);
+ $cellIndex = PHPExcel_Cell::columnIndexFromString($cell->getColumn());
+ if ($cellIndex-1 + $pNumCols < 0) {
+ continue;
+ }
+
+ // New coordinates
+ $newCoordinates = PHPExcel_Cell::stringFromColumnIndex($cellIndex-1 + $pNumCols) . ($cell->getRow() + $pNumRows);
+
+ // Should the cell be updated? Move value and cellXf index from one cell to another.
+ if (($cellIndex >= $beforeColumnIndex) &&
+ ($cell->getRow() >= $beforeRow)) {
+
+ // Update cell styles
+ $pSheet->getCell($newCoordinates)->setXfIndex($cell->getXfIndex());
+
+ // Insert this cell at its new location
+ if ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA) {
+ // Formula should be adjusted
+ $pSheet->getCell($newCoordinates)
+ ->setValue($this->updateFormulaReferences($cell->getValue(),
+ $pBefore, $pNumCols, $pNumRows, $pSheet->getTitle()));
+ } else {
+ // Formula should not be adjusted
+ $pSheet->getCell($newCoordinates)->setValue($cell->getValue());
+ }
+
+ // Clear the original cell
+ $pSheet->getCellCacheController()->deleteCacheData($cellID);
+
+ } else {
+ /* We don't need to update styles for rows/columns before our insertion position,
+ but we do still need to adjust any formulae in those cells */
+ if ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA) {
+ // Formula should be adjusted
+ $cell->setValue($this->updateFormulaReferences($cell->getValue(),
+ $pBefore, $pNumCols, $pNumRows, $pSheet->getTitle()));
+ }
+
+ }
+ }
+
+ // Duplicate styles for the newly inserted cells
+ $highestColumn = $pSheet->getHighestColumn();
+ $highestRow = $pSheet->getHighestRow();
+
+ if ($pNumCols > 0 && $beforeColumnIndex - 2 > 0) {
+ for ($i = $beforeRow; $i <= $highestRow - 1; ++$i) {
+
+ // Style
+ $coordinate = PHPExcel_Cell::stringFromColumnIndex( $beforeColumnIndex - 2 ) . $i;
+ if ($pSheet->cellExists($coordinate)) {
+ $xfIndex = $pSheet->getCell($coordinate)->getXfIndex();
+ $conditionalStyles = $pSheet->conditionalStylesExists($coordinate) ?
+ $pSheet->getConditionalStyles($coordinate) : false;
+ for ($j = $beforeColumnIndex - 1; $j <= $beforeColumnIndex - 2 + $pNumCols; ++$j) {
+ $pSheet->getCellByColumnAndRow($j, $i)->setXfIndex($xfIndex);
+ if ($conditionalStyles) {
+ $cloned = array();
+ foreach ($conditionalStyles as $conditionalStyle) {
+ $cloned[] = clone $conditionalStyle;
+ }
+ $pSheet->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($j) . $i, $cloned);
+ }
+ }
+ }
+
+ }
+ }
+
+ if ($pNumRows > 0 && $beforeRow - 1 > 0) {
+ for ($i = $beforeColumnIndex - 1; $i <= PHPExcel_Cell::columnIndexFromString($highestColumn) - 1; ++$i) {
+
+ // Style
+ $coordinate = PHPExcel_Cell::stringFromColumnIndex($i) . ($beforeRow - 1);
+ if ($pSheet->cellExists($coordinate)) {
+ $xfIndex = $pSheet->getCell($coordinate)->getXfIndex();
+ $conditionalStyles = $pSheet->conditionalStylesExists($coordinate) ?
+ $pSheet->getConditionalStyles($coordinate) : false;
+ for ($j = $beforeRow; $j <= $beforeRow - 1 + $pNumRows; ++$j) {
+ $pSheet->getCell(PHPExcel_Cell::stringFromColumnIndex($i) . $j)->setXfIndex($xfIndex);
+ if ($conditionalStyles) {
+ $cloned = array();
+ foreach ($conditionalStyles as $conditionalStyle) {
+ $cloned[] = clone $conditionalStyle;
+ }
+ $pSheet->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($i) . $j, $cloned);
+ }
+ }
+ }
+ }
+ }
+
+ // Update worksheet: column dimensions
+ $this->_adjustColumnDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows);
+
+ // Update worksheet: row dimensions
+ $this->_adjustRowDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows);
+
+ // Update worksheet: page breaks
+ $this->_adjustPageBreaks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows);
+
+ // Update worksheet: comments
+ $this->_adjustComments($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows);
+
+ // Update worksheet: hyperlinks
+ $this->_adjustHyperlinks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows);
+
+ // Update worksheet: data validations
+ $this->_adjustDataValidations($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows);
+
+ // Update worksheet: merge cells
+ $this->_adjustMergeCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows);
+
+ // Update worksheet: protected cells
+ $this->_adjustProtectedCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows);
+
+ // Update worksheet: autofilter
+ $autoFilter = $pSheet->getAutoFilter();
+ $autoFilterRange = $autoFilter->getRange();
+ if (!empty($autoFilterRange)) {
+ if ($pNumCols != 0) {
+ $autoFilterColumns = array_keys($autoFilter->getColumns());
+ if (count($autoFilterColumns) > 0) {
+ sscanf($pBefore,'%[A-Z]%d', $column, $row);
+ $columnIndex = PHPExcel_Cell::columnIndexFromString($column);
+ list($rangeStart,$rangeEnd) = PHPExcel_Cell::rangeBoundaries($autoFilterRange);
+ if ($columnIndex <= $rangeEnd[0]) {
+ if ($pNumCols < 0) {
+ // If we're actually deleting any columns that fall within the autofilter range,
+ // then we delete any rules for those columns
+ $deleteColumn = $columnIndex + $pNumCols - 1;
+ $deleteCount = abs($pNumCols);
+ for ($i = 1; $i <= $deleteCount; ++$i) {
+ if (in_array(PHPExcel_Cell::stringFromColumnIndex($deleteColumn),$autoFilterColumns)) {
+ $autoFilter->clearColumn(PHPExcel_Cell::stringFromColumnIndex($deleteColumn));
+ }
+ ++$deleteColumn;
+ }
+ }
+ $startCol = ($columnIndex > $rangeStart[0]) ? $columnIndex : $rangeStart[0];
+
+ // Shuffle columns in autofilter range
+ if ($pNumCols > 0) {
+ // For insert, we shuffle from end to beginning to avoid overwriting
+ $startColID = PHPExcel_Cell::stringFromColumnIndex($startCol-1);
+ $toColID = PHPExcel_Cell::stringFromColumnIndex($startCol+$pNumCols-1);
+ $endColID = PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]);
+
+ $startColRef = $startCol;
+ $endColRef = $rangeEnd[0];
+ $toColRef = $rangeEnd[0]+$pNumCols;
+
+ do {
+ $autoFilter->shiftColumn(PHPExcel_Cell::stringFromColumnIndex($endColRef-1),PHPExcel_Cell::stringFromColumnIndex($toColRef-1));
+ --$endColRef;
+ --$toColRef;
+ } while ($startColRef <= $endColRef);
+ } else {
+ // For delete, we shuffle from beginning to end to avoid overwriting
+ $startColID = PHPExcel_Cell::stringFromColumnIndex($startCol-1);
+ $toColID = PHPExcel_Cell::stringFromColumnIndex($startCol+$pNumCols-1);
+ $endColID = PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]);
+ do {
+ $autoFilter->shiftColumn($startColID,$toColID);
+ ++$startColID;
+ ++$toColID;
+ } while ($startColID != $endColID);
+ }
+ }
+ }
+ }
+ $pSheet->setAutoFilter( $this->updateCellReference($autoFilterRange, $pBefore, $pNumCols, $pNumRows) );
+ }
+
+ // Update worksheet: freeze pane
+ if ($pSheet->getFreezePane() != '') {
+ $pSheet->freezePane( $this->updateCellReference($pSheet->getFreezePane(), $pBefore, $pNumCols, $pNumRows) );
+ }
+
+ // Page setup
+ if ($pSheet->getPageSetup()->isPrintAreaSet()) {
+ $pSheet->getPageSetup()->setPrintArea( $this->updateCellReference($pSheet->getPageSetup()->getPrintArea(), $pBefore, $pNumCols, $pNumRows) );
+ }
+
+ // Update worksheet: drawings
+ $aDrawings = $pSheet->getDrawingCollection();
+ foreach ($aDrawings as $objDrawing) {
+ $newReference = $this->updateCellReference($objDrawing->getCoordinates(), $pBefore, $pNumCols, $pNumRows);
+ if ($objDrawing->getCoordinates() != $newReference) {
+ $objDrawing->setCoordinates($newReference);
+ }
+ }
+
+ // Update workbook: named ranges
+ if (count($pSheet->getParent()->getNamedRanges()) > 0) {
+ foreach ($pSheet->getParent()->getNamedRanges() as $namedRange) {
+ if ($namedRange->getWorksheet()->getHashCode() == $pSheet->getHashCode()) {
+ $namedRange->setRange(
+ $this->updateCellReference($namedRange->getRange(), $pBefore, $pNumCols, $pNumRows)
+ );
+ }
+ }
+ }
+
+ // Garbage collect
+ $pSheet->garbageCollect();
+ }
+
+ /**
+ * Update references within formulas
+ *
+ * @param string $pFormula Formula to update
+ * @param int $pBefore Insert before this one
+ * @param int $pNumCols Number of columns to insert
+ * @param int $pNumRows Number of rows to insert
+ * @param string $sheetName Worksheet name/title
+ * @return string Updated formula
+ * @throws PHPExcel_Exception
+ */
+ public function updateFormulaReferences($pFormula = '', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, $sheetName = '') {
+ // Update cell references in the formula
+ $formulaBlocks = explode('"',$pFormula);
+ $i = false;
+ foreach($formulaBlocks as &$formulaBlock) {
+ // Ignore blocks that were enclosed in quotes (alternating entries in the $formulaBlocks array after the explode)
+ if ($i = !$i) {
+ $adjustCount = 0;
+ $newCellTokens = $cellTokens = array();
+ // Search for row ranges (e.g. 'Sheet1'!3:5 or 3:5) with or without $ absolutes (e.g. $3:5)
+ $matchCount = preg_match_all('/'.self::REFHELPER_REGEXP_ROWRANGE.'/i', ' '.$formulaBlock.' ', $matches, PREG_SET_ORDER);
+ if ($matchCount > 0) {
+ foreach($matches as $match) {
+ $fromString = ($match[2] > '') ? $match[2].'!' : '';
+ $fromString .= $match[3].':'.$match[4];
+ $modified3 = substr($this->updateCellReference('$A'.$match[3],$pBefore,$pNumCols,$pNumRows),2);
+ $modified4 = substr($this->updateCellReference('$A'.$match[4],$pBefore,$pNumCols,$pNumRows),2);
+
+ if ($match[3].':'.$match[4] !== $modified3.':'.$modified4) {
+ if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) {
+ $toString = ($match[2] > '') ? $match[2].'!' : '';
+ $toString .= $modified3.':'.$modified4;
+ // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
+ $column = 100000;
+ $row = 10000000+trim($match[3],'$');
+ $cellIndex = $column.$row;
+
+ $newCellTokens[$cellIndex] = preg_quote($toString);
+ $cellTokens[$cellIndex] = '/(? 0) {
+ foreach($matches as $match) {
+ $fromString = ($match[2] > '') ? $match[2].'!' : '';
+ $fromString .= $match[3].':'.$match[4];
+ $modified3 = substr($this->updateCellReference($match[3].'$1',$pBefore,$pNumCols,$pNumRows),0,-2);
+ $modified4 = substr($this->updateCellReference($match[4].'$1',$pBefore,$pNumCols,$pNumRows),0,-2);
+
+ if ($match[3].':'.$match[4] !== $modified3.':'.$modified4) {
+ if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) {
+ $toString = ($match[2] > '') ? $match[2].'!' : '';
+ $toString .= $modified3.':'.$modified4;
+ // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
+ $column = PHPExcel_Cell::columnIndexFromString(trim($match[3],'$')) + 100000;
+ $row = 10000000;
+ $cellIndex = $column.$row;
+
+ $newCellTokens[$cellIndex] = preg_quote($toString);
+ $cellTokens[$cellIndex] = '/(? 0) {
+ foreach($matches as $match) {
+ $fromString = ($match[2] > '') ? $match[2].'!' : '';
+ $fromString .= $match[3].':'.$match[4];
+ $modified3 = $this->updateCellReference($match[3],$pBefore,$pNumCols,$pNumRows);
+ $modified4 = $this->updateCellReference($match[4],$pBefore,$pNumCols,$pNumRows);
+
+ if ($match[3].$match[4] !== $modified3.$modified4) {
+ if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) {
+ $toString = ($match[2] > '') ? $match[2].'!' : '';
+ $toString .= $modified3.':'.$modified4;
+ list($column,$row) = PHPExcel_Cell::coordinateFromString($match[3]);
+ // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
+ $column = PHPExcel_Cell::columnIndexFromString(trim($column,'$')) + 100000;
+ $row = trim($row,'$') + 10000000;
+ $cellIndex = $column.$row;
+
+ $newCellTokens[$cellIndex] = preg_quote($toString);
+ $cellTokens[$cellIndex] = '/(? 0) {
+ foreach($matches as $match) {
+ $fromString = ($match[2] > '') ? $match[2].'!' : '';
+ $fromString .= $match[3];
+ $modified3 = $this->updateCellReference($match[3],$pBefore,$pNumCols,$pNumRows);
+
+ if ($match[3] !== $modified3) {
+ if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) {
+ $toString = ($match[2] > '') ? $match[2].'!' : '';
+ $toString .= $modified3;
+ list($column,$row) = PHPExcel_Cell::coordinateFromString($match[3]);
+ // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
+ $column = PHPExcel_Cell::columnIndexFromString(trim($column,'$')) + 100000;
+ $row = trim($row,'$') + 10000000;
+ $cellIndex = $column.$row;
+
+ $newCellTokens[$cellIndex] = preg_quote($toString);
+ $cellTokens[$cellIndex] = '/(? 0) {
+ if ($pNumCols > 0) {
+ krsort($cellTokens);
+ krsort($newCellTokens);
+ } else {
+ ksort($cellTokens);
+ ksort($newCellTokens);
+ }
+ // Update cell references in the formula
+ $formulaBlock = str_replace('\\','',preg_replace($cellTokens,$newCellTokens,$formulaBlock));
+ }
+ }
+ }
+ unset($formulaBlock);
+
+ // Then rebuild the formula string
+ return implode('"',$formulaBlocks);
+ }
+
+ /**
+ * Update cell reference
+ *
+ * @param string $pCellRange Cell range
+ * @param int $pBefore Insert before this one
+ * @param int $pNumCols Number of columns to increment
+ * @param int $pNumRows Number of rows to increment
+ * @return string Updated cell range
+ * @throws PHPExcel_Exception
+ */
+ public function updateCellReference($pCellRange = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) {
+ // Is it in another worksheet? Will not have to update anything.
+ if (strpos($pCellRange, "!") !== false) {
+ return $pCellRange;
+ // Is it a range or a single cell?
+ } elseif (strpos($pCellRange, ':') === false && strpos($pCellRange, ',') === false) {
+ // Single cell
+ return $this->_updateSingleCellReference($pCellRange, $pBefore, $pNumCols, $pNumRows);
+ } elseif (strpos($pCellRange, ':') !== false || strpos($pCellRange, ',') !== false) {
+ // Range
+ return $this->_updateCellRange($pCellRange, $pBefore, $pNumCols, $pNumRows);
+ } else {
+ // Return original
+ return $pCellRange;
+ }
+ }
+
+ /**
+ * Update named formulas (i.e. containing worksheet references / named ranges)
+ *
+ * @param PHPExcel $pPhpExcel Object to update
+ * @param string $oldName Old name (name to replace)
+ * @param string $newName New name
+ */
+ public function updateNamedFormulas(PHPExcel $pPhpExcel, $oldName = '', $newName = '') {
+ if ($oldName == '') {
+ return;
+ }
+
+ foreach ($pPhpExcel->getWorksheetIterator() as $sheet) {
+ foreach ($sheet->getCellCollection(false) as $cellID) {
+ $cell = $sheet->getCell($cellID);
+ if (($cell !== NULL) && ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA)) {
+ $formula = $cell->getValue();
+ if (strpos($formula, $oldName) !== false) {
+ $formula = str_replace("'" . $oldName . "'!", "'" . $newName . "'!", $formula);
+ $formula = str_replace($oldName . "!", $newName . "!", $formula);
+ $cell->setValueExplicit($formula, PHPExcel_Cell_DataType::TYPE_FORMULA);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Update cell range
+ *
+ * @param string $pCellRange Cell range (e.g. 'B2:D4', 'B:C' or '2:3')
+ * @param int $pBefore Insert before this one
+ * @param int $pNumCols Number of columns to increment
+ * @param int $pNumRows Number of rows to increment
+ * @return string Updated cell range
+ * @throws PHPExcel_Exception
+ */
+ private function _updateCellRange($pCellRange = 'A1:A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) {
+ if (strpos($pCellRange,':') !== false || strpos($pCellRange, ',') !== false) {
+ // Update range
+ $range = PHPExcel_Cell::splitRange($pCellRange);
+ $ic = count($range);
+ for ($i = 0; $i < $ic; ++$i) {
+ $jc = count($range[$i]);
+ for ($j = 0; $j < $jc; ++$j) {
+ if (ctype_alpha($range[$i][$j])) {
+ $r = PHPExcel_Cell::coordinateFromString($this->_updateSingleCellReference($range[$i][$j].'1', $pBefore, $pNumCols, $pNumRows));
+ $range[$i][$j] = $r[0];
+ } elseif(ctype_digit($range[$i][$j])) {
+ $r = PHPExcel_Cell::coordinateFromString($this->_updateSingleCellReference('A'.$range[$i][$j], $pBefore, $pNumCols, $pNumRows));
+ $range[$i][$j] = $r[1];
+ } else {
+ $range[$i][$j] = $this->_updateSingleCellReference($range[$i][$j], $pBefore, $pNumCols, $pNumRows);
+ }
+ }
+ }
+
+ // Recreate range string
+ return PHPExcel_Cell::buildRange($range);
+ } else {
+ throw new PHPExcel_Exception("Only cell ranges may be passed to this method.");
+ }
+ }
+
+ /**
+ * Update single cell reference
+ *
+ * @param string $pCellReference Single cell reference
+ * @param int $pBefore Insert before this one
+ * @param int $pNumCols Number of columns to increment
+ * @param int $pNumRows Number of rows to increment
+ * @return string Updated cell reference
+ * @throws PHPExcel_Exception
+ */
+ private function _updateSingleCellReference($pCellReference = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) {
+ if (strpos($pCellReference, ':') === false && strpos($pCellReference, ',') === false) {
+ // Get coordinates of $pBefore
+ list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString( $pBefore );
+
+ // Get coordinates of $pCellReference
+ list($newColumn, $newRow) = PHPExcel_Cell::coordinateFromString( $pCellReference );
+
+ // Verify which parts should be updated
+ $updateColumn = (($newColumn{0} != '$') && ($beforeColumn{0} != '$') &&
+ PHPExcel_Cell::columnIndexFromString($newColumn) >= PHPExcel_Cell::columnIndexFromString($beforeColumn));
+
+ $updateRow = (($newRow{0} != '$') && ($beforeRow{0} != '$') &&
+ $newRow >= $beforeRow);
+
+ // Create new column reference
+ if ($updateColumn) {
+ $newColumn = PHPExcel_Cell::stringFromColumnIndex( PHPExcel_Cell::columnIndexFromString($newColumn) - 1 + $pNumCols );
+ }
+
+ // Create new row reference
+ if ($updateRow) {
+ $newRow = $newRow + $pNumRows;
+ }
+
+ // Return new reference
+ return $newColumn . $newRow;
+ } else {
+ throw new PHPExcel_Exception("Only single cell references may be passed to this method.");
+ }
+ }
+
+ /**
+ * __clone implementation. Cloning should not be allowed in a Singleton!
+ *
+ * @throws PHPExcel_Exception
+ */
+ public final function __clone() {
+ throw new PHPExcel_Exception("Cloning a Singleton is not allowed!");
+ }
+}
diff --git a/framework/library/phpexcel/PHPExcel/Style/NumberFormat.php b/framework/library/phpexcel/PHPExcel/Style/NumberFormat.php
new file mode 100644
index 0000000..a381f4f
--- /dev/null
+++ b/framework/library/phpexcel/PHPExcel/Style/NumberFormat.php
@@ -0,0 +1,708 @@
+_formatCode = NULL;
+ }
+ }
+
+ /**
+ * Get the shared style component for the currently active cell in currently active sheet.
+ * Only used for style supervisor
+ *
+ * @return PHPExcel_Style_NumberFormat
+ */
+ public function getSharedComponent()
+ {
+ return $this->_parent->getSharedComponent()->getNumberFormat();
+ }
+
+ /**
+ * Build style array from subcomponents
+ *
+ * @param array $array
+ * @return array
+ */
+ public function getStyleArray($array)
+ {
+ return array('numberformat' => $array);
+ }
+
+ /**
+ * Apply styles from array
+ *
+ * "+r+"
+ * $objPHPExcel->getActiveSheet()->getStyle('B2')->getNumberFormat()->applyFromArray(
+ * array(
+ * 'code' => PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_EUR_SIMPLE
+ * )
+ * );
+ *
+ *
+ * @param array $pStyles Array containing style information
+ * @throws PHPExcel_Exception
+ * @return PHPExcel_Style_NumberFormat
+ */
+ public function applyFromArray($pStyles = null)
+ {
+ if (is_array($pStyles)) {
+ if ($this->_isSupervisor) {
+ $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles));
+ } else {
+ if (array_key_exists('code', $pStyles)) {
+ $this->setFormatCode($pStyles['code']);
+ }
+ }
+ } else {
+ throw new PHPExcel_Exception("Invalid style array passed.");
+ }
+ return $this;
+ }
+
+ /**
+ * Get Format Code
+ *
+ * @return string
+ */
+ public function getFormatCode()
+ {
+ if ($this->_isSupervisor) {
+ return $this->getSharedComponent()->getFormatCode();
+ }
+ if ($this->_builtInFormatCode !== false)
+ {
+ return self::builtInFormatCode($this->_builtInFormatCode);
+ }
+ return $this->_formatCode;
+ }
+
+ /**
+ * Set Format Code
+ *
+ * @param string $pValue
+ * @return PHPExcel_Style_NumberFormat
+ */
+ public function setFormatCode($pValue = PHPExcel_Style_NumberFormat::FORMAT_GENERAL)
+ {
+ if ($pValue == '') {
+ $pValue = PHPExcel_Style_NumberFormat::FORMAT_GENERAL;
+ }
+ if ($this->_isSupervisor) {
+ $styleArray = $this->getStyleArray(array('code' => $pValue));
+ $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
+ } else {
+ $this->_formatCode = $pValue;
+ $this->_builtInFormatCode = self::builtInFormatCodeIndex($pValue);
+ }
+ return $this;
+ }
+
+ /**
+ * Get Built-In Format Code
+ *
+ * @return int
+ */
+ public function getBuiltInFormatCode()
+ {
+ if ($this->_isSupervisor) {
+ return $this->getSharedComponent()->getBuiltInFormatCode();
+ }
+ return $this->_builtInFormatCode;
+ }
+
+ /**
+ * Set Built-In Format Code
+ *
+ * @param int $pValue
+ * @return PHPExcel_Style_NumberFormat
+ */
+ public function setBuiltInFormatCode($pValue = 0)
+ {
+
+ if ($this->_isSupervisor) {
+ $styleArray = $this->getStyleArray(array('code' => self::builtInFormatCode($pValue)));
+ $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
+ } else {
+ $this->_builtInFormatCode = $pValue;
+ $this->_formatCode = self::builtInFormatCode($pValue);
+ }
+ return $this;
+ }
+
+ /**
+ * Fill built-in format codes
+ */
+ private static function fillBuiltInFormatCodes()
+ {
+ // Built-in format codes
+ if (is_null(self::$_builtInFormats)) {
+ self::$_builtInFormats = array();
+
+ // General
+ self::$_builtInFormats[0] = PHPExcel_Style_NumberFormat::FORMAT_GENERAL;
+ self::$_builtInFormats[1] = '0';
+ self::$_builtInFormats[2] = '0.00';
+ self::$_builtInFormats[3] = '#,##0';
+ self::$_builtInFormats[4] = '#,##0.00';
+
+ self::$_builtInFormats[9] = '0%';
+ self::$_builtInFormats[10] = '0.00%';
+ self::$_builtInFormats[11] = '0.00E+00';
+ self::$_builtInFormats[12] = '# ?/?';
+ self::$_builtInFormats[13] = '# ??/??';
+ self::$_builtInFormats[14] = 'mm-dd-yy';
+ self::$_builtInFormats[15] = 'd-mmm-yy';
+ self::$_builtInFormats[16] = 'd-mmm';
+ self::$_builtInFormats[17] = 'mmm-yy';
+ self::$_builtInFormats[18] = 'h:mm AM/PM';
+ self::$_builtInFormats[19] = 'h:mm:ss AM/PM';
+ self::$_builtInFormats[20] = 'h:mm';
+ self::$_builtInFormats[21] = 'h:mm:ss';
+ self::$_builtInFormats[22] = 'm/d/yy h:mm';
+
+ self::$_builtInFormats[37] = '#,##0 ;(#,##0)';
+ self::$_builtInFormats[38] = '#,##0 ;[Red](#,##0)';
+ self::$_builtInFormats[39] = '#,##0.00;(#,##0.00)';
+ self::$_builtInFormats[40] = '#,##0.00;[Red](#,##0.00)';
+
+ self::$_builtInFormats[44] = '_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)';
+ self::$_builtInFormats[45] = 'mm:ss';
+ self::$_builtInFormats[46] = '[h]:mm:ss';
+ self::$_builtInFormats[47] = 'mmss.0';
+ self::$_builtInFormats[48] = '##0.0E+0';
+ self::$_builtInFormats[49] = '@';
+
+ // CHT
+ self::$_builtInFormats[27] = '[$-404]e/m/d';
+ self::$_builtInFormats[30] = 'm/d/yy';
+ self::$_builtInFormats[36] = '[$-404]e/m/d';
+ self::$_builtInFormats[50] = '[$-404]e/m/d';
+ self::$_builtInFormats[57] = '[$-404]e/m/d';
+
+ // THA
+ self::$_builtInFormats[59] = 't0';
+ self::$_builtInFormats[60] = 't0.00';
+ self::$_builtInFormats[61] = 't#,##0';
+ self::$_builtInFormats[62] = 't#,##0.00';
+ self::$_builtInFormats[67] = 't0%';
+ self::$_builtInFormats[68] = 't0.00%';
+ self::$_builtInFormats[69] = 't# ?/?';
+ self::$_builtInFormats[70] = 't# ??/??';
+
+ // Flip array (for faster lookups)
+ self::$_flippedBuiltInFormats = array_flip(self::$_builtInFormats);
+ }
+ }
+
+ /**
+ * Get built-in format code
+ *
+ * @param int $pIndex
+ * @return string
+ */
+ public static function builtInFormatCode($pIndex)
+ {
+ // Clean parameter
+ $pIndex = intval($pIndex);
+
+ // Ensure built-in format codes are available
+ self::fillBuiltInFormatCodes();
+
+ // Lookup format code
+ if (isset(self::$_builtInFormats[$pIndex])) {
+ return self::$_builtInFormats[$pIndex];
+ }
+
+ return '';
+ }
+
+ /**
+ * Get built-in format code index
+ *
+ * @param string $formatCode
+ * @return int|boolean
+ */
+ public static function builtInFormatCodeIndex($formatCode)
+ {
+ // Ensure built-in format codes are available
+ self::fillBuiltInFormatCodes();
+
+ // Lookup format code
+ if (isset(self::$_flippedBuiltInFormats[$formatCode])) {
+ return self::$_flippedBuiltInFormats[$formatCode];
+ }
+
+ return false;
+ }
+
+ /**
+ * Get hash code
+ *
+ * @return string Hash code
+ */
+ public function getHashCode()
+ {
+ if ($this->_isSupervisor) {
+ return $this->getSharedComponent()->getHashCode();
+ }
+ return md5(
+ $this->_formatCode
+ . $this->_builtInFormatCode
+ . __CLASS__
+ );
+ }
+
+ /**
+ * Search/replace values to convert Excel date/time format masks to PHP format masks
+ *
+ * @var array
+ */
+ private static $_dateFormatReplacements = array(
+ // first remove escapes related to non-format characters
+ '\\' => '',
+ // 12-hour suffix
+ 'am/pm' => 'A',
+ // 4-digit year
+ 'e' => 'Y',
+ 'yyyy' => 'Y',
+ // 2-digit year
+ 'yy' => 'y',
+ // first letter of month - no php equivalent
+ 'mmmmm' => 'M',
+ // full month name
+ 'mmmm' => 'F',
+ // short month name
+ 'mmm' => 'M',
+ // mm is minutes if time, but can also be month w/leading zero
+ // so we try to identify times be the inclusion of a : separator in the mask
+ // It isn't perfect, but the best way I know how
+ ':mm' => ':i',
+ 'mm:' => 'i:',
+ // month leading zero
+ 'mm' => 'm',
+ // month no leading zero
+ 'm' => 'n',
+ // full day of week name
+ 'dddd' => 'l',
+ // short day of week name
+ 'ddd' => 'D',
+ // days leading zero
+ 'dd' => 'd',
+ // days no leading zero
+ 'd' => 'j',
+ // seconds
+ 'ss' => 's',
+ // fractional seconds - no php equivalent
+ '.s' => ''
+ );
+ /**
+ * Search/replace values to convert Excel date/time format masks hours to PHP format masks (24 hr clock)
+ *
+ * @var array
+ */
+ private static $_dateFormatReplacements24 = array(
+ 'hh' => 'H',
+ 'h' => 'G'
+ );
+ /**
+ * Search/replace values to convert Excel date/time format masks hours to PHP format masks (12 hr clock)
+ *
+ * @var array
+ */
+ private static $_dateFormatReplacements12 = array(
+ 'hh' => 'h',
+ 'h' => 'g'
+ );
+
+ private static function _formatAsDate(&$value, &$format)
+ {
+ // dvc: convert Excel formats to PHP date formats
+
+ // strip off first part containing e.g. [$-F800] or [$USD-409]
+ // general syntax: [$
';
+ if ($value != (int)$value) {
+ self::_formatAsFraction($value, $format);
+ }
+
+ } else {
+ // Handle the number itself
+
+ // scale number
+ $value = $value / $scale;
+
+ // Strip #
+ $format = preg_replace('/\\#/', '0', $format);
+
+ $n = "/\[[^\]]+\]/";
+ $m = preg_replace($n, '', $format);
+ $number_regex = "/(0+)(\.?)(0*)/";
+ if (preg_match($number_regex, $m, $matches)) {
+ $left = $matches[1];
+ $dec = $matches[2];
+ $right = $matches[3];
+
+ // minimun width of formatted number (including dot)
+ $minWidth = strlen($left) + strlen($dec) + strlen($right);
+ if ($useThousands) {
+ $value = number_format(
+ $value
+ , strlen($right)
+ , PHPExcel_Shared_String::getDecimalSeparator()
+ , PHPExcel_Shared_String::getThousandsSeparator()
+ );
+ $value = preg_replace($number_regex, $value, $format);
+ } else {
+ if (preg_match('/0([^\d\.]+)0/', $format, $matches)) {
+ $value = self::_complexNumberFormatMask($value, $format);
+ } else {
+ $sprintf_pattern = "%0$minWidth." . strlen($right) . "f";
+ $value = sprintf($sprintf_pattern, $value);
+ $value = preg_replace($number_regex, $value, $format);
+ }
+ }
+ }
+ }
+ if (preg_match('/\[\$(.*)\]/u', $format, $m)) {
+ // Currency or Accounting
+ $currencyFormat = $m[0];
+ $currencyCode = $m[1];
+ list($currencyCode) = explode('-',$currencyCode);
+ if ($currencyCode == '') {
+ $currencyCode = PHPExcel_Shared_String::getCurrencyCode();
+ }
+ $value = preg_replace('/\[\$([^\]]*)\]/u',$currencyCode,$value);
+ }
+ }
+ }
+
+ // Additional formatting provided by callback function
+ if ($callBack !== null) {
+ list($writerInstance, $function) = $callBack;
+ $value = $writerInstance->$function($value, $formatColor);
+ }
+
+ return $value;
+ }
+
+}
diff --git a/framework/library/phpexcel/PHPExcel/Style/Protection.php b/framework/library/phpexcel/PHPExcel/Style/Protection.php
new file mode 100644
index 0000000..a8f65ce
--- /dev/null
+++ b/framework/library/phpexcel/PHPExcel/Style/Protection.php
@@ -0,0 +1,207 @@
+_locked = self::PROTECTION_INHERIT;
+ $this->_hidden = self::PROTECTION_INHERIT;
+ }
+ }
+
+ /**
+ * Get the shared style component for the currently active cell in currently active sheet.
+ * Only used for style supervisor
+ *
+ * @return PHPExcel_Style_Protection
+ */
+ public function getSharedComponent()
+ {
+ return $this->_parent->getSharedComponent()->getProtection();
+ }
+
+ /**
+ * Build style array from subcomponents
+ *
+ * @param array $array
+ * @return array
+ */
+ public function getStyleArray($array)
+ {
+ return array('protection' => $array);
+ }
+
+ /**
+ * Apply styles from array
+ *
+ *
+ * $objPHPExcel->getActiveSheet()->getStyle('B2')->getLocked()->applyFromArray(
+ * array(
+ * 'locked' => TRUE,
+ * 'hidden' => FALSE
+ * )
+ * );
+ *
+ *
+ * @param array $pStyles Array containing style information
+ * @throws PHPExcel_Exception
+ * @return PHPExcel_Style_Protection
+ */
+ public function applyFromArray($pStyles = NULL) {
+ if (is_array($pStyles)) {
+ if ($this->_isSupervisor) {
+ $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles));
+ } else {
+ if (isset($pStyles['locked'])) {
+ $this->setLocked($pStyles['locked']);
+ }
+ if (isset($pStyles['hidden'])) {
+ $this->setHidden($pStyles['hidden']);
+ }
+ }
+ } else {
+ throw new PHPExcel_Exception("Invalid style array passed.");
+ }
+ return $this;
+ }
+
+ /**
+ * Get locked
+ *
+ * @return string
+ */
+ public function getLocked() {
+ if ($this->_isSupervisor) {
+ return $this->getSharedComponent()->getLocked();
+ }
+ return $this->_locked;
+ }
+
+ /**
+ * Set locked
+ *
+ * @param string $pValue
+ * @return PHPExcel_Style_Protection
+ */
+ public function setLocked($pValue = self::PROTECTION_INHERIT) {
+ if ($this->_isSupervisor) {
+ $styleArray = $this->getStyleArray(array('locked' => $pValue));
+ $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
+ } else {
+ $this->_locked = $pValue;
+ }
+ return $this;
+ }
+
+ /**
+ * Get hidden
+ *
+ * @return string
+ */
+ public function getHidden() {
+ if ($this->_isSupervisor) {
+ return $this->getSharedComponent()->getHidden();
+ }
+ return $this->_hidden;
+ }
+
+ /**
+ * Set hidden
+ *
+ * @param string $pValue
+ * @return PHPExcel_Style_Protection
+ */
+ public function setHidden($pValue = self::PROTECTION_INHERIT) {
+ if ($this->_isSupervisor) {
+ $styleArray = $this->getStyleArray(array('hidden' => $pValue));
+ $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
+ } else {
+ $this->_hidden = $pValue;
+ }
+ return $this;
+ }
+
+ /**
+ * Get hash code
+ *
+ * @return string Hash code
+ */
+ public function getHashCode() {
+ if ($this->_isSupervisor) {
+ return $this->getSharedComponent()->getHashCode();
+ }
+ return md5(
+ $this->_locked
+ . $this->_hidden
+ . __CLASS__
+ );
+ }
+
+}
diff --git a/framework/library/phpexcel/PHPExcel/Worksheet/PageMargins.php b/framework/library/phpexcel/PHPExcel/Worksheet/PageMargins.php
new file mode 100644
index 0000000..339815d
--- /dev/null
+++ b/framework/library/phpexcel/PHPExcel/Worksheet/PageMargins.php
@@ -0,0 +1,220 @@
+_left;
+ }
+
+ /**
+ * Set Left
+ *
+ * @param double $pValue
+ * @return PHPExcel_Worksheet_PageMargins
+ */
+ public function setLeft($pValue) {
+ $this->_left = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get Right
+ *
+ * @return double
+ */
+ public function getRight() {
+ return $this->_right;
+ }
+
+ /**
+ * Set Right
+ *
+ * @param double $pValue
+ * @return PHPExcel_Worksheet_PageMargins
+ */
+ public function setRight($pValue) {
+ $this->_right = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get Top
+ *
+ * @return double
+ */
+ public function getTop() {
+ return $this->_top;
+ }
+
+ /**
+ * Set Top
+ *
+ * @param double $pValue
+ * @return PHPExcel_Worksheet_PageMargins
+ */
+ public function setTop($pValue) {
+ $this->_top = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get Bottom
+ *
+ * @return double
+ */
+ public function getBottom() {
+ return $this->_bottom;
+ }
+
+ /**
+ * Set Bottom
+ *
+ * @param double $pValue
+ * @return PHPExcel_Worksheet_PageMargins
+ */
+ public function setBottom($pValue) {
+ $this->_bottom = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get Header
+ *
+ * @return double
+ */
+ public function getHeader() {
+ return $this->_header;
+ }
+
+ /**
+ * Set Header
+ *
+ * @param double $pValue
+ * @return PHPExcel_Worksheet_PageMargins
+ */
+ public function setHeader($pValue) {
+ $this->_header = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get Footer
+ *
+ * @return double
+ */
+ public function getFooter() {
+ return $this->_footer;
+ }
+
+ /**
+ * Set Footer
+ *
+ * @param double $pValue
+ * @return PHPExcel_Worksheet_PageMargins
+ */
+ public function setFooter($pValue) {
+ $this->_footer = $pValue;
+ return $this;
+ }
+
+ /**
+ * Implement PHP __clone to create a deep clone, not just a shallow copy.
+ */
+ public function __clone() {
+ $vars = get_object_vars($this);
+ foreach ($vars as $key => $value) {
+ if (is_object($value)) {
+ $this->$key = clone $value;
+ } else {
+ $this->$key = $value;
+ }
+ }
+ }
+}
diff --git a/framework/library/phpexcel/PHPExcel/Worksheet/PageSetup.php b/framework/library/phpexcel/PHPExcel/Worksheet/PageSetup.php
new file mode 100644
index 0000000..1508eea
--- /dev/null
+++ b/framework/library/phpexcel/PHPExcel/Worksheet/PageSetup.php
@@ -0,0 +1,798 @@
+
+ * Paper size taken from Office Open XML Part 4 - Markup Language Reference, page 1988:
+ *
+ * 1 = Letter paper (8.5 in. by 11 in.)
+ * 2 = Letter small paper (8.5 in. by 11 in.)
+ * 3 = Tabloid paper (11 in. by 17 in.)
+ * 4 = Ledger paper (17 in. by 11 in.)
+ * 5 = Legal paper (8.5 in. by 14 in.)
+ * 6 = Statement paper (5.5 in. by 8.5 in.)
+ * 7 = Executive paper (7.25 in. by 10.5 in.)
+ * 8 = A3 paper (297 mm by 420 mm)
+ * 9 = A4 paper (210 mm by 297 mm)
+ * 10 = A4 small paper (210 mm by 297 mm)
+ * 11 = A5 paper (148 mm by 210 mm)
+ * 12 = B4 paper (250 mm by 353 mm)
+ * 13 = B5 paper (176 mm by 250 mm)
+ * 14 = Folio paper (8.5 in. by 13 in.)
+ * 15 = Quarto paper (215 mm by 275 mm)
+ * 16 = Standard paper (10 in. by 14 in.)
+ * 17 = Standard paper (11 in. by 17 in.)
+ * 18 = Note paper (8.5 in. by 11 in.)
+ * 19 = #9 envelope (3.875 in. by 8.875 in.)
+ * 20 = #10 envelope (4.125 in. by 9.5 in.)
+ * 21 = #11 envelope (4.5 in. by 10.375 in.)
+ * 22 = #12 envelope (4.75 in. by 11 in.)
+ * 23 = #14 envelope (5 in. by 11.5 in.)
+ * 24 = C paper (17 in. by 22 in.)
+ * 25 = D paper (22 in. by 34 in.)
+ * 26 = E paper (34 in. by 44 in.)
+ * 27 = DL envelope (110 mm by 220 mm)
+ * 28 = C5 envelope (162 mm by 229 mm)
+ * 29 = C3 envelope (324 mm by 458 mm)
+ * 30 = C4 envelope (229 mm by 324 mm)
+ * 31 = C6 envelope (114 mm by 162 mm)
+ * 32 = C65 envelope (114 mm by 229 mm)
+ * 33 = B4 envelope (250 mm by 353 mm)
+ * 34 = B5 envelope (176 mm by 250 mm)
+ * 35 = B6 envelope (176 mm by 125 mm)
+ * 36 = Italy envelope (110 mm by 230 mm)
+ * 37 = Monarch envelope (3.875 in. by 7.5 in.).
+ * 38 = 6 3/4 envelope (3.625 in. by 6.5 in.)
+ * 39 = US standard fanfold (14.875 in. by 11 in.)
+ * 40 = German standard fanfold (8.5 in. by 12 in.)
+ * 41 = German legal fanfold (8.5 in. by 13 in.)
+ * 42 = ISO B4 (250 mm by 353 mm)
+ * 43 = Japanese double postcard (200 mm by 148 mm)
+ * 44 = Standard paper (9 in. by 11 in.)
+ * 45 = Standard paper (10 in. by 11 in.)
+ * 46 = Standard paper (15 in. by 11 in.)
+ * 47 = Invite envelope (220 mm by 220 mm)
+ * 50 = Letter extra paper (9.275 in. by 12 in.)
+ * 51 = Legal extra paper (9.275 in. by 15 in.)
+ * 52 = Tabloid extra paper (11.69 in. by 18 in.)
+ * 53 = A4 extra paper (236 mm by 322 mm)
+ * 54 = Letter transverse paper (8.275 in. by 11 in.)
+ * 55 = A4 transverse paper (210 mm by 297 mm)
+ * 56 = Letter extra transverse paper (9.275 in. by 12 in.)
+ * 57 = SuperA/SuperA/A4 paper (227 mm by 356 mm)
+ * 58 = SuperB/SuperB/A3 paper (305 mm by 487 mm)
+ * 59 = Letter plus paper (8.5 in. by 12.69 in.)
+ * 60 = A4 plus paper (210 mm by 330 mm)
+ * 61 = A5 transverse paper (148 mm by 210 mm)
+ * 62 = JIS B5 transverse paper (182 mm by 257 mm)
+ * 63 = A3 extra paper (322 mm by 445 mm)
+ * 64 = A5 extra paper (174 mm by 235 mm)
+ * 65 = ISO B5 extra paper (201 mm by 276 mm)
+ * 66 = A2 paper (420 mm by 594 mm)
+ * 67 = A3 transverse paper (297 mm by 420 mm)
+ * 68 = A3 extra transverse paper (322 mm by 445 mm)
+ *
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Worksheet
+ * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel)
+ */
+class PHPExcel_Worksheet_PageSetup
+{
+ /* Paper size */
+ const PAPERSIZE_LETTER = 1;
+ const PAPERSIZE_LETTER_SMALL = 2;
+ const PAPERSIZE_TABLOID = 3;
+ const PAPERSIZE_LEDGER = 4;
+ const PAPERSIZE_LEGAL = 5;
+ const PAPERSIZE_STATEMENT = 6;
+ const PAPERSIZE_EXECUTIVE = 7;
+ const PAPERSIZE_A3 = 8;
+ const PAPERSIZE_A4 = 9;
+ const PAPERSIZE_A4_SMALL = 10;
+ const PAPERSIZE_A5 = 11;
+ const PAPERSIZE_B4 = 12;
+ const PAPERSIZE_B5 = 13;
+ const PAPERSIZE_FOLIO = 14;
+ const PAPERSIZE_QUARTO = 15;
+ const PAPERSIZE_STANDARD_1 = 16;
+ const PAPERSIZE_STANDARD_2 = 17;
+ const PAPERSIZE_NOTE = 18;
+ const PAPERSIZE_NO9_ENVELOPE = 19;
+ const PAPERSIZE_NO10_ENVELOPE = 20;
+ const PAPERSIZE_NO11_ENVELOPE = 21;
+ const PAPERSIZE_NO12_ENVELOPE = 22;
+ const PAPERSIZE_NO14_ENVELOPE = 23;
+ const PAPERSIZE_C = 24;
+ const PAPERSIZE_D = 25;
+ const PAPERSIZE_E = 26;
+ const PAPERSIZE_DL_ENVELOPE = 27;
+ const PAPERSIZE_C5_ENVELOPE = 28;
+ const PAPERSIZE_C3_ENVELOPE = 29;
+ const PAPERSIZE_C4_ENVELOPE = 30;
+ const PAPERSIZE_C6_ENVELOPE = 31;
+ const PAPERSIZE_C65_ENVELOPE = 32;
+ const PAPERSIZE_B4_ENVELOPE = 33;
+ const PAPERSIZE_B5_ENVELOPE = 34;
+ const PAPERSIZE_B6_ENVELOPE = 35;
+ const PAPERSIZE_ITALY_ENVELOPE = 36;
+ const PAPERSIZE_MONARCH_ENVELOPE = 37;
+ const PAPERSIZE_6_3_4_ENVELOPE = 38;
+ const PAPERSIZE_US_STANDARD_FANFOLD = 39;
+ const PAPERSIZE_GERMAN_STANDARD_FANFOLD = 40;
+ const PAPERSIZE_GERMAN_LEGAL_FANFOLD = 41;
+ const PAPERSIZE_ISO_B4 = 42;
+ const PAPERSIZE_JAPANESE_DOUBLE_POSTCARD = 43;
+ const PAPERSIZE_STANDARD_PAPER_1 = 44;
+ const PAPERSIZE_STANDARD_PAPER_2 = 45;
+ const PAPERSIZE_STANDARD_PAPER_3 = 46;
+ const PAPERSIZE_INVITE_ENVELOPE = 47;
+ const PAPERSIZE_LETTER_EXTRA_PAPER = 48;
+ const PAPERSIZE_LEGAL_EXTRA_PAPER = 49;
+ const PAPERSIZE_TABLOID_EXTRA_PAPER = 50;
+ const PAPERSIZE_A4_EXTRA_PAPER = 51;
+ const PAPERSIZE_LETTER_TRANSVERSE_PAPER = 52;
+ const PAPERSIZE_A4_TRANSVERSE_PAPER = 53;
+ const PAPERSIZE_LETTER_EXTRA_TRANSVERSE_PAPER = 54;
+ const PAPERSIZE_SUPERA_SUPERA_A4_PAPER = 55;
+ const PAPERSIZE_SUPERB_SUPERB_A3_PAPER = 56;
+ const PAPERSIZE_LETTER_PLUS_PAPER = 57;
+ const PAPERSIZE_A4_PLUS_PAPER = 58;
+ const PAPERSIZE_A5_TRANSVERSE_PAPER = 59;
+ const PAPERSIZE_JIS_B5_TRANSVERSE_PAPER = 60;
+ const PAPERSIZE_A3_EXTRA_PAPER = 61;
+ const PAPERSIZE_A5_EXTRA_PAPER = 62;
+ const PAPERSIZE_ISO_B5_EXTRA_PAPER = 63;
+ const PAPERSIZE_A2_PAPER = 64;
+ const PAPERSIZE_A3_TRANSVERSE_PAPER = 65;
+ const PAPERSIZE_A3_EXTRA_TRANSVERSE_PAPER = 66;
+
+ /* Page orientation */
+ const ORIENTATION_DEFAULT = 'default';
+ const ORIENTATION_LANDSCAPE = 'landscape';
+ const ORIENTATION_PORTRAIT = 'portrait';
+
+ /* Print Range Set Method */
+ const SETPRINTRANGE_OVERWRITE = 'O';
+ const SETPRINTRANGE_INSERT = 'I';
+
+
+ /**
+ * Paper size
+ *
+ * @var int
+ */
+ private $_paperSize = PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER;
+
+ /**
+ * Orientation
+ *
+ * @var string
+ */
+ private $_orientation = PHPExcel_Worksheet_PageSetup::ORIENTATION_DEFAULT;
+
+ /**
+ * Scale (Print Scale)
+ *
+ * Print scaling. Valid values range from 10 to 400
+ * This setting is overridden when fitToWidth and/or fitToHeight are in use
+ *
+ * @var int?
+ */
+ private $_scale = 100;
+
+ /**
+ * Fit To Page
+ * Whether scale or fitToWith / fitToHeight applies
+ *
+ * @var boolean
+ */
+ private $_fitToPage = FALSE;
+
+ /**
+ * Fit To Height
+ * Number of vertical pages to fit on
+ *
+ * @var int?
+ */
+ private $_fitToHeight = 1;
+
+ /**
+ * Fit To Width
+ * Number of horizontal pages to fit on
+ *
+ * @var int?
+ */
+ private $_fitToWidth = 1;
+
+ /**
+ * Columns to repeat at left
+ *
+ * @var array Containing start column and end column, empty array if option unset
+ */
+ private $_columnsToRepeatAtLeft = array('', '');
+
+ /**
+ * Rows to repeat at top
+ *
+ * @var array Containing start row number and end row number, empty array if option unset
+ */
+ private $_rowsToRepeatAtTop = array(0, 0);
+
+ /**
+ * Center page horizontally
+ *
+ * @var boolean
+ */
+ private $_horizontalCentered = FALSE;
+
+ /**
+ * Center page vertically
+ *
+ * @var boolean
+ */
+ private $_verticalCentered = FALSE;
+
+ /**
+ * Print area
+ *
+ * @var string
+ */
+ private $_printArea = NULL;
+
+ /**
+ * First page number
+ *
+ * @var int
+ */
+ private $_firstPageNumber = NULL;
+
+ /**
+ * Create a new PHPExcel_Worksheet_PageSetup
+ */
+ public function __construct()
+ {
+ }
+
+ /**
+ * Get Paper Size
+ *
+ * @return int
+ */
+ public function getPaperSize() {
+ return $this->_paperSize;
+ }
+
+ /**
+ * Set Paper Size
+ *
+ * @param int $pValue
+ * @return PHPExcel_Worksheet_PageSetup
+ */
+ public function setPaperSize($pValue = PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER) {
+ $this->_paperSize = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get Orientation
+ *
+ * @return string
+ */
+ public function getOrientation() {
+ return $this->_orientation;
+ }
+
+ /**
+ * Set Orientation
+ *
+ * @param string $pValue
+ * @return PHPExcel_Worksheet_PageSetup
+ */
+ public function setOrientation($pValue = PHPExcel_Worksheet_PageSetup::ORIENTATION_DEFAULT) {
+ $this->_orientation = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get Scale
+ *
+ * @return int?
+ */
+ public function getScale() {
+ return $this->_scale;
+ }
+
+ /**
+ * Set Scale
+ *
+ * Print scaling. Valid values range from 10 to 400
+ * This setting is overridden when fitToWidth and/or fitToHeight are in use
+ *
+ * @param int? $pValue
+ * @param boolean $pUpdate Update fitToPage so scaling applies rather than fitToHeight / fitToWidth
+ * @return PHPExcel_Worksheet_PageSetup
+ * @throws PHPExcel_Exception
+ */
+ public function setScale($pValue = 100, $pUpdate = true) {
+ // Microsoft Office Excel 2007 only allows setting a scale between 10 and 400 via the user interface,
+ // but it is apparently still able to handle any scale >= 0, where 0 results in 100
+ if (($pValue >= 0) || is_null($pValue)) {
+ $this->_scale = $pValue;
+ if ($pUpdate) {
+ $this->_fitToPage = false;
+ }
+ } else {
+ throw new PHPExcel_Exception("Scale must not be negative");
+ }
+ return $this;
+ }
+
+ /**
+ * Get Fit To Page
+ *
+ * @return boolean
+ */
+ public function getFitToPage() {
+ return $this->_fitToPage;
+ }
+
+ /**
+ * Set Fit To Page
+ *
+ * @param boolean $pValue
+ * @return PHPExcel_Worksheet_PageSetup
+ */
+ public function setFitToPage($pValue = TRUE) {
+ $this->_fitToPage = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get Fit To Height
+ *
+ * @return int?
+ */
+ public function getFitToHeight() {
+ return $this->_fitToHeight;
+ }
+
+ /**
+ * Set Fit To Height
+ *
+ * @param int? $pValue
+ * @param boolean $pUpdate Update fitToPage so it applies rather than scaling
+ * @return PHPExcel_Worksheet_PageSetup
+ */
+ public function setFitToHeight($pValue = 1, $pUpdate = TRUE) {
+ $this->_fitToHeight = $pValue;
+ if ($pUpdate) {
+ $this->_fitToPage = TRUE;
+ }
+ return $this;
+ }
+
+ /**
+ * Get Fit To Width
+ *
+ * @return int?
+ */
+ public function getFitToWidth() {
+ return $this->_fitToWidth;
+ }
+
+ /**
+ * Set Fit To Width
+ *
+ * @param int? $pValue
+ * @param boolean $pUpdate Update fitToPage so it applies rather than scaling
+ * @return PHPExcel_Worksheet_PageSetup
+ */
+ public function setFitToWidth($pValue = 1, $pUpdate = TRUE) {
+ $this->_fitToWidth = $pValue;
+ if ($pUpdate) {
+ $this->_fitToPage = TRUE;
+ }
+ return $this;
+ }
+
+ /**
+ * Is Columns to repeat at left set?
+ *
+ * @return boolean
+ */
+ public function isColumnsToRepeatAtLeftSet() {
+ if (is_array($this->_columnsToRepeatAtLeft)) {
+ if ($this->_columnsToRepeatAtLeft[0] != '' && $this->_columnsToRepeatAtLeft[1] != '') {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Get Columns to repeat at left
+ *
+ * @return array Containing start column and end column, empty array if option unset
+ */
+ public function getColumnsToRepeatAtLeft() {
+ return $this->_columnsToRepeatAtLeft;
+ }
+
+ /**
+ * Set Columns to repeat at left
+ *
+ * @param array $pValue Containing start column and end column, empty array if option unset
+ * @return PHPExcel_Worksheet_PageSetup
+ */
+ public function setColumnsToRepeatAtLeft($pValue = null) {
+ if (is_array($pValue)) {
+ $this->_columnsToRepeatAtLeft = $pValue;
+ }
+ return $this;
+ }
+
+ /**
+ * Set Columns to repeat at left by start and end
+ *
+ * @param string $pStart
+ * @param string $pEnd
+ * @return PHPExcel_Worksheet_PageSetup
+ */
+ public function setColumnsToRepeatAtLeftByStartAndEnd($pStart = 'A', $pEnd = 'A') {
+ $this->_columnsToRepeatAtLeft = array($pStart, $pEnd);
+ return $this;
+ }
+
+ /**
+ * Is Rows to repeat at top set?
+ *
+ * @return boolean
+ */
+ public function isRowsToRepeatAtTopSet() {
+ if (is_array($this->_rowsToRepeatAtTop)) {
+ if ($this->_rowsToRepeatAtTop[0] != 0 && $this->_rowsToRepeatAtTop[1] != 0) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Get Rows to repeat at top
+ *
+ * @return array Containing start column and end column, empty array if option unset
+ */
+ public function getRowsToRepeatAtTop() {
+ return $this->_rowsToRepeatAtTop;
+ }
+
+ /**
+ * Set Rows to repeat at top
+ *
+ * @param array $pValue Containing start column and end column, empty array if option unset
+ * @return PHPExcel_Worksheet_PageSetup
+ */
+ public function setRowsToRepeatAtTop($pValue = null) {
+ if (is_array($pValue)) {
+ $this->_rowsToRepeatAtTop = $pValue;
+ }
+ return $this;
+ }
+
+ /**
+ * Set Rows to repeat at top by start and end
+ *
+ * @param int $pStart
+ * @param int $pEnd
+ * @return PHPExcel_Worksheet_PageSetup
+ */
+ public function setRowsToRepeatAtTopByStartAndEnd($pStart = 1, $pEnd = 1) {
+ $this->_rowsToRepeatAtTop = array($pStart, $pEnd);
+ return $this;
+ }
+
+ /**
+ * Get center page horizontally
+ *
+ * @return bool
+ */
+ public function getHorizontalCentered() {
+ return $this->_horizontalCentered;
+ }
+
+ /**
+ * Set center page horizontally
+ *
+ * @param bool $value
+ * @return PHPExcel_Worksheet_PageSetup
+ */
+ public function setHorizontalCentered($value = false) {
+ $this->_horizontalCentered = $value;
+ return $this;
+ }
+
+ /**
+ * Get center page vertically
+ *
+ * @return bool
+ */
+ public function getVerticalCentered() {
+ return $this->_verticalCentered;
+ }
+
+ /**
+ * Set center page vertically
+ *
+ * @param bool $value
+ * @return PHPExcel_Worksheet_PageSetup
+ */
+ public function setVerticalCentered($value = false) {
+ $this->_verticalCentered = $value;
+ return $this;
+ }
+
+ /**
+ * Get print area
+ *
+ * @param int $index Identifier for a specific print area range if several ranges have been set
+ * Default behaviour, or a index value of 0, will return all ranges as a comma-separated string
+ * Otherwise, the specific range identified by the value of $index will be returned
+ * Print areas are numbered from 1
+ * @throws PHPExcel_Exception
+ * @return string
+ */
+ public function getPrintArea($index = 0) {
+ if ($index == 0) {
+ return $this->_printArea;
+ }
+ $printAreas = explode(',',$this->_printArea);
+ if (isset($printAreas[$index-1])) {
+ return $printAreas[$index-1];
+ }
+ throw new PHPExcel_Exception("Requested Print Area does not exist");
+ }
+
+ /**
+ * Is print area set?
+ *
+ * @param int $index Identifier for a specific print area range if several ranges have been set
+ * Default behaviour, or an index value of 0, will identify whether any print range is set
+ * Otherwise, existence of the range identified by the value of $index will be returned
+ * Print areas are numbered from 1
+ * @return boolean
+ */
+ public function isPrintAreaSet($index = 0) {
+ if ($index == 0) {
+ return !is_null($this->_printArea);
+ }
+ $printAreas = explode(',',$this->_printArea);
+ return isset($printAreas[$index-1]);
+ }
+
+ /**
+ * Clear a print area
+ *
+ * @param int $index Identifier for a specific print area range if several ranges have been set
+ * Default behaviour, or an index value of 0, will clear all print ranges that are set
+ * Otherwise, the range identified by the value of $index will be removed from the series
+ * Print areas are numbered from 1
+ * @return PHPExcel_Worksheet_PageSetup
+ */
+ public function clearPrintArea($index = 0) {
+ if ($index == 0) {
+ $this->_printArea = NULL;
+ } else {
+ $printAreas = explode(',',$this->_printArea);
+ if (isset($printAreas[$index-1])) {
+ unset($printAreas[$index-1]);
+ $this->_printArea = implode(',',$printAreas);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set print area. e.g. 'A1:D10' or 'A1:D10,G5:M20'
+ *
+ * @param string $value
+ * @param int $index Identifier for a specific print area range allowing several ranges to be set
+ * When the method is "O"verwrite, then a positive integer index will overwrite that indexed
+ * entry in the print areas list; a negative index value will identify which entry to
+ * overwrite working bacward through the print area to the list, with the last entry as -1.
+ * Specifying an index value of 0, will overwrite all existing print ranges.
+ * When the method is "I"nsert, then a positive index will insert after that indexed entry in
+ * the print areas list, while a negative index will insert before the indexed entry.
+ * Specifying an index value of 0, will always append the new print range at the end of the
+ * list.
+ * Print areas are numbered from 1
+ * @param string $method Determines the method used when setting multiple print areas
+ * Default behaviour, or the "O" method, overwrites existing print area
+ * The "I" method, inserts the new print area before any specified index, or at the end of the list
+ * @return PHPExcel_Worksheet_PageSetup
+ * @throws PHPExcel_Exception
+ */
+ public function setPrintArea($value, $index = 0, $method = self::SETPRINTRANGE_OVERWRITE) {
+ if (strpos($value,'!') !== false) {
+ throw new PHPExcel_Exception('Cell coordinate must not specify a worksheet.');
+ } elseif (strpos($value,':') === false) {
+ throw new PHPExcel_Exception('Cell coordinate must be a range of cells.');
+ } elseif (strpos($value,'$') !== false) {
+ throw new PHPExcel_Exception('Cell coordinate must not be absolute.');
+ }
+ $value = strtoupper($value);
+
+ if ($method == self::SETPRINTRANGE_OVERWRITE) {
+ if ($index == 0) {
+ $this->_printArea = $value;
+ } else {
+ $printAreas = explode(',',$this->_printArea);
+ if($index < 0) {
+ $index = count($printAreas) - abs($index) + 1;
+ }
+ if (($index <= 0) || ($index > count($printAreas))) {
+ throw new PHPExcel_Exception('Invalid index for setting print range.');
+ }
+ $printAreas[$index-1] = $value;
+ $this->_printArea = implode(',',$printAreas);
+ }
+ } elseif($method == self::SETPRINTRANGE_INSERT) {
+ if ($index == 0) {
+ $this->_printArea .= ($this->_printArea == '') ? $value : ','.$value;
+ } else {
+ $printAreas = explode(',',$this->_printArea);
+ if($index < 0) {
+ $index = abs($index) - 1;
+ }
+ if ($index > count($printAreas)) {
+ throw new PHPExcel_Exception('Invalid index for setting print range.');
+ }
+ $printAreas = array_merge(array_slice($printAreas,0,$index),array($value),array_slice($printAreas,$index));
+ $this->_printArea = implode(',',$printAreas);
+ }
+ } else {
+ throw new PHPExcel_Exception('Invalid method for setting print range.');
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add a new print area (e.g. 'A1:D10' or 'A1:D10,G5:M20') to the list of print areas
+ *
+ * @param string $value
+ * @param int $index Identifier for a specific print area range allowing several ranges to be set
+ * A positive index will insert after that indexed entry in the print areas list, while a
+ * negative index will insert before the indexed entry.
+ * Specifying an index value of 0, will always append the new print range at the end of the
+ * list.
+ * Print areas are numbered from 1
+ * @return PHPExcel_Worksheet_PageSetup
+ * @throws PHPExcel_Exception
+ */
+ public function addPrintArea($value, $index = -1) {
+ return $this->setPrintArea($value, $index, self::SETPRINTRANGE_INSERT);
+ }
+
+ /**
+ * Set print area
+ *
+ * @param int $column1 Column 1
+ * @param int $row1 Row 1
+ * @param int $column2 Column 2
+ * @param int $row2 Row 2
+ * @param int $index Identifier for a specific print area range allowing several ranges to be set
+ * When the method is "O"verwrite, then a positive integer index will overwrite that indexed
+ * entry in the print areas list; a negative index value will identify which entry to
+ * overwrite working bacward through the print area to the list, with the last entry as -1.
+ * Specifying an index value of 0, will overwrite all existing print ranges.
+ * When the method is "I"nsert, then a positive index will insert after that indexed entry in
+ * the print areas list, while a negative index will insert before the indexed entry.
+ * Specifying an index value of 0, will always append the new print range at the end of the
+ * list.
+ * Print areas are numbered from 1
+ * @param string $method Determines the method used when setting multiple print areas
+ * Default behaviour, or the "O" method, overwrites existing print area
+ * The "I" method, inserts the new print area before any specified index, or at the end of the list
+ * @return PHPExcel_Worksheet_PageSetup
+ * @throws PHPExcel_Exception
+ */
+ public function setPrintAreaByColumnAndRow($column1, $row1, $column2, $row2, $index = 0, $method = self::SETPRINTRANGE_OVERWRITE)
+ {
+ return $this->setPrintArea(PHPExcel_Cell::stringFromColumnIndex($column1) . $row1 . ':' . PHPExcel_Cell::stringFromColumnIndex($column2) . $row2, $index, $method);
+ }
+
+ /**
+ * Add a new print area to the list of print areas
+ *
+ * @param int $column1 Start Column for the print area
+ * @param int $row1 Start Row for the print area
+ * @param int $column2 End Column for the print area
+ * @param int $row2 End Row for the print area
+ * @param int $index Identifier for a specific print area range allowing several ranges to be set
+ * A positive index will insert after that indexed entry in the print areas list, while a
+ * negative index will insert before the indexed entry.
+ * Specifying an index value of 0, will always append the new print range at the end of the
+ * list.
+ * Print areas are numbered from 1
+ * @return PHPExcel_Worksheet_PageSetup
+ * @throws PHPExcel_Exception
+ */
+ public function addPrintAreaByColumnAndRow($column1, $row1, $column2, $row2, $index = -1)
+ {
+ return $this->setPrintArea(PHPExcel_Cell::stringFromColumnIndex($column1) . $row1 . ':' . PHPExcel_Cell::stringFromColumnIndex($column2) . $row2, $index, self::SETPRINTRANGE_INSERT);
+ }
+
+ /**
+ * Get first page number
+ *
+ * @return int
+ */
+ public function getFirstPageNumber() {
+ return $this->_firstPageNumber;
+ }
+
+ /**
+ * Set first page number
+ *
+ * @param int $value
+ * @return PHPExcel_Worksheet_HeaderFooter
+ */
+ public function setFirstPageNumber($value = null) {
+ $this->_firstPageNumber = $value;
+ return $this;
+ }
+
+ /**
+ * Reset first page number
+ *
+ * @return PHPExcel_Worksheet_HeaderFooter
+ */
+ public function resetFirstPageNumber() {
+ return $this->setFirstPageNumber(null);
+ }
+
+ /**
+ * Implement PHP __clone to create a deep clone, not just a shallow copy.
+ */
+ public function __clone() {
+ $vars = get_object_vars($this);
+ foreach ($vars as $key => $value) {
+ if (is_object($value)) {
+ $this->$key = clone $value;
+ } else {
+ $this->$key = $value;
+ }
+ }
+ }
+}
diff --git a/framework/library/phpexcel/PHPExcel/Worksheet/Protection.php b/framework/library/phpexcel/PHPExcel/Worksheet/Protection.php
new file mode 100644
index 0000000..e9d6bb6
--- /dev/null
+++ b/framework/library/phpexcel/PHPExcel/Worksheet/Protection.php
@@ -0,0 +1,545 @@
+_sheet ||
+ $this->_objects ||
+ $this->_scenarios ||
+ $this->_formatCells ||
+ $this->_formatColumns ||
+ $this->_formatRows ||
+ $this->_insertColumns ||
+ $this->_insertRows ||
+ $this->_insertHyperlinks ||
+ $this->_deleteColumns ||
+ $this->_deleteRows ||
+ $this->_selectLockedCells ||
+ $this->_sort ||
+ $this->_autoFilter ||
+ $this->_pivotTables ||
+ $this->_selectUnlockedCells;
+ }
+
+ /**
+ * Get Sheet
+ *
+ * @return boolean
+ */
+ function getSheet() {
+ return $this->_sheet;
+ }
+
+ /**
+ * Set Sheet
+ *
+ * @param boolean $pValue
+ * @return PHPExcel_Worksheet_Protection
+ */
+ function setSheet($pValue = false) {
+ $this->_sheet = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get Objects
+ *
+ * @return boolean
+ */
+ function getObjects() {
+ return $this->_objects;
+ }
+
+ /**
+ * Set Objects
+ *
+ * @param boolean $pValue
+ * @return PHPExcel_Worksheet_Protection
+ */
+ function setObjects($pValue = false) {
+ $this->_objects = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get Scenarios
+ *
+ * @return boolean
+ */
+ function getScenarios() {
+ return $this->_scenarios;
+ }
+
+ /**
+ * Set Scenarios
+ *
+ * @param boolean $pValue
+ * @return PHPExcel_Worksheet_Protection
+ */
+ function setScenarios($pValue = false) {
+ $this->_scenarios = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get FormatCells
+ *
+ * @return boolean
+ */
+ function getFormatCells() {
+ return $this->_formatCells;
+ }
+
+ /**
+ * Set FormatCells
+ *
+ * @param boolean $pValue
+ * @return PHPExcel_Worksheet_Protection
+ */
+ function setFormatCells($pValue = false) {
+ $this->_formatCells = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get FormatColumns
+ *
+ * @return boolean
+ */
+ function getFormatColumns() {
+ return $this->_formatColumns;
+ }
+
+ /**
+ * Set FormatColumns
+ *
+ * @param boolean $pValue
+ * @return PHPExcel_Worksheet_Protection
+ */
+ function setFormatColumns($pValue = false) {
+ $this->_formatColumns = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get FormatRows
+ *
+ * @return boolean
+ */
+ function getFormatRows() {
+ return $this->_formatRows;
+ }
+
+ /**
+ * Set FormatRows
+ *
+ * @param boolean $pValue
+ * @return PHPExcel_Worksheet_Protection
+ */
+ function setFormatRows($pValue = false) {
+ $this->_formatRows = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get InsertColumns
+ *
+ * @return boolean
+ */
+ function getInsertColumns() {
+ return $this->_insertColumns;
+ }
+
+ /**
+ * Set InsertColumns
+ *
+ * @param boolean $pValue
+ * @return PHPExcel_Worksheet_Protection
+ */
+ function setInsertColumns($pValue = false) {
+ $this->_insertColumns = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get InsertRows
+ *
+ * @return boolean
+ */
+ function getInsertRows() {
+ return $this->_insertRows;
+ }
+
+ /**
+ * Set InsertRows
+ *
+ * @param boolean $pValue
+ * @return PHPExcel_Worksheet_Protection
+ */
+ function setInsertRows($pValue = false) {
+ $this->_insertRows = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get InsertHyperlinks
+ *
+ * @return boolean
+ */
+ function getInsertHyperlinks() {
+ return $this->_insertHyperlinks;
+ }
+
+ /**
+ * Set InsertHyperlinks
+ *
+ * @param boolean $pValue
+ * @return PHPExcel_Worksheet_Protection
+ */
+ function setInsertHyperlinks($pValue = false) {
+ $this->_insertHyperlinks = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get DeleteColumns
+ *
+ * @return boolean
+ */
+ function getDeleteColumns() {
+ return $this->_deleteColumns;
+ }
+
+ /**
+ * Set DeleteColumns
+ *
+ * @param boolean $pValue
+ * @return PHPExcel_Worksheet_Protection
+ */
+ function setDeleteColumns($pValue = false) {
+ $this->_deleteColumns = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get DeleteRows
+ *
+ * @return boolean
+ */
+ function getDeleteRows() {
+ return $this->_deleteRows;
+ }
+
+ /**
+ * Set DeleteRows
+ *
+ * @param boolean $pValue
+ * @return PHPExcel_Worksheet_Protection
+ */
+ function setDeleteRows($pValue = false) {
+ $this->_deleteRows = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get SelectLockedCells
+ *
+ * @return boolean
+ */
+ function getSelectLockedCells() {
+ return $this->_selectLockedCells;
+ }
+
+ /**
+ * Set SelectLockedCells
+ *
+ * @param boolean $pValue
+ * @return PHPExcel_Worksheet_Protection
+ */
+ function setSelectLockedCells($pValue = false) {
+ $this->_selectLockedCells = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get Sort
+ *
+ * @return boolean
+ */
+ function getSort() {
+ return $this->_sort;
+ }
+
+ /**
+ * Set Sort
+ *
+ * @param boolean $pValue
+ * @return PHPExcel_Worksheet_Protection
+ */
+ function setSort($pValue = false) {
+ $this->_sort = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get AutoFilter
+ *
+ * @return boolean
+ */
+ function getAutoFilter() {
+ return $this->_autoFilter;
+ }
+
+ /**
+ * Set AutoFilter
+ *
+ * @param boolean $pValue
+ * @return PHPExcel_Worksheet_Protection
+ */
+ function setAutoFilter($pValue = false) {
+ $this->_autoFilter = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get PivotTables
+ *
+ * @return boolean
+ */
+ function getPivotTables() {
+ return $this->_pivotTables;
+ }
+
+ /**
+ * Set PivotTables
+ *
+ * @param boolean $pValue
+ * @return PHPExcel_Worksheet_Protection
+ */
+ function setPivotTables($pValue = false) {
+ $this->_pivotTables = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get SelectUnlockedCells
+ *
+ * @return boolean
+ */
+ function getSelectUnlockedCells() {
+ return $this->_selectUnlockedCells;
+ }
+
+ /**
+ * Set SelectUnlockedCells
+ *
+ * @param boolean $pValue
+ * @return PHPExcel_Worksheet_Protection
+ */
+ function setSelectUnlockedCells($pValue = false) {
+ $this->_selectUnlockedCells = $pValue;
+ return $this;
+ }
+
+ /**
+ * Get Password (hashed)
+ *
+ * @return string
+ */
+ function getPassword() {
+ return $this->_password;
+ }
+
+ /**
+ * Set Password
+ *
+ * @param string $pValue
+ * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true
+ * @return PHPExcel_Worksheet_Protection
+ */
+ function setPassword($pValue = '', $pAlreadyHashed = false) {
+ if (!$pAlreadyHashed) {
+ $pValue = PHPExcel_Shared_PasswordHasher::hashPassword($pValue);
+ }
+ $this->_password = $pValue;
+ return $this;
+ }
+
+ /**
+ * Implement PHP __clone to create a deep clone, not just a shallow copy.
+ */
+ public function __clone() {
+ $vars = get_object_vars($this);
+ foreach ($vars as $key => $value) {
+ if (is_object($value)) {
+ $this->$key = clone $value;
+ } else {
+ $this->$key = $value;
+ }
+ }
+ }
+}
diff --git a/framework/library/phpexcel/PHPExcel/Writer/Excel5/Parser.php b/framework/library/phpexcel/PHPExcel/Writer/Excel5/Parser.php
new file mode 100644
index 0000000..443fefc
--- /dev/null
+++ b/framework/library/phpexcel/PHPExcel/Writer/Excel5/Parser.php
@@ -0,0 +1,1582 @@
+=,;#()"{}
+ const REGEX_SHEET_TITLE_UNQUOTED = '[^\*\:\/\\\\\?\[\]\+\-\% \\\'\^\&\<\>\=\,\;\#\(\)\"\{\}]+';
+
+ // Sheet title in quoted form (without surrounding quotes)
+ // Invalid sheet title characters cannot occur in the sheet title:
+ // *:/\?[] (usual invalid sheet title characters)
+ // Single quote is represented as a pair ''
+ const REGEX_SHEET_TITLE_QUOTED = '(([^\*\:\/\\\\\?\[\]\\\'])+|(\\\'\\\')+)+';
+
+ /**
+ * The index of the character we are currently looking at
+ * @var integer
+ */
+ public $_current_char;
+
+ /**
+ * The token we are working on.
+ * @var string
+ */
+ public $_current_token;
+
+ /**
+ * The formula to parse
+ * @var string
+ */
+ public $_formula;
+
+ /**
+ * The character ahead of the current char
+ * @var string
+ */
+ public $_lookahead;
+
+ /**
+ * The parse tree to be generated
+ * @var string
+ */
+ public $_parse_tree;
+
+ /**
+ * Array of external sheets
+ * @var array
+ */
+ public $_ext_sheets;
+
+ /**
+ * Array of sheet references in the form of REF structures
+ * @var array
+ */
+ public $_references;
+
+ /**
+ * The class constructor
+ *
+ */
+ public function __construct()
+ {
+ $this->_current_char = 0;
+ $this->_current_token = ''; // The token we are working on.
+ $this->_formula = ''; // The formula to parse.
+ $this->_lookahead = ''; // The character ahead of the current char.
+ $this->_parse_tree = ''; // The parse tree to be generated.
+ $this->_initializeHashes(); // Initialize the hashes: ptg's and function's ptg's
+ $this->_ext_sheets = array();
+ $this->_references = array();
+ }
+
+ /**
+ * Initialize the ptg and function hashes.
+ *
+ * @access private
+ */
+ function _initializeHashes()
+ {
+ // The Excel ptg indices
+ $this->ptg = array(
+ 'ptgExp' => 0x01,
+ 'ptgTbl' => 0x02,
+ 'ptgAdd' => 0x03,
+ 'ptgSub' => 0x04,
+ 'ptgMul' => 0x05,
+ 'ptgDiv' => 0x06,
+ 'ptgPower' => 0x07,
+ 'ptgConcat' => 0x08,
+ 'ptgLT' => 0x09,
+ 'ptgLE' => 0x0A,
+ 'ptgEQ' => 0x0B,
+ 'ptgGE' => 0x0C,
+ 'ptgGT' => 0x0D,
+ 'ptgNE' => 0x0E,
+ 'ptgIsect' => 0x0F,
+ 'ptgUnion' => 0x10,
+ 'ptgRange' => 0x11,
+ 'ptgUplus' => 0x12,
+ 'ptgUminus' => 0x13,
+ 'ptgPercent' => 0x14,
+ 'ptgParen' => 0x15,
+ 'ptgMissArg' => 0x16,
+ 'ptgStr' => 0x17,
+ 'ptgAttr' => 0x19,
+ 'ptgSheet' => 0x1A,
+ 'ptgEndSheet' => 0x1B,
+ 'ptgErr' => 0x1C,
+ 'ptgBool' => 0x1D,
+ 'ptgInt' => 0x1E,
+ 'ptgNum' => 0x1F,
+ 'ptgArray' => 0x20,
+ 'ptgFunc' => 0x21,
+ 'ptgFuncVar' => 0x22,
+ 'ptgName' => 0x23,
+ 'ptgRef' => 0x24,
+ 'ptgArea' => 0x25,
+ 'ptgMemArea' => 0x26,
+ 'ptgMemErr' => 0x27,
+ 'ptgMemNoMem' => 0x28,
+ 'ptgMemFunc' => 0x29,
+ 'ptgRefErr' => 0x2A,
+ 'ptgAreaErr' => 0x2B,
+ 'ptgRefN' => 0x2C,
+ 'ptgAreaN' => 0x2D,
+ 'ptgMemAreaN' => 0x2E,
+ 'ptgMemNoMemN' => 0x2F,
+ 'ptgNameX' => 0x39,
+ 'ptgRef3d' => 0x3A,
+ 'ptgArea3d' => 0x3B,
+ 'ptgRefErr3d' => 0x3C,
+ 'ptgAreaErr3d' => 0x3D,
+ 'ptgArrayV' => 0x40,
+ 'ptgFuncV' => 0x41,
+ 'ptgFuncVarV' => 0x42,
+ 'ptgNameV' => 0x43,
+ 'ptgRefV' => 0x44,
+ 'ptgAreaV' => 0x45,
+ 'ptgMemAreaV' => 0x46,
+ 'ptgMemErrV' => 0x47,
+ 'ptgMemNoMemV' => 0x48,
+ 'ptgMemFuncV' => 0x49,
+ 'ptgRefErrV' => 0x4A,
+ 'ptgAreaErrV' => 0x4B,
+ 'ptgRefNV' => 0x4C,
+ 'ptgAreaNV' => 0x4D,
+ 'ptgMemAreaNV' => 0x4E,
+ 'ptgMemNoMemN' => 0x4F,
+ 'ptgFuncCEV' => 0x58,
+ 'ptgNameXV' => 0x59,
+ 'ptgRef3dV' => 0x5A,
+ 'ptgArea3dV' => 0x5B,
+ 'ptgRefErr3dV' => 0x5C,
+ 'ptgAreaErr3d' => 0x5D,
+ 'ptgArrayA' => 0x60,
+ 'ptgFuncA' => 0x61,
+ 'ptgFuncVarA' => 0x62,
+ 'ptgNameA' => 0x63,
+ 'ptgRefA' => 0x64,
+ 'ptgAreaA' => 0x65,
+ 'ptgMemAreaA' => 0x66,
+ 'ptgMemErrA' => 0x67,
+ 'ptgMemNoMemA' => 0x68,
+ 'ptgMemFuncA' => 0x69,
+ 'ptgRefErrA' => 0x6A,
+ 'ptgAreaErrA' => 0x6B,
+ 'ptgRefNA' => 0x6C,
+ 'ptgAreaNA' => 0x6D,
+ 'ptgMemAreaNA' => 0x6E,
+ 'ptgMemNoMemN' => 0x6F,
+ 'ptgFuncCEA' => 0x78,
+ 'ptgNameXA' => 0x79,
+ 'ptgRef3dA' => 0x7A,
+ 'ptgArea3dA' => 0x7B,
+ 'ptgRefErr3dA' => 0x7C,
+ 'ptgAreaErr3d' => 0x7D
+ );
+
+ // Thanks to Michael Meeks and Gnumeric for the initial arg values.
+ //
+ // The following hash was generated by "function_locale.pl" in the distro.
+ // Refer to function_locale.pl for non-English function names.
+ //
+ // The array elements are as follow:
+ // ptg: The Excel function ptg code.
+ // args: The number of arguments that the function takes:
+ // >=0 is a fixed number of arguments.
+ // -1 is a variable number of arguments.
+ // class: The reference, value or array class of the function args.
+ // vol: The function is volatile.
+ //
+ $this->_functions = array(
+ // function ptg args class vol
+ 'COUNT' => array( 0, -1, 0, 0 ),
+ 'IF' => array( 1, -1, 1, 0 ),
+ 'ISNA' => array( 2, 1, 1, 0 ),
+ 'ISERROR' => array( 3, 1, 1, 0 ),
+ 'SUM' => array( 4, -1, 0, 0 ),
+ 'AVERAGE' => array( 5, -1, 0, 0 ),
+ 'MIN' => array( 6, -1, 0, 0 ),
+ 'MAX' => array( 7, -1, 0, 0 ),
+ 'ROW' => array( 8, -1, 0, 0 ),
+ 'COLUMN' => array( 9, -1, 0, 0 ),
+ 'NA' => array( 10, 0, 0, 0 ),
+ 'NPV' => array( 11, -1, 1, 0 ),
+ 'STDEV' => array( 12, -1, 0, 0 ),
+ 'DOLLAR' => array( 13, -1, 1, 0 ),
+ 'FIXED' => array( 14, -1, 1, 0 ),
+ 'SIN' => array( 15, 1, 1, 0 ),
+ 'COS' => array( 16, 1, 1, 0 ),
+ 'TAN' => array( 17, 1, 1, 0 ),
+ 'ATAN' => array( 18, 1, 1, 0 ),
+ 'PI' => array( 19, 0, 1, 0 ),
+ 'SQRT' => array( 20, 1, 1, 0 ),
+ 'EXP' => array( 21, 1, 1, 0 ),
+ 'LN' => array( 22, 1, 1, 0 ),
+ 'LOG10' => array( 23, 1, 1, 0 ),
+ 'ABS' => array( 24, 1, 1, 0 ),
+ 'INT' => array( 25, 1, 1, 0 ),
+ 'SIGN' => array( 26, 1, 1, 0 ),
+ 'ROUND' => array( 27, 2, 1, 0 ),
+ 'LOOKUP' => array( 28, -1, 0, 0 ),
+ 'INDEX' => array( 29, -1, 0, 1 ),
+ 'REPT' => array( 30, 2, 1, 0 ),
+ 'MID' => array( 31, 3, 1, 0 ),
+ 'LEN' => array( 32, 1, 1, 0 ),
+ 'VALUE' => array( 33, 1, 1, 0 ),
+ 'TRUE' => array( 34, 0, 1, 0 ),
+ 'FALSE' => array( 35, 0, 1, 0 ),
+ 'AND' => array( 36, -1, 0, 0 ),
+ 'OR' => array( 37, -1, 0, 0 ),
+ 'NOT' => array( 38, 1, 1, 0 ),
+ 'MOD' => array( 39, 2, 1, 0 ),
+ 'DCOUNT' => array( 40, 3, 0, 0 ),
+ 'DSUM' => array( 41, 3, 0, 0 ),
+ 'DAVERAGE' => array( 42, 3, 0, 0 ),
+ 'DMIN' => array( 43, 3, 0, 0 ),
+ 'DMAX' => array( 44, 3, 0, 0 ),
+ 'DSTDEV' => array( 45, 3, 0, 0 ),
+ 'VAR' => array( 46, -1, 0, 0 ),
+ 'DVAR' => array( 47, 3, 0, 0 ),
+ 'TEXT' => array( 48, 2, 1, 0 ),
+ 'LINEST' => array( 49, -1, 0, 0 ),
+ 'TREND' => array( 50, -1, 0, 0 ),
+ 'LOGEST' => array( 51, -1, 0, 0 ),
+ 'GROWTH' => array( 52, -1, 0, 0 ),
+ 'PV' => array( 56, -1, 1, 0 ),
+ 'FV' => array( 57, -1, 1, 0 ),
+ 'NPER' => array( 58, -1, 1, 0 ),
+ 'PMT' => array( 59, -1, 1, 0 ),
+ 'RATE' => array( 60, -1, 1, 0 ),
+ 'MIRR' => array( 61, 3, 0, 0 ),
+ 'IRR' => array( 62, -1, 0, 0 ),
+ 'RAND' => array( 63, 0, 1, 1 ),
+ 'MATCH' => array( 64, -1, 0, 0 ),
+ 'DATE' => array( 65, 3, 1, 0 ),
+ 'TIME' => array( 66, 3, 1, 0 ),
+ 'DAY' => array( 67, 1, 1, 0 ),
+ 'MONTH' => array( 68, 1, 1, 0 ),
+ 'YEAR' => array( 69, 1, 1, 0 ),
+ 'WEEKDAY' => array( 70, -1, 1, 0 ),
+ 'HOUR' => array( 71, 1, 1, 0 ),
+ 'MINUTE' => array( 72, 1, 1, 0 ),
+ 'SECOND' => array( 73, 1, 1, 0 ),
+ 'NOW' => array( 74, 0, 1, 1 ),
+ 'AREAS' => array( 75, 1, 0, 1 ),
+ 'ROWS' => array( 76, 1, 0, 1 ),
+ 'COLUMNS' => array( 77, 1, 0, 1 ),
+ 'OFFSET' => array( 78, -1, 0, 1 ),
+ 'SEARCH' => array( 82, -1, 1, 0 ),
+ 'TRANSPOSE' => array( 83, 1, 1, 0 ),
+ 'TYPE' => array( 86, 1, 1, 0 ),
+ 'ATAN2' => array( 97, 2, 1, 0 ),
+ 'ASIN' => array( 98, 1, 1, 0 ),
+ 'ACOS' => array( 99, 1, 1, 0 ),
+ 'CHOOSE' => array( 100, -1, 1, 0 ),
+ 'HLOOKUP' => array( 101, -1, 0, 0 ),
+ 'VLOOKUP' => array( 102, -1, 0, 0 ),
+ 'ISREF' => array( 105, 1, 0, 0 ),
+ 'LOG' => array( 109, -1, 1, 0 ),
+ 'CHAR' => array( 111, 1, 1, 0 ),
+ 'LOWER' => array( 112, 1, 1, 0 ),
+ 'UPPER' => array( 113, 1, 1, 0 ),
+ 'PROPER' => array( 114, 1, 1, 0 ),
+ 'LEFT' => array( 115, -1, 1, 0 ),
+ 'RIGHT' => array( 116, -1, 1, 0 ),
+ 'EXACT' => array( 117, 2, 1, 0 ),
+ 'TRIM' => array( 118, 1, 1, 0 ),
+ 'REPLACE' => array( 119, 4, 1, 0 ),
+ 'SUBSTITUTE' => array( 120, -1, 1, 0 ),
+ 'CODE' => array( 121, 1, 1, 0 ),
+ 'FIND' => array( 124, -1, 1, 0 ),
+ 'CELL' => array( 125, -1, 0, 1 ),
+ 'ISERR' => array( 126, 1, 1, 0 ),
+ 'ISTEXT' => array( 127, 1, 1, 0 ),
+ 'ISNUMBER' => array( 128, 1, 1, 0 ),
+ 'ISBLANK' => array( 129, 1, 1, 0 ),
+ 'T' => array( 130, 1, 0, 0 ),
+ 'N' => array( 131, 1, 0, 0 ),
+ 'DATEVALUE' => array( 140, 1, 1, 0 ),
+ 'TIMEVALUE' => array( 141, 1, 1, 0 ),
+ 'SLN' => array( 142, 3, 1, 0 ),
+ 'SYD' => array( 143, 4, 1, 0 ),
+ 'DDB' => array( 144, -1, 1, 0 ),
+ 'INDIRECT' => array( 148, -1, 1, 1 ),
+ 'CALL' => array( 150, -1, 1, 0 ),
+ 'CLEAN' => array( 162, 1, 1, 0 ),
+ 'MDETERM' => array( 163, 1, 2, 0 ),
+ 'MINVERSE' => array( 164, 1, 2, 0 ),
+ 'MMULT' => array( 165, 2, 2, 0 ),
+ 'IPMT' => array( 167, -1, 1, 0 ),
+ 'PPMT' => array( 168, -1, 1, 0 ),
+ 'COUNTA' => array( 169, -1, 0, 0 ),
+ 'PRODUCT' => array( 183, -1, 0, 0 ),
+ 'FACT' => array( 184, 1, 1, 0 ),
+ 'DPRODUCT' => array( 189, 3, 0, 0 ),
+ 'ISNONTEXT' => array( 190, 1, 1, 0 ),
+ 'STDEVP' => array( 193, -1, 0, 0 ),
+ 'VARP' => array( 194, -1, 0, 0 ),
+ 'DSTDEVP' => array( 195, 3, 0, 0 ),
+ 'DVARP' => array( 196, 3, 0, 0 ),
+ 'TRUNC' => array( 197, -1, 1, 0 ),
+ 'ISLOGICAL' => array( 198, 1, 1, 0 ),
+ 'DCOUNTA' => array( 199, 3, 0, 0 ),
+ 'USDOLLAR' => array( 204, -1, 1, 0 ),
+ 'FINDB' => array( 205, -1, 1, 0 ),
+ 'SEARCHB' => array( 206, -1, 1, 0 ),
+ 'REPLACEB' => array( 207, 4, 1, 0 ),
+ 'LEFTB' => array( 208, -1, 1, 0 ),
+ 'RIGHTB' => array( 209, -1, 1, 0 ),
+ 'MIDB' => array( 210, 3, 1, 0 ),
+ 'LENB' => array( 211, 1, 1, 0 ),
+ 'ROUNDUP' => array( 212, 2, 1, 0 ),
+ 'ROUNDDOWN' => array( 213, 2, 1, 0 ),
+ 'ASC' => array( 214, 1, 1, 0 ),
+ 'DBCS' => array( 215, 1, 1, 0 ),
+ 'RANK' => array( 216, -1, 0, 0 ),
+ 'ADDRESS' => array( 219, -1, 1, 0 ),
+ 'DAYS360' => array( 220, -1, 1, 0 ),
+ 'TODAY' => array( 221, 0, 1, 1 ),
+ 'VDB' => array( 222, -1, 1, 0 ),
+ 'MEDIAN' => array( 227, -1, 0, 0 ),
+ 'SUMPRODUCT' => array( 228, -1, 2, 0 ),
+ 'SINH' => array( 229, 1, 1, 0 ),
+ 'COSH' => array( 230, 1, 1, 0 ),
+ 'TANH' => array( 231, 1, 1, 0 ),
+ 'ASINH' => array( 232, 1, 1, 0 ),
+ 'ACOSH' => array( 233, 1, 1, 0 ),
+ 'ATANH' => array( 234, 1, 1, 0 ),
+ 'DGET' => array( 235, 3, 0, 0 ),
+ 'INFO' => array( 244, 1, 1, 1 ),
+ 'DB' => array( 247, -1, 1, 0 ),
+ 'FREQUENCY' => array( 252, 2, 0, 0 ),
+ 'ERROR.TYPE' => array( 261, 1, 1, 0 ),
+ 'REGISTER.ID' => array( 267, -1, 1, 0 ),
+ 'AVEDEV' => array( 269, -1, 0, 0 ),
+ 'BETADIST' => array( 270, -1, 1, 0 ),
+ 'GAMMALN' => array( 271, 1, 1, 0 ),
+ 'BETAINV' => array( 272, -1, 1, 0 ),
+ 'BINOMDIST' => array( 273, 4, 1, 0 ),
+ 'CHIDIST' => array( 274, 2, 1, 0 ),
+ 'CHIINV' => array( 275, 2, 1, 0 ),
+ 'COMBIN' => array( 276, 2, 1, 0 ),
+ 'CONFIDENCE' => array( 277, 3, 1, 0 ),
+ 'CRITBINOM' => array( 278, 3, 1, 0 ),
+ 'EVEN' => array( 279, 1, 1, 0 ),
+ 'EXPONDIST' => array( 280, 3, 1, 0 ),
+ 'FDIST' => array( 281, 3, 1, 0 ),
+ 'FINV' => array( 282, 3, 1, 0 ),
+ 'FISHER' => array( 283, 1, 1, 0 ),
+ 'FISHERINV' => array( 284, 1, 1, 0 ),
+ 'FLOOR' => array( 285, 2, 1, 0 ),
+ 'GAMMADIST' => array( 286, 4, 1, 0 ),
+ 'GAMMAINV' => array( 287, 3, 1, 0 ),
+ 'CEILING' => array( 288, 2, 1, 0 ),
+ 'HYPGEOMDIST' => array( 289, 4, 1, 0 ),
+ 'LOGNORMDIST' => array( 290, 3, 1, 0 ),
+ 'LOGINV' => array( 291, 3, 1, 0 ),
+ 'NEGBINOMDIST' => array( 292, 3, 1, 0 ),
+ 'NORMDIST' => array( 293, 4, 1, 0 ),
+ 'NORMSDIST' => array( 294, 1, 1, 0 ),
+ 'NORMINV' => array( 295, 3, 1, 0 ),
+ 'NORMSINV' => array( 296, 1, 1, 0 ),
+ 'STANDARDIZE' => array( 297, 3, 1, 0 ),
+ 'ODD' => array( 298, 1, 1, 0 ),
+ 'PERMUT' => array( 299, 2, 1, 0 ),
+ 'POISSON' => array( 300, 3, 1, 0 ),
+ 'TDIST' => array( 301, 3, 1, 0 ),
+ 'WEIBULL' => array( 302, 4, 1, 0 ),
+ 'SUMXMY2' => array( 303, 2, 2, 0 ),
+ 'SUMX2MY2' => array( 304, 2, 2, 0 ),
+ 'SUMX2PY2' => array( 305, 2, 2, 0 ),
+ 'CHITEST' => array( 306, 2, 2, 0 ),
+ 'CORREL' => array( 307, 2, 2, 0 ),
+ 'COVAR' => array( 308, 2, 2, 0 ),
+ 'FORECAST' => array( 309, 3, 2, 0 ),
+ 'FTEST' => array( 310, 2, 2, 0 ),
+ 'INTERCEPT' => array( 311, 2, 2, 0 ),
+ 'PEARSON' => array( 312, 2, 2, 0 ),
+ 'RSQ' => array( 313, 2, 2, 0 ),
+ 'STEYX' => array( 314, 2, 2, 0 ),
+ 'SLOPE' => array( 315, 2, 2, 0 ),
+ 'TTEST' => array( 316, 4, 2, 0 ),
+ 'PROB' => array( 317, -1, 2, 0 ),
+ 'DEVSQ' => array( 318, -1, 0, 0 ),
+ 'GEOMEAN' => array( 319, -1, 0, 0 ),
+ 'HARMEAN' => array( 320, -1, 0, 0 ),
+ 'SUMSQ' => array( 321, -1, 0, 0 ),
+ 'KURT' => array( 322, -1, 0, 0 ),
+ 'SKEW' => array( 323, -1, 0, 0 ),
+ 'ZTEST' => array( 324, -1, 0, 0 ),
+ 'LARGE' => array( 325, 2, 0, 0 ),
+ 'SMALL' => array( 326, 2, 0, 0 ),
+ 'QUARTILE' => array( 327, 2, 0, 0 ),
+ 'PERCENTILE' => array( 328, 2, 0, 0 ),
+ 'PERCENTRANK' => array( 329, -1, 0, 0 ),
+ 'MODE' => array( 330, -1, 2, 0 ),
+ 'TRIMMEAN' => array( 331, 2, 0, 0 ),
+ 'TINV' => array( 332, 2, 1, 0 ),
+ 'CONCATENATE' => array( 336, -1, 1, 0 ),
+ 'POWER' => array( 337, 2, 1, 0 ),
+ 'RADIANS' => array( 342, 1, 1, 0 ),
+ 'DEGREES' => array( 343, 1, 1, 0 ),
+ 'SUBTOTAL' => array( 344, -1, 0, 0 ),
+ 'SUMIF' => array( 345, -1, 0, 0 ),
+ 'COUNTIF' => array( 346, 2, 0, 0 ),
+ 'COUNTBLANK' => array( 347, 1, 0, 0 ),
+ 'ISPMT' => array( 350, 4, 1, 0 ),
+ 'DATEDIF' => array( 351, 3, 1, 0 ),
+ 'DATESTRING' => array( 352, 1, 1, 0 ),
+ 'NUMBERSTRING' => array( 353, 2, 1, 0 ),
+ 'ROMAN' => array( 354, -1, 1, 0 ),
+ 'GETPIVOTDATA' => array( 358, -1, 0, 0 ),
+ 'HYPERLINK' => array( 359, -1, 1, 0 ),
+ 'PHONETIC' => array( 360, 1, 0, 0 ),
+ 'AVERAGEA' => array( 361, -1, 0, 0 ),
+ 'MAXA' => array( 362, -1, 0, 0 ),
+ 'MINA' => array( 363, -1, 0, 0 ),
+ 'STDEVPA' => array( 364, -1, 0, 0 ),
+ 'VARPA' => array( 365, -1, 0, 0 ),
+ 'STDEVA' => array( 366, -1, 0, 0 ),
+ 'VARA' => array( 367, -1, 0, 0 ),
+ 'BAHTTEXT' => array( 368, 1, 0, 0 ),
+ );
+ }
+
+ /**
+ * Convert a token to the proper ptg value.
+ *
+ * @access private
+ * @param mixed $token The token to convert.
+ * @return mixed the converted token on success
+ */
+ function _convert($token)
+ {
+ if (preg_match("/\"([^\"]|\"\"){0,255}\"/", $token)) {
+ return $this->_convertString($token);
+
+ } elseif (is_numeric($token)) {
+ return $this->_convertNumber($token);
+
+ // match references like A1 or $A$1
+ } elseif (preg_match('/^\$?([A-Ia-i]?[A-Za-z])\$?(\d+)$/',$token)) {
+ return $this->_convertRef2d($token);
+
+ // match external references like Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1
+ } elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?[A-Ia-i]?[A-Za-z]\\$?(\d+)$/u",$token)) {
+ return $this->_convertRef3d($token);
+
+ // match external references like 'Sheet1'!A1 or 'Sheet1:Sheet2'!A1 or 'Sheet1'!$A$1 or 'Sheet1:Sheet2'!$A$1
+ } elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?(\d+)$/u",$token)) {
+ return $this->_convertRef3d($token);
+
+ // match ranges like A1:B2 or $A$1:$B$2
+ } elseif (preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)\:(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)$/', $token)) {
+ return $this->_convertRange2d($token);
+
+ // match external ranges like Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2
+ } elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)\:\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)$/u",$token)) {
+ return $this->_convertRange3d($token);
+
+ // match external ranges like 'Sheet1'!A1:B2 or 'Sheet1:Sheet2'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1:Sheet2'!$A$1:$B$2
+ } elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)\:\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)$/u",$token)) {
+ return $this->_convertRange3d($token);
+
+ // operators (including parentheses)
+ } elseif (isset($this->ptg[$token])) {
+ return pack("C", $this->ptg[$token]);
+
+ // match error codes
+ } elseif (preg_match("/^#[A-Z0\/]{3,5}[!?]{1}$/", $token) or $token == '#N/A') {
+ return $this->_convertError($token);
+
+ // commented so argument number can be processed correctly. See toReversePolish().
+ /*elseif (preg_match("/[A-Z0-9\xc0-\xdc\.]+/",$token))
+ {
+ return($this->_convertFunction($token,$this->_func_args));
+ }*/
+
+ // if it's an argument, ignore the token (the argument remains)
+ } elseif ($token == 'arg') {
+ return '';
+ }
+
+ // TODO: use real error codes
+ throw new PHPExcel_Writer_Exception("Unknown token $token");
+ }
+
+ /**
+ * Convert a number token to ptgInt or ptgNum
+ *
+ * @access private
+ * @param mixed $num an integer or double for conversion to its ptg value
+ */
+ function _convertNumber($num)
+ {
+ // Integer in the range 0..2**16-1
+ if ((preg_match("/^\d+$/", $num)) and ($num <= 65535)) {
+ return pack("Cv", $this->ptg['ptgInt'], $num);
+ } else { // A float
+ if (PHPExcel_Writer_Excel5_BIFFwriter::getByteOrder()) { // if it's Big Endian
+ $num = strrev($num);
+ }
+ return pack("Cd", $this->ptg['ptgNum'], $num);
+ }
+ }
+
+ /**
+ * Convert a string token to ptgStr
+ *
+ * @access private
+ * @param string $string A string for conversion to its ptg value.
+ * @return mixed the converted token on success
+ */
+ function _convertString($string)
+ {
+ // chop away beggining and ending quotes
+ $string = substr($string, 1, strlen($string) - 2);
+ if (strlen($string) > 255) {
+ throw new PHPExcel_Writer_Exception("String is too long");
+ }
+
+ return pack('C', $this->ptg['ptgStr']) . PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($string);
+ }
+
+ /**
+ * Convert a function to a ptgFunc or ptgFuncVarV depending on the number of
+ * args that it takes.
+ *
+ * @access private
+ * @param string $token The name of the function for convertion to ptg value.
+ * @param integer $num_args The number of arguments the function receives.
+ * @return string The packed ptg for the function
+ */
+ function _convertFunction($token, $num_args)
+ {
+ $args = $this->_functions[$token][1];
+// $volatile = $this->_functions[$token][3];
+
+ // Fixed number of args eg. TIME($i,$j,$k).
+ if ($args >= 0) {
+ return pack("Cv", $this->ptg['ptgFuncV'], $this->_functions[$token][0]);
+ }
+ // Variable number of args eg. SUM($i,$j,$k, ..).
+ if ($args == -1) {
+ return pack("CCv", $this->ptg['ptgFuncVarV'], $num_args, $this->_functions[$token][0]);
+ }
+ }
+
+ /**
+ * Convert an Excel range such as A1:D4 to a ptgRefV.
+ *
+ * @access private
+ * @param string $range An Excel range in the A1:A2
+ * @param int $class
+ */
+ function _convertRange2d($range, $class=0)
+ {
+
+ // TODO: possible class value 0,1,2 check Formula.pm
+ // Split the range into 2 cell refs
+ if (preg_match('/^(\$)?([A-Ia-i]?[A-Za-z])(\$)?(\d+)\:(\$)?([A-Ia-i]?[A-Za-z])(\$)?(\d+)$/', $range)) {
+ list($cell1, $cell2) = explode(':', $range);
+ } else {
+ // TODO: use real error codes
+ throw new PHPExcel_Writer_Exception("Unknown range separator");
+ }
+
+ // Convert the cell references
+ list($row1, $col1) = $this->_cellToPackedRowcol($cell1);
+ list($row2, $col2) = $this->_cellToPackedRowcol($cell2);
+
+ // The ptg value depends on the class of the ptg.
+ if ($class == 0) {
+ $ptgArea = pack("C", $this->ptg['ptgArea']);
+ } elseif ($class == 1) {
+ $ptgArea = pack("C", $this->ptg['ptgAreaV']);
+ } elseif ($class == 2) {
+ $ptgArea = pack("C", $this->ptg['ptgAreaA']);
+ } else {
+ // TODO: use real error codes
+ throw new PHPExcel_Writer_Exception("Unknown class $class");
+ }
+ return $ptgArea . $row1 . $row2 . $col1. $col2;
+ }
+
+ /**
+ * Convert an Excel 3d range such as "Sheet1!A1:D4" or "Sheet1:Sheet2!A1:D4" to
+ * a ptgArea3d.
+ *
+ * @access private
+ * @param string $token An Excel range in the Sheet1!A1:A2 format.
+ * @return mixed The packed ptgArea3d token on success.
+ */
+ function _convertRange3d($token)
+ {
+// $class = 0; // formulas like Sheet1!$A$1:$A$2 in list type data validation need this class (0x3B)
+
+ // Split the ref at the ! symbol
+ list($ext_ref, $range) = explode('!', $token);
+
+ // Convert the external reference part (different for BIFF8)
+ $ext_ref = $this->_getRefIndex($ext_ref);
+
+ // Split the range into 2 cell refs
+ list($cell1, $cell2) = explode(':', $range);
+
+ // Convert the cell references
+ if (preg_match("/^(\\$)?[A-Ia-i]?[A-Za-z](\\$)?(\d+)$/", $cell1)) {
+ list($row1, $col1) = $this->_cellToPackedRowcol($cell1);
+ list($row2, $col2) = $this->_cellToPackedRowcol($cell2);
+ } else { // It's a rows range (like 26:27)
+ list($row1, $col1, $row2, $col2) = $this->_rangeToPackedRange($cell1.':'.$cell2);
+ }
+
+ // The ptg value depends on the class of the ptg.
+// if ($class == 0) {
+ $ptgArea = pack("C", $this->ptg['ptgArea3d']);
+// } elseif ($class == 1) {
+// $ptgArea = pack("C", $this->ptg['ptgArea3dV']);
+// } elseif ($class == 2) {
+// $ptgArea = pack("C", $this->ptg['ptgArea3dA']);
+// } else {
+// throw new PHPExcel_Writer_Exception("Unknown class $class");
+// }
+
+ return $ptgArea . $ext_ref . $row1 . $row2 . $col1. $col2;
+ }
+
+ /**
+ * Convert an Excel reference such as A1, $B2, C$3 or $D$4 to a ptgRefV.
+ *
+ * @access private
+ * @param string $cell An Excel cell reference
+ * @return string The cell in packed() format with the corresponding ptg
+ */
+ function _convertRef2d($cell)
+ {
+// $class = 2; // as far as I know, this is magick.
+
+ // Convert the cell reference
+ $cell_array = $this->_cellToPackedRowcol($cell);
+ list($row, $col) = $cell_array;
+
+ // The ptg value depends on the class of the ptg.
+// if ($class == 0) {
+// $ptgRef = pack("C", $this->ptg['ptgRef']);
+// } elseif ($class == 1) {
+// $ptgRef = pack("C", $this->ptg['ptgRefV']);
+// } elseif ($class == 2) {
+ $ptgRef = pack("C", $this->ptg['ptgRefA']);
+// } else {
+// // TODO: use real error codes
+// throw new PHPExcel_Writer_Exception("Unknown class $class");
+// }
+ return $ptgRef.$row.$col;
+ }
+
+ /**
+ * Convert an Excel 3d reference such as "Sheet1!A1" or "Sheet1:Sheet2!A1" to a
+ * ptgRef3d.
+ *
+ * @access private
+ * @param string $cell An Excel cell reference
+ * @return mixed The packed ptgRef3d token on success.
+ */
+ function _convertRef3d($cell)
+ {
+// $class = 2; // as far as I know, this is magick.
+
+ // Split the ref at the ! symbol
+ list($ext_ref, $cell) = explode('!', $cell);
+
+ // Convert the external reference part (different for BIFF8)
+ $ext_ref = $this->_getRefIndex($ext_ref);
+
+ // Convert the cell reference part
+ list($row, $col) = $this->_cellToPackedRowcol($cell);
+
+ // The ptg value depends on the class of the ptg.
+// if ($class == 0) {
+// $ptgRef = pack("C", $this->ptg['ptgRef3d']);
+// } elseif ($class == 1) {
+// $ptgRef = pack("C", $this->ptg['ptgRef3dV']);
+// } elseif ($class == 2) {
+ $ptgRef = pack("C", $this->ptg['ptgRef3dA']);
+// } else {
+// throw new PHPExcel_Writer_Exception("Unknown class $class");
+// }
+
+ return $ptgRef . $ext_ref. $row . $col;
+ }
+
+ /**
+ * Convert an error code to a ptgErr
+ *
+ * @access private
+ * @param string $errorCode The error code for conversion to its ptg value
+ * @return string The error code ptgErr
+ */
+ function _convertError($errorCode)
+ {
+ switch ($errorCode) {
+ case '#NULL!': return pack("C", 0x00);
+ case '#DIV/0!': return pack("C", 0x07);
+ case '#VALUE!': return pack("C", 0x0F);
+ case '#REF!': return pack("C", 0x17);
+ case '#NAME?': return pack("C", 0x1D);
+ case '#NUM!': return pack("C", 0x24);
+ case '#N/A': return pack("C", 0x2A);
+ }
+ return pack("C", 0xFF);
+ }
+
+ /**
+ * Convert the sheet name part of an external reference, for example "Sheet1" or
+ * "Sheet1:Sheet2", to a packed structure.
+ *
+ * @access private
+ * @param string $ext_ref The name of the external reference
+ * @return string The reference index in packed() format
+ */
+ function _packExtRef($ext_ref)
+ {
+ $ext_ref = preg_replace("/^'/", '', $ext_ref); // Remove leading ' if any.
+ $ext_ref = preg_replace("/'$/", '', $ext_ref); // Remove trailing ' if any.
+
+ // Check if there is a sheet range eg., Sheet1:Sheet2.
+ if (preg_match("/:/", $ext_ref)) {
+ list($sheet_name1, $sheet_name2) = explode(':', $ext_ref);
+
+ $sheet1 = $this->_getSheetIndex($sheet_name1);
+ if ($sheet1 == -1) {
+ throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name1 in formula");
+ }
+ $sheet2 = $this->_getSheetIndex($sheet_name2);
+ if ($sheet2 == -1) {
+ throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name2 in formula");
+ }
+
+ // Reverse max and min sheet numbers if necessary
+ if ($sheet1 > $sheet2) {
+ list($sheet1, $sheet2) = array($sheet2, $sheet1);
+ }
+ } else { // Single sheet name only.
+ $sheet1 = $this->_getSheetIndex($ext_ref);
+ if ($sheet1 == -1) {
+ throw new PHPExcel_Writer_Exception("Unknown sheet name $ext_ref in formula");
+ }
+ $sheet2 = $sheet1;
+ }
+
+ // References are stored relative to 0xFFFF.
+ $offset = -1 - $sheet1;
+
+ return pack('vdvv', $offset, 0x00, $sheet1, $sheet2);
+ }
+
+ /**
+ * Look up the REF index that corresponds to an external sheet name
+ * (or range). If it doesn't exist yet add it to the workbook's references
+ * array. It assumes all sheet names given must exist.
+ *
+ * @access private
+ * @param string $ext_ref The name of the external reference
+ * @return mixed The reference index in packed() format on success
+ */
+ function _getRefIndex($ext_ref)
+ {
+ $ext_ref = preg_replace("/^'/", '', $ext_ref); // Remove leading ' if any.
+ $ext_ref = preg_replace("/'$/", '', $ext_ref); // Remove trailing ' if any.
+ $ext_ref = str_replace('\'\'', '\'', $ext_ref); // Replace escaped '' with '
+
+ // Check if there is a sheet range eg., Sheet1:Sheet2.
+ if (preg_match("/:/", $ext_ref)) {
+ list($sheet_name1, $sheet_name2) = explode(':', $ext_ref);
+
+ $sheet1 = $this->_getSheetIndex($sheet_name1);
+ if ($sheet1 == -1) {
+ throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name1 in formula");
+ }
+ $sheet2 = $this->_getSheetIndex($sheet_name2);
+ if ($sheet2 == -1) {
+ throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name2 in formula");
+ }
+
+ // Reverse max and min sheet numbers if necessary
+ if ($sheet1 > $sheet2) {
+ list($sheet1, $sheet2) = array($sheet2, $sheet1);
+ }
+ } else { // Single sheet name only.
+ $sheet1 = $this->_getSheetIndex($ext_ref);
+ if ($sheet1 == -1) {
+ throw new PHPExcel_Writer_Exception("Unknown sheet name $ext_ref in formula");
+ }
+ $sheet2 = $sheet1;
+ }
+
+ // assume all references belong to this document
+ $supbook_index = 0x00;
+ $ref = pack('vvv', $supbook_index, $sheet1, $sheet2);
+ $total_references = count($this->_references);
+ $index = -1;
+ for ($i = 0; $i < $total_references; ++$i) {
+ if ($ref == $this->_references[$i]) {
+ $index = $i;
+ break;
+ }
+ }
+ // if REF was not found add it to references array
+ if ($index == -1) {
+ $this->_references[$total_references] = $ref;
+ $index = $total_references;
+ }
+
+ return pack('v', $index);
+ }
+
+ /**
+ * Look up the index that corresponds to an external sheet name. The hash of
+ * sheet names is updated by the addworksheet() method of the
+ * PHPExcel_Writer_Excel5_Workbook class.
+ *
+ * @access private
+ * @param string $sheet_name Sheet name
+ * @return integer The sheet index, -1 if the sheet was not found
+ */
+ function _getSheetIndex($sheet_name)
+ {
+ if (!isset($this->_ext_sheets[$sheet_name])) {
+ return -1;
+ } else {
+ return $this->_ext_sheets[$sheet_name];
+ }
+ }
+
+ /**
+ * This method is used to update the array of sheet names. It is
+ * called by the addWorksheet() method of the
+ * PHPExcel_Writer_Excel5_Workbook class.
+ *
+ * @access public
+ * @see PHPExcel_Writer_Excel5_Workbook::addWorksheet()
+ * @param string $name The name of the worksheet being added
+ * @param integer $index The index of the worksheet being added
+ */
+ function setExtSheet($name, $index)
+ {
+ $this->_ext_sheets[$name] = $index;
+ }
+
+ /**
+ * pack() row and column into the required 3 or 4 byte format.
+ *
+ * @access private
+ * @param string $cell The Excel cell reference to be packed
+ * @return array Array containing the row and column in packed() format
+ */
+ function _cellToPackedRowcol($cell)
+ {
+ $cell = strtoupper($cell);
+ list($row, $col, $row_rel, $col_rel) = $this->_cellToRowcol($cell);
+ if ($col >= 256) {
+ throw new PHPExcel_Writer_Exception("Column in: $cell greater than 255");
+ }
+ if ($row >= 65536) {
+ throw new PHPExcel_Writer_Exception("Row in: $cell greater than 65536 ");
+ }
+
+ // Set the high bits to indicate if row or col are relative.
+ $col |= $col_rel << 14;
+ $col |= $row_rel << 15;
+ $col = pack('v', $col);
+
+ $row = pack('v', $row);
+
+ return array($row, $col);
+ }
+
+ /**
+ * pack() row range into the required 3 or 4 byte format.
+ * Just using maximum col/rows, which is probably not the correct solution
+ *
+ * @access private
+ * @param string $range The Excel range to be packed
+ * @return array Array containing (row1,col1,row2,col2) in packed() format
+ */
+ function _rangeToPackedRange($range)
+ {
+ preg_match('/(\$)?(\d+)\:(\$)?(\d+)/', $range, $match);
+ // return absolute rows if there is a $ in the ref
+ $row1_rel = empty($match[1]) ? 1 : 0;
+ $row1 = $match[2];
+ $row2_rel = empty($match[3]) ? 1 : 0;
+ $row2 = $match[4];
+ // Convert 1-index to zero-index
+ --$row1;
+ --$row2;
+ // Trick poor inocent Excel
+ $col1 = 0;
+ $col2 = 65535; // FIXME: maximum possible value for Excel 5 (change this!!!)
+
+ // FIXME: this changes for BIFF8
+ if (($row1 >= 65536) or ($row2 >= 65536)) {
+ throw new PHPExcel_Writer_Exception("Row in: $range greater than 65536 ");
+ }
+
+ // Set the high bits to indicate if rows are relative.
+ $col1 |= $row1_rel << 15;
+ $col2 |= $row2_rel << 15;
+ $col1 = pack('v', $col1);
+ $col2 = pack('v', $col2);
+
+ $row1 = pack('v', $row1);
+ $row2 = pack('v', $row2);
+
+ return array($row1, $col1, $row2, $col2);
+ }
+
+ /**
+ * Convert an Excel cell reference such as A1 or $B2 or C$3 or $D$4 to a zero
+ * indexed row and column number. Also returns two (0,1) values to indicate
+ * whether the row or column are relative references.
+ *
+ * @access private
+ * @param string $cell The Excel cell reference in A1 format.
+ * @return array
+ */
+ function _cellToRowcol($cell)
+ {
+ preg_match('/(\$)?([A-I]?[A-Z])(\$)?(\d+)/',$cell,$match);
+ // return absolute column if there is a $ in the ref
+ $col_rel = empty($match[1]) ? 1 : 0;
+ $col_ref = $match[2];
+ $row_rel = empty($match[3]) ? 1 : 0;
+ $row = $match[4];
+
+ // Convert base26 column string to a number.
+ $expn = strlen($col_ref) - 1;
+ $col = 0;
+ $col_ref_length = strlen($col_ref);
+ for ($i = 0; $i < $col_ref_length; ++$i) {
+ $col += (ord($col_ref{$i}) - 64) * pow(26, $expn);
+ --$expn;
+ }
+
+ // Convert 1-index to zero-index
+ --$row;
+ --$col;
+
+ return array($row, $col, $row_rel, $col_rel);
+ }
+
+ /**
+ * Advance to the next valid token.
+ *
+ * @access private
+ */
+ function _advance()
+ {
+ $i = $this->_current_char;
+ $formula_length = strlen($this->_formula);
+ // eat up white spaces
+ if ($i < $formula_length) {
+ while ($this->_formula{$i} == " ") {
+ ++$i;
+ }
+
+ if ($i < ($formula_length - 1)) {
+ $this->_lookahead = $this->_formula{$i+1};
+ }
+ $token = '';
+ }
+
+ while ($i < $formula_length) {
+ $token .= $this->_formula{$i};
+
+ if ($i < ($formula_length - 1)) {
+ $this->_lookahead = $this->_formula{$i+1};
+ } else {
+ $this->_lookahead = '';
+ }
+
+ if ($this->_match($token) != '') {
+ //if ($i < strlen($this->_formula) - 1) {
+ // $this->_lookahead = $this->_formula{$i+1};
+ //}
+ $this->_current_char = $i + 1;
+ $this->_current_token = $token;
+ return 1;
+ }
+
+ if ($i < ($formula_length - 2)) {
+ $this->_lookahead = $this->_formula{$i+2};
+ } else { // if we run out of characters _lookahead becomes empty
+ $this->_lookahead = '';
+ }
+ ++$i;
+ }
+ //die("Lexical error ".$this->_current_char);
+ }
+
+ /**
+ * Checks if it's a valid token.
+ *
+ * @access private
+ * @param mixed $token The token to check.
+ * @return mixed The checked token or false on failure
+ */
+ function _match($token)
+ {
+ switch($token) {
+ case "+":
+ case "-":
+ case "*":
+ case "/":
+ case "(":
+ case ")":
+ case ",":
+ case ";":
+ case ">=":
+ case "<=":
+ case "=":
+ case "<>":
+ case "^":
+ case "&":
+ case "%":
+ return $token;
+ break;
+ case ">":
+ if ($this->_lookahead == '=') { // it's a GE token
+ break;
+ }
+ return $token;
+ break;
+ case "<":
+ // it's a LE or a NE token
+ if (($this->_lookahead == '=') or ($this->_lookahead == '>')) {
+ break;
+ }
+ return $token;
+ break;
+ default:
+ // if it's a reference A1 or $A$1 or $A1 or A$1
+ if (preg_match('/^\$?[A-Ia-i]?[A-Za-z]\$?[0-9]+$/',$token) and
+ !preg_match("/[0-9]/",$this->_lookahead) and
+ ($this->_lookahead != ':') and ($this->_lookahead != '.') and
+ ($this->_lookahead != '!'))
+ {
+ return $token;
+ }
+ // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1)
+ elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$token) and
+ !preg_match("/[0-9]/",$this->_lookahead) and
+ ($this->_lookahead != ':') and ($this->_lookahead != '.'))
+ {
+ return $token;
+ }
+ // If it's an external reference ('Sheet1'!A1 or 'Sheet1:Sheet2'!A1 or 'Sheet1'!$A$1 or 'Sheet1:Sheet2'!$A$1)
+ elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$token) and
+ !preg_match("/[0-9]/",$this->_lookahead) and
+ ($this->_lookahead != ':') and ($this->_lookahead != '.'))
+ {
+ return $token;
+ }
+ // if it's a range A1:A2 or $A$1:$A$2
+ elseif (preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/', $token) and
+ !preg_match("/[0-9]/",$this->_lookahead))
+ {
+ return $token;
+ }
+ // If it's an external range like Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2
+ elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$token) and
+ !preg_match("/[0-9]/",$this->_lookahead))
+ {
+ return $token;
+ }
+ // If it's an external range like 'Sheet1'!A1:B2 or 'Sheet1:Sheet2'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1:Sheet2'!$A$1:$B$2
+ elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$token) and
+ !preg_match("/[0-9]/",$this->_lookahead))
+ {
+ return $token;
+ }
+ // If it's a number (check that it's not a sheet name or range)
+ elseif (is_numeric($token) and
+ (!is_numeric($token.$this->_lookahead) or ($this->_lookahead == '')) and
+ ($this->_lookahead != '!') and ($this->_lookahead != ':'))
+ {
+ return $token;
+ }
+ // If it's a string (of maximum 255 characters)
+ elseif (preg_match("/\"([^\"]|\"\"){0,255}\"/",$token) and $this->_lookahead != '"' and (substr_count($token, '"')%2 == 0))
+ {
+ return $token;
+ }
+ // If it's an error code
+ elseif (preg_match("/^#[A-Z0\/]{3,5}[!?]{1}$/", $token) or $token == '#N/A')
+ {
+ return $token;
+ }
+ // if it's a function call
+ elseif (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/i",$token) and ($this->_lookahead == "("))
+ {
+ return $token;
+ }
+ // It's an argument of some description (e.g. a named range),
+ // precise nature yet to be determined
+ elseif(substr($token,-1) == ')') {
+ return $token;
+ }
+ return '';
+ }
+ }
+
+ /**
+ * The parsing method. It parses a formula.
+ *
+ * @access public
+ * @param string $formula The formula to parse, without the initial equal
+ * sign (=).
+ * @return mixed true on success
+ */
+ function parse($formula)
+ {
+ $this->_current_char = 0;
+ $this->_formula = $formula;
+ $this->_lookahead = isset($formula{1}) ? $formula{1} : '';
+ $this->_advance();
+ $this->_parse_tree = $this->_condition();
+ return true;
+ }
+
+ /**
+ * It parses a condition. It assumes the following rule:
+ * Cond -> Expr [(">" | "<") Expr]
+ *
+ * @access private
+ * @return mixed The parsed ptg'd tree on success
+ */
+ function _condition()
+ {
+ $result = $this->_expression();
+ if ($this->_current_token == "<") {
+ $this->_advance();
+ $result2 = $this->_expression();
+ $result = $this->_createTree('ptgLT', $result, $result2);
+ } elseif ($this->_current_token == ">") {
+ $this->_advance();
+ $result2 = $this->_expression();
+ $result = $this->_createTree('ptgGT', $result, $result2);
+ } elseif ($this->_current_token == "<=") {
+ $this->_advance();
+ $result2 = $this->_expression();
+ $result = $this->_createTree('ptgLE', $result, $result2);
+ } elseif ($this->_current_token == ">=") {
+ $this->_advance();
+ $result2 = $this->_expression();
+ $result = $this->_createTree('ptgGE', $result, $result2);
+ } elseif ($this->_current_token == "=") {
+ $this->_advance();
+ $result2 = $this->_expression();
+ $result = $this->_createTree('ptgEQ', $result, $result2);
+ } elseif ($this->_current_token == "<>") {
+ $this->_advance();
+ $result2 = $this->_expression();
+ $result = $this->_createTree('ptgNE', $result, $result2);
+ } elseif ($this->_current_token == "&") {
+ $this->_advance();
+ $result2 = $this->_expression();
+ $result = $this->_createTree('ptgConcat', $result, $result2);
+ }
+ return $result;
+ }
+
+ /**
+ * It parses a expression. It assumes the following rule:
+ * Expr -> Term [("+" | "-") Term]
+ * -> "string"
+ * -> "-" Term : Negative value
+ * -> "+" Term : Positive value
+ * -> Error code
+ *
+ * @access private
+ * @return mixed The parsed ptg'd tree on success
+ */
+ function _expression()
+ {
+ // If it's a string return a string node
+ if (preg_match("/\"([^\"]|\"\"){0,255}\"/", $this->_current_token)) {
+ $tmp = str_replace('""', '"', $this->_current_token);
+ if (($tmp == '"') || ($tmp == '')) $tmp = '""'; // Trap for "" that has been used for an empty string
+ $result = $this->_createTree($tmp, '', '');
+ $this->_advance();
+ return $result;
+ // If it's an error code
+ } elseif (preg_match("/^#[A-Z0\/]{3,5}[!?]{1}$/", $this->_current_token) or $this->_current_token == '#N/A'){
+ $result = $this->_createTree($this->_current_token, 'ptgErr', '');
+ $this->_advance();
+ return $result;
+ // If it's a negative value
+ } elseif ($this->_current_token == "-") {
+ // catch "-" Term
+ $this->_advance();
+ $result2 = $this->_expression();
+ $result = $this->_createTree('ptgUminus', $result2, '');
+ return $result;
+ // If it's a positive value
+ } elseif ($this->_current_token == "+") {
+ // catch "+" Term
+ $this->_advance();
+ $result2 = $this->_expression();
+ $result = $this->_createTree('ptgUplus', $result2, '');
+ return $result;
+ }
+ $result = $this->_term();
+ while (($this->_current_token == "+") or
+ ($this->_current_token == "-") or
+ ($this->_current_token == "^")) {
+ /**/
+ if ($this->_current_token == "+") {
+ $this->_advance();
+ $result2 = $this->_term();
+ $result = $this->_createTree('ptgAdd', $result, $result2);
+ } elseif ($this->_current_token == "-") {
+ $this->_advance();
+ $result2 = $this->_term();
+ $result = $this->_createTree('ptgSub', $result, $result2);
+ } else {
+ $this->_advance();
+ $result2 = $this->_term();
+ $result = $this->_createTree('ptgPower', $result, $result2);
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * This function just introduces a ptgParen element in the tree, so that Excel
+ * doesn't get confused when working with a parenthesized formula afterwards.
+ *
+ * @access private
+ * @see _fact()
+ * @return array The parsed ptg'd tree
+ */
+ function _parenthesizedExpression()
+ {
+ $result = $this->_createTree('ptgParen', $this->_expression(), '');
+ return $result;
+ }
+
+ /**
+ * It parses a term. It assumes the following rule:
+ * Term -> Fact [("*" | "/") Fact]
+ *
+ * @access private
+ * @return mixed The parsed ptg'd tree on success
+ */
+ function _term()
+ {
+ $result = $this->_fact();
+ while (($this->_current_token == "*") or
+ ($this->_current_token == "/")) {
+ /**/
+ if ($this->_current_token == "*") {
+ $this->_advance();
+ $result2 = $this->_fact();
+ $result = $this->_createTree('ptgMul', $result, $result2);
+ } else {
+ $this->_advance();
+ $result2 = $this->_fact();
+ $result = $this->_createTree('ptgDiv', $result, $result2);
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * It parses a factor. It assumes the following rule:
+ * Fact -> ( Expr )
+ * | CellRef
+ * | CellRange
+ * | Number
+ * | Function
+ *
+ * @access private
+ * @return mixed The parsed ptg'd tree on success
+ */
+ function _fact()
+ {
+ if ($this->_current_token == "(") {
+ $this->_advance(); // eat the "("
+ $result = $this->_parenthesizedExpression();
+ if ($this->_current_token != ")") {
+ throw new PHPExcel_Writer_Exception("')' token expected.");
+ }
+ $this->_advance(); // eat the ")"
+ return $result;
+ }
+ // if it's a reference
+ if (preg_match('/^\$?[A-Ia-i]?[A-Za-z]\$?[0-9]+$/',$this->_current_token))
+ {
+ $result = $this->_createTree($this->_current_token, '', '');
+ $this->_advance();
+ return $result;
+ }
+ // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1)
+ elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$this->_current_token))
+ {
+ $result = $this->_createTree($this->_current_token, '', '');
+ $this->_advance();
+ return $result;
+ }
+ // If it's an external reference ('Sheet1'!A1 or 'Sheet1:Sheet2'!A1 or 'Sheet1'!$A$1 or 'Sheet1:Sheet2'!$A$1)
+ elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$this->_current_token))
+ {
+ $result = $this->_createTree($this->_current_token, '', '');
+ $this->_advance();
+ return $result;
+ }
+ // if it's a range A1:B2 or $A$1:$B$2
+ elseif (preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/',$this->_current_token) or
+ preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/',$this->_current_token))
+ {
+ // must be an error?
+ $result = $this->_createTree($this->_current_token, '', '');
+ $this->_advance();
+ return $result;
+ }
+ // If it's an external range (Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2)
+ elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$this->_current_token))
+ {
+ // must be an error?
+ //$result = $this->_current_token;
+ $result = $this->_createTree($this->_current_token, '', '');
+ $this->_advance();
+ return $result;
+ }
+ // If it's an external range ('Sheet1'!A1:B2 or 'Sheet1'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1'!$A$1:$B$2)
+ elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$this->_current_token))
+ {
+ // must be an error?
+ //$result = $this->_current_token;
+ $result = $this->_createTree($this->_current_token, '', '');
+ $this->_advance();
+ return $result;
+ }
+ // If it's a number or a percent
+ elseif (is_numeric($this->_current_token))
+ {
+ if($this->_lookahead == '%'){
+ $result = $this->_createTree('ptgPercent', $this->_current_token, '');
+ } else {
+ $result = $this->_createTree($this->_current_token, '', '');
+ }
+ $this->_advance();
+ return $result;
+ }
+ // if it's a function call
+ elseif (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/i",$this->_current_token))
+ {
+ $result = $this->_func();
+ return $result;
+ }
+ throw new PHPExcel_Writer_Exception("Syntax error: ".$this->_current_token.
+ ", lookahead: ".$this->_lookahead.
+ ", current char: ".$this->_current_char);
+ }
+
+ /**
+ * It parses a function call. It assumes the following rule:
+ * Func -> ( Expr [,Expr]* )
+ *
+ * @access private
+ * @return mixed The parsed ptg'd tree on success
+ */
+ function _func()
+ {
+ $num_args = 0; // number of arguments received
+ $function = strtoupper($this->_current_token);
+ $result = ''; // initialize result
+ $this->_advance();
+ $this->_advance(); // eat the "("
+ while ($this->_current_token != ')') {
+ /**/
+ if ($num_args > 0) {
+ if ($this->_current_token == "," or
+ $this->_current_token == ";")
+ {
+ $this->_advance(); // eat the "," or ";"
+ } else {
+ throw new PHPExcel_Writer_Exception("Syntax error: comma expected in ".
+ "function $function, arg #{$num_args}");
+ }
+ $result2 = $this->_condition();
+ $result = $this->_createTree('arg', $result, $result2);
+ } else { // first argument
+ $result2 = $this->_condition();
+ $result = $this->_createTree('arg', '', $result2);
+ }
+ ++$num_args;
+ }
+ if (!isset($this->_functions[$function])) {
+ throw new PHPExcel_Writer_Exception("Function $function() doesn't exist");
+ }
+ $args = $this->_functions[$function][1];
+ // If fixed number of args eg. TIME($i,$j,$k). Check that the number of args is valid.
+ if (($args >= 0) and ($args != $num_args)) {
+ throw new PHPExcel_Writer_Exception("Incorrect number of arguments in function $function() ");
+ }
+
+ $result = $this->_createTree($function, $result, $num_args);
+ $this->_advance(); // eat the ")"
+ return $result;
+ }
+
+ /**
+ * Creates a tree. In fact an array which may have one or two arrays (sub-trees)
+ * as elements.
+ *
+ * @access private
+ * @param mixed $value The value of this node.
+ * @param mixed $left The left array (sub-tree) or a final node.
+ * @param mixed $right The right array (sub-tree) or a final node.
+ * @return array A tree
+ */
+ function _createTree($value, $left, $right)
+ {
+ return array('value' => $value, 'left' => $left, 'right' => $right);
+ }
+
+ /**
+ * Builds a string containing the tree in reverse polish notation (What you
+ * would use in a HP calculator stack).
+ * The following tree:
+ *
+ * +
+ * / \
+ * 2 3
+ *
+ * produces: "23+"
+ *
+ * The following tree:
+ *
+ * +
+ * / \
+ * 3 *
+ * / \
+ * 6 A1
+ *
+ * produces: "36A1*+"
+ *
+ * In fact all operands, functions, references, etc... are written as ptg's
+ *
+ * @access public
+ * @param array $tree The optional tree to convert.
+ * @return string The tree in reverse polish notation
+ */
+ function toReversePolish($tree = array())
+ {
+ $polish = ""; // the string we are going to return
+ if (empty($tree)) { // If it's the first call use _parse_tree
+ $tree = $this->_parse_tree;
+ }
+
+ if (is_array($tree['left'])) {
+ $converted_tree = $this->toReversePolish($tree['left']);
+ $polish .= $converted_tree;
+ } elseif ($tree['left'] != '') { // It's a final node
+ $converted_tree = $this->_convert($tree['left']);
+ $polish .= $converted_tree;
+ }
+ if (is_array($tree['right'])) {
+ $converted_tree = $this->toReversePolish($tree['right']);
+ $polish .= $converted_tree;
+ } elseif ($tree['right'] != '') { // It's a final node
+ $converted_tree = $this->_convert($tree['right']);
+ $polish .= $converted_tree;
+ }
+ // if it's a function convert it here (so we can set it's arguments)
+ if (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/",$tree['value']) and
+ !preg_match('/^([A-Ia-i]?[A-Za-z])(\d+)$/',$tree['value']) and
+ !preg_match("/^[A-Ia-i]?[A-Za-z](\d+)\.\.[A-Ia-i]?[A-Za-z](\d+)$/",$tree['value']) and
+ !is_numeric($tree['value']) and
+ !isset($this->ptg[$tree['value']]))
+ {
+ // left subtree for a function is always an array.
+ if ($tree['left'] != '') {
+ $left_tree = $this->toReversePolish($tree['left']);
+ } else {
+ $left_tree = '';
+ }
+ // add it's left subtree and return.
+ return $left_tree.$this->_convertFunction($tree['value'], $tree['right']);
+ } else {
+ $converted_tree = $this->_convert($tree['value']);
+ }
+ $polish .= $converted_tree;
+ return $polish;
+ }
+
+}
diff --git a/framework/library/phpexcel/PHPExcel/Writer/OpenDocument.php b/framework/library/phpexcel/PHPExcel/Writer/OpenDocument.php
new file mode 100644
index 0000000..912ba9d
--- /dev/null
+++ b/framework/library/phpexcel/PHPExcel/Writer/OpenDocument.php
@@ -0,0 +1,190 @@
+setPHPExcel($pPHPExcel);
+
+ $writerPartsArray = array(
+ 'content' => 'PHPExcel_Writer_OpenDocument_Content',
+ 'meta' => 'PHPExcel_Writer_OpenDocument_Meta',
+ 'meta_inf' => 'PHPExcel_Writer_OpenDocument_MetaInf',
+ 'mimetype' => 'PHPExcel_Writer_OpenDocument_Mimetype',
+ 'settings' => 'PHPExcel_Writer_OpenDocument_Settings',
+ 'styles' => 'PHPExcel_Writer_OpenDocument_Styles',
+ 'thumbnails' => 'PHPExcel_Writer_OpenDocument_Thumbnails'
+ );
+
+ foreach ($writerPartsArray as $writer => $class) {
+ $this->writerParts[$writer] = new $class($this);
+ }
+ }
+
+ /**
+ * Get writer part
+ *
+ * @param string $pPartName Writer part name
+ * @return PHPExcel_Writer_Excel2007_WriterPart
+ */
+ public function getWriterPart($pPartName = '')
+ {
+ if ($pPartName != '' && isset($this->writerParts[strtolower($pPartName)])) {
+ return $this->writerParts[strtolower($pPartName)];
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Save PHPExcel to file
+ *
+ * @param string $pFilename
+ * @throws PHPExcel_Writer_Exception
+ */
+ public function save($pFilename = null)
+ {
+ if (!$this->spreadSheet) {
+ throw new PHPExcel_Writer_Exception('PHPExcel object unassigned.');
+ }
+
+ // garbage collect
+ $this->spreadSheet->garbageCollect();
+
+ // If $pFilename is php://output or php://stdout, make it a temporary file...
+ $originalFilename = $pFilename;
+ if (strtolower($pFilename) == 'php://output' || strtolower($pFilename) == 'php://stdout') {
+ $pFilename = @tempnam(PHPExcel_Shared_File::sys_get_temp_dir(), 'phpxltmp');
+ if ($pFilename == '') {
+ $pFilename = $originalFilename;
+ }
+ }
+
+ $objZip = $this->createZip($pFilename);
+
+ $objZip->addFromString('META-INF/manifest.xml', $this->getWriterPart('meta_inf')->writeManifest());
+ $objZip->addFromString('Thumbnails/thumbnail.png', $this->getWriterPart('thumbnails')->writeThumbnail());
+ $objZip->addFromString('content.xml', $this->getWriterPart('content')->write());
+ $objZip->addFromString('meta.xml', $this->getWriterPart('meta')->write());
+ $objZip->addFromString('mimetype', $this->getWriterPart('mimetype')->write());
+ $objZip->addFromString('settings.xml', $this->getWriterPart('settings')->write());
+ $objZip->addFromString('styles.xml', $this->getWriterPart('styles')->write());
+
+ // Close file
+ if ($objZip->close() === false) {
+ throw new PHPExcel_Writer_Exception("Could not close zip file $pFilename.");
+ }
+
+ // If a temporary file was used, copy it to the correct file stream
+ if ($originalFilename != $pFilename) {
+ if (copy($pFilename, $originalFilename) === false) {
+ throw new PHPExcel_Writer_Exception("Could not copy temporary zip file $pFilename to $originalFilename.");
+ }
+ @unlink($pFilename);
+ }
+ }
+
+ /**
+ * Create zip object
+ *
+ * @param string $pFilename
+ * @throws PHPExcel_Writer_Exception
+ * @return ZipArchive
+ */
+ private function createZip($pFilename)
+ {
+ // Create new ZIP file and open it for writing
+ $zipClass = PHPExcel_Settings::getZipClass();
+ $objZip = new $zipClass();
+
+ // Retrieve OVERWRITE and CREATE constants from the instantiated zip class
+ // This method of accessing constant values from a dynamic class should work with all appropriate versions of PHP
+ $ro = new ReflectionObject($objZip);
+ $zipOverWrite = $ro->getConstant('OVERWRITE');
+ $zipCreate = $ro->getConstant('CREATE');
+
+ if (file_exists($pFilename)) {
+ unlink($pFilename);
+ }
+ // Try opening the ZIP file
+ if ($objZip->open($pFilename, $zipOverWrite) !== true) {
+ if ($objZip->open($pFilename, $zipCreate) !== true) {
+ throw new PHPExcel_Writer_Exception("Could not open $pFilename for writing.");
+ }
+ }
+
+ return $objZip;
+ }
+
+ /**
+ * Get PHPExcel object
+ *
+ * @return PHPExcel
+ * @throws PHPExcel_Writer_Exception
+ */
+ public function getPHPExcel()
+ {
+ if ($this->spreadSheet !== null) {
+ return $this->spreadSheet;
+ } else {
+ throw new PHPExcel_Writer_Exception('No PHPExcel assigned.');
+ }
+ }
+
+ /**
+ * Set PHPExcel object
+ *
+ * @param PHPExcel $pPHPExcel PHPExcel object
+ * @throws PHPExcel_Writer_Exception
+ * @return PHPExcel_Writer_Excel2007
+ */
+ public function setPHPExcel(PHPExcel $pPHPExcel = null)
+ {
+ $this->spreadSheet = $pPHPExcel;
+ return $this;
+ }
+}
diff --git a/framework/library/phpexcel/PHPExcel/Writer/PDF.php b/framework/library/phpexcel/PHPExcel/Writer/PDF.php
new file mode 100644
index 0000000..ed31195
--- /dev/null
+++ b/framework/library/phpexcel/PHPExcel/Writer/PDF.php
@@ -0,0 +1,90 @@
+_renderer = new $rendererName($phpExcel);
+ }
+
+
+ /**
+ * Magic method to handle direct calls to the configured PDF renderer wrapper class.
+ *
+ * @param string $name Renderer library method name
+ * @param mixed[] $arguments Array of arguments to pass to the renderer method
+ * @return mixed Returned data from the PDF renderer wrapper method
+ */
+ public function __call($name, $arguments)
+ {
+ if ($this->_renderer === NULL) {
+ throw new PHPExcel_Writer_Exception("PDF Rendering library has not been defined.");
+ }
+
+ return call_user_func_array(array($this->_renderer, $name), $arguments);
+ }
+
+}
diff --git a/web/common/permission.inc.php b/web/common/permission.inc.php
new file mode 100644
index 0000000..7c77b29
--- /dev/null
+++ b/web/common/permission.inc.php
@@ -0,0 +1,943 @@
+
+ array (
+ 'default' => '',
+ 'direct' =>
+ array (
+ 0 => 'auth',
+ 1 => 'welcome',
+ ),
+ 'vice_founder' =>
+ array (
+ 0 => 'account*',
+ ),
+ 'owner' =>
+ array (
+ 0 => 'account*',
+ ),
+ 'manager' =>
+ array (
+ 0 => 'common-info',
+ 1 => 'display',
+ 2 => 'manage',
+ 3 => 'post-step',
+ 4 => 'post-user',
+ 5 => 'post',
+ 6 => 'create',
+ ),
+ 'operator' =>
+ array (
+ 0 => 'common-info',
+ 1 => 'display',
+ 2 => 'manage',
+ 3 => 'post-step',
+ 4 => 'create',
+ ),
+ 'clerk' =>
+ array (
+ 0 => 'display',
+ ),
+ 'unbind_user' =>
+ array (
+ ),
+ ),
+ 'advertisement' =>
+ array (
+ 'default' => '',
+ 'direct' =>
+ array (
+ ),
+ 'vice_founder' =>
+ array (
+ ),
+ 'owner' =>
+ array (
+ ),
+ 'manager' =>
+ array (
+ ),
+ 'operator' =>
+ array (
+ ),
+ 'clerk' =>
+ array (
+ ),
+ 'unbind_user' =>
+ array (
+ ),
+ ),
+ 'article' =>
+ array (
+ 'default' => '',
+ 'direct' =>
+ array (
+ 0 => 'notice-show',
+ 1 => 'news-show',
+ ),
+ 'vice_founder' =>
+ array (
+ ),
+ 'owner' =>
+ array (
+ ),
+ 'manager' =>
+ array (
+ ),
+ 'operator' =>
+ array (
+ ),
+ 'clerk' =>
+ array (
+ ),
+ 'unbind_user' =>
+ array (
+ ),
+ ),
+ 'message' =>
+ array (
+ 'default' => '',
+ 'direct' =>
+ array (
+ ),
+ 'vice_founder' =>
+ array (
+ 0 => 'notice',
+ ),
+ 'owner' =>
+ array (
+ 0 => 'notice',
+ ),
+ 'manager' =>
+ array (
+ 0 => 'notice',
+ ),
+ 'operator' =>
+ array (
+ 0 => 'notice',
+ ),
+ 'clerk' =>
+ array (
+ 0 => 'notice',
+ ),
+ 'unbind_user' =>
+ array (
+ 0 => 'notice',
+ ),
+ ),
+ 'cloud' =>
+ array (
+ 'default' => 'touch',
+ 'direct' =>
+ array (
+ 0 => 'touch',
+ 1 => 'dock',
+ ),
+ 'vice_founder' =>
+ array (
+ ),
+ 'owner' =>
+ array (
+ ),
+ 'manager' =>
+ array (
+ ),
+ 'operator' =>
+ array (
+ ),
+ 'clerk' =>
+ array (
+ ),
+ 'unbind_user' =>
+ array (
+ ),
+ ),
+ 'cron' =>
+ array (
+ 'default' => '',
+ 'direct' =>
+ array (
+ 0 => 'entry',
+ ),
+ 'vice_founder' =>
+ array (
+ ),
+ 'owner' =>
+ array (
+ ),
+ 'manager' =>
+ array (
+ ),
+ 'operator' =>
+ array (
+ ),
+ 'clerk' =>
+ array (
+ ),
+ 'unbind_user' =>
+ array (
+ ),
+ ),
+ 'founder' =>
+ array (
+ 'default' => '',
+ 'direct' =>
+ array (
+ ),
+ 'vice_founder' =>
+ array (
+ ),
+ 'owner' =>
+ array (
+ ),
+ 'manager' =>
+ array (
+ ),
+ 'operator' =>
+ array (
+ ),
+ 'clerk' =>
+ array (
+ ),
+ 'unbind_user' =>
+ array (
+ ),
+ ),
+ 'help' =>
+ array (
+ 'default' => '',
+ 'direct' =>
+ array (
+ ),
+ 'vice_founder' =>
+ array (
+ 0 => 'help*',
+ ),
+ 'owner' =>
+ array (
+ 0 => 'help*',
+ ),
+ 'manager' =>
+ array (
+ 0 => 'help*',
+ ),
+ 'operator' =>
+ array (
+ 0 => 'help*',
+ ),
+ 'clerk' =>
+ array (
+ ),
+ 'unbind_user' =>
+ array (
+ ),
+ ),
+ 'home' =>
+ array (
+ 'default' => 'welcome',
+ 'direct' =>
+ array (
+ ),
+ 'vice_founder' =>
+ array (
+ 0 => 'home*',
+ ),
+ 'owner' =>
+ array (
+ 0 => 'home*',
+ ),
+ 'manager' =>
+ array (
+ 0 => 'home*',
+ ),
+ 'operator' =>
+ array (
+ 0 => 'home*',
+ ),
+ 'clerk' =>
+ array (
+ 0 => 'welcome',
+ ),
+ 'unbind_user' =>
+ array (
+ ),
+ 'expired' =>
+ array (
+ 0 => 'welcome',
+ ),
+ ),
+ 'mc' =>
+ array (
+ 'default' => '',
+ 'direct' =>
+ array (
+ ),
+ 'vice_founder' =>
+ array (
+ 0 => 'mc*',
+ ),
+ 'owner' =>
+ array (
+ 0 => 'mc*',
+ ),
+ 'manager' =>
+ array (
+ 0 => 'chats',
+ 1 => 'fields',
+ 2 => 'group',
+ 3 => 'trade',
+ 4 => 'fans',
+ 5 => 'member',
+ 6 => 'message',
+ ),
+ 'operator' =>
+ array (
+ 0 => 'chats',
+ 1 => 'fields',
+ 2 => 'group',
+ 3 => 'trade',
+ ),
+ 'clerk' =>
+ array (
+ ),
+ 'unbind_user' =>
+ array (
+ ),
+ ),
+ 'module' =>
+ array (
+ 'default' => '',
+ 'direct' =>
+ array (
+ ),
+ 'vice_founder' =>
+ array (
+ 0 => 'module*',
+ ),
+ 'owner' =>
+ array (
+ 0 => 'manage-account',
+ 1 => 'manage-system',
+ 2 => 'permission',
+ 3 => 'display',
+ 4 => 'welcome',
+ 5 => 'link',
+ 6 => 'link-account',
+ 7 => 'shortcut',
+ 8 => 'plugin',
+ ),
+ 'manager' =>
+ array (
+ 0 => 'manage-account',
+ 1 => 'display',
+ 2 => 'welcome',
+ 3 => 'link',
+ 4 => 'link-account',
+ 5 => 'shortcut',
+ 6 => 'plugin',
+ ),
+ 'operator' =>
+ array (
+ 0 => 'manage-account',
+ 1 => 'display',
+ 2 => 'welcome',
+ 3 => 'link',
+ 4 => 'link-account',
+ 5 => 'shortcut',
+ 6 => 'plugin',
+ ),
+ 'clerk' =>
+ array (
+ 0 => 'display',
+ 1 => 'manage-account',
+ 2 => 'welcome',
+ 3 => 'link',
+ 4 => 'link-account',
+ 5 => 'shortcut',
+ 6 => 'plugin',
+ ),
+ 'unbind_user' =>
+ array (
+ ),
+ ),
+ 'platform' =>
+ array (
+ 'default' => '',
+ 'direct' =>
+ array (
+ ),
+ 'vice_founder' =>
+ array (
+ 0 => 'platform*',
+ ),
+ 'owner' =>
+ array (
+ 0 => 'platform*',
+ ),
+ 'manager' =>
+ array (
+ 0 => 'cover',
+ 1 => 'reply',
+ 2 => 'menu',
+ 3 => 'qr',
+ 4 => 'mass',
+ 5 => 'material',
+ 6 => 'material-post',
+ 7 => 'url2qr',
+ ),
+ 'operator' =>
+ array (
+ 0 => 'cover',
+ 1 => 'reply',
+ 2 => 'material',
+ 3 => 'material-post',
+ 4 => 'url2qr',
+ ),
+ 'clerk' =>
+ array (
+ 0 => 'reply',
+ 1 => 'cover',
+ 2 => 'material',
+ 3 => 'material-post',
+ ),
+ 'unbind_user' =>
+ array (
+ ),
+ ),
+ 'profile' =>
+ array (
+ 'default' => '',
+ 'direct' =>
+ array (
+ ),
+ 'vice_founder' =>
+ array (
+ 0 => 'profile*',
+ ),
+ 'owner' =>
+ array (
+ 0 => 'profile*',
+ ),
+ 'manager' =>
+ array (
+ 0 => 'remote',
+ 1 => 'passport',
+ 2 => 'tplnotice',
+ 3 => 'notify',
+ 4 => 'common',
+ 5 => 'payment',
+ 6 => 'refund',
+ 7 => 'module-link-uniacid',
+ 8 => 'bind-domain',
+ ),
+ 'operator' =>
+ array (
+ ),
+ 'clerk' =>
+ array (
+ ),
+ 'unbind_user' =>
+ array (
+ 0 => 'profile*',
+ ),
+ ),
+ 'site' =>
+ array (
+ 'default' => '',
+ 'direct' =>
+ array (
+ 0 => 'entry',
+ ),
+ 'vice_founder' =>
+ array (
+ 0 => 'site*',
+ ),
+ 'owner' =>
+ array (
+ 0 => 'site*',
+ ),
+ 'manager' =>
+ array (
+ 0 => 'editor',
+ 1 => 'article',
+ 2 => 'category',
+ 3 => 'style',
+ 4 => 'nav',
+ 5 => 'slide',
+ 6 => 'multi',
+ 7 => 'comment',
+ ),
+ 'operator' =>
+ array (
+ 0 => 'editor',
+ 1 => 'article',
+ 2 => 'category',
+ 3 => 'style',
+ 4 => 'nav',
+ 5 => 'slide',
+ ),
+ 'clerk' =>
+ array (
+ 0 => 'nav',
+ ),
+ 'unbind_user' =>
+ array (
+ ),
+ ),
+ 'statistics' =>
+ array (
+ 'default' => '',
+ 'direct' =>
+ array (
+ ),
+ 'vice_founder' =>
+ array (
+ 0 => 'statistics*',
+ ),
+ 'owner' =>
+ array (
+ 0 => 'statistics*',
+ ),
+ 'manager' =>
+ array (
+ 0 => 'app',
+ 1 => 'site',
+ 2 => 'setting',
+ 3 => 'fans',
+ ),
+ 'operator' =>
+ array (
+ ),
+ 'clerk' =>
+ array (
+ ),
+ 'unbind_user' =>
+ array (
+ ),
+ ),
+ 'store' =>
+ array (
+ 'default' => '',
+ 'direct' =>
+ array (
+ ),
+ 'vice_founder' =>
+ array (
+ 0 => 'goods-buyer',
+ 1 => 'orders',
+ ),
+ 'owner' =>
+ array (
+ 0 => 'goods-buyer',
+ 1 => 'orders',
+ ),
+ 'manager' =>
+ array (
+ 0 => 'goods-buyer',
+ 1 => 'orders',
+ ),
+ 'operator' =>
+ array (
+ 0 => 'goods-buyer',
+ 1 => 'orders',
+ ),
+ 'clerk' =>
+ array (
+ ),
+ 'unbind_user' =>
+ array (
+ ),
+ 'expired' =>
+ array (
+ 0 => 'goods-buyer',
+ 1 => 'orders',
+ ),
+ ),
+ 'system' =>
+ array (
+ 'default' => '',
+ 'direct' =>
+ array (
+ ),
+ 'vice_founder' =>
+ array (
+ 0 => 'updatecache',
+ ),
+ 'owner' =>
+ array (
+ 0 => 'updatecache',
+ ),
+ 'manager' =>
+ array (
+ 0 => 'updatecache',
+ ),
+ 'operator' =>
+ array (
+ 0 => 'updatecache',
+ ),
+ 'clerk' =>
+ array (
+ 0 => 'updatecache',
+ ),
+ 'unbind_user' =>
+ array (
+ 0 => 'updatecache',
+ ),
+ 'expired' =>
+ array (
+ 0 => 'updatecache',
+ ),
+ ),
+ 'user' =>
+ array (
+ 'default' => 'display',
+ 'direct' =>
+ array (
+ 0 => 'login',
+ 1 => 'register',
+ 2 => 'logout',
+ 3 => 'find-password',
+ 4 => 'third-bind',
+ 5 => 'agreement-show',
+ ),
+ 'vice_founder' =>
+ array (
+ 0 => 'user*',
+ ),
+ 'owner' =>
+ array (
+ 0 => 'profile',
+ ),
+ 'manager' =>
+ array (
+ 0 => 'profile',
+ ),
+ 'operator' =>
+ array (
+ 0 => 'profile',
+ ),
+ 'clerk' =>
+ array (
+ 0 => 'profile',
+ ),
+ 'unbind_user' =>
+ array (
+ 0 => 'profile',
+ ),
+ 'expired' =>
+ array (
+ 0 => 'user*',
+ ),
+ ),
+ 'miniapp' =>
+ array (
+ 'default' => '',
+ 'direct' =>
+ array (
+ ),
+ 'vice_founder' =>
+ array (
+ 0 => 'miniapp*',
+ ),
+ 'owner' =>
+ array (
+ 0 => 'miniapp*',
+ ),
+ 'manager' =>
+ array (
+ 0 => 'display',
+ 1 => 'version',
+ 2 => 'post',
+ ),
+ 'operator' =>
+ array (
+ 0 => 'display',
+ 1 => 'version',
+ 2 => 'post',
+ ),
+ 'clerk' =>
+ array (
+ 0 => 'display',
+ 1 => 'version',
+ 2 => 'post',
+ ),
+ 'unbind_user' =>
+ array (
+ ),
+ ),
+ 'wxapp' =>
+ array (
+ 'default' => '',
+ 'direct' =>
+ array (
+ ),
+ 'vice_founder' =>
+ array (
+ 0 => 'wxapp*',
+ ),
+ 'owner' =>
+ array (
+ 0 => 'wxapp*',
+ ),
+ 'manager' =>
+ array (
+ 0 => 'display',
+ 1 => 'version',
+ 2 => 'post',
+ 3 => 'auth',
+ 4 => 'manage',
+ ),
+ 'operator' =>
+ array (
+ 0 => 'display',
+ 1 => 'version',
+ 2 => 'post',
+ 3 => 'auth',
+ ),
+ 'clerk' =>
+ array (
+ 0 => 'display',
+ ),
+ 'unbind_user' =>
+ array (
+ ),
+ ),
+ 'webapp' =>
+ array (
+ 'default' => '',
+ 'direct' =>
+ array (
+ ),
+ 'vice_founder' =>
+ array (
+ 0 => 'webapp*',
+ ),
+ 'owner' =>
+ array (
+ 0 => 'webapp*',
+ ),
+ 'manager' =>
+ array (
+ 0 => 'home',
+ 1 => 'manage',
+ ),
+ 'operator' =>
+ array (
+ 0 => 'home',
+ 1 => 'manage',
+ ),
+ 'clerk' =>
+ array (
+ 0 => 'home',
+ ),
+ 'unbind_user' =>
+ array (
+ ),
+ ),
+ 'phoneapp' =>
+ array (
+ 'default' => '',
+ 'direct' =>
+ array (
+ ),
+ 'vice_founder' =>
+ array (
+ 0 => 'phoneapp*',
+ ),
+ 'owner' =>
+ array (
+ 0 => 'phoneapp*',
+ ),
+ 'manager' =>
+ array (
+ 0 => 'display',
+ 1 => 'manage',
+ 2 => 'version',
+ ),
+ 'operator' =>
+ array (
+ 0 => 'display',
+ 1 => 'manage',
+ 2 => 'version',
+ ),
+ 'clerk' =>
+ array (
+ 0 => 'display',
+ ),
+ ),
+ 'utility' =>
+ array (
+ 'default' => '',
+ 'direct' =>
+ array (
+ 0 => 'verifycode',
+ 1 => 'code',
+ 2 => 'bindcall',
+ 3 => 'subscribe',
+ 4 => 'wxcode',
+ 5 => 'modules',
+ 6 => 'link',
+ 7 => 'visit',
+ 8 => 'file',
+ ),
+ 'vice_founder' =>
+ array (
+ 0 => 'user',
+ 1 => 'emulator',
+ 2 => 'file',
+ ),
+ 'owner' =>
+ array (
+ 0 => 'emulator',
+ 1 => 'file',
+ ),
+ 'manager' =>
+ array (
+ 0 => 'emulator',
+ 1 => 'file',
+ ),
+ 'operator' =>
+ array (
+ 0 => 'emulator',
+ 1 => 'file',
+ ),
+ 'clerk' =>
+ array (
+ 0 => 'emulator',
+ 1 => 'file',
+ ),
+ 'unbind_user' =>
+ array (
+ ),
+ ),
+ 'append' =>
+ array (
+ 0 => 'append*',
+ ),
+ 'see_more_info' =>
+ array (
+ 'founder' =>
+ array (
+ 0 => 'see_module_manage_system_except_installed',
+ 1 => 'see_module_manage_system_ugrade',
+ 2 => 'see_module_manage_system_stop',
+ 3 => 'see_module_manage_system_install',
+ 4 => 'see_module_manage_system_shopinfo',
+ 5 => 'see_module_manage_system_info_edit',
+ 6 => 'see_module_manage_system_detailinfo',
+ 7 => 'see_module_manage_system_group_add',
+ 8 => 'see_module_manage_system_welcome_support',
+ 9 => 'see_account_post_modules_tpl_edit_store_endtime',
+ 10 => 'see_account_manage_module_tpl_all_permission',
+ 11 => 'see_account_manage_sms_blance',
+ 12 => 'see_account_manage_users_edit_vicefounder',
+ 13 => 'see_account_manage_users_edit_owner',
+ 14 => 'see_account_manage_users_set_permission_for_manager',
+ 15 => 'see_account_manage_users_set_permission_for_operator',
+ 16 => 'see_account_manage_users_addmanager',
+ 17 => 'see_account_manage_users_delmanager',
+ 18 => 'see_account_manage_users_deloperator',
+ 19 => 'see_account_manage_users_adduser',
+ 20 => 'see_account_manage_users_add_viceuser',
+ 21 => 'see_account_manage_display',
+ 22 => 'see_account_manage_recycle',
+ 23 => 'see_account_manage_system_platform',
+ 24 => 'see_account_manage_expired_message',
+ 25 => 'see_permission_create_account_group',
+ 26 => 'see_permission_module_group',
+ 27 => 'see_permission_user_group',
+ 28 => 'see_permission_founder_group',
+ 29 => 'see_system_upgrade',
+ 30 => 'see_system_manage_clerk',
+ 31 => 'see_system_manage_vice_founder',
+ 32 => 'see_system_add_vice_founder',
+ 33 => 'see_notice_post',
+ 34 => 'see_message_official',
+ 35 => 'see_message_order',
+ 36 => 'see_message_register',
+ 37 => 'see_message_worker',
+ 38 => 'see_module_manage_system_newversion',
+ 39 => 'see_user_add_welcome_account',
+ 40 => 'see_user_edit_base_founder_name',
+ 41 => 'see_user_create_own_vice_founder',
+ 42 => 'see_user_profile_account_num',
+ 43 => 'see_user_profile_edit_username',
+ 44 => 'see_user_manage_display',
+ 45 => 'see_user_manage_founder',
+ 46 => 'see_user_manage_clerk',
+ 47 => 'see_user_manage_check',
+ 48 => 'see_user_manage_recycle',
+ 49 => 'see_user_manage_fields',
+ 50 => 'see_user_manage_expire',
+ 51 => 'see_workorder',
+ 52 => 'see_controller',
+ 53 => 'see_modules_deactivate',
+ ),
+ 'vice_founder' =>
+ array (
+ 0 => 'see_account_manage_users_adduser',
+ 1 => 'see_account_manage_users_edit_owner',
+ 2 => 'see_account_manage_users_set_permission_for_manager',
+ 3 => 'see_account_manage_users_set_permission_for_operator',
+ 4 => 'see_account_manage_users_deloperator',
+ 5 => 'see_account_manage_users_delmanager',
+ 6 => 'see_account_manage_display',
+ 7 => 'see_account_manage_recycle',
+ 8 => 'see_module_manage_system_group_add',
+ 9 => 'see_permission_create_account_group',
+ 10 => 'see_permission_module_group',
+ 11 => 'see_permission_user_group',
+ 12 => 'see_user_add_welcome_account',
+ 13 => 'see_user_profile_account_num',
+ 14 => 'see_user_manage_display',
+ 15 => 'see_user_manage_check',
+ 16 => 'see_user_manage_recycle',
+ 17 => 'see_controller',
+ ),
+ 'owner' =>
+ array (
+ 0 => 'see_account_manage_users_set_permission_for_manager',
+ 1 => 'see_account_manage_users_set_permission_for_operator',
+ 2 => 'see_account_manage_users_deloperator',
+ 3 => 'see_account_manage_users_delmanager',
+ 4 => 'see_account_manage_display',
+ 5 => 'see_account_manage_recycle',
+ 6 => 'see_modules_recharge',
+ 7 => 'see_user_add_welcome_account',
+ 8 => 'see_user_profile_account_num',
+ ),
+ 'manager' =>
+ array (
+ 0 => 'see_account_manage_users_set_permission_for_operator',
+ 1 => 'see_account_manage_users_deloperator',
+ 2 => 'see_account_manage_display',
+ 3 => 'see_user_profile_welcome',
+ 4 => 'see_user_add_welcome_account',
+ 5 => 'see_user_profile_account_num',
+ ),
+ 'operator' =>
+ array (
+ 0 => 'see_account_manage_display',
+ 1 => 'see_user_profile_welcome',
+ 2 => 'see_user_add_welcome_account',
+ 3 => 'see_user_profile_account_num',
+ ),
+ 'clerk' =>
+ array (
+ ),
+ 'unbind_user' =>
+ array (
+ 0 => 'see_user_profile_welcome',
+ ),
+ 'expired' =>
+ array (
+ ),
+ ),
+);
+return $we7_file_permission;
\ No newline at end of file
diff --git a/web/resource/components/kindeditor/plugins/code/prettify.css b/web/resource/components/kindeditor/plugins/code/prettify.css
new file mode 100644
index 0000000..b8287e5
--- /dev/null
+++ b/web/resource/components/kindeditor/plugins/code/prettify.css
@@ -0,0 +1,13 @@
+.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}
+
+pre.prettyprint {
+ border: 0;
+ border-left: 3px solid rgb(204, 204, 204);
+ margin-left: 2em;
+ padding: 0.5em;
+ font-size: 110%;
+ display: block;
+ font-family: "Consolas", "Monaco", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace;
+ margin: 1em 0px;
+ white-space: pre;
+}
diff --git a/web/resource/components/kindeditor/plugins/code/prettify.js b/web/resource/components/kindeditor/plugins/code/prettify.js
new file mode 100644
index 0000000..eef5ad7
--- /dev/null
+++ b/web/resource/components/kindeditor/plugins/code/prettify.js
@@ -0,0 +1,28 @@
+var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
+(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a=
+[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c';e.addCommand("mcePageBreak",function(){e.insertContent(e.settings.pagebreak_split_block?"
$/i])}return{filter:r,innerText:i,trimHtml:o}}),r(f,[p,m,l],function(e,t,n){return function(r){function i(e){var t,n=r.dom;if(t=r.fire("BeforePastePreProcess",{content:e}),t=r.fire("PastePreProcess",t),e=t.content,!t.isDefaultPrevented()){if(r.hasEventListeners("PastePostProcess")&&!t.isDefaultPrevented()){var i=n.add(r.getBody(),"div",{style:"display:none"},e);t=r.fire("PastePostProcess",{node:i}),n.remove(i),e=t.node.innerHTML}t.isDefaultPrevented()||r.insertContent(e,{merge:r.settings.paste_merge_formats!==!1})}}function o(e){e=r.dom.encode(e).replace(/\r\n/g,"\n");var t=r.dom.getParent(r.selection.getStart(),r.dom.isBlock),o=r.settings.forced_root_block,a;o&&(a=r.dom.createHTML(o,r.settings.forced_root_block_attrs),a=a.substr(0,a.length-3)+">"),t&&/^(PRE|DIV)$/.test(t.nodeName)||!o?e=n.filter(e,[[/\n/g,"
"]]):(e=n.filter(e,[[/\n\n/g,"
)$/,a+"$1"],[/\n/g,"
"]]),-1!=e.indexOf("
")&&(e=a+e)),i(e)}function a(){var t=r.dom,n=r.getBody(),i=r.dom.getViewPort(r.getWin()),o=i.y,a=20,s;if(b=r.selection.getRng(),r.inline&&(s=r.selection.getScrollContainer(),s&&s.scrollTop>0&&(o=s.scrollTop)),b.getClientRects){var l=b.getClientRects();if(l.length)a=o+(l[0].top-t.getPos(n).y);else{a=o;var c=b.startContainer;c&&(3==c.nodeType&&c.parentNode!=n&&(c=c.parentNode),1==c.nodeType&&(a=t.getPos(c,s||n).y))}}y=t.add(r.getBody(),"div",{id:"mcepastebin",contentEditable:!0,"data-mce-bogus":"1",style:"position: absolute; top: "+a+"px;width: 10px; height: 10px; overflow: hidden; opacity: 0"},x),(e.ie||e.gecko)&&t.setStyle(y,"left","rtl"==t.getStyle(n,"direction",!0)?65535:-65535),t.bind(y,"beforedeactivate focusin focusout",function(e){e.stopPropagation()}),y.focus(),r.selection.select(y,!0)}function s(){if(y){for(var e;e=r.dom.get("mcepastebin");)r.dom.remove(e),r.dom.unbind(e);b&&r.selection.setRng(b)}y=b=null}function l(){var e=x,t,n;for(t=r.dom.select("div[id=mcepastebin]"),n=t.length;n--;){var i=t[n].innerHTML;e==x&&(e=""),i.length>e.length&&(e=i)}return e}function c(e){var t={};if(e&&e.types){var n=e.getData("Text");n&&n.length>0&&(t["text/plain"]=n);for(var r=0;r
| "+(l.ie?" ":" ")+" | ";r+="
| ';e+=" |
8U}fi7AzZCsS=07??9MLn2Bde0{8v^K