diff --git a/CHANGELOG.md b/CHANGELOG.md index b0aa81f4be..9883c3dd75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ and this project adheres to [Semantic Versioning](https://semver.org). - Mpdf and Tcpdf Borders on Merged Cells. [Issue #3557](https://github.com/PHPOffice/PhpSpreadsheet/issues/3557) [PR #4047](https://github.com/PHPOffice/PhpSpreadsheet/pull/4047) - Xls Conditional Format Improvements. [PR #4030](https://github.com/PHPOffice/PhpSpreadsheet/pull/4030) [PR #4033](https://github.com/PHPOffice/PhpSpreadsheet/pull/4033) - Conditional Range Unions and Intersections [Issue #4039](https://github.com/PHPOffice/PhpSpreadsheet/issues/4039) [PR #4042](https://github.com/PHPOffice/PhpSpreadsheet/pull/4042) +- Ods comments with newlines. [Issue #4081](https://github.com/PHPOffice/PhpSpreadsheet/issues/4081) [PR #4086](https://github.com/PHPOffice/PhpSpreadsheet/pull/4086) - Propagate errors in Text functions. [Issue #2581](https://github.com/PHPOffice/PhpSpreadsheet/issues/2581) [PR #4080](https://github.com/PHPOffice/PhpSpreadsheet/pull/4080) - Csv Reader allow use of html mimetype. [Issue #4036](https://github.com/PHPOffice/PhpSpreadsheet/issues/4036) [PR #4040](https://github.com/PHPOffice/PhpSpreadsheet/pull/4040) - Problem rendering line chart with missing plot label. [PR #4074](https://github.com/PHPOffice/PhpSpreadsheet/pull/4074) diff --git a/src/PhpSpreadsheet/Reader/Ods.php b/src/PhpSpreadsheet/Reader/Ods.php index ceb345dc3f..346d97c543 100644 --- a/src/PhpSpreadsheet/Reader/Ods.php +++ b/src/PhpSpreadsheet/Reader/Ods.php @@ -436,14 +436,25 @@ public function loadIntoExisting(string $filename, Spreadsheet $spreadsheet): Sp if ($annotation->length > 0 && $annotation->item(0) !== null) { $textNode = $annotation->item(0)->getElementsByTagNameNS($textNs, 'p'); + $textNodeLength = $textNode->length; + $newLineOwed = false; + for ($textNodeIndex = 0; $textNodeIndex < $textNodeLength; ++$textNodeIndex) { + $textNodeItem = $textNode->item($textNodeIndex); + if ($textNodeItem !== null) { + $text = $this->scanElementForText($textNodeItem); + if ($newLineOwed) { + $spreadsheet->getActiveSheet() + ->getComment($columnID . $rowID) + ->getText() + ->createText("\n"); + } + $newLineOwed = true; - if ($textNode->length > 0 && $textNode->item(0) !== null) { - $text = $this->scanElementForText($textNode->item(0)); - - $spreadsheet->getActiveSheet() - ->getComment($columnID . $rowID) - ->setText($this->parseRichText($text)); -// ->setAuthor( $author ) + $spreadsheet->getActiveSheet() + ->getComment($columnID . $rowID) + ->getText() + ->createText($this->parseRichText($text)); + } } } @@ -731,6 +742,8 @@ protected function scanElementForText(DOMNode $element): string /** @var DOMNode $child */ if ($child->nodeType == XML_TEXT_NODE) { $str .= $child->nodeValue; + } elseif ($child->nodeType == XML_ELEMENT_NODE && $child->nodeName == 'text:line-break') { + $str .= "\n"; } elseif ($child->nodeType == XML_ELEMENT_NODE && $child->nodeName == 'text:s') { // It's a space diff --git a/src/PhpSpreadsheet/Writer/Ods/Cell/Comment.php b/src/PhpSpreadsheet/Writer/Ods/Cell/Comment.php index b0829bf1de..f0b7d57041 100644 --- a/src/PhpSpreadsheet/Writer/Ods/Cell/Comment.php +++ b/src/PhpSpreadsheet/Writer/Ods/Cell/Comment.php @@ -24,7 +24,22 @@ public static function write(XMLWriter $objWriter, Cell $cell): void $objWriter->writeAttribute('svg:x', $comment->getMarginLeft()); $objWriter->writeAttribute('svg:y', $comment->getMarginTop()); $objWriter->writeElement('dc:creator', $comment->getAuthor()); - $objWriter->writeElement('text:p', $comment->getText()->getPlainText()); + + $objWriter->startElement('text:p'); + $text = $comment->getText()->getPlainText(); + $textElements = explode("\n", $text); + $newLineOwed = false; + foreach ($textElements as $textSegment) { + if ($newLineOwed) { + $objWriter->writeElement('text:line-break'); + } + $newLineOwed = true; + if ($textSegment !== '') { + $objWriter->writeElement('text:span', $textSegment); + } + } + $objWriter->endElement(); // text:p + $objWriter->endElement(); } } diff --git a/tests/PhpSpreadsheetTests/Reader/Ods/MultiLineCommentTest.php b/tests/PhpSpreadsheetTests/Reader/Ods/MultiLineCommentTest.php new file mode 100644 index 0000000000..f6fd5657a1 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Reader/Ods/MultiLineCommentTest.php @@ -0,0 +1,41 @@ +load($filename); + $sheet = $spreadsheet->getActiveSheet(); + self::assertSame("First line.\n\nSecond line.", $sheet->getComment('A1')->getText()->getPlainText()); + $spreadsheet->disconnectWorksheets(); + } + + public function testOneParagraphMultipleSpans(): void + { + $spreadsheetOld = new Spreadsheet(); + $sheetOld = $spreadsheetOld->getActiveSheet(); + $sheetOld->getCell('A1')->setValue('Hello'); + $text = $sheetOld->getComment('A1')->getText(); + $text->createText('First'); + $text->createText(' line.'); + $text->createText("\n"); + $text->createText("\n"); + $text->createText("Second line.\nThird line."); + $spreadsheet = $this->writeAndReload($spreadsheetOld, 'Ods'); + $spreadsheetOld->disconnectWorksheets(); + + $sheet = $spreadsheet->getActiveSheet(); + self::assertSame("First line.\n\nSecond line.\nThird line.", $sheet->getComment('A1')->getText()->getPlainText()); + $spreadsheet->disconnectWorksheets(); + } +} diff --git a/tests/data/Reader/Ods/issue.4081.ods b/tests/data/Reader/Ods/issue.4081.ods new file mode 100644 index 0000000000..6d690bd4e1 Binary files /dev/null and b/tests/data/Reader/Ods/issue.4081.ods differ