mirror of
https://github.com/PHPOffice/PhpSpreadsheet.git
synced 2026-09-10 10:06:30 +00:00
Merge branch 'master' into NumberFormat-Wizards_Non-breaking-space
This commit is contained in:
@@ -7,6 +7,7 @@ use DOMElement;
|
||||
use DOMNode;
|
||||
use DOMText;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||
use PhpOffice\PhpSpreadsheet\Helper\Dimension as CssDimension;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Security\XmlScanner;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
@@ -283,15 +284,35 @@ class Html extends BaseReader
|
||||
* @param int|string $row
|
||||
* @param mixed $cellContent
|
||||
*/
|
||||
protected function flushCell(Worksheet $sheet, $column, $row, &$cellContent): void
|
||||
protected function flushCell(Worksheet $sheet, $column, $row, &$cellContent, array $attributeArray): void
|
||||
{
|
||||
if (is_string($cellContent)) {
|
||||
// Simple String content
|
||||
if (trim($cellContent) > '') {
|
||||
// Only actually write it if there's content in the string
|
||||
// Write to worksheet to be done here...
|
||||
// ... we return the cell so we can mess about with styles more easily
|
||||
$sheet->setCellValue($column . $row, $cellContent);
|
||||
// ... 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-type'])) {
|
||||
$datatype = $attributeArray['data-type'];
|
||||
if (in_array($datatype, [DataType::TYPE_STRING, DataType::TYPE_STRING2, DataType::TYPE_INLINE])) {
|
||||
//Prevent to Excel treat string with beginning equal sign or convert big numbers to scientific number
|
||||
if (substr($cellContent, 0, 1) === '=') {
|
||||
$sheet->getCell($column . $row)
|
||||
->getStyle()
|
||||
->setQuotePrefix(true);
|
||||
}
|
||||
}
|
||||
//catching the Exception and ignoring the invalid data types
|
||||
try {
|
||||
$sheet->setCellValueExplicit($column . $row, $cellContent, $attributeArray['data-type']);
|
||||
} catch (\PhpOffice\PhpSpreadsheet\Exception $exception) {
|
||||
$sheet->setCellValue($column . $row, $cellContent);
|
||||
}
|
||||
} else {
|
||||
$sheet->setCellValue($column . $row, $cellContent);
|
||||
}
|
||||
$this->dataArray[$row][$column] = $cellContent;
|
||||
}
|
||||
} else {
|
||||
@@ -355,7 +376,7 @@ class Html extends BaseReader
|
||||
private function processDomElementHr(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child, array &$attributeArray): void
|
||||
{
|
||||
if ($child->nodeName === 'hr') {
|
||||
$this->flushCell($sheet, $column, $row, $cellContent);
|
||||
$this->flushCell($sheet, $column, $row, $cellContent, $attributeArray);
|
||||
++$row;
|
||||
if (isset($this->formats[$child->nodeName])) {
|
||||
$sheet->getStyle($column . $row)->applyFromArray($this->formats[$child->nodeName]);
|
||||
@@ -375,7 +396,7 @@ class Html extends BaseReader
|
||||
$sheet->getStyle($column . $row)->getAlignment()->setWrapText(true);
|
||||
} else {
|
||||
// Otherwise flush our existing content and move the row cursor on
|
||||
$this->flushCell($sheet, $column, $row, $cellContent);
|
||||
$this->flushCell($sheet, $column, $row, $cellContent, $attributeArray);
|
||||
++$row;
|
||||
}
|
||||
} else {
|
||||
@@ -421,11 +442,11 @@ class Html extends BaseReader
|
||||
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
||||
} else {
|
||||
if ($cellContent > '') {
|
||||
$this->flushCell($sheet, $column, $row, $cellContent);
|
||||
$this->flushCell($sheet, $column, $row, $cellContent, $attributeArray);
|
||||
++$row;
|
||||
}
|
||||
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
||||
$this->flushCell($sheet, $column, $row, $cellContent);
|
||||
$this->flushCell($sheet, $column, $row, $cellContent, $attributeArray);
|
||||
|
||||
if (isset($this->formats[$child->nodeName])) {
|
||||
$sheet->getStyle($column . $row)->applyFromArray($this->formats[$child->nodeName]);
|
||||
@@ -448,11 +469,11 @@ class Html extends BaseReader
|
||||
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
||||
} else {
|
||||
if ($cellContent > '') {
|
||||
$this->flushCell($sheet, $column, $row, $cellContent);
|
||||
$this->flushCell($sheet, $column, $row, $cellContent, $attributeArray);
|
||||
}
|
||||
++$row;
|
||||
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
||||
$this->flushCell($sheet, $column, $row, $cellContent);
|
||||
$this->flushCell($sheet, $column, $row, $cellContent, $attributeArray);
|
||||
$column = 'A';
|
||||
}
|
||||
} else {
|
||||
@@ -472,7 +493,7 @@ class Html extends BaseReader
|
||||
private function processDomElementTable(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child, array &$attributeArray): void
|
||||
{
|
||||
if ($child->nodeName === 'table') {
|
||||
$this->flushCell($sheet, $column, $row, $cellContent);
|
||||
$this->flushCell($sheet, $column, $row, $cellContent, $attributeArray);
|
||||
$column = $this->setTableStartColumn($column);
|
||||
if ($this->tableLevel > 1 && $row > 1) {
|
||||
--$row;
|
||||
@@ -574,7 +595,7 @@ class Html extends BaseReader
|
||||
// apply inline style
|
||||
$this->applyInlineStyle($sheet, $row, $column, $attributeArray);
|
||||
|
||||
$this->flushCell($sheet, $column, $row, $cellContent);
|
||||
$this->flushCell($sheet, $column, $row, $cellContent, $attributeArray);
|
||||
|
||||
$this->processDomElementBgcolor($sheet, $row, $column, $attributeArray);
|
||||
$this->processDomElementWidth($sheet, $column, $attributeArray);
|
||||
|
||||
@@ -507,26 +507,6 @@ class Xlsx extends BaseReader
|
||||
$relsWorkbook = $this->loadZip("$dir/_rels/" . basename($relTarget) . '.rels', '');
|
||||
$relsWorkbook->registerXPathNamespace('rel', Namespaces::RELATIONSHIPS);
|
||||
|
||||
$sharedStrings = [];
|
||||
$relType = "rel:Relationship[@Type='"
|
||||
//. Namespaces::SHARED_STRINGS
|
||||
. "$xmlNamespaceBase/sharedStrings"
|
||||
. "']";
|
||||
$xpath = self::getArrayItem($relsWorkbook->xpath($relType));
|
||||
|
||||
if ($xpath) {
|
||||
$xmlStrings = $this->loadZip("$dir/$xpath[Target]", $mainNS);
|
||||
if (isset($xmlStrings->si)) {
|
||||
foreach ($xmlStrings->si as $val) {
|
||||
if (isset($val->t)) {
|
||||
$sharedStrings[] = StringHelper::controlCharacterOOXML2PHP((string) $val->t);
|
||||
} elseif (isset($val->r)) {
|
||||
$sharedStrings[] = $this->parseRichText($val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$worksheets = [];
|
||||
$macros = $customUI = null;
|
||||
foreach ($relsWorkbook->Relationship as $elex) {
|
||||
@@ -682,6 +662,27 @@ class Xlsx extends BaseReader
|
||||
$dxfs = $this->styleReader->dxfs($this->readDataOnly);
|
||||
$styles = $this->styleReader->styles();
|
||||
|
||||
// Read content after setting the styles
|
||||
$sharedStrings = [];
|
||||
$relType = "rel:Relationship[@Type='"
|
||||
//. Namespaces::SHARED_STRINGS
|
||||
. "$xmlNamespaceBase/sharedStrings"
|
||||
. "']";
|
||||
$xpath = self::getArrayItem($relsWorkbook->xpath($relType));
|
||||
|
||||
if ($xpath) {
|
||||
$xmlStrings = $this->loadZip("$dir/$xpath[Target]", $mainNS);
|
||||
if (isset($xmlStrings->si)) {
|
||||
foreach ($xmlStrings->si as $val) {
|
||||
if (isset($val->t)) {
|
||||
$sharedStrings[] = StringHelper::controlCharacterOOXML2PHP((string) $val->t);
|
||||
} elseif (isset($val->r)) {
|
||||
$sharedStrings[] = $this->parseRichText($val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$xmlWorkbook = $this->loadZipNoNamespace($relTarget, $mainNS);
|
||||
$xmlWorkbookNS = $this->loadZip($relTarget, $mainNS);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Reader\Html;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Exception as ReaderException;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Html;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
||||
@@ -380,4 +381,42 @@ class HtmlTest extends TestCase
|
||||
}
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
}
|
||||
|
||||
public function testDataType(): void
|
||||
{
|
||||
$html = '<table>
|
||||
<tr>
|
||||
<td data-type="b">1</td>
|
||||
<td data-type="s">12345678987654</td>
|
||||
<!-- in some cases, you may want to treat the string with beginning equal sign as a string rather than a formula -->
|
||||
<td data-type="s">=B1</td>
|
||||
<td data-type="d">2022-02-21 10:20:30</td>
|
||||
<td data-type="null">null</td>
|
||||
<td data-type="invalid-datatype">text with invalid datatype</td>
|
||||
</tr>
|
||||
</table>';
|
||||
|
||||
$reader = new Html();
|
||||
$spreadsheet = $reader->loadFromString($html);
|
||||
$firstSheet = $spreadsheet->getSheet(0);
|
||||
|
||||
// check boolean data type
|
||||
self::assertEquals(DataType::TYPE_BOOL, $firstSheet->getCell('A1')->getDataType());
|
||||
self::assertIsBool($firstSheet->getCell('A1')->getValue());
|
||||
|
||||
// check string data type
|
||||
self::assertEquals(DataType::TYPE_STRING, $firstSheet->getCell('B1')->getDataType());
|
||||
self::assertIsString($firstSheet->getCell('B1')->getValue());
|
||||
|
||||
// check string with beginning equal sign (=B1) and string datatype,is not formula
|
||||
self::assertEquals(DataType::TYPE_STRING, $firstSheet->getCell('C1')->getDataType());
|
||||
self::assertEquals('=B1', $firstSheet->getCell('C1')->getValue());
|
||||
self::assertTrue($firstSheet->getCell('C1')->getStyle()->getQuotePrefix());
|
||||
|
||||
//check iso date
|
||||
self::assertEqualsWithDelta($firstSheet->getCell('D1')->getValue(), 44613.43090277778, 1.0e-12);
|
||||
|
||||
//null
|
||||
self::assertEquals($firstSheet->getCell('E1')->getValue(), null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Reader\Xlsx;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
||||
|
||||
class Issue3464Test extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private static $testbook = 'tests/data/Reader/XLSX/issue.3464.xlsx';
|
||||
|
||||
public function testReadFontColor(): void
|
||||
{
|
||||
$inputFileType = IOFactory::identify(self::$testbook);
|
||||
$objReader = IOFactory::createReader($inputFileType);
|
||||
$objReader->setReadEmptyCells(false);
|
||||
|
||||
$sheet = $objReader->load(self::$testbook)->getActiveSheet();
|
||||
$rickText = $sheet->getCell([1, 1])->getValue();
|
||||
self::assertInstanceOf(RichText::class, $rickText);
|
||||
|
||||
$elements = $rickText->getRichTextElements();
|
||||
self::assertCount(2, $elements);
|
||||
|
||||
self::assertEquals("产品介绍\n", $elements[0]->getText());
|
||||
$font = $elements[0]->getFont();
|
||||
self::assertNotNull($font);
|
||||
self::assertEquals('7f7f7f', $font->getColor()->getRGB());
|
||||
|
||||
self::assertEquals('(这是一行示例数据,在导入时需要删除该行)', $elements[1]->getText());
|
||||
$font = $elements[1]->getFont();
|
||||
self::assertNotNull($font);
|
||||
self::assertEquals('ff2600', $font->getColor()->getRGB());
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user