summaryrefslogtreecommitdiff
path: root/sc/source/ui/vba/excelvbahelper.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/ui/vba/excelvbahelper.cxx')
-rw-r--r--sc/source/ui/vba/excelvbahelper.cxx473
1 files changed, 473 insertions, 0 deletions
diff --git a/sc/source/ui/vba/excelvbahelper.cxx b/sc/source/ui/vba/excelvbahelper.cxx
new file mode 100644
index 000000000000..4f49aab539c4
--- /dev/null
+++ b/sc/source/ui/vba/excelvbahelper.cxx
@@ -0,0 +1,473 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "excelvbahelper.hxx"
+
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/sheet/XSheetCellRange.hpp>
+#include "docuno.hxx"
+#include "tabvwsh.hxx"
+#include "transobj.hxx"
+#include "scmod.hxx"
+#include "cellsuno.hxx"
+#include "compiler.hxx"
+#include "token.hxx"
+#include "tokenarray.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::ooo::vba;
+
+namespace ooo {
+namespace vba {
+namespace excel {
+
+// ============================================================================
+
+uno::Reference< sheet::XDatabaseRanges >
+GetDataBaseRanges( ScDocShell* pShell ) throw ( uno::RuntimeException )
+{
+ uno::Reference< frame::XModel > xModel;
+ if ( pShell )
+ xModel.set( pShell->GetModel(), uno::UNO_QUERY_THROW );
+ uno::Reference< beans::XPropertySet > xModelProps( xModel, uno::UNO_QUERY_THROW );
+ uno::Reference< sheet::XDatabaseRanges > xDBRanges( xModelProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DatabaseRanges") ) ), uno::UNO_QUERY_THROW );
+ return xDBRanges;
+}
+
+// returns the XDatabaseRange for the autofilter on sheet (nSheet)
+// also populates sName with the name of range
+uno::Reference< sheet::XDatabaseRange >
+GetAutoFiltRange( ScDocShell* pShell, sal_Int16 nSheet, rtl::OUString& sName ) throw ( uno::RuntimeException )
+{
+ uno::Reference< container::XIndexAccess > xIndexAccess( GetDataBaseRanges( pShell ), uno::UNO_QUERY_THROW );
+ uno::Reference< sheet::XDatabaseRange > xDataBaseRange;
+ table::CellRangeAddress dbAddress;
+ for ( sal_Int32 index=0; index < xIndexAccess->getCount(); ++index )
+ {
+ uno::Reference< sheet::XDatabaseRange > xDBRange( xIndexAccess->getByIndex( index ), uno::UNO_QUERY_THROW );
+ uno::Reference< container::XNamed > xNamed( xDBRange, uno::UNO_QUERY_THROW );
+ // autofilters work weirdly with openoffice, unnamed is the default
+ // named range which is used to create an autofilter, but
+ // its also possible that another name could be used
+ // this also causes problems when an autofilter is created on
+ // another sheet
+ // ( but.. you can use any named range )
+ dbAddress = xDBRange->getDataArea();
+ if ( dbAddress.Sheet == nSheet )
+ {
+ sal_Bool bHasAuto = false;
+ uno::Reference< beans::XPropertySet > xProps( xDBRange, uno::UNO_QUERY_THROW );
+ xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("AutoFilter") ) ) >>= bHasAuto;
+ if ( bHasAuto )
+ {
+ sName = xNamed->getName();
+ xDataBaseRange=xDBRange;
+ break;
+ }
+ }
+ }
+ return xDataBaseRange;
+}
+
+ScDocShell* GetDocShellFromRange( const uno::Reference< uno::XInterface >& xRange ) throw ( uno::RuntimeException )
+{
+ ScCellRangesBase* pScCellRangesBase = ScCellRangesBase::getImplementation( xRange );
+ if ( !pScCellRangesBase )
+ {
+ throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Failed to access underlying doc shell uno range object" ) ), uno::Reference< uno::XInterface >() );
+ }
+ return pScCellRangesBase->GetDocShell();
+}
+
+uno::Reference< XHelperInterface >
+getUnoSheetModuleObj( const uno::Reference< table::XCellRange >& xRange ) throw ( uno::RuntimeException )
+{
+ uno::Reference< sheet::XSheetCellRange > xSheetRange( xRange, uno::UNO_QUERY_THROW );
+ uno::Reference< sheet::XSpreadsheet > xSheet( xSheetRange->getSpreadsheet(), uno::UNO_SET_THROW );
+ return getUnoSheetModuleObj( xSheet );
+}
+
+ScDocShell* GetDocShellFromRanges( const uno::Reference< sheet::XSheetCellRangeContainer >& xRanges ) throw ( uno::RuntimeException )
+{
+ // need the ScCellRangesBase to get docshell
+ uno::Reference< uno::XInterface > xIf( xRanges, uno::UNO_QUERY_THROW );
+ return GetDocShellFromRange( xIf );
+}
+
+ScDocument* GetDocumentFromRange( const uno::Reference< uno::XInterface >& xRange ) throw ( uno::RuntimeException )
+{
+ ScDocShell* pDocShell = GetDocShellFromRange( xRange );
+ if ( !pDocShell )
+ {
+ throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Failed to access underlying document from uno range object" ) ), uno::Reference< uno::XInterface >() );
+ }
+ return pDocShell->GetDocument();
+}
+
+uno::Reference< frame::XModel > GetModelFromRange( const uno::Reference< uno::XInterface >& xRange ) throw ( uno::RuntimeException )
+{
+ ScDocShell* pDocShell = GetDocShellFromRange( xRange );
+ if ( !pDocShell )
+ {
+ throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Failed to access underlying model uno range object" ) ), uno::Reference< uno::XInterface >() );
+ }
+ return pDocShell->GetModel();
+}
+
+void implSetZoom( const uno::Reference< frame::XModel >& xModel, sal_Int16 nZoom, std::vector< SCTAB >& nTabs )
+{
+ ScTabViewShell* pViewSh = excel::getBestViewShell( xModel );
+ Fraction aFract( nZoom, 100 );
+ pViewSh->GetViewData()->SetZoom( aFract, aFract, nTabs );
+ pViewSh->RefreshZoom();
+}
+bool isInPrintPreview( SfxViewFrame* pView )
+{
+ sal_uInt16 nViewNo = SID_VIEWSHELL1 - SID_VIEWSHELL0;
+ if ( pView->GetObjectShell()->GetFactory().GetViewFactoryCount() >
+nViewNo && !pView->GetObjectShell()->IsInPlaceActive() )
+ {
+ SfxViewFactory &rViewFactory =
+ pView->GetObjectShell()->GetFactory().GetViewFactory(nViewNo);
+ if ( pView->GetCurViewId() == rViewFactory.GetOrdinal() )
+ return true;
+ }
+ return false;
+}
+
+const ::rtl::OUString REPLACE_CELLS_WARNING( RTL_CONSTASCII_USTRINGPARAM( "ReplaceCellsWarning"));
+
+class PasteCellsWarningReseter
+{
+private:
+ bool bInitialWarningState;
+ static uno::Reference< beans::XPropertySet > getGlobalSheetSettings() throw ( uno::RuntimeException )
+ {
+ static uno::Reference< beans::XPropertySet > xTmpProps( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW );
+ static uno::Reference<uno::XComponentContext > xContext( xTmpProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))), uno::UNO_QUERY_THROW );
+ static uno::Reference<lang::XMultiComponentFactory > xServiceManager(
+ xContext->getServiceManager(), uno::UNO_QUERY_THROW );
+ static uno::Reference< beans::XPropertySet > xProps( xServiceManager->createInstanceWithContext( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.GlobalSheetSettings" ) ) ,xContext ), uno::UNO_QUERY_THROW );
+ return xProps;
+ }
+
+ bool getReplaceCellsWarning() throw ( uno::RuntimeException )
+ {
+ sal_Bool res = false;
+ getGlobalSheetSettings()->getPropertyValue( REPLACE_CELLS_WARNING ) >>= res;
+ return ( res == sal_True );
+ }
+
+ void setReplaceCellsWarning( bool bState ) throw ( uno::RuntimeException )
+ {
+ getGlobalSheetSettings()->setPropertyValue( REPLACE_CELLS_WARNING, uno::makeAny( bState ) );
+ }
+public:
+ PasteCellsWarningReseter() throw ( uno::RuntimeException )
+ {
+ bInitialWarningState = getReplaceCellsWarning();
+ if ( bInitialWarningState )
+ setReplaceCellsWarning( false );
+ }
+ ~PasteCellsWarningReseter()
+ {
+ if ( bInitialWarningState )
+ {
+ // don't allow dtor to throw
+ try
+ {
+ setReplaceCellsWarning( true );
+ }
+ catch ( uno::Exception& /*e*/ ){}
+ }
+ }
+};
+
+void
+implnPaste( const uno::Reference< frame::XModel>& xModel )
+{
+ PasteCellsWarningReseter resetWarningBox;
+ ScTabViewShell* pViewShell = getBestViewShell( xModel );
+ if ( pViewShell )
+ {
+ pViewShell->PasteFromSystem();
+ pViewShell->CellContentChanged();
+ }
+}
+
+
+void
+implnCopy( const uno::Reference< frame::XModel>& xModel )
+{
+ ScTabViewShell* pViewShell = getBestViewShell( xModel );
+ if ( pViewShell )
+ {
+ pViewShell->CopyToClip(NULL,false,false,true);
+
+ // mark the copied transfer object so it is used in ScVbaRange::Insert
+ ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard( NULL );
+ if (pClipObj)
+ pClipObj->SetUseInApi( true );
+ }
+}
+
+void
+implnCut( const uno::Reference< frame::XModel>& xModel )
+{
+ ScTabViewShell* pViewShell = getBestViewShell( xModel );
+ if ( pViewShell )
+ {
+ pViewShell->CutToClip( NULL, sal_True );
+
+ // mark the copied transfer object so it is used in ScVbaRange::Insert
+ ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard( NULL );
+ if (pClipObj)
+ pClipObj->SetUseInApi( true );
+ }
+}
+
+void implnPasteSpecial( const uno::Reference< frame::XModel>& xModel, sal_uInt16 nFlags,sal_uInt16 nFunction,sal_Bool bSkipEmpty, sal_Bool bTranspose)
+{
+ PasteCellsWarningReseter resetWarningBox;
+ sal_Bool bAsLink(false), bOtherDoc(false);
+ InsCellCmd eMoveMode = INS_NONE;
+
+ ScTabViewShell* pTabViewShell = getBestViewShell( xModel );
+ if ( pTabViewShell )
+ {
+ ScViewData* pView = pTabViewShell->GetViewData();
+ Window* pWin = ( pView != NULL ) ? pView->GetActiveWin() : NULL;
+ if ( pView && pWin )
+ {
+ if ( bAsLink && bOtherDoc )
+ pTabViewShell->PasteFromSystem(0);//SOT_FORMATSTR_ID_LINK
+ else
+ {
+ ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
+ ScDocument* pDoc = NULL;
+ if ( pOwnClip )
+ pDoc = pOwnClip->GetDocument();
+ pTabViewShell->PasteFromClip( nFlags, pDoc,
+ nFunction, bSkipEmpty, bTranspose, bAsLink,
+ eMoveMode, IDF_NONE, sal_True );
+ pTabViewShell->CellContentChanged();
+ }
+ }
+ }
+
+}
+
+void implnCopyRange( const uno::Reference< frame::XModel>& xModel, const ScRange& rRange )
+{
+ ScTabViewShell* pViewShell = getBestViewShell( xModel );
+ if ( pViewShell )
+ {
+ pViewShell->CopyToClip( NULL, rRange, false, true, true );
+ }
+}
+
+ScDocShell*
+getDocShell( const css::uno::Reference< css::frame::XModel>& xModel )
+{
+ uno::Reference< uno::XInterface > xIf( xModel, uno::UNO_QUERY_THROW );
+ ScModelObj* pModel = dynamic_cast< ScModelObj* >( xIf.get() );
+ ScDocShell* pDocShell = NULL;
+ if ( pModel )
+ pDocShell = (ScDocShell*)pModel->GetEmbeddedObject();
+ return pDocShell;
+
+}
+
+ScTabViewShell*
+getBestViewShell( const css::uno::Reference< css::frame::XModel>& xModel )
+{
+ ScDocShell* pDocShell = getDocShell( xModel );
+ if ( pDocShell )
+ return pDocShell->GetBestViewShell();
+ return NULL;
+}
+
+ScTabViewShell*
+getCurrentBestViewShell( const uno::Reference< uno::XComponentContext >& xContext )
+{
+ uno::Reference< frame::XModel > xModel = getCurrentExcelDoc( xContext );
+ return getBestViewShell( xModel );
+}
+
+SfxViewFrame*
+getViewFrame( const uno::Reference< frame::XModel >& xModel )
+{
+ ScTabViewShell* pViewShell = getBestViewShell( xModel );
+ if ( pViewShell )
+ return pViewShell->GetViewFrame();
+ return NULL;
+}
+
+sal_Bool IsR1C1ReferFormat( ScDocument* pDoc, const rtl::OUString& sRangeStr )
+{
+ ScRangeList aCellRanges;
+ String sAddress( sRangeStr );
+ sal_uInt16 nMask = SCA_VALID;
+ sal_uInt16 rResFlags = aCellRanges.Parse( sAddress, pDoc, nMask, formula::FormulaGrammar::CONV_XL_R1C1 );
+ if ( rResFlags & SCA_VALID )
+ {
+ return sal_True;
+ }
+ return false;
+}
+
+uno::Reference< vba::XHelperInterface >
+getUnoSheetModuleObj( const uno::Reference< sheet::XSpreadsheet >& xSheet ) throw ( uno::RuntimeException )
+{
+ uno::Reference< beans::XPropertySet > xProps( xSheet, uno::UNO_QUERY_THROW );
+ rtl::OUString sCodeName;
+ xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("CodeName") ) ) >>= sCodeName;
+ // #TODO #FIXME ideally we should 'throw' here if we don't get a valid parent, but... it is possible
+ // to create a module ( and use 'Option VBASupport 1' ) for a calc document, in this scenario there
+ // are *NO* special document module objects ( of course being able to switch between vba/non vba mode at
+ // the document in the future could fix this, especially IF the switching of the vba mode takes care to
+ // create the special document module objects if they don't exist.
+ uno::Reference< XHelperInterface > xParent( ov::getUnoDocModule( sCodeName, GetDocShellFromRange( xSheet ) ), uno::UNO_QUERY );
+ return xParent;
+}
+
+formula::FormulaGrammar::Grammar GetFormulaGrammar( ScDocument* pDoc, const ScAddress& sAddress, const css::uno::Any& aFormula )
+{
+ formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_NATIVE_XL_A1;
+ if ( pDoc && aFormula.hasValue() && aFormula.getValueTypeClass() == uno::TypeClass_STRING )
+ {
+ rtl::OUString sFormula;
+ aFormula >>= sFormula;
+
+ ScCompiler aCompiler( pDoc, sAddress );
+ aCompiler.SetGrammar( formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1 );
+ ScTokenArray* pCode = aCompiler.CompileString( sFormula );
+ if ( pCode )
+ {
+ sal_uInt16 nLen = pCode->GetLen();
+ formula::FormulaToken** pTokens = pCode->GetArray();
+ for ( sal_uInt16 nPos = 0; nPos < nLen; nPos++ )
+ {
+ const formula::FormulaToken& rToken = *pTokens[nPos];
+ switch ( rToken.GetType() )
+ {
+ case formula::svSingleRef:
+ case formula::svDoubleRef:
+ {
+ return formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1;
+ }
+ break;
+ default: break;
+ }
+ }
+ }
+ }
+ return eGrammar;
+}
+
+void CompileExcelFormulaToODF( ScDocument* pDoc, const String& rOldFormula, String& rNewFormula )
+{
+ if ( !pDoc )
+ {
+ return;
+ }
+ ScCompiler aCompiler( pDoc, ScAddress() );
+ aCompiler.SetGrammar( excel::GetFormulaGrammar( pDoc, ScAddress(), uno::Any( rtl::OUString( rOldFormula ) ) ) );
+ aCompiler.CompileString( rOldFormula );
+ aCompiler.SetGrammar( formula::FormulaGrammar::GRAM_PODF_A1 );
+ aCompiler.CreateStringFromTokenArray( rNewFormula );
+}
+
+void CompileODFFormulaToExcel( ScDocument* pDoc, const String& rOldFormula, String& rNewFormula, const formula::FormulaGrammar::Grammar eGrammar )
+{
+ // eGrammar can be formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1 and formula::FormulaGrammar::GRAM_NATIVE_XL_A1
+ if ( !pDoc )
+ {
+ return;
+ }
+ ScCompiler aCompiler( pDoc, ScAddress() );
+ aCompiler.SetGrammar( formula::FormulaGrammar::GRAM_PODF_A1 );
+ ScTokenArray* pCode = aCompiler.CompileString( rOldFormula );
+ aCompiler.SetGrammar( eGrammar );
+ if ( !pCode )
+ {
+ return;
+ }
+ sal_uInt16 nLen = pCode->GetLen();
+ formula::FormulaToken** pTokens = pCode->GetArray();
+ for ( sal_uInt16 nPos = 0; nPos < nLen && pTokens[nPos]; nPos++ )
+ {
+ String rFormula;
+ formula::FormulaToken* pToken = pTokens[nPos];
+ aCompiler.CreateStringFromToken( rFormula, pToken, true );
+ if ( pToken->GetOpCode() == ocSep )
+ {
+ // Excel formula separator is ",".
+ rFormula = String::CreateFromAscii(",");
+ }
+ rNewFormula += rFormula;
+ }
+}
+
+uno::Reference< XHelperInterface >
+getUnoSheetModuleObj( const uno::Reference< sheet::XSheetCellRangeContainer >& xRanges ) throw ( uno::RuntimeException )
+{
+ uno::Reference< container::XEnumerationAccess > xEnumAccess( xRanges, uno::UNO_QUERY_THROW );
+ uno::Reference< container::XEnumeration > xEnum = xEnumAccess->createEnumeration();
+ uno::Reference< table::XCellRange > xRange( xEnum->nextElement(), uno::UNO_QUERY_THROW );
+ return getUnoSheetModuleObj( xRange );
+}
+
+uno::Reference< XHelperInterface >
+getUnoSheetModuleObj( const uno::Reference< table::XCell >& xCell ) throw ( uno::RuntimeException )
+{
+ uno::Reference< sheet::XSheetCellRange > xSheetRange( xCell, uno::UNO_QUERY_THROW );
+ uno::Reference< sheet::XSpreadsheet > xSheet( xSheetRange->getSpreadsheet(), uno::UNO_SET_THROW );
+ return getUnoSheetModuleObj( xSheet );
+}
+
+uno::Reference< XHelperInterface >
+getUnoSheetModuleObj( const uno::Reference< frame::XModel >& xModel, SCTAB nTab ) throw ( uno::RuntimeException )
+{
+ uno::Reference< sheet::XSpreadsheetDocument > xDoc( xModel, uno::UNO_QUERY_THROW );
+ uno::Reference< container::XIndexAccess > xSheets( xDoc->getSheets(), uno::UNO_QUERY_THROW );
+ uno::Reference< sheet::XSpreadsheet > xSheet( xSheets->getByIndex( nTab ), uno::UNO_QUERY_THROW );
+ return getUnoSheetModuleObj( xSheet );
+}
+
+SfxItemSet*
+ScVbaCellRangeAccess::GetDataSet( ScCellRangesBase* pRangeObj )
+{
+ return pRangeObj ? pRangeObj->GetCurrentDataSet( true ) : 0;
+}
+
+// ============================================================================
+
+} // namespace excel
+} // namespace vba
+} // namespace ooo