mirror of
https://github.com/PHPOffice/PhpSpreadsheet.git
synced 2026-09-17 13:36:49 +00:00
Merge branch 'master' into issue4656
This commit is contained in:
@@ -303,6 +303,10 @@ class Html extends BaseReader
|
||||
// ... we return the cell, so we can mess about with styles more easily
|
||||
|
||||
// Set cell value explicitly if there is data-type attribute
|
||||
if (isset($attributeArray['data-checkbox'])) {
|
||||
$sheet->getStyle($column . $row)
|
||||
->setCheckBox(true);
|
||||
}
|
||||
if (isset($attributeArray['data-type'])) {
|
||||
$datatype = $attributeArray['data-type'];
|
||||
if (in_array($datatype, [DataType::TYPE_STRING, DataType::TYPE_STRING2, DataType::TYPE_INLINE])) {
|
||||
@@ -335,7 +339,15 @@ class Html extends BaseReader
|
||||
$hyperlink = $sheet->hyperlinkExists($column . $row) ? $sheet->getHyperlink($column . $row) : null;
|
||||
|
||||
try {
|
||||
$sheet->setCellValueExplicit($column . $row, $cellContent, $attributeArray['data-type']);
|
||||
if (isset($attributeArray['data-formula'])) {
|
||||
$sheet->setCellValueExplicit($column . $row, $attributeArray['data-formula'], DataType::TYPE_FORMULA);
|
||||
$sheet->getCell($column . $row)
|
||||
->setCalculatedValue(
|
||||
$cellContent
|
||||
);
|
||||
} else {
|
||||
$sheet->setCellValueExplicit($column . $row, $cellContent, $attributeArray['data-type']);
|
||||
}
|
||||
} catch (SpreadsheetException) {
|
||||
$sheet->setCellValue($column . $row, $cellContent);
|
||||
}
|
||||
|
||||
@@ -96,6 +96,15 @@ class Html extends BaseWriter
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected bool $dataFormula = false;
|
||||
|
||||
public function setDataFormula(bool $dataFormula): self
|
||||
{
|
||||
$this->dataFormula = $dataFormula;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use inline CSS?
|
||||
*/
|
||||
@@ -1701,20 +1710,24 @@ class Html extends BaseWriter
|
||||
$htmlx .= $this->generateRowIncludeCharts($worksheet, $coordinate);
|
||||
// Column start
|
||||
$html .= ' <' . $cellType;
|
||||
if ($worksheet->getStyle($coordinate)->getCheckbox()) {
|
||||
$html .= ' data-checkbox="1"';
|
||||
}
|
||||
$dataType = $worksheet->getCell($coordinate)->getDataType();
|
||||
if ($this->betterBoolean) {
|
||||
$dataType = $worksheet->getCell($coordinate)->getDataType();
|
||||
if ($dataType === DataType::TYPE_BOOL) {
|
||||
$html .= ' data-type="' . DataType::TYPE_BOOL . '"';
|
||||
} elseif ($dataType === DataType::TYPE_FORMULA && $this->preCalculateFormulas) {
|
||||
try {
|
||||
if (
|
||||
is_bool(
|
||||
$worksheet
|
||||
->getCell($coordinate)
|
||||
->getCalculatedValue()
|
||||
)
|
||||
) {
|
||||
$calculatedValue = $worksheet
|
||||
->getCell($coordinate)
|
||||
->getCalculatedValue();
|
||||
if (is_bool($calculatedValue)) {
|
||||
$html .= ' data-type="' . DataType::TYPE_BOOL . '"';
|
||||
} elseif ($this->dataFormula && is_string($calculatedValue)) {
|
||||
$html .= ' data-type="' . DataType::TYPE_STRING . '"';
|
||||
} elseif ($this->dataFormula && (is_int($calculatedValue) || is_float($calculatedValue))) {
|
||||
$html .= ' data-type="' . DataType::TYPE_NUMERIC . '"';
|
||||
}
|
||||
} catch (CalculationException) {
|
||||
$html .= ' data-type="' . DataType::TYPE_ERROR . '"';
|
||||
@@ -1723,6 +1736,16 @@ class Html extends BaseWriter
|
||||
$html .= ' data-type="' . DataType::TYPE_STRING . '"';
|
||||
}
|
||||
}
|
||||
if ($dataType === DataType::TYPE_FORMULA && $this->dataFormula) {
|
||||
if ($this->preCalculateFormulas) {
|
||||
$html .= ' data-formula="'
|
||||
. htmlspecialchars(
|
||||
$worksheet->getCell($coordinate)
|
||||
->getValueString()
|
||||
)
|
||||
. '"';
|
||||
}
|
||||
}
|
||||
$holdCss = '';
|
||||
if (!$this->useInlineCss && !$this->isPdf && is_string($cssClass)) {
|
||||
$html .= ' class="' . $cssClass . '"';
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Reader\Html;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Html as HtmlReader;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Html as HtmlWriter;
|
||||
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
|
||||
|
||||
class DataFormulaTest extends AbstractFunctional
|
||||
{
|
||||
public function testDataFormula(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$sheet->setCellValue('A1', true);
|
||||
$sheet->setCellValue('A2', false);
|
||||
$sheet->setCellValue('A3', false); // no checkbox
|
||||
$sheet->getStyle('A1')->setCheckBox(true);
|
||||
$sheet->getStyle('A2')->setCheckBox(true);
|
||||
$sheet->setCellValue('B1', '=AND(TRUE,TRUE)');
|
||||
$sheet->setCellValue('B2', '=AND(TRUE,FALSE)');
|
||||
$sheet->setCellValue('B3', '=AND(FALSE,TRUE)'); // no checkbox
|
||||
$sheet->getStyle('B1')->setCheckBox(true);
|
||||
$sheet->getStyle('B2')->setCheckBox(true);
|
||||
$sheet->setCellValue('C1', '="A"&"B"&"C"');
|
||||
$sheet->setCellValue('C2', 5);
|
||||
$sheet->setCellValue('C3', '=3+2');
|
||||
|
||||
$writer = new HtmlWriter($spreadsheet);
|
||||
$this->writeDataFormula($writer);
|
||||
$content = $writer->generateHtmlAll();
|
||||
$expected = '<td data-checkbox="1" data-type="b" class="column0 style1 b">☑</td>';
|
||||
self::assertStringContainsString($expected, $content, 'bool non-formula');
|
||||
$expected = '<td data-checkbox="1" data-type="b" data-formula="=AND(TRUE,TRUE)" class="column1 style1 b">☑</td>';
|
||||
self::assertStringContainsString($expected, $content, 'bool formula');
|
||||
$expected = '<td data-type="s" data-formula="="A"&"B"&"C"" class="column2 style0 s">ABC</td>';
|
||||
self::assertStringContainsString($expected, $content, 'string formula requiring escaped characters');
|
||||
$expected = '<td class="column2 style0 n">5</td>';
|
||||
self::assertStringContainsString($expected, $content, 'numeric non-formula');
|
||||
$expected = '<td data-type="n" data-formula="=3+2" class="column2 style0 n">5</td>';
|
||||
self::assertStringContainsString($expected, $content, 'numeric formula');
|
||||
|
||||
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Html', null, $this->writeDataFormula(...));
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
|
||||
$rsheet = $reloadedSpreadsheet->getActiveSheet();
|
||||
self::assertTrue($rsheet->getCell('A1')->getValue());
|
||||
self::assertFalse($rsheet->getCell('A2')->getValue());
|
||||
self::assertFalse($rsheet->getCell('A3')->getValue());
|
||||
self::assertTrue($rsheet->getStyle('A1')->getCheckBox());
|
||||
self::assertTrue($rsheet->getStyle('A2')->getCheckBox());
|
||||
self::assertFalse($rsheet->getStyle('A3')->getCheckBox());
|
||||
|
||||
self::assertSame('=AND(TRUE,TRUE)', $rsheet->getCell('B1')->getValue());
|
||||
self::assertTrue(
|
||||
$rsheet->getCell('B1')->getOldCalculatedValue()
|
||||
);
|
||||
self::assertTrue(
|
||||
$rsheet->getCell('B1')->getCalculatedValue()
|
||||
);
|
||||
self::assertTrue($rsheet->getStyle('B1')->getCheckBox());
|
||||
|
||||
self::assertSame('=AND(TRUE,FALSE)', $rsheet->getCell('B2')->getValue());
|
||||
self::assertFalse(
|
||||
$rsheet->getCell('B2')->getOldCalculatedValue()
|
||||
);
|
||||
self::assertFalse(
|
||||
$rsheet->getCell('B2')->getCalculatedValue()
|
||||
);
|
||||
self::assertTrue($rsheet->getStyle('B2')->getCheckBox());
|
||||
|
||||
self::assertSame('=AND(FALSE,TRUE)', $rsheet->getCell('B3')->getValue());
|
||||
self::assertFalse(
|
||||
$rsheet->getCell('B3')->getOldCalculatedValue()
|
||||
);
|
||||
self::assertFalse(
|
||||
$rsheet->getCell('B3')->getCalculatedValue()
|
||||
);
|
||||
self::assertFalse($rsheet->getStyle('B3')->getCheckBox());
|
||||
|
||||
self::assertSame('="A"&"B"&"C"', $rsheet->getCell('C1')->getValue());
|
||||
self::assertSame(
|
||||
'ABC',
|
||||
$rsheet->getCell('C1')->getOldCalculatedValue()
|
||||
);
|
||||
self::assertSame(
|
||||
'ABC',
|
||||
$rsheet->getCell('C1')->getCalculatedValue()
|
||||
);
|
||||
|
||||
self::assertSame(5, $rsheet->getCell('C2')->getValue());
|
||||
self::assertNull(
|
||||
$rsheet->getCell('C2')->getOldCalculatedValue()
|
||||
);
|
||||
self::assertSame(
|
||||
5,
|
||||
$rsheet->getCell('C2')->getCalculatedValue()
|
||||
);
|
||||
|
||||
self::assertSame('=3+2', $rsheet->getCell('C3')->getValue());
|
||||
self::assertSame(
|
||||
5,
|
||||
$rsheet->getCell('C3')->getOldCalculatedValue()
|
||||
);
|
||||
self::assertSame(
|
||||
5,
|
||||
$rsheet->getCell('C3')->getCalculatedValue()
|
||||
);
|
||||
|
||||
$reloadedSpreadsheet->disconnectWorksheets();
|
||||
}
|
||||
|
||||
private function writeDataFormula(HtmlWriter $writer): void
|
||||
{
|
||||
$writer->setDataFormula(true);
|
||||
}
|
||||
|
||||
public function testNoPreCalculate(): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$sheet->setCellValue('A1', true);
|
||||
$sheet->setCellValue('A2', false);
|
||||
$sheet->setCellValue('A3', false); // no checkbox
|
||||
$sheet->getStyle('A1')->setCheckBox(true);
|
||||
$sheet->getStyle('A2')->setCheckBox(true);
|
||||
$sheet->setCellValue('B1', '=AND(TRUE,TRUE)');
|
||||
$sheet->setCellValue('B2', '=AND(TRUE,FALSE)');
|
||||
$sheet->setCellValue('B3', '=AND(FALSE,TRUE)'); // no checkbox
|
||||
$sheet->getStyle('B1')->setCheckBox(true);
|
||||
$sheet->getStyle('B2')->setCheckBox(true);
|
||||
$sheet->setCellValue('C1', '="A"&"B"&"C"');
|
||||
$sheet->setCellValue('C2', 5);
|
||||
$sheet->setCellValue('C3', '=3+2');
|
||||
|
||||
$writer = new HtmlWriter($spreadsheet);
|
||||
$this->writeDataFormula($writer);
|
||||
$writer->setPreCalculateFormulas(false);
|
||||
$content = $writer->generateHtmlAll();
|
||||
$expected = '<td data-checkbox="1" data-type="b" class="column0 style1 b">☑</td>';
|
||||
self::assertStringContainsString($expected, $content, 'bool non-formula');
|
||||
$expected = '<td data-checkbox="1" class="column1 style1 f">=AND(TRUE,TRUE)</td>';
|
||||
self::assertStringContainsString($expected, $content, 'bool formula');
|
||||
$expected = '<td class="column2 style0 f">="A"&"B"&"C"</td>';
|
||||
self::assertStringContainsString($expected, $content, 'string formula requiring escaped characters');
|
||||
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
$reader = new HtmlReader();
|
||||
$reloadedSpreadsheet = $reader->loadFromString($content);
|
||||
$rsheet = $reloadedSpreadsheet->getActiveSheet();
|
||||
self::assertTrue($rsheet->getStyle('B1')->getCheckBox());
|
||||
$reloadedSpreadsheet->disconnectWorksheets();
|
||||
}
|
||||
}
|
||||
@@ -82,9 +82,8 @@ class StyleCheckBoxTest extends AbstractFunctional
|
||||
self::assertSame('=AND(TRUE,TRUE)', $sheet->getCell('B1')->getValue());
|
||||
self::assertSame('=AND(FALSE,TRUE)', $sheet->getCell('B2')->getValue());
|
||||
self::assertSame('=AND(TRUE,FALSE)', $sheet->getCell('B3')->getValue());
|
||||
// Formulas not evaluated, so no checkboxes.
|
||||
self::assertFalse($sheet->getStyle('B1')->getCheckBox());
|
||||
self::assertFalse($sheet->getStyle('B2')->getCheckBox());
|
||||
self::assertTrue($sheet->getStyle('B1')->getCheckBox());
|
||||
self::assertTrue($sheet->getStyle('B2')->getCheckBox());
|
||||
self::assertFalse($sheet->getStyle('B3')->getCheckBox());
|
||||
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
|
||||
@@ -20,16 +20,18 @@ class Issue3982Test extends TestCase
|
||||
* We can mitigate the problem by changing entirely-null rows
|
||||
* to empty rows in rangeToArrayYieldRows. (uses 455MB).
|
||||
* That's a breaking change, but might be worth considering.
|
||||
*
|
||||
* Aha! I have narrowed the problem to self::assertCount,
|
||||
* which has a ready substitution. I will report the problem
|
||||
* to Phpunit if I can come up with a simpler example.
|
||||
*/
|
||||
public function testLoadAllRows(): void
|
||||
{
|
||||
if (!method_exists(TestCase::class, 'setOutputCallback')) {
|
||||
self::markTestSkipped('Memory loop in Phpunit 10');
|
||||
}
|
||||
$spreadsheet = IOFactory::load(self::$testbook);
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$data = $sheet->toArray(null, true, false, true);
|
||||
self::assertCount(1048576, $data);
|
||||
$count = count($data);
|
||||
self::assertSame(1_048_576, $count);
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user