1
0
Fork 0
libreoffice/sc/source/ui/view/tabvwshc.cxx
Daniel Baumann 8e63e14cf6
Adding upstream version 4:25.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 16:20:04 +02:00

781 lines
27 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <scitems.hxx>
#include <sfx2/childwin.hxx>
#include <sfx2/dispatch.hxx>
#include <svx/theme/ThemeColorChangerCommon.hxx>
#include <editeng/editview.hxx>
#include <inputhdl.hxx>
#include <tabvwsh.hxx>
#include <sc.hrc>
#include <scres.hrc>
#include <global.hxx>
#include <scmod.hxx>
#include <document.hxx>
#include <uiitems.hxx>
#include <namedlg.hxx>
#include <namedefdlg.hxx>
#include <solvrdlg.hxx>
#include <optsolver.hxx>
#include <tabopdlg.hxx>
#include <consdlg.hxx>
#include <filtdlg.hxx>
#include <dbnamdlg.hxx>
#include <areasdlg.hxx>
#include <crnrdlg.hxx>
#include <formula.hxx>
#include <highred.hxx>
#include <simpref.hxx>
#include <funcdesc.hxx>
#include <dpobject.hxx>
#include <markdata.hxx>
#include <reffact.hxx>
#include <condformatdlg.hxx>
#include <condformateasydlg.hxx>
#include <xmlsourcedlg.hxx>
#include <condformatdlgdata.hxx>
#include <formdata.hxx>
#include <inputwin.hxx>
#include <RandomNumberGeneratorDialog.hxx>
#include <SamplingDialog.hxx>
#include <DescriptiveStatisticsDialog.hxx>
#include <AnalysisOfVarianceDialog.hxx>
#include <CorrelationDialog.hxx>
#include <CovarianceDialog.hxx>
#include <ExponentialSmoothingDialog.hxx>
#include <MovingAverageDialog.hxx>
#include <RegressionDialog.hxx>
#include <TTestDialog.hxx>
#include <FTestDialog.hxx>
#include <ZTestDialog.hxx>
#include <ChiSquareTestDialog.hxx>
#include <FourierAnalysisDialog.hxx>
#include <PivotLayoutDialog.hxx>
#include <SparklineDialog.hxx>
#include <SparklineDataRangeDialog.hxx>
#include <svtools/colorcfg.hxx>
#include <comphelper/lok.hxx>
#include <o3tl/unreachable.hxx>
#include <o3tl/make_shared.hxx>
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
void ScTabViewShell::SetCurRefDlgId( sal_uInt16 nNew )
{
// CurRefDlgId is stored in ScModule to find if a ref dialog is open,
// and in the view to identify the view that has opened the dialog
nCurRefDlgId = nNew;
}
//ugly hack to call Define Name from Manage Names
void ScTabViewShell::SwitchBetweenRefDialogs(SfxModelessDialogController* pDialog)
{
ScModule* mod = ScModule::get();
sal_uInt16 nSlotId = mod->GetCurRefDlgId();
if( nSlotId == FID_ADD_NAME )
{
static_cast<ScNameDefDlg*>(pDialog)->GetNewData(maName, maScope);
static_cast<ScNameDefDlg*>(pDialog)->Close();
sal_uInt16 nId = ScNameDlgWrapper::GetChildWindowId();
SfxViewFrame& rViewFrm = GetViewFrame();
SfxChildWindow* pWnd = rViewFrm.GetChildWindow( nId );
mod->SetRefDialog( nId, pWnd == nullptr );
}
else if (nSlotId == FID_DEFINE_NAME)
{
mbInSwitch = true;
static_cast<ScNameDlg*>(pDialog)->GetRangeNames(m_RangeMap);
static_cast<ScNameDlg*>(pDialog)->Close();
sal_uInt16 nId = ScNameDefDlgWrapper::GetChildWindowId();
SfxViewFrame& rViewFrm = GetViewFrame();
SfxChildWindow* pWnd = rViewFrm.GetChildWindow( nId );
mod->SetRefDialog( nId, pWnd == nullptr );
}
}
std::shared_ptr<SfxModelessDialogController> ScTabViewShell::CreateRefDialogController(
SfxBindings* pB, SfxChildWindow* pCW,
SfxChildWinInfo* pInfo,
weld::Window* pParent, sal_uInt16 nSlotId)
{
// only open dialog when called through ScModule::SetRefDialog,
// so that it does not re appear for instance after a crash (#42341#).
if (ScModule::get()->GetCurRefDlgId() != nSlotId)
return nullptr;
if ( nCurRefDlgId != nSlotId )
{
if (!(comphelper::LibreOfficeKit::isActive() && nSlotId == SID_OPENDLG_FUNCTION))
{
// the dialog has been opened in a different view
// -> lock the dispatcher for this view (modal mode)
GetViewData().GetDispatcher().Lock( true ); // lock is reset when closing dialog
}
return nullptr;
}
std::shared_ptr<SfxModelessDialogController> xResult;
if(pCW)
pCW->SetHideNotDelete(true);
ScDocument& rDoc = GetViewData().GetDocument();
switch( nSlotId )
{
case SID_CORRELATION_DIALOG:
xResult = std::make_shared<ScCorrelationDialog>(pB, pCW, pParent, GetViewData());
break;
case SID_SAMPLING_DIALOG:
xResult = std::make_shared<ScSamplingDialog>(pB, pCW, pParent, GetViewData());
break;
case SID_DESCRIPTIVE_STATISTICS_DIALOG:
xResult = std::make_shared<ScDescriptiveStatisticsDialog>(pB, pCW, pParent, GetViewData());
break;
case SID_ANALYSIS_OF_VARIANCE_DIALOG:
xResult = std::make_shared<ScAnalysisOfVarianceDialog>(pB, pCW, pParent, GetViewData());
break;
case SID_COVARIANCE_DIALOG:
xResult = std::make_shared<ScCovarianceDialog>(pB, pCW, pParent, GetViewData());
break;
case SID_EXPONENTIAL_SMOOTHING_DIALOG:
xResult = std::make_shared<ScExponentialSmoothingDialog>(pB, pCW, pParent, GetViewData());
break;
case SID_MOVING_AVERAGE_DIALOG:
xResult = std::make_shared<ScMovingAverageDialog>(pB, pCW, pParent, GetViewData());
break;
case SID_REGRESSION_DIALOG:
xResult = std::make_shared<ScRegressionDialog>(pB, pCW, pParent, GetViewData());
break;
case SID_FTEST_DIALOG:
xResult = std::make_shared<ScFTestDialog>(pB, pCW, pParent, GetViewData());
break;
case SID_TTEST_DIALOG:
xResult = std::make_shared<ScTTestDialog>(pB, pCW, pParent, GetViewData());
break;
case SID_ZTEST_DIALOG:
xResult = std::make_shared<ScZTestDialog>(pB, pCW, pParent, GetViewData());
break;
case SID_CHI_SQUARE_TEST_DIALOG:
xResult = std::make_shared<ScChiSquareTestDialog>(pB, pCW, pParent, GetViewData());
break;
case SID_FOURIER_ANALYSIS_DIALOG:
xResult = std::make_shared<ScFourierAnalysisDialog>(pB, pCW, pParent, GetViewData());
break;
case WID_SIMPLE_REF:
{
// dialog checks, what is in the cell
ScViewData& rViewData = GetViewData();
rViewData.SetRefTabNo( rViewData.GetTabNo() );
xResult = std::make_shared<ScSimpleRefDlg>(pB, pCW, pParent);
break;
}
case FID_DEFINE_NAME:
{
if (!mbInSwitch)
{
xResult = std::make_shared<ScNameDlg>(pB, pCW, pParent, GetViewData(),
ScAddress( GetViewData().GetCurX(),
GetViewData().GetCurY(),
GetViewData().GetTabNo() ) );
}
else
{
xResult = std::make_shared<ScNameDlg>( pB, pCW, pParent, GetViewData(),
ScAddress( GetViewData().GetCurX(),
GetViewData().GetCurY(),
GetViewData().GetTabNo() ), &m_RangeMap);
static_cast<ScNameDlg*>(xResult.get())->SetEntry(maName, maScope);
mbInSwitch = false;
}
break;
}
case FID_ADD_NAME:
{
if (!mbInSwitch)
{
std::map<OUString, ScRangeName*> aRangeMap;
rDoc.GetRangeNameMap(aRangeMap);
xResult = std::make_shared<ScNameDefDlg>(pB, pCW, pParent, GetViewData(), std::move(aRangeMap),
ScAddress(GetViewData().GetCurX(),
GetViewData().GetCurY(),
GetViewData().GetTabNo()), true);
}
else
{
std::map<OUString, ScRangeName*> aRangeMap;
for (auto& itr : m_RangeMap)
{
aRangeMap.insert(std::pair<OUString, ScRangeName*>(itr.first, &itr.second));
}
xResult = std::make_shared<ScNameDefDlg>(pB, pCW, pParent, GetViewData(), std::move(aRangeMap),
ScAddress(GetViewData().GetCurX(),
GetViewData().GetCurY(),
GetViewData().GetTabNo()), false);
}
break;
}
case SID_RANDOM_NUMBER_GENERATOR_DIALOG:
xResult = std::make_shared<ScRandomNumberGeneratorDialog>(pB, pCW, pParent, GetViewData());
break;
case SID_SPARKLINE_DIALOG:
{
xResult = std::make_shared<sc::SparklineDialog>(pB, pCW, pParent, GetViewData());
break;
}
case SID_SPARKLINE_DATA_RANGE_DIALOG:
{
xResult = std::make_shared<sc::SparklineDataRangeDialog>(pB, pCW, pParent, GetViewData());
break;
}
case SID_DEFINE_DBNAME:
{
// when called for an existing range, then mark
GetDBData( true, SC_DB_OLD );
const ScMarkData& rMark = GetViewData().GetMarkData();
if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
MarkDataArea( false );
xResult = std::make_shared<ScDbNameDlg>(pB, pCW, pParent, GetViewData());
break;
}
case SID_OPENDLG_EDIT_PRINTAREA:
xResult = std::make_shared<ScPrintAreasDlg>(pB, pCW, pParent);
break;
case SID_DEFINE_COLROWNAMERANGES:
xResult = std::make_shared<ScColRowNameRangesDlg>(pB, pCW, pParent, GetViewData());
break;
case SID_OPENDLG_SOLVE:
{
ScViewData& rViewData = GetViewData();
ScAddress aCurPos( rViewData.GetCurX(),
rViewData.GetCurY(),
rViewData.GetTabNo());
xResult = std::make_shared<ScSolverDlg>(pB, pCW, pParent, &rViewData.GetDocument(), aCurPos);
break;
}
case SID_OPENDLG_TABOP:
{
ScViewData& rViewData = GetViewData();
ScRefAddress aCurPos ( rViewData.GetCurX(),
rViewData.GetCurY(),
rViewData.GetTabNo());
xResult = std::make_shared<ScTabOpDlg>(pB, pCW, pParent, &rViewData.GetDocument(), aCurPos);
break;
}
case SID_OPENDLG_CONSOLIDATE:
{
SfxItemSetFixed<SCITEM_CONSOLIDATEDATA,
SCITEM_CONSOLIDATEDATA> aArgSet( GetPool() );
const ScConsolidateParam* pDlgData =
rDoc.GetConsolidateDlgData();
if ( !pDlgData )
{
ScConsolidateParam aConsParam;
SCCOL nStartCol, nEndCol;
SCROW nStartRow, nEndRow;
SCTAB nStartTab, nEndTab;
GetViewData().GetSimpleArea( nStartCol, nStartRow, nStartTab,
nEndCol, nEndRow, nEndTab );
PutInOrder( nStartCol, nEndCol );
PutInOrder( nStartRow, nEndRow );
PutInOrder( nStartTab, nEndTab );
aConsParam.nCol = nStartCol;
aConsParam.nRow = nStartRow;
aConsParam.nTab = nStartTab;
aArgSet.Put( ScConsolidateItem( SCITEM_CONSOLIDATEDATA,
&aConsParam ) );
}
else
{
aArgSet.Put( ScConsolidateItem( SCITEM_CONSOLIDATEDATA, pDlgData ) );
}
xResult = std::make_shared<ScConsolidateDlg>(pB, pCW, pParent, aArgSet);
break;
}
case SID_EASY_CONDITIONAL_FORMAT_DIALOG:
{
xResult = std::make_shared<sc::ConditionalFormatEasyDialog>(pB, pCW, pParent, &GetViewData());
break;
}
case SID_FILTER:
{
ScQueryParam aQueryParam;
SfxItemSetFixed<SCITEM_QUERYDATA, SCITEM_QUERYDATA> aArgSet( GetPool() );
ScDBData* pDBData = GetDBData(false, SC_DB_MAKE, ScGetDBSelection::RowDown);
pDBData->ExtendDataArea(rDoc);
pDBData->ExtendBackColorArea(rDoc);
pDBData->GetQueryParam( aQueryParam );
ScRange aArea;
pDBData->GetArea(aArea);
MarkRange(aArea, false);
aArgSet.Put( ScQueryItem( SCITEM_QUERYDATA,
&GetViewData(),
&aQueryParam ) );
// mark current sheet (due to RefInput in dialog)
GetViewData().SetRefTabNo( GetViewData().GetTabNo() );
xResult = std::make_shared<ScFilterDlg>(pB, pCW, pParent, aArgSet);
break;
}
case SID_SPECIAL_FILTER:
{
ScQueryParam aQueryParam;
SfxItemSetFixed<SCITEM_QUERYDATA,
SCITEM_QUERYDATA> aArgSet( GetPool() );
ScDBData* pDBData = GetDBData(false, SC_DB_MAKE, ScGetDBSelection::RowDown);
pDBData->ExtendDataArea(rDoc);
pDBData->GetQueryParam( aQueryParam );
ScRange aArea;
pDBData->GetArea(aArea);
MarkRange(aArea, false);
ScQueryItem aItem( SCITEM_QUERYDATA, &GetViewData(), &aQueryParam );
ScRange aAdvSource;
if (pDBData->GetAdvancedQuerySource(aAdvSource))
aItem.SetAdvancedQuerySource( &aAdvSource );
aArgSet.Put( aItem );
// mark current sheet (due to RefInput in dialog)
GetViewData().SetRefTabNo( GetViewData().GetTabNo() );
xResult = std::make_shared<ScSpecialFilterDlg>(pB, pCW, pParent, aArgSet);
break;
}
case SID_OPENDLG_OPTSOLVER:
{
ScViewData& rViewData = GetViewData();
ScAddress aCurPos( rViewData.GetCurX(), rViewData.GetCurY(), rViewData.GetTabNo());
xResult = std::make_shared<ScOptSolverDlg>(pB, pCW, pParent, rViewData.GetDocShell(), aCurPos);
break;
}
case FID_CHG_SHOW:
{
// dialog checks, what is in the cell
xResult = std::make_shared<ScHighlightChgDlg>(pB, pCW, pParent, GetViewData());
break;
}
case SID_MANAGE_XML_SOURCE:
{
xResult = std::make_shared<ScXMLSourceDlg>(pB, pCW, pParent, &rDoc);
break;
}
case SID_OPENDLG_PIVOTTABLE:
{
// all settings must be in pDialogDPObject
if( pDialogDPObject )
{
// Check for an existing datapilot output.
ScViewData& rViewData = GetViewData();
rViewData.SetRefTabNo( rViewData.GetTabNo() );
ScDPObject* pObj = rDoc.GetDPAtCursor(rViewData.GetCurX(), rViewData.GetCurY(), rViewData.GetTabNo());
xResult = std::make_shared<ScPivotLayoutDialog>(pB, pCW, pParent, &rViewData, pDialogDPObject.get(), pObj == nullptr);
}
break;
}
case SID_OPENDLG_FUNCTION:
{
if (!isLOKMobilePhone())
{
// dialog checks, what is in the cell
xResult = o3tl::make_shared<ScFormulaDlg>(pB, pCW, pParent, GetViewData(), ScGlobal::GetStarCalcFunctionMgr());
}
break;
}
case WID_CONDFRMT_REF:
{
// Get the DialogData stored by Conditional Format Manager Dialog.
const std::shared_ptr<ScCondFormatDlgData>& rDlgData(getScCondFormatDlgData());
if (rDlgData)
{
ScViewData& rViewData = GetViewData();
rViewData.SetRefTabNo( rViewData.GetTabNo() );
xResult = std::make_shared<ScCondFormatDlg>(pB, pCW, pParent, &rViewData, rDlgData);
// Remove the DialogData stored by Conditional Format Manager Dialog.
setScCondFormatDlgData(nullptr);
}
break;
}
}
if (xResult)
{
pInfo->nFlags = SfxChildWindowFlags::NEVERHIDE;
xResult->Initialize(pInfo);
}
return xResult;
}
int ScTabViewShell::getPart() const
{
return GetViewData().GetTabNo();
}
void ScTabViewShell::afterCallbackRegistered()
{
// common tasks
SfxViewShell::afterCallbackRegistered();
UpdateInputHandler(true, false);
ScInputHandler* pHdl = mpInputHandler ? mpInputHandler.get() : ScModule::get()->GetInputHdl();
if (pHdl)
{
ScInputWindow* pInputWindow = pHdl->GetInputWindow();
if (pInputWindow)
{
pInputWindow->NotifyLOKClient();
}
}
SfxObjectShell* pDocShell = GetObjectShell();
if (pDocShell)
{
std::shared_ptr<model::ColorSet> pThemeColors = pDocShell->GetThemeColors();
std::set<Color> aDocumentColors = pDocShell->GetDocColors();
svx::theme::notifyLOK(pThemeColors, aDocumentColors);
}
}
void ScTabViewShell::NotifyCursor(SfxViewShell* pOtherShell) const
{
ScDrawView* pDrView = const_cast<ScTabViewShell*>(this)->GetScDrawView();
if (pDrView)
{
if (pDrView->GetTextEditObject())
{
// Blinking cursor.
EditView& rEditView = pDrView->GetTextEditOutlinerView()->GetEditView();
rEditView.RegisterOtherShell(pOtherShell);
rEditView.ShowCursor();
rEditView.RegisterOtherShell(nullptr);
// Text selection, if any.
rEditView.DrawSelectionXOR(pOtherShell);
}
else
{
// Graphic selection.
pDrView->AdjustMarkHdl(pOtherShell);
}
}
const ScGridWindow* pWin = GetViewData().GetActiveWin();
if (pWin)
pWin->updateKitCellCursor(pOtherShell);
}
::Color ScTabViewShell::GetColorConfigColor(svtools::ColorConfigEntry nColorType) const
{
switch (nColorType)
{
case svtools::ColorConfigEntry::DOCCOLOR:
{
const ScViewRenderingOptions& rViewRenderingOptions = GetViewRenderingData();
return rViewRenderingOptions.GetDocColor();
}
// Should never be called for an unimplemented color type
default:
{
O3TL_UNREACHABLE;
}
}
}
css::uno::Reference<css::datatransfer::XTransferable2> ScTabViewShell::GetClipData(vcl::Window* pWin)
{
SfxViewFrame* pViewFrame = nullptr;
css::uno::Reference<css::datatransfer::XTransferable2> xTransferable;
css::uno::Reference<css::datatransfer::clipboard::XClipboard> xClipboard;
if (pWin)
xClipboard = pWin->GetClipboard();
else if ((pViewFrame = SfxViewFrame::GetFirst(nullptr, false)))
xClipboard = pViewFrame->GetWindow().GetClipboard();
xTransferable.set(xClipboard.is() ? xClipboard->getContents() : nullptr, css::uno::UNO_QUERY);
return xTransferable;
}
void ScTabViewShell::notifyAllViewsHeaderInvalidation(const SfxViewShell* pForViewShell, HeaderType eHeaderType, SCTAB nCurrentTabIndex)
{
if (!comphelper::LibreOfficeKit::isActive())
return;
OString aPayload;
switch (eHeaderType)
{
case COLUMN_HEADER:
aPayload = "column"_ostr;
break;
case ROW_HEADER:
aPayload = "row"_ostr;
break;
case BOTH_HEADERS:
default:
aPayload = "all"_ostr;
break;
}
SfxViewShell* pViewShell = SfxViewShell::GetFirst();
while (pViewShell)
{
ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell);
if (pTabViewShell && pViewShell->GetDocId() == pForViewShell->GetDocId()
&& (nCurrentTabIndex == -1 || pTabViewShell->getPart() == nCurrentTabIndex))
{
pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_HEADER, aPayload);
}
pViewShell = SfxViewShell::GetNext(*pViewShell);
}
}
bool ScTabViewShell::isAnyEditViewInRange(const SfxViewShell* pForViewShell, bool bColumns, SCCOLROW nStart, SCCOLROW nEnd)
{
if (comphelper::LibreOfficeKit::isActive())
{
SfxViewShell* pViewShell = SfxViewShell::GetFirst();
while (pViewShell)
{
ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell);
if (pTabViewShell && pTabViewShell->GetDocId() == pForViewShell->GetDocId())
{
ScInputHandler* pInputHandler = pTabViewShell->GetInputHandler();
if (pInputHandler && pInputHandler->GetActiveView())
{
const ScViewData& rViewData = pTabViewShell->GetViewData();
SCCOLROW nPos = bColumns ? rViewData.GetCurX() : rViewData.GetCurY();
if (nStart <= nPos && nPos <= nEnd)
return true;
}
}
pViewShell = SfxViewShell::GetNext(*pViewShell);
}
}
return false;
}
void ScTabViewShell::notifyAllViewsSheetGeomInvalidation(const SfxViewShell* pForViewShell, bool bColumns,
bool bRows, bool bSizes, bool bHidden, bool bFiltered,
bool bGroups, SCTAB nCurrentTabIndex)
{
if (!comphelper::LibreOfficeKit::isActive() ||
!comphelper::LibreOfficeKit::isCompatFlagSet(
comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs))
return;
if (!bColumns && !bRows)
return;
bool bAllTypes = bSizes && bHidden && bFiltered && bGroups;
bool bAllDims = bColumns && bRows;
OString aPayload = bAllDims ? "all" : bColumns ? "columns" : "rows";
if (!bAllTypes)
{
if (bSizes)
aPayload += " sizes";
if (bHidden)
aPayload += " hidden";
if (bFiltered)
aPayload += " filtered";
if (bGroups)
aPayload += " groups";
}
SfxViewShell* pViewShell = SfxViewShell::GetFirst();
while (pViewShell)
{
ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell);
if (pTabViewShell && pViewShell->GetDocId() == pForViewShell->GetDocId() &&
(nCurrentTabIndex == -1 || pTabViewShell->getPart() == nCurrentTabIndex))
{
pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_SHEET_GEOMETRY, aPayload);
}
pViewShell = SfxViewShell::GetNext(*pViewShell);
}
}
bool ScTabViewShell::UseSubTotal(ScRangeList* pRangeList)
{
bool bSubTotal = false;
ScDocument& rDoc = GetViewData().GetDocument();
size_t nRangeCount (pRangeList->size());
size_t nRangeIndex (0);
while (!bSubTotal && nRangeIndex < nRangeCount)
{
const ScRange& rRange = (*pRangeList)[nRangeIndex];
SCTAB nTabEnd(rRange.aEnd.Tab());
SCTAB nTab(rRange.aStart.Tab());
while (!bSubTotal && nTab <= nTabEnd)
{
SCROW nRowEnd(rRange.aEnd.Row());
SCROW nRow(rRange.aStart.Row());
while (!bSubTotal && nRow <= nRowEnd)
{
if (rDoc.RowFiltered(nRow, nTab))
bSubTotal = true;
else
++nRow;
}
++nTab;
}
++nRangeIndex;
}
if (!bSubTotal)
{
const ScDBCollection::NamedDBs& rDBs = rDoc.GetDBCollection()->getNamedDBs();
for (const auto& rxDB : rDBs)
{
const ScDBData& rDB = *rxDB;
if (!rDB.HasAutoFilter())
continue;
nRangeIndex = 0;
while (!bSubTotal && nRangeIndex < nRangeCount)
{
const ScRange & rRange = (*pRangeList)[nRangeIndex];
ScRange aDBArea;
rDB.GetArea(aDBArea);
if (aDBArea.Intersects(rRange))
bSubTotal = true;
++nRangeIndex;
}
if (bSubTotal)
break;
}
}
return bSubTotal;
}
OUString ScTabViewShell::DoAutoSum(bool& rRangeFinder, bool& rSubTotal, const OpCode eCode)
{
OUString aFormula;
const ScMarkData& rMark = GetViewData().GetMarkData();
if ( rMark.IsMarked() || rMark.IsMultiMarked() )
{
ScRangeList aMarkRangeList;
rRangeFinder = rSubTotal = false;
rMark.FillRangeListWithMarks( &aMarkRangeList, false );
ScDocument& rDoc = 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 & rRange( aMarkRangeList[i] );
if ( rDoc.IsBlockEmpty( rRange.aStart.Col(), rRange.aStart.Row(),
rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aStart.Tab() ) )
{
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, eCode );
}
}
else
{
const bool bSubTotal( UseSubTotal( &aMarkRangeList ) );
for ( size_t i = 0; i < nCount; ++i )
{
const ScRange & rRange = aMarkRangeList[i];
const bool bSetCursor = ( i == nCount - 1 );
const bool bContinue = ( i != 0 );
if ( !AutoSum( rRange, bSubTotal, bSetCursor, bContinue, eCode ) )
{
MarkRange( rRange, false );
SetCursor( rRange.aEnd.Col(), rRange.aEnd.Row() );
const ScRangeList aRangeList;
ScAddress aAddr = rRange.aEnd;
aAddr.IncRow();
aFormula = GetAutoSumFormula( aRangeList, bSubTotal, aAddr , eCode);
break;
}
}
}
}
else // Only insert into input row
{
ScRangeList aRangeList;
rRangeFinder = GetAutoSumArea( aRangeList );
rSubTotal = UseSubTotal( &aRangeList );
ScAddress aAddr = GetViewData().GetCurPos();
aFormula = GetAutoSumFormula( aRangeList, rSubTotal, aAddr , eCode);
}
return aFormula;
}
void ScTabViewShell::InitFormEditData()
{
mpFormEditData.reset(new ScFormEditData);
}
void ScTabViewShell::ClearFormEditData()
{
mpFormEditData.reset();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */