From 317f00b25904287e53c4183308029dd64084a4a4 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Mon, 23 Jul 2012 21:52:14 +0100 Subject: [PATCH] Bugfix to ensure that General format is not treated as a date format despite containg e for epoch OOCalc Reader modified to process number-rows-repeated Modify OOCalc Reader to only read cells that containing data, or merged cells (depending on setReadDataOnly setting) --- Classes/PHPExcel/Reader/OOCalc.php | 73 +++++++++++++++++++----------- Classes/PHPExcel/Shared/Date.php | 46 ++++++++++--------- changelog.txt | 1 + 3 files changed, 73 insertions(+), 47 deletions(-) diff --git a/Classes/PHPExcel/Reader/OOCalc.php b/Classes/PHPExcel/Reader/OOCalc.php index ddb5637..b10043a 100644 --- a/Classes/PHPExcel/Reader/OOCalc.php +++ b/Classes/PHPExcel/Reader/OOCalc.php @@ -319,14 +319,23 @@ class PHPExcel_Reader_OOCalc implements PHPExcel_Reader_IReader foreach ($worksheetData as $key => $rowData) { switch ($key) { case 'table-row' : + $rowDataTableAttributes = $rowData->attributes($namespacesContent['table']); + $rowRepeats = (isset($rowDataTableAttributes['number-rows-repeated'])) ? + $rowDataTableAttributes['number-rows-repeated'] : 1; $columnIndex = 0; foreach ($rowData as $key => $cellData) { - $tmpInfo['lastColumnIndex'] = max($tmpInfo['lastColumnIndex'], $columnIndex); - ++$columnIndex; + $cellDataTableAttributes = $cellData->attributes($namespacesContent['table']); + $colRepeats = (isset($cellDataTableAttributes['number-columns-repeated'])) ? + $cellDataTableAttributes['number-columns-repeated'] : 1; + $cellDataOfficeAttributes = $cellData->attributes($namespacesContent['office']); + if (isset($cellDataOfficeAttributes['value-type'])) { + $tmpInfo['lastColumnIndex'] = max($tmpInfo['lastColumnIndex'], $columnIndex + $colRepeats - 1); + $tmpInfo['totalRows'] = max($tmpInfo['totalRows'], $rowIndex + $rowRepeats); + } + $columnIndex += $colRepeats; } - ++$rowIndex; - $tmpInfo['totalRows'] = max($tmpInfo['totalRows'], $rowIndex); + $rowIndex += $rowRepeats; break; } } @@ -492,6 +501,9 @@ class PHPExcel_Reader_OOCalc implements PHPExcel_Reader_IReader break; } case 'table-row' : + $rowDataTableAttributes = $rowData->attributes($namespacesContent['table']); + $rowRepeats = (isset($rowDataTableAttributes['number-rows-repeated'])) ? + $rowDataTableAttributes['number-rows-repeated'] : 1; $columnID = 'A'; foreach($rowData as $key => $cellData) { if ($this->getReadFilter() !== NULL) { @@ -644,44 +656,53 @@ class PHPExcel_Reader_OOCalc implements PHPExcel_Reader_IReader // echo 'Adjusted Formula: '.$cellDataFormula.'
'; } - $repeats = (isset($cellDataTableAttributes['number-columns-repeated'])) ? + $colRepeats = (isset($cellDataTableAttributes['number-columns-repeated'])) ? $cellDataTableAttributes['number-columns-repeated'] : 1; if ($type !== NULL) { - for ($i = 0; $i < $repeats; ++$i) { + for ($i = 0; $i < $colRepeats; ++$i) { if ($i > 0) { ++$columnID; } - $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $dataValue),$type); - if ($hasCalculatedValue) { -// echo 'Forumla result is '.$dataValue.'
'; - $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setCalculatedValue($dataValue); - } - if ($formatting !== NULL) { - $objPHPExcel->getActiveSheet()->getStyle($columnID.$rowID)->getNumberFormat()->setFormatCode($formatting); - } - if ($hyperlink !== NULL) { - $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->getHyperlink()->setUrl($hyperlink); + if ($type !== PHPExcel_Cell_DataType::TYPE_NULL) { + for ($rowAdjust = 0; $rowAdjust < $rowRepeats; ++$rowAdjust) { + $rID = $rowID + $rowAdjust; + $objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $dataValue),$type); + if ($hasCalculatedValue) { +// echo 'Forumla result is '.$dataValue.'
'; + $objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->setCalculatedValue($dataValue); + } + if ($formatting !== NULL) { + $objPHPExcel->getActiveSheet()->getStyle($columnID.$rID)->getNumberFormat()->setFormatCode($formatting); + } else { + $objPHPExcel->getActiveSheet()->getStyle($columnID.$rID)->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_GENERAL); + } + if ($hyperlink !== NULL) { + $objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->getHyperlink()->setUrl($hyperlink); + } + } } } } // Merged cells if ((isset($cellDataTableAttributes['number-columns-spanned'])) || (isset($cellDataTableAttributes['number-rows-spanned']))) { - $columnTo = $columnID; - if (isset($cellDataTableAttributes['number-columns-spanned'])) { - $columnTo = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($columnID) + $cellDataTableAttributes['number-columns-spanned'] -2); + if (($type !== PHPExcel_Cell_DataType::TYPE_NULL) || (!$this->_readDataOnly)) { + $columnTo = $columnID; + if (isset($cellDataTableAttributes['number-columns-spanned'])) { + $columnTo = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($columnID) + $cellDataTableAttributes['number-columns-spanned'] -2); + } + $rowTo = $rowID; + if (isset($cellDataTableAttributes['number-rows-spanned'])) { + $rowTo = $rowTo + $cellDataTableAttributes['number-rows-spanned'] - 1; + } + $cellRange = $columnID.$rowID.':'.$columnTo.$rowTo; + $objPHPExcel->getActiveSheet()->mergeCells($cellRange); } - $rowTo = $rowID; - if (isset($cellDataTableAttributes['number-rows-spanned'])) { - $rowTo = $rowTo + $cellDataTableAttributes['number-rows-spanned'] - 1; - } - $cellRange = $columnID.$rowID.':'.$columnTo.$rowTo; - $objPHPExcel->getActiveSheet()->mergeCells($cellRange); } ++$columnID; } - ++$rowID; + $rowID += $rowRepeats; break; } } diff --git a/Classes/PHPExcel/Shared/Date.php b/Classes/PHPExcel/Shared/Date.php index d7b8609..20c9aeb 100644 --- a/Classes/PHPExcel/Shared/Date.php +++ b/Classes/PHPExcel/Shared/Date.php @@ -88,9 +88,9 @@ class PHPExcel_Shared_Date if (($baseDate == self::CALENDAR_WINDOWS_1900) || ($baseDate == self::CALENDAR_MAC_1904)) { self::$ExcelBaseDate = $baseDate; - return True; + return TRUE; } - return False; + return FALSE; } // function setExcelCalendar() @@ -166,12 +166,12 @@ class PHPExcel_Shared_Date * * @param mixed $dateValue PHP serialized date/time or date object * @return mixed Excel date/time value - * or boolean False on failure + * or boolean FALSE on failure */ public static function PHPToExcel($dateValue = 0) { $saveTimeZone = date_default_timezone_get(); date_default_timezone_set('UTC'); - $retValue = False; + $retValue = FALSE; if ((is_object($dateValue)) && ($dateValue instanceof self::$dateTimeObjectType)) { $retValue = self::FormattedPHPToExcel( $dateValue->format('Y'), $dateValue->format('m'), $dateValue->format('d'), $dateValue->format('H'), $dateValue->format('i'), $dateValue->format('s') @@ -204,12 +204,12 @@ class PHPExcel_Shared_Date // Fudge factor for the erroneous fact that the year 1900 is treated as a Leap Year in MS Excel // This affects every date following 28th February 1900 // - $excel1900isLeapYear = True; - if (($year == 1900) && ($month <= 2)) { $excel1900isLeapYear = False; } + $excel1900isLeapYear = TRUE; + if (($year == 1900) && ($month <= 2)) { $excel1900isLeapYear = FALSE; } $myExcelBaseDate = 2415020; } else { $myExcelBaseDate = 2416481; - $excel1900isLeapYear = False; + $excel1900isLeapYear = FALSE; } // Julian base date Adjustment @@ -264,6 +264,10 @@ class PHPExcel_Shared_Date public static function isDateTimeFormatCode($pFormatCode = '') { // Switch on formatcode switch ($pFormatCode) { + // General contains an epoch letter 'e', so we trap for it explicitly here + case PHPExcel_Style_NumberFormat::GENERAL: + return FALSE; + // Explicitly defined date formats case PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD: case PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD2: case PHPExcel_Style_NumberFormat::FORMAT_DATE_DDMMYYYY: @@ -286,32 +290,32 @@ class PHPExcel_Shared_Date case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX16: case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX17: case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX22: - return true; + return TRUE; } // Typically number, currency or accounting (or occasionally fraction) formats if ((substr($pFormatCode,0,1) == '_') || (substr($pFormatCode,0,2) == '0 ')) { - return false; + return FALSE; } // Try checking for any of the date formatting characters that don't appear within square braces if (preg_match('/(^|\])[^\[]*['.self::$possibleDateFormatCharacters.']/i',$pFormatCode)) { // We might also have a format mask containing quoted strings... // we don't want to test for any of our characters within the quoted blocks - if (strpos($pFormatCode,'"') !== false) { - $i = false; + if (strpos($pFormatCode,'"') !== FALSE) { + $i = FALSE; foreach(explode('"',$pFormatCode) as $subVal) { // Only test in alternate array entries (the non-quoted blocks) if (($i = !$i) && (preg_match('/(^|\])[^\[]*['.self::$possibleDateFormatCharacters.']/i',$subVal))) { - return true; + return TRUE; } } - return false; + return FALSE; } - return true; + return TRUE; } // No date... - return false; + return FALSE; } // function isDateTimeFormatCode() @@ -319,23 +323,23 @@ class PHPExcel_Shared_Date * Convert a date/time string to Excel time * * @param string $dateValue Examples: '2009-12-31', '2009-12-31 15:59', '2009-12-31 15:59:10' - * @return float|false Excel date/time serial value + * @return float|FALSE Excel date/time serial value */ public static function stringToExcel($dateValue = '') { if (strlen($dateValue) < 2) - return false; + return FALSE; if (!preg_match('/^(\d{1,4}[ \.\/\-][A-Z]{3,9}([ \.\/\-]\d{1,4})?|[A-Z]{3,9}[ \.\/\-]\d{1,4}([ \.\/\-]\d{1,4})?|\d{1,4}[ \.\/\-]\d{1,4}([ \.\/\-]\d{1,4})?)( \d{1,2}:\d{1,2}(:\d{1,2})?)?$/iu', $dateValue)) - return false; + return FALSE; $dateValueNew = PHPExcel_Calculation_DateTime::DATEVALUE($dateValue); if ($dateValueNew === PHPExcel_Calculation_Functions::VALUE()) { - return false; + return FALSE; } else { - if (strpos($dateValue, ':') !== false) { + if (strpos($dateValue, ':') !== FALSE) { $timeValue = PHPExcel_Calculation_DateTime::TIMEVALUE($dateValue); if ($timeValue === PHPExcel_Calculation_Functions::VALUE()) { - return false; + return FALSE; } $dateValueNew += $timeValue; } diff --git a/changelog.txt b/changelog.txt index de7e90d..092b3eb 100644 --- a/changelog.txt +++ b/changelog.txt @@ -89,6 +89,7 @@ Fixed in develop branch: - Bugfix: (seltzlab) Fix to excel2007 Chart Writer when a $plotSeriesValues is empty - Bugfix: (MBaker) Work item 18370 - Error loading xlsx file with column breaks - Bugfix: (MBaker) OOCalc Reader now handles percentage and currency data types +- Bugfix: (MBaker) OOCalc Reader modified to process number-rows-repeated 2012-05-19 (v1.7.7):