tdf#159483 sc HTML copy: handle data-sheets-value attribute for the bool case

Similar to commit f8c95cf93ce9ab8b9b78f3af03411d0cc2e195ba (tdf#159483
sc HTML import: handle data-sheets-value attribute for the bool case,
2024-02-08).

Change-Id: I25ce8c81bd906ac0fb912e125e061516a604e786
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163419
Reviewed-by: Miklos Vajna <[email protected]>
Tested-by: Jenkins
diff --git a/sc/qa/filter/html/html.cxx b/sc/qa/filter/html/html.cxx
index e0d7977..fb9a436 100644
--- a/sc/qa/filter/html/html.cxx
+++ b/sc/qa/filter/html/html.cxx
@@ -214,6 +214,31 @@ CPPUNIT_TEST_FIXTURE(Test, testCopyText)
    htmlDocUniquePtr pHtmlDoc = parseHtmlStream(&aStream);
    assertXPath(pHtmlDoc, "//td"_ostr, "data-sheets-value"_ostr, "{ \"1\": 2, \"2\": \"01\"}");
}

CPPUNIT_TEST_FIXTURE(Test, testCopyBoolean)
{
    // Given a document with boolean values in A1-A2:
    createScDoc();
    ScDocument* pDoc = getScDoc();
    ScAddress aCellPos1(/*nColP=*/0, /*nRowP=*/0, /*nTabP=*/0);
    pDoc->SetString(aCellPos1, "TRUE");
    ScAddress aCellPos2(/*nColP=*/0, /*nRowP=*/1, /*nTabP=*/0);
    pDoc->SetString(aCellPos2, "FALSE");

    // 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 booleans:
    aStream.Seek(0);
    htmlDocUniquePtr pHtmlDoc = parseHtmlStream(&aStream);
    // Without the accompanying fix in place, this test would have failed with:
    // - XPath '//td' no attribute 'data-sheets-value' exist
    // i.e. metadata was missing to avoid converting TRUE to text.
    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_PLUGIN_IMPLEMENT();
diff --git a/sc/source/filter/html/htmlexp.cxx b/sc/source/filter/html/htmlexp.cxx
index a2f14f6..1e5dcf2 100644
--- a/sc/source/filter/html/htmlexp.cxx
+++ b/sc/source/filter/html/htmlexp.cxx
@@ -88,6 +88,8 @@
#include <rtl/strbuf.hxx>
#include <officecfg/Office/Common.hxx>
#include <tools/json_writer.hxx>
#include <svl/numformat.hxx>
#include <svl/zformat.hxx>

using ::editeng::SvxBorderLine;
using namespace ::com::sun::star;
@@ -1143,13 +1145,36 @@ void ScHTMLExport::WriteCell( sc::ColumnBlockPosition& rBlockPos, SCCOL nCol, SC
    aStrTD.append(HTMLOutFuncs::CreateTableDataOptionsValNum(bValueData, fVal,
        nFormat, *pFormatter, &aNonConvertibleChars));

    if (!bValueData)
    std::optional<tools::JsonWriter> oJson;
    if (bValueData)
    {
        if (nFormat)
        {
            const SvNumberformat* pFormatEntry = pFormatter->GetEntry(nFormat);
            if (pFormatEntry)
            {
                OUString aNumStr = pFormatEntry->GetFormatstring();
                if (aNumStr == "BOOLEAN")
                {
                    // 4 is boolean.
                    oJson.emplace();
                    oJson->put("1", static_cast<sal_Int32>(4));
                    oJson->put("4", static_cast<sal_Int32>(fVal));
                }
            }
        }
    }
    else
    {
        // 2 is text.
        tools::JsonWriter aJson;
        aJson.put("1", static_cast<sal_Int32>(2));
        aJson.put("2", pDoc->GetString(aPos));
        OUString aJsonString = OUString::fromUtf8(aJson.finishAndGetAsOString());
        oJson.emplace();
        oJson->put("1", static_cast<sal_Int32>(2));
        oJson->put("2", pDoc->GetString(aPos));
    }

    if (oJson)
    {
        OUString aJsonString = OUString::fromUtf8(oJson->finishAndGetAsOString());
        aStrTD.append(" " OOO_STRING_SVTOOLS_HTML_O_DSval "=\""
                      + HTMLOutFuncs::ConvertStringToHTML(aJsonString) + "\"");
    }