Skip to content

Commit cf5bf08

Browse files
committed
Xlsx Reader Shared Formula with Boolean Results
A solution, at least in part, for issue PHPOffice#4280. Xlsx Reader is not handling shared formulae correctly. As a result, some cells are treated as if they contain boolean values rather than formulae.
1 parent eccbcce commit cf5bf08

File tree

3 files changed

+45
-6
lines changed

3 files changed

+45
-6
lines changed

src/PhpSpreadsheet/Reader/Xlsx.php

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,8 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
854854
}
855855

856856
// Read cell!
857+
$useFormula = isset($c->f)
858+
&& ((string) $c->f !== '' || (isset($c->f->attributes()['t']) && strtolower((string) $c->f->attributes()['t']) === 'shared'));
857859
switch ($cellDataType) {
858860
case DataType::TYPE_STRING:
859861
if ((string) $c->v != '') {
@@ -868,7 +870,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
868870

869871
break;
870872
case DataType::TYPE_BOOL:
871-
if (!isset($c->f) || ((string) $c->f) === '') {
873+
if (!$useFormula) {
872874
if (isset($c->v)) {
873875
$value = self::castToBoolean($c);
874876
} else {
@@ -883,16 +885,16 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
883885

884886
break;
885887
case DataType::TYPE_STRING2:
886-
if (isset($c->f)) {
888+
if ($useFormula) {
887889
$this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, 'castToString');
888890
self::storeFormulaAttributes($c->f, $docSheet, $r);
889891
} else {
890-
$value = self::castToString($c);
892+
$value = self::castToString($c);
891893
}
892894

893895
break;
894896
case DataType::TYPE_INLINE:
895-
if (isset($c->f)) {
897+
if ($useFormula) {
896898
$this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, 'castToError');
897899
self::storeFormulaAttributes($c->f, $docSheet, $r);
898900
} else {
@@ -901,7 +903,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
901903

902904
break;
903905
case DataType::TYPE_ERROR:
904-
if (!isset($c->f)) {
906+
if (!$useFormula) {
905907
$value = self::castToError($c);
906908
} else {
907909
// Formula
@@ -916,7 +918,7 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
916918

917919
break;
918920
default:
919-
if (!isset($c->f)) {
921+
if (!$useFormula) {
920922
$value = self::castToString($c);
921923
if (is_numeric($value)) {
922924
$value += 0;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpOffice\PhpSpreadsheetTests\Reader\Xlsx;
6+
7+
use PhpOffice\PhpSpreadsheet\IOFactory;
8+
use PHPUnit\Framework\TestCase;
9+
10+
class SharedFormulaeTest extends TestCase
11+
{
12+
public function testSharedFormulae(): void
13+
{
14+
// Boolean functions were not handled correctly.
15+
$filename = 'tests/data/Reader/XLSX/sharedformulae.xlsx';
16+
$reader = IOFactory::createReader('Xlsx');
17+
$spreadsheet = $reader->load($filename);
18+
$sheet = $spreadsheet->getActiveSheet();
19+
$expected = [
20+
[1, '=A1+1', '=A1>3', '="x"&A1'],
21+
[2, '=A2+1', '=A2>3', '="x"&A2'],
22+
[3, '=A3+1', '=A3>3', '="x"&A3'],
23+
[4, '=A4+1', '=A4>3', '="x"&A4'],
24+
[5, '=A5+1', '=A5>3', '="x"&A5'],
25+
];
26+
self::assertSame($expected, $sheet->toArray(null, false, false));
27+
$expected = [
28+
[1, 2, false, 'x1'],
29+
[2, 3, false, 'x2'],
30+
[3, 4, false, 'x3'],
31+
[4, 5, true, 'x4'],
32+
[5, 6, true, 'x5'],
33+
];
34+
self::assertSame($expected, $sheet->toArray(null, true, false));
35+
$spreadsheet->disconnectWorksheets();
36+
}
37+
}
8.88 KB
Binary file not shown.

0 commit comments

Comments
 (0)