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:
Henry Castro 2016-10-04 11:28:27 -04:00
parent 306add13e1
commit af239f5aff
9 changed files with 236 additions and 150 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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; ]
}

View File

@ -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;
]

View File

@ -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);
}
}
}
}
}
}

View File

@ -265,7 +265,6 @@ public:
virtual void MouseMove( const MouseEvent& rMEvt ) override;
protected:
static bool UseSubTotal( ScRangeList* pRangeList );
bool IsPointerAtResizePos();
private:

View File

@ -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);

View File

@ -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;

View File

@ -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: */