sc lok: add .uno:AutoSum
Change-Id: Id2bc0200734308aae1c2e39814c22c6b76664c59 Reviewed-on: https://gerrit.libreoffice.org/29525 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Henry Castro <hcastro@collabora.com>
This commit is contained in:
@@ -243,6 +243,7 @@
|
||||
#define SC_HINT_FORCESETTAB (SC_MESSAGE_START + 36)
|
||||
#define SID_ENTER_STRING (SC_MESSAGE_START + 37)
|
||||
#define SID_ROWCOL_SELCOUNT (SC_MESSAGE_START + 38)
|
||||
#define SID_AUTO_SUM (SC_MESSAGE_START + 39)
|
||||
|
||||
// messages for opening dialogs:
|
||||
#define SID_OPENDLG_CONSOLIDATE (SC_MESSAGE_START + 50)
|
||||
|
@@ -66,6 +66,7 @@ public:
|
||||
void testTextEditViews();
|
||||
void testTextEditViewInvalidations();
|
||||
void testGraphicInvalidate();
|
||||
void testAutoSum();
|
||||
|
||||
CPPUNIT_TEST_SUITE(ScTiledRenderingTest);
|
||||
CPPUNIT_TEST(testRowColumnSelections);
|
||||
@@ -83,6 +84,7 @@ public:
|
||||
CPPUNIT_TEST(testTextEditViews);
|
||||
CPPUNIT_TEST(testTextEditViewInvalidations);
|
||||
CPPUNIT_TEST(testGraphicInvalidate);
|
||||
CPPUNIT_TEST(testAutoSum);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
private:
|
||||
@@ -390,6 +392,7 @@ public:
|
||||
bool m_bFullInvalidateTiles;
|
||||
bool m_bInvalidateTiles;
|
||||
bool m_bViewLock;
|
||||
OString m_sCellFormula;
|
||||
|
||||
ViewCallback()
|
||||
: m_bOwnCursorInvalidated(false),
|
||||
@@ -457,6 +460,11 @@ public:
|
||||
m_bInvalidateTiles = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LOK_CALLBACK_CELL_FORMULA:
|
||||
{
|
||||
m_sCellFormula = pPayload;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -820,6 +828,24 @@ void ScTiledRenderingTest::testGraphicInvalidate()
|
||||
comphelper::LibreOfficeKit::setActive(false);
|
||||
}
|
||||
|
||||
void ScTiledRenderingTest::testAutoSum()
|
||||
{
|
||||
// Load a document
|
||||
comphelper::LibreOfficeKit::setActive();
|
||||
createDoc("small.ods");
|
||||
|
||||
ViewCallback aView;
|
||||
SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView);
|
||||
|
||||
uno::Sequence<beans::PropertyValue> aArgs;
|
||||
comphelper::dispatchCommand(".uno:AutoSum", aArgs);
|
||||
Scheduler::ProcessEventsToIdle();
|
||||
CPPUNIT_ASSERT(aView.m_sCellFormula.startsWith("=SUM("));
|
||||
|
||||
mxComponent->dispose();
|
||||
mxComponent.clear();
|
||||
comphelper::LibreOfficeKit::setActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(ScTiledRenderingTest);
|
||||
|
@@ -235,6 +235,7 @@ interface CellSelection
|
||||
SID_TRANSLITERATE_FULLWIDTH [ ExecMethod = ExecuteTrans; StateMethod = GetBlockState; ]
|
||||
SID_TRANSLITERATE_HIRAGANA [ ExecMethod = ExecuteTrans; StateMethod = GetBlockState; ]
|
||||
SID_TRANSLITERATE_KATAGANA [ ExecMethod = ExecuteTrans; StateMethod = GetBlockState; ]
|
||||
SID_AUTO_SUM [ ExecMethod = ExecuteEdit; ]
|
||||
}
|
||||
|
||||
|
||||
|
@@ -6632,3 +6632,21 @@ SfxUInt16Item NumberFormatType SID_NUMBER_TYPE_FORMAT
|
||||
ToolBoxConfig = TRUE,
|
||||
GroupId = GID_FORMAT;
|
||||
]
|
||||
|
||||
|
||||
SfxVoidItem AutoSum SID_AUTO_SUM
|
||||
[
|
||||
AutoUpdate = FALSE,
|
||||
FastCall = FALSE,
|
||||
ReadOnlyDoc = TRUE,
|
||||
Toggle = FALSE,
|
||||
Container = FALSE,
|
||||
RecordAbsolute = FALSE,
|
||||
RecordPerSet;
|
||||
|
||||
|
||||
AccelConfig = FALSE,
|
||||
MenuConfig = FALSE,
|
||||
ToolBoxConfig = TRUE,
|
||||
GroupId = GID_INTERN;
|
||||
]
|
||||
|
@@ -292,65 +292,6 @@ void ScInputWindow::SetInputHandler( ScInputHandler* pNew )
|
||||
}
|
||||
}
|
||||
|
||||
bool ScInputWindow::UseSubTotal(ScRangeList* pRangeList)
|
||||
{
|
||||
bool bSubTotal = false;
|
||||
ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>( SfxViewShell::Current() );
|
||||
if ( pViewSh )
|
||||
{
|
||||
ScDocument* pDoc = pViewSh->GetViewData().GetDocument();
|
||||
size_t nRangeCount (pRangeList->size());
|
||||
size_t nRangeIndex (0);
|
||||
while (!bSubTotal && nRangeIndex < nRangeCount)
|
||||
{
|
||||
const ScRange* pRange = (*pRangeList)[nRangeIndex];
|
||||
if( pRange )
|
||||
{
|
||||
SCTAB nTabEnd(pRange->aEnd.Tab());
|
||||
SCTAB nTab(pRange->aStart.Tab());
|
||||
while (!bSubTotal && nTab <= nTabEnd)
|
||||
{
|
||||
SCROW nRowEnd(pRange->aEnd.Row());
|
||||
SCROW nRow(pRange->aStart.Row());
|
||||
while (!bSubTotal && nRow <= nRowEnd)
|
||||
{
|
||||
if (pDoc->RowFiltered(nRow, nTab))
|
||||
bSubTotal = true;
|
||||
else
|
||||
++nRow;
|
||||
}
|
||||
++nTab;
|
||||
}
|
||||
}
|
||||
++nRangeIndex;
|
||||
}
|
||||
|
||||
const ScDBCollection::NamedDBs& rDBs = pDoc->GetDBCollection()->getNamedDBs();
|
||||
ScDBCollection::NamedDBs::const_iterator itr = rDBs.begin(), itrEnd = rDBs.end();
|
||||
for (; !bSubTotal && itr != itrEnd; ++itr)
|
||||
{
|
||||
const ScDBData& rDB = **itr;
|
||||
if (!rDB.HasAutoFilter())
|
||||
continue;
|
||||
|
||||
nRangeIndex = 0;
|
||||
while (!bSubTotal && nRangeIndex < nRangeCount)
|
||||
{
|
||||
const ScRange* pRange = (*pRangeList)[nRangeIndex];
|
||||
if( pRange )
|
||||
{
|
||||
ScRange aDBArea;
|
||||
rDB.GetArea(aDBArea);
|
||||
if (aDBArea.Intersects(*pRange))
|
||||
bSubTotal = true;
|
||||
}
|
||||
++nRangeIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bSubTotal;
|
||||
}
|
||||
|
||||
void ScInputWindow::Select()
|
||||
{
|
||||
ScModule* pScMod = SC_MOD();
|
||||
@@ -390,98 +331,10 @@ void ScInputWindow::Select()
|
||||
ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>( SfxViewShell::Current() );
|
||||
if ( pViewSh )
|
||||
{
|
||||
const ScMarkData& rMark = pViewSh->GetViewData().GetMarkData();
|
||||
if ( rMark.IsMarked() || rMark.IsMultiMarked() )
|
||||
const OUString aFormula = pViewSh->DoAutoSum();
|
||||
if (!aFormula.isEmpty())
|
||||
{
|
||||
ScRangeList aMarkRangeList;
|
||||
rMark.FillRangeListWithMarks( &aMarkRangeList, false );
|
||||
ScDocument* pDoc = pViewSh->GetViewData().GetDocument();
|
||||
|
||||
// check if one of the marked ranges is empty
|
||||
bool bEmpty = false;
|
||||
const size_t nCount = aMarkRangeList.size();
|
||||
for ( size_t i = 0; i < nCount; ++i )
|
||||
{
|
||||
const ScRange aRange( *aMarkRangeList[i] );
|
||||
if ( pDoc->IsBlockEmpty( aRange.aStart.Tab(),
|
||||
aRange.aStart.Col(), aRange.aStart.Row(),
|
||||
aRange.aEnd.Col(), aRange.aEnd.Row() ) )
|
||||
{
|
||||
bEmpty = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( bEmpty )
|
||||
{
|
||||
ScRangeList aRangeList;
|
||||
const bool bDataFound = pViewSh->GetAutoSumArea( aRangeList );
|
||||
if ( bDataFound )
|
||||
{
|
||||
ScAddress aAddr = aRangeList.back()->aEnd;
|
||||
aAddr.IncRow();
|
||||
const bool bSubTotal( UseSubTotal( &aRangeList ) );
|
||||
pViewSh->EnterAutoSum( aRangeList, bSubTotal, aAddr );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const bool bSubTotal( UseSubTotal( &aMarkRangeList ) );
|
||||
for ( size_t i = 0; i < nCount; ++i )
|
||||
{
|
||||
const ScRange aRange( *aMarkRangeList[i] );
|
||||
const bool bSetCursor = ( i == nCount - 1 );
|
||||
const bool bContinue = ( i != 0 );
|
||||
if ( !pViewSh->AutoSum( aRange, bSubTotal, bSetCursor, bContinue ) )
|
||||
{
|
||||
pViewSh->MarkRange( aRange, false );
|
||||
pViewSh->SetCursor( aRange.aEnd.Col(), aRange.aEnd.Row() );
|
||||
const ScRangeList aRangeList;
|
||||
ScAddress aAddr = aRange.aEnd;
|
||||
aAddr.IncRow();
|
||||
const OUString aFormula = pViewSh->GetAutoSumFormula(
|
||||
aRangeList, bSubTotal, aAddr );
|
||||
SetFuncString( aFormula );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Only insert into input row
|
||||
{
|
||||
ScRangeList aRangeList;
|
||||
const bool bDataFound = pViewSh->GetAutoSumArea( aRangeList );
|
||||
const bool bSubTotal( UseSubTotal( &aRangeList ) );
|
||||
ScAddress aAddr = pViewSh->GetViewData().GetCurPos();
|
||||
const OUString aFormula = pViewSh->GetAutoSumFormula( aRangeList, bSubTotal, aAddr );
|
||||
SetFuncString( aFormula );
|
||||
|
||||
if ( bDataFound && pScMod->IsEditMode() )
|
||||
{
|
||||
ScInputHandler* pHdl = pScMod->GetInputHdl( pViewSh );
|
||||
if ( pHdl )
|
||||
{
|
||||
pHdl->InitRangeFinder( aFormula );
|
||||
|
||||
//! SetSelection at the InputHandler?
|
||||
//! Set bSelIsRef?
|
||||
const sal_Int32 nOpen = aFormula.indexOf('(');
|
||||
const sal_Int32 nLen = aFormula.getLength();
|
||||
if ( nOpen != -1 && nLen > nOpen )
|
||||
{
|
||||
sal_uInt8 nAdd(1);
|
||||
if (bSubTotal)
|
||||
nAdd = 3;
|
||||
ESelection aSel(0,nOpen+nAdd,0,nLen-1);
|
||||
EditView* pTableView = pHdl->GetTableView();
|
||||
if (pTableView)
|
||||
pTableView->SetSelection(aSel);
|
||||
EditView* pTopView = pHdl->GetTopView();
|
||||
if (pTopView)
|
||||
pTopView->SetSelection(aSel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -265,7 +265,6 @@ public:
|
||||
virtual void MouseMove( const MouseEvent& rMEvt ) override;
|
||||
|
||||
protected:
|
||||
static bool UseSubTotal( ScRangeList* pRangeList );
|
||||
bool IsPointerAtResizePos();
|
||||
|
||||
private:
|
||||
|
@@ -382,6 +382,8 @@ public:
|
||||
|
||||
bool IsActive() const { return bIsActive; }
|
||||
OUString GetFormula(ScAddress& rAddress);
|
||||
bool UseSubTotal(ScRangeList* pRangeList);
|
||||
const OUString DoAutoSum();
|
||||
|
||||
// ugly hack to call Define Names from Manage Names
|
||||
void SwitchBetweenRefDialogs(SfxModelessDialog* pDialog);
|
||||
|
@@ -44,6 +44,7 @@
|
||||
#include <vcl/waitobj.hxx>
|
||||
#include <vcl/builderfactory.hxx>
|
||||
#include <unotools/localedatawrapper.hxx>
|
||||
#include <editeng/editview.hxx>
|
||||
|
||||
#include "cellsh.hxx"
|
||||
#include "sc.hrc"
|
||||
@@ -2535,6 +2536,38 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq )
|
||||
}
|
||||
break;
|
||||
|
||||
case SID_AUTO_SUM:
|
||||
{
|
||||
const OUString aFormula = pTabViewShell->DoAutoSum();
|
||||
if (!aFormula.isEmpty())
|
||||
{
|
||||
ScInputHandler* pHdl = pScMod->GetInputHdl(pTabViewShell);
|
||||
if (pHdl)
|
||||
{
|
||||
if (!pScMod->IsEditMode())
|
||||
{
|
||||
pScMod->SetInputMode(SC_INPUT_TABLE);
|
||||
}
|
||||
|
||||
EditView *pEditView=pHdl->GetActiveView();
|
||||
if (pEditView)
|
||||
{
|
||||
ESelection aTextSel = pEditView->GetSelection();
|
||||
aTextSel.nStartPos = 0;
|
||||
aTextSel.nEndPos = EE_TEXTPOS_ALL;
|
||||
pHdl->DataChanging();
|
||||
pEditView->SetSelection(aTextSel);
|
||||
pEditView->InsertText(aFormula);
|
||||
aTextSel.nStartPos = aFormula.getLength() - 1;
|
||||
aTextSel.nEndPos = aFormula.getLength() - 1;
|
||||
pEditView->SetSelection(aTextSel);
|
||||
pHdl->DataChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
OSL_FAIL("incorrect slot in ExecuteEdit");
|
||||
break;
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#include <sfx2/childwin.hxx>
|
||||
#include <sfx2/dispatch.hxx>
|
||||
#include <editeng/editview.hxx>
|
||||
#include <inputhdl.hxx>
|
||||
|
||||
#include "tabvwsh.hxx"
|
||||
#include "sc.hrc"
|
||||
@@ -542,4 +543,156 @@ void ScTabViewShell::NotifyCursor(SfxViewShell* pOtherShell) const
|
||||
pWin->updateLibreOfficeKitCellCursor(pOtherShell);
|
||||
}
|
||||
|
||||
bool ScTabViewShell::UseSubTotal(ScRangeList* pRangeList)
|
||||
{
|
||||
bool bSubTotal = false;
|
||||
ScDocument* pDoc = GetViewData().GetDocument();
|
||||
size_t nRangeCount (pRangeList->size());
|
||||
size_t nRangeIndex (0);
|
||||
while (!bSubTotal && nRangeIndex < nRangeCount)
|
||||
{
|
||||
const ScRange* pRange = (*pRangeList)[nRangeIndex];
|
||||
if( pRange )
|
||||
{
|
||||
SCTAB nTabEnd(pRange->aEnd.Tab());
|
||||
SCTAB nTab(pRange->aStart.Tab());
|
||||
while (!bSubTotal && nTab <= nTabEnd)
|
||||
{
|
||||
SCROW nRowEnd(pRange->aEnd.Row());
|
||||
SCROW nRow(pRange->aStart.Row());
|
||||
while (!bSubTotal && nRow <= nRowEnd)
|
||||
{
|
||||
if (pDoc->RowFiltered(nRow, nTab))
|
||||
bSubTotal = true;
|
||||
else
|
||||
++nRow;
|
||||
}
|
||||
++nTab;
|
||||
}
|
||||
}
|
||||
++nRangeIndex;
|
||||
}
|
||||
|
||||
const ScDBCollection::NamedDBs& rDBs = pDoc->GetDBCollection()->getNamedDBs();
|
||||
ScDBCollection::NamedDBs::const_iterator itr = rDBs.begin(), itrEnd = rDBs.end();
|
||||
for (; !bSubTotal && itr != itrEnd; ++itr)
|
||||
{
|
||||
const ScDBData& rDB = **itr;
|
||||
if (!rDB.HasAutoFilter())
|
||||
continue;
|
||||
|
||||
nRangeIndex = 0;
|
||||
while (!bSubTotal && nRangeIndex < nRangeCount)
|
||||
{
|
||||
const ScRange* pRange = (*pRangeList)[nRangeIndex];
|
||||
if( pRange )
|
||||
{
|
||||
ScRange aDBArea;
|
||||
rDB.GetArea(aDBArea);
|
||||
if (aDBArea.Intersects(*pRange))
|
||||
bSubTotal = true;
|
||||
}
|
||||
++nRangeIndex;
|
||||
}
|
||||
}
|
||||
return bSubTotal;
|
||||
}
|
||||
|
||||
const OUString ScTabViewShell::DoAutoSum()
|
||||
{
|
||||
OUString aFormula;
|
||||
ScModule* pScMod = SC_MOD();
|
||||
const ScMarkData& rMark = GetViewData().GetMarkData();
|
||||
if ( rMark.IsMarked() || rMark.IsMultiMarked() )
|
||||
{
|
||||
ScRangeList aMarkRangeList;
|
||||
rMark.FillRangeListWithMarks( &aMarkRangeList, false );
|
||||
ScDocument* pDoc = GetViewData().GetDocument();
|
||||
|
||||
// check if one of the marked ranges is empty
|
||||
bool bEmpty = false;
|
||||
const size_t nCount = aMarkRangeList.size();
|
||||
for ( size_t i = 0; i < nCount; ++i )
|
||||
{
|
||||
const ScRange aRange( *aMarkRangeList[i] );
|
||||
if ( pDoc->IsBlockEmpty( aRange.aStart.Tab(),
|
||||
aRange.aStart.Col(), aRange.aStart.Row(),
|
||||
aRange.aEnd.Col(), aRange.aEnd.Row() ) )
|
||||
{
|
||||
bEmpty = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( bEmpty )
|
||||
{
|
||||
ScRangeList aRangeList;
|
||||
const bool bDataFound = GetAutoSumArea( aRangeList );
|
||||
if ( bDataFound )
|
||||
{
|
||||
ScAddress aAddr = aRangeList.back()->aEnd;
|
||||
aAddr.IncRow();
|
||||
const bool bSubTotal( UseSubTotal( &aRangeList ) );
|
||||
EnterAutoSum( aRangeList, bSubTotal, aAddr );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const bool bSubTotal( UseSubTotal( &aMarkRangeList ) );
|
||||
for ( size_t i = 0; i < nCount; ++i )
|
||||
{
|
||||
const ScRange aRange( *aMarkRangeList[i] );
|
||||
const bool bSetCursor = ( i == nCount - 1 );
|
||||
const bool bContinue = ( i != 0 );
|
||||
if ( !AutoSum( aRange, bSubTotal, bSetCursor, bContinue ) )
|
||||
{
|
||||
MarkRange( aRange, false );
|
||||
SetCursor( aRange.aEnd.Col(), aRange.aEnd.Row() );
|
||||
const ScRangeList aRangeList;
|
||||
ScAddress aAddr = aRange.aEnd;
|
||||
aAddr.IncRow();
|
||||
aFormula = GetAutoSumFormula( aRangeList, bSubTotal, aAddr );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Only insert into input row
|
||||
{
|
||||
ScRangeList aRangeList;
|
||||
const bool bDataFound = GetAutoSumArea( aRangeList );
|
||||
const bool bSubTotal( UseSubTotal( &aRangeList ) );
|
||||
ScAddress aAddr = GetViewData().GetCurPos();
|
||||
aFormula = GetAutoSumFormula( aRangeList, bSubTotal, aAddr );
|
||||
|
||||
if ( bDataFound && pScMod->IsEditMode() )
|
||||
{
|
||||
ScInputHandler* pHdl = pScMod->GetInputHdl( this );
|
||||
if ( pHdl )
|
||||
{
|
||||
pHdl->InitRangeFinder( aFormula );
|
||||
|
||||
//! SetSelection at the InputHandler?
|
||||
//! Set bSelIsRef?
|
||||
const sal_Int32 nOpen = aFormula.indexOf('(');
|
||||
const sal_Int32 nLen = aFormula.getLength();
|
||||
if ( nOpen != -1 && nLen > nOpen )
|
||||
{
|
||||
sal_uInt8 nAdd(1);
|
||||
if (bSubTotal)
|
||||
nAdd = 3;
|
||||
ESelection aSel(0,nOpen+nAdd,0,nLen-1);
|
||||
EditView* pTableView = pHdl->GetTableView();
|
||||
if (pTableView)
|
||||
pTableView->SetSelection(aSel);
|
||||
EditView* pTopView = pHdl->GetTopView();
|
||||
if (pTopView)
|
||||
pTopView->SetSelection(aSel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return aFormula;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
Reference in New Issue
Block a user