diff options
Diffstat (limited to 'sc')
-rw-r--r-- | sc/inc/document.hxx | 2 | ||||
-rw-r--r-- | sc/inc/subtotalparam.hxx | 1 | ||||
-rw-r--r-- | sc/inc/table.hxx | 4 | ||||
-rw-r--r-- | sc/inc/unonames.hxx | 1 | ||||
-rw-r--r-- | sc/inc/unowids.hxx | 3 | ||||
-rw-r--r-- | sc/qa/uitest/data/tdf162262.ods | bin | 0 -> 17343 bytes | |||
-rw-r--r-- | sc/qa/uitest/sort/subtotals.py | 109 | ||||
-rw-r--r-- | sc/qa/unit/data/xlsx/subtotal-above.xlsx | bin | 0 -> 10111 bytes | |||
-rw-r--r-- | sc/qa/unit/subsequent_export_test4.cxx | 12 | ||||
-rw-r--r-- | sc/source/core/data/document.cxx | 19 | ||||
-rw-r--r-- | sc/source/core/data/subtotalparam.cxx | 6 | ||||
-rw-r--r-- | sc/source/core/data/table3.cxx | 79 | ||||
-rw-r--r-- | sc/source/filter/excel/excdoc.cxx | 3 | ||||
-rw-r--r-- | sc/source/filter/excel/excrecds.cxx | 10 | ||||
-rw-r--r-- | sc/source/filter/inc/excrecds.hxx | 3 | ||||
-rw-r--r-- | sc/source/filter/oox/worksheetsettings.cxx | 6 | ||||
-rw-r--r-- | sc/source/ui/dbgui/tpsubt.cxx | 6 | ||||
-rw-r--r-- | sc/source/ui/inc/tpsubt.hxx | 1 | ||||
-rw-r--r-- | sc/source/ui/unoobj/cellsuno.cxx | 6 | ||||
-rw-r--r-- | sc/source/ui/view/cellsh1.cxx | 6 | ||||
-rw-r--r-- | sc/uiconfig/scalc/ui/subtotaloptionspage.ui | 152 |
21 files changed, 332 insertions, 97 deletions
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 43a08fcdc7b0..bf8eaa34f2f2 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -982,6 +982,8 @@ public: SC_DLLPUBLIC bool GetName( SCTAB nTab, OUString& rName ) const; SC_DLLPUBLIC bool GetCodeName( SCTAB nTab, OUString& rName ) const; SC_DLLPUBLIC bool SetCodeName( SCTAB nTab, const OUString& rName ); + SC_DLLPUBLIC bool GetTotalsRowBelow( SCTAB nTab ) const; + SC_DLLPUBLIC bool SetTotalsRowBelow( SCTAB nTab, bool bVal ); SC_DLLPUBLIC bool GetTable( const OUString& rName, SCTAB& rTab ) const; SC_DLLPUBLIC SCCOL MaxCol() const { return mxSheetLimits->mnMaxCol; } SC_DLLPUBLIC SCROW MaxRow() const { return mxSheetLimits->mnMaxRow; } diff --git a/sc/inc/subtotalparam.hxx b/sc/inc/subtotalparam.hxx index 8e36dad83987..3b379edb167d 100644 --- a/sc/inc/subtotalparam.hxx +++ b/sc/inc/subtotalparam.hxx @@ -24,6 +24,7 @@ struct SC_DLLPUBLIC ScSubTotalParam bool bPagebreak:1; ///< page break at change of group bool bCaseSens:1; bool bDoSort:1; ///< presort + bool bSummaryBelow:1; ///< Summary below or above (default: below) bool bAscending:1; ///< sort ascending bool bUserDef:1; ///< sort user defined bool bIncludePattern:1; ///< sort formats diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 7da55e4cb3ee..b70f77c95445 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -253,6 +253,7 @@ private: bool bActiveScenario:1; bool mbPageBreaksValid:1; bool mbForceBreaks:1; + bool mbTotalsRowBelow:1; /** this is touched from formula group threading context */ std::atomic<bool> bStreamValid; @@ -394,6 +395,9 @@ public: const OUString& GetCodeName() const { return aCodeName; } void SetCodeName( const OUString& rNewName ) { aCodeName = rNewName; } + bool GetTotalsRowBelow() const { return mbTotalsRowBelow; } + void SetTotalsRowBelow( bool bNewVal ) { mbTotalsRowBelow = bNewVal; } + const OUString& GetUpperName() const; const OUString& GetPageStyle() const { return aPageStyle; } diff --git a/sc/inc/unonames.hxx b/sc/inc/unonames.hxx index 916fd839d4b7..0d8fd9dbd696 100644 --- a/sc/inc/unonames.hxx +++ b/sc/inc/unonames.hxx @@ -192,6 +192,7 @@ inline constexpr OUString SC_UNONAME_TABLAYOUT = u"TableLayout"_ustr; inline constexpr OUString SC_UNONAME_AUTOPRINT = u"AutomaticPrintArea"_ustr; inline constexpr OUString SC_UNONAME_TABCOLOR = u"TabColor"_ustr; inline constexpr OUString SC_UNONAME_CONDFORMAT = u"ConditionalFormats"_ustr; +inline constexpr OUString SC_UNONAME_TOTALBELOW = u"TotalsRowBelow"_ustr; inline constexpr OUString SC_UNONAME_VISFLAG = u"VisibleFlag"_ustr; diff --git a/sc/inc/unowids.hxx b/sc/inc/unowids.hxx index b5de8f1f292c..389b2dda0da2 100644 --- a/sc/inc/unowids.hxx +++ b/sc/inc/unowids.hxx @@ -75,7 +75,8 @@ #define SC_WID_UNO_FORMRT2 ( SC_WID_UNO_START + 46 ) #define SC_WID_UNO_CELLCONTENTTYPE ( SC_WID_UNO_START + 47 ) #define SC_WID_UNO_SOLVERSETTINGS ( SC_WID_UNO_START + 48 ) -#define SC_WID_UNO_END ( SC_WID_UNO_START + 48 ) +#define SC_WID_UNO_TOTALBELOW ( SC_WID_UNO_START + 49 ) +#define SC_WID_UNO_END ( SC_WID_UNO_START + 49 ) inline bool IsScUnoWid( sal_uInt16 nWid ) { diff --git a/sc/qa/uitest/data/tdf162262.ods b/sc/qa/uitest/data/tdf162262.ods Binary files differnew file mode 100644 index 000000000000..138348366298 --- /dev/null +++ b/sc/qa/uitest/data/tdf162262.ods diff --git a/sc/qa/uitest/sort/subtotals.py b/sc/qa/uitest/sort/subtotals.py index b824dcab98c8..6eddd1bc03b4 100644 --- a/sc/qa/uitest/sort/subtotals.py +++ b/sc/qa/uitest/sort/subtotals.py @@ -137,4 +137,113 @@ class Subtotals(UITestCase): self.assertEqual(get_cell_by_position(calc_doc, 0, 0, 1).getValue(), 1) self.assertEqual(get_cell_by_position(calc_doc, 0, 1, 1).getValue(), 2) + def test_tdf162262(self): + with self.ui_test.load_file(get_url_for_data_file("tdf162262.ods")) as calc_doc: + XcalcDoc = self.xUITest.getTopFocusWindow() + gridwin = XcalcDoc.getChild("grid_window") + # One group level + # Select cell range + gridwin.executeAction("SELECT", mkPropertyValues({"RANGE": "A1:C15"})) + # Select from the menu bar Data + # Select option subtotal + # Subtotal dialog displays + with self.ui_test.execute_dialog_through_command(".uno:DataSubTotals") as xDialog: + # Select group by: Day + xGroupBy = xDialog.getChild("group_by1") + select_by_text(xGroupBy, "Day") + # Select 'Calculate subtotals for' -> Value 1 and Value 2 + xCheckListMenu = xDialog.getChild("grid1") + xTreeList = xCheckListMenu.getChild("columns1") + xFirstEntry = xTreeList.getChild("1") + xFirstEntry.executeAction("CLICK", tuple()) + xFirstEntry = xTreeList.getChild("2") + xFirstEntry.executeAction("CLICK", tuple()) + + # Select tab options + xTabs = xDialog.getChild("tabcontrol") + select_pos(xTabs, "3") + # Unselect option Summary below -> false + xSummarybelow = xDialog.getChild("summarybelow") + xSummarybelow.executeAction("CLICK", tuple()) + # apply with OK + + self.assertEqual(get_cell_by_position(calc_doc, 0, 0, 1).getString(), "Grand Sum") + self.assertEqual(get_cell_by_position(calc_doc, 0, 1, 1).getValue(), 105) + self.assertEqual(get_cell_by_position(calc_doc, 0, 2, 1).getValue(), 119) + + self.assertEqual(get_cell_by_position(calc_doc, 0, 0, 2).getString(), "Friday Result") + self.assertEqual(get_cell_by_position(calc_doc, 0, 1, 2).getValue(), 19) + self.assertEqual(get_cell_by_position(calc_doc, 0, 2, 2).getValue(), 21) + + self.assertEqual(get_cell_by_position(calc_doc, 0, 0, 20).getString(), "Wednesday Result") + self.assertEqual(get_cell_by_position(calc_doc, 0, 1, 20).getValue(), 11) + self.assertEqual(get_cell_by_position(calc_doc, 0, 2, 20).getValue(), 13) + + def test_tdf162262_multi(self): + with self.ui_test.load_file(get_url_for_data_file("tdf162262.ods")) as calc_doc: + XcalcDoc = self.xUITest.getTopFocusWindow() + gridwin = XcalcDoc.getChild("grid_window") + # Multi group level + # Select cell range + gridwin.executeAction("SELECT", mkPropertyValues({"RANGE": "A1:C15"})) + # Select from the menu bar Data + # Select option subtotal + # Subtotal dialog displays + with self.ui_test.execute_dialog_through_command(".uno:DataSubTotals") as xDialog: + # Select group by 1: Day + xGroupBy = xDialog.getChild("group_by1") + select_by_text(xGroupBy, "Day") + # Select 'Calculate subtotals for' -> Value 1 + xCheckListMenu = xDialog.getChild("grid1") + xTreeList = xCheckListMenu.getChild("columns1") + # Select 1 column + xFirstEntry = xTreeList.getChild("1") + xFirstEntry.executeAction("CLICK", tuple()) + + # Select tab Group by 2 + xTabs = xDialog.getChild("tabcontrol") + select_pos(xTabs, "1") + + # Select group by 2: Day + xGroupBy = xDialog.getChild("group_by2") + select_by_text(xGroupBy, "Day") + # Select 'Calculate subtotals for' -> Value 2 + xCheckListMenu = xDialog.getChild("grid2") + xTreeList = xCheckListMenu.getChild("columns2") + # Select second column + xFirstEntry = xTreeList.getChild("2") + xFirstEntry.executeAction("CLICK", tuple()) + + # Select tab options + xTabs = xDialog.getChild("tabcontrol") + select_pos(xTabs, "3") + # Unselect option Summary below -> false + xSummarybelow = xDialog.getChild("summarybelow") + xSummarybelow.executeAction("CLICK", tuple()) + # apply with OK + + self.assertEqual(get_cell_by_position(calc_doc, 0, 0, 1).getString(), "Grand Sum") + self.assertEqual(get_cell_by_position(calc_doc, 0, 1, 1).getValue(), 0) + self.assertEqual(get_cell_by_position(calc_doc, 0, 2, 1).getValue(), 119) + + self.assertEqual(get_cell_by_position(calc_doc, 0, 0, 2).getString(), "Grand Sum") + self.assertEqual(get_cell_by_position(calc_doc, 0, 1, 2).getValue(), 105) + self.assertEqual(get_cell_by_position(calc_doc, 0, 2, 2).getValue(), 0) + + self.assertEqual(get_cell_by_position(calc_doc, 0, 0, 3).getString(), "Friday Sum") + self.assertEqual(get_cell_by_position(calc_doc, 0, 1, 3).getValue(), 0) + self.assertEqual(get_cell_by_position(calc_doc, 0, 2, 3).getValue(), 21) + + self.assertEqual(get_cell_by_position(calc_doc, 0, 0, 4).getString(), "Friday Sum") + self.assertEqual(get_cell_by_position(calc_doc, 0, 1, 4).getValue(), 19) + self.assertEqual(get_cell_by_position(calc_doc, 0, 2, 4).getValue(), 0) + + self.assertEqual(get_cell_by_position(calc_doc, 0, 0, 27).getString(), "Wednesday Sum") + self.assertEqual(get_cell_by_position(calc_doc, 0, 1, 27).getValue(), 0) + self.assertEqual(get_cell_by_position(calc_doc, 0, 2, 27).getValue(), 13) + + self.assertEqual(get_cell_by_position(calc_doc, 0, 0, 28).getString(), "Wednesday Sum") + self.assertEqual(get_cell_by_position(calc_doc, 0, 1, 28).getValue(), 11) + self.assertEqual(get_cell_by_position(calc_doc, 0, 2, 28).getValue(), 0) + # vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/sc/qa/unit/data/xlsx/subtotal-above.xlsx b/sc/qa/unit/data/xlsx/subtotal-above.xlsx Binary files differnew file mode 100644 index 000000000000..b271dbab19be --- /dev/null +++ b/sc/qa/unit/data/xlsx/subtotal-above.xlsx diff --git a/sc/qa/unit/subsequent_export_test4.cxx b/sc/qa/unit/subsequent_export_test4.cxx index e6b5a6389af3..fdb3b6f9a876 100644 --- a/sc/qa/unit/subsequent_export_test4.cxx +++ b/sc/qa/unit/subsequent_export_test4.cxx @@ -398,6 +398,18 @@ CPPUNIT_TEST_FIXTURE(ScExportTest4, testTdf81470) assertXPath(pHeaders, "/x:headers/x:header[3]", "userName", u"Kohei Yoshida"); } +CPPUNIT_TEST_FIXTURE(ScExportTest4, testTdf162262) +{ + createScDoc("xlsx/subtotal-above.xlsx"); + + save(u"Calc Office Open XML"_ustr); + + xmlDocUniquePtr pSheet = parseExport(u"xl/worksheets/sheet1.xml"_ustr); + CPPUNIT_ASSERT(pSheet); + + assertXPath(pSheet, "/x:worksheet/x:sheetPr/x:outlinePr", "summaryBelow", u"0"); +} + CPPUNIT_TEST_FIXTURE(ScExportTest4, testTdf122331) { createScDoc("ods/tdf122331.ods"); diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index f97fca6ef8a9..dbcdbe089163 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -228,6 +228,25 @@ bool ScDocument::GetCodeName( SCTAB nTab, OUString& rName ) const return false; } +bool ScDocument::SetTotalsRowBelow( SCTAB nTab, bool bVal ) +{ + if (ScTable* pTable = FetchTable(nTab)) + { + pTable->SetTotalsRowBelow(bVal); + return true; + } + return false; +} + +bool ScDocument::GetTotalsRowBelow( SCTAB nTab ) const +{ + if (const ScTable* pTable = FetchTable(nTab)) + { + return pTable->GetTotalsRowBelow(); + } + return true; +} + bool ScDocument::GetTable( const OUString& rName, SCTAB& rTab ) const { static OUString aCacheName, aCacheUpperName; diff --git a/sc/source/core/data/subtotalparam.cxx b/sc/source/core/data/subtotalparam.cxx index e8f32954297c..6fd8e18c6b0e 100644 --- a/sc/source/core/data/subtotalparam.cxx +++ b/sc/source/core/data/subtotalparam.cxx @@ -26,7 +26,7 @@ ScSubTotalParam::ScSubTotalParam() ScSubTotalParam::ScSubTotalParam( const ScSubTotalParam& r ) : nCol1(r.nCol1),nRow1(r.nRow1),nCol2(r.nCol2),nRow2(r.nRow2),nUserIndex(r.nUserIndex), bRemoveOnly(r.bRemoveOnly),bReplace(r.bReplace),bPagebreak(r.bPagebreak),bCaseSens(r.bCaseSens), - bDoSort(r.bDoSort),bAscending(r.bAscending),bUserDef(r.bUserDef), + bDoSort(r.bDoSort), bSummaryBelow(r.bSummaryBelow), bAscending(r.bAscending), bUserDef(r.bUserDef), bIncludePattern(r.bIncludePattern) { for (sal_uInt16 i=0; i<MAXSUBTOTAL; i++) @@ -59,7 +59,7 @@ void ScSubTotalParam::Clear() nRow1=nRow2 = 0; nUserIndex = 0; bPagebreak=bCaseSens=bUserDef=bIncludePattern=bRemoveOnly = false; - bAscending=bReplace=bDoSort = true; + bAscending=bReplace=bDoSort=bSummaryBelow = true; for (sal_uInt16 i=0; i<MAXSUBTOTAL; i++) { @@ -90,6 +90,7 @@ ScSubTotalParam& ScSubTotalParam::operator=( const ScSubTotalParam& r ) bPagebreak = r.bPagebreak; bCaseSens = r.bCaseSens; bDoSort = r.bDoSort; + bSummaryBelow = r.bSummaryBelow; bAscending = r.bAscending; bUserDef = r.bUserDef; nUserIndex = r.nUserIndex; @@ -135,6 +136,7 @@ bool ScSubTotalParam::operator==( const ScSubTotalParam& rOther ) const && (bReplace == rOther.bReplace) && (bPagebreak == rOther.bPagebreak) && (bDoSort == rOther.bDoSort) + && (bSummaryBelow == rOther.bSummaryBelow) && (bCaseSens == rOther.bCaseSens) && (bAscending == rOther.bAscending) && (bUserDef == rOther.bUserDef) diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx index d022ba2c4473..fed72506c2a3 100644 --- a/sc/source/core/data/table3.cxx +++ b/sc/source/core/data/table3.cxx @@ -2060,9 +2060,10 @@ bool ScTable::DoSubTotals( ScSubTotalParam& rParam ) if (nResCount > 0) // otherwise only sort { + SCROW nAboveRows = rParam.bSummaryBelow ? nStartRow : nStartRow + nLevel; for (sal_uInt16 i = 0; i <= aRowEntry.nGroupNo; ++i) { - aSubString = GetString( nGroupCol[i], nStartRow ); + aSubString = GetString( nGroupCol[i], nAboveRows ); if ( bIgnoreCase ) aCompString[i] = ScGlobal::getCharClass().uppercase( aSubString ); else @@ -2070,8 +2071,8 @@ bool ScTable::DoSubTotals( ScSubTotalParam& rParam ) } // aSubString stays on the last bool bBlockVis = false; // group visible? - aRowEntry.nSubStartRow = nStartRow; - for (SCROW nRow=nStartRow; nRow<=nEndRow+1 && bSpaceLeft; nRow++) + aRowEntry.nSubStartRow = nAboveRows; + for (SCROW nRow=nAboveRows; nRow<=nEndRow+1 && bSpaceLeft; nRow++) { bool bChanged; if (nRow>nEndRow) @@ -2099,9 +2100,21 @@ bool ScTable::DoSubTotals( ScSubTotalParam& rParam ) } if ( bChanged ) { - aRowEntry.nDestRow = nRow; - aRowEntry.nFuncStart = aRowEntry.nSubStartRow; - aRowEntry.nFuncEnd = nRow-1; + if (rParam.bSummaryBelow) + { + aRowEntry.nDestRow = nRow; + aRowEntry.nFuncStart = aRowEntry.nSubStartRow; + aRowEntry.nFuncEnd = nRow - 1; + } + else + { + aRowEntry.nDestRow = aRowEntry.nSubStartRow; + aRowEntry.nFuncStart = aRowEntry.nSubStartRow + 1; + if (nRow != nEndRow + 1) + aRowEntry.nFuncEnd = nRow - nLevel; + else + aRowEntry.nFuncEnd = nRow; + } bSpaceLeft = rDocument.InsertRow( 0, nTab, rDocument.MaxCol(), nTab, aRowEntry.nDestRow, 1 ); @@ -2157,17 +2170,27 @@ bool ScTable::DoSubTotals( ScSubTotalParam& rParam ) if (!aRowVector.empty()) { - // generate global total - SCROW nGlobalStartRow = aRowVector[0].nSubStartRow; - SCROW nGlobalStartFunc = aRowVector[0].nFuncStart; SCROW nGlobalEndRow = 0; SCROW nGlobalEndFunc = 0; - for (const auto& rRowEntry : aRowVector) + for (auto& rRowEntry : aRowVector) { + if (!rParam.bSummaryBelow) + { + // if we have Global summary above, we need to shift summary rows down + rRowEntry.nDestRow = rRowEntry.nDestRow + nLevelCount; + rRowEntry.nFuncEnd = rRowEntry.nFuncEnd + nLevelCount; + rRowEntry.nFuncStart = rRowEntry.nFuncStart + nLevelCount - rRowEntry.nGroupNo; + rRowEntry.nSubStartRow = rRowEntry.nSubStartRow + nLevelCount; + } + nGlobalEndRow = (nGlobalEndRow < rRowEntry.nDestRow) ? rRowEntry.nDestRow : nGlobalEndRow; nGlobalEndFunc = (nGlobalEndFunc < rRowEntry.nFuncEnd) ? rRowEntry.nFuncEnd : nGlobalEndRow; } + // generate global total + SCROW nGlobalStartRow = aRowVector[0].nSubStartRow; + SCROW nGlobalStartFunc = aRowVector[0].nFuncStart; + for (sal_uInt16 nLevel = 0; nLevel<nLevelCount; nLevel++) { const sal_uInt16 nGroupNo = nLevelCount - nLevel - 1; @@ -2179,18 +2202,30 @@ bool ScTable::DoSubTotals( ScSubTotalParam& rParam ) continue; } - // increment end row - nGlobalEndRow++; - - // add row entry for formula - aRowEntry.nGroupNo = nGroupNo; - aRowEntry.nSubStartRow = nGlobalStartRow; - aRowEntry.nFuncStart = nGlobalStartFunc; - aRowEntry.nDestRow = nGlobalEndRow; - aRowEntry.nFuncEnd = nGlobalEndFunc; - - // increment row - nGlobalEndFunc++; + if (rParam.bSummaryBelow) + { + // increment end row + nGlobalEndRow++; + + // add row entry for formula + aRowEntry.nGroupNo = nGroupNo; + aRowEntry.nSubStartRow = nGlobalStartRow; + aRowEntry.nFuncStart = nGlobalStartFunc; + aRowEntry.nDestRow = nGlobalEndRow; + aRowEntry.nFuncEnd = nGlobalEndFunc; + + // increment row + nGlobalEndFunc++; + } + else + { + // if we have Global summary we need to shift summary rows down + aRowEntry.nGroupNo = nGroupNo; + aRowEntry.nSubStartRow = nGlobalStartRow - nGroupNo - 1; + aRowEntry.nFuncStart = nGlobalStartFunc - nGroupNo - 1; + aRowEntry.nDestRow = nGlobalStartRow - nGroupNo - 1; + aRowEntry.nFuncEnd = nGlobalEndFunc; + } bSpaceLeft = rDocument.InsertRow(0, nTab, rDocument.MaxCol(), nTab, aRowEntry.nDestRow, 1); diff --git a/sc/source/filter/excel/excdoc.cxx b/sc/source/filter/excel/excdoc.cxx index 847e6d457cbf..7907a87223c0 100644 --- a/sc/source/filter/excel/excdoc.cxx +++ b/sc/source/filter/excel/excdoc.cxx @@ -586,8 +586,9 @@ void ExcTable::FillAsTableXml() XclExtLstRef xExtLst = new XclExtLst( GetRoot() ); bool bFitToPages = xPageSett->GetPageData().mbFitToPages; + bool bSummaryBelow = GetRoot().GetDoc().GetTotalsRowBelow(mnScTab); Color aTabColor = GetRoot().GetDoc().GetTabBgColor(mnScTab); - Add(new XclExpXmlSheetPr(bFitToPages, mnScTab, aTabColor, &GetFilterManager())); + Add(new XclExpXmlSheetPr(bFitToPages, mnScTab, aTabColor, bSummaryBelow, &GetFilterManager())); // GUTS (count & size of outline icons) aRecList.AppendRecord( mxCellTable->CreateRecord( EXC_ID_GUTS ) ); diff --git a/sc/source/filter/excel/excrecds.cxx b/sc/source/filter/excel/excrecds.cxx index 381836c10c12..afd38447d865 100644 --- a/sc/source/filter/excel/excrecds.cxx +++ b/sc/source/filter/excel/excrecds.cxx @@ -368,8 +368,8 @@ XclExpWsbool::XclExpWsbool( bool bFitToPages ) SetValue( GetValue() | EXC_WSBOOL_FITTOPAGE ); } -XclExpXmlSheetPr::XclExpXmlSheetPr( bool bFitToPages, SCTAB nScTab, const Color& rTabColor, XclExpFilterManager* pManager ) : - mnScTab(nScTab), mpManager(pManager), mbFitToPage(bFitToPages), maTabColor(rTabColor) {} +XclExpXmlSheetPr::XclExpXmlSheetPr( bool bFitToPages, SCTAB nScTab, const Color& rTabColor, bool bSummaryBelow, XclExpFilterManager* pManager ) : + mnScTab(nScTab), mpManager(pManager), mbFitToPage(bFitToPages), maTabColor(rTabColor), mbSummaryBelow(bSummaryBelow) {} void XclExpXmlSheetPr::SaveXml( XclExpXmlStream& rStrm ) { @@ -388,11 +388,13 @@ void XclExpXmlSheetPr::SaveXml( XclExpXmlStream& rStrm ) // Note : the order of child elements is significant. Don't change the order. - // OOXTODO: XML_outlinePr - if (maTabColor != COL_AUTO) rWorksheet->singleElement(XML_tabColor, XML_rgb, XclXmlUtils::ToOString(maTabColor)); + // OOXTODO: XML_outlinePr --> XML_applyStyles, XML_showOutlineSymbols, XML_summaryBelow, XML_summaryRight + if (!mbSummaryBelow) + rWorksheet->singleElement(XML_outlinePr, XML_summaryBelow, "0"); + rWorksheet->singleElement(XML_pageSetUpPr, // OOXTODO: XML_autoPageBreaks, XML_fitToPage, ToPsz(mbFitToPage)); diff --git a/sc/source/filter/inc/excrecds.hxx b/sc/source/filter/inc/excrecds.hxx index c7ab0aa96bd2..629ddfd18b5a 100644 --- a/sc/source/filter/inc/excrecds.hxx +++ b/sc/source/filter/inc/excrecds.hxx @@ -304,7 +304,7 @@ class XclExpXmlSheetPr : public XclExpRecordBase { public: explicit XclExpXmlSheetPr( - bool bFitToPages, SCTAB nScTab, const Color& rTabColor, XclExpFilterManager* pManager ); + bool bFitToPages, SCTAB nScTab, const Color& rTabColor, bool bSummaryBelow, XclExpFilterManager* pManager ); virtual void SaveXml( XclExpXmlStream& rStrm ) override; @@ -313,6 +313,7 @@ private: XclExpFilterManager* mpManager; bool mbFitToPage; Color maTabColor; + bool mbSummaryBelow; }; class XclExpFiltermode : public XclExpEmptyRecord diff --git a/sc/source/filter/oox/worksheetsettings.cxx b/sc/source/filter/oox/worksheetsettings.cxx index 988207aa9067..46d633044115 100644 --- a/sc/source/filter/oox/worksheetsettings.cxx +++ b/sc/source/filter/oox/worksheetsettings.cxx @@ -287,6 +287,12 @@ void WorksheetSettings::finalizeImport() ::Color nColor = maSheetSettings.maTabColor.getColor( getBaseFilter().getGraphicHelper() ); aPropSet.setProperty( PROP_TabColor, nColor ); } + + // Summary data below or above the contents + if ( !maSheetSettings.mbSummaryBelow ) + { + aPropSet.setProperty( PROP_TotalsRowBelow, false ); + } } } // namespace oox::xls diff --git a/sc/source/ui/dbgui/tpsubt.cxx b/sc/source/ui/dbgui/tpsubt.cxx index c657f482da34..e0fcf640f756 100644 --- a/sc/source/ui/dbgui/tpsubt.cxx +++ b/sc/source/ui/dbgui/tpsubt.cxx @@ -447,6 +447,7 @@ ScTpSubTotalOptions::ScTpSubTotalOptions(weld::Container* pPage, weld::DialogCon , m_xBtnPagebreak(m_xBuilder->weld_check_button(u"pagebreak"_ustr)) , m_xBtnCase(m_xBuilder->weld_check_button(u"case"_ustr)) , m_xBtnSort(m_xBuilder->weld_check_button(u"sort"_ustr)) + , m_xBtnSummary(m_xBuilder->weld_check_button(u"summarybelow"_ustr)) , m_xFlSort(m_xBuilder->weld_label(u"label2"_ustr)) , m_xBtnAscending(m_xBuilder->weld_radio_button(u"ascending"_ustr)) , m_xBtnDescending(m_xBuilder->weld_radio_button(u"descending"_ustr)) @@ -490,6 +491,7 @@ void ScTpSubTotalOptions::Reset( const SfxItemSet* /* rArgSet */ ) m_xBtnCase->set_active( rSubTotalData.bCaseSens ); m_xBtnFormats->set_active( rSubTotalData.bIncludePattern ); m_xBtnSort->set_active( rSubTotalData.bDoSort ); + m_xBtnSummary->set_active( rSubTotalData.bSummaryBelow ); m_xBtnAscending->set_active( rSubTotalData.bAscending ); m_xBtnDescending->set_active( !rSubTotalData.bAscending ); @@ -524,6 +526,10 @@ bool ScTpSubTotalOptions::FillItemSet( SfxItemSet* rArgSet ) theSubTotalData.bCaseSens = m_xBtnCase->get_active(); theSubTotalData.bIncludePattern = m_xBtnFormats->get_active(); theSubTotalData.bDoSort = m_xBtnSort->get_active(); + + theSubTotalData.bSummaryBelow = m_xBtnSummary->get_active(); + pDoc->SetTotalsRowBelow(pViewData->GetTabNo(), theSubTotalData.bSummaryBelow); + theSubTotalData.bAscending = m_xBtnAscending->get_active(); theSubTotalData.bUserDef = m_xBtnUserDef->get_active(); theSubTotalData.nUserIndex = (m_xBtnUserDef->get_active()) diff --git a/sc/source/ui/inc/tpsubt.hxx b/sc/source/ui/inc/tpsubt.hxx index ecfa2ec18522..42eed5e4046e 100644 --- a/sc/source/ui/inc/tpsubt.hxx +++ b/sc/source/ui/inc/tpsubt.hxx @@ -135,6 +135,7 @@ private: std::unique_ptr<weld::CheckButton> m_xBtnPagebreak; std::unique_ptr<weld::CheckButton> m_xBtnCase; std::unique_ptr<weld::CheckButton> m_xBtnSort; + std::unique_ptr<weld::CheckButton> m_xBtnSummary; std::unique_ptr<weld::Label> m_xFlSort; std::unique_ptr<weld::RadioButton> m_xBtnAscending; std::unique_ptr<weld::RadioButton> m_xBtnDescending; diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx index 9cc4117ed403..556edb426ba9 100644 --- a/sc/source/ui/unoobj/cellsuno.cxx +++ b/sc/source/ui/unoobj/cellsuno.cxx @@ -787,6 +787,7 @@ static const SfxItemPropertySet* lcl_GetSheetPropertySet() { SC_UNO_CODENAME, SC_WID_UNO_CODENAME, cppu::UnoType<OUString>::get(), 0, 0}, { SC_UNO_NAMEDRANGES, SC_WID_UNO_NAMES, cppu::UnoType<sheet::XNamedRanges>::get(), 0, 0 }, { SC_UNO_SOLVERSETTINGS, SC_WID_UNO_SOLVERSETTINGS, cppu::UnoType<sheet::XSolverSettings>::get(), 0, 0 }, + { SC_UNONAME_TOTALBELOW, SC_WID_UNO_TOTALBELOW, cppu::UnoType<bool>::get(), 0, 0 }, }; static SfxItemPropertySet aSheetPropertySet( aSheetPropertyMap_Impl ); return &aSheetPropertySet; @@ -8062,6 +8063,11 @@ void ScTableSheetObj::SetOnePropertyValue( const SfxItemPropertyMapEntry* pEntry // how to set the format correctly } } + else if (pEntry->nWID == SC_WID_UNO_TOTALBELOW) + { + bool bTotalsRowBelow = ScUnoHelpFunctions::GetBoolFromAny(aValue); + rDoc.SetTotalsRowBelow(nTab, bTotalsRowBelow); + } else ScCellRangeObj::SetOnePropertyValue(pEntry, aValue); // base class, no Item WID } diff --git a/sc/source/ui/view/cellsh1.cxx b/sc/source/ui/view/cellsh1.cxx index 1e4b9f1bdc33..71a827abc1f3 100644 --- a/sc/source/ui/view/cellsh1.cxx +++ b/sc/source/ui/view/cellsh1.cxx @@ -3643,6 +3643,12 @@ void ScCellShell::ExecuteSubtotals(SfxRequest& rReq) } pDBData->GetSubTotalParam( aSubTotalParam ); + + ScDocument& rDoc = GetViewData().GetDocument(); + SCTAB nTab = GetViewData().GetTabNo(); + if (!rDoc.GetTotalsRowBelow(nTab)) + aSubTotalParam.bSummaryBelow = false; + aSubTotalParam.bRemoveOnly = false; if (bAnonymous) { diff --git a/sc/uiconfig/scalc/ui/subtotaloptionspage.ui b/sc/uiconfig/scalc/ui/subtotaloptionspage.ui index d81fb987be61..0d1c54f510d0 100644 --- a/sc/uiconfig/scalc/ui/subtotaloptionspage.ui +++ b/sc/uiconfig/scalc/ui/subtotaloptionspage.ui @@ -1,39 +1,39 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- Generated with glade 3.36.0 --> +<!-- Generated with glade 3.38.2 --> <interface domain="sc"> <requires lib="gtk+" version="3.20"/> <object class="GtkBox" id="SubTotalOptionsPage"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="border_width">6</property> + <property name="can-focus">False</property> + <property name="border-width">6</property> <property name="orientation">vertical</property> <property name="spacing">12</property> <child> <object class="GtkFrame" id="frame1"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="hexpand">True</property> - <property name="label_xalign">0</property> - <property name="shadow_type">none</property> + <property name="label-xalign">0</property> + <property name="shadow-type">none</property> <child> - <!-- n-columns=1 n-rows=1 --> + <!-- n-columns=1 n-rows=4 --> <object class="GtkGrid" id="grid1"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="hexpand">True</property> - <property name="vexpand">True</property> - <property name="row_spacing">6</property> + <property name="can-focus">False</property> <property name="margin-start">12</property> <property name="margin-top">6</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="row-spacing">6</property> <child> <object class="GtkCheckButton" id="pagebreak"> <property name="label" translatable="yes" context="subtotaloptionspage|pagebreak">_Page break between groups</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> <property name="hexpand">True</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> + <property name="use-underline">True</property> + <property name="draw-indicator">True</property> <child internal-child="accessible"> <object class="AtkObject" id="pagebreak-atkobject"> <property name="AtkObject::accessible-description" translatable="yes" context="subtotaloptionspage|extended_tip|pagebreak">Inserts a new page after each group of subtotaled data.</property> @@ -41,19 +41,19 @@ </child> </object> <packing> - <property name="left_attach">0</property> - <property name="top_attach">0</property> + <property name="left-attach">0</property> + <property name="top-attach">0</property> </packing> </child> <child> <object class="GtkCheckButton" id="case"> <property name="label" translatable="yes" context="subtotaloptionspage|case">_Case sensitive</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> <property name="hexpand">True</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> + <property name="use-underline">True</property> + <property name="draw-indicator">True</property> <child internal-child="accessible"> <object class="AtkObject" id="case-atkobject"> <property name="AtkObject::accessible-description" translatable="yes" context="subtotaloptionspage|extended_tip|case">Recalculates subtotals when you change the case of a data label.</property> @@ -61,19 +61,19 @@ </child> </object> <packing> - <property name="left_attach">0</property> - <property name="top_attach">1</property> + <property name="left-attach">0</property> + <property name="top-attach">1</property> </packing> </child> <child> <object class="GtkCheckButton" id="sort"> <property name="label" translatable="yes" context="subtotaloptionspage|sort">Pre-_sort area according to groups</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> <property name="hexpand">True</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> + <property name="use-underline">True</property> + <property name="draw-indicator">True</property> <child internal-child="accessible"> <object class="AtkObject" id="sort-atkobject"> <property name="AtkObject::accessible-description" translatable="yes" context="subtotaloptionspage|extended_tip|sort">Sorts the area that you selected in the Group by box of the Group tabs according to the columns that you selected.</property> @@ -81,8 +81,28 @@ </child> </object> <packing> - <property name="left_attach">0</property> - <property name="top_attach">2</property> + <property name="left-attach">0</property> + <property name="top-attach">2</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="summarybelow"> + <property name="label" translatable="yes" context="subtotaloptionspage|sort">_Summary below data</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="hexpand">True</property> + <property name="use-underline">True</property> + <property name="draw-indicator">True</property> + <child internal-child="accessible"> + <object class="AtkObject" id="summarybelow-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="subtotaloptionspage|extended_tip|summarybelow">Decide if the subtotals below or above the data. Reposition subtotals when you change the summary below data options.</property> + </object> + </child> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">3</property> </packing> </child> </object> @@ -90,7 +110,7 @@ <child type="label"> <object class="GtkLabel" id="label1"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="label" translatable="yes" context="subtotaloptionspage|label1">Groups</property> <attributes> <attribute name="weight" value="bold"/> @@ -107,31 +127,31 @@ <child> <object class="GtkFrame" id="frame2"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="hexpand">True</property> <property name="vexpand">True</property> - <property name="label_xalign">0</property> - <property name="shadow_type">none</property> + <property name="label-xalign">0</property> + <property name="shadow-type">none</property> <child> - <!-- n-columns=1 n-rows=1 --> + <!-- n-columns=1 n-rows=5 --> <object class="GtkGrid" id="grid2"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="hexpand">True</property> - <property name="vexpand">True</property> - <property name="row_spacing">6</property> + <property name="can-focus">False</property> <property name="margin-start">12</property> <property name="margin-top">6</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="row-spacing">6</property> <child> <object class="GtkRadioButton" id="ascending"> <property name="label" translatable="yes" context="subtotaloptionspage|ascending">_Ascending</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> <property name="hexpand">True</property> - <property name="use_underline">True</property> + <property name="use-underline">True</property> <property name="active">True</property> - <property name="draw_indicator">True</property> + <property name="draw-indicator">True</property> <child internal-child="accessible"> <object class="AtkObject" id="ascending-atkobject"> <property name="AtkObject::accessible-description" translatable="yes" context="subtotaloptionspage|extended_tip|ascending">Sorts beginning with the lowest value. You can define the sort rules on Data - Sort - Options.</property> @@ -139,19 +159,19 @@ </child> </object> <packing> - <property name="left_attach">0</property> - <property name="top_attach">0</property> + <property name="left-attach">0</property> + <property name="top-attach">0</property> </packing> </child> <child> <object class="GtkRadioButton" id="descending"> <property name="label" translatable="yes" context="subtotaloptionspage|descending">D_escending</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> <property name="hexpand">True</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> + <property name="use-underline">True</property> + <property name="draw-indicator">True</property> <property name="group">ascending</property> <child internal-child="accessible"> <object class="AtkObject" id="descending-atkobject"> @@ -160,19 +180,19 @@ </child> </object> <packing> - <property name="left_attach">0</property> - <property name="top_attach">1</property> + <property name="left-attach">0</property> + <property name="top-attach">1</property> </packing> </child> <child> <object class="GtkCheckButton" id="formats"> <property name="label" translatable="yes" context="subtotaloptionspage|formats">I_nclude formats</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> <property name="hexpand">True</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> + <property name="use-underline">True</property> + <property name="draw-indicator">True</property> <child internal-child="accessible"> <object class="AtkObject" id="formats-atkobject"> <property name="AtkObject::accessible-description" translatable="yes" context="subtotaloptionspage|extended_tip|formats">Considers formatting attributes when sorting.</property> @@ -180,40 +200,40 @@ </child> </object> <packing> - <property name="left_attach">0</property> - <property name="top_attach">2</property> + <property name="left-attach">0</property> + <property name="top-attach">2</property> </packing> </child> <child> <object class="GtkCheckButton" id="btnuserdef"> <property name="label" translatable="yes" context="subtotaloptionspage|btnuserdef">C_ustom sort order</property> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> <property name="hexpand">True</property> - <property name="use_underline">True</property> - <property name="draw_indicator">True</property> + <property name="use-underline">True</property> + <property name="draw-indicator">True</property> <accessibility> <relation type="label-for" target="lbuserdef"/> </accessibility> </object> <packing> - <property name="left_attach">0</property> - <property name="top_attach">3</property> + <property name="left-attach">0</property> + <property name="top-attach">3</property> </packing> </child> <child> <object class="GtkComboBoxText" id="lbuserdef"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="margin-start">12</property> <accessibility> <relation type="labelled-by" target="btnuserdef"/> </accessibility> </object> <packing> - <property name="left_attach">0</property> - <property name="top_attach">4</property> + <property name="left-attach">0</property> + <property name="top-attach">4</property> </packing> </child> </object> @@ -221,7 +241,7 @@ <child type="label"> <object class="GtkLabel" id="label2"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can-focus">False</property> <property name="label" translatable="yes" context="subtotaloptionspage|label2">Sort</property> <attributes> <attribute name="weight" value="bold"/> |