summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2024-03-01 14:14:33 +0100
committerMiklos Vajna <vmiklos@collabora.com>2024-03-04 08:19:22 +0100
commit17581e684ca701bfd96ed2bf16aa14c3903b74d4 (patch)
tree7823a19859dee1e66684b3f1ef04ce2a3f936c3a
parentea4dfeb83889d5dc955646999e4b2b06693e631b (diff)
tdf#159483 sc HTML copy: handle data-sheets-value attribute for the num caseHEADmaster
Type 1000 and 2000 into cells in Calc, format them as e.g. a HUF currency, the resulting formatted strings can be copied to google sheets, but the SUM() on them will be 0 (and not 3000). Our own import knows how to read metadata to get the original float value, but our exporter didn't emit these. Fix the problem by adding support for non-boolean float values + number formats in the HTML export. This is more or less export equivalent of commit 789964785a61daab5f8065f006dd7aaf843c7236 (tdf#159483 sc HTML import: handle data-sheets-value attribute for the num case, 2024-02-09). Change-Id: I5acb3724367ce38bd96056dbe4f846cd7bbc5fe2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164213 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
-rw-r--r--sc/qa/filter/html/html.cxx37
-rw-r--r--sc/source/filter/html/htmlexp.cxx22
2 files changed, 59 insertions, 0 deletions
diff --git a/sc/qa/filter/html/html.cxx b/sc/qa/filter/html/html.cxx
index fb9a436c72a0..916dd23981ec 100644
--- a/sc/qa/filter/html/html.cxx
+++ b/sc/qa/filter/html/html.cxx
@@ -239,6 +239,43 @@ CPPUNIT_TEST_FIXTURE(Test, testCopyBoolean)
assertXPath(pHtmlDoc, "(//td)[1]"_ostr, "data-sheets-value"_ostr, "{ \"1\": 4, \"4\": 1}");
assertXPath(pHtmlDoc, "(//td)[2]"_ostr, "data-sheets-value"_ostr, "{ \"1\": 4, \"4\": 0}");
}
+
+CPPUNIT_TEST_FIXTURE(Test, testCopyFormattedNumber)
+{
+ // Given a document with formatted numbers in A1-A2:
+ createScDoc();
+ ScDocument* pDoc = getScDoc();
+ sal_Int32 nCheckPos;
+ SvNumFormatType nType;
+ sal_uInt32 nFormat;
+ OUString aNumberFormat("#,##0.00");
+ SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
+ pFormatter->PutEntry(aNumberFormat, nCheckPos, nType, nFormat);
+ ScAddress aCellPos1(/*nColP=*/0, /*nRowP=*/0, /*nTabP=*/0);
+ pDoc->SetNumberFormat(aCellPos1, nFormat);
+ pDoc->SetString(aCellPos1, "1000");
+ ScAddress aCellPos2(/*nColP=*/0, /*nRowP=*/1, /*nTabP=*/0);
+ pDoc->SetNumberFormat(aCellPos2, nFormat);
+ pDoc->SetString(aCellPos2, "2000");
+
+ // When copying those values:
+ ScImportExport aExporter(*pDoc, ScRange(aCellPos1, aCellPos2));
+ SvMemoryStream aStream;
+ CPPUNIT_ASSERT(aExporter.ExportStream(aStream, OUString(), SotClipboardFormatId::HTML));
+
+ // Then make sure the values are numbers:
+ aStream.Seek(0);
+ htmlDocUniquePtr pHtmlDoc = parseHtmlStream(&aStream);
+ // Without the accompanying fix in place, this test would have failed with:
+ // - XPath '(//td)[1]' no attribute 'data-sheets-value' exist
+ // i.e. only a formatted number string was written, without a float value.
+ assertXPath(pHtmlDoc, "(//td)[1]"_ostr, "data-sheets-value"_ostr, "{ \"1\": 3, \"3\": 1000}");
+ assertXPath(pHtmlDoc, "(//td)[1]"_ostr, "data-sheets-numberformat"_ostr,
+ "{ \"1\": 2, \"2\": \"#,##0.00\", \"3\": 1}");
+ assertXPath(pHtmlDoc, "(//td)[2]"_ostr, "data-sheets-value"_ostr, "{ \"1\": 3, \"3\": 2000}");
+ assertXPath(pHtmlDoc, "(//td)[2]"_ostr, "data-sheets-numberformat"_ostr,
+ "{ \"1\": 2, \"2\": \"#,##0.00\", \"3\": 1}");
+}
}
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sc/source/filter/html/htmlexp.cxx b/sc/source/filter/html/htmlexp.cxx
index 1e5dcf24b6c5..c2554b7612f1 100644
--- a/sc/source/filter/html/htmlexp.cxx
+++ b/sc/source/filter/html/htmlexp.cxx
@@ -1146,6 +1146,7 @@ void ScHTMLExport::WriteCell( sc::ColumnBlockPosition& rBlockPos, SCCOL nCol, SC
nFormat, *pFormatter, &aNonConvertibleChars));
std::optional<tools::JsonWriter> oJson;
+ const SvNumberformat* pNumberFormat = nullptr;
if (bValueData)
{
if (nFormat)
@@ -1161,6 +1162,14 @@ void ScHTMLExport::WriteCell( sc::ColumnBlockPosition& rBlockPos, SCCOL nCol, SC
oJson->put("1", static_cast<sal_Int32>(4));
oJson->put("4", static_cast<sal_Int32>(fVal));
}
+ else
+ {
+ // 3 is number.
+ oJson.emplace();
+ oJson->put("1", static_cast<sal_Int32>(3));
+ oJson->put("3", static_cast<sal_Int32>(fVal));
+ pNumberFormat = pFormatEntry;
+ }
}
}
}
@@ -1179,6 +1188,19 @@ void ScHTMLExport::WriteCell( sc::ColumnBlockPosition& rBlockPos, SCCOL nCol, SC
+ HTMLOutFuncs::ConvertStringToHTML(aJsonString) + "\"");
}
+ if (pNumberFormat)
+ {
+ // 2 is a number format.
+ oJson.emplace();
+ oJson->put("1", static_cast<sal_Int32>(2));
+ oJson->put("2", pNumberFormat->GetFormatstring());
+ // The number format is for a number.
+ oJson->put("3", static_cast<sal_Int32>(1));
+ OUString aJsonString = OUString::fromUtf8(oJson->finishAndGetAsOString());
+ aStrTD.append(" " OOO_STRING_SVTOOLS_HTML_O_DSnum "=\""
+ + HTMLOutFuncs::ConvertStringToHTML(aJsonString) + "\"");
+ }
+
TAG_ON(aStrTD.makeStringAndClear());
//write the note for this as the first thing in the tag