diff --git a/sc/source/ui/vba/vbahelper.cxx b/sc/source/ui/vba/vbahelper.cxx new file mode 100644 index 000000000000..911365fc3dc8 --- /dev/null +++ b/sc/source/ui/vba/vbahelper.cxx @@ -0,0 +1,527 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: vbahelper.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: rt $ $Date: 2007-04-25 16:07:21 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include "vbahelper.hxx" +#include "tabvwsh.hxx" +#include "transobj.hxx" +#include "scmod.hxx" + +using namespace ::com::sun::star; +using namespace ::org::openoffice; + +void unoToSbxValue( SbxVariable* pVar, const uno::Any& aValue ); + +uno::Any sbxToUnoValue( SbxVariable* pVar ); + + +namespace org +{ +namespace openoffice +{ + +// helper method to determine if the view ( calc ) is in print-preview mode +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")); +const uno::Any& +aNULL() +{ + static uno::Any aNULLL = uno::makeAny( uno::Reference< uno::XInterface >() ); + return aNULLL; +} + +class PasteCellsWarningReseter +{ +private: + bool bInitialWarningState; + static uno::Reference< beans::XPropertySet > getGlobalSheetSettings() throw ( uno::RuntimeException ) + { + static uno::Reference xContext( ::cppu::defaultBootstrap_InitialComponentContext(), uno::UNO_QUERY_THROW ); + static uno::Reference 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 = sal_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 +dispatchRequests (uno::Reference< frame::XModel>& xModel,rtl::OUString & aUrl, uno::Sequence< beans::PropertyValue >& sProps ) +{ + + util::URL url ; + url.Complete = aUrl; + rtl::OUString emptyString = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "" )); + uno::Reference xController = xModel->getCurrentController(); + uno::Reference xFrame = xController->getFrame(); + uno::Reference xDispatchProvider (xFrame,uno::UNO_QUERY_THROW); + try + { + uno::Reference xContext( ::cppu::defaultBootstrap_InitialComponentContext()); + if ( !xContext.is() ) + { + return ; + } + + uno::Reference xServiceManager( + xContext->getServiceManager() ); + if ( !xServiceManager.is() ) + { + return ; + } + uno::Reference xParser( xServiceManager->createInstanceWithContext( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ) ) + ,xContext), uno::UNO_QUERY_THROW ); + if (!xParser.is()) + return; + xParser->parseStrict (url); + } + catch ( ::cppu::BootstrapException & /*e*/ ) + { + return ; + } + catch ( uno::Exception & /*e*/ ) + { + return ; + } + + uno::Reference xDispatcher = xDispatchProvider->queryDispatch(url,emptyString,0); + + uno::Sequence dispatchProps(1); + + sal_Int32 nProps = sProps.getLength(); + beans::PropertyValue* pDest = dispatchProps.getArray(); + if ( nProps ) + { + dispatchProps.realloc( nProps + 1 ); + // need to reaccquire pDest after realloc + pDest = dispatchProps.getArray(); + beans::PropertyValue* pSrc = sProps.getArray(); + for ( sal_Int32 index=0; indexdispatch( url, dispatchProps ); +} + +void +dispatchRequests (uno::Reference< frame::XModel>& xModel,rtl::OUString & aUrl) +{ + uno::Sequence dispatchProps; + dispatchRequests( xModel, aUrl, dispatchProps ); +} + + +void +implnPaste() +{ + PasteCellsWarningReseter resetWarningBox; + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if ( pViewShell ) + { + pViewShell->PasteFromSystem(); + pViewShell->CellContentChanged(); + } +} + + +void +implnCopy() +{ + ScTabViewShell* pViewShell = getCurrentBestViewShell(); + if ( pViewShell ) + pViewShell->CopyToClip(NULL,false,false,true); +} + +void +implnCut() +{ + ScTabViewShell* pViewShell = getCurrentBestViewShell(); + if ( pViewShell ) + pViewShell->CutToClip( NULL, TRUE ); +} + +void implnPasteSpecial(USHORT nFlags,USHORT nFunction,sal_Bool bSkipEmpty, sal_Bool bTranspose) +{ + PasteCellsWarningReseter resetWarningBox; + sal_Bool bAsLink(sal_False), bOtherDoc(sal_False); + InsCellCmd eMoveMode = INS_NONE; + + ScTabViewShell* pTabViewShell = ScTabViewShell::GetActiveViewShell(); + if ( !pTabViewShell ) + // none active, try next best + pTabViewShell = getCurrentBestViewShell(); + 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, TRUE ); + pTabViewShell->CellContentChanged(); + } + } + } + +} + +bool +isRangeShortCut( const ::rtl::OUString& sParam ) +{ + // for a ShortCutRange param, I'd expect the first letter to be + //[A-Z] and the last letter to be a digit 0-9 e.g A10, [A1:A10] etc. + ::rtl::OString sStr = rtl::OUStringToOString( sParam, + RTL_TEXTENCODING_UTF8 ); + const sal_Char* pFirst = (const sal_Char*)sStr; + const sal_Char* pLast = pFirst + ( sStr.getLength() - 1 ); + if ( (( *pFirst >= 'A' && *pFirst <= 'Z' ) || ( *pFirst >= 'a' && *pFirst <= 'Z' ) ) ) + if ( ( *pLast >= '0' ) && ( *pLast <= '9' ) ) + return true; + + return false; +} + + uno::Reference< frame::XModel > +getCurrentDocument() throw (uno::RuntimeException) +{ + uno::Reference< frame::XModel > xModel; + SbxObject* pBasic = dynamic_cast< SbxObject* > ( SFX_APP()->GetBasic() ); + SbxObject* basicChosen = pBasic ; + if ( basicChosen == NULL) + { + OSL_TRACE("getModelFromBasic() StarBASIC* is NULL" ); + return xModel; + } + SbxObject* p = pBasic; + SbxObject* pParent = p->GetParent(); + SbxObject* pParentParent = pParent ? pParent->GetParent() : NULL; + + if( pParentParent ) + { + basicChosen = pParentParent; + } + else if( pParent ) + { + basicChosen = pParent; + } + + + uno::Any aModel; + SbxVariable *pCompVar = basicChosen->Find( UniString(RTL_CONSTASCII_USTRINGPARAM("ThisComponent")), SbxCLASS_OBJECT ); + + if ( pCompVar ) + { + aModel = sbxToUnoValue( pCompVar ); + if ( sal_False == ( aModel >>= xModel ) || + !xModel.is() ) + { + // trying last gasp try the current component + uno::Reference xCtx( ::cppu::defaultBootstrap_InitialComponentContext(), uno::UNO_QUERY_THROW ); + uno::Reference xSMgr( xCtx->getServiceManager(), uno::UNO_QUERY_THROW ); + uno::Reference< frame::XDesktop > xDesktop (xSMgr->createInstanceWithContext(::rtl::OUString::createFromAscii("com.sun.star.frame.Desktop"), xCtx), uno::UNO_QUERY_THROW ); + xModel.set( xDesktop->getCurrentComponent(), uno::UNO_QUERY ); + if ( !xModel.is() ) + { + throw uno::RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Can't extract model from basic ( its obviously not set yet ) therefore don't know the currently selected document") ), uno::Reference< uno::XInterface >() ); + } + return xModel; + } + else + { + OSL_TRACE("Have model ThisComponent points to url %s", + ::rtl::OUStringToOString( xModel->getURL(), + RTL_TEXTENCODING_ASCII_US ).pData->buffer ); + } + } + else + { + OSL_TRACE("Failed to get ThisComponent"); + throw uno::RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "Can't determine the currently selected document") ), + uno::Reference< uno::XInterface >() ); + } + return xModel; +} + +ScDocShell* +getDocShell( 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( css::uno::Reference< css::frame::XModel>& xModel ) +{ + ScDocShell* pDocShell = getDocShell( xModel ); + if ( pDocShell ) + return pDocShell->GetBestViewShell(); + return NULL; +} + +ScTabViewShell* +getCurrentBestViewShell() +{ + uno::Reference< frame::XModel > xModel = getCurrentDocument(); + return getBestViewShell( xModel ); +} + +SfxViewFrame* +getCurrentViewFrame() +{ + ScTabViewShell* pViewShell = getCurrentBestViewShell(); + if ( pViewShell ) + return pViewShell->GetViewFrame(); + return NULL; +} + +sal_Int32 +OORGBToXLRGB( sal_Int32 nCol ) +{ + sal_Int32 nRed = nCol; + nRed &= 0x00FF0000; + nRed >>= 16; + sal_Int32 nGreen = nCol; + nGreen &= 0x0000FF00; + nGreen >>= 8; + sal_Int32 nBlue = nCol; + nBlue &= 0x000000FF; + sal_Int32 nRGB = ( (nBlue << 16) | (nGreen << 8) | nRed ); + return nRGB; +} +sal_Int32 +XLRGBToOORGB( sal_Int32 nCol ) +{ + sal_Int32 nBlue = nCol; + nBlue &= 0x00FF0000; + nBlue >>= 16; + sal_Int32 nGreen = nCol; + nGreen &= 0x0000FF00; + nGreen >>= 8; + sal_Int32 nRed = nCol; + nRed &= 0x000000FF; + sal_Int32 nRGB = ( (nRed << 16) | (nGreen << 8) | nBlue ); + return nRGB; +} +uno::Any +OORGBToXLRGB( const uno::Any& aCol ) +{ + sal_Int32 nCol; + aCol >>= nCol; + nCol = OORGBToXLRGB( nCol ); + return uno::makeAny( nCol ); +} +uno::Any +XLRGBToOORGB( const uno::Any& aCol ) +{ + sal_Int32 nCol; + aCol >>= nCol; + nCol = XLRGBToOORGB( nCol ); + return uno::makeAny( nCol ); +} + +void PrintOutHelper( 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, css::uno::Reference< frame::XModel >& xModel, sal_Bool bUseSelection ) +{ + sal_Int32 nTo = 0; + sal_Int32 nFrom = 0; + sal_Int16 nCopies = 1; + sal_Bool bPreview = sal_False; + sal_Bool bCollate = sal_False; + sal_Bool bSelection = bUseSelection; + From >>= nFrom; + To >>= nTo; + Copies >>= nCopies; + Preview >>= bPreview; + if ( nCopies > 1 ) // Collate only useful when more that 1 copy + Collate >>= bCollate; + + rtl::OUString sRange( RTL_CONSTASCII_USTRINGPARAM( "-" ) ); + rtl::OUString sFileName; + + if (( nFrom || nTo ) ) + { + if ( nFrom ) + sRange = ( ::rtl::OUString::valueOf( nFrom ) + sRange ); + if ( nTo ) + sRange += ::rtl::OUString::valueOf( nTo ); + } + + if ( PrToFileName.getValue() ) + { + PrToFileName >>= sFileName; + } + ScTabViewShell* pViewShell = getBestViewShell( xModel ); + SfxViewFrame* pViewFrame = NULL; + if ( pViewShell ) + pViewFrame = pViewShell->GetViewFrame(); + if ( pViewFrame ) + { + SfxAllItemSet aArgs( SFX_APP()->GetPool() ); + + SfxBoolItem sfxCollate( SID_PRINT_COLLATE, bCollate ); + aArgs.Put( sfxCollate, sfxCollate.Which() ); + SfxInt16Item sfxCopies( SID_PRINT_COPIES, nCopies ); + aArgs.Put( sfxCopies, sfxCopies.Which() ); + if ( sFileName.getLength() ) + { + SfxStringItem sfxFileName( SID_FILE_NAME, sFileName); + aArgs.Put( sfxFileName, sfxFileName.Which() ); + + } + if ( sRange.getLength() ) + { + SfxStringItem sfxRange( SID_PRINT_PAGES, sRange ); + aArgs.Put( sfxRange, sfxRange.Which() ); + } + SfxBoolItem sfxSelection( SID_SELECTION, bSelection ); + aArgs.Put( sfxSelection, sfxSelection.Which() ); + SfxBoolItem sfxAsync( SID_ASYNCHRON, sal_False ); + aArgs.Put( sfxAsync, sfxAsync.Which() ); + SfxDispatcher* pDispatcher = pViewFrame->GetDispatcher(); + + if ( pDispatcher ) + { + if ( bPreview ) + { + if ( !pViewFrame->GetFrame()->IsInPlace() ) + { + SC_MOD()->InputEnterHandler(); + pViewFrame->GetDispatcher()->Execute( SID_VIEWSHELL1, SFX_CALLMODE_SYNCHRON ); + while ( isInPrintPreview( pViewFrame ) ) + Application::Yield(); + } + } + else + pDispatcher->Execute( (USHORT)SID_PRINTDOC, (SfxCallMode)SFX_CALLMODE_SYNCHRON, aArgs ); + } + + } + + // #FIXME #TODO + // 1 Preview ( does such a thing exist in OO.org? ) + // 2 ActivePrinter ( how/can we switch a printer via API? ) + // 3 PrintToFile ( ms behaviour if this option is specified but no + // filename supplied 'PrToFileName' then the user will be prompted ) + // 4 Need to check behaviour of Selected sheets with range ( e.g. From & To + // values ) in oOO these options are mutually exclusive + // 5 There is a pop up to do with transparent objects in the print source + // should be able to disable that via configuration for the duration + // of this method +} + +} +}