summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
Diffstat (limited to 'sc')
-rw-r--r--sc/inc/document.hxx2
-rw-r--r--sc/inc/subtotalparam.hxx1
-rw-r--r--sc/inc/table.hxx4
-rw-r--r--sc/inc/unonames.hxx1
-rw-r--r--sc/inc/unowids.hxx3
-rw-r--r--sc/qa/uitest/data/tdf162262.odsbin0 -> 17343 bytes
-rw-r--r--sc/qa/uitest/sort/subtotals.py109
-rw-r--r--sc/qa/unit/data/xlsx/subtotal-above.xlsxbin0 -> 10111 bytes
-rw-r--r--sc/qa/unit/subsequent_export_test4.cxx12
-rw-r--r--sc/source/core/data/document.cxx19
-rw-r--r--sc/source/core/data/subtotalparam.cxx6
-rw-r--r--sc/source/core/data/table3.cxx79
-rw-r--r--sc/source/filter/excel/excdoc.cxx3
-rw-r--r--sc/source/filter/excel/excrecds.cxx10
-rw-r--r--sc/source/filter/inc/excrecds.hxx3
-rw-r--r--sc/source/filter/oox/worksheetsettings.cxx6
-rw-r--r--sc/source/ui/dbgui/tpsubt.cxx6
-rw-r--r--sc/source/ui/inc/tpsubt.hxx1
-rw-r--r--sc/source/ui/unoobj/cellsuno.cxx6
-rw-r--r--sc/source/ui/view/cellsh1.cxx6
-rw-r--r--sc/uiconfig/scalc/ui/subtotaloptionspage.ui152
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
new file mode 100644
index 000000000000..138348366298
--- /dev/null
+++ b/sc/qa/uitest/data/tdf162262.ods
Binary files differ
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
new file mode 100644
index 000000000000..b271dbab19be
--- /dev/null
+++ b/sc/qa/unit/data/xlsx/subtotal-above.xlsx
Binary files differ
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"/>