diff --git a/Classes/PHPExcel/IOFactory.php b/Classes/PHPExcel/IOFactory.php
index 8b92bf5..f7a6d0a 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 0000000..e0bb94a
--- /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 3da0031..fa2f94c 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