/* -*- 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 <config_features.h>
#include <basic/sberrors.hxx>
#include <scitems.hxx>
#include <comphelper/lok.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/app.hxx>
#include <sfx2/request.hxx>
#include <sfx2/sfxdlg.hxx>
#include <svl/aeitem.hxx>
#include <basic/sbxcore.hxx>
#include <svl/whiter.hxx>
#include <svl/zforlist.hxx>
#include <svl/stritem.hxx>
#include <svl/visitem.hxx>
#include <svtools/miscopt.hxx>
#include <unotools/moduleoptions.hxx>
#include <com/sun/star/frame/FrameSearchFlag.hpp>
#include <com/sun/star/sdbc/XResultSet.hpp>
#include <com/sun/star/sheet/TableValidationVisibility.hpp>
#include <cellsh.hxx>
#include <tabvwsh.hxx>
#include <sc.hrc>
#include <globstr.hrc>
#include <scresid.hxx>
#include <global.hxx>
#include <globalnames.hxx>
#include <scmod.hxx>
#include <docsh.hxx>
#include <document.hxx>
#include <uiitems.hxx>
#include <dbfunc.hxx>
#include <dbdocfun.hxx>
#include <filtdlg.hxx>
#include <dbnamdlg.hxx>
#include <reffact.hxx>
#include <validat.hxx>
#include <validate.hxx>
#include <datamapper.hxx>
#include <scui_def.hxx>
#include <scabstdlg.hxx>
#include <impex.hxx>
#include <asciiopt.hxx>
#include <datastream.hxx>
#include <datastreamdlg.hxx>
#include <dataproviderdlg.hxx>
#include <queryentry.hxx>
#include <markdata.hxx>
#include <documentlinkmgr.hxx>
#include <memory>
using namespace com::sun::star;
static bool lcl_GetTextToColumnsRange( const ScViewData* pData, ScRange& rRange, bool bDoEmptyCheckOnly )
{
OSL_ENSURE( pData, "lcl_GetTextToColumnsRange: pData is null!" );
bool bRet = false;
const ScMarkData& rMark = pData->GetMarkData();
if ( rMark.IsMarked() )
{
if ( !rMark.IsMultiMarked() )
{
rMark.GetMarkArea( rRange );
if ( rRange.aStart.Col() == rRange.aEnd.Col() )
{
bRet = true;
}
}
}
else
{
const SCCOL nCol = pData->GetCurX();
const SCROW nRow = pData->GetCurY();
const SCTAB nTab = pData->GetTabNo();
rRange = ScRange( nCol, nRow, nTab, nCol, nRow, nTab );
bRet = true;
}
const ScDocument* pDoc = pData->GetDocument();
OSL_ENSURE( pDoc, "lcl_GetTextToColumnsRange: pDoc is null!" );
if ( bDoEmptyCheckOnly )
{
if ( bRet && pDoc->IsBlockEmpty( rRange.aStart.Tab(), rRange.aStart.Col(),
rRange.aStart.Row(), rRange.aEnd.Col(),
rRange.aEnd.Row() ) )
{
bRet = false;
}
}
else if ( bRet )
{
rRange.PutInOrder();
SCCOL nStartCol = rRange.aStart.Col(), nEndCol = rRange.aEnd.Col();
SCROW nStartRow = rRange.aStart.Row(), nEndRow = rRange.aEnd.Row();
bool bShrunk = false;
pDoc->ShrinkToUsedDataArea( bShrunk, rRange.aStart.Tab(), nStartCol, nStartRow,
nEndCol, nEndRow, false, false, true );
if ( bShrunk )
{
rRange.aStart.SetRow( nStartRow );
rRange.aEnd.SetRow( nEndRow );
}
}
return bRet;
}
static bool lcl_GetSortParam( const ScViewData* pData, const ScSortParam& rSortParam )
{
ScTabViewShell* pTabViewShell = pData->GetViewShell();
ScDBData* pDBData = pTabViewShell->GetDBData();
ScDocument* pDoc = pData->GetDocument();
SCTAB nTab = pData->GetTabNo();
ScDirection eFillDir = DIR_TOP;
bool bSort = true;
ScRange aExternalRange;
if( rSortParam.nCol1 != rSortParam.nCol2 )
eFillDir = DIR_LEFT;
if( rSortParam.nRow1 != rSortParam.nRow2 )
eFillDir = DIR_TOP;
if( rSortParam.nRow2 == MAXROW )
{
// Assume that user selected entire column(s), but cater for the
// possibility that the start row is not the first row.
SCSIZE nCount = pDoc->GetEmptyLinesInBlock( rSortParam.nCol1, rSortParam.nRow1, nTab,
rSortParam.nCol2, rSortParam.nRow2, nTab, eFillDir );
aExternalRange = ScRange( rSortParam.nCol1,
::std::min( rSortParam.nRow1 + sal::static_int_cast<SCROW>( nCount ), MAXROW), nTab,
rSortParam.nCol2, rSortParam.nRow2, nTab);
aExternalRange.PutInOrder();
}
else if (rSortParam.nCol1 != rSortParam.nCol2 || rSortParam.nRow1 != rSortParam.nRow2)
{
// Preserve a preselected area.
aExternalRange = ScRange( rSortParam.nCol1, rSortParam.nRow1, nTab, rSortParam.nCol2, rSortParam.nRow2, nTab);
aExternalRange.PutInOrder();
}
else
aExternalRange = ScRange( pData->GetCurX(), pData->GetCurY(), nTab );
SCROW nStartRow = aExternalRange.aStart.Row();
SCCOL nStartCol = aExternalRange.aStart.Col();
SCROW nEndRow = aExternalRange.aEnd.Row();
SCCOL nEndCol = aExternalRange.aEnd.Col();
pDoc->GetDataArea( aExternalRange.aStart.Tab(), nStartCol, nStartRow, nEndCol, nEndRow, false, false );
aExternalRange.aStart.SetRow( nStartRow );
aExternalRange.aStart.SetCol( nStartCol );
aExternalRange.aEnd.SetRow( nEndRow );
aExternalRange.aEnd.SetCol( nEndCol );
// with LibreOfficeKit, don't try to interact with the user
if (!comphelper::LibreOfficeKit::isActive() &&
((rSortParam.nCol1 == rSortParam.nCol2 && aExternalRange.aStart.Col() != aExternalRange.aEnd.Col()) ||
(rSortParam.nRow1 == rSortParam.nRow2 && aExternalRange.aStart.Row() != aExternalRange.aEnd.Row())))
{
pTabViewShell->AddHighlightRange( aExternalRange,COL_LIGHTBLUE );
OUString aExtendStr( aExternalRange.Format(ScRefFlags::VALID, pDoc));
ScRange aCurrentRange( rSortParam.nCol1, rSortParam.nRow1, nTab, rSortParam.nCol2, rSortParam.nRow2, nTab );
OUString aCurrentStr( aCurrentRange.Format(ScRefFlags::VALID, pDoc));
ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
ScopedVclPtr<AbstractScSortWarningDlg> pWarningDlg(pFact->CreateScSortWarningDlg(pTabViewShell->GetFrameWeld(), aExtendStr, aCurrentStr));
short bResult = pWarningDlg->Execute();
if( bResult == BTN_EXTEND_RANGE || bResult == BTN_CURRENT_SELECTION )
{
if( bResult == BTN_EXTEND_RANGE )
{
pTabViewShell->MarkRange( aExternalRange, false );
pDBData->SetArea( nTab, aExternalRange.aStart.Col(), aExternalRange.aStart.Row(), aExternalRange.aEnd.Col(), aExternalRange.aEnd.Row() );
}
}
else
{
bSort = false;
pData->GetDocShell()->CancelAutoDBRange();
}
pTabViewShell->ClearHighlightRanges();
}
return bSort;
}
void ScCellShell::ExecuteDB( SfxRequest& rReq )
{
ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell();
sal_uInt16 nSlotId = rReq.GetSlot();
const SfxItemSet* pReqArgs = rReq.GetArgs();
ScModule* pScMod = SC_MOD();
pTabViewShell->HideListBox(); // Autofilter-DropDown-Listbox
if ( GetViewData()->HasEditView( GetViewData()->GetActivePart() ) )
{
pScMod->InputEnterHandler();
pTabViewShell->UpdateInputHandler();
}
switch ( nSlotId )
{
case SID_VIEW_DATA_SOURCE_BROWSER:
{
// check if database beamer is open
SfxViewFrame* pViewFrame = pTabViewShell->GetViewFrame();
bool bWasOpen = false;
{
uno::Reference<frame::XFrame> xFrame = pViewFrame->GetFrame().GetFrameInterface();
uno::Reference<frame::XFrame> xBeamerFrame = xFrame->findFrame(
"_beamer",
frame::FrameSearchFlag::CHILDREN);
if ( xBeamerFrame.is() )
bWasOpen = true;
}
if ( bWasOpen )
{
// close database beamer: just forward to SfxViewFrame
pViewFrame->ExecuteSlot( rReq );
}
else
{
// show database beamer: SfxViewFrame call must be synchronous
pViewFrame->ExecuteSlot( rReq, false ); // false = synchronous
// select current database in database beamer
ScImportParam aImportParam;
ScDBData* pDBData = pTabViewShell->GetDBData(true,SC_DB_OLD); // don't create if none found
if (pDBData)
pDBData->GetImportParam( aImportParam );
ScDBDocFunc::ShowInBeamer( aImportParam, pTabViewShell->GetViewFrame() );
}
rReq.Done(); // needed because it's a toggle slot
}
break;
case SID_REIMPORT_DATA:
{
bool bOk = false;
ScDBData* pDBData = pTabViewShell->GetDBData(true,SC_DB_OLD);
if (pDBData)
{
ScImportParam aImportParam;
pDBData->GetImportParam( aImportParam );
if (aImportParam.bImport && !pDBData->HasImportSelection())
{
pTabViewShell->ImportData( aImportParam );
pDBData->SetImportParam( aImportParam ); //! Undo ??
bOk = true;
}
}
if (!bOk && ! rReq.IsAPI() )
pTabViewShell->ErrorMessage(STR_REIMPORT_EMPTY);
if( bOk )
rReq.Done();
}
break;
case SID_REFRESH_DBAREA:
{
ScDBData* pDBData = pTabViewShell->GetDBData(true,SC_DB_OLD);
if (pDBData)
{
// repeat import like SID_REIMPORT_DATA
bool bContinue = true;
ScImportParam aImportParam;
pDBData->GetImportParam( aImportParam );
if (aImportParam.bImport && !pDBData->HasImportSelection())
{
bContinue = pTabViewShell->ImportData( aImportParam );
pDBData->SetImportParam( aImportParam ); //! Undo ??
// mark (size may have been changed)
ScRange aNewRange;
pDBData->GetArea(aNewRange);
pTabViewShell->MarkRange(aNewRange);
}
if ( bContinue ) // fail at import -> break
{
// internal operations, when any stored
if ( pDBData->HasQueryParam() || pDBData->HasSortParam() ||
pDBData->HasSubTotalParam() )
pTabViewShell->RepeatDB();
// pivot tables that have the range as data source
ScRange aRange;
pDBData->GetArea(aRange);
GetViewData()->GetDocShell()->RefreshPivotTables(aRange);
}
}
rReq.Done();
}
break;
case SID_SBA_BRW_INSERT:
{
OSL_FAIL( "Deprecated Slot" );
}
break;
case SID_DATA_FORM:
{
ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
ScopedVclPtr<AbstractScDataFormDlg> pDlg(pFact->CreateScDataFormDlg(
pTabViewShell->GetDialogParent(), pTabViewShell));
pDlg->Execute();
rReq.Done();
}
break;
case SID_SUBTOTALS:
ExecuteSubtotals(rReq);
break;
case SID_SORT_DESCENDING:
case SID_SORT_ASCENDING:
{
//#i60401 ux-ctest: Calc does not support all users' strategies regarding sorting data
//the patch comes from maoyg
ScSortParam aSortParam;
ScDBData* pDBData = pTabViewShell->GetDBData();
ScViewData* pData = GetViewData();
pDBData->GetSortParam( aSortParam );
if( lcl_GetSortParam( pData, aSortParam ) )
{
SCCOL nCol = GetViewData()->GetCurX();
SCCOL nTab = GetViewData()->GetTabNo();
ScDocument* pDoc = GetViewData()->GetDocument();
pDBData->GetSortParam( aSortParam );
bool bHasHeader = pDoc->HasColHeader( aSortParam.nCol1, aSortParam.nRow1, aSortParam.nCol2, aSortParam.nRow2, nTab );
if( nCol < aSortParam.nCol1 )
nCol = aSortParam.nCol1;
else if( nCol > aSortParam.nCol2 )
nCol = aSortParam.nCol2;
aSortParam.bHasHeader = bHasHeader;
aSortParam.bByRow = true;
aSortParam.bCaseSens = false;
aSortParam.bNaturalSort = false;
aSortParam.bIncludeComments = false;
aSortParam.bIncludeGraphicObjects = true;
aSortParam.bIncludePattern = true;
aSortParam.bInplace = true;
aSortParam.maKeyState[0].bDoSort = true;
aSortParam.maKeyState[0].nField = nCol;
aSortParam.maKeyState[0].bAscending = ( nSlotId == SID_SORT_ASCENDING );
for ( sal_uInt16 i=1; i<aSortParam.GetSortKeyCount(); i++ )
aSortParam.maKeyState[i].bDoSort = false;
pTabViewShell->UISort( aSortParam ); // subtotal when needed new
rReq.Done();
}
}
break;
case SID_SORT:
{
const SfxItemSet* pArgs = rReq.GetArgs();
//#i60401 ux-ctest: Calc does not support all users' strategies regarding sorting data
//the patch comes from maoyg
if ( pArgs ) // Basic
{
ScSortParam aSortParam;
ScDBData* pDBData = pTabViewShell->GetDBData();
ScViewData* pData = GetViewData();
pDBData->GetSortParam( aSortParam );
if( lcl_GetSortParam( pData, aSortParam ) )
{
ScDocument* pDoc = GetViewData()->GetDocument();
pDBData->GetSortParam( aSortParam );
bool bHasHeader = pDoc->HasColHeader( aSortParam.nCol1, aSortParam.nRow1, aSortParam.nCol2, aSortParam.nRow2, pData->GetTabNo() );
if( bHasHeader )
aSortParam.bHasHeader = bHasHeader;
aSortParam.bInplace = true; // from Basic always
const SfxPoolItem* pItem;
if ( pArgs->GetItemState( SID_SORT_BYROW, true, &pItem ) == SfxItemState::SET )
aSortParam.bByRow = static_cast<const SfxBoolItem*>(pItem)->GetValue();
if ( pArgs->GetItemState( SID_SORT_HASHEADER, true, &pItem ) == SfxItemState::SET )
aSortParam.bHasHeader = static_cast<const SfxBoolItem*>(pItem)->GetValue();
if ( pArgs->GetItemState( SID_SORT_CASESENS, true, &pItem ) == SfxItemState::SET )
aSortParam.bCaseSens = static_cast<const SfxBoolItem*>(pItem)->GetValue();
if ( pArgs->GetItemState( SID_SORT_NATURALSORT, true, &pItem ) == SfxItemState::SET )
aSortParam.bNaturalSort = static_cast<const SfxBoolItem*>(pItem)->GetValue();
if ( pArgs->GetItemState( SID_SORT_INCCOMMENTS, true, &pItem ) == SfxItemState::SET )
aSortParam.bIncludeComments = static_cast<const SfxBoolItem*>(pItem)->GetValue();
if ( pArgs->GetItemState( SID_SORT_INCIMAGES, true, &pItem ) == SfxItemState::SET )
aSortParam.bIncludeGraphicObjects = static_cast<const SfxBoolItem*>(pItem)->GetValue();
if ( pArgs->GetItemState( SID_SORT_ATTRIBS, true, &pItem ) == SfxItemState::SET )
aSortParam.bIncludePattern = static_cast<const SfxBoolItem*>(pItem)->GetValue();
if ( pArgs->GetItemState( SID_SORT_USERDEF, true, &pItem ) == SfxItemState::SET )
{
sal_uInt16 nUserIndex = static_cast<const SfxUInt16Item*>(pItem)->GetValue();
aSortParam.bUserDef = ( nUserIndex != 0 );
if ( nUserIndex )
aSortParam.nUserIndex = nUserIndex - 1; // Basic: 1-based
}
SCCOLROW nField0 = 0;
if ( pArgs->GetItemState( FN_PARAM_1, true, &pItem ) == SfxItemState::SET )
nField0 = static_cast<const SfxInt32Item*>(pItem)->GetValue();
aSortParam.maKeyState[0].bDoSort = ( nField0 != 0 );
aSortParam.maKeyState[0].nField = nField0 > 0 ? (nField0-1) : 0;
if ( pArgs->GetItemState( FN_PARAM_2, true, &pItem ) == SfxItemState::SET )
aSortParam.maKeyState[0].bAscending = static_cast<const SfxBoolItem*>(pItem)->GetValue();
SCCOLROW nField1 = 0;
if ( pArgs->GetItemState( FN_PARAM_3, true, &pItem ) == SfxItemState::SET )
nField1 = static_cast<const SfxInt32Item*>(pItem)->GetValue();
aSortParam.maKeyState[1].bDoSort = ( nField1 != 0 );
aSortParam.maKeyState[1].nField = nField1 > 0 ? (nField1-1) : 0;
if ( pArgs->GetItemState( FN_PARAM_4, true, &pItem ) == SfxItemState::SET )
aSortParam.maKeyState[1].bAscending = static_cast<const SfxBoolItem*>(pItem)->GetValue();
SCCOLROW nField2 = 0;
if ( pArgs->GetItemState( FN_PARAM_5, true, &pItem ) == SfxItemState::SET )
nField2 = static_cast<const SfxInt32Item*>(pItem)->GetValue();
aSortParam.maKeyState[2].bDoSort = ( nField2 != 0 );
aSortParam.maKeyState[2].nField = nField2 > 0 ? (nField2-1) : 0;
if ( pArgs->GetItemState( FN_PARAM_6, true, &pItem ) == SfxItemState::SET )
aSortParam.maKeyState[2].bAscending = static_cast<const SfxBoolItem*>(pItem)->GetValue();
// subtotal when needed new
pTabViewShell->UISort( aSortParam );
rReq.Done();
}
}
else
{
ScSortParam aSortParam;
ScDBData* pDBData = pTabViewShell->GetDBData();
ScViewData* pData = GetViewData();
pDBData->GetSortParam( aSortParam );
if( lcl_GetSortParam( pData, aSortParam ) )
{
ScDocument* pDoc = GetViewData()->GetDocument();
SfxItemSet aArgSet( GetPool(), svl::Items<SCITEM_SORTDATA, SCITEM_SORTDATA>{} );
pDBData->GetSortParam( aSortParam );
bool bHasHeader = pDoc->HasColHeader( aSortParam.nCol1, aSortParam.nRow1, aSortParam.nCol2, aSortParam.nRow2, pData->GetTabNo() );
if( bHasHeader )
aSortParam.bHasHeader = bHasHeader;
aArgSet.Put( ScSortItem( SCITEM_SORTDATA, GetViewData(), &aSortParam ) );
ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateScSortDlg(pTabViewShell->GetFrameWeld(), &aArgSet));
pDlg->SetCurPageId("criteria"); // 1=sort field tab 2=sort options tab
if ( pDlg->Execute() == RET_OK )
{
const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
const ScSortParam& rOutParam = static_cast<const ScSortItem&>(
pOutSet->Get( SCITEM_SORTDATA )).GetSortData();
// subtotal when needed new
pTabViewShell->UISort( rOutParam );
if ( rOutParam.bInplace )
{
rReq.AppendItem( SfxBoolItem( SID_SORT_BYROW,
rOutParam.bByRow ) );
rReq.AppendItem( SfxBoolItem( SID_SORT_HASHEADER,
rOutParam.bHasHeader ) );
rReq.AppendItem( SfxBoolItem( SID_SORT_CASESENS,
rOutParam.bCaseSens ) );
rReq.AppendItem( SfxBoolItem( SID_SORT_NATURALSORT,
rOutParam.bNaturalSort ) );
rReq.AppendItem( SfxBoolItem( SID_SORT_INCCOMMENTS,
rOutParam.bIncludeComments ) );
rReq.AppendItem( SfxBoolItem( SID_SORT_INCIMAGES,
rOutParam.bIncludeGraphicObjects ) );
rReq.AppendItem( SfxBoolItem( SID_SORT_ATTRIBS,
rOutParam.bIncludePattern ) );
sal_uInt16 nUser = rOutParam.bUserDef ? ( rOutParam.nUserIndex + 1 ) : 0;
rReq.AppendItem( SfxUInt16Item( SID_SORT_USERDEF, nUser ) );
if ( rOutParam.maKeyState[0].bDoSort )
{
rReq.AppendItem( SfxInt32Item( FN_PARAM_1,
rOutParam.maKeyState[0].nField + 1 ) );
rReq.AppendItem( SfxBoolItem( FN_PARAM_2,
rOutParam.maKeyState[0].bAscending ) );
}
if ( rOutParam.maKeyState[1].bDoSort )
{
rReq.AppendItem( SfxInt32Item( FN_PARAM_3,
rOutParam.maKeyState[1].nField + 1 ) );
rReq.AppendItem( SfxBoolItem( FN_PARAM_4,
rOutParam.maKeyState[1].bAscending ) );
}
if ( rOutParam.maKeyState[2].bDoSort )
{
rReq.AppendItem( SfxInt32Item( FN_PARAM_5,
rOutParam.maKeyState[2].nField + 1 ) );
rReq.AppendItem( SfxBoolItem( FN_PARAM_6,
rOutParam.maKeyState[2].bAscending ) );
}
}
rReq.Done();
}
else
GetViewData()->GetDocShell()->CancelAutoDBRange();
}
}
}
break;
case SID_FILTER:
{
const SfxItemSet* pArgs = rReq.GetArgs();
if ( pArgs )
{
OSL_FAIL("SID_FILTER with arguments?");
pTabViewShell->Query( static_cast<const ScQueryItem&>(
pArgs->Get( SCITEM_QUERYDATA )).GetQueryData(), nullptr, true );
rReq.Done();
}
else
{
sal_uInt16 nId = ScFilterDlgWrapper::GetChildWindowId();
SfxViewFrame* pViewFrm = pTabViewShell->GetViewFrame();
SfxChildWindow* pWnd = pViewFrm->GetChildWindow( nId );
pScMod->SetRefDialog( nId, pWnd == nullptr );
}
}
break;
case SID_SPECIAL_FILTER:
{
const SfxItemSet* pArgs = rReq.GetArgs();
if ( pArgs )
{
OSL_FAIL("SID_SPECIAL_FILTER with arguments?");
pTabViewShell->Query( static_cast<const ScQueryItem&>(
pArgs->Get( SCITEM_QUERYDATA )).GetQueryData(), nullptr, true );
rReq.Done();
}
else
{
sal_uInt16 nId = ScSpecialFilterDlgWrapper::GetChildWindowId();
SfxViewFrame* pViewFrm = pTabViewShell->GetViewFrame();
SfxChildWindow* pWnd = pViewFrm->GetChildWindow( nId );
pScMod->SetRefDialog( nId, pWnd == nullptr );
}
}
break;
case FID_FILTER_OK:
{
const SfxPoolItem* pItem;
if ( pReqArgs && SfxItemState::SET ==
pReqArgs->GetItemState( SCITEM_QUERYDATA, true, &pItem ) )
{
const ScQueryItem& rQueryItem = static_cast<const ScQueryItem&>(*pItem);
SCTAB nCurTab = GetViewData()->GetTabNo();
SCTAB nRefTab = GetViewData()->GetRefTabNo();
// If RefInput switched to a different sheet from the data sheet,
// switch back:
if ( nCurTab != nRefTab )
{
pTabViewShell->SetTabNo( nRefTab );
pTabViewShell->PaintExtras();
}
ScRange aAdvSource;
if (rQueryItem.GetAdvancedQuerySource(aAdvSource))
pTabViewShell->Query( rQueryItem.GetQueryData(), &aAdvSource, true );
else
pTabViewShell->Query( rQueryItem.GetQueryData(), nullptr, true );
rReq.Done( *pReqArgs );
}
}
break;
case SID_UNFILTER:
{
ScQueryParam aParam;
ScDBData* pDBData = pTabViewShell->GetDBData();
pDBData->GetQueryParam( aParam );
SCSIZE nEC = aParam.GetEntryCount();
for (SCSIZE i=0; i<nEC; i++)
aParam.GetEntry(i).bDoQuery = false;
aParam.bDuplicate = true;
pTabViewShell->Query( aParam, nullptr, true );
rReq.Done();
}
break;
case SID_AUTO_FILTER:
pTabViewShell->ToggleAutoFilter();
rReq.Done();
break;
case SID_AUTOFILTER_HIDE:
pTabViewShell->HideAutoFilter();
rReq.Done();
break;
case SID_PIVOT_TABLE:
{
const SfxPoolItem* pItem;
if ( pReqArgs && SfxItemState::SET ==
pReqArgs->GetItemState( SCITEM_PIVOTDATA, true, &pItem ) )
{
SCTAB nCurTab = GetViewData()->GetTabNo();
SCTAB nRefTab = GetViewData()->GetRefTabNo();
// If RefInput switched to a different sheet from the data sheet,
// switch back:
if ( nCurTab != nRefTab )
{
pTabViewShell->SetTabNo( nRefTab );
pTabViewShell->PaintExtras();
}
const ScDPObject* pDPObject = pTabViewShell->GetDialogDPObject();
if ( pDPObject )
{
const ScPivotItem* pPItem = static_cast<const ScPivotItem*>(pItem);
bool bSuccess = pTabViewShell->MakePivotTable(
pPItem->GetData(), pPItem->GetDestRange(), pPItem->IsNewSheet(), *pDPObject );
SfxBoolItem aRet(0, bSuccess);
rReq.SetReturnValue(aRet);
}
rReq.Done();
}
#if HAVE_FEATURE_SCRIPTING
else if (rReq.IsAPI())
SbxBase::SetError(ERRCODE_BASIC_BAD_PARAMETER);
#endif
}
break;
case SID_OPENDLG_PIVOTTABLE:
ExecuteDataPilotDialog();
break;
case SID_DEFINE_DBNAME:
{
sal_uInt16 nId = ScDbNameDlgWrapper::GetChildWindowId();
SfxViewFrame* pViewFrm = pTabViewShell->GetViewFrame();
SfxChildWindow* pWnd = pViewFrm->GetChildWindow( nId );
pScMod->SetRefDialog( nId, pWnd == nullptr );
}
break;
case SID_SELECT_DB:
{
if ( pReqArgs )
{
const SfxStringItem* pItem =
static_cast<const SfxStringItem*>(&pReqArgs->Get( SID_SELECT_DB ));
if( pItem )
{
pTabViewShell->GotoDBArea( pItem->GetValue() );
rReq.Done();
}
else
{
OSL_FAIL("NULL");
}
}
else
{
ScDocument* pDoc = GetViewData()->GetDocument();
ScDBCollection* pDBCol = pDoc->GetDBCollection();
if ( pDBCol )
{
std::vector<OUString> aList;
const ScDBCollection::NamedDBs& rDBs = pDBCol->getNamedDBs();
ScDBCollection::NamedDBs::const_iterator itr = rDBs.begin(), itrEnd = rDBs.end();
for (; itr != itrEnd; ++itr)
aList.push_back((*itr)->GetName());
ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
ScopedVclPtr<AbstractScSelEntryDlg> pDlg(pFact->CreateScSelEntryDlg(pTabViewShell->GetFrameWeld(), aList));
if ( pDlg->Execute() == RET_OK )
{
OUString aName = pDlg->GetSelectedEntry();
pTabViewShell->GotoDBArea( aName );
rReq.AppendItem( SfxStringItem( SID_SELECT_DB, aName ) );
rReq.Done();
}
}
}
}
break;
case SID_DATA_STREAMS:
{
sc::DataStreamDlg aDialog(GetViewData()->GetDocShell(), pTabViewShell->GetFrameWeld());
ScDocument *pDoc = GetViewData()->GetDocument();
sc::DocumentLinkManager& rMgr = pDoc->GetDocLinkManager();
sc::DataStream* pStrm = rMgr.getDataStream();
if (pStrm)
aDialog.Init(*pStrm);
if (aDialog.run() == RET_OK)
aDialog.StartStream();
}
break;
case SID_DATA_STREAMS_PLAY:
{
ScDocument *pDoc = GetViewData()->GetDocument();
sc::DocumentLinkManager& rMgr = pDoc->GetDocLinkManager();
sc::DataStream* pStrm = rMgr.getDataStream();
if (pStrm)
pStrm->StartImport();
}
break;
case SID_DATA_STREAMS_STOP:
{
ScDocument *pDoc = GetViewData()->GetDocument();
sc::DocumentLinkManager& rMgr = pDoc->GetDocLinkManager();
sc::DataStream* pStrm = rMgr.getDataStream();
if (pStrm)
pStrm->StopImport();
}
break;
case SID_DATA_PROVIDER:
{
std::shared_ptr<ScDocument> xDoc(new ScDocument, o3tl::default_delete<ScDocument>());
xDoc->InsertTab(0, "test");
ScDocument* pDoc = GetViewData()->GetDocument();
ScopedVclPtrInstance< ScDataProviderDlg > aDialog( pTabViewShell->GetDialogParent(), xDoc, pDoc);
if (aDialog->Execute() == RET_OK)
{
aDialog->import(pDoc);
}
}
break;
case SID_DATA_PROVIDER_REFRESH:
{
ScDocument* pDoc = GetViewData()->GetDocument();
auto& rDataMapper = pDoc->GetExternalDataMapper();
for (auto& rDataSource : rDataMapper.getDataSources())
{
rDataSource.refresh(pDoc, false);
}
}
break;
case SID_MANAGE_XML_SOURCE:
ExecuteXMLSourceDialog();
break;
case FID_VALIDATION:
case FID_CURRENTVALIDATION:
{
const SfxPoolItem* pItem;
const SfxItemSet* pArgs = rReq.GetArgs();
if ( pArgs )
{
OSL_FAIL("later...");
}
else
{
SfxItemSet aArgSet( GetPool(), ScTPValidationValue::GetRanges() );
ScValidationMode eMode = SC_VALID_ANY;
ScConditionMode eOper = ScConditionMode::Equal;
OUString aExpr1, aExpr2;
bool bBlank = true;
sal_Int16 nListType = css::sheet::TableValidationVisibility::UNSORTED;
bool bShowHelp = false;
OUString aHelpTitle, aHelpText;
bool bShowError = false;
ScValidErrorStyle eErrStyle = SC_VALERR_STOP;
OUString aErrTitle, aErrText;
ScDocument* pDoc = GetViewData()->GetDocument();
SCCOL nCurX = GetViewData()->GetCurX();
SCROW nCurY = GetViewData()->GetCurY();
SCTAB nTab = GetViewData()->GetTabNo();
ScAddress aCursorPos( nCurX, nCurY, nTab );
sal_uLong nIndex = pDoc->GetAttr(
nCurX, nCurY, nTab, ATTR_VALIDDATA )->GetValue();
if ( nIndex )
{
const ScValidationData* pOldData = pDoc->GetValidationEntry( nIndex );
if ( pOldData )
{
eMode = pOldData->GetDataMode();
eOper = pOldData->GetOperation();
sal_uInt32 nNumFmt = 0;
if ( eMode == SC_VALID_DATE || eMode == SC_VALID_TIME )
{
SvNumFormatType nType = ( eMode == SC_VALID_DATE ) ? SvNumFormatType::DATE
: SvNumFormatType::TIME;
nNumFmt = pDoc->GetFormatTable()->GetStandardFormat(
nType, ScGlobal::eLnge );
}
aExpr1 = pOldData->GetExpression( aCursorPos, 0, nNumFmt );
aExpr2 = pOldData->GetExpression( aCursorPos, 1, nNumFmt );
bBlank = pOldData->IsIgnoreBlank();
nListType = pOldData->GetListType();
bShowHelp = pOldData->GetInput( aHelpTitle, aHelpText );
bShowError = pOldData->GetErrMsg( aErrTitle, aErrText, eErrStyle );
aArgSet.Put( SfxAllEnumItem( FID_VALID_MODE, sal::static_int_cast<sal_uInt16>(eMode) ) );
aArgSet.Put( SfxAllEnumItem( FID_VALID_CONDMODE, sal::static_int_cast<sal_uInt16>(eOper) ) );
aArgSet.Put( SfxStringItem( FID_VALID_VALUE1, aExpr1 ) );
aArgSet.Put( SfxStringItem( FID_VALID_VALUE2, aExpr2 ) );
aArgSet.Put( SfxBoolItem( FID_VALID_BLANK, bBlank ) );
aArgSet.Put( SfxInt16Item( FID_VALID_LISTTYPE, nListType ) );
aArgSet.Put( SfxBoolItem( FID_VALID_SHOWHELP, bShowHelp ) );
aArgSet.Put( SfxStringItem( FID_VALID_HELPTITLE, aHelpTitle ) );
aArgSet.Put( SfxStringItem( FID_VALID_HELPTEXT, aHelpText ) );
aArgSet.Put( SfxBoolItem( FID_VALID_SHOWERR, bShowError ) );
aArgSet.Put( SfxAllEnumItem( FID_VALID_ERRSTYLE, sal::static_int_cast<sal_uInt16>(eErrStyle) ) );
aArgSet.Put( SfxStringItem( FID_VALID_ERRTITLE, aErrTitle ) );
aArgSet.Put( SfxStringItem( FID_VALID_ERRTEXT, aErrText ) );
}
}
// cell range picker
ScopedVclPtrInstance<ScValidationDlg> pDlg(GetViewData()->GetActiveWin(), &aArgSet, pTabViewShell);
short nResult = pDlg->Execute();
if ( nResult == RET_OK )
{
const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
if ( pOutSet->GetItemState( FID_VALID_MODE, true, &pItem ) == SfxItemState::SET )
eMode = static_cast<ScValidationMode>(static_cast<const SfxAllEnumItem*>(pItem)->GetValue());
if ( pOutSet->GetItemState( FID_VALID_CONDMODE, true, &pItem ) == SfxItemState::SET )
eOper = static_cast<ScConditionMode>(static_cast<const SfxAllEnumItem*>(pItem)->GetValue());
if ( pOutSet->GetItemState( FID_VALID_VALUE1, true, &pItem ) == SfxItemState::SET )
{
OUString aTemp1 = static_cast<const SfxStringItem*>(pItem)->GetValue();
if (eMode == SC_VALID_DATE || eMode == SC_VALID_TIME)
{
sal_uInt32 nNumIndex = 0;
double nVal;
if (pDoc->GetFormatTable()->IsNumberFormat(aTemp1, nNumIndex, nVal))
aExpr1 = ::rtl::math::doubleToUString( nVal,
rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
ScGlobal::pLocaleData->getNumDecimalSep()[0], true);
else
aExpr1 = aTemp1;
}
else
aExpr1 = aTemp1;
}
if ( pOutSet->GetItemState( FID_VALID_VALUE2, true, &pItem ) == SfxItemState::SET )
{
OUString aTemp2 = static_cast<const SfxStringItem*>(pItem)->GetValue();
if (eMode == SC_VALID_DATE || eMode == SC_VALID_TIME)
{
sal_uInt32 nNumIndex = 0;
double nVal;
if (pDoc->GetFormatTable()->IsNumberFormat(aTemp2, nNumIndex, nVal))
aExpr2 = ::rtl::math::doubleToUString( nVal,
rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
ScGlobal::pLocaleData->getNumDecimalSep()[0], true);
else
aExpr2 = aTemp2;
if ( eMode == SC_VALID_TIME ) {
sal_Int32 wraparound = aExpr1.compareTo(aExpr2);
if (wraparound > 0) {
if (eOper == ScConditionMode::Between) {
eOper = ScConditionMode::NotBetween;
OUString tmp = aExpr1;
aExpr1 = aExpr2;
aExpr2 = tmp;
}
else if (eOper == ScConditionMode::NotBetween) {
eOper = ScConditionMode::Between;
OUString tmp = aExpr1;
aExpr1 = aExpr2;
aExpr2 = tmp;
}
}
}
}
else
aExpr2 = aTemp2;
}
if ( pOutSet->GetItemState( FID_VALID_BLANK, true, &pItem ) == SfxItemState::SET )
bBlank = static_cast<const SfxBoolItem*>(pItem)->GetValue();
if ( pOutSet->GetItemState( FID_VALID_LISTTYPE, true, &pItem ) == SfxItemState::SET )
nListType = static_cast<const SfxInt16Item*>(pItem)->GetValue();
if ( pOutSet->GetItemState( FID_VALID_SHOWHELP, true, &pItem ) == SfxItemState::SET )
bShowHelp = static_cast<const SfxBoolItem*>(pItem)->GetValue();
if ( pOutSet->GetItemState( FID_VALID_HELPTITLE, true, &pItem ) == SfxItemState::SET )
aHelpTitle = static_cast<const SfxStringItem*>(pItem)->GetValue();
if ( pOutSet->GetItemState( FID_VALID_HELPTEXT, true, &pItem ) == SfxItemState::SET )
aHelpText = static_cast<const SfxStringItem*>(pItem)->GetValue();
if ( pOutSet->GetItemState( FID_VALID_SHOWERR, true, &pItem ) == SfxItemState::SET )
bShowError = static_cast<const SfxBoolItem*>(pItem)->GetValue();
if ( pOutSet->GetItemState( FID_VALID_ERRSTYLE, true, &pItem ) == SfxItemState::SET )
eErrStyle = static_cast<ScValidErrorStyle>(static_cast<const SfxAllEnumItem*>(pItem)->GetValue());
if ( pOutSet->GetItemState( FID_VALID_ERRTITLE, true, &pItem ) == SfxItemState::SET )
aErrTitle = static_cast<const SfxStringItem*>(pItem)->GetValue();
if ( pOutSet->GetItemState( FID_VALID_ERRTEXT, true, &pItem ) == SfxItemState::SET )
aErrText = static_cast<const SfxStringItem*>(pItem)->GetValue();
ScValidationData aData( eMode, eOper, aExpr1, aExpr2, pDoc, aCursorPos );
aData.SetIgnoreBlank( bBlank );
aData.SetListType( nListType );
aData.SetInput(aHelpTitle, aHelpText); // sets bShowInput to TRUE
if (!bShowHelp)
aData.ResetInput(); // reset only bShowInput
aData.SetError(aErrTitle, aErrText, eErrStyle); // sets bShowError to TRUE
if (!bShowError)
aData.ResetError(); // reset only bShowError
pTabViewShell->SetValidation( aData );
pTabViewShell->TestHintWindow();
rReq.Done( *pOutSet );
}
}
}
break;
case SID_TEXT_TO_COLUMNS:
{
ScViewData* pData = GetViewData();
OSL_ENSURE( pData, "ScCellShell::ExecuteDB: SID_TEXT_TO_COLUMNS - pData is null!" );
ScRange aRange;
if ( lcl_GetTextToColumnsRange( pData, aRange, false ) )
{
ScDocument* pDoc = pData->GetDocument();
OSL_ENSURE( pDoc, "ScCellShell::ExecuteDB: SID_TEXT_TO_COLUMNS - pDoc is null!" );
ScImportExport aExport( pDoc, aRange );
aExport.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::None, 0, false ) );
// #i87703# text to columns fails with tab separator
aExport.SetDelimiter( u'\0' );
SvMemoryStream aStream;
aStream.SetStreamCharSet( RTL_TEXTENCODING_UNICODE );
ScImportExport::SetNoEndianSwap( aStream );
aExport.ExportStream( aStream, OUString(), SotClipboardFormatId::STRING );
ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
ScopedVclPtr<AbstractScImportAsciiDlg> pDlg(pFact->CreateScImportAsciiDlg(
nullptr, OUString(), &aStream, SC_TEXTTOCOLUMNS));
if ( pDlg->Execute() == RET_OK )
{
ScDocShell* pDocSh = pData->GetDocShell();
OSL_ENSURE( pDocSh, "ScCellShell::ExecuteDB: SID_TEXT_TO_COLUMNS - pDocSh is null!" );
OUString aUndo = ScResId( STR_UNDO_TEXTTOCOLUMNS );
pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo, 0, pData->GetViewShell()->GetViewShellId() );
ScImportExport aImport( pDoc, aRange.aStart );
ScAsciiOptions aOptions;
pDlg->GetOptions( aOptions );
pDlg->SaveParameters();
aImport.SetExtOptions( aOptions );
aImport.SetApi( false );
aImport.SetImportBroadcast( true );
aImport.SetOverwriting( true );
aStream.Seek( 0 );
aImport.ImportStream( aStream, OUString(), SotClipboardFormatId::STRING );
pDocSh->GetUndoManager()->LeaveListAction();
}
}
}
break;
}
}
void ScCellShell::GetDBState( SfxItemSet& rSet )
{
ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell();
ScViewData* pData = GetViewData();
ScDocShell* pDocSh = pData->GetDocShell();
ScDocument& rDoc = pDocSh->GetDocument();
SCCOL nPosX = pData->GetCurX();
SCROW nPosY = pData->GetCurY();
SCTAB nTab = pData->GetTabNo();
bool bAutoFilter = false;
bool bAutoFilterTested = false;
SfxWhichIter aIter(rSet);
sal_uInt16 nWhich = aIter.FirstWhich();
while (nWhich)
{
switch (nWhich)
{
case SID_REFRESH_DBAREA:
{
// imported data without selection
// or filter,sort,subtotal (also without import)
bool bOk = false;
ScDBData* pDBData = pTabViewShell->GetDBData(false,SC_DB_OLD);
if (pDBData && rDoc.GetChangeTrack() == nullptr)
{
if ( pDBData->HasImportParam() )
bOk = !pDBData->HasImportSelection();
else
{
bOk = pDBData->HasQueryParam() ||
pDBData->HasSortParam() ||
pDBData->HasSubTotalParam();
}
}
if (!bOk)
rSet.DisableItem( nWhich );
}
break;
case SID_FILTER:
case SID_SPECIAL_FILTER:
{
ScRange aDummy;
ScMarkType eMarkType = GetViewData()->GetSimpleArea( aDummy);
if (eMarkType != SC_MARK_SIMPLE && eMarkType != SC_MARK_SIMPLE_FILTERED)
{
rSet.DisableItem( nWhich );
}
}
break;
//in case of Redlining and multiselection disable
case SID_SORT_ASCENDING:
case SID_SORT_DESCENDING:
case SCITEM_SORTDATA:
case SCITEM_SUBTDATA:
case SID_OPENDLG_PIVOTTABLE:
{
//! move ReadOnly check to idl flags
if ( pDocSh->IsReadOnly() || rDoc.GetChangeTrack()!=nullptr ||
GetViewData()->IsMultiMarked() )
{
rSet.DisableItem( nWhich );
}
}
break;
case SID_REIMPORT_DATA:
{
// only imported data without selection
ScDBData* pDBData = pTabViewShell->GetDBData(false,SC_DB_OLD);
if (!pDBData || !pDBData->HasImportParam() || pDBData->HasImportSelection() ||
rDoc.GetChangeTrack()!=nullptr)
{
rSet.DisableItem( nWhich );
}
}
break;
case SID_VIEW_DATA_SOURCE_BROWSER:
{
if (!SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::EModule::DATABASE))
rSet.Put(SfxVisibilityItem(nWhich, false));
else
// get state (BoolItem) from SfxViewFrame
pTabViewShell->GetViewFrame()->GetSlotState( nWhich, nullptr, &rSet );
}
break;
case SID_SBA_BRW_INSERT:
{
// SBA wants a sal_Bool-item, enabled
rSet.Put(SfxBoolItem(nWhich, true));
}
break;
case SID_AUTO_FILTER:
case SID_AUTOFILTER_HIDE:
{
if (!bAutoFilterTested)
{
bAutoFilter = rDoc.HasAutoFilter( nPosX, nPosY, nTab );
bAutoFilterTested = true;
}
if ( nWhich == SID_AUTO_FILTER )
{
ScRange aDummy;
ScMarkType eMarkType = GetViewData()->GetSimpleArea( aDummy);
if (eMarkType != SC_MARK_SIMPLE && eMarkType != SC_MARK_SIMPLE_FILTERED)
{
rSet.DisableItem( nWhich );
}
else if (rDoc.GetDPAtBlock(aDummy))
{
rSet.DisableItem( nWhich );
}
else
rSet.Put( SfxBoolItem( nWhich, bAutoFilter ) );
}
else
if (!bAutoFilter)
rSet.DisableItem( nWhich );
}
break;
case SID_UNFILTER:
{
SCCOL nStartCol, nEndCol;
SCROW nStartRow, nEndRow;
SCTAB nStartTab, nEndTab;
bool bAnyQuery = false;
bool bSelected = (GetViewData()->GetSimpleArea(
nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab )
== SC_MARK_SIMPLE);
if ( bSelected )
{
if (nStartCol==nEndCol && nStartRow==nEndRow)
bSelected = false;
}
else
{
nStartCol = GetViewData()->GetCurX();
nStartRow = GetViewData()->GetCurY();
nStartTab = GetViewData()->GetTabNo();
}
ScDBData* pDBData = bSelected
? rDoc.GetDBAtArea( nStartTab, nStartCol, nStartRow, nEndCol, nEndRow )
: rDoc.GetDBAtCursor( nStartCol, nStartRow, nStartTab, ScDBDataPortion::AREA );
if ( pDBData )
{
ScQueryParam aParam;
pDBData->GetQueryParam( aParam );
if ( aParam.GetEntry(0).bDoQuery )
bAnyQuery = true;
}
if ( !bAnyQuery )
rSet.DisableItem( nWhich );
}
break;
case SID_DEFINE_DBNAME:
{
if ( pDocSh->IsDocShared() )
{
rSet.DisableItem( nWhich );
}
}
break;
case SID_DATA_PROVIDER:
break;
case SID_DATA_PROVIDER_REFRESH:
{
ScDocument* pDoc = GetViewData()->GetDocument();
auto& rDataMapper = pDoc->GetExternalDataMapper();
if (rDataMapper.getDataSources().empty())
rSet.DisableItem(nWhich);
}
break;
case SID_DATA_STREAMS:
case SID_DATA_STREAMS_PLAY:
case SID_DATA_STREAMS_STOP:
{
SvtMiscOptions aMiscOptions;
if ( !aMiscOptions.IsExperimentalMode() )
rSet.DisableItem( nWhich );
}
break;
case SID_TEXT_TO_COLUMNS:
{
ScRange aRange;
if ( !lcl_GetTextToColumnsRange( pData, aRange, true ) )
{
rSet.DisableItem( nWhich );
}
}
break;
case SID_MANAGE_XML_SOURCE:
{
SvtMiscOptions aMiscOptions;
if ( !aMiscOptions.IsExperimentalMode() )
rSet.DisableItem( nWhich );
}
break;
}
nWhich = aIter.NextWhich();
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V547 Expression 'pItem' is always true.