From e348d752613dc30e33a48e26865ac195a4b4991b Mon Sep 17 00:00:00 2001 From: Vissarion Fisikopoulos Date: Wed, 12 Nov 2025 15:42:27 +0200 Subject: [PATCH] tdf#62248 fix multiple groupings on same field issue in reportbuilder In a reportbuilder report, when grouping on the same field multiple times (with different interval/prefix characters setting), the two groupings interact and in the end it does not work right; both grouping levels behave like one of them. That's because the report function created by Report Builder for each of the groupings share the same name. Choose unique function name in ORptExport::exportGroupsExpressionAsFunction and sync OXMLGroup::OXMLGroup to parse that name. Keep supporting legacy names for backwards compatibility. Change-Id: Ic91e51743a407225d50b14f85d02c58ca0a243c0 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193993 Tested-by: Jenkins Reviewed-by: Hossein --- .../qa/unit/ReportDesignBasicTests.cxx | 57 ++++++++++++++++++ .../ReportBuilder_grouping_same_field.odb | Bin 0 -> 16689 bytes reportdesign/source/filter/xml/xmlExport.cxx | 4 +- reportdesign/source/filter/xml/xmlGroup.cxx | 31 +++++++++- 4 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 reportdesign/qa/unit/data/ReportBuilder_grouping_same_field.odb diff --git a/reportdesign/qa/unit/ReportDesignBasicTests.cxx b/reportdesign/qa/unit/ReportDesignBasicTests.cxx index 03489b24501b..875aca028be9 100644 --- a/reportdesign/qa/unit/ReportDesignBasicTests.cxx +++ b/reportdesign/qa/unit/ReportDesignBasicTests.cxx @@ -21,6 +21,7 @@ #include #include +#include using namespace ::com::sun::star; using namespace ::com::sun::star::uno; @@ -58,6 +59,62 @@ CPPUNIT_TEST_FIXTURE(RptBasicTest, roundTripTest) testLoadingAndSaving(u"calc8"_ustr, aReportNames[1], xComponentLoader, xActiveConnection); } +CPPUNIT_TEST_FIXTURE(RptBasicTest, multiGroupingSameFieldIntervals) +{ + // ODB fixture must contain a table and a report that groups on the same field twice + // with different settings (e.g., INTERVAL 5 and INTERVAL 10). The report should be + // prepared to reproduce the original failure (Column not found: INT_count_...). + loadURLCopy(u"ReportBuilder_grouping_same_field.odb"); + + Reference xModel(mxComponent, UNO_QUERY_THROW); + Reference xController(xModel->getCurrentController()); + Reference xUI(xController, UNO_QUERY_THROW); + + xUI->connect(); + Reference xActiveConnection = xUI->getActiveConnection(); + + Reference xSupp(xModel, UNO_QUERY_THROW); + Reference xNameAccess = xSupp->getReportDocuments(); + const Sequence aReportNames(xNameAccess->getElementNames()); + CPPUNIT_ASSERT(aReportNames.getLength() > 0); + + Reference xComponentLoader(xNameAccess, UNO_QUERY_THROW); + + // Execute all reports via writer export. This will fail the test if any report + // throws ReportExecutionException like "Column not found: INT_count_Number_*". + for (const OUString& rName : aReportNames) + testLoadingAndSaving(u"writer8"_ustr, rName, xComponentLoader, xActiveConnection); + + // Additionally, load the textual outputs of all reports and compare their lengths. + // They should be identical. + if (aReportNames.getLength() >= 2) + { + ::comphelper::NamedValueCollection aLoadArgs; + aLoadArgs.put(u"ActiveConnection"_ustr, xActiveConnection); + + Reference xComp1 = xComponentLoader->loadComponentFromURL( + aReportNames[0], u"_blank"_ustr, 0, aLoadArgs.getPropertyValues()); + Reference xComp2 = xComponentLoader->loadComponentFromURL( + aReportNames[1], u"_blank"_ustr, 0, aLoadArgs.getPropertyValues()); + Reference xTextDoc1(xComp1, UNO_QUERY); + Reference xTextDoc2(xComp2, UNO_QUERY); + + if (xTextDoc1.is() && xTextDoc2.is()) + { + sal_Int32 nLen1 = xTextDoc1->getText()->getString().getLength(); + sal_Int32 nLen2 = xTextDoc2->getText()->getString().getLength(); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Report textual output length differs", nLen1, nLen2); + } + + Reference xClose1(xComp1, UNO_QUERY); + if (xClose1.is()) + xClose1->close(true); + Reference xClose2(xComp2, UNO_QUERY); + if (xClose2.is()) + xClose2->close(true); + } +} + void RptBasicTest::testLoadingAndSaving(const OUString& rFilterName, const OUString& rReportName, Reference& xComponentLoader, Reference& xActiveConnection) diff --git a/reportdesign/qa/unit/data/ReportBuilder_grouping_same_field.odb b/reportdesign/qa/unit/data/ReportBuilder_grouping_same_field.odb new file mode 100644 index 0000000000000000000000000000000000000000..bba06e5aa285d18da4b13b3747c2c75008ae89dd GIT binary patch literal 16689 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 literal 0 HcmV?d00001 diff --git a/reportdesign/source/filter/xml/xmlExport.cxx b/reportdesign/source/filter/xml/xmlExport.cxx index 455b46648769..7d09758dbcbf 100644 --- a/reportdesign/source/filter/xml/xmlExport.cxx +++ b/reportdesign/source/filter/xml/xmlExport.cxx @@ -1415,7 +1415,9 @@ void ORptExport::exportGroupsExpressionAsFunction(const Reference< XGroups>& _xG sFunction = "INT"; uno::Reference< XFunction> xCountFunction = xFunctions->createFunction(); xCountFunction->setInitialFormula(beans::Optional< OUString>(true,u"rpt:0"_ustr)); - OUString sCountName = sFunction + "_count_" + sExpression; + OUString sCountName = sFunction + "_count_" + + OUString::number(xGroup->getGroupInterval()) + + "_" + sExpression; xCountFunction->setName(sCountName); xCountFunction->setFormula( "rpt:[" + sCountName + "] + 1" ); exportFunction(xCountFunction); diff --git a/reportdesign/source/filter/xml/xmlGroup.cxx b/reportdesign/source/filter/xml/xmlGroup.cxx index b25a31fa8089..a3799c19905e 100644 --- a/reportdesign/source/filter/xml/xmlGroup.cxx +++ b/reportdesign/source/filter/xml/xmlGroup.cxx @@ -73,6 +73,14 @@ OXMLGroup::OXMLGroup( ORptFilter& _rImport case XML_ELEMENT(REPORT, XML_SORT_ASCENDING): m_xGroup->setSortAscending(IsXMLToken(aIter, XML_TRUE)); break; + case XML_ELEMENT(REPORT, XML_SORT_EXPRESSION): + { + // Use the explicit sort field as the group's expression + OUString sExpr = aIter.toString(); + if (sExpr.indexOf("INT_count") == -1)// for backward compatibility + m_xGroup->setExpression(sExpr); + } + break; case XML_ELEMENT(REPORT, XML_GROUP_EXPRESSION): { OUString sValue = aIter.toString(); @@ -138,7 +146,21 @@ OXMLGroup::OXMLGroup( ORptFilter& _rImport { nGroupOn = report::GroupOn::INTERVAL; _rImport.removeFunction(sExpression); - sExpression = sExpression.copy(std::string_view("INT_count_").size()); + // sExpression can be either: + // - "INT_count__" (new) + // - "INT_count_" (legacy) + const OUString aPrefix = u"INT_count_"_ustr; + const sal_Int32 nStart = aPrefix.getLength(); + const sal_Int32 nEnd = sExpression.indexOf(u'_', nStart); + const sal_Int32 nDigitsOfInterval = (nEnd >= 0 && nEnd > nStart) + ? (nEnd - nStart) : 0; + + // Cut after prefix; if digits found, also skip the following '_' + sal_Int32 nCut = nStart; + if (nDigitsOfInterval > 0 && nEnd >= 0) + nCut = nEnd + 1; + if (nCut <= sExpression.getLength()) + sExpression = sExpression.copy(nCut); OUString sInterval = sCompleteFormula.getToken(1,'/'); sInterval = sInterval.getToken(0,')'); m_xGroup->setGroupInterval(sInterval.toInt32()); @@ -146,10 +168,13 @@ OXMLGroup::OXMLGroup( ORptFilter& _rImport m_xGroup->setGroupOn(nGroupOn); + // Drop only the reference name; keep functions for export _rImport.removeFunction(sValue); - sValue = sExpression; + + // Only set expression from fallback if not already provided via sort-expression + if (m_xGroup->getExpression().isEmpty()) + m_xGroup->setExpression(sExpression); } - m_xGroup->setExpression(sValue); } } break;