/* -*- 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 <sal/config.h>
#include <string_view>
#include "vbaworksheet.hxx"
#include "vbanames.hxx"
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/XIntrospectionAccess.hpp>
#include <com/sun/star/container/XNamed.hpp>
#include <com/sun/star/util/XProtectable.hpp>
#include <com/sun/star/table/XCellRange.hpp>
#include <com/sun/star/sheet/XSpreadsheetView.hpp>
#include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
#include <com/sun/star/sheet/XCalculatable.hpp>
#include <com/sun/star/sheet/XCellRangeAddressable.hpp>
#include <com/sun/star/sheet/XSheetCellRange.hpp>
#include <com/sun/star/sheet/XSheetCellCursor.hpp>
#include <com/sun/star/sheet/XSheetAnnotationsSupplier.hpp>
#include <com/sun/star/sheet/XUsedAreaCursor.hpp>
#include <com/sun/star/sheet/XSpreadsheets.hpp>
#include <com/sun/star/sheet/XSheetOutline.hpp>
#include <com/sun/star/sheet/XSheetPageBreak.hpp>
#include <com/sun/star/sheet/XDataPilotTablesSupplier.hpp>
#include <com/sun/star/sheet/XNamedRanges.hpp>
#include <com/sun/star/frame/Desktop.hpp>
#include <com/sun/star/table/XTableChartsSupplier.hpp>
#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
#include <com/sun/star/drawing/XControlShape.hpp>
#include <com/sun/star/form/XFormsSupplier.hpp>
#include <ooo/vba/excel/XApplication.hpp>
#include <ooo/vba/excel/XlEnableSelection.hpp>
#include <ooo/vba/excel/XlSheetVisibility.hpp>
#include <ooo/vba/XControlProvider.hpp>
#include <basic/sberrors.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/servicehelper.hxx>
#include <utility>
#include <vbahelper/vbashapes.hxx>
//zhangyun showdataform
#include <scabstdlg.hxx>
#include <tabvwsh.hxx>
#include <tabprotection.hxx>
#include "excelvbahelper.hxx"
#include "vbaoutline.hxx"
#include "vbarange.hxx"
#include "vbacomments.hxx"
#include "vbachartobjects.hxx"
#include "vbapivottables.hxx"
#include "vbaoleobjects.hxx"
#include "vbapagesetup.hxx"
#include "vbapagebreaks.hxx"
#include "vbaworksheets.hxx"
#include "vbahyperlinks.hxx"
#include "vbasheetobjects.hxx"
#include <dbdata.hxx>
#include <attrib.hxx>
#define STANDARDWIDTH 2267
#define STANDARDHEIGHT 427
using namespace com::sun::star;
using namespace ooo::vba;
static void getNewSpreadsheetName (OUString &aNewName, std::u16string_view aOldName, const uno::Reference <sheet::XSpreadsheetDocument>& xSpreadDoc )
{
if (!xSpreadDoc.is())
throw lang::IllegalArgumentException( u"getNewSpreadsheetName() xSpreadDoc is null"_ustr, uno::Reference< uno::XInterface >(), 1 );
static const char aUnderScore[] = "_";
int currentNum =2;
aNewName = OUString::Concat(aOldName) + aUnderScore + OUString::number(currentNum) ;
SCTAB nTab = 0;
while ( ScVbaWorksheets::nameExists(xSpreadDoc,aNewName, nTab ) )
{
aNewName = OUString::Concat(aOldName) + aUnderScore + OUString::number(++currentNum);
}
}
static void removeAllSheets( const uno::Reference <sheet::XSpreadsheetDocument>& xSpreadDoc, const OUString& aSheetName)
{
if (!xSpreadDoc.is())
throw lang::IllegalArgumentException( u"removeAllSheets() xSpreadDoc is null"_ustr, uno::Reference< uno::XInterface >(), 1 );
uno::Reference<sheet::XSpreadsheets> xSheets = xSpreadDoc->getSheets();
uno::Reference <container::XIndexAccess> xIndex( xSheets, uno::UNO_QUERY );
if ( !xIndex.is() )
return;
uno::Reference<container::XNameContainer> xNameContainer(xSheets,uno::UNO_QUERY_THROW);
for (sal_Int32 i = xIndex->getCount() -1; i>= 1; i--)
{
uno::Reference< sheet::XSpreadsheet > xSheet(xIndex->getByIndex(i), uno::UNO_QUERY);
uno::Reference< container::XNamed > xNamed( xSheet, uno::UNO_QUERY_THROW );
xNameContainer->removeByName(xNamed->getName());
}
uno::Reference< sheet::XSpreadsheet > xSheet(xIndex->getByIndex(0), uno::UNO_QUERY);
uno::Reference< container::XNamed > xNamed( xSheet, uno::UNO_QUERY_THROW );
xNamed->setName(aSheetName);
}
static uno::Reference<frame::XModel>
openNewDoc(const OUString& aSheetName )
{
uno::Reference<frame::XModel> xModel;
try
{
const uno::Reference< uno::XComponentContext >& xContext(
comphelper::getProcessComponentContext() );
uno::Reference <frame::XDesktop2 > xComponentLoader = frame::Desktop::create(xContext);
uno::Reference<lang::XComponent > xComponent( xComponentLoader->loadComponentFromURL(
u"private:factory/scalc"_ustr,
u"_blank"_ustr, 0,
uno::Sequence < css::beans::PropertyValue >() ) );
uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( xComponent, uno::UNO_QUERY_THROW );
removeAllSheets(xSpreadDoc,aSheetName);
xModel.set(xSpreadDoc,uno::UNO_QUERY_THROW);
}
catch ( uno::Exception & /*e*/ )
{
}
return xModel;
}
ScVbaWorksheet::ScVbaWorksheet(const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext,
uno::Reference< sheet::XSpreadsheet > xSheet,
uno::Reference< frame::XModel > xModel ) : WorksheetImpl_BASE( xParent, xContext ), mxSheet(std::move( xSheet )), mxModel(std::move(xModel)), mbVeryHidden( false )
{
}
ScVbaWorksheet::ScVbaWorksheet( uno::Sequence< uno::Any> const & args,
uno::Reference< uno::XComponentContext> const & xContext ) : WorksheetImpl_BASE( getXSomethingFromArgs< XHelperInterface >( args, 0 ), xContext ), mxModel( getXSomethingFromArgs< frame::XModel >( args, 1 ) ), mbVeryHidden( false )
{
if ( args.getLength() < 3 )
throw lang::IllegalArgumentException();
OUString sSheetName;
args[2] >>= sSheetName;
uno::Reference< sheet::XSpreadsheetDocument > xSpreadDoc( mxModel, uno::UNO_QUERY_THROW );
uno::Reference< container::XNameAccess > xNameAccess( xSpreadDoc->getSheets(), uno::UNO_QUERY_THROW );
mxSheet.set( xNameAccess->getByName( sSheetName ), uno::UNO_QUERY_THROW );
}
ScVbaWorksheet::~ScVbaWorksheet()
{
}
const uno::Sequence<sal_Int8>& ScVbaWorksheet::getUnoTunnelId()
{
static const comphelper::UnoIdInit theScVbaWorksheetUnoTunnelId;
return theScVbaWorksheetUnoTunnelId.getSeq();
}
uno::Reference< ov::excel::XWorksheet >
ScVbaWorksheet::createSheetCopyInNewDoc(const OUString& aCurrSheetName)
{
uno::Reference< sheet::XSheetCellCursor > xSheetCellCursor = getSheet()->createCursor( );
uno::Reference<sheet::XUsedAreaCursor> xUsedCursor(xSheetCellCursor,uno::UNO_QUERY_THROW);
uno::Reference<excel::XRange> xRange = new ScVbaRange( this, mxContext, xSheetCellCursor);
if (xRange.is())
xRange->Select();
excel::implnCopy(mxModel);
uno::Reference<frame::XModel> xModel = openNewDoc(aCurrSheetName);
if (xModel.is())
{
excel::implnPaste(xModel);
}
uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( xModel, uno::UNO_QUERY_THROW );
excel::setUpDocumentModules(xSpreadDoc);
uno::Reference <sheet::XSpreadsheets> xSheets( xSpreadDoc->getSheets(), uno::UNO_SET_THROW );
uno::Reference <container::XIndexAccess> xIndex( xSheets, uno::UNO_QUERY_THROW );
uno::Reference< sheet::XSpreadsheet > xSheet(xIndex->getByIndex(0), uno::UNO_QUERY_THROW);
ScDocShell* pShell = excel::getDocShell( xModel );
OUString aCodeName;
if (pShell)
pShell->GetDocument().GetCodeName( 0, aCodeName );
return uno::Reference< excel::XWorksheet >( getUnoDocModule( aCodeName, pShell ), uno::UNO_QUERY_THROW );
}
css::uno::Reference< ov::excel::XWorksheet >
ScVbaWorksheet::createSheetCopy(uno::Reference<excel::XWorksheet> const & xSheet, bool bAfter)
{
OUString aCurrSheetName = getName();
ScVbaWorksheet* pDestSheet = excel::getImplFromDocModuleWrapper<ScVbaWorksheet>( xSheet );
uno::Reference <sheet::XSpreadsheetDocument> xDestDoc( pDestSheet->getModel(), uno::UNO_QUERY );
uno::Reference <sheet::XSpreadsheetDocument> xSrcDoc( getModel(), uno::UNO_QUERY );
SCTAB nDest = 0;
SCTAB nSrc = 0;
OUString aSheetName = xSheet->getName();
bool bSameDoc = ( pDestSheet->getModel() == getModel() );
bool bDestSheetExists = ScVbaWorksheets::nameExists (xDestDoc, aSheetName, nDest );
bool bSheetExists = ScVbaWorksheets::nameExists (xSrcDoc, aCurrSheetName, nSrc );
// set sheet name to be newSheet name
aSheetName = aCurrSheetName;
if ( bSheetExists && bDestSheetExists )
{
SCTAB nDummy=0;
if(bAfter)
nDest++;
uno::Reference<sheet::XSpreadsheets> xSheets = xDestDoc->getSheets();
if ( bSameDoc || ScVbaWorksheets::nameExists( xDestDoc, aCurrSheetName, nDummy ) )
getNewSpreadsheetName(aSheetName,aCurrSheetName,xDestDoc);
if ( bSameDoc )
xSheets->copyByName(aCurrSheetName,aSheetName,nDest);
else
{
ScDocShell* pDestDocShell = excel::getDocShell( pDestSheet->getModel() );
ScDocShell* pSrcDocShell = excel::getDocShell( getModel() );
if ( pDestDocShell && pSrcDocShell )
pDestDocShell->TransferTab( *pSrcDocShell, nSrc, nDest, true, true );
}
}
// return new sheet
uno::Reference< excel::XApplication > xApplication( Application(), uno::UNO_QUERY_THROW );
uno::Reference< excel::XWorksheet > xNewSheet( xApplication->Worksheets( uno::Any( aSheetName ) ), uno::UNO_QUERY_THROW );
return xNewSheet;
}
OUString
ScVbaWorksheet::getName()
{
uno::Reference< container::XNamed > xNamed( getSheet(), uno::UNO_QUERY_THROW );
return xNamed->getName();
}
void
ScVbaWorksheet::setName(const OUString &rName )
{
uno::Reference< container::XNamed > xNamed( getSheet(), uno::UNO_QUERY_THROW );
xNamed->setName( rName );
}
sal_Int32
ScVbaWorksheet::getVisible()
{
uno::Reference< beans::XPropertySet > xProps( getSheet(), uno::UNO_QUERY_THROW );
bool bVisible = false;
xProps->getPropertyValue( u"IsVisible"_ustr ) >>= bVisible;
using namespace ::ooo::vba::excel::XlSheetVisibility;
return bVisible ? xlSheetVisible : (mbVeryHidden ? xlSheetVeryHidden : xlSheetHidden);
}
void
ScVbaWorksheet::setVisible( sal_Int32 nVisible )
{
using namespace ::ooo::vba::excel::XlSheetVisibility;
bool bVisible = true;
switch( nVisible )
{
case xlSheetVisible: case 1: // Excel accepts -1 and 1 for visible sheets
bVisible = true;
mbVeryHidden = false;
break;
case xlSheetHidden:
bVisible = false;
mbVeryHidden = false;
break;
case xlSheetVeryHidden:
bVisible = false;
mbVeryHidden = true;
break;
default:
throw uno::RuntimeException();
}
uno::Reference< beans::XPropertySet > xProps( getSheet(), uno::UNO_QUERY_THROW );
xProps->setPropertyValue( u"IsVisible"_ustr, uno::Any( bVisible ) );
}
sal_Int16
ScVbaWorksheet::getIndex()
{
return getSheetID() + 1;
}
sal_Int32
ScVbaWorksheet::getEnableSelection()
{
uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( getModel(), uno::UNO_QUERY_THROW );
SCTAB nTab = 0;
if ( !ScVbaWorksheets::nameExists(xSpreadDoc, getName(), nTab) )
throw uno::RuntimeException(u"Sheet Name does not exist."_ustr );
if ( ScDocShell* pShell = excel::getDocShell( getModel() ))
{
ScDocument& rDoc = pShell->GetDocument();
const ScTableProtection* pProtect = rDoc.GetTabProtection(nTab);
bool bLockedCells = false;
bool bUnlockedCells = false;
if( pProtect )
{
bLockedCells = pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
bUnlockedCells = pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
}
if( bLockedCells )
return excel::XlEnableSelection::xlNoRestrictions;
if( bUnlockedCells )
return excel::XlEnableSelection::xlUnlockedCells;
}
return excel::XlEnableSelection::xlNoSelection;
}
void
ScVbaWorksheet::setEnableSelection( sal_Int32 nSelection )
{
if( (nSelection != excel::XlEnableSelection::xlNoRestrictions) &&
(nSelection != excel::XlEnableSelection::xlUnlockedCells) &&
(nSelection != excel::XlEnableSelection::xlNoSelection) )
{
DebugHelper::runtimeexception(ERRCODE_BASIC_BAD_PARAMETER);
}
uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( getModel(), uno::UNO_QUERY_THROW );
SCTAB nTab = 0;
if ( !ScVbaWorksheets::nameExists(xSpreadDoc, getName(), nTab) )
throw uno::RuntimeException(u"Sheet Name does not exist."_ustr );
if ( ScDocShell* pShell = excel::getDocShell( getModel() ))
{
ScDocument& rDoc = pShell->GetDocument();
const ScTableProtection* pProtect = rDoc.GetTabProtection(nTab);
// default is xlNoSelection
bool bLockedCells = false;
bool bUnlockedCells = false;
if( nSelection == excel::XlEnableSelection::xlNoRestrictions )
{
bLockedCells = true;
bUnlockedCells = true;
}
else if( nSelection == excel::XlEnableSelection::xlUnlockedCells )
{
bUnlockedCells = true;
}
if( pProtect )
{
ScTableProtection aNewProtect(*pProtect);
aNewProtect.setOption(ScTableProtection::SELECT_LOCKED_CELLS, bLockedCells);
aNewProtect.setOption(ScTableProtection::SELECT_UNLOCKED_CELLS, bUnlockedCells);
rDoc.SetTabProtection(nTab, &aNewProtect);
}
}
}
sal_Bool SAL_CALL ScVbaWorksheet::getAutoFilterMode()
{
if ( ScDocShell* pShell = excel::getDocShell( getModel() ))
{
ScDocument& rDoc = pShell->GetDocument();
ScDBData* pDBData = rDoc.GetAnonymousDBData(getSheetID());
if (pDBData)
return pDBData->HasAutoFilter();
}
return false;
}
void SAL_CALL ScVbaWorksheet::setAutoFilterMode( sal_Bool bAutoFilterMode )
{
ScDocShell* pDocShell = excel::getDocShell( getModel() );
if (!pDocShell)
return;
ScDocument& rDoc = pDocShell->GetDocument();
ScDBData* pDBData = rDoc.GetAnonymousDBData(getSheetID());
if (!pDBData)
return;
pDBData->SetAutoFilter(bAutoFilterMode);
ScRange aRange;
pDBData->GetArea(aRange);
if (bAutoFilterMode)
rDoc.ApplyFlagsTab( aRange.aStart.Col(), aRange.aStart.Row(),
aRange.aEnd.Col(), aRange.aStart.Row(),
aRange.aStart.Tab(), ScMF::Auto );
else if (!bAutoFilterMode)
rDoc.RemoveFlagsTab(aRange.aStart.Col(), aRange.aStart.Row(),
aRange.aEnd.Col(), aRange.aStart.Row(),
aRange.aStart.Tab(), ScMF::Auto );
ScRange aPaintRange(aRange.aStart, aRange.aEnd);
aPaintRange.aEnd.SetRow(aPaintRange.aStart.Row());
pDocShell->PostPaint(aPaintRange, PaintPartFlags::Grid);
}
uno::Reference< excel::XRange >
ScVbaWorksheet::getUsedRange()
{
uno::Reference< sheet::XSheetCellRange > xSheetCellRange(getSheet(), uno::UNO_QUERY_THROW );
uno::Reference< sheet::XSheetCellCursor > xSheetCellCursor( getSheet()->createCursorByRange( xSheetCellRange ), uno::UNO_SET_THROW );
uno::Reference<sheet::XUsedAreaCursor> xUsedCursor(xSheetCellCursor,uno::UNO_QUERY_THROW);
xUsedCursor->gotoStartOfUsedArea( false );
xUsedCursor->gotoEndOfUsedArea( true );
return new ScVbaRange(this, mxContext, xSheetCellCursor);
}
uno::Reference< excel::XOutline >
ScVbaWorksheet::Outline( )
{
uno::Reference<sheet::XSheetOutline> xOutline(getSheet(),uno::UNO_QUERY_THROW);
return new ScVbaOutline( this, mxContext, xOutline);
}
uno::Reference< excel::XPageSetup >
ScVbaWorksheet::PageSetup( )
{
return new ScVbaPageSetup( this, mxContext, getSheet(), getModel() );
}
uno::Any
ScVbaWorksheet::HPageBreaks( const uno::Any& aIndex )
{
uno::Reference< sheet::XSheetPageBreak > xSheetPageBreak(getSheet(),uno::UNO_QUERY_THROW);
uno::Reference< excel::XHPageBreaks > xHPageBreaks( new ScVbaHPageBreaks( this, mxContext, xSheetPageBreak));
if ( aIndex.hasValue() )
return xHPageBreaks->Item( aIndex, uno::Any());
return uno::Any( xHPageBreaks );
}
uno::Any
ScVbaWorksheet::VPageBreaks( const uno::Any& aIndex )
{
uno::Reference< sheet::XSheetPageBreak > xSheetPageBreak( getSheet(), uno::UNO_QUERY_THROW );
uno::Reference< excel::XVPageBreaks > xVPageBreaks( new ScVbaVPageBreaks( this, mxContext, xSheetPageBreak ) );
if( aIndex.hasValue() )
return xVPageBreaks->Item( aIndex, uno::Any());
return uno::Any( xVPageBreaks );
}
sal_Int32
ScVbaWorksheet::getStandardWidth()
{
return STANDARDWIDTH ;
}
sal_Int32
ScVbaWorksheet::getStandardHeight()
{
return STANDARDHEIGHT;
}
sal_Bool
ScVbaWorksheet::getProtectionMode()
{
return false;
}
sal_Bool
ScVbaWorksheet::getProtectContents()
{
uno::Reference<util::XProtectable > xProtectable(getSheet(), uno::UNO_QUERY_THROW);
return xProtectable->isProtected();
}
sal_Bool
ScVbaWorksheet::getProtectDrawingObjects()
{
SCTAB nTab = 0;
OUString aSheetName = getName();
uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( getModel(), uno::UNO_QUERY_THROW );
bool bSheetExists = ScVbaWorksheets::nameExists (xSpreadDoc, aSheetName, nTab);
if ( bSheetExists )
{
if ( ScDocShell* pShell = excel::getDocShell( getModel() ))
{
ScDocument& rDoc = pShell->GetDocument();
const ScTableProtection* pProtect = rDoc.GetTabProtection(nTab);
if ( pProtect )
return pProtect->isOptionEnabled( ScTableProtection::OBJECTS );
}
}
return false;
}
sal_Bool
ScVbaWorksheet::getProtectScenarios()
{
return false;
}
void
ScVbaWorksheet::Activate()
{
uno::Reference< sheet::XSpreadsheetView > xSpreadsheet(
getModel()->getCurrentController(), uno::UNO_QUERY_THROW );
xSpreadsheet->setActiveSheet(getSheet());
}
void
ScVbaWorksheet::Select()
{
Activate();
}
void
ScVbaWorksheet::Move( const uno::Any& Before, const uno::Any& After )
{
uno::Reference<excel::XWorksheet> xSheet;
OUString aCurrSheetName = getName();
if (!(Before >>= xSheet) && !(After >>=xSheet)&& !(Before.hasValue()) && !(After.hasValue()))
{
uno::Reference< sheet::XSheetCellCursor > xSheetCellCursor = getSheet()->createCursor( );
uno::Reference<sheet::XUsedAreaCursor> xUsedCursor(xSheetCellCursor,uno::UNO_QUERY_THROW);
// #FIXME needs worksheet as parent
uno::Reference<excel::XRange> xRange = new ScVbaRange( this, mxContext, xSheetCellCursor);
if (xRange.is())
xRange->Select();
excel::implnCopy(mxModel);
uno::Reference<frame::XModel> xModel = openNewDoc(aCurrSheetName);
if (xModel.is())
{
excel::implnPaste(xModel);
Delete();
}
return ;
}
uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( getModel(), uno::UNO_QUERY_THROW );
SCTAB nDest = 0;
if ( ScVbaWorksheets::nameExists (xSpreadDoc, xSheet->getName(), nDest) )
{
bool bAfter = After.hasValue();
if (bAfter)
nDest++;
uno::Reference<sheet::XSpreadsheets> xSheets = xSpreadDoc->getSheets();
xSheets->moveByName(aCurrSheetName,nDest);
}
}
void
ScVbaWorksheet::Copy( const uno::Any& Before, const uno::Any& After )
{
uno::Reference<excel::XWorksheet> xSheet;
if (!(Before >>= xSheet) && !(After >>=xSheet)&& !(Before.hasValue()) && !(After.hasValue()))
{
createSheetCopyInNewDoc(getName());
return;
}
uno::Reference<excel::XWorksheet> xNewSheet = createSheetCopy(xSheet, After.hasValue());
xNewSheet->Activate();
}
void
ScVbaWorksheet::Paste( const uno::Any& Destination, const uno::Any& /*Link*/ )
{
// #TODO# #FIXME# Link is not used
uno::Reference<excel::XRange> xRange( Destination, uno::UNO_QUERY );
if ( xRange.is() )
xRange->Select();
excel::implnPaste( mxModel );
}
void
ScVbaWorksheet::Delete()
{
uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( getModel(), uno::UNO_QUERY_THROW );
OUString aSheetName = getName();
SCTAB nTab = 0;
if (!ScVbaWorksheets::nameExists(xSpreadDoc, aSheetName, nTab ))
{
return;
}
uno::Reference<sheet::XSpreadsheets> xSheets = xSpreadDoc->getSheets();
uno::Reference<container::XNameContainer> xNameContainer(xSheets,uno::UNO_QUERY_THROW);
xNameContainer->removeByName(aSheetName);
mxSheet.clear();
}
uno::Reference< excel::XWorksheet >
ScVbaWorksheet::getSheetAtOffset(SCTAB offset)
{
uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( getModel(), uno::UNO_QUERY_THROW );
uno::Reference <sheet::XSpreadsheets> xSheets( xSpreadDoc->getSheets(), uno::UNO_SET_THROW );
uno::Reference <container::XIndexAccess> xIndex( xSheets, uno::UNO_QUERY_THROW );
SCTAB nIdx = 0;
if ( !ScVbaWorksheets::nameExists (xSpreadDoc, getName(), nIdx ) )
return uno::Reference< excel::XWorksheet >();
nIdx = nIdx + offset;
uno::Reference< sheet::XSpreadsheet > xSheet(xIndex->getByIndex(nIdx), uno::UNO_QUERY_THROW);
// parent will be the parent of 'this' worksheet
return new ScVbaWorksheet (getParent(), mxContext, xSheet, getModel());
}
uno::Reference< excel::XWorksheet >
ScVbaWorksheet::getNext()
{
return getSheetAtOffset(static_cast<SCTAB>(1));
}
uno::Reference< excel::XWorksheet >
ScVbaWorksheet::getPrevious()
{
return getSheetAtOffset(-1);
}
void
ScVbaWorksheet::Protect( const uno::Any& Password, const uno::Any& /*DrawingObjects*/, const uno::Any& /*Contents*/, const uno::Any& /*Scenarios*/, const uno::Any& /*UserInterfaceOnly*/ )
{
// #TODO# #FIXME# is there anything we can do with the unused param
// can the implementation use anything else here
uno::Reference<util::XProtectable > xProtectable(getSheet(), uno::UNO_QUERY_THROW);
OUString aPasswd;
Password >>= aPasswd;
xProtectable->protect( aPasswd );
}
void
ScVbaWorksheet::Unprotect( const uno::Any& Password )
{
uno::Reference<util::XProtectable > xProtectable(getSheet(), uno::UNO_QUERY_THROW);
OUString aPasswd;
Password >>= aPasswd;
xProtectable->unprotect( aPasswd );
}
void
ScVbaWorksheet::Calculate()
{
uno::Reference <sheet::XCalculatable> xReCalculate(getModel(), uno::UNO_QUERY_THROW);
xReCalculate->calculate();
}
uno::Reference< excel::XRange >
ScVbaWorksheet::Range( const ::uno::Any& Cell1, const ::uno::Any& Cell2 )
{
uno::Reference< excel::XRange > xSheetRange( new ScVbaRange( this, mxContext
, uno::Reference< table::XCellRange >( getSheet(), uno::UNO_QUERY_THROW ) ) );
return xSheetRange->Range( Cell1, Cell2 );
}
void
ScVbaWorksheet::CheckSpelling( const uno::Any& /*CustomDictionary*/,const uno::Any& /*IgnoreUppercase*/,const uno::Any& /*AlwaysSuggest*/, const uno::Any& /*SpellingLang*/ )
{
// #TODO# #FIXME# unused params above, can we do anything with those
uno::Reference< frame::XModel > xModel( getModel() );
dispatchRequests(xModel,u".uno:SpellDialog"_ustr);
}
uno::Reference< excel::XRange >
ScVbaWorksheet::getSheetRange()
{
uno::Reference< table::XCellRange > xRange( getSheet(),uno::UNO_QUERY_THROW );
return uno::Reference< excel::XRange >( new ScVbaRange( this, mxContext, xRange ) );
}
// These are hacks - we prolly (somehow) need to inherit
// the vbarange functionality here ...
uno::Reference< excel::XRange >
ScVbaWorksheet::Cells( const ::uno::Any &nRow, const ::uno::Any &nCol )
{
// Performance optimization for often-called Cells method:
// Use a common helper method instead of creating a new ScVbaRange object
uno::Reference< table::XCellRange > xRange( getSheet(), uno::UNO_QUERY_THROW );
uno::Reference< frame::XModel > xModel( getModel(), uno::UNO_SET_THROW );
if(ScDocShell* pShell = excel::getDocShell( xModel ))
return ScVbaRange::CellsHelper(pShell->GetDocument(), this, mxContext, xRange, nRow, nCol );
throw uno::RuntimeException();
}
uno::Reference< excel::XRange >
ScVbaWorksheet::Rows(const uno::Any& aIndex )
{
return getSheetRange()->Rows( aIndex );
}
uno::Reference< excel::XRange >
ScVbaWorksheet::Columns( const uno::Any& aIndex )
{
return getSheetRange()->Columns( aIndex );
}
uno::Any SAL_CALL
ScVbaWorksheet::ChartObjects( const uno::Any& Index )
{
if ( !mxCharts.is() )
{
uno::Reference< table::XTableChartsSupplier > xChartSupplier( getSheet(), uno::UNO_QUERY_THROW );
uno::Reference< table::XTableCharts > xTableCharts = xChartSupplier->getCharts();
uno::Reference< drawing::XDrawPageSupplier > xDrawPageSupplier( mxSheet, uno::UNO_QUERY_THROW );
mxCharts = new ScVbaChartObjects( this, mxContext, xTableCharts, xDrawPageSupplier );
}
if ( Index.hasValue() )
{
return mxCharts->Item( Index, uno::Any() );
}
else
return uno::Any( uno::Reference<ov::excel::XChartObjects>(mxCharts) );
}
uno::Any SAL_CALL
ScVbaWorksheet::PivotTables( const uno::Any& Index )
{
uno::Reference< css::sheet::XSpreadsheet > xSheet = getSheet();
uno::Reference< sheet::XDataPilotTablesSupplier > xTables(xSheet, uno::UNO_QUERY_THROW ) ;
uno::Reference< container::XIndexAccess > xIndexAccess( xTables->getDataPilotTables(), uno::UNO_QUERY_THROW );
uno::Reference< XCollection > xColl( new ScVbaPivotTables( this, mxContext, xIndexAccess ) );
if ( Index.hasValue() )
return xColl->Item( Index, uno::Any() );
return uno::Any( xColl );
}
uno::Any SAL_CALL
ScVbaWorksheet::Comments( const uno::Any& Index )
{
uno::Reference< css::sheet::XSpreadsheet > xSheet = getSheet();
uno::Reference< sheet::XSheetAnnotationsSupplier > xAnnosSupp( xSheet, uno::UNO_QUERY_THROW );
uno::Reference< sheet::XSheetAnnotations > xAnnos( xAnnosSupp->getAnnotations(), uno::UNO_SET_THROW );
uno::Reference< container::XIndexAccess > xIndexAccess( xAnnos, uno::UNO_QUERY_THROW );
uno::Reference< XCollection > xColl( new ScVbaComments( this, mxContext, mxModel, xIndexAccess ) );
if ( Index.hasValue() )
return xColl->Item( Index, uno::Any() );
return uno::Any( xColl );
}
uno::Any SAL_CALL
ScVbaWorksheet::Hyperlinks( const uno::Any& aIndex )
{
/* The worksheet always returns the same Hyperlinks object.
See vbahyperlinks.hxx for more details. */
if( !mxHlinks.is() )
mxHlinks.set( new ScVbaHyperlinks( this, mxContext ) );
if( aIndex.hasValue() )
return uno::Reference< XCollection >( mxHlinks, uno::UNO_QUERY_THROW )->Item( aIndex, uno::Any() );
return uno::Any( mxHlinks );
}
uno::Any SAL_CALL
ScVbaWorksheet::Names( const css::uno::Any& aIndex )
{
css::uno::Reference<css::beans::XPropertySet> xProps(getSheet(), css::uno::UNO_QUERY_THROW);
uno::Reference< sheet::XNamedRanges > xNamedRanges( xProps->getPropertyValue(u"NamedRanges"_ustr), uno::UNO_QUERY_THROW );
uno::Reference< XCollection > xNames( new ScVbaNames( this, mxContext, xNamedRanges, mxModel ) );
if ( aIndex.hasValue() )
return xNames->Item( aIndex, uno::Any() );
return uno::Any( xNames );
}
uno::Any SAL_CALL
ScVbaWorksheet::OLEObjects( const uno::Any& Index )
{
uno::Reference< sheet::XSpreadsheet > xSpreadsheet( getSheet(), uno::UNO_SET_THROW );
uno::Reference< drawing::XDrawPageSupplier > xDrawPageSupplier( xSpreadsheet, uno::UNO_QUERY_THROW );
uno::Reference< drawing::XDrawPage > xDrawPage( xDrawPageSupplier->getDrawPage(), uno::UNO_SET_THROW );
uno::Reference< container::XIndexAccess > xIndexAccess( xDrawPage, uno::UNO_QUERY_THROW );
uno::Reference< excel::XOLEObjects >xOleObjects( new ScVbaOLEObjects( this, mxContext, xIndexAccess ) );
if( Index.hasValue() )
return xOleObjects->Item( Index, uno::Any() );
return uno::Any( xOleObjects );
}
uno::Any SAL_CALL
ScVbaWorksheet::Shapes( const uno::Any& aIndex )
{
uno::Reference< sheet::XSpreadsheet > xSpreadsheet( getSheet(), uno::UNO_SET_THROW );
uno::Reference< drawing::XDrawPageSupplier > xDrawPageSupplier( xSpreadsheet, uno::UNO_QUERY_THROW );
uno::Reference< drawing::XShapes > xShapes( xDrawPageSupplier->getDrawPage(), uno::UNO_QUERY_THROW );
uno::Reference< container::XIndexAccess > xIndexAccess( xShapes, uno::UNO_QUERY_THROW );
uno::Reference< msforms::XShapes> xVbaShapes( new ScVbaShapes( this, mxContext, xIndexAccess, getModel() ) );
if ( aIndex.hasValue() )
return xVbaShapes->Item( aIndex, uno::Any() );
return uno::Any( xVbaShapes );
}
uno::Any
ScVbaWorksheet::getButtons( const uno::Any &rIndex, bool bOptionButtons )
{
::rtl::Reference< ScVbaSheetObjectsBase > &rxButtons = bOptionButtons ? mxButtons[0] : mxButtons[1];
if( !rxButtons.is() )
rxButtons.set( new ScVbaButtons( this, mxContext, mxModel, mxSheet, bOptionButtons ) );
else
rxButtons->collectShapes();
if( rIndex.hasValue() )
return rxButtons->Item( rIndex, uno::Any() );
return uno::Any( uno::Reference< XCollection >( rxButtons ) );
}
uno::Any SAL_CALL
ScVbaWorksheet::Buttons( const uno::Any& rIndex )
{
return getButtons( rIndex, false );
}
uno::Any SAL_CALL
ScVbaWorksheet::CheckBoxes( const uno::Any& /*rIndex*/ )
{
throw uno::RuntimeException();
}
uno::Any SAL_CALL
ScVbaWorksheet::DropDowns( const uno::Any& /*rIndex*/ )
{
throw uno::RuntimeException();
}
uno::Any SAL_CALL
ScVbaWorksheet::GroupBoxes( const uno::Any& /*rIndex*/ )
{
throw uno::RuntimeException();
}
uno::Any SAL_CALL
ScVbaWorksheet::Labels( const uno::Any& /*rIndex*/ )
{
throw uno::RuntimeException();
}
uno::Any SAL_CALL
ScVbaWorksheet::ListBoxes( const uno::Any& /*rIndex*/ )
{
throw uno::RuntimeException();
}
uno::Any SAL_CALL
ScVbaWorksheet::OptionButtons( const uno::Any& rIndex )
{
return getButtons( rIndex, true );
}
uno::Any SAL_CALL
ScVbaWorksheet::ScrollBars( const uno::Any& /*rIndex*/ )
{
throw uno::RuntimeException();
}
uno::Any SAL_CALL
ScVbaWorksheet::Spinners( const uno::Any& /*rIndex*/ )
{
throw uno::RuntimeException();
}
void SAL_CALL
ScVbaWorksheet::ShowDataForm( )
{
uno::Reference< frame::XModel > xModel( getModel(), uno::UNO_SET_THROW );
if (ScTabViewShell* pTabViewShell = excel::getBestViewShell( xModel ))
{
ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
ScopedVclPtr<AbstractScDataFormDlg> pDlg(pFact->CreateScDataFormDlg(pTabViewShell->GetFrameWeld(),
pTabViewShell));
pDlg->Execute();
}
}
uno::Any SAL_CALL
ScVbaWorksheet::Evaluate( const OUString& Name )
{
// #TODO Evaluate allows other things to be evaluated, e.g. functions
// I think ( like SIN(3) etc. ) need to investigate that
// named Ranges also? e.g. [MyRange] if so need a list of named ranges
uno::Any aVoid;
return uno::Any( Range( uno::Any( Name ), aVoid ) );
}
uno::Reference< beans::XIntrospectionAccess > SAL_CALL
ScVbaWorksheet::getIntrospection( )
{
return uno::Reference< beans::XIntrospectionAccess >();
}
uno::Any SAL_CALL
ScVbaWorksheet::invoke( const OUString& /*aFunctionName*/, const uno::Sequence< uno::Any >& /*aParams*/, uno::Sequence< ::sal_Int16 >& /*aOutParamIndex*/, uno::Sequence< uno::Any >& /*aOutParam*/ )
{
throw uno::RuntimeException(u"Unsupported"_ustr); // unsupported operation
}
void SAL_CALL
ScVbaWorksheet::setValue( const OUString& aPropertyName, const uno::Any& aValue )
{
setDefaultPropByIntrospection( getValue( aPropertyName ), aValue );
}
uno::Any SAL_CALL
ScVbaWorksheet::getValue( const OUString& aPropertyName )
{
uno::Reference< drawing::XControlShape > xControlShape( getControlShape( aPropertyName ), uno::UNO_QUERY_THROW );
uno::Reference<lang::XMultiComponentFactory > xServiceManager( mxContext->getServiceManager(), uno::UNO_SET_THROW );
uno::Reference< XControlProvider > xControlProvider( xServiceManager->createInstanceWithContext(u"ooo.vba.ControlProvider"_ustr, mxContext ), uno::UNO_QUERY_THROW );
uno::Reference< msforms::XControl > xControl( xControlProvider->createControl( xControlShape, getModel() ) );
return uno::Any( xControl );
}
sal_Bool SAL_CALL
ScVbaWorksheet::hasMethod( const OUString& /*aName*/ )
{
return false;
}
uno::Reference< container::XNameAccess >
ScVbaWorksheet::getFormControls() const
{
uno::Reference< container::XNameAccess > xFormControls;
try
{
uno::Reference< sheet::XSpreadsheet > xSpreadsheet( getSheet(), uno::UNO_SET_THROW );
uno::Reference< drawing::XDrawPageSupplier > xDrawPageSupplier( xSpreadsheet, uno::UNO_QUERY_THROW );
uno::Reference< form::XFormsSupplier > xFormSupplier( xDrawPageSupplier->getDrawPage(), uno::UNO_QUERY_THROW );
uno::Reference< container::XIndexAccess > xIndexAccess( xFormSupplier->getForms(), uno::UNO_QUERY_THROW );
// get the www-standard container ( maybe we should access the
// 'www-standard' by name rather than index, this seems an
// implementation detail
if( xIndexAccess->hasElements() )
xFormControls.set( xIndexAccess->getByIndex(0), uno::UNO_QUERY );
}
catch( uno::Exception& )
{
}
return xFormControls;
}
sal_Bool SAL_CALL
ScVbaWorksheet::hasProperty( const OUString& aName )
{
uno::Reference< container::XNameAccess > xFormControls( getFormControls() );
if ( xFormControls.is() )
return xFormControls->hasByName( aName );
return false;
}
uno::Any
ScVbaWorksheet::getControlShape( std::u16string_view sName )
{
// ideally we would get an XControl object but it appears an XControl
// implementation only exists for a Control implementation obtained from the
// view ( e.g. in basic you would get this from
// thiscomponent.currentcontroller.getControl( controlModel ) )
// and the thing to realise is that it is only possible to get an XControl
// for a currently displayed control :-( often we would want to modify
// a control not on the active sheet. But... you can always access the
// XControlShape from the DrawPage whether that is the active drawpage or not
uno::Reference< drawing::XDrawPageSupplier > xDrawPageSupplier( getSheet(), uno::UNO_QUERY_THROW );
uno::Reference< container::XIndexAccess > xIndexAccess( xDrawPageSupplier->getDrawPage(), uno::UNO_QUERY_THROW );
sal_Int32 nCount = xIndexAccess->getCount();
for( int index = 0; index < nCount; index++ )
{
uno::Any aUnoObj = xIndexAccess->getByIndex( index );
// It seems there are some drawing objects that can not query into Control shapes?
uno::Reference< drawing::XControlShape > xControlShape( aUnoObj, uno::UNO_QUERY );
if( xControlShape.is() )
{
uno::Reference< container::XNamed > xNamed( xControlShape->getControl(), uno::UNO_QUERY_THROW );
if( sName == xNamed->getName() )
{
return aUnoObj;
}
}
}
return uno::Any();
}
OUString
ScVbaWorksheet::getServiceImplName()
{
return u"ScVbaWorksheet"_ustr;
}
void SAL_CALL
ScVbaWorksheet::setEnableCalculation( sal_Bool bEnableCalculation )
{
uno::Reference <sheet::XCalculatable> xCalculatable(getModel(), uno::UNO_QUERY_THROW);
xCalculatable->enableAutomaticCalculation( bEnableCalculation);
}
sal_Bool SAL_CALL
ScVbaWorksheet::getEnableCalculation( )
{
uno::Reference <sheet::XCalculatable> xCalculatable(getModel(), uno::UNO_QUERY_THROW);
return xCalculatable->isAutomaticCalculationEnabled();
}
uno::Sequence< OUString >
ScVbaWorksheet::getServiceNames()
{
static uno::Sequence< OUString > const aServiceNames
{
u"ooo.vba.excel.Worksheet"_ustr
};
return aServiceNames;
}
OUString SAL_CALL
ScVbaWorksheet::getCodeName()
{
uno::Reference< beans::XPropertySet > xSheetProp( mxSheet, uno::UNO_QUERY_THROW );
return xSheetProp->getPropertyValue(u"CodeName"_ustr).get< OUString >();
}
sal_Int16
ScVbaWorksheet::getSheetID() const
{
uno::Reference< sheet::XCellRangeAddressable > xAddressable( mxSheet, uno::UNO_QUERY_THROW ); // if ActiveSheet, mxSheet is null.
return xAddressable->getRangeAddress().Sheet;
}
void SAL_CALL
ScVbaWorksheet::PrintOut( const uno::Any& From, const uno::Any& To, const uno::Any& Copies, const uno::Any& Preview, const uno::Any& ActivePrinter, const uno::Any& PrintToFile, const uno::Any& Collate, const uno::Any& PrToFileName, const uno::Any& )
{
sal_Int32 nTo = 0;
sal_Int32 nFrom = 0;
bool bSelection = false;
From >>= nFrom;
To >>= nTo;
if ( !( nFrom || nTo ) )
bSelection = true;
uno::Reference< frame::XModel > xModel( getModel(), uno::UNO_SET_THROW );
PrintOutHelper( excel::getBestViewShell( xModel ), From, To, Copies, Preview, ActivePrinter, PrintToFile, Collate, PrToFileName, bSelection );
}
void SAL_CALL
ScVbaWorksheet::ExportAsFixedFormat(const css::uno::Any& Type, const css::uno::Any& FileName, const css::uno::Any& Quality,
const css::uno::Any& IncludeDocProperties, const css::uno::Any& /*IgnorePrintAreas*/, const css::uno::Any& From,
const css::uno::Any& To, const css::uno::Any& OpenAfterPublish, const css::uno::Any& /*FixedFormatExtClassPtr*/)
{
uno::Reference< frame::XModel > xModel(getModel(), uno::UNO_SET_THROW);
uno::Reference< excel::XApplication > xApplication(Application(), uno::UNO_QUERY_THROW);
excel::ExportAsFixedFormatHelper(xModel, xApplication, Type, FileName, Quality,
IncludeDocProperties, From, To, OpenAfterPublish);
}
sal_Int64 SAL_CALL
ScVbaWorksheet::getSomething(const uno::Sequence<sal_Int8 > & rId)
{
return comphelper::getSomethingImpl(rId, this);
}
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
Calc_ScVbaWorksheet_get_implementation(
css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& args)
{
return cppu::acquire(new ScVbaWorksheet(args, context));
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V547 Expression 'bVisible' is always false.
↑ V1019 Compound assignment expression 'After >>= xSheet' is used inside condition.
↑ V1019 Compound assignment expression 'After >>= xSheet' is used inside condition.
↑ V1048 The 'bVisible' variable was assigned the same value.