From 68a0918ceb0cf0e46377713a6eba553969b04a7a Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Fri, 4 Oct 2013 20:48:15 +0100 Subject: [PATCH] General: Fix to calculation properties for Excel2007 so that the opening application will only recalculate on load if it's actually required General: Modified Excel2007 Writer to default preCalculateFormulas to false Note that autosize columns will still recalculate affected formulae internally --- Classes/PHPExcel/Writer/Excel2007.php | 11 +++++++++++ Classes/PHPExcel/Writer/Excel2007/Workbook.php | 8 ++++++-- Examples/03formulas.php | 9 +++++++++ Examples/13calculation.php | 9 +++++++++ changelog.txt | 4 ++++ 5 files changed, 39 insertions(+), 2 deletions(-) diff --git a/Classes/PHPExcel/Writer/Excel2007.php b/Classes/PHPExcel/Writer/Excel2007.php index 3d67b3db..4e93201a 100644 --- a/Classes/PHPExcel/Writer/Excel2007.php +++ b/Classes/PHPExcel/Writer/Excel2007.php @@ -35,6 +35,17 @@ */ class PHPExcel_Writer_Excel2007 extends PHPExcel_Writer_Abstract implements PHPExcel_Writer_IWriter { + /** + * Pre-calculate formulas + * Forces PHPExcel to recalculate all formulae in a workbook when saving, so that the pre-calculated values are + * immediately available to MS Excel or other office spreadsheet viewer when opening the file + * + * Overrides the default TRUE for this specific writer for performance reasons + * + * @var boolean + */ + protected $_preCalculateFormulas = FALSE; + /** * Office2003 compatibility * diff --git a/Classes/PHPExcel/Writer/Excel2007/Workbook.php b/Classes/PHPExcel/Writer/Excel2007/Workbook.php index db88e74e..2abf9ebd 100644 --- a/Classes/PHPExcel/Writer/Excel2007/Workbook.php +++ b/Classes/PHPExcel/Writer/Excel2007/Workbook.php @@ -194,10 +194,14 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write { $objWriter->startElement('calcPr'); - $objWriter->writeAttribute('calcId', '124519'); + // Set the calcid to a higher value than Excel itself will use, otherwise Excel will always recalc + // If MS Excel does do a recalc, then users opening a file in MS Excel will be prompted to save on exit + // because the file has changed + $objWriter->writeAttribute('calcId', '999999'); $objWriter->writeAttribute('calcMode', 'auto'); // fullCalcOnLoad isn't needed if we've recalculating for the save - $objWriter->writeAttribute('fullCalcOnLoad', ($recalcRequired) ? '0' : '1'); + $objWriter->writeAttribute('calcCompleted', ($recalcRequired) ? 1 : 0); + $objWriter->writeAttribute('fullCalcOnLoad', ($recalcRequired) ? 0 : 1); $objWriter->endElement(); } diff --git a/Examples/03formulas.php b/Examples/03formulas.php index 04e56d24..b493aa5f 100644 --- a/Examples/03formulas.php +++ b/Examples/03formulas.php @@ -107,6 +107,15 @@ echo date('H:i:s') , " Write to Excel2007 format" , EOL; $callStartTime = microtime(true); $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007'); + +// +// If we set Pre Calculated Formulas to true then PHPExcel will calculate all formulae in the +// workbook before saving. This adds time and memory overhead, and can cause some problems with formulae +// using functions or features (such as array formulae) that aren't yet supported by the calculation engine +// If the value is false (the default) for the Excel2007 Writer, then MS Excel (or the application used to +// open the file) will need to recalculate values itself to guarantee that the correct results are available. +// +//$objWriter->setPreCalculateFormulas(true); $objWriter->save(str_replace('.php', '.xlsx', __FILE__)); $callEndTime = microtime(true); $callTime = $callEndTime - $callStartTime; diff --git a/Examples/13calculation.php b/Examples/13calculation.php index c1c0de8d..a8f17b0d 100644 --- a/Examples/13calculation.php +++ b/Examples/13calculation.php @@ -207,6 +207,15 @@ echo date('H:i:s') , " Write to Excel2007 format" , EOL; $callStartTime = microtime(true); $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007'); + +// +// If we set Pre Calculated Formulas to true then PHPExcel will calculate all formulae in the +// workbook before saving. This adds time and memory overhead, and can cause some problems with formulae +// using functions or features (such as array formulae) that aren't yet supported by the calculation engine +// If the value is false (the default) for the Excel2007 Writer, then MS Excel (or the application used to +// open the file) will need to recalculate values itself to guarantee that the correct results are available. +// +//$objWriter->setPreCalculateFormulas(true); $objWriter->save(str_replace('.php', '.xlsx', __FILE__)); $callEndTime = microtime(true); $callTime = $callEndTime - $callStartTime; diff --git a/changelog.txt b/changelog.txt index cbbc50ff..3eca4dc1 100644 --- a/changelog.txt +++ b/changelog.txt @@ -33,6 +33,10 @@ Fixed in develop branch for release v1.8.0: - Feature: (MBaker) - Added Horizontal FILL alignment for Excel5 and Excel2007 Readers/Writers, and Horizontal DISTRIBUTED alignment for Excel2007 Reader/Writer - General: (cdhutch) Work item 20055 - Remove array_shift in ReferenceHelper::insertNewBefore improves column or row delete speed - General: (MBaker) - Improve stock chart handling and rendering, with help from Swashata Ghosh +- General: (MBaker) - Fix to calculation properties for Excel2007 so that the opening application will only recalculate on load + if it's actually required +- General: (MBaker) - Modified Excel2007 Writer to default preCalculateFormulas to false + Note that autosize columns will still recalculate affected formulae internally Fixed in develop branch for release v1.7.9: