在导出到Excel时,像处理任何其他文本值一样处理公式

我已经构build了一个报告解决scheme,可以将数据导出为Excel。 使用PHPExcel,这个工作很漂亮。 但是,我们需要构build仪表板样式模板表,并在运行时将其插入到输出中,包括公式。 我有这一切工作正常,我的问题是,有时这些仪表板模板是相当复杂的PHPExcel扼stream圈公式的时候,它会尝试输出。

我花了相当多的时间find解决方法,甚至去分叉我自己,并添加一个禁用计算,将试图阻止处理公式的方法,但不能得到它的工作。 我也试过禁用计算caching。

@MarkBaker在这个库上做了一个非常棒的工作,我已经多次看到他提到的这个并不是为了修改文件而devise的,但是如果做得非常仔细的话,它似乎就可以工作。

我的问题是,我如何告诉PHPExcel 停止尝试计算公式? 我希望它像对待任何其他文本值一样对待它们,并让Excel自己处理validation。 这可能吗?

作为一个例子,下面是一个PHPExcel似乎不喜欢的公式:

=IFERROR(IF($L$3="UNITS",COUNTIF('K1_Current_Accounts'!$M$2:$M$10000,'Snapshot Summary'!H5)+COUNTIF('K1_Current_Available'!$M$2:$M$10000,'Snapshot Summary'!H5),IF($L$3="Cost Basis",SUMIF('K1_Current_Accounts'!$M$2:$M$10000,'Snapshot Summary'!H5,'K1_Current_Accounts'!$E$2:$E$10000)+SUMIF('K1_Current_Available'!$M$2:$M$10000,'Snapshot Summary'!H5,'K1_Current_Available'!$E$2:$E$10000),IF($L$3="Notes",SUMIFS('K1_Current_Accounts'!$AA$2:$AA$10000,'K1_Current_Accounts'!$M$2:$M$10000,'Snapshot Summary'!H5,'K1_Current_Accounts'!$R$2:$R$10000,'Snapshot Summary'!$A$7)+SUMIFS('K1_Current_Accounts'!$AA$2:$AA$10000,'K1_Current_Accounts'!$M$2:$M$10000,'Snapshot Summary'!H5,'K1_Current_Accounts'!$R$2:$R$10000,'Snapshot Summary'!$A$8)+SUMIFS('K1_Current_Accounts'!$AA$2:$AA$10000,'K1_Current_Accounts'!$M$2:$M$10000,'Snapshot Summary'!H5,'K1_Current_Accounts'!$R$2:$R$10000,'Snapshot Summary'!$A$9),IF($L$3="Cash",SUMIFS('K1_Historical_Accounts'!$AC$2:$AC$10000,'K1_Historical_Accounts'!$M$2:$M$10000,'Snapshot Summary'!H5,'K1_Historical_Accounts'!$R$2:$R$10000,'Snapshot Summary'!$A$10))))),"") 

在这里输入图像说明

我读到SUMIFS可能会导致问题,但我不知道如何按照build议(这些仪表板是由业务开发团队构build的)重构那些SUMPRODUCT 。 此外,我们有我们的列的范围去像10000,因为范围如A:A也不工作。 他们在Excel中工作得很好,所以如果我能够让PHPExcel停止validation所有事情,并让它通过,我的生活将是光荣的!

编辑

进一步看堆栈跟踪,它似乎开始发生时,它试图写一个图表:

在这里输入图像说明

编辑2

将图表生成作为这个问题的来源,只有一个图表,它的数据源是='Sales History'!$Y$4:$CR$5 ,我可以看到它肯定会尝试处理,但是这不应该这不是一个问题,因为这是一个相对简单的参考。

您可以通过将Writer的preCalculateFormulas标志设置为false来防止PHPExcel在写入时计算公式

 $objWriter->setPreCalculateFormulas(false); 

编辑

我已经对Excel2007 Writer进行了一些实验性更改,以禁用图表的单元格计算:

/PHPExcel/Writer/Excel2007/Chart.php我已经添加了一个新的属性

 protected $calculateCellValues; 

并修改writeChart()方法来接受一个额外的参数:

 public function writeChart(PHPExcel_Chart $pChart = null, $calculateCellValues = true) { $this->calculateCellValues = $calculateCellValues; 

并修改了后续调用$pChart->refresh()

 // Ensure that data series values are up-to-date before we save if ($this->calculateCellValues) { $pChart->refresh(); } 

并且在/PHPExcel/Writer/Excel2007.phpsave()方法中,我修改了对第300行的writeChart()的调用来读取:

 $objZip->addFromString( 'xl/charts/chart' . ($chartCount + 1) . '.xml', $this->getWriterPart('Chart') ->writeChart($chart, $this->preCalculateFormulas) ); 

(即,我已经将$this->preCalculateFormulas注入到图表$this->preCalculateFormulas 。)

一个临时testing表明,当生成的xlsx文件被打开时,MS Excel将自己触发一个重新计算。但是这并不是一个完整的testing

我从来没有使用PHPExcel,但我可以从SUMIF / S()更改为SUMPRODUCTS为您的公式。 您可以使用Alt + Enter使这些庞大的公式具有一定的可读性。

为了解决这个问题,Excel会在应用任何math运算时将TRUE / FALSE设置为1/0,这样就可以{TRUE,TRUE,FALSE} x {FALSE,TRUE,TRUE}得到{0,1, 0}。 然后,SUMPRODUCT将{0,1,0}乘以您想要过滤的行/列总计,然后将这些值相加。

 =IFERROR( IF($L$3="UNITS", COUNTIF('K1_Current_Accounts'!$M$2:$M$10000,'Snapshot Summary'!H5) +COUNTIF('K1_Current_Available'!$M$2:$M$10000,'Snapshot Summary'!H5), IF($L$3="Cost Basis", SUMPRODUCT(--('K1_Current_Accounts'!$M$2:$M$10000='Snapshot Summary'!H5),'K1_Current_Accounts'!$E$2:$E$10000) +SUMPRODUCT(--('K1_Current_Available'!$M$2:$M$10000='Snapshot Summary'!H5),'K1_Current_Available'!$E$2:$E$10000), IF($L$3="Notes", SUMPRODUCT('K1_Current_Accounts'!$AA$2:$AA$10000,--('K1_Current_Accounts'!$M$2:$M$10000='Snapshot Summary'!H5),--('K1_Current_Accounts'!$R$2:$R$10000='Snapshot Summary'!$A$7)) +SUMPRODUCT('K1_Current_Accounts'!$AA$2:$AA$10000,--('K1_Current_Accounts'!$M$2:$M$10000='Snapshot Summary'!H5),--('K1_Current_Accounts'!$R$2:$R$10000='Snapshot Summary'!$A$8)) +SUMPRODUCT('K1_Current_Accounts'!$AA$2:$AA$10000,--('K1_Current_Accounts'!$M$2:$M$10000='Snapshot Summary'!H5),--('K1_Current_Accounts'!$R$2:$R$10000='Snapshot Summary'!$A$9)), IF($L$3="Cash", SUMPRODUCT('K1_Historical_Accounts'!$AC$2:$AC$10000,--('K1_Historical_Accounts'!$M$2:$M$10000='Snapshot Summary'!H5),--('K1_Historical_Accounts'!$R$2:$R$10000='Snapshot Summary'!$A$10)))))) ,"")