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 2ec403de8f74699130cc80e1eda7862cb123cbfd
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Tue Feb 13 08:11:54 2024 +0100
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Tue Feb 13 16:53:24 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.
    
    Change-Id: Id749df9062d8fcb9a2f0acd928585a304efaae28
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163291
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins
    (cherry picked from commit c0da56cb3e9f9678cae7142dee03fb706a2aebd9)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163289
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

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="{&quot;1&quot;:3,&quot;3&quot;: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 917a690c7090..c9d53d93bed7 100644
--- a/sc/source/filter/html/htmlpars.cxx
+++ b/sc/source/filter/html/htmlpars.cxx
@@ -989,6 +989,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 )
@@ -1069,26 +1097,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;
@@ -1098,6 +1112,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 )
@@ -1628,6 +1648,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* );

Reply via email to