PageRenderTime 58ms CodeModel.GetById 13ms app.highlight 37ms RepoModel.GetById 2ms app.codeStats 0ms

/PHPExcel/Reader/OOCalc.php

https://bitbucket.org/nfredricks/wp-employee-time
PHP | 733 lines | 452 code | 80 blank | 201 comment | 71 complexity | aa78ecc6eae4e8d98ef5d9673dd54d3d MD5 | raw file
  1<?php
  2/**
  3 * PHPExcel
  4 *
  5 * Copyright (c) 2006 - 2012 PHPExcel
  6 *
  7 * This library is free software; you can redistribute it and/or
  8 * modify it under the terms of the GNU Lesser General Public
  9 * License as published by the Free Software Foundation; either
 10 * version 2.1 of the License, or (at your option) any later version.
 11 *
 12 * This library is distributed in the hope that it will be useful,
 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 15 * Lesser General Public License for more details.
 16 *
 17 * You should have received a copy of the GNU Lesser General Public
 18 * License along with this library; if not, write to the Free Software
 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 20 *
 21 * @category   PHPExcel
 22 * @package    PHPExcel_Reader
 23 * @copyright  Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
 24 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt	LGPL
 25 * @version    1.7.8, 2012-10-12
 26 */
 27
 28
 29/** PHPExcel root directory */
 30if (!defined('PHPEXCEL_ROOT')) {
 31	/**
 32	 * @ignore
 33	 */
 34	define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
 35	require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
 36}
 37
 38/**
 39 * PHPExcel_Reader_OOCalc
 40 *
 41 * @category	PHPExcel
 42 * @package		PHPExcel_Reader
 43 * @copyright	Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
 44 */
 45class PHPExcel_Reader_OOCalc implements PHPExcel_Reader_IReader
 46{
 47	/**
 48	 * Read data only?
 49	 * Identifies whether the Reader should only read data values for cells, and ignore any formatting information;
 50	 *		or whether it should read both data and formatting
 51	 *
 52	 * @var	boolean
 53	 */
 54	private $_readDataOnly = false;
 55
 56	/**
 57	 * Restrict which sheets should be loaded?
 58	 * This property holds an array of worksheet names to be loaded. If null, then all worksheets will be loaded.
 59	 *
 60	 * @var	array of string
 61	 */
 62	private $_loadSheetsOnly = null;
 63
 64	/**
 65	 * Formats
 66	 *
 67	 * @var array
 68	 */
 69	private $_styles = array();
 70
 71	/**
 72	 * PHPExcel_Reader_IReadFilter instance
 73	 *
 74	 * @var PHPExcel_Reader_IReadFilter
 75	 */
 76	private $_readFilter = null;
 77
 78
 79	/**
 80	 * Create a new PHPExcel_Reader_OOCalc
 81	 */
 82	public function __construct() {
 83		$this->_readFilter 	= new PHPExcel_Reader_DefaultReadFilter();
 84	}
 85
 86
 87	/**
 88	 * Read data only?
 89	 *		If this is true, then the Reader will only read data values for cells, it will not read any formatting information.
 90	 *		If false (the default) it will read data and formatting.
 91	 *
 92	 * @return	boolean
 93	 */
 94	public function getReadDataOnly() {
 95		return $this->_readDataOnly;
 96	}
 97
 98
 99	/**
100	 * Set read data only
101	 *		Set to true, to advise the Reader only to read data values for cells, and to ignore any formatting information.
102	 *		Set to false (the default) to advise the Reader to read both data and formatting for cells.
103	 *
104	 * @param	boolean	$pValue
105	 * @return	PHPExcel_Reader_OOCalc
106	 */
107	public function setReadDataOnly($pValue = false) {
108		$this->_readDataOnly = $pValue;
109		return $this;
110	}
111
112
113	/**
114	 * Get which sheets to load
115	 *		Returns either an array of worksheet names (the list of worksheets that should be loaded), or a null
116	 *			indicating that all worksheets in the workbook should be loaded.
117	 *
118	 * @return mixed
119	 */
120	public function getLoadSheetsOnly()
121	{
122		return $this->_loadSheetsOnly;
123	}
124
125
126	/**
127	 * Set which sheets to load
128	 *
129	 * @param mixed $value
130	 *		This should be either an array of worksheet names to be loaded, or a string containing a single worksheet name.
131	 *		If NULL, then it tells the Reader to read all worksheets in the workbook
132	 *
133	 * @return PHPExcel_Reader_OOCalc
134	 */
135	public function setLoadSheetsOnly($value = null)
136	{
137		$this->_loadSheetsOnly = is_array($value) ?
138			$value : array($value);
139		return $this;
140	}
141
142
143	/**
144	 * Set all sheets to load
145	 *		Tells the Reader to load all worksheets from the workbook.
146	 *
147	 * @return PHPExcel_Reader_OOCalc
148	 */
149	public function setLoadAllSheets()
150	{
151		$this->_loadSheetsOnly = null;
152		return $this;
153	}
154
155
156	/**
157	 * Read filter
158	 *
159	 * @return PHPExcel_Reader_IReadFilter
160	 */
161	public function getReadFilter() {
162		return $this->_readFilter;
163	}
164
165
166	/**
167	 * Set read filter
168	 *
169	 * @param PHPExcel_Reader_IReadFilter $pValue
170	 * @return PHPExcel_Reader_OOCalc
171	 */
172	public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) {
173		$this->_readFilter = $pValue;
174		return $this;
175	}
176
177
178	/**
179	 * Can the current PHPExcel_Reader_IReader read the file?
180	 *
181	 * @param 	string 		$pFileName
182	 * @return 	boolean
183	 * @throws Exception
184	 */
185	public function canRead($pFilename)
186	{
187		// Check if file exists
188		if (!file_exists($pFilename)) {
189			throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
190		}
191
192		// Check if zip class exists
193		if (!class_exists('ZipArchive',FALSE)) {
194			throw new Exception("ZipArchive library is not enabled");
195		}
196
197		// Load file
198		$zip = new ZipArchive;
199		if ($zip->open($pFilename) === true) {
200			// check if it is an OOXML archive
201			$stat = $zip->statName('mimetype');
202			if ($stat && ($stat['size'] <= 255)) {
203				$mimeType = $zip->getFromName($stat['name']);
204			} else {
205				$zip->close();
206				return FALSE;
207			}
208
209			$zip->close();
210
211			return ($mimeType === 'application/vnd.oasis.opendocument.spreadsheet');
212		}
213
214		return FALSE;
215	}
216
217
218	/**
219	 * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object
220	 *
221	 * @param 	string 		$pFilename
222	 * @throws 	Exception
223	 */
224	public function listWorksheetNames($pFilename)
225	{
226		// Check if file exists
227		if (!file_exists($pFilename)) {
228			throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
229		}
230
231		$worksheetNames = array();
232
233		$zip = new ZipArchive;
234		if ($zip->open($pFilename) === true) {
235
236			$xml = simplexml_load_string($zip->getFromName("content.xml"));
237			$namespacesContent = $xml->getNamespaces(true);
238
239			$workbook = $xml->children($namespacesContent['office']);
240			foreach($workbook->body->spreadsheet as $workbookData) {
241				$workbookData = $workbookData->children($namespacesContent['table']);
242				foreach($workbookData->table as $worksheetDataSet) {
243					$worksheetDataAttributes = $worksheetDataSet->attributes($namespacesContent['table']);
244
245					$worksheetNames[] = $worksheetDataAttributes['name'];
246				}
247			}
248		}
249
250		return $worksheetNames;
251	}
252
253
254	/**
255	 * Loads PHPExcel from file
256	 *
257	 * @param 	string 		$pFilename
258	 * @return 	PHPExcel
259	 * @throws 	Exception
260	 */
261	public function load($pFilename)
262	{
263		// Create new PHPExcel
264		$objPHPExcel = new PHPExcel();
265
266		// Load into this instance
267		return $this->loadIntoExisting($pFilename, $objPHPExcel);
268	}
269
270
271	private static function identifyFixedStyleValue($styleList,&$styleAttributeValue) {
272		$styleAttributeValue = strtolower($styleAttributeValue);
273		foreach($styleList as $style) {
274			if ($styleAttributeValue == strtolower($style)) {
275				$styleAttributeValue = $style;
276				return true;
277			}
278		}
279		return false;
280	}
281
282
283	/**
284	 * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns)
285	 *
286	 * @param   string     $pFilename
287	 * @throws   Exception
288	 */
289	public function listWorksheetInfo($pFilename)
290	{
291		// Check if file exists
292		if (!file_exists($pFilename)) {
293			throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
294		}
295
296		$worksheetInfo = array();
297
298		$zip = new ZipArchive;
299		if ($zip->open($pFilename) === true) {
300
301			$xml = simplexml_load_string($zip->getFromName("content.xml"));
302			$namespacesContent = $xml->getNamespaces(true);
303
304			$workbook = $xml->children($namespacesContent['office']);
305			foreach($workbook->body->spreadsheet as $workbookData) {
306				$workbookData = $workbookData->children($namespacesContent['table']);
307				foreach($workbookData->table as $worksheetDataSet) {
308					$worksheetData = $worksheetDataSet->children($namespacesContent['table']);
309					$worksheetDataAttributes = $worksheetDataSet->attributes($namespacesContent['table']);
310
311					$tmpInfo = array();
312					$tmpInfo['worksheetName'] = (string) $worksheetDataAttributes['name'];
313					$tmpInfo['lastColumnLetter'] = 'A';
314					$tmpInfo['lastColumnIndex'] = 0;
315					$tmpInfo['totalRows'] = 0;
316					$tmpInfo['totalColumns'] = 0;
317
318					$rowIndex = 0;
319					foreach ($worksheetData as $key => $rowData) {
320						switch ($key) {
321							case 'table-row' :
322								$rowDataTableAttributes = $rowData->attributes($namespacesContent['table']);
323								$rowRepeats = (isset($rowDataTableAttributes['number-rows-repeated'])) ?
324										$rowDataTableAttributes['number-rows-repeated'] : 1;
325								$columnIndex = 0;
326
327								foreach ($rowData as $key => $cellData) {
328									$cellDataTableAttributes = $cellData->attributes($namespacesContent['table']);
329									$colRepeats = (isset($cellDataTableAttributes['number-columns-repeated'])) ?
330										$cellDataTableAttributes['number-columns-repeated'] : 1;
331									$cellDataOfficeAttributes = $cellData->attributes($namespacesContent['office']);
332									if (isset($cellDataOfficeAttributes['value-type'])) {
333										$tmpInfo['lastColumnIndex'] = max($tmpInfo['lastColumnIndex'], $columnIndex + $colRepeats - 1);
334										$tmpInfo['totalRows'] = max($tmpInfo['totalRows'], $rowIndex + $rowRepeats);
335									}
336									$columnIndex += $colRepeats;
337								}
338								$rowIndex += $rowRepeats;
339								break;
340						}
341					}
342
343					$tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']);
344					$tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1;
345
346					$worksheetInfo[] = $tmpInfo;
347				}
348			}
349		}
350
351		return $worksheetInfo;
352	}
353
354
355	/**
356	 * Loads PHPExcel from file into PHPExcel instance
357	 *
358	 * @param 	string 		$pFilename
359	 * @param	PHPExcel	$objPHPExcel
360	 * @return 	PHPExcel
361	 * @throws 	Exception
362	 */
363	public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel)
364	{
365		// Check if file exists
366		if (!file_exists($pFilename)) {
367			throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
368		}
369
370		$timezoneObj = new DateTimeZone('Europe/London');
371		$GMT = new DateTimeZone('UTC');
372
373		$zip = new ZipArchive;
374		if ($zip->open($pFilename) === true) {
375//			echo '<h1>Meta Information</h1>';
376			$xml = simplexml_load_string($zip->getFromName("meta.xml"));
377			$namespacesMeta = $xml->getNamespaces(true);
378//			echo '<pre>';
379//			print_r($namespacesMeta);
380//			echo '</pre><hr />';
381
382			$docProps = $objPHPExcel->getProperties();
383			$officeProperty = $xml->children($namespacesMeta['office']);
384			foreach($officeProperty as $officePropertyData) {
385				$officePropertyDC = array();
386				if (isset($namespacesMeta['dc'])) {
387					$officePropertyDC = $officePropertyData->children($namespacesMeta['dc']);
388				}
389				foreach($officePropertyDC as $propertyName => $propertyValue) {
390					switch ($propertyName) {
391						case 'title' :
392								$docProps->setTitle($propertyValue);
393								break;
394						case 'subject' :
395								$docProps->setSubject($propertyValue);
396								break;
397						case 'creator' :
398								$docProps->setCreator($propertyValue);
399								$docProps->setLastModifiedBy($propertyValue);
400								break;
401						case 'date' :
402								$creationDate = strtotime($propertyValue);
403								$docProps->setCreated($creationDate);
404								$docProps->setModified($creationDate);
405								break;
406						case 'description' :
407								$docProps->setDescription($propertyValue);
408								break;
409					}
410				}
411				$officePropertyMeta = array();
412				if (isset($namespacesMeta['dc'])) {
413					$officePropertyMeta = $officePropertyData->children($namespacesMeta['meta']);
414				}
415				foreach($officePropertyMeta as $propertyName => $propertyValue) {
416					$propertyValueAttributes = $propertyValue->attributes($namespacesMeta['meta']);
417					switch ($propertyName) {
418						case 'initial-creator' :
419								$docProps->setCreator($propertyValue);
420								break;
421						case 'keyword' :
422								$docProps->setKeywords($propertyValue);
423								break;
424						case 'creation-date' :
425								$creationDate = strtotime($propertyValue);
426								$docProps->setCreated($creationDate);
427								break;
428						case 'user-defined' :
429								$propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_STRING;
430								foreach ($propertyValueAttributes as $key => $value) {
431									if ($key == 'name') {
432										$propertyValueName = (string) $value;
433									} elseif($key == 'value-type') {
434										switch ($value) {
435											case 'date'	:
436												$propertyValue = PHPExcel_DocumentProperties::convertProperty($propertyValue,'date');
437												$propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_DATE;
438												break;
439											case 'boolean'	:
440												$propertyValue = PHPExcel_DocumentProperties::convertProperty($propertyValue,'bool');
441												$propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_BOOLEAN;
442												break;
443											case 'float'	:
444												$propertyValue = PHPExcel_DocumentProperties::convertProperty($propertyValue,'r4');
445												$propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_FLOAT;
446												break;
447											default :
448												$propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_STRING;
449										}
450									}
451								}
452								$docProps->setCustomProperty($propertyValueName,$propertyValue,$propertyValueType);
453								break;
454					}
455				}
456			}
457
458
459//			echo '<h1>Workbook Content</h1>';
460			$xml = simplexml_load_string($zip->getFromName("content.xml"));
461			$namespacesContent = $xml->getNamespaces(true);
462//			echo '<pre>';
463//			print_r($namespacesContent);
464//			echo '</pre><hr />';
465
466			$workbook = $xml->children($namespacesContent['office']);
467			foreach($workbook->body->spreadsheet as $workbookData) {
468				$workbookData = $workbookData->children($namespacesContent['table']);
469				$worksheetID = 0;
470				foreach($workbookData->table as $worksheetDataSet) {
471					$worksheetData = $worksheetDataSet->children($namespacesContent['table']);
472//					print_r($worksheetData);
473//					echo '<br />';
474					$worksheetDataAttributes = $worksheetDataSet->attributes($namespacesContent['table']);
475//					print_r($worksheetDataAttributes);
476//					echo '<br />';
477					if ((isset($this->_loadSheetsOnly)) && (isset($worksheetDataAttributes['name'])) &&
478						(!in_array($worksheetDataAttributes['name'], $this->_loadSheetsOnly))) {
479						continue;
480					}
481
482//					echo '<h2>Worksheet '.$worksheetDataAttributes['name'].'</h2>';
483					// Create new Worksheet
484					$objPHPExcel->createSheet();
485					$objPHPExcel->setActiveSheetIndex($worksheetID);
486					if (isset($worksheetDataAttributes['name'])) {
487						$worksheetName = (string) $worksheetDataAttributes['name'];
488						//	Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in
489						//		formula cells... during the load, all formulae should be correct, and we're simply
490						//		bringing the worksheet name in line with the formula, not the reverse
491						$objPHPExcel->getActiveSheet()->setTitle($worksheetName,false);
492					}
493
494					$rowID = 1;
495					foreach($worksheetData as $key => $rowData) {
496//						echo '<b>'.$key.'</b><br />';
497						switch ($key) {
498							case 'table-header-rows':
499								foreach ($rowData as $key=>$cellData) {
500									$rowData = $cellData;
501									break;
502								}
503							case 'table-row' :
504								$rowDataTableAttributes = $rowData->attributes($namespacesContent['table']);
505								$rowRepeats = (isset($rowDataTableAttributes['number-rows-repeated'])) ?
506										$rowDataTableAttributes['number-rows-repeated'] : 1;
507								$columnID = 'A';
508								foreach($rowData as $key => $cellData) {
509									if ($this->getReadFilter() !== NULL) {
510										if (!$this->getReadFilter()->readCell($columnID, $rowID, $worksheetName)) {
511											continue;
512										}
513									}
514
515//									echo '<b>'.$columnID.$rowID.'</b><br />';
516									$cellDataText = (isset($namespacesContent['text'])) ?
517										$cellData->children($namespacesContent['text']) :
518										'';
519									$cellDataOffice = $cellData->children($namespacesContent['office']);
520									$cellDataOfficeAttributes = $cellData->attributes($namespacesContent['office']);
521									$cellDataTableAttributes = $cellData->attributes($namespacesContent['table']);
522
523//									echo 'Office Attributes: ';
524//									print_r($cellDataOfficeAttributes);
525//									echo '<br />Table Attributes: ';
526//									print_r($cellDataTableAttributes);
527//									echo '<br />Cell Data Text';
528//									print_r($cellDataText);
529//									echo '<br />';
530//
531									$type = $formatting = $hyperlink = null;
532									$hasCalculatedValue = false;
533									$cellDataFormula = '';
534									if (isset($cellDataTableAttributes['formula'])) {
535										$cellDataFormula = $cellDataTableAttributes['formula'];
536										$hasCalculatedValue = true;
537									}
538
539									if (isset($cellDataOffice->annotation)) {
540//										echo 'Cell has comment<br />';
541										$annotationText = $cellDataOffice->annotation->children($namespacesContent['text']);
542										$textArray = array();
543										foreach($annotationText as $t) {
544											foreach($t->span as $text) {
545												$textArray[] = (string)$text;
546											}
547										}
548										$text = implode("\n",$textArray);
549//										echo $text,'<br />';
550										$objPHPExcel->getActiveSheet()->getComment( $columnID.$rowID )
551//																		->setAuthor( $author )
552																		->setText($this->_parseRichText($text) );
553									}
554
555									if (isset($cellDataText->p)) {
556										// Consolidate if there are multiple p records (maybe with spans as well)
557										$dataArray = array();
558										// Text can have multiple text:p and within those, multiple text:span.
559										// text:p newlines, but text:span does not.
560										// Also, here we assume there is no text data is span fields are specified, since
561										// we have no way of knowing proper positioning anyway.
562										foreach ($cellDataText->p as $pData) {
563											if (isset($pData->span)) {
564												// span sections do not newline, so we just create one large string here
565												$spanSection = "";
566												foreach ($pData->span as $spanData) {
567													$spanSection .= $spanData;
568												}
569												array_push($dataArray, $spanSection);
570											} else {
571												array_push($dataArray, $pData);
572											}
573										}
574										$allCellDataText = implode($dataArray, "\n");
575
576//										echo 'Value Type is '.$cellDataOfficeAttributes['value-type'].'<br />';
577										switch ($cellDataOfficeAttributes['value-type']) {
578 											case 'string' :
579													$type = PHPExcel_Cell_DataType::TYPE_STRING;
580													$dataValue = $allCellDataText;
581													if (isset($dataValue->a)) {
582														$dataValue = $dataValue->a;
583														$cellXLinkAttributes = $dataValue->attributes($namespacesContent['xlink']);
584														$hyperlink = $cellXLinkAttributes['href'];
585													}
586													break;
587											case 'boolean' :
588													$type = PHPExcel_Cell_DataType::TYPE_BOOL;
589													$dataValue = ($allCellDataText == 'TRUE') ? True : False;
590													break;
591											case 'percentage' :
592													$type = PHPExcel_Cell_DataType::TYPE_NUMERIC;
593													$dataValue = (float) $cellDataOfficeAttributes['value'];
594													if (floor($dataValue) == $dataValue) {
595														$dataValue = (integer) $dataValue;
596													}
597													$formatting = PHPExcel_Style_NumberFormat::FORMAT_PERCENTAGE_00;
598													break;
599											case 'currency' :
600													$type = PHPExcel_Cell_DataType::TYPE_NUMERIC;
601													$dataValue = (float) $cellDataOfficeAttributes['value'];
602													if (floor($dataValue) == $dataValue) {
603														$dataValue = (integer) $dataValue;
604													}
605													$formatting = PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_USD_SIMPLE;
606													break;
607											case 'float' :
608													$type = PHPExcel_Cell_DataType::TYPE_NUMERIC;
609													$dataValue = (float) $cellDataOfficeAttributes['value'];
610													if (floor($dataValue) == $dataValue) {
611														if ($dataValue = (integer) $dataValue)
612															$dataValue = (integer) $dataValue;
613														else
614															$dataValue = (float) $dataValue;
615													}
616													break;
617											case 'date' :
618													$type = PHPExcel_Cell_DataType::TYPE_NUMERIC;
619												    $dateObj = new DateTime($cellDataOfficeAttributes['date-value'], $GMT);
620													$dateObj->setTimeZone($timezoneObj);
621													list($year,$month,$day,$hour,$minute,$second) = explode(' ',$dateObj->format('Y m d H i s'));
622													$dataValue = PHPExcel_Shared_Date::FormattedPHPToExcel($year,$month,$day,$hour,$minute,$second);
623													if ($dataValue != floor($dataValue)) {
624														$formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15.' '.PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4;
625													} else {
626														$formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15;
627													}
628													break;
629											case 'time' :
630													$type = PHPExcel_Cell_DataType::TYPE_NUMERIC;
631													$dataValue = PHPExcel_Shared_Date::PHPToExcel(strtotime('01-01-1970 '.implode(':',sscanf($cellDataOfficeAttributes['time-value'],'PT%dH%dM%dS'))));
632													$formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4;
633													break;
634										}
635//										echo 'Data value is '.$dataValue.'<br />';
636//										if ($hyperlink !== NULL) {
637//											echo 'Hyperlink is '.$hyperlink.'<br />';
638//										}
639									} else {
640										$type = PHPExcel_Cell_DataType::TYPE_NULL;
641										$dataValue = NULL;
642									}
643
644									if ($hasCalculatedValue) {
645										$type = PHPExcel_Cell_DataType::TYPE_FORMULA;
646//										echo 'Formula: '.$cellDataFormula.'<br />';
647										$cellDataFormula = substr($cellDataFormula,strpos($cellDataFormula,':=')+1);
648										$temp = explode('"',$cellDataFormula);
649										$tKey = false;
650										foreach($temp as &$value) {
651											//	Only replace in alternate array entries (i.e. non-quoted blocks)
652											if ($tKey = !$tKey) {
653												$value = preg_replace('/\[\.(.*):\.(.*)\]/Ui','$1:$2',$value);
654												$value = preg_replace('/\[\.(.*)\]/Ui','$1',$value);
655												$value = PHPExcel_Calculation::_translateSeparator(';',',',$value,$inBraces);
656											}
657										}
658										unset($value);
659										//	Then rebuild the formula string
660										$cellDataFormula = implode('"',$temp);
661//										echo 'Adjusted Formula: '.$cellDataFormula.'<br />';
662									}
663
664									$colRepeats = (isset($cellDataTableAttributes['number-columns-repeated'])) ?
665										$cellDataTableAttributes['number-columns-repeated'] : 1;
666									if ($type !== NULL) {
667										for ($i = 0; $i < $colRepeats; ++$i) {
668											if ($i > 0) {
669												++$columnID;
670											}
671											if ($type !== PHPExcel_Cell_DataType::TYPE_NULL) {
672												for ($rowAdjust = 0; $rowAdjust < $rowRepeats; ++$rowAdjust) {
673													$rID = $rowID + $rowAdjust;
674													$objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $dataValue),$type);
675													if ($hasCalculatedValue) {
676//														echo 'Forumla result is '.$dataValue.'<br />';
677														$objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->setCalculatedValue($dataValue);
678													}
679													if ($formatting !== NULL) {
680														$objPHPExcel->getActiveSheet()->getStyle($columnID.$rID)->getNumberFormat()->setFormatCode($formatting);
681													} else {
682														$objPHPExcel->getActiveSheet()->getStyle($columnID.$rID)->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_GENERAL);
683													}
684													if ($hyperlink !== NULL) {
685														$objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->getHyperlink()->setUrl($hyperlink);
686													}
687												}
688											}
689										}
690									}
691
692									//	Merged cells
693									if ((isset($cellDataTableAttributes['number-columns-spanned'])) || (isset($cellDataTableAttributes['number-rows-spanned']))) {
694										if (($type !== PHPExcel_Cell_DataType::TYPE_NULL) || (!$this->_readDataOnly)) {
695											$columnTo = $columnID;
696											if (isset($cellDataTableAttributes['number-columns-spanned'])) {
697												$columnTo = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($columnID) + $cellDataTableAttributes['number-columns-spanned'] -2);
698											}
699											$rowTo = $rowID;
700											if (isset($cellDataTableAttributes['number-rows-spanned'])) {
701												$rowTo = $rowTo + $cellDataTableAttributes['number-rows-spanned'] - 1;
702											}
703											$cellRange = $columnID.$rowID.':'.$columnTo.$rowTo;
704											$objPHPExcel->getActiveSheet()->mergeCells($cellRange);
705										}
706									}
707
708									++$columnID;
709								}
710								$rowID += $rowRepeats;
711								break;
712						}
713					}
714					++$worksheetID;
715				}
716			}
717
718		}
719
720		// Return
721		return $objPHPExcel;
722	}
723
724
725	private function _parseRichText($is = '') {
726		$value = new PHPExcel_RichText();
727
728		$value->createText($is);
729
730		return $value;
731	}
732
733}