From f897a2d808f75d2dccd8eac293f95873922d77cd Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Thu, 2 Sep 2010 13:38:17 +0000 Subject: [PATCH] Feature: Work item 8769 - Implement Gnumeric File Format Initial work on Gnumeric Reader (Worksheet Data and basic Document Properties) git-svn-id: https://phpexcel.svn.codeplex.com/svn/trunk@60279 2327b42d-5241-43d6-9e2a-de5ac946f064 --- Classes/PHPExcel/IOFactory.php | 4 + Classes/PHPExcel/Reader/Gnumeric.php | 428 +++++++++++++++++++++++++++ changelog.txt | 4 +- 3 files changed, 435 insertions(+), 1 deletion(-) create mode 100644 Classes/PHPExcel/Reader/Gnumeric.php diff --git a/Classes/PHPExcel/IOFactory.php b/Classes/PHPExcel/IOFactory.php index 8b92bf50..f7a6d0ab 100644 --- a/Classes/PHPExcel/IOFactory.php +++ b/Classes/PHPExcel/IOFactory.php @@ -75,6 +75,7 @@ class PHPExcel_IOFactory 'Excel2003XML', 'OOCalc', 'SYLK', + 'Gnumeric', 'Serialized', 'CSV', ); @@ -247,6 +248,9 @@ class PHPExcel_IOFactory case 'xml': $reader = self::createReader('Excel2003XML'); break; + case 'gnumeric': + $reader = self::createReader('Gnumeric'); + break; case 'csv': // Do nothing // We must not try to use CSV reader since it loads diff --git a/Classes/PHPExcel/Reader/Gnumeric.php b/Classes/PHPExcel/Reader/Gnumeric.php new file mode 100644 index 00000000..e0bb94a7 --- /dev/null +++ b/Classes/PHPExcel/Reader/Gnumeric.php @@ -0,0 +1,428 @@ +_readDataOnly; + } + + /** + * Set read data only + * + * @param boolean $pValue + * @return PHPExcel_Reader_Gnumeric + */ + public function setReadDataOnly($pValue = false) { + $this->_readDataOnly = $pValue; + return $this; + } + + /** + * Get which sheets to load + * + * @return mixed + */ + public function getLoadSheetsOnly() + { + return $this->_loadSheetsOnly; + } + + /** + * Set which sheets to load + * + * @param mixed $value + * @return PHPExcel_Reader_Gnumeric + */ + public function setLoadSheetsOnly($value = null) + { + $this->_loadSheetsOnly = is_array($value) ? + $value : array($value); + return $this; + } + + /** + * Set all sheets to load + * + * @return PHPExcel_Reader_Gnumeric + */ + public function setLoadAllSheets() + { + $this->_loadSheetsOnly = null; + return $this; + } + + /** + * Read filter + * + * @return PHPExcel_Reader_IReadFilter + */ + public function getReadFilter() { + return $this->_readFilter; + } + + /** + * Set read filter + * + * @param PHPExcel_Reader_IReadFilter $pValue + * @return PHPExcel_Reader_Gnumeric + */ + public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) { + $this->_readFilter = $pValue; + return $this; + } + + /** + * Create a new PHPExcel_Reader_Gnumeric + */ + public function __construct() { + $this->_sheetIndex = 0; + $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); + $this->_referenceHelper = PHPExcel_ReferenceHelper::getInstance(); + } + + /** + * Can the current PHPExcel_Reader_IReader read the file? + * + * @param string $pFileName + * @return boolean + */ + public function canRead($pFilename) + { + // Check if zip class exists + if (!function_exists('gzread')) { + return false; + } + + // Check if file exists + if (!file_exists($pFilename)) { + throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + return true; + } + + /** + * Loads PHPExcel from file + * + * @param string $pFilename + * @return PHPExcel + * @throws Exception + */ + public function load($pFilename) + { + // Create new PHPExcel + $objPHPExcel = new PHPExcel(); + + // Load into this instance + return $this->loadIntoExisting($pFilename, $objPHPExcel); + } + + private static function identifyFixedStyleValue($styleList,&$styleAttributeValue) { + $styleAttributeValue = strtolower($styleAttributeValue); + foreach($styleList as $style) { + if ($styleAttributeValue == strtolower($style)) { + $styleAttributeValue = $style; + return true; + } + } + return false; + } + + private function _gzfileGetContents($filename) { + $file = @gzopen($filename, 'rb'); + if ($file !== false) { + $data = ''; + while (!gzeof($file)) { + $data .= gzread($file, 1024); + } + gzclose($file); + } + return $data; + } + + /** + * Loads PHPExcel from file into PHPExcel instance + * + * @param string $pFilename + * @param PHPExcel $objPHPExcel + * @return PHPExcel + * @throws Exception + */ + public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $timezoneObj = new DateTimeZone('Europe/London'); + $GMT = new DateTimeZone('UTC'); + + $gFileData = $this->_gzfileGetContents($pFilename); + +// echo '
';
+//		echo htmlentities($gFileData);
+//		echo '

'; +// + $xml = simplexml_load_string($gFileData); + $namespacesMeta = $xml->getNamespaces(true); + +// var_dump($namespacesMeta); +// + $gnmXML = $xml->children($namespacesMeta['gnm']); + + $officeXML = $xml->children($namespacesMeta['office']); + $officeDocXML = $officeXML->{'document-meta'}; + $officeDocMetaXML = $officeDocXML->meta; + + $docProps = $objPHPExcel->getProperties(); + + foreach($officeDocMetaXML as $officePropertyData) { + + $officePropertyDC = array(); + if (isset($namespacesMeta['dc'])) { + $officePropertyDC = $officePropertyData->children($namespacesMeta['dc']); + } + foreach($officePropertyDC as $propertyName => $propertyValue) { + $propertyValue = (string) $propertyValue; + switch ($propertyName) { + case 'title' : + $docProps->setTitle(trim($propertyValue)); + break; + case 'subject' : + $docProps->setSubject(trim($propertyValue)); + break; + case 'creator' : + $docProps->setCreator(trim($propertyValue)); + break; + case 'date' : + $creationDate = strtotime(trim($propertyValue)); + $docProps->setCreated($creationDate); + break; + case 'description' : + $docProps->setDescription(trim($propertyValue)); + break; + } + } + $officePropertyMeta = array(); + if (isset($namespacesMeta['meta'])) { + $officePropertyMeta = $officePropertyData->children($namespacesMeta['meta']); + } + foreach($officePropertyMeta as $propertyName => $propertyValue) { + $attributes = $propertyValue->attributes($namespacesMeta['meta']); + $propertyValue = (string) $propertyValue; + switch ($propertyName) { + case 'keyword' : + $docProps->setKeywords(trim($propertyValue)); + break; + case 'initial-creator' : + $docProps->setCreator(trim($propertyValue)); + break; + case 'creation-date' : + $creationDate = strtotime(trim($propertyValue)); + $docProps->setCreated($creationDate); + break; + case 'user-defined' : + list(,$attrName) = explode(':',$attributes['name']); + switch ($attrName) { + case 'publisher' : + $docProps->setCompany(trim($propertyValue)); + break; + case 'category' : + $docProps->setCategory(trim($propertyValue)); + break; + case 'manager' : + $docProps->setManager(trim($propertyValue)); + break; + } + break; + } + } + } + + + $worksheetID = 0; + foreach($gnmXML->Sheets->Sheet as $sheet) { + $worksheetName = (string) $sheet->Name; +// echo 'Worksheet: ',$worksheetName,'
'; + if ((isset($this->_loadSheetsOnly)) && (!in_array($worksheetName, $this->_loadSheetsOnly))) { + continue; + } + + // Create new Worksheet + $objPHPExcel->createSheet(); + $objPHPExcel->setActiveSheetIndex($worksheetID); + $objPHPExcel->getActiveSheet()->setTitle($worksheetName); + + foreach($sheet->Cells->Cell as $cell) { + $cellAttributes = $cell->attributes(); + $row = (string) $cellAttributes->Row + 1; + $column = PHPExcel_Cell::stringFromColumnIndex($cellAttributes->Col); + $ValueType = $cellAttributes->ValueType; + $ExprID = (string) $cellAttributes->ExprID; +// echo 'Cell ',$column,$row,'
'; +// echo 'Type is ',$ValueType,'
'; +// echo 'Value is ',$cell,'
'; + $type = PHPExcel_Cell_DataType::TYPE_FORMULA; + if ($ExprID > '') { + if (((string) $cell) > '') { + + $this->_expressions[$ExprID] = array( 'column' => $cellAttributes->Col, + 'row' => $cellAttributes->Row, + 'formula' => (string) $cell + ); +// echo 'NEW EXPRESSION ',$ExprID,'
'; + } else { + $expression = $this->_expressions[$ExprID]; + + $cell = $this->_referenceHelper->updateFormulaReferences( $expression['formula'], + 'A1', + $cellAttributes->Col - $expression['column'], + $cellAttributes->Row - $expression['row'], + $worksheetName + ); +// echo 'SHARED EXPRESSION ',$ExprID,'
'; +// echo 'New Value is ',$cell,'
'; + } + } + switch($ValueType) { + case '20' : + $type = PHPExcel_Cell_DataType::TYPE_BOOL; + $cell = ($cell == 'TRUE') ? True : False; + break; + case '40' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + break; + case '60' : + $type = PHPExcel_Cell_DataType::TYPE_STRING; + break; + } + $objPHPExcel->getActiveSheet()->getCell($column.$row)->setValueExplicit($cell,$type); + } + + $worksheetID++; + } + + + // Return + return $objPHPExcel; + } + + /** + * Get sheet index + * + * @return int + */ + public function getSheetIndex() { + return $this->_sheetIndex; + } + + /** + * Set sheet index + * + * @param int $pValue Sheet index + * @return PHPExcel_Reader_Gnumeric + */ + public function setSheetIndex($pValue = 0) { + $this->_sheetIndex = $pValue; + return $this; + } +} diff --git a/changelog.txt b/changelog.txt index 3da0031a..fa2f94c7 100644 --- a/changelog.txt +++ b/changelog.txt @@ -24,8 +24,10 @@ Fixed in SVN: -- Bugfix: (Progi1984) Workitem 7895 - Excel5 : Formula : Percent +- Feature: (MBaker) Work item 8769 - Implement Gnumeric File Format + Initial work on Gnumeric Reader (Worksheet Data and basic Document Properties) - Feature: (MBaker) Support for Extended Workbook Properties in Excel2007, Excel5 and OOCalc Readers; support for User-defined Workbook Properties in Excel2007 and OOCalc Readers +- Bugfix: (Progi1984) Workitem 7895 - Excel5 : Formula : Percent - Bugfix: (MB) Work item 14143 - NA() doesn't propagate in matrix calc - quick fix in JAMA/Matrix.php - Bugfix: (Progi1984) Workitem 7895 - Excel5 : Formula : Error constant - Bugfix: (Progi1984) Workitem 7895 - Excel5 : Formula : Concatenation operator