sc/qa/filter/html/data/single-cell.html | 1 sc/qa/filter/html/html.cxx | 24 +++++++++++++ sc/source/filter/html/htmlpars.cxx | 57 +++++++++++++++++++++++--------- sc/source/filter/inc/htmlpars.hxx | 4 ++ 4 files changed, 70 insertions(+), 16 deletions(-)
New commits: commit e54ebdb47bedb3dda4f7c68ba5a96086061184f6 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Tue Feb 13 08:11:54 2024 +0100 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Tue Feb 13 15:23:43 2024 +0100 tdf#159483 sc HTML paste: handle data-sheets- attributes on a span Copy multiple cells, including a formula from google sheets to Calc, the formula is handled as a formula by the HTML paste. Do the same for a single cell, then only the result is pasted. The trouble is that the data-sheets-* attributes appear on <td> elements for multiple cells, but they appear on a <span> for a single cell. Fix the problem by extending ScHTMLLayoutParser::ProcToken() to handle the HtmlTokenId::SPAN_ON token and share the code between the <td> and <span> handler, so this markup works in both cases. Note that this is the paste handler, the no changes to the normal HTML import are made for now. (cherry picked from commit c0da56cb3e9f9678cae7142dee03fb706a2aebd9) Change-Id: Id749df9062d8fcb9a2f0acd928585a304efaae28 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163306 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> diff --git a/sc/qa/filter/html/data/single-cell.html b/sc/qa/filter/html/data/single-cell.html new file mode 100644 index 000000000000..0b5613f7e2be --- /dev/null +++ b/sc/qa/filter/html/data/single-cell.html @@ -0,0 +1 @@ +<span style="font-size:10pt;font-family:Arial;font-style:normal;text-align:right;" data-sheets-root="1" data-sheets-value="{"1":3,"3":3}" data-sheets-formula="=SUM(R[0]C[-2]:R[0]C[-1])">3</span> diff --git a/sc/qa/filter/html/html.cxx b/sc/qa/filter/html/html.cxx index 83e35d9f8281..c6112e357d80 100644 --- a/sc/qa/filter/html/html.cxx +++ b/sc/qa/filter/html/html.cxx @@ -168,6 +168,30 @@ CPPUNIT_TEST_FIXTURE(Test, testPasteTdAsFormula) pDoc->GetFormula(/*col=*/2, /*row=*/0, /*tab=*/0)); CPPUNIT_ASSERT_EQUAL(static_cast<double>(3), pDoc->GetValue(/*col=*/2, /*row=*/0, /*tab=*/0)); } + +CPPUNIT_TEST_FIXTURE(Test, testPasteSingleCell) +{ + // Given a document with '1' in A1 and '2' in B1: + createScDoc(); + ScDocument* pDoc = getScDoc(); + pDoc->SetValue(ScAddress(0, 0, 0), 1.0); + pDoc->SetValue(ScAddress(1, 0, 0), 2.0); + + // When pasting SUM(A1:B1) into C1: + ScAddress aCellPos(/*nColP=*/2, /*nRowP=*/0, /*nTabP=*/0); + ScImportExport aImporter(*pDoc, aCellPos); + SvFileStream aFile(createFileURL(u"single-cell.html"), StreamMode::READ); + CPPUNIT_ASSERT(aImporter.ImportStream(aFile, OUString(), SotClipboardFormatId::HTML)); + + // Then make sure C1 is a sum and it evaluates to 3: + // Without the accompanying fix in place, this test would have failed with: + // - Expected: =SUM(A1:B1) + // - Actual : + // i.e. data-sheets-* on <td> worked, but not on <span>. + CPPUNIT_ASSERT_EQUAL(OUString("=SUM(A1:B1)"), + pDoc->GetFormula(/*col=*/2, /*row=*/0, /*tab=*/0)); + CPPUNIT_ASSERT_EQUAL(static_cast<double>(3), pDoc->GetValue(/*col=*/2, /*row=*/0, /*tab=*/0)); +} } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sc/source/filter/html/htmlpars.cxx b/sc/source/filter/html/htmlpars.cxx index c9f0474e3cf8..bb6f65c88a08 100644 --- a/sc/source/filter/html/htmlpars.cxx +++ b/sc/source/filter/html/htmlpars.cxx @@ -992,6 +992,34 @@ IMPL_LINK( ScHTMLLayoutParser, HTMLImportHdl, HtmlImportInfo&, rInfo, void ) } } +void ScHTMLLayoutParser::HandleDataSheetsAttributes(const HTMLOptions& rOptions) +{ + for (const auto& rOption : rOptions) + { + switch (rOption.GetToken()) + { + case HtmlOptionId::DSVAL: + { + ParseDataSheetsValue(rOption.GetString(), mxActEntry->pValStr, mxActEntry->pNumStr); + break; + } + case HtmlOptionId::DSNUM: + { + ParseDataSheetsNumberformat(rOption.GetString(), mxActEntry->pNumStr); + break; + } + case HtmlOptionId::DSFORMULA: + { + ParseDataSheetsFormula(rOption.GetString(), mxActEntry->moFormulaStr, + mxActEntry->moFormulaGrammar); + break; + } + default: + break; + } + } +} + void ScHTMLLayoutParser::TableDataOn( HtmlImportInfo* pInfo ) { if ( bInCell ) @@ -1072,26 +1100,12 @@ void ScHTMLLayoutParser::TableDataOn( HtmlImportInfo* pInfo ) mxActEntry->pNumStr = rOption.GetString(); } break; - case HtmlOptionId::DSVAL: - { - ParseDataSheetsValue(rOption.GetString(), mxActEntry->pValStr, mxActEntry->pNumStr); - } - break; - case HtmlOptionId::DSNUM: - { - ParseDataSheetsNumberformat(rOption.GetString(), mxActEntry->pNumStr); - } - break; - case HtmlOptionId::DSFORMULA: - { - ParseDataSheetsFormula(rOption.GetString(), mxActEntry->moFormulaStr, - mxActEntry->moFormulaGrammar); - } - break; default: break; } } + HandleDataSheetsAttributes(rOptions); + mxActEntry->nCol = nColCnt; mxActEntry->nRow = nRowCnt; mxActEntry->nTab = nTable; @@ -1101,6 +1115,12 @@ void ScHTMLLayoutParser::TableDataOn( HtmlImportInfo* pInfo ) SvxHorJustifyItem( SvxCellHorJustify::Center, ATTR_HOR_JUSTIFY) ); } +void ScHTMLLayoutParser::SpanOn(HtmlImportInfo* pInfo) +{ + const HTMLOptions& rOptions = static_cast<HTMLParser*>(pInfo->pParser)->GetOptions(); + HandleDataSheetsAttributes(rOptions); +} + void ScHTMLLayoutParser::TableRowOn( const HtmlImportInfo* pInfo ) { if ( nColCnt > nColCntStart ) @@ -1638,6 +1658,11 @@ void ScHTMLLayoutParser::ProcToken( HtmlImportInfo* pInfo ) TableDataOn( pInfo ); } break; + case HtmlTokenId::SPAN_ON: + { + SpanOn(pInfo); + } + break; case HtmlTokenId::TABLEHEADER_OFF: case HtmlTokenId::TABLEDATA_OFF: // Closes cell { diff --git a/sc/source/filter/inc/htmlpars.hxx b/sc/source/filter/inc/htmlpars.hxx index 5b2d441098f3..1ac9aa000225 100644 --- a/sc/source/filter/inc/htmlpars.hxx +++ b/sc/source/filter/inc/htmlpars.hxx @@ -28,6 +28,7 @@ #include <utility> #include <vector> #include <o3tl/sorted_vector.hxx> +#include <svtools/parhtml.hxx> #include <rangelst.hxx> #include "eeparser.hxx" @@ -212,6 +213,9 @@ private: void Image( HtmlImportInfo* ); void AnchorOn( HtmlImportInfo* ); void FontOn( HtmlImportInfo* ); + void SpanOn(HtmlImportInfo* pInfo); + /// Handles the various data-sheets-* attributes on <td> and <span>. + void HandleDataSheetsAttributes(const HTMLOptions& rOptions); public: ScHTMLLayoutParser( EditEngine*, OUString aBaseURL, const Size& aPageSize, ScDocument* );