Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Excel "CELL" function not recalculating after spreadhsheet opened by phpspreadsheets #2581

Closed
twistedsymphony opened this issue Feb 11, 2022 · 4 comments · Fixed by #4080
Closed

Comments

@twistedsymphony
Copy link

twistedsymphony commented Feb 11, 2022

This is:

- [x] a bug report
- [ ] a feature request
- [ ] **not** a usage question (ask them on https://stackoverflow.com/questions/tagged/phpspreadsheet or https://gitter.im/PHPOffice/PhpSpreadsheet)

What is the expected behavior?

The Function should either retain it's original calculated value or recalculate

What is the current behavior?

the function returns "#VALUE!"

What are the steps to reproduce?

Use phpspreadsheet to open the file: test.xlsx
this file include a cell function

=CONCATENATE("Prefix ",MID(CELL("filename"),FIND("]",CELL("filename"))+1,255), " Suffix")

Then use phpspreadsheet to output the file; creating a new file. The newly output file will show the formula as un-calculated. (there may be some other requirements but the behavior can be observed in the included simplified example)

test.xlsx before opening:
file_before

ouput.xlsx produced by phpspreadsheet:
file_after

Please provide a Minimal, Complete, and Verifiable example of code that exhibits the issue without relying on an external Excel file or a web server:

<?php

require __DIR__ . '/vendor/autoload.php';

$sheetReader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx');
$sheetReader = $sheetReader->load('test.xlsx');

$sheetWriter = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($sheetReader, 'Xlsx');

header('Content-Type: application/vnd.ms-excel');
header("Content-Disposition: attachment; filename=\"output.xlsx\"");
$sheetWriter->save('php://output');

Which versions of PhpSpreadsheet and PHP are affected?

This was observed on php 7.4 and phpspreadsheet 1.21.0

@twistedsymphony
Copy link
Author

I suspect the issue is related to the fact that the CELL("filename") function returns the actual filename and file path in addition to the sheet name and the file name (perhaps?) does not exist when the spreadsheet is stored in memory without an explicit reference location on disc. Thus when phpspreadsheet recalculates it's unable to properly calculate this value and the #VALUE! error gets saved as the result.

I came across this issue when upgrading an old phpExcel application to phpSpreadsheet and it functioned properly with phpExcel on php5.6

@oleibman
Copy link
Collaborator

The CELL function is not currently implemented in PhpSpreadsheet.

@MarkBaker
Copy link
Member

Note that PHPExcel also never implemented the CELL{} function

@twistedsymphony
Copy link
Author

Note that PHPExcel also never implemented the CELL{} function

That's true, however PHPExcel seems to have ignored the previously calculated CELL functions and left the result in place while PHP Spreadsheet wipes out the previously calculated data. This is the root of the problem I'm currently experiencing.

oleibman added a commit to oleibman/PhpSpreadsheet that referenced this issue Jun 30, 2024
Fix PHPOffice#2581 (not obvious - see next paragraph for explanation). This continues the work of PR PHPOffice#2902 (and also PR PHPOffice#3467) to have errors propagated through function calculations rather than treating them as strings. All text functions, and the concatenation operator, are addressed in this PR.

In the original issue, the spreadsheet being loaded uses the result of an unimplemented function as an argument to another function. When `getCalculatedValue` is used on the cell in question, the result is returned as `#VALUE!`. If the cell had just contained a function call to the unimplemented function, getCalculatedValue would have recognized the situation and returned oldCalculatedValue as the result. Not perfect, but good enough most of the time. User would like oldCalculatedValue returned here as well, which seems like a reasonable request.

PhpSpreadsheet always returns `#Not Yet Implemented` as the result for a function which it knows about but which is not yet implemented. That is the key to the `Cell` class being able to substitute oldCalculatedValue in the first place. However, in order to do that for the issue in question, that result has to be propagated to any functions for which the result is an argument. I don't want to add unimplemented to the list of known error codes, but I am willing to add a parameter to `ErrorValue::isError` to indicate whether that value should be considered an error (default is "no").

The first use of that new parameter would be by the text functions. They go through a common Helper routine, so it is pretty easily implemented. And, as it turns out, most of the text functions do not currently propagate errors, e.g. if A1 results in a value error, `=LEFT(A1,2)` will result in `#V` rather than `#VALUE!`. With this PR, they will now be handled correctly.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

3 participants