diff options
91 files changed, 4645 insertions, 724 deletions
diff --git a/sc/inc/cellsuno.hxx b/sc/inc/cellsuno.hxx index 13469b110455..a53f167b164a 100644 --- a/sc/inc/cellsuno.hxx +++ b/sc/inc/cellsuno.hxx @@ -90,6 +90,7 @@ #include <com/sun/star/document/XActionLockable.hpp> #include <com/sun/star/beans/XTolerantMultiPropertySet.hpp> #include <com/sun/star/sheet/XExternalSheetName.hpp> +#include <com/sun/star/document/XEventsSupplier.hpp> #include <cppuhelper/implbase2.hxx> #include <cppuhelper/implbase3.hxx> @@ -1002,7 +1003,8 @@ class ScTableSheetObj : public ScCellRangeObj, public com::sun::star::util::XProtectable, public com::sun::star::sheet::XScenario, public com::sun::star::sheet::XScenarioEnhanced, - public com::sun::star::sheet::XExternalSheetName + public com::sun::star::sheet::XExternalSheetName, + public com::sun::star::document::XEventsSupplier { friend class ScTableSheetsObj; // fuer insertByName() @@ -1207,6 +1209,10 @@ public: throw (::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException); + // XEventsSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameReplace > SAL_CALL getEvents() + throw (::com::sun::star::uno::RuntimeException); + // XPropertySet ueberladen wegen Sheet-Properties virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() diff --git a/sc/inc/convuno.hxx b/sc/inc/convuno.hxx index 135ac055b2fe..0f93d6d6de0d 100644 --- a/sc/inc/convuno.hxx +++ b/sc/inc/convuno.hxx @@ -28,6 +28,7 @@ #ifndef SC_CONVUNO_HXX #define SC_CONVUNO_HXX +#include <algorithm> #include <i18npool/lang.h> #include <com/sun/star/table/CellAddress.hpp> #include <com/sun/star/table/CellRangeAddress.hpp> @@ -70,6 +71,19 @@ public: static inline void FillApiEndAddress( ::com::sun::star::table::CellAddress& rApiAddress, const ::com::sun::star::table::CellRangeAddress& rApiRange ); + + /** Returns true, if the passed ranges have at least one common cell. */ + static inline bool Intersects( + const ::com::sun::star::table::CellRangeAddress& rApiARange1, + const ::com::sun::star::table::CellRangeAddress& rApiARange2 ); + /** Returns true, if the passed address rApiInner is inside the passed range rApiOuter. */ + static inline bool Contains( + const ::com::sun::star::table::CellRangeAddress& rApiOuter, + const ::com::sun::star::table::CellAddress& rApiInner ); + /** Returns true, if the passed range rApiInner is completely inside the passed range rApiOuter. */ + static inline bool Contains( + const ::com::sun::star::table::CellRangeAddress& rApiOuter, + const ::com::sun::star::table::CellRangeAddress& rApiInner ); }; @@ -135,6 +149,33 @@ inline void ScUnoConversion::FillApiEndAddress( rApiAddress.Sheet = rApiRange.Sheet; } +inline bool ScUnoConversion::Intersects( + const ::com::sun::star::table::CellRangeAddress& rApiRange1, + const ::com::sun::star::table::CellRangeAddress& rApiRange2 ) +{ + return (rApiRange1.Sheet == rApiRange2.Sheet) && + (::std::max( rApiRange1.StartColumn, rApiRange2.StartColumn ) <= ::std::min( rApiRange1.EndColumn, rApiRange2.EndColumn )) && + (::std::max( rApiRange1.StartRow, rApiRange2.StartRow ) <= ::std::min( rApiRange1.EndRow, rApiRange2.EndRow )); +} + +inline bool ScUnoConversion::Contains( + const ::com::sun::star::table::CellRangeAddress& rApiOuter, + const ::com::sun::star::table::CellAddress& rApiInner ) +{ + return (rApiOuter.Sheet == rApiInner.Sheet) && + (rApiOuter.StartColumn <= rApiInner.Column) && (rApiInner.Column <= rApiOuter.EndColumn) && + (rApiOuter.StartRow <= rApiInner.Row) && (rApiInner.Row <= rApiOuter.EndRow); +} + +inline bool ScUnoConversion::Contains( + const ::com::sun::star::table::CellRangeAddress& rApiOuter, + const ::com::sun::star::table::CellRangeAddress& rApiInner ) +{ + return (rApiOuter.Sheet == rApiInner.Sheet) && + (rApiOuter.StartColumn <= rApiInner.StartColumn) && (rApiInner.EndColumn <= rApiOuter.EndColumn) && + (rApiOuter.StartRow <= rApiInner.StartRow) && (rApiInner.EndRow <= rApiOuter.EndRow); +} + //___________________________________________________________________ inline sal_Bool operator==( diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 044ccc853034..cf52a13aceaa 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -734,6 +734,14 @@ public: BOOL HasBackgroundDraw( SCTAB nTab, const Rectangle& rMMRect ); BOOL HasAnyDraw( SCTAB nTab, const Rectangle& rMMRect ); + const ScSheetEvents* GetSheetEvents( SCTAB nTab ) const; + void SetSheetEvents( SCTAB nTab, const ScSheetEvents* pNew ); + bool HasSheetEventScript( sal_Int32 nEvent ) const; // on any sheet + + BOOL HasCalcNotification( SCTAB nTab ) const; + void SetCalcNotification( SCTAB nTab ); + void ResetCalcNotifications(); + SC_DLLPUBLIC ScOutlineTable* GetOutlineTable( SCTAB nTab, BOOL bCreate = FALSE ); BOOL SetOutlineTable( SCTAB nTab, const ScOutlineTable* pNewOutline ); diff --git a/sc/inc/docuno.hxx b/sc/inc/docuno.hxx index a27e3101b9c1..14c9515dfacb 100644 --- a/sc/inc/docuno.hxx +++ b/sc/inc/docuno.hxx @@ -112,6 +112,7 @@ private: const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& rOptions, ScMarkData& rMark, ScPrintSelectionStatus& rStatus, String& rPagesStr ) const; com::sun::star::uno::Reference<com::sun::star::uno::XAggregation> GetFormatter(); + void HandleCalculateEvents(); rtl::OUString maBuildId; protected: diff --git a/sc/inc/eventuno.hxx b/sc/inc/eventuno.hxx new file mode 100755 index 000000000000..f3ae72f0f1bf --- /dev/null +++ b/sc/inc/eventuno.hxx @@ -0,0 +1,91 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sheetdata.hxx,v $ + * $Revision: 1.16.32.2 $ + * + * 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. + * + ************************************************************************/ + +#ifndef SC_EVENTUNO_HXX +#define SC_EVENTUNO_HXX + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/container/XNameReplace.hpp> +#include <cppuhelper/implbase2.hxx> +#include <svl/lstner.hxx> + +#include "global.hxx" + +class ScDocShell; + +class ScSheetEventsObj : public cppu::WeakImplHelper2< + com::sun::star::container::XNameReplace, + com::sun::star::lang::XServiceInfo>, + public SfxListener +{ +private: + ScDocShell* mpDocShell; + SCTAB mnTab; + +public: + ScSheetEventsObj(ScDocShell* pDocSh, SCTAB nT); + virtual ~ScSheetEventsObj(); + + virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); + + // XNameReplace + virtual void SAL_CALL replaceByName( const ::rtl::OUString& aName, + const ::com::sun::star::uno::Any& aElement ) + throw(::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::container::NoSuchElementException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + + // XNameAccess + virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) + throw(::com::sun::star::container::NoSuchElementException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames() + throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) + throw(::com::sun::star::uno::RuntimeException); + + // XElementAccess + virtual ::com::sun::star::uno::Type SAL_CALL getElementType() + throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasElements() throw(::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() + throw(::com::sun::star::uno::RuntimeException); +}; + +#endif + diff --git a/sc/inc/funcuno.hxx b/sc/inc/funcuno.hxx index 3eef9082e26d..4413782a0e2f 100644 --- a/sc/inc/funcuno.hxx +++ b/sc/inc/funcuno.hxx @@ -72,7 +72,8 @@ private: ScTempDocCache aDocCache; ScDocOptions* pOptions; SfxItemPropertyMap aPropertyMap; - BOOL bInvalid; + bool mbArray; + bool mbValid; public: ScFunctionAccess(); diff --git a/sc/inc/sc.hrc b/sc/inc/sc.hrc index aad25ab4d0a4..4a697dc57558 100644 --- a/sc/inc/sc.hrc +++ b/sc/inc/sc.hrc @@ -835,6 +835,7 @@ #define FID_TAB_DESELECTALL (TAB_POPUP_START+8) #define FID_TAB_MENU_SET_TAB_BG_COLOR (TAB_POPUP_START + 9) #define FID_TAB_SET_TAB_BG_COLOR (TAB_POPUP_START + 10) +#define FID_TAB_EVENTS (TAB_POPUP_START+11) #define TAB_POPUP_END (TAB_POPUP_START + 20) diff --git a/sc/inc/sheetevents.hxx b/sc/inc/sheetevents.hxx new file mode 100755 index 000000000000..8f52efb990f7 --- /dev/null +++ b/sc/inc/sheetevents.hxx @@ -0,0 +1,65 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sheetdata.hxx,v $ + * $Revision: 1.16.32.2 $ + * + * 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. + * + ************************************************************************/ + +#ifndef SC_SHEETEVENTS_HXX +#define SC_SHEETEVENTS_HXX + +#include <rtl/ustring.hxx> + +#define SC_SHEETEVENT_FOCUS 0 +#define SC_SHEETEVENT_UNFOCUS 1 +#define SC_SHEETEVENT_SELECT 2 +#define SC_SHEETEVENT_DOUBLECLICK 3 +#define SC_SHEETEVENT_RIGHTCLICK 4 +#define SC_SHEETEVENT_CHANGE 5 +#define SC_SHEETEVENT_CALCULATE 6 +#define SC_SHEETEVENT_COUNT 7 + +class ScSheetEvents +{ + rtl::OUString** mpScriptNames; + + void Clear(); + +public: + ScSheetEvents(); + ScSheetEvents(const ScSheetEvents& rOther); + ~ScSheetEvents(); + + const ScSheetEvents& operator= (const ScSheetEvents& rOther); + + const rtl::OUString* GetScript(sal_Int32 nEvent) const; + void SetScript(sal_Int32 nEvent, const rtl::OUString* pNew); + + static rtl::OUString GetEventName(sal_Int32 nEvent); +}; + +#endif + diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index e93f4e381f95..6cc5a4d16aaa 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -63,6 +63,7 @@ class ScPrintSaverTab; class ScProgress; class ScProgress; class ScRangeList; +class ScSheetEvents; class ScSortInfoArray; class ScStyleSheet; class ScTableLink; @@ -118,6 +119,8 @@ private: ScOutlineTable* pOutlineTable; + ScSheetEvents* pSheetEvents; + SCCOL nTableAreaX; SCROW nTableAreaY; BOOL bTableAreaValid; @@ -126,6 +129,7 @@ private: BOOL bVisible; BOOL bStreamValid; BOOL bPendingRowHeights; + BOOL bCalcNotification; SCTAB nTab; USHORT nRecalcLvl; // Rekursionslevel Size-Recalc @@ -190,6 +194,9 @@ public: void RemoveSubTotals( ScSubTotalParam& rParam ); BOOL DoSubTotals( ScSubTotalParam& rParam ); + const ScSheetEvents* GetSheetEvents() const { return pSheetEvents; } + void SetSheetEvents( const ScSheetEvents* pNew ); + BOOL IsVisible() const { return bVisible; } void SetVisible( BOOL bVis ); @@ -199,6 +206,9 @@ public: BOOL IsPendingRowHeights() const { return bPendingRowHeights; } void SetPendingRowHeights( BOOL bSet ); + BOOL GetCalcNotification() const { return bCalcNotification; } + void SetCalcNotification( BOOL bSet ); + BOOL IsLayoutRTL() const { return bLayoutRTL; } BOOL IsLoadingRTL() const { return bLoadingRTL; } void SetLayoutRTL( BOOL bSet ); diff --git a/sc/inc/unonames.hxx b/sc/inc/unonames.hxx index 48ea39d40181..2d011f425398 100644 --- a/sc/inc/unonames.hxx +++ b/sc/inc/unonames.hxx @@ -635,5 +635,10 @@ #define SC_UNO_SHAREDOC "IsDocumentShared" +// EventDescriptor + +#define SC_UNO_EVENTTYPE "EventType" +#define SC_UNO_SCRIPT "Script" + #endif diff --git a/sc/inc/viewuno.hxx b/sc/inc/viewuno.hxx index 988602b2056f..19b5c60fd070 100644 --- a/sc/inc/viewuno.hxx +++ b/sc/inc/viewuno.hxx @@ -48,6 +48,8 @@ #include <com/sun/star/lang/XUnoTunnel.hpp> #include <com/sun/star/datatransfer/XTransferableSupplier.hpp> +#include "address.hxx" + class ScTabViewShell; #define SC_VIEWPANE_ACTIVE 0xFFFF @@ -195,6 +197,7 @@ private: XViewPropertyChangeListenerArr_Impl aPropertyChgListeners; XMouseClickHandlerArr_Impl aMouseClickHandlers; XActivationEventListenerArr_Impl aActivationListeners; + SCTAB nPreviousTab; sal_Bool bDrawSelModeSet; ScViewPaneObj* GetObjectByIndex_Impl(USHORT nIndex) const; @@ -223,7 +226,7 @@ public: void SelectionChanged(); void VisAreaChanged(); void SheetChanged(); - sal_Bool IsMouseListening() { return aMouseClickHandlers.Count() > 0; } + bool IsMouseListening() const; sal_Bool MousePressed( const ::com::sun::star::awt::MouseEvent& e ) throw (::com::sun::star::uno::RuntimeException); sal_Bool MouseReleased( const ::com::sun::star::awt::MouseEvent& e ) throw (::com::sun::star::uno::RuntimeException); diff --git a/sc/sdi/scalc.sdi b/sc/sdi/scalc.sdi index 07442c7ee259..1e42ce5fb1dc 100644 --- a/sc/sdi/scalc.sdi +++ b/sc/sdi/scalc.sdi @@ -6819,6 +6819,31 @@ SfxVoidItem TableDeselectAll FID_TAB_DESELECTALL ] //-------------------------------------------------------------------------- +SfxVoidItem TableEvents FID_TAB_EVENTS +() +[ + /* flags: */ + AutoUpdate = FALSE, + Cachable = Cachable, + FastCall = FALSE, + HasCoreId = FALSE, + HasDialog = TRUE, + ReadOnlyDoc = TRUE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + Synchron; + + /* config: */ + AccelConfig = TRUE, + MenuConfig = TRUE, + StatusBarConfig = FALSE, + ToolBoxConfig = FALSE, + GroupId = GID_EDIT; +] + +//-------------------------------------------------------------------------- SfxVoidItem TextAttributes SID_DRAWTEXT_ATTR_DLG () [ diff --git a/sc/sdi/tabvwsh.sdi b/sc/sdi/tabvwsh.sdi index a7b493fc2aa7..fac67839e656 100644 --- a/sc/sdi/tabvwsh.sdi +++ b/sc/sdi/tabvwsh.sdi @@ -52,13 +52,14 @@ interface Tables FID_TAB_SELECTALL [ ExecMethod = Execute; StateMethod = GetState; ] FID_TAB_DESELECTALL [ ExecMethod = Execute; StateMethod = GetState; ] FID_TAB_MENU_RENAME [ ExecMethod = ExecuteTable; StateMethod = GetStateTable; ] - FID_TAB_APPEND [ ExecMethod = ExecuteTable; StateMethod = GetStateTable; ] - FID_INS_TABLE [ ExecMethod = ExecuteTable; StateMethod = GetStateTable; ] + FID_TAB_APPEND [ ExecMethod = ExecuteTable; StateMethod = GetStateTable; ] + FID_INS_TABLE [ ExecMethod = ExecuteTable; StateMethod = GetStateTable; ] FID_INS_TABLE_EXT [ ExecMethod = ExecuteTable; StateMethod = GetStateTable; ] - FID_TABLE_HIDE [ ExecMethod = ExecuteTable; StateMethod = GetStateTable; ] - FID_TABLE_SHOW [ ExecMethod = ExecuteTable; StateMethod = GetStateTable; ] - SID_SELECT_TABLES [ ExecMethod = Execute; StateMethod = GetState; ] + FID_TABLE_HIDE [ ExecMethod = ExecuteTable; StateMethod = GetStateTable; ] + FID_TABLE_SHOW [ ExecMethod = ExecuteTable; StateMethod = GetStateTable; ] + SID_SELECT_TABLES [ ExecMethod = Execute; StateMethod = GetState; ] FID_TAB_MENU_SET_TAB_BG_COLOR [ ExecMethod = ExecuteTable; StateMethod = GetStateTable; ] + FID_TAB_EVENTS [ ExecMethod = ExecuteTable; StateMethod = GetStateTable; ] } // =========================================================================== diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx index 4fe49b3728dd..e4741eb7b468 100644 --- a/sc/source/core/data/documen3.cxx +++ b/sc/source/core/data/documen3.cxx @@ -83,6 +83,7 @@ #include "tabprotection.hxx" #include "formulaparserpool.hxx" #include "clipparam.hxx" +#include "sheetevents.hxx" #include <memory> @@ -498,6 +499,52 @@ ScFormulaParserPool& ScDocument::GetFormulaParserPool() const return *mxFormulaParserPool; } +const ScSheetEvents* ScDocument::GetSheetEvents( SCTAB nTab ) const +{ + if (VALIDTAB(nTab) && pTab[nTab]) + return pTab[nTab]->GetSheetEvents(); + return NULL; +} + +void ScDocument::SetSheetEvents( SCTAB nTab, const ScSheetEvents* pNew ) +{ + if (VALIDTAB(nTab) && pTab[nTab]) + pTab[nTab]->SetSheetEvents( pNew ); +} + +bool ScDocument::HasSheetEventScript( sal_Int32 nEvent ) const +{ + for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++) + if (pTab[nTab]) + { + const ScSheetEvents* pEvents = pTab[nTab]->GetSheetEvents(); + if ( pEvents && pEvents->GetScript( nEvent ) ) + return true; + } + return false; +} + +BOOL ScDocument::HasCalcNotification( SCTAB nTab ) const +{ + if (VALIDTAB(nTab) && pTab[nTab]) + return pTab[nTab]->GetCalcNotification(); + return FALSE; +} + +void ScDocument::SetCalcNotification( SCTAB nTab ) +{ + // set only if not set before + if (VALIDTAB(nTab) && pTab[nTab] && !pTab[nTab]->GetCalcNotification()) + pTab[nTab]->SetCalcNotification(TRUE); +} + +void ScDocument::ResetCalcNotifications() +{ + for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++) + if (pTab[nTab] && pTab[nTab]->GetCalcNotification()) + pTab[nTab]->SetCalcNotification(FALSE); +} + ScOutlineTable* ScDocument::GetOutlineTable( SCTAB nTab, BOOL bCreate ) { ScOutlineTable* pVal = NULL; diff --git a/sc/source/core/data/documen7.cxx b/sc/source/core/data/documen7.cxx index ad2ec90379df..97aae44f1a7b 100644 --- a/sc/source/core/data/documen7.cxx +++ b/sc/source/core/data/documen7.cxx @@ -52,6 +52,7 @@ #include "scmod.hxx" // SC_MOD #include "inputopt.hxx" // GetExpandRefs #include "conditio.hxx" +#include "sheetevents.hxx" #include <tools/shl.hxx> @@ -452,6 +453,8 @@ void ScDocument::TrackFormulas( ULONG nHintId ) if ( pFormulaTrack ) { erBEEPER(); + // outside the loop, check if any sheet has a "calculate" event script + bool bCalcEvent = HasSheetEventScript( SC_SHEETEVENT_CALCULATE ); SvtBroadcaster* pBC; ScFormulaCell* pTrack; ScFormulaCell* pNext; @@ -465,6 +468,9 @@ void ScDocument::TrackFormulas( ULONG nHintId ) // Repaint fuer bedingte Formate mit relativen Referenzen: if ( pCondFormList ) pCondFormList->SourceChanged( pTrack->aPos ); + // for "calculate" event, keep track of which sheets are affected by tracked formulas + if ( bCalcEvent ) + SetCalcNotification( pTrack->aPos.Tab() ); pTrack = pTrack->GetNextTrack(); } while ( pTrack ); pTrack = pFormulaTrack; diff --git a/sc/source/core/data/makefile.mk b/sc/source/core/data/makefile.mk index 189e2e568b88..7e8c00a0637f 100644 --- a/sc/source/core/data/makefile.mk +++ b/sc/source/core/data/makefile.mk @@ -98,6 +98,7 @@ SLOFILES = \ $(SLO)$/patattr.obj \ $(SLO)$/pivot2.obj \ $(SLO)$/poolhelp.obj \ + $(SLO)$/sheetevents.obj \ $(SLO)$/sortparam.obj \ $(SLO)$/stlpool.obj \ $(SLO)$/stlsheet.obj \ diff --git a/sc/source/core/data/sheetevents.cxx b/sc/source/core/data/sheetevents.cxx new file mode 100755 index 000000000000..e9e430ef85d9 --- /dev/null +++ b/sc/source/core/data/sheetevents.cxx @@ -0,0 +1,141 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: sheetdata.cxx,v $ + * $Revision: 1.69.32.3 $ + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +// INCLUDE --------------------------------------------------------------- + +#include <tools/debug.hxx> + +#include "sheetevents.hxx" + +// ----------------------------------------------------------------------- + +// static +rtl::OUString ScSheetEvents::GetEventName(sal_Int32 nEvent) +{ + if (nEvent<0 || nEvent>=SC_SHEETEVENT_COUNT) + { + DBG_ERRORFILE("invalid event number"); + return rtl::OUString(); + } + + static const sal_Char* aEventNames[] = + { + "OnFocus", // SC_SHEETEVENT_FOCUS + "OnUnfocus", // SC_SHEETEVENT_UNFOCUS + "OnSelect", // SC_SHEETEVENT_SELECT + "OnDoubleClick", // SC_SHEETEVENT_DOUBLECLICK + "OnRightClick", // SC_SHEETEVENT_RIGHTCLICK + "OnChange", // SC_SHEETEVENT_CHANGE + "OnCalculate" // SC_SHEETEVENT_CALCULATE + }; + return rtl::OUString::createFromAscii(aEventNames[nEvent]); +} + +// ----------------------------------------------------------------------- + +ScSheetEvents::ScSheetEvents() : + mpScriptNames(NULL) +{ +} + +ScSheetEvents::~ScSheetEvents() +{ + Clear(); +} + +void ScSheetEvents::Clear() +{ + if (mpScriptNames) + { + for (sal_Int32 nEvent=0; nEvent<SC_SHEETEVENT_COUNT; ++nEvent) + delete mpScriptNames[nEvent]; + delete[] mpScriptNames; + mpScriptNames = NULL; + } +} + +ScSheetEvents::ScSheetEvents(const ScSheetEvents& rOther) : + mpScriptNames(NULL) +{ + *this = rOther; +} + +const ScSheetEvents& ScSheetEvents::operator=(const ScSheetEvents& rOther) +{ + Clear(); + if (rOther.mpScriptNames) + { + mpScriptNames = new rtl::OUString*[SC_SHEETEVENT_COUNT]; + for (sal_Int32 nEvent=0; nEvent<SC_SHEETEVENT_COUNT; ++nEvent) + if (rOther.mpScriptNames[nEvent]) + mpScriptNames[nEvent] = new rtl::OUString(*rOther.mpScriptNames[nEvent]); + else + mpScriptNames[nEvent] = NULL; + } + return *this; +} + +const rtl::OUString* ScSheetEvents::GetScript(sal_Int32 nEvent) const +{ + if (nEvent<0 || nEvent>=SC_SHEETEVENT_COUNT) + { + DBG_ERRORFILE("invalid event number"); + return NULL; + } + + if (mpScriptNames) + return mpScriptNames[nEvent]; + return NULL; +} + +void ScSheetEvents::SetScript(sal_Int32 nEvent, const rtl::OUString* pNew) +{ + if (nEvent<0 || nEvent>=SC_SHEETEVENT_COUNT) + { + DBG_ERRORFILE("invalid event number"); + return; + } + + if (!mpScriptNames) + { + mpScriptNames = new rtl::OUString*[SC_SHEETEVENT_COUNT]; + for (sal_Int32 nEventIdx=0; nEventIdx<SC_SHEETEVENT_COUNT; ++nEventIdx) + mpScriptNames[nEventIdx] = NULL; + } + delete mpScriptNames[nEvent]; + if (pNew) + mpScriptNames[nEvent] = new rtl::OUString(*pNew); + else + mpScriptNames[nEvent] = NULL; +} + diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx index 8b7ca593b2e9..ca54da645444 100644 --- a/sc/source/core/data/table1.cxx +++ b/sc/source/core/data/table1.cxx @@ -112,6 +112,7 @@ #include "hints.hxx" // fuer Paint-Broadcast #include "prnsave.hxx" #include "tabprotection.hxx" +#include "sheetevents.hxx" // STATIC DATA ----------------------------------------------------------- @@ -135,10 +136,12 @@ ScTable::ScTable( ScDocument* pDoc, SCTAB nNewTab, const String& rNewName, pColFlags( NULL ), pRowFlags( NULL ), pOutlineTable( NULL ), + pSheetEvents( NULL ), bTableAreaValid( FALSE ), bVisible( TRUE ), bStreamValid( FALSE ), bPendingRowHeights( FALSE ), + bCalcNotification( FALSE ), nTab( nNewTab ), nRecalcLvl( 0 ), pDocument( pDoc ), @@ -214,6 +217,7 @@ ScTable::~ScTable() delete[] pColFlags; delete pRowHeight; delete pRowFlags; + delete pSheetEvents; delete pOutlineTable; delete pSearchParam; delete pSearchText; diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index 69d16df7be58..199d972560e3 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -56,6 +56,7 @@ #include "fillinfo.hxx" #include "bcaslot.hxx" #include "postit.hxx" +#include "sheetevents.hxx" #include "globstr.hrc" #include <math.h> @@ -97,6 +98,27 @@ void ScTable::StartOutlineTable() } +void ScTable::SetSheetEvents( const ScSheetEvents* pNew ) +{ + delete pSheetEvents; + if (pNew) + pSheetEvents = new ScSheetEvents(*pNew); + else + pSheetEvents = NULL; + + SetCalcNotification( FALSE ); // discard notifications before the events were set + + if (IsStreamValid()) + SetStreamValid(FALSE); +} + + +void ScTable::SetCalcNotification( BOOL bSet ) +{ + bCalcNotification = bSet; +} + + BOOL ScTable::TestInsertRow( SCCOL nStartCol, SCCOL nEndCol, SCSIZE nSize ) { BOOL bTest = TRUE; diff --git a/sc/source/filter/excel/excimp8.cxx b/sc/source/filter/excel/excimp8.cxx index a3ea403bf4c3..9608804da9f9 100644 --- a/sc/source/filter/excel/excimp8.cxx +++ b/sc/source/filter/excel/excimp8.cxx @@ -30,6 +30,7 @@ #include "excimp8.hxx" +#include <com/sun/star/sheet/XSpreadsheetDocument.hpp> #include <scitems.hxx> #include <comphelper/processfactory.hxx> @@ -54,6 +55,8 @@ #include <editeng/flditem.hxx> #include <svx/xflclit.hxx> #include <filter/msfilter/svxmsbas.hxx> +#include <basic/basmgr.hxx> +#include <oox/xls/excelvbaproject.hxx> #include <vcl/graph.hxx> #include <vcl/bmpacc.hxx> @@ -64,6 +67,7 @@ #include <tools/string.hxx> #include <tools/urlobj.hxx> #include <rtl/math.hxx> +#include <rtl/ustrbuf.hxx> #include <unotools/localedatawrapper.hxx> #include <unotools/charclass.hxx> #include <drwlayer.hxx> @@ -99,27 +103,19 @@ #include <com/sun/star/document/XDocumentProperties.hpp> #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> -#include <basic/basmgr.hxx> #include <cppuhelper/component_context.hxx> -#include <com/sun/star/container/XNameContainer.hpp> #include <sfx2/app.hxx> using namespace com::sun::star; - - -#define INVALID_POS 0xFFFFFFFF - - +using ::rtl::OUString; ImportExcel8::ImportExcel8( XclImpRootData& rImpData, SvStream& rStrm ) : - ImportExcel( rImpData, rStrm ), mnTab(0) + ImportExcel( rImpData, rStrm ) { + // replace BIFF2-BIFF5 formula importer with BIFF8 formula importer delete pFormConv; - pFormConv = pExcRoot->pFmlaConverter = new ExcelToSc8( GetRoot() ); - - bHasBasic = FALSE; } @@ -228,27 +224,6 @@ void ImportExcel8::Labelsst( void ) } -void ImportExcel8::Codename( BOOL bWorkbookGlobals ) -{ - if( bHasBasic ) - { - String aName( aIn.ReadUniString() ); - if( aName.Len() ) - { - if( bWorkbookGlobals ) - { - GetExtDocOptions().GetDocSettings().maGlobCodeName = aName; - GetDoc().SetCodeName( aName ); - } - else - { - GetExtDocOptions().AppendCodeName( aName ); - GetDoc().SetCodeName( mnTab++, aName ); - } - } - } -} - void ImportExcel8::SheetProtection( void ) { GetSheetProtectBuffer().ReadOptions( aIn, GetCurrScTab() ); @@ -294,9 +269,8 @@ void ImportExcel8::EndSheet( void ) void ImportExcel8::PostDocLoad( void ) { - // delay reading basic until sheet object ( codenames etc. ) are read - - if ( bHasBasic ) + // reading basic has been delayed until sheet objects (codenames etc.) are read + if( HasBasic() ) ReadBasic(); // #i11776# filtered ranges before outlines and hidden rows if( pExcRoot->pAutoFilterBuffer ) @@ -317,24 +291,47 @@ void ImportExcel8::PostDocLoad( void ) } // read doc info (no docshell while pasting from clipboard) + LoadDocumentProperties(); + // attach document events to VBA macros + AttachDocumentEvents(); + + // #i45843# Pivot tables are now handled outside of PostDocLoad, so they are available + // when formula cells are calculated, for the GETPIVOTDATA function. +} + +void ImportExcel8::LoadDocumentProperties() +{ + // no docshell while pasting from clipboard if( SfxObjectShell* pShell = GetDocShell() ) { // BIFF5+ without storage is possible SotStorageRef xRootStrg = GetRootStorage(); - if( xRootStrg.Is() ) + if( xRootStrg.Is() ) try + { + uno::Reference< document::XDocumentPropertiesSupplier > xDPS( pShell->GetModel(), uno::UNO_QUERY_THROW ); + uno::Reference< document::XDocumentProperties > xDocProps( xDPS->getDocumentProperties(), uno::UNO_SET_THROW ); + sfx2::LoadOlePropertySet( xDocProps, xRootStrg ); + } + catch( uno::Exception& ) { - uno::Reference<document::XDocumentPropertiesSupplier> xDPS( - pShell->GetModel(), uno::UNO_QUERY_THROW); - uno::Reference<document::XDocumentProperties> xDocProps - = xDPS->getDocumentProperties(); - sfx2::LoadOlePropertySet(xDocProps, GetRootStorage()); } } - - // #i45843# Pivot tables are now handled outside of PostDocLoad, so they are available - // when formula cells are calculated, for the GETPIVOTDATA function. } +void ImportExcel8::AttachDocumentEvents() +{ + SfxObjectShell* pShell = GetDocShell(); + if( HasBasic() && pShell ) + { + uno::Reference< lang::XMultiServiceFactory > xGlobalFactory = ::comphelper::getProcessServiceFactory(); + uno::Reference< sheet::XSpreadsheetDocument > xDocument( pShell->GetModel(), uno::UNO_QUERY ); + if( xGlobalFactory.is() && xDocument.is() ) + { + ::oox::xls::VbaProject aVbaProject( xGlobalFactory, xDocument ); + aVbaProject.attachToEvents(); + } + } +} //___________________________________________________________________ // autofilter diff --git a/sc/source/filter/excel/read.cxx b/sc/source/filter/excel/read.cxx index 79026e7b3a48..cfe5aedb867e 100644 --- a/sc/source/filter/excel/read.cxx +++ b/sc/source/filter/excel/read.cxx @@ -986,10 +986,10 @@ FltError ImportExcel8::Read( void ) case 0x22: Rec1904(); break; // 1904 [ 2345 ] case 0x56: Builtinfmtcnt(); break; // BUILTINFMTCNT[ 34 ] case 0x8D: Hideobj(); break; // HIDEOBJ [ 345 ] - case 0xD3: bHasBasic = true; break; + case 0xD3: SetHasBasic(); break; case 0xDE: Olesize(); break; - case 0x01BA: Codename( TRUE ); break; + case EXC_ID_CODENAME: ReadCodeName( aIn, true ); break; case EXC_ID_USESELFS: ReadUsesElfs(); break; case EXC_ID2_FONT: rFontBfr.ReadFont( maStrm ); break; @@ -1082,6 +1082,8 @@ FltError ImportExcel8::Read( void ) case EXC_ID2_DIMENSIONS: case EXC_ID3_DIMENSIONS: ReadDimensions(); break; + case EXC_ID_CODENAME: ReadCodeName( aIn, false ); break; + case 0x0A: // EOF [ 2345 ] eAkt = EXC_STATE_SHEET; aIn.SeekGlobalPosition(); // und zurueck an alte Position @@ -1097,7 +1099,6 @@ FltError ImportExcel8::Read( void ) case 0x9B: FilterMode(); break; // FILTERMODE case 0x9D: AutoFilterInfo(); break;// AUTOFILTERINFO case 0x9E: AutoFilter(); break; // AUTOFILTER - case 0x01BA: Codename( FALSE ); break; case 0x0208: Row34(); break; // ROW [ 34 ] case 0x0021: case 0x0221: Array34(); break; // ARRAY [ 34 ] diff --git a/sc/source/filter/excel/xichart.cxx b/sc/source/filter/excel/xichart.cxx index 97ac2d7459d5..7cbd74a836d2 100755 --- a/sc/source/filter/excel/xichart.cxx +++ b/sc/source/filter/excel/xichart.cxx @@ -4053,12 +4053,16 @@ void XclImpChart::ReadChartSubStream( XclImpStream& rStrm ) case EXC_ID_WINDOW2: rTabViewSett.ReadWindow2( rStrm, true );break; case EXC_ID_SCL: rTabViewSett.ReadScl( rStrm ); break; + case EXC_ID_SHEETEXT: //0x0862 { + // FIXME: do not need to pass palette, XclImpTabVieSettings is derived from root XclImpPalette& rPal = GetPalette(); rTabViewSett.ReadTabBgColor( rStrm, rPal); } break; + + case EXC_ID_CODENAME: ReadCodeName( rStrm, false ); break; } // common records diff --git a/sc/source/filter/excel/xiescher.cxx b/sc/source/filter/excel/xiescher.cxx index 3d055d94a498..02c5203d356a 100644 --- a/sc/source/filter/excel/xiescher.cxx +++ b/sc/source/filter/excel/xiescher.cxx @@ -62,10 +62,6 @@ #include <basegfx/point/b2dpoint.hxx> #include <basegfx/polygon/b2dpolygon.hxx> -#include <basic/sbstar.hxx> -#include <basic/sbmod.hxx> -#include <basic/sbmeth.hxx> - #include <svx/svdopath.hxx> #include <svx/svdocirc.hxx> #include <svx/svdoedge.hxx> @@ -478,14 +474,14 @@ void XclImpDrawObjBase::PreProcessSdrObject( XclImpDffConverter& rDffConv, SdrOb { if( ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( &rSdrObj, TRUE ) ) { - pInfo->SetMacro( XclControlHelper::GetScMacroName( maMacroName, GetDocShell() ) ); + pInfo->SetMacro( XclTools::GetSbMacroUrl( maMacroName, GetDocShell() ) ); pInfo->SetHlink( maHyperlink ); } } #else if( mbSimpleMacro && (maMacroName.Len() > 0) ) if( ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( &rSdrObj, TRUE ) ) - pInfo->SetMacro( XclControlHelper::GetScMacroName( maMacroName, GetDocShell() ) ); + pInfo->SetMacro( XclTools::GetSbMacroUrl( maMacroName, GetDocShell() ) ); #endif // call virtual function for object type specific processing @@ -550,16 +546,7 @@ void XclImpDrawObjBase::ReadMacro8( XclImpStream& rStrm ) DBG_ASSERT( nTokenId == XclTokenArrayHelper::GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ), "XclImpDrawObjBase::ReadMacro - tNameXR token expected" ); if( nTokenId == XclTokenArrayHelper::GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ) ) - { maMacroName = GetLinkManager().GetMacroName( nExtSheet, nExtName ); - // #i38718# missing module name - try to find the macro in the imported modules - if( maMacroName.Len() && (maMacroName.Search( '.' ) == STRING_NOTFOUND) ) - if( SfxObjectShell* pDocShell = GetDocShell() ) - if( StarBASIC* pBasic = pDocShell->GetBasic() ) - if( SbMethod* pMethod = dynamic_cast< SbMethod* >( pBasic->Find( maMacroName, SbxCLASS_METHOD ) ) ) - if( SbModule* pModule = pMethod->GetModule() ) - maMacroName.Insert( '.', 0 ).Insert( pModule->GetName(), 0 ); - } } } } diff --git a/sc/source/filter/excel/xiroot.cxx b/sc/source/filter/excel/xiroot.cxx index 3384cf248c87..3fd2650cf2ff 100644 --- a/sc/source/filter/excel/xiroot.cxx +++ b/sc/source/filter/excel/xiroot.cxx @@ -29,6 +29,8 @@ #include "precompiled_sc.hxx" #include "xiroot.hxx" #include "addincol.hxx" +#include "document.hxx" +#include "scextopt.hxx" #include "xltracer.hxx" #include "xihelper.hxx" #include "xiformula.hxx" @@ -49,7 +51,8 @@ XclImpRootData::XclImpRootData( XclBiff eBiff, SfxMedium& rMedium, SotStorageRef xRootStrg, ScDocument& rDoc, rtl_TextEncoding eTextEnc ) : XclRootData( eBiff, rMedium, xRootStrg, rDoc, eTextEnc, false ), - mbHasCodePage( false ) + mbHasCodePage( false ), + mbHasBasic( false ) { } @@ -272,5 +275,25 @@ String XclImpRoot::GetScAddInName( const String& rXclName ) const return rXclName; } -// ============================================================================ +void XclImpRoot::ReadCodeName( XclImpStream& rStrm, bool bGlobals ) +{ + if( mrImpData.mbHasBasic && (GetBiff() == EXC_BIFF8) ) + { + String aName = rStrm.ReadUniString(); + if( aName.Len() > 0 ) + { + if( bGlobals ) + { + GetExtDocOptions().GetDocSettings().maGlobCodeName = aName; + GetDoc().SetCodeName( aName ); + } + else + { + GetExtDocOptions().AppendCodeName( aName ); + GetDoc().SetCodeName( GetCurrScTab(), aName ); + } + } + } +} +// ============================================================================ diff --git a/sc/source/filter/excel/xlescher.cxx b/sc/source/filter/excel/xlescher.cxx index e1132c1b5606..3b4b8e29ac0b 100644 --- a/sc/source/filter/excel/xlescher.cxx +++ b/sc/source/filter/excel/xlescher.cxx @@ -28,14 +28,15 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sc.hxx" +#include "xlescher.hxx" + #include <com/sun/star/drawing/XControlShape.hpp> #include <com/sun/star/script/ScriptEventDescriptor.hpp> #include <svx/unoapi.hxx> -#include "xestream.hxx" #include "document.hxx" +#include "xestream.hxx" #include "xistream.hxx" -#include "xlescher.hxx" -#include <filter/msfilter/msvbahelper.hxx> +#include "xltools.hxx" using ::rtl::OUString; using ::com::sun::star::uno::Reference; @@ -326,33 +327,7 @@ Reference< XControlModel > XclControlHelper::GetControlModel( Reference< XShape return xCtrlModel; } -#define EXC_MACRONAME_PRE "vnd.sun.star.script:Standard." -#define EXC_MACRONAME_SUF "?language=Basic&location=document" - -OUString XclControlHelper::GetScMacroName( const String& rXclMacroName, SfxObjectShell* pDocShell ) -{ - String sTmp( rXclMacroName ); - if( rXclMacroName.Len() > 0 ) - { - ooo::vba::VBAMacroResolvedInfo aMacro = ooo::vba::resolveVBAMacro( pDocShell, rXclMacroName, false ); - if ( aMacro.IsResolved() ) - return ooo::vba::makeMacroURL( aMacro.ResolvedMacro() ); - - } - return OUString(); -} - -String XclControlHelper::GetXclMacroName( const OUString& rScMacroName ) -{ - const OUString saMacroNamePre = CREATE_OUSTRING( EXC_MACRONAME_PRE ); - const OUString saMacroNameSuf = CREATE_OUSTRING( EXC_MACRONAME_SUF ); - sal_Int32 snScMacroNameLen = rScMacroName.getLength(); - sal_Int32 snXclMacroNameLen = snScMacroNameLen - saMacroNamePre.getLength() - saMacroNameSuf.getLength(); - if( (snXclMacroNameLen > 0) && rScMacroName.matchIgnoreAsciiCase( saMacroNamePre, 0 ) && - rScMacroName.matchIgnoreAsciiCase( saMacroNameSuf, snScMacroNameLen - saMacroNameSuf.getLength() ) ) - return rScMacroName.copy( saMacroNamePre.getLength(), snXclMacroNameLen ); - return String::EmptyString(); -} +namespace { static const struct { @@ -369,17 +344,17 @@ spTbxListenerData[] = /*EXC_TBX_EVENT_CHANGE*/ { "XChangeListener", "changed" } }; -#define EXC_MACROSCRIPT "Script" +} // namespace bool XclControlHelper::FillMacroDescriptor( ScriptEventDescriptor& rDescriptor, - XclTbxEventType eEventType, const String& rXclMacroName, SfxObjectShell* pShell ) + XclTbxEventType eEventType, const String& rXclMacroName, SfxObjectShell* pDocShell ) { if( rXclMacroName.Len() > 0 ) { rDescriptor.ListenerType = OUString::createFromAscii( spTbxListenerData[ eEventType ].mpcListenerType ); rDescriptor.EventMethod = OUString::createFromAscii( spTbxListenerData[ eEventType ].mpcEventMethod ); - rDescriptor.ScriptType = CREATE_OUSTRING( EXC_MACROSCRIPT ); - rDescriptor.ScriptCode = GetScMacroName( rXclMacroName, pShell ); + rDescriptor.ScriptType = CREATE_OUSTRING( "Script" ); + rDescriptor.ScriptCode = XclTools::GetSbMacroUrl( rXclMacroName, pDocShell ); return true; } return false; @@ -389,12 +364,11 @@ String XclControlHelper::ExtractFromMacroDescriptor( const ScriptEventDescriptor& rDescriptor, XclTbxEventType eEventType ) { if( (rDescriptor.ScriptCode.getLength() > 0) && - rDescriptor.ScriptType.equalsIgnoreAsciiCaseAscii( EXC_MACROSCRIPT ) && + rDescriptor.ScriptType.equalsIgnoreAsciiCaseAscii( "Script" ) && rDescriptor.ListenerType.equalsAscii( spTbxListenerData[ eEventType ].mpcListenerType ) && rDescriptor.EventMethod.equalsAscii( spTbxListenerData[ eEventType ].mpcEventMethod ) ) - return GetXclMacroName( rDescriptor.ScriptCode ); + return XclTools::GetXclMacroName( rDescriptor.ScriptCode ); return String::EmptyString(); } // ============================================================================ - diff --git a/sc/source/filter/excel/xltools.cxx b/sc/source/filter/excel/xltools.cxx index 90393ae6a787..0dd988d67586 100644 --- a/sc/source/filter/excel/xltools.cxx +++ b/sc/source/filter/excel/xltools.cxx @@ -34,6 +34,7 @@ #include <unotools/fontcvt.hxx> #include <sfx2/objsh.hxx> #include <editeng/editstat.hxx> +#include <filter/msfilter/msvbahelper.hxx> #include "xestream.hxx" #include "document.hxx" #include "docuno.hxx" @@ -46,6 +47,8 @@ #include "xiroot.hxx" #include "xltools.hxx" +using ::rtl::OUString; + // GUID import/export ========================================================= XclGuid::XclGuid() @@ -684,6 +687,37 @@ void XclTools::SkipSubStream( XclImpStream& rStrm ) } } +// Basic macro names ---------------------------------------------------------- + +const OUString XclTools::maSbMacroPrefix( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.script:Standard." ) ); +const OUString XclTools::maSbMacroSuffix( RTL_CONSTASCII_USTRINGPARAM( "?language=Basic&location=document" ) ); + +OUString XclTools::GetSbMacroUrl( const String& rMacroName, SfxObjectShell* pDocShell ) +{ + OSL_ENSURE( rMacroName.Len() > 0, "XclTools::GetSbMacroUrl - macro name is empty" ); + ::ooo::vba::VBAMacroResolvedInfo aMacroInfo = ::ooo::vba::resolveVBAMacro( pDocShell, rMacroName, false ); + if( aMacroInfo.IsResolved() ) + return ::ooo::vba::makeMacroURL( aMacroInfo.ResolvedMacro() ); + return OUString(); +} + +OUString XclTools::GetSbMacroUrl( const String& rModuleName, const String& rMacroName, SfxObjectShell* pDocShell ) +{ + OSL_ENSURE( rModuleName.Len() > 0, "XclTools::GetSbMacroUrl - module name is empty" ); + OSL_ENSURE( rMacroName.Len() > 0, "XclTools::GetSbMacroUrl - macro name is empty" ); + return GetSbMacroUrl( rModuleName + OUString( sal_Unicode( '.' ) ) + rMacroName, pDocShell ); +} + +String XclTools::GetXclMacroName( const OUString& rSbMacroUrl ) +{ + sal_Int32 nSbMacroUrlLen = rSbMacroUrl.getLength(); + sal_Int32 nMacroNameLen = nSbMacroUrlLen - maSbMacroPrefix.getLength() - maSbMacroSuffix.getLength(); + if( (nMacroNameLen > 0) && rSbMacroUrl.matchIgnoreAsciiCase( maSbMacroPrefix, 0 ) && + rSbMacroUrl.matchIgnoreAsciiCase( maSbMacroSuffix, nSbMacroUrlLen - maSbMacroSuffix.getLength() ) ) + return rSbMacroUrl.copy( maSbMacroPrefix.getLength(), nMacroNameLen ); + return String::EmptyString(); +} + // read/write colors ---------------------------------------------------------- XclImpStream& operator>>( XclImpStream& rStrm, Color& rColor ) @@ -700,4 +734,3 @@ XclExpStream& operator<<( XclExpStream& rStrm, const Color& rColor ) } // ============================================================================ - diff --git a/sc/source/filter/inc/excimp8.hxx b/sc/source/filter/inc/excimp8.hxx index 1340f7c6f8be..5b2bbe2e7b5d 100644 --- a/sc/source/filter/inc/excimp8.hxx +++ b/sc/source/filter/inc/excimp8.hxx @@ -50,37 +50,38 @@ class XclImpStream; class ImportExcel8 : public ImportExcel { - SCTAB mnTab; - protected: - ExcScenarioList aScenList; - - BOOL bHasBasic; - - void Calccount( void ); // 0x0C - void Precision( void ); // 0x0E - void Delta( void ); // 0x10 - void Iteration( void ); // 0x11 - void Boundsheet( void ); // 0x85 - void FilterMode( void ); // 0x9B - void AutoFilterInfo( void ); // 0x9D - void AutoFilter( void ); // 0x9E - void Scenman( void ); // 0xAE - void Scenario( void ); // 0xAF - void ReadBasic( void ); // 0xD3 - void Labelsst( void ); // 0xFD - - void Hlink( void ); // 0x01B8 - void Codename( BOOL bWBGlobals ); // 0x01BA - void SheetProtection( void ); // 0x0867 - - virtual void EndSheet( void ); - virtual void PostDocLoad( void ); - - public: - ImportExcel8( XclImpRootData& rImpData, SvStream& rStrm ); - virtual ~ImportExcel8( void ); - - virtual FltError Read( void ); +public: + ImportExcel8( XclImpRootData& rImpData, SvStream& rStrm ); + virtual ~ImportExcel8( void ); + + virtual FltError Read( void ); + +protected: + ExcScenarioList aScenList; + + void Calccount( void ); // 0x0C + void Precision( void ); // 0x0E + void Delta( void ); // 0x10 + void Iteration( void ); // 0x11 + void Boundsheet( void ); // 0x85 + void FilterMode( void ); // 0x9B + void AutoFilterInfo( void ); // 0x9D + void AutoFilter( void ); // 0x9E + void Scenman( void ); // 0xAE + void Scenario( void ); // 0xAF + void ReadBasic( void ); // 0xD3 + void Labelsst( void ); // 0xFD + + void Hlink( void ); // 0x01B8 + void Codename( BOOL bWBGlobals ); // 0x01BA + void SheetProtection( void ); // 0x0867 + + virtual void EndSheet( void ); + virtual void PostDocLoad( void ); + +private: + void LoadDocumentProperties(); + void AttachDocumentEvents(); }; diff --git a/sc/source/filter/inc/xiroot.hxx b/sc/source/filter/inc/xiroot.hxx index 0e06b31b650d..c5cf284d2d2e 100644 --- a/sc/source/filter/inc/xiroot.hxx +++ b/sc/source/filter/inc/xiroot.hxx @@ -116,6 +116,7 @@ struct XclImpRootData : public XclRootData XclImpDocProtectRef mxDocProtect; /// Document protection options. bool mbHasCodePage; /// true = CODEPAGE record exists. + bool mbHasBasic; /// true = document contains VB project. explicit XclImpRootData( XclBiff eBiff, SfxMedium& rMedium, SotStorageRef xRootStrg, ScDocument& rDoc, rtl_TextEncoding eTextEnc ); @@ -202,6 +203,13 @@ public: /** Returns the Calc add-in function name for an Excel function name. */ String GetScAddInName( const String& rXclName ) const; + /** Returns true, if the document contains a VB project. */ + inline bool HasBasic() const { return mrImpData.mbHasBasic; } + /** Called to indicate that the document contains a VB project. */ + inline void SetHasBasic() { mrImpData.mbHasBasic = true; } + /** Reads the CODENAME record and inserts the codename into the document. */ + void ReadCodeName( XclImpStream& rStrm, bool bGlobals ); + private: mutable XclImpRootData& mrImpData; /// Reference to the global import data struct. }; @@ -209,4 +217,3 @@ private: // ============================================================================ #endif - diff --git a/sc/source/filter/inc/xlconst.hxx b/sc/source/filter/inc/xlconst.hxx index 0ffdcc3f1a6d..42160aae7529 100644 --- a/sc/source/filter/inc/xlconst.hxx +++ b/sc/source/filter/inc/xlconst.hxx @@ -250,7 +250,11 @@ const sal_uInt16 EXC_ID_DSF = 0x0161; const sal_uInt16 EXC_ID_USERSVIEWBEGIN = 0x01AA; const sal_uInt16 EXC_ID_USERSVIEWEND = 0x01AB; -// (0x01C0) XL9FILE -------------------------------------------------------- +// (0x01BA) CODENAME ---------------------------------------------------------- + +const sal_uInt16 EXC_ID_CODENAME = 0x01BA; + +// (0x01C0) XL9FILE ----------------------------------------------------------- const sal_uInt16 EXC_ID_XL9FILE = 0x01C0; diff --git a/sc/source/filter/inc/xlescher.hxx b/sc/source/filter/inc/xlescher.hxx index 95a87b51de12..10194ab41bc0 100644 --- a/sc/source/filter/inc/xlescher.hxx +++ b/sc/source/filter/inc/xlescher.hxx @@ -28,6 +28,7 @@ #ifndef SC_XLESCHER_HXX #define SC_XLESCHER_HXX +#include <tools/gen.hxx> #include <vcl/mapunit.hxx> #include "fapihelper.hxx" #include "xladdress.hxx" @@ -431,16 +432,12 @@ public: static ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > GetControlModel( ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xShape ); - /** Returns the Calc macro name from an Excel macro name. */ - static ::rtl::OUString GetScMacroName( const String& rXclMacroName, SfxObjectShell* pShell = NULL ); - /** Returns the Excel macro name from a Calc macro name. */ - static String GetXclMacroName( const ::rtl::OUString& rScMacroName ); - /** Fills the macro descriptor according to the passed macro name. */ static bool FillMacroDescriptor( ::com::sun::star::script::ScriptEventDescriptor& rDescriptor, XclTbxEventType eEventType, - const String& rXclMacroName, SfxObjectShell* pShell = NULL ); + const String& rXclMacroName, + SfxObjectShell* pDocShell = 0 ); /** Tries to extract an Excel macro name from the passed macro descriptor. */ static String ExtractFromMacroDescriptor( const ::com::sun::star::script::ScriptEventDescriptor& rDescriptor, diff --git a/sc/source/filter/inc/xltools.hxx b/sc/source/filter/inc/xltools.hxx index e8ceed8248d6..efe20a583104 100644 --- a/sc/source/filter/inc/xltools.hxx +++ b/sc/source/filter/inc/xltools.hxx @@ -31,6 +31,8 @@ #include "address.hxx" #include "ftools.hxx" +class SfxObjectShell; + // BIFF versions ============================================================== #define DBG_ERROR_BIFF() DBG_ERRORFILE( "Unknown BIFF type!" ) @@ -229,13 +231,24 @@ public: /** Skips a substream (BOF/EOF record block). Includes all embedded substreams. */ static void SkipSubStream( XclImpStream& rStrm ); - // ------------------------------------------------------------------------ + // Basic macro names ------------------------------------------------------ + + /** Returns the full StarBasic macro URL from an Excel macro name. */ + static ::rtl::OUString GetSbMacroUrl( const String& rMacroName, SfxObjectShell* pDocShell = 0 ); + /** Returns the full StarBasic macro URL from an Excel module and macro name. */ + static ::rtl::OUString GetSbMacroUrl( const String& rModuleName, const String& rMacroName, SfxObjectShell* pDocShell = 0 ); + /** Returns the Excel macro name from a full StarBasic macro URL. */ + static String GetXclMacroName( const ::rtl::OUString& rSbMacroUrl ); + +// ------------------------------------------------------------------------ private: - static const String maDefNamePrefix; /// Prefix for built-in defined names. - static const String maStyleNamePrefix1; /// Prefix for built-in cell style names. - static const String maStyleNamePrefix2; /// Prefix for built-in cell style names from OOX filter. - static const String maCFStyleNamePrefix1; /// Prefix for cond. formatting style names. - static const String maCFStyleNamePrefix2; /// Prefix for cond. formatting style names from OOX filter. + static const String maDefNamePrefix; /// Prefix for built-in defined names. + static const String maStyleNamePrefix1; /// Prefix for built-in cell style names. + static const String maStyleNamePrefix2; /// Prefix for built-in cell style names from OOX filter. + static const String maCFStyleNamePrefix1; /// Prefix for cond. formatting style names. + static const String maCFStyleNamePrefix2; /// Prefix for cond. formatting style names from OOX filter. + static const ::rtl::OUString maSbMacroPrefix; /// Prefix for StarBasic macros. + static const ::rtl::OUString maSbMacroSuffix; /// Suffix for StarBasic macros. }; // read/write colors ---------------------------------------------------------- diff --git a/sc/source/filter/xml/XMLCodeNameProvider.cxx b/sc/source/filter/xml/XMLCodeNameProvider.cxx new file mode 100755 index 000000000000..ca4bac7eb511 --- /dev/null +++ b/sc/source/filter/xml/XMLCodeNameProvider.cxx @@ -0,0 +1,204 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +// INCLUDE --------------------------------------------------------------- + +#include "XMLCodeNameProvider.hxx" +#include "document.hxx" + +using namespace rtl; +using namespace com::sun::star; + +sal_Bool XMLCodeNameProvider::_getCodeName( const uno::Any& aAny, String& rCodeName ) +{ + uno::Sequence<beans::PropertyValue> aProps; + if( !(aAny >>= aProps) ) + return sal_False; + + OUString sCodeNameProp( RTL_CONSTASCII_USTRINGPARAM("CodeName") ); + sal_Int32 nPropCount = aProps.getLength(); + for( sal_Int32 i=0; i<nPropCount; i++ ) + { + if( aProps[i].Name == sCodeNameProp ) + { + OUString sCodeName; + if( aProps[i].Value >>= sCodeName ) + { + rCodeName = sCodeName; + return sal_True; + } + } + } + + return sal_False; +} + + +XMLCodeNameProvider::XMLCodeNameProvider( ScDocument* pDoc ) : + mpDoc( pDoc ), + msDocName( RTL_CONSTASCII_USTRINGPARAM("*doc*") ), + msCodeNameProp( RTL_CONSTASCII_USTRINGPARAM("CodeName") ) +{ +} + +XMLCodeNameProvider::~XMLCodeNameProvider() +{ +} + +::sal_Bool SAL_CALL XMLCodeNameProvider::hasByName( const OUString& aName ) + throw (uno::RuntimeException ) +{ + if( aName == msDocName ) + return mpDoc->GetCodeName().Len() > 0; + + SCTAB nCount = mpDoc->GetTableCount(); + String sName( aName ); + String sSheetName, sCodeName; + for( SCTAB i = 0; i < nCount; i++ ) + { + if( mpDoc->GetName( i, sSheetName ) && sSheetName == sName ) + { + mpDoc->GetCodeName( i, sCodeName ); + return sCodeName.Len() > 0; + } + } + + return sal_False; +} + +uno::Any SAL_CALL XMLCodeNameProvider::getByName( const OUString& aName ) + throw (container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + uno::Any aRet; + uno::Sequence<beans::PropertyValue> aProps(1); + aProps[0].Name = msCodeNameProp; + if( aName == msDocName ) + { + OUString sUCodeName( mpDoc->GetCodeName() ); + aProps[0].Value <<= sUCodeName; + aRet <<= aProps; + return aRet; + } + + SCTAB nCount = mpDoc->GetTableCount(); + String sName( aName ); + String sSheetName, sCodeName; + for( SCTAB i = 0; i < nCount; i++ ) + { + if( mpDoc->GetName( i, sSheetName ) && sSheetName == sName ) + { + mpDoc->GetCodeName( i, sCodeName ); + OUString sUCodeName( sCodeName ); + aProps[0].Value <<= sUCodeName; + aRet <<= aProps; + return aRet; + } + } + + return aRet; +} + +uno::Sequence< OUString > SAL_CALL XMLCodeNameProvider::getElementNames( ) + throw (uno::RuntimeException) +{ + SCTAB nCount = mpDoc->GetTableCount() + 1; + uno::Sequence< rtl::OUString > aNames( nCount ); + sal_Int32 nRealCount = 0; + + if( mpDoc->GetCodeName().Len() ) + aNames[nRealCount++] = msDocName; + + String sSheetName, sCodeName; + for( SCTAB i = 0; i < nCount; i++ ) + { + mpDoc->GetCodeName( i, sCodeName ); + if( sCodeName.Len() > 0 ) + { + if( mpDoc->GetName( i, sSheetName ) ) + aNames[nRealCount++] = sSheetName; + } + } + + if( nCount != nRealCount ) + aNames.realloc( nRealCount ); + + return aNames; +} + +uno::Type SAL_CALL XMLCodeNameProvider::getElementType( ) + throw (uno::RuntimeException) +{ + return uno::Type(); +} + +::sal_Bool SAL_CALL XMLCodeNameProvider::hasElements() + throw (uno::RuntimeException ) +{ + if( mpDoc->GetCodeName().Len() > 0 ) + return sal_True; + + SCTAB nCount = mpDoc->GetTableCount(); + String sSheetName, sCodeName; + for( SCTAB i = 0; i < nCount; i++ ) + { + mpDoc->GetCodeName( i, sCodeName ); + if( sCodeName.Len() > 0 && mpDoc->GetName( i, sSheetName ) ) + return sal_True; + } + + return sal_False; +} + +void XMLCodeNameProvider::set( const uno::Reference< container::XNameAccess>& xNameAccess, ScDocument *pDoc ) +{ + uno::Any aAny; + OUString sDocName( RTL_CONSTASCII_USTRINGPARAM("*doc*") ); + String sCodeName; + if( xNameAccess->hasByName( sDocName ) ) + { + aAny = xNameAccess->getByName( sDocName ); + if( _getCodeName( aAny, sCodeName ) ) + pDoc->SetCodeName( sCodeName ); + } + + SCTAB nCount = pDoc->GetTableCount(); + String sSheetName; + for( SCTAB i = 0; i < nCount; i++ ) + { + if( pDoc->GetName( i, sSheetName ) && + xNameAccess->hasByName( sSheetName ) ) + { + aAny = xNameAccess->getByName( sSheetName ); + if( _getCodeName( aAny, sCodeName ) ) + pDoc->SetCodeName( i, sCodeName ); + } + } +} diff --git a/sc/source/filter/xml/XMLCodeNameProvider.hxx b/sc/source/filter/xml/XMLCodeNameProvider.hxx new file mode 100755 index 000000000000..39d84409c555 --- /dev/null +++ b/sc/source/filter/xml/XMLCodeNameProvider.hxx @@ -0,0 +1,70 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef SC_XMLCODENAMEPROVIDER_HXX +#define SC_XMLCODENAMEPROVIDER_HXX + +#include <com/sun/star/container/XNameAccess.hpp> +#include <cppuhelper/implbase1.hxx> + +class ScDocument; +class String; + +class XMLCodeNameProvider : public ::cppu::WeakImplHelper1< ::com::sun::star::container::XNameAccess > +{ + ScDocument* mpDoc; + ::rtl::OUString msDocName; + ::rtl::OUString msCodeNameProp; + + static sal_Bool _getCodeName( const ::com::sun::star::uno::Any& aAny, + String& rCodeName ); + +public: + XMLCodeNameProvider( ScDocument* pDoc ); + virtual ~XMLCodeNameProvider(); + + virtual ::sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) + throw (::com::sun::star::uno::RuntimeException ); + + virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) + throw (::com::sun::star::container::NoSuchElementException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) + throw (::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Type SAL_CALL getElementType( ) + throw (::com::sun::star::uno::RuntimeException); + + virtual ::sal_Bool SAL_CALL hasElements() + throw (::com::sun::star::uno::RuntimeException ); + + static void set( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess>& xNameAccess, ScDocument *pDoc ); +}; + +#endif diff --git a/sc/source/filter/xml/makefile.mk b/sc/source/filter/xml/makefile.mk index 360148d38244..7f9f2d529a90 100644 --- a/sc/source/filter/xml/makefile.mk +++ b/sc/source/filter/xml/makefile.mk @@ -96,7 +96,8 @@ SLOFILES = \ $(SLO)$/XMLChangeTrackingImportHelper.obj \ $(SLO)$/XMLTrackedChangesContext.obj \ $(SLO)$/XMLExportSharedData.obj \ - $(SLO)$/XMLEmptyContext.obj + $(SLO)$/XMLEmptyContext.obj \ + $(SLO)$/XMLCodeNameProvider.obj NOOPTFILES= \ diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx index 8121de6a46e1..baa0a664ac53 100644 --- a/sc/source/filter/xml/xmlexprt.cxx +++ b/sc/source/filter/xml/xmlexprt.cxx @@ -80,6 +80,7 @@ #include <xmloff/txtparae.hxx> #include <xmloff/xmlcnitm.hxx> #include <xmloff/xmlerror.hxx> +#include <xmloff/XMLEventExport.hxx> #include <rtl/ustring.hxx> @@ -134,6 +135,8 @@ #include <com/sun/star/document/XDocumentProperties.hpp> #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> +#include "XMLCodeNameProvider.hxx" + #include <sfx2/objsh.hxx> #include <vector> @@ -1745,6 +1748,16 @@ void ScXMLExport::_ExportContent() AddAttribute( XML_NAMESPACE_TABLE, XML_PRINT, XML_FALSE); SvXMLElementExport aElemT(*this, sElemTab, sal_True, sal_True); CheckAttrList(); + + if ( pDoc && pDoc->GetSheetEvents( static_cast<SCTAB>(nTable) ) && + getDefaultVersion() == SvtSaveOptions::ODFVER_LATEST ) + { + // store sheet events + uno::Reference<document::XEventsSupplier> xSupplier(xTable, uno::UNO_QUERY); + uno::Reference<container::XNameAccess> xEvents(xSupplier->getEvents(), uno::UNO_QUERY); + GetEventExport().ExportExt( xEvents ); + } + WriteTableSource(); WriteScenario(); uno::Reference<drawing::XDrawPage> xDrawPage; @@ -4265,6 +4278,9 @@ void ScXMLExport::GetViewSettings(uno::Sequence<beans::PropertyValue>& rProps) GetChangeTrackViewSettings(rProps); } + + + void ScXMLExport::GetConfigurationSettings(uno::Sequence<beans::PropertyValue>& rProps) { if (GetModel().is()) @@ -4275,16 +4291,41 @@ void ScXMLExport::GetConfigurationSettings(uno::Sequence<beans::PropertyValue>& uno::Reference <beans::XPropertySet> xProperties(xMultiServiceFactory->createInstance(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.SpreadsheetSettings"))), uno::UNO_QUERY); if (xProperties.is()) SvXMLUnitConverter::convertPropertySet(rProps, xProperties); + + sal_Int32 nPropsToAdd = 0; + rtl::OUStringBuffer aTrackedChangesKey; if (GetDocument() && GetDocument()->GetChangeTrack() && GetDocument()->GetChangeTrack()->IsProtected()) { - rtl::OUStringBuffer aBuffer; - SvXMLUnitConverter::encodeBase64(aBuffer, GetDocument()->GetChangeTrack()->GetProtection()); - if (aBuffer.getLength()) + SvXMLUnitConverter::encodeBase64(aTrackedChangesKey, GetDocument()->GetChangeTrack()->GetProtection()); + if (aTrackedChangesKey.getLength()) + ++nPropsToAdd; + } + + uno::Reference <container::XNameAccess> xCodeNameAccess; + DBG_ASSERT( pDoc, "ScXMLExport::GetConfigurationSettings - no ScDocument!" ); + if( pDoc ) + { + xCodeNameAccess = new XMLCodeNameProvider( pDoc ); + if( xCodeNameAccess.is() && xCodeNameAccess->hasElements() ) + ++nPropsToAdd; + else + xCodeNameAccess = 0; + } + + if( nPropsToAdd > 0 ) + { + sal_Int32 nCount(rProps.getLength()); + rProps.realloc(nCount + nPropsToAdd); + if (aTrackedChangesKey.getLength()) { - sal_Int32 nCount(rProps.getLength()); - rProps.realloc(nCount + 1); rProps[nCount].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TrackedChangesProtectionKey")); - rProps[nCount].Value <<= aBuffer.makeStringAndClear(); + rProps[nCount].Value <<= aTrackedChangesKey.makeStringAndClear(); + ++nCount; + } + if( xCodeNameAccess.is() ) + { + rProps[nCount].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ScriptConfiguration")); + rProps[nCount].Value <<= xCodeNameAccess; } } } @@ -4372,6 +4413,22 @@ sal_uInt32 ScXMLExport::exportDoc( enum XMLTokenEnum eClass ) CollectUserDefinedNamespaces(&pDrawLayer->GetItemPool(), EE_CHAR_XMLATTRIBS); CollectUserDefinedNamespaces(&pDrawLayer->GetItemPool(), SDRATTR_XMLATTRIBUTES); } + + // sheet events use officeooo namespace + if( (getExportFlags() & EXPORT_CONTENT) != 0 && + getDefaultVersion() == SvtSaveOptions::ODFVER_LATEST ) + { + bool bAnySheetEvents = false; + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab=0; nTab<nTabCount; ++nTab) + if (pDoc->GetSheetEvents(nTab)) + bAnySheetEvents = true; + if (bAnySheetEvents) + _GetNamespaceMap().Add( + GetXMLToken( XML_NP_OFFICE_EXT ), + GetXMLToken( XML_N_OFFICE_EXT ), + XML_NAMESPACE_OFFICE_EXT ); + } } } return SvXMLExport::exportDoc( eClass ); diff --git a/sc/source/filter/xml/xmlimprt.cxx b/sc/source/filter/xml/xmlimprt.cxx index 58ea9e0e5b17..269e1dd9a7e4 100644 --- a/sc/source/filter/xml/xmlimprt.cxx +++ b/sc/source/filter/xml/xmlimprt.cxx @@ -645,6 +645,8 @@ const SvXMLTokenMap& ScXMLImport::GetTableElemTokenMap() { XML_NAMESPACE_TABLE, XML_SCENARIO, XML_TOK_TABLE_SCENARIO }, { XML_NAMESPACE_TABLE, XML_SHAPES, XML_TOK_TABLE_SHAPES }, { XML_NAMESPACE_OFFICE, XML_FORMS, XML_TOK_TABLE_FORMS }, + { XML_NAMESPACE_OFFICE, XML_EVENT_LISTENERS, XML_TOK_TABLE_EVENT_LISTENERS }, + { XML_NAMESPACE_OFFICE_EXT, XML_EVENT_LISTENERS, XML_TOK_TABLE_EVENT_LISTENERS_EXT }, XML_TOKEN_MAP_END }; @@ -2216,10 +2218,11 @@ void ScXMLImport::SetConfigurationSettings(const uno::Sequence<beans::PropertyVa if (xMultiServiceFactory.is()) { sal_Int32 nCount(aConfigProps.getLength()); - rtl::OUString sName(RTL_CONSTASCII_USTRINGPARAM("TrackedChangesProtectionKey")); + rtl::OUString sCTName(RTL_CONSTASCII_USTRINGPARAM("TrackedChangesProtectionKey")); + rtl::OUString sSCName(RTL_CONSTASCII_USTRINGPARAM("ScriptConfiguration")); for (sal_Int32 i = nCount - 1; i >= 0; --i) { - if (aConfigProps[i].Name == sName) + if (aConfigProps[i].Name == sCTName) { rtl::OUString sKey; if (aConfigProps[i].Value >>= sKey) @@ -2240,6 +2243,28 @@ void ScXMLImport::SetConfigurationSettings(const uno::Sequence<beans::PropertyVa } } } + else if (aConfigProps[i].Name == sSCName) + { + uno::Type aType = aConfigProps[i].Value.getValueType(); + uno::Reference<beans::XPropertySet> xImportInfo = + getImportInfo(); + + if (xImportInfo.is() && + (aType.equals(getCppuType( + (uno::Reference<container::XNameContainer> *)0 ) ) || + aType.equals(getCppuType( + (uno::Reference<container::XNameAccess> *)0 ) ) ) ) + { + uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = + xImportInfo->getPropertySetInfo(); + if (xPropertySetInfo.is() && + xPropertySetInfo->hasPropertyByName(sSCName) ) + { + xImportInfo->setPropertyValue(sSCName, + aConfigProps[i].Value ); + } + } + } } uno::Reference <uno::XInterface> xInterface = xMultiServiceFactory->createInstance(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.SpreadsheetSettings"))); uno::Reference <beans::XPropertySet> xProperties(xInterface, uno::UNO_QUERY); diff --git a/sc/source/filter/xml/xmlimprt.hxx b/sc/source/filter/xml/xmlimprt.hxx index e2cea5ae9609..9771655ebd4b 100644 --- a/sc/source/filter/xml/xmlimprt.hxx +++ b/sc/source/filter/xml/xmlimprt.hxx @@ -174,7 +174,9 @@ enum ScXMLTableTokens XML_TOK_TABLE_SOURCE, XML_TOK_TABLE_SCENARIO, XML_TOK_TABLE_SHAPES, - XML_TOK_TABLE_FORMS + XML_TOK_TABLE_FORMS, + XML_TOK_TABLE_EVENT_LISTENERS, + XML_TOK_TABLE_EVENT_LISTENERS_EXT }; enum ScXMLTableRowsTokens diff --git a/sc/source/filter/xml/xmltabi.cxx b/sc/source/filter/xml/xmltabi.cxx index 095b6ee6d450..69f00106b7c7 100644 --- a/sc/source/filter/xml/xmltabi.cxx +++ b/sc/source/filter/xml/xmltabi.cxx @@ -53,6 +53,7 @@ #include <xmloff/nmspmap.hxx> #include <xmloff/formsimp.hxx> #include <xmloff/xmltoken.hxx> +#include <xmloff/XMLEventsImportContext.hxx> #include <com/sun/star/sheet/XSpreadsheetDocument.hpp> #include <com/sun/star/sheet/XSpreadsheets.hpp> @@ -323,6 +324,14 @@ SvXMLImportContext *ScXMLTableContext::CreateChildContext( USHORT nPrefix, pContext = GetScImport().GetFormImport()->createOfficeFormsContext( GetScImport(), nPrefix, rLName ); } break; + case XML_TOK_TABLE_EVENT_LISTENERS: + case XML_TOK_TABLE_EVENT_LISTENERS_EXT: + { + // use XEventsSupplier interface of the sheet + uno::Reference<document::XEventsSupplier> xSupplier( GetScImport().GetTables().GetCurrentXSheet(), uno::UNO_QUERY ); + pContext = new XMLEventsImportContext( GetImport(), nPrefix, rLName, xSupplier ); + } + break; default: ; } diff --git a/sc/source/filter/xml/xmlwrap.cxx b/sc/source/filter/xml/xmlwrap.cxx index f21ed7d55ac2..dbe647bc433f 100644 --- a/sc/source/filter/xml/xmlwrap.cxx +++ b/sc/source/filter/xml/xmlwrap.cxx @@ -80,6 +80,7 @@ #include "XMLExportSharedData.hxx" #include "docuno.hxx" #include "sheetdata.hxx" +#include "XMLCodeNameProvider.hxx" #define MAP_LEN(x) x, sizeof(x) - 1 @@ -425,6 +426,7 @@ sal_Bool ScXMLImportWrapper::Import(sal_Bool bStylesOnly, ErrCode& nError) { MAP_LEN( "StreamRelPath" ), 0, &::getCppuType( (rtl::OUString *)0 ), ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0 }, { MAP_LEN( "StreamName" ), 0, &::getCppuType( (rtl::OUString *)0 ), ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0 }, { MAP_LEN( "BuildId" ), 0, &::getCppuType( (OUString *)0 ), ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0 }, + { MAP_LEN( "ScriptConfiguration" ), 0, &::getCppuType((uno::Reference<container::XNameAccess> *)0), ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0}, { NULL, 0, 0, NULL, 0, 0 } }; @@ -635,6 +637,12 @@ sal_Bool ScXMLImportWrapper::Import(sal_Bool bStylesOnly, ErrCode& nError) xModelSet->setPropertyValue( sBuildPropName, xInfoSet->getPropertyValue(sBuildPropName) ); } } + + // Set Code Names + uno::Any aAny = xInfoSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("ScriptConfiguration") )); + uno::Reference <container::XNameAccess> xCodeNameAccess; + if( aAny >>= xCodeNameAccess ) + XMLCodeNameProvider::set( xCodeNameAccess, &rDoc ); } // Don't test bStylesRetval and bMetaRetval, because it could be an older file which not contain such streams diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx index 5ca2a01f05c9..34c758dfc78d 100644 --- a/sc/source/ui/docshell/docfunc.cxx +++ b/sc/source/ui/docshell/docfunc.cxx @@ -2792,6 +2792,7 @@ BOOL ScDocFunc::DeleteTable( SCTAB nTab, BOOL bRecord, BOOL /* bApi */ ) } pUndoDoc->SetVisible( nTab, pDoc->IsVisible( nTab ) ); pUndoDoc->SetTabBgColor( nTab, pDoc->GetTabBgColor(nTab) ); + pUndoDoc->SetSheetEvents( nTab, pDoc->GetSheetEvents( nTab ) ); // Drawing-Layer muss sein Undo selbst in der Hand behalten !!! pDoc->BeginDrawUndo(); // DeleteTab erzeugt ein SdrUndoDelPage diff --git a/sc/source/ui/docshell/docsh4.cxx b/sc/source/ui/docshell/docsh4.cxx index 1fe5cc7a74ba..03f4516b7281 100755 --- a/sc/source/ui/docshell/docsh4.cxx +++ b/sc/source/ui/docshell/docsh4.cxx @@ -121,9 +121,9 @@ using namespace ::com::sun::star; #include "scresid.hxx" //add by CHINA001 #include "scabstdlg.hxx" //CHINA001 #include "externalrefmgr.hxx" - #include "sharedocdlg.hxx" #include "conditio.hxx" +#include "sheetevents.hxx" //------------------------------------------------------------------ @@ -1289,6 +1289,14 @@ void ScDocShell::DoHardRecalc( BOOL /* bApi */ ) if ( pSh ) pSh->UpdateCharts(TRUE); + // set notification flags for "calculate" event (used in SFX_HINT_DATACHANGED broadcast) + // (might check for the presence of any formulas on each sheet) + SCTAB nTabCount = aDocument.GetTableCount(); + SCTAB nTab; + if (aDocument.HasSheetEventScript( SC_SHEETEVENT_CALCULATE )) + for (nTab=0; nTab<nTabCount; nTab++) + aDocument.SetCalcNotification(nTab); + // CalcAll doesn't broadcast value changes, so SC_HINT_CALCALL is broadcasted globally // in addition to SFX_HINT_DATACHANGED. aDocument.BroadcastUno( SfxSimpleHint( SC_HINT_CALCALL ) ); @@ -1296,8 +1304,7 @@ void ScDocShell::DoHardRecalc( BOOL /* bApi */ ) // use hard recalc also to disable stream-copying of all sheets // (somewhat consistent with charts) - SCTAB nTabCount = aDocument.GetTableCount(); - for (SCTAB nTab=0; nTab<nTabCount; nTab++) + for (nTab=0; nTab<nTabCount; nTab++) if (aDocument.IsStreamValid(nTab)) aDocument.SetStreamValid(nTab, FALSE); diff --git a/sc/source/ui/src/popup.src b/sc/source/ui/src/popup.src index ece9a0a8b1aa..9753aa1590e3 100644 --- a/sc/source/ui/src/popup.src +++ b/sc/source/ui/src/popup.src @@ -190,6 +190,12 @@ Menu RID_POPUP_TAB HelpId = FID_TAB_RTL ; Text [ en-US ] = "S~heet Right-To-Left" ; }; + MenuItem + { + Identifier = FID_TAB_EVENTS ; + HelpId = FID_TAB_EVENTS ; + Text [ en-US ] = "Sheet E~vents..." ; + }; //------------------------------ MenuItem { Separator = TRUE ; }; //------------------------------ diff --git a/sc/source/ui/undo/undotab.cxx b/sc/source/ui/undo/undotab.cxx index b3a7db1148fe..2d8340ad030b 100644 --- a/sc/source/ui/undo/undotab.cxx +++ b/sc/source/ui/undo/undotab.cxx @@ -414,6 +414,7 @@ void ScUndoDeleteTab::Undo() } pDoc->SetVisible( nTab, pRefUndoDoc->IsVisible( nTab ) ); pDoc->SetTabBgColor( nTab, pRefUndoDoc->GetTabBgColor(nTab) ); + pDoc->SetSheetEvents( nTab, pRefUndoDoc->GetSheetEvents( nTab ) ); if ( pRefUndoDoc->IsTabProtected( nTab ) ) pDoc->SetTabProtection(nTab, pRefUndoDoc->GetTabProtection(nTab)); diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx index 6233d5f8944e..b62a4e4eb633 100644 --- a/sc/source/ui/unoobj/cellsuno.cxx +++ b/sc/source/ui/unoobj/cellsuno.cxx @@ -84,6 +84,7 @@ #include "srchuno.hxx" #include "targuno.hxx" #include "tokenuno.hxx" +#include "eventuno.hxx" #include "docsh.hxx" #include "markdata.hxx" #include "patattr.hxx" @@ -6838,6 +6839,7 @@ uno::Any SAL_CALL ScTableSheetObj::queryInterface( const uno::Type& rType ) thro SC_QUERYINTERFACE( sheet::XScenarioEnhanced ) SC_QUERYINTERFACE( sheet::XSheetLinkable ) SC_QUERYINTERFACE( sheet::XExternalSheetName ) + SC_QUERYINTERFACE( document::XEventsSupplier ) return ScCellRangeObj::queryInterface( rType ); } @@ -6861,7 +6863,7 @@ uno::Sequence<uno::Type> SAL_CALL ScTableSheetObj::getTypes() throw(uno::Runtime long nParentLen = aParentTypes.getLength(); const uno::Type* pParentPtr = aParentTypes.getConstArray(); - aTypes.realloc( nParentLen + 17 ); + aTypes.realloc( nParentLen + 18 ); uno::Type* pPtr = aTypes.getArray(); pPtr[nParentLen + 0] = getCppuType((const uno::Reference<sheet::XSpreadsheet>*)0); pPtr[nParentLen + 1] = getCppuType((const uno::Reference<container::XNamed>*)0); @@ -6880,6 +6882,7 @@ uno::Sequence<uno::Type> SAL_CALL ScTableSheetObj::getTypes() throw(uno::Runtime pPtr[nParentLen +14] = getCppuType((const uno::Reference<sheet::XScenarioEnhanced>*)0); pPtr[nParentLen +15] = getCppuType((const uno::Reference<sheet::XSheetLinkable>*)0); pPtr[nParentLen +16] = getCppuType((const uno::Reference<sheet::XExternalSheetName>*)0); + pPtr[nParentLen +17] = getCppuType((const uno::Reference<document::XEventsSupplier>*)0); for (long i=0; i<nParentLen; i++) pPtr[i] = pParentPtr[i]; // parent types first @@ -8161,6 +8164,18 @@ void ScTableSheetObj::setExternalName( const ::rtl::OUString& aUrl, const ::rtl: } } +// XEventsSupplier + +uno::Reference<container::XNameReplace> SAL_CALL ScTableSheetObj::getEvents() throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + return new ScSheetEventsObj( pDocSh, GetTab_Impl() ); + + return NULL; +} + // XPropertySet erweitert fuer Sheet-Properties uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTableSheetObj::getPropertySetInfo() diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx index 4f07767a1c88..bc32b7592dc4 100644 --- a/sc/source/ui/unoobj/docuno.cxx +++ b/sc/source/ui/unoobj/docuno.cxx @@ -96,6 +96,7 @@ #include "scmod.hxx" #include "rangeutl.hxx" #include "ViewSettingsSequenceDefines.hxx" +#include "sheetevents.hxx" #include "sc.hrc" #include "scresid.hxx" @@ -590,6 +591,10 @@ void ScModelObj::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) // (if a broadcast is added to SetDrawModified, is has to be tested here, too) DELETEZ( pPrintFuncCache ); + + // handle "OnCalculate" sheet events + if ( pDocShell && pDocShell->GetDocument()->HasSheetEventScript( SC_SHEETEVENT_CALCULATE ) ) + HandleCalculateEvents(); } } else if ( rHint.ISA( ScPointerChangedHint ) ) @@ -2075,11 +2080,11 @@ sal_Int64 SAL_CALL ScModelObj::getSomething( } if ( rId.getLength() == 16 && - 0 == rtl_compareMemory( SfxObjectShell::getUnoTunnelId().getConstArray(), + 0 == rtl_compareMemory( SfxObjectShell::getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) - { - return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(pDocShell )); - } + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(pDocShell )); + } // aggregated number formats supplier has XUnoTunnel, too // interface from aggregated object must be obtained via queryAggregation @@ -2148,7 +2153,23 @@ void ScModelObj::removeChangesListener( const uno::Reference< util::XChangesList bool ScModelObj::HasChangesListeners() const { - return ( maChangesListeners.getLength() > 0 ); + if ( maChangesListeners.getLength() > 0 ) + return true; + + if ( pDocShell ) + { + // "change" event set in any sheet? + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab = 0; nTab < nTabCount; nTab++) + { + const ScSheetEvents* pEvents = pDoc->GetSheetEvents(nTab); + if (pEvents && pEvents->GetScript(SC_SHEETEVENT_CHANGE)) + return true; + } + } + + return false; } void ScModelObj::NotifyChanges( const ::rtl::OUString& rOperation, const ScRangeList& rRanges, @@ -2194,6 +2215,91 @@ void ScModelObj::NotifyChanges( const ::rtl::OUString& rOperation, const ScRange } } } + + // handle sheet events + //! separate method with ScMarkData? Then change HasChangesListeners back. + if ( rOperation.compareToAscii("cell-change") == 0 && pDocShell ) + { + ScMarkData aMarkData; + aMarkData.MarkFromRangeList( rRanges, FALSE ); + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab = 0; nTab < nTabCount; nTab++) + if (aMarkData.GetTableSelect(nTab)) + { + const ScSheetEvents* pEvents = pDoc->GetSheetEvents(nTab); + if (pEvents) + { + const rtl::OUString* pScript = pEvents->GetScript(SC_SHEETEVENT_CHANGE); + if (pScript) + { + ScRangeList aTabRanges; // collect ranges on this sheet + ULONG nRangeCount = rRanges.Count(); + for ( ULONG nIndex = 0; nIndex < nRangeCount; ++nIndex ) + { + ScRange aRange( *rRanges.GetObject( nIndex ) ); + if ( aRange.aStart.Tab() == nTab ) + aTabRanges.Append( aRange ); + } + ULONG nTabRangeCount = aTabRanges.Count(); + if ( nTabRangeCount > 0 ) + { + uno::Reference<uno::XInterface> xTarget; + if ( nTabRangeCount == 1 ) + { + ScRange aRange( *aTabRanges.GetObject( 0 ) ); + if ( aRange.aStart == aRange.aEnd ) + xTarget.set( static_cast<cppu::OWeakObject*>( new ScCellObj( pDocShell, aRange.aStart ) ) ); + else + xTarget.set( static_cast<cppu::OWeakObject*>( new ScCellRangeObj( pDocShell, aRange ) ) ); + } + else + xTarget.set( static_cast<cppu::OWeakObject*>( new ScCellRangesObj( pDocShell, aTabRanges ) ) ); + + uno::Sequence<uno::Any> aParams(1); + aParams[0] <<= xTarget; + + uno::Any aRet; + uno::Sequence<sal_Int16> aOutArgsIndex; + uno::Sequence<uno::Any> aOutArgs; + + /*ErrCode eRet =*/ pDocShell->CallXScript( *pScript, aParams, aRet, aOutArgsIndex, aOutArgs ); + } + } + } + } + } +} + +void ScModelObj::HandleCalculateEvents() +{ + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + // don't call events before the document is visible + // (might also set a flag on SFX_EVENT_LOADFINISHED and only disable while loading) + if ( pDoc->IsDocVisible() ) + { + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab = 0; nTab < nTabCount; nTab++) + { + const ScSheetEvents* pEvents = pDoc->GetSheetEvents(nTab); + if (pEvents) + { + const rtl::OUString* pScript = pEvents->GetScript(SC_SHEETEVENT_CALCULATE); + if (pScript && pDoc->HasCalcNotification(nTab)) + { + uno::Any aRet; + uno::Sequence<uno::Any> aParams; + uno::Sequence<sal_Int16> aOutArgsIndex; + uno::Sequence<uno::Any> aOutArgs; + pDocShell->CallXScript( *pScript, aParams, aRet, aOutArgsIndex, aOutArgs ); + } + } + } + } + pDoc->ResetCalcNotifications(); + } } //------------------------------------------------------------------------ diff --git a/sc/source/ui/unoobj/eventuno.cxx b/sc/source/ui/unoobj/eventuno.cxx new file mode 100755 index 000000000000..d7de00f4cc56 --- /dev/null +++ b/sc/source/ui/unoobj/eventuno.cxx @@ -0,0 +1,201 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tokenuno.cxx,v $ + * $Revision: 1.6.108.8 $ + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +#include "eventuno.hxx" +#include "miscuno.hxx" +#include "unoguard.hxx" +#include "docsh.hxx" +#include "sheetevents.hxx" +#include "unonames.hxx" + +using namespace ::com::sun::star; + +//------------------------------------------------------------------------ + +SC_SIMPLE_SERVICE_INFO( ScSheetEventsObj, "ScSheetEventsObj", "com.sun.star.document.Events" ) + +//------------------------------------------------------------------------ + +ScSheetEventsObj::ScSheetEventsObj(ScDocShell* pDocSh, SCTAB nT) : + mpDocShell( pDocSh ), + mnTab( nT ) +{ + mpDocShell->GetDocument()->AddUnoObject(*this); +} + +ScSheetEventsObj::~ScSheetEventsObj() +{ + if (mpDocShell) + mpDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScSheetEventsObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + //! reference update + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + mpDocShell = NULL; + } +} + +sal_Int32 lcl_GetEventFromName( const rtl::OUString& aName ) +{ + for (sal_Int32 nEvent=0; nEvent<SC_SHEETEVENT_COUNT; ++nEvent) + if ( aName == ScSheetEvents::GetEventName(nEvent) ) + return nEvent; + + return -1; // not found +} + +// XNameReplace + +void SAL_CALL ScSheetEventsObj::replaceByName( const rtl::OUString& aName, const uno::Any& aElement ) + throw(lang::IllegalArgumentException, container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (!mpDocShell) + throw uno::RuntimeException(); + + sal_Int32 nEvent = lcl_GetEventFromName(aName); + if (nEvent < 0) + throw container::NoSuchElementException(); + + ScSheetEvents aNewEvents; + const ScSheetEvents* pOldEvents = mpDocShell->GetDocument()->GetSheetEvents(mnTab); + if (pOldEvents) + aNewEvents = *pOldEvents; + + rtl::OUString aScript; + if ( aElement.hasValue() ) // empty Any -> reset event + { + uno::Sequence<beans::PropertyValue> aPropSeq; + if ( aElement >>= aPropSeq ) + { + sal_Int32 nPropCount = aPropSeq.getLength(); + for (sal_Int32 nPos=0; nPos<nPropCount; ++nPos) + { + const beans::PropertyValue& rProp = aPropSeq[nPos]; + if ( rProp.Name.compareToAscii( SC_UNO_EVENTTYPE ) == 0 ) + { + rtl::OUString aEventType; + if ( rProp.Value >>= aEventType ) + { + // only "Script" is supported + if ( aEventType.compareToAscii( SC_UNO_SCRIPT ) != 0 ) + throw lang::IllegalArgumentException(); + } + } + else if ( rProp.Name.compareToAscii( SC_UNO_SCRIPT ) == 0 ) + rProp.Value >>= aScript; + } + } + } + if (aScript.getLength()) + aNewEvents.SetScript( nEvent, &aScript ); + else + aNewEvents.SetScript( nEvent, NULL ); // reset + + mpDocShell->GetDocument()->SetSheetEvents( mnTab, &aNewEvents ); + mpDocShell->SetDocumentModified(); +} + +// XNameAccess + +uno::Any SAL_CALL ScSheetEventsObj::getByName( const rtl::OUString& aName ) + throw(container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + sal_Int32 nEvent = lcl_GetEventFromName(aName); + if (nEvent < 0) + throw container::NoSuchElementException(); + + const rtl::OUString* pScript = NULL; + if (mpDocShell) + { + const ScSheetEvents* pEvents = mpDocShell->GetDocument()->GetSheetEvents(mnTab); + if (pEvents) + pScript = pEvents->GetScript(nEvent); + } + + uno::Any aRet; + if (pScript) + { + uno::Sequence<beans::PropertyValue> aPropSeq( 2 ); + aPropSeq[0] = beans::PropertyValue( + rtl::OUString::createFromAscii("EventType"), -1, + uno::makeAny( rtl::OUString::createFromAscii("Script") ), beans::PropertyState_DIRECT_VALUE ); + aPropSeq[1] = beans::PropertyValue( + rtl::OUString::createFromAscii("Script"), -1, + uno::makeAny( *pScript ), beans::PropertyState_DIRECT_VALUE ); + aRet <<= aPropSeq; + } + // empty Any if nothing was set + return aRet; +} + +uno::Sequence<rtl::OUString> SAL_CALL ScSheetEventsObj::getElementNames() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Sequence<rtl::OUString> aNames(SC_SHEETEVENT_COUNT); + for (sal_Int32 nEvent=0; nEvent<SC_SHEETEVENT_COUNT; ++nEvent) + aNames[nEvent] = ScSheetEvents::GetEventName(nEvent); + return aNames; +} + +sal_Bool SAL_CALL ScSheetEventsObj::hasByName( const ::rtl::OUString& aName ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + sal_Int32 nEvent = lcl_GetEventFromName(aName); + return (nEvent >= 0); +} + +// XElementAccess + +uno::Type SAL_CALL ScSheetEventsObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Sequence<beans::PropertyValue>*)0); +} + +sal_Bool SAL_CALL ScSheetEventsObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (mpDocShell) + return sal_True; + return sal_False; +} + + + diff --git a/sc/source/ui/unoobj/funcuno.cxx b/sc/source/ui/unoobj/funcuno.cxx index 0c197a8b738d..7012b477050c 100644 --- a/sc/source/ui/unoobj/funcuno.cxx +++ b/sc/source/ui/unoobj/funcuno.cxx @@ -34,6 +34,7 @@ #include <sfx2/app.hxx> #include <svl/itemprop.hxx> +#include "scitems.hxx" #include "funcuno.hxx" #include "miscuno.hxx" #include "cellsuno.hxx" @@ -55,6 +56,7 @@ #include "docpool.hxx" #include "attrib.hxx" #include "clipparam.hxx" +#include "dociter.hxx" using namespace com::sun::star; @@ -185,6 +187,32 @@ BOOL lcl_CopyData( ScDocument* pSrcDoc, const ScRange& rSrcRange, pClipDoc->ApplyPatternAreaTab( 0,0, MAXCOL,MAXROW, nSrcTab, aPattern ); } + // If the range contains formula cells with default number format, + // apply a number format for the formula result + ScCellIterator aIter( pClipDoc, rSrcRange ); + ScBaseCell* pCell = aIter.GetFirst(); + while (pCell) + { + if (pCell->GetCellType() == CELLTYPE_FORMULA) + { + ScAddress aCellPos = aIter.GetPos(); + sal_uInt32 nFormat = pClipDoc->GetNumberFormat(aCellPos); + if ( (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 ) + { + ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell); + USHORT nErrCode = pFCell->GetErrCode(); + if ( nErrCode == 0 && pFCell->IsValue() ) + { + sal_uInt32 nNewFormat = pFCell->GetStandardFormat( *pClipDoc->GetFormatTable(), nFormat ); + if ( nNewFormat != nFormat ) + pClipDoc->ApplyAttr( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab(), + SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) ); + } + } + } + pCell = aIter.GetNext(); + } + ScMarkData aDestMark; aDestMark.SelectOneTable( nDestTab ); aDestMark.SetMarkArea( aNewRange ); @@ -199,7 +227,8 @@ BOOL lcl_CopyData( ScDocument* pSrcDoc, const ScRange& rSrcRange, ScFunctionAccess::ScFunctionAccess() : pOptions( NULL ), aPropertyMap( ScDocOptionsHelper::GetPropertyMap() ), - bInvalid( FALSE ) + mbArray( true ), // default according to behaviour of older Office versions + mbValid( true ) { StartListening( *SFX_APP() ); // for SFX_HINT_DEINITIALIZING } @@ -216,7 +245,7 @@ void ScFunctionAccess::Notify( SfxBroadcaster&, const SfxHint& rHint ) { // document must not be used anymore aDocCache.Clear(); - bInvalid = TRUE; + mbValid = false; } } @@ -288,14 +317,22 @@ void SAL_CALL ScFunctionAccess::setPropertyValue( { ScUnoGuard aGuard; - if ( !pOptions ) - pOptions = new ScDocOptions(); + if( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsArrayFunction" ) ) ) + { + if( !(aValue >>= mbArray) ) + throw lang::IllegalArgumentException(); + } + else + { + if ( !pOptions ) + pOptions = new ScDocOptions(); - // options aren't initialized from configuration - always get the same default behaviour + // options aren't initialized from configuration - always get the same default behaviour - BOOL bDone = ScDocOptionsHelper::setPropertyValue( *pOptions, aPropertyMap, aPropertyName, aValue ); - if (!bDone) - throw beans::UnknownPropertyException(); + BOOL bDone = ScDocOptionsHelper::setPropertyValue( *pOptions, aPropertyMap, aPropertyName, aValue ); + if (!bDone) + throw beans::UnknownPropertyException(); + } } uno::Any SAL_CALL ScFunctionAccess::getPropertyValue( const rtl::OUString& aPropertyName ) @@ -304,6 +341,9 @@ uno::Any SAL_CALL ScFunctionAccess::getPropertyValue( const rtl::OUString& aProp { ScUnoGuard aGuard; + if( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsArrayFunction" ) ) ) + return uno::Any( mbArray ); + if ( !pOptions ) pOptions = new ScDocOptions(); @@ -497,7 +537,7 @@ uno::Any SAL_CALL ScFunctionAccess::callFunction( const rtl::OUString& aName, { ScUnoGuard aGuard; - if (bInvalid) + if (!mbValid) throw uno::RuntimeException(); // use cached document if not in use, temporary document otherwise @@ -556,12 +596,13 @@ uno::Any SAL_CALL ScFunctionAccess::callFunction( const rtl::OUString& aName, uno::TypeClass eClass = rArg.getValueTypeClass(); uno::Type aType = rArg.getValueType(); if ( eClass == uno::TypeClass_BYTE || - eClass == uno::TypeClass_SHORT || - eClass == uno::TypeClass_UNSIGNED_SHORT || - eClass == uno::TypeClass_LONG || - eClass == uno::TypeClass_UNSIGNED_LONG || - eClass == uno::TypeClass_FLOAT || - eClass == uno::TypeClass_DOUBLE ) + eClass == uno::TypeClass_BOOLEAN || + eClass == uno::TypeClass_SHORT || + eClass == uno::TypeClass_UNSIGNED_SHORT || + eClass == uno::TypeClass_LONG || + eClass == uno::TypeClass_UNSIGNED_LONG || + eClass == uno::TypeClass_FLOAT || + eClass == uno::TypeClass_DOUBLE ) { // #87871# accept integer types because Basic passes a floating point // variable as byte, short or long if it's an integer number. @@ -650,13 +691,13 @@ uno::Any SAL_CALL ScFunctionAccess::callFunction( const rtl::OUString& aName, // GRAM_PODF_A1 doesn't really matter for the token array but fits with // other API compatibility grammars. ScFormulaCell* pFormula = new ScFormulaCell( pDoc, aFormulaPos, - &aTokenArr,formula::FormulaGrammar::GRAM_PODF_A1, MM_FORMULA ); + &aTokenArr, formula::FormulaGrammar::GRAM_PODF_A1, (BYTE)(mbArray ? MM_FORMULA : MM_NONE) ); pDoc->PutCell( aFormulaPos, pFormula ); //! necessary? // call GetMatrix before GetErrCode because GetMatrix always recalculates // if there is no matrix result - const ScMatrix* pMat = pFormula->GetMatrix(); + const ScMatrix* pMat = mbArray ? pFormula->GetMatrix() : 0; USHORT nErrCode = pFormula->GetErrCode(); if ( nErrCode == 0 ) { diff --git a/sc/source/ui/unoobj/makefile.mk b/sc/source/ui/unoobj/makefile.mk index 35fdf164bf92..36c3493ceefc 100644 --- a/sc/source/ui/unoobj/makefile.mk +++ b/sc/source/ui/unoobj/makefile.mk @@ -79,6 +79,7 @@ SLO1FILES = \ $(SLO)$/filtuno.obj \ $(SLO)$/unodoc.obj \ $(SLO)$/addruno.obj \ + $(SLO)$/eventuno.obj \ $(SLO)$/listenercalls.obj \ $(SLO)$/cellvaluebinding.obj \ $(SLO)$/celllistsource.obj \ diff --git a/sc/source/ui/unoobj/viewuno.cxx b/sc/source/ui/unoobj/viewuno.cxx index 15fb8183a88f..d10d3ba54f86 100644 --- a/sc/source/ui/unoobj/viewuno.cxx +++ b/sc/source/ui/unoobj/viewuno.cxx @@ -66,7 +66,9 @@ #include "scmod.hxx" #include "appoptio.hxx" #include "gridwin.hxx" +#include "sheetevents.hxx" #include <com/sun/star/view/DocumentZoomType.hpp> +#include <com/sun/star/awt/MouseButton.hpp> #include "AccessibilityHints.hxx" #include <svx/sdrhittesthelper.hxx> @@ -476,9 +478,11 @@ ScTabViewObj::ScTabViewObj( ScTabViewShell* pViewSh ) : aPropSet( lcl_GetViewOptPropertyMap() ), aMouseClickHandlers( 0 ), aActivationListeners( 0 ), + nPreviousTab( 0 ), bDrawSelModeSet(sal_False) { - //! Listening oder so + if (pViewSh) + nPreviousTab = pViewSh->GetViewData()->GetTabNo(); } ScTabViewObj::~ScTabViewObj() @@ -529,15 +533,44 @@ void SAL_CALL ScTabViewObj::release() throw() SfxBaseController::release(); } +void lcl_CallActivate( ScDocShell* pDocSh, SCTAB nTab, sal_Int32 nEvent ) +{ + ScDocument* pDoc = pDocSh->GetDocument(); + // when deleting a sheet, nPreviousTab can be invalid + // (could be handled with reference updates) + if (!pDoc->HasTable(nTab)) + return; + + const ScSheetEvents* pEvents = pDoc->GetSheetEvents(nTab); + if (pEvents) + { + const rtl::OUString* pScript = pEvents->GetScript(nEvent); + if (pScript) + { + uno::Any aRet; + uno::Sequence<uno::Any> aParams; + uno::Sequence<sal_Int16> aOutArgsIndex; + uno::Sequence<uno::Any> aOutArgs; + + /*ErrCode eRet =*/ pDocSh->CallXScript( *pScript, aParams, aRet, aOutArgsIndex, aOutArgs ); + } + } +} + void ScTabViewObj::SheetChanged() { - if (aActivationListeners.Count() > 0 && GetViewShell()) + if ( !GetViewShell() ) + return; + + ScViewData* pViewData = GetViewShell()->GetViewData(); + ScDocShell* pDocSh = pViewData->GetDocShell(); + if (aActivationListeners.Count() > 0) { sheet::ActivationEvent aEvent; uno::Reference< sheet::XSpreadsheetView > xView(this); uno::Reference< uno::XInterface > xSource(xView, uno::UNO_QUERY); aEvent.Source = xSource; - aEvent.ActiveSheet = new ScTableSheetObj(GetViewShell()->GetViewData()->GetDocShell(), GetViewShell()->GetViewData()->GetTabNo()); + aEvent.ActiveSheet = new ScTableSheetObj(pDocSh, pViewData->GetTabNo()); for ( USHORT n=0; n<aActivationListeners.Count(); n++ ) { try @@ -551,6 +584,15 @@ void ScTabViewObj::SheetChanged() } } } + + // handle sheet events + SCTAB nNewTab = pViewData->GetTabNo(); + if ( nNewTab != nPreviousTab ) + { + lcl_CallActivate( pDocSh, nPreviousTab, SC_SHEETEVENT_UNFOCUS ); + lcl_CallActivate( pDocSh, nNewTab, SC_SHEETEVENT_FOCUS ); + } + nPreviousTab = nNewTab; } uno::Sequence<uno::Type> SAL_CALL ScTabViewObj::getTypes() throw(uno::RuntimeException) @@ -1194,6 +1236,22 @@ uno::Reference< uno::XInterface > ScTabViewObj::GetClickedObject(const Point& rP return xTarget; } +bool ScTabViewObj::IsMouseListening() const +{ + if ( aMouseClickHandlers.Count() > 0 ) + return true; + + // also include sheet events, because MousePressed must be called for them + ScTabViewShell* pViewSh = GetViewShell(); + ScViewData* pViewData = pViewSh->GetViewData(); + const ScSheetEvents* pEvents = pViewData->GetDocument()->GetSheetEvents(pViewData->GetTabNo()); + if ( pEvents && ( pEvents->GetScript(SC_SHEETEVENT_RIGHTCLICK) != NULL || + pEvents->GetScript(SC_SHEETEVENT_DOUBLECLICK) != NULL ) ) + return true; + + return false; +} + sal_Bool ScTabViewObj::MousePressed( const awt::MouseEvent& e ) throw (::uno::RuntimeException) { @@ -1229,6 +1287,50 @@ sal_Bool ScTabViewObj::MousePressed( const awt::MouseEvent& e ) } } } + + // handle sheet events + bool bDoubleClick = ( e.Buttons == awt::MouseButton::LEFT && e.ClickCount == 2 ); + bool bRightClick = ( e.Buttons == awt::MouseButton::RIGHT && e.ClickCount == 1 ); + if ( ( bDoubleClick || bRightClick ) && !bReturn ) + { + sal_Int32 nEvent = bDoubleClick ? SC_SHEETEVENT_DOUBLECLICK : SC_SHEETEVENT_RIGHTCLICK; + + ScTabViewShell* pViewSh = GetViewShell(); + ScViewData* pViewData = pViewSh->GetViewData(); + ScDocShell* pDocSh = pViewData->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + const ScSheetEvents* pEvents = pDoc->GetSheetEvents(nTab); + if (pEvents) + { + const rtl::OUString* pScript = pEvents->GetScript(nEvent); + if (pScript) + { + // the macro parameter is the clicked object, as in the mousePressed call above + uno::Reference< uno::XInterface > xTarget = GetClickedObject(Point(e.X, e.Y)); + if (xTarget.is()) + { + uno::Sequence<uno::Any> aParams(1); + aParams[0] <<= xTarget; + + uno::Any aRet; + uno::Sequence<sal_Int16> aOutArgsIndex; + uno::Sequence<uno::Any> aOutArgs; + + /*ErrCode eRet =*/ pDocSh->CallXScript( *pScript, aParams, aRet, aOutArgsIndex, aOutArgs ); + + // look for a boolean return value of true + sal_Bool bRetValue = sal_False; + if (aRet >>= bRetValue) + { + if (bRetValue) + bReturn = sal_True; + } + } + } + } + } + return bReturn; } @@ -1702,6 +1804,30 @@ void ScTabViewObj::SelectionChanged() aEvent.Source.set(static_cast<cppu::OWeakObject*>(this)); for ( USHORT n=0; n<aSelectionListeners.Count(); n++ ) (*aSelectionListeners[n])->selectionChanged( aEvent ); + + // handle sheet events + ScTabViewShell* pViewSh = GetViewShell(); + ScViewData* pViewData = pViewSh->GetViewData(); + ScDocShell* pDocSh = pViewData->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + const ScSheetEvents* pEvents = pDoc->GetSheetEvents(nTab); + if (pEvents) + { + const rtl::OUString* pScript = pEvents->GetScript(SC_SHEETEVENT_SELECT); + if (pScript) + { + // the macro parameter is the selection as returned by getSelection + uno::Sequence<uno::Any> aParams(1); + aParams[0] = getSelection(); + + uno::Any aRet; + uno::Sequence<sal_Int16> aOutArgsIndex; + uno::Sequence<uno::Any> aOutArgs; + + /*ErrCode eRet =*/ pDocSh->CallXScript( *pScript, aParams, aRet, aOutArgsIndex, aOutArgs ); + } + } } diff --git a/sc/source/ui/vba/makefile.mk b/sc/source/ui/vba/makefile.mk index 00a26e2f94de..0a84b8dd12a5 100644 --- a/sc/source/ui/vba/makefile.mk +++ b/sc/source/ui/vba/makefile.mk @@ -78,28 +78,31 @@ SLOFILES= \ $(SLO)$/vbaborders.obj \ $(SLO)$/vbacharacters.obj \ $(SLO)$/vbavalidation.obj \ - $(SLO)$/vbaoleobject.obj \ - $(SLO)$/vbaoleobjects.obj \ - $(SLO)$/vbatextboxshape.obj \ - $(SLO)$/vbapane.obj \ - $(SLO)$/vbatextframe.obj \ - $(SLO)$/vbacharttitle.obj \ - $(SLO)$/vbacharts.obj \ - $(SLO)$/vbaaxistitle.obj \ - $(SLO)$/vbaaxes.obj \ - $(SLO)$/vbaaxis.obj \ - $(SLO)$/vbaformat.obj \ - $(SLO)$/vbacondition.obj \ - $(SLO)$/vbaformatcondition.obj \ - $(SLO)$/vbaformatconditions.obj \ - $(SLO)$/vbastyle.obj \ - $(SLO)$/vbastyles.obj \ - $(SLO)$/vbaassistant.obj \ - $(SLO)$/vbahyperlink.obj \ - $(SLO)$/vbapagesetup.obj \ - $(SLO)$/vbapagebreak.obj \ - $(SLO)$/vbapagebreaks.obj \ - $(SLO)$/service.obj + $(SLO)$/vbasheetobject.obj \ + $(SLO)$/vbasheetobjects.obj \ + $(SLO)$/vbaoleobject.obj \ + $(SLO)$/vbaoleobjects.obj \ + $(SLO)$/vbatextboxshape.obj \ + $(SLO)$/vbapane.obj \ + $(SLO)$/vbatextframe.obj \ + $(SLO)$/vbacharttitle.obj \ + $(SLO)$/vbacharts.obj \ + $(SLO)$/vbaaxistitle.obj \ + $(SLO)$/vbaaxes.obj \ + $(SLO)$/vbaaxis.obj \ + $(SLO)$/vbaformat.obj \ + $(SLO)$/vbacondition.obj \ + $(SLO)$/vbaformatcondition.obj \ + $(SLO)$/vbaformatconditions.obj \ + $(SLO)$/vbastyle.obj \ + $(SLO)$/vbastyles.obj \ + $(SLO)$/vbaassistant.obj \ + $(SLO)$/vbahyperlink.obj \ + $(SLO)$/vbahyperlinks.obj \ + $(SLO)$/vbapagesetup.obj \ + $(SLO)$/vbapagebreak.obj \ + $(SLO)$/vbapagebreaks.obj \ + $(SLO)$/service.obj .ENDIF # --- Targets ------------------------------------------------------ diff --git a/sc/source/ui/vba/vbaapplication.cxx b/sc/source/ui/vba/vbaapplication.cxx index 3d5af01acef1..aea8d8bc11d4 100644 --- a/sc/source/ui/vba/vbaapplication.cxx +++ b/sc/source/ui/vba/vbaapplication.cxx @@ -114,7 +114,10 @@ public: ActiveWorkbook( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext) : ScVbaWorkbook( xParent, xContext ){} }; -ScVbaApplication::ScVbaApplication( const uno::Reference<uno::XComponentContext >& xContext ): ScVbaApplication_BASE( xContext ), m_xCalculation( excel::XlCalculation::xlCalculationAutomatic ) +ScVbaApplication::ScVbaApplication( const uno::Reference<uno::XComponentContext >& xContext ) : + ScVbaApplication_BASE( xContext ), + m_xCalculation( excel::XlCalculation::xlCalculationAutomatic ), + m_xDisplayAlerts( sal_True) { } @@ -127,6 +130,66 @@ SfxObjectShell* ScVbaApplication::GetDocShell( const uno::Reference< frame::XMod return static_cast< SfxObjectShell* >( excel::getDocShell( xModel ) ); } +::rtl::OUString SAL_CALL +ScVbaApplication::getExactName( const ::rtl::OUString& aApproximateName ) throw (uno::RuntimeException) +{ + uno::Reference< beans::XExactName > xWSF( new ScVbaWSFunction( this, mxContext ) ); + return xWSF->getExactName( aApproximateName ); +} + +uno::Reference< beans::XIntrospectionAccess > SAL_CALL +ScVbaApplication::getIntrospection() throw(css::uno::RuntimeException) +{ + uno::Reference< script::XInvocation > xWSF( new ScVbaWSFunction( this, mxContext ) ); + return xWSF->getIntrospection(); +} + +uno::Any SAL_CALL +ScVbaApplication::invoke( const ::rtl::OUString& FunctionName, const uno::Sequence< uno::Any >& Params, uno::Sequence< sal_Int16 >& OutParamIndex, uno::Sequence< uno::Any >& OutParam) throw(lang::IllegalArgumentException, script::CannotConvertException, reflection::InvocationTargetException, uno::RuntimeException) +{ + /* When calling the functions directly at the Application object, no runtime + errors are thrown, but the error is inserted into the return value. */ + uno::Any aAny; + try + { + uno::Reference< script::XInvocation > xWSF( new ScVbaWSFunction( this, mxContext ) ); + aAny = xWSF->invoke( FunctionName, Params, OutParamIndex, OutParam ); + } + catch( uno::Exception& ) + { + aAny <<= script::BasicErrorException( ::rtl::OUString(), uno::Reference< uno::XInterface >(), 1000, ::rtl::OUString() ); + } + return aAny; +} + +void SAL_CALL +ScVbaApplication::setValue( const ::rtl::OUString& PropertyName, const uno::Any& Value ) throw(beans::UnknownPropertyException, script::CannotConvertException, reflection::InvocationTargetException, uno::RuntimeException) +{ + uno::Reference< script::XInvocation > xWSF( new ScVbaWSFunction( this, mxContext ) ); + xWSF->setValue( PropertyName, Value ); +} + +uno::Any SAL_CALL +ScVbaApplication::getValue( const ::rtl::OUString& PropertyName ) throw(beans::UnknownPropertyException, uno::RuntimeException) +{ + uno::Reference< script::XInvocation > xWSF( new ScVbaWSFunction( this, mxContext ) ); + return xWSF->getValue( PropertyName ); +} + +sal_Bool SAL_CALL +ScVbaApplication::hasMethod( const ::rtl::OUString& Name ) throw(uno::RuntimeException) +{ + uno::Reference< script::XInvocation > xWSF( new ScVbaWSFunction( this, mxContext ) ); + return xWSF->hasMethod( Name ); +} + +sal_Bool SAL_CALL +ScVbaApplication::hasProperty( const ::rtl::OUString& Name ) throw(uno::RuntimeException) +{ + uno::Reference< script::XInvocation > xWSF( new ScVbaWSFunction( this, mxContext ) ); + return xWSF->hasProperty( Name ); +} + uno::Reference< excel::XWorkbook > ScVbaApplication::getActiveWorkbook() throw (uno::RuntimeException) { @@ -190,7 +253,7 @@ ScVbaApplication::getSelection() throw (uno::RuntimeException) } else { - throw uno::RuntimeException( sImpementaionName + rtl::OUString::createFromAscii(" donot be surpported"), uno::Reference< uno::XInterface >() ); + throw uno::RuntimeException( sImpementaionName + rtl::OUString::createFromAscii(" not suported"), uno::Reference< uno::XInterface >() ); } } @@ -244,7 +307,7 @@ ScVbaApplication::Worksheets( const uno::Any& aIndex ) throw (uno::RuntimeExcept uno::Any SAL_CALL ScVbaApplication::WorksheetFunction( ) throw (::com::sun::star::uno::RuntimeException) { - return uno::makeAny( uno::Reference< script::XInvocation >( new ScVbaWSFunction( this, mxContext) ) ); + return uno::makeAny( uno::Reference< script::XInvocation >( new ScVbaWSFunction( this, mxContext ) ) ); } uno::Any SAL_CALL @@ -270,7 +333,10 @@ uno::Reference< excel::XWindow > SAL_CALL ScVbaApplication::getActiveWindow() throw (uno::RuntimeException) { // #FIXME sofar can't determine Parent - return new ScVbaWindow( uno::Reference< XHelperInterface >(), mxContext, getCurrentDocument() ); + uno::Reference< frame::XModel > xModel = getCurrentDocument(); + ScVbaWindow* pWin = new ScVbaWindow( uno::Reference< XHelperInterface >(), mxContext, xModel ); + uno::Reference< excel::XWindow > xWin( pWin ); + return xWin; } uno::Any SAL_CALL @@ -321,23 +387,6 @@ ScVbaApplication::setStatusBar( const uno::Any& _statusbar ) throw (uno::Runtime uno::Reference< uno::XInterface >() ); } -double SAL_CALL -ScVbaApplication::CountA( const uno::Any& arg1 ) throw (uno::RuntimeException) -{ - double result = 0; - uno::Reference< script::XInvocation > xInvoc( WorksheetFunction(), uno::UNO_QUERY_THROW ); - if ( xInvoc.is() ) - { - static rtl::OUString FunctionName( RTL_CONSTASCII_USTRINGPARAM("CountA" ) ); - uno::Sequence< uno::Any > Params(1); - Params[0] = arg1; - uno::Sequence< sal_Int16 > OutParamIndex; - uno::Sequence< uno::Any > OutParam; - xInvoc->invoke( FunctionName, Params, OutParamIndex, OutParam ) >>= result; - } - return result; -} - ::sal_Int32 SAL_CALL ScVbaApplication::getCalculation() throw (uno::RuntimeException) { @@ -482,8 +531,11 @@ ScVbaApplication::GoTo( const uno::Any& Reference, const uno::Any& Scroll ) thro ScGridWindow* gridWindow = (ScGridWindow*)pShell->GetWindow(); try { - uno::Reference< excel::XRange > xVbaSheetRange = ScVbaRange::getRangeObjectForName( mxContext, sRangeName, excel::getDocShell( xModel ), formula::FormulaGrammar::CONV_XL_R1C1 ); -; + // FIXME: pass proper Worksheet parent + uno::Reference< excel::XRange > xVbaSheetRange = ScVbaRange::getRangeObjectForName( + uno::Reference< XHelperInterface >(), mxContext, sRangeName, + excel::getDocShell( xModel ), formula::FormulaGrammar::CONV_XL_R1C1 ); + if( bScroll ) { xVbaSheetRange->Select(); @@ -621,15 +673,21 @@ ScVbaApplication::getName() throw (uno::RuntimeException) } // #TODO #FIXME get/setDisplayAlerts are just stub impl +// here just the status of the switch is set +// the function that throws an error message needs to +// evaluate this switch in order to know whether it has to disable the +// error message thrown by OpenOffice + void SAL_CALL -ScVbaApplication::setDisplayAlerts(sal_Bool /*displayAlerts*/) throw (uno::RuntimeException) +ScVbaApplication::setDisplayAlerts(sal_Bool displayAlerts) throw (uno::RuntimeException) { + m_xDisplayAlerts = displayAlerts; } sal_Bool SAL_CALL ScVbaApplication::getDisplayAlerts() throw (uno::RuntimeException) { - return sal_True; + return m_xDisplayAlerts; } void SAL_CALL ScVbaApplication::Calculate() throw( script::BasicErrorException , uno::RuntimeException ) @@ -889,7 +947,8 @@ lcl_intersectionImpl( ScRangeList& rl1, ScRangeList& rl2 ) RangesList lcl_intersections( RangesList& vRanges ) { RangesList intersections; - for( RangesList::iterator it = vRanges.begin(); it != vRanges.end(); ++it ) + RangesList::iterator it = vRanges.begin(); + while( it != vRanges.end() ) { Ranges intermediateList; for( RangesList::iterator it_inner = vRanges.begin(); it_inner != vRanges.end(); ++it_inner ) @@ -902,6 +961,7 @@ RangesList lcl_intersections( RangesList& vRanges ) } } it = vRanges.erase( it ); // remove it so we don't include it in the next pass. + // 'it' is removed uncontidionally from vRanges, so the while loop will terminate ScRangeList argIntersect; lcl_strip_containedRanges( intermediateList ); diff --git a/sc/source/ui/vba/vbaapplication.hxx b/sc/source/ui/vba/vbaapplication.hxx index 02822e9f18ad..96638651bcd1 100644 --- a/sc/source/ui/vba/vbaapplication.hxx +++ b/sc/source/ui/vba/vbaapplication.hxx @@ -43,15 +43,29 @@ class ScVbaApplication : public ScVbaApplication_BASE { private: sal_Int32 m_xCalculation; + sal_Bool m_xDisplayAlerts; rtl::OUString getOfficePath( const rtl::OUString& sPath ) throw ( css::uno::RuntimeException ); + protected: - virtual css::uno::Reference< css::frame::XModel > getCurrentDocument() throw (css::uno::RuntimeException); + virtual css::uno::Reference< css::frame::XModel > getCurrentDocument() throw (css::uno::RuntimeException); + public: ScVbaApplication( const css::uno::Reference< css::uno::XComponentContext >& m_xContext ); virtual ~ScVbaApplication(); virtual SfxObjectShell* GetDocShell( const css::uno::Reference< css::frame::XModel >& xModel ) throw (css::uno::RuntimeException); + // XExactName + virtual ::rtl::OUString SAL_CALL getExactName( const ::rtl::OUString& aApproximateName ) throw (css::uno::RuntimeException); + + // XInvocation + virtual css::uno::Reference< css::beans::XIntrospectionAccess > SAL_CALL getIntrospection(void) throw(css::uno::RuntimeException); + virtual css::uno::Any SAL_CALL invoke(const rtl::OUString& FunctionName, const css::uno::Sequence< css::uno::Any >& Params, css::uno::Sequence< sal_Int16 >& OutParamIndex, css::uno::Sequence< css::uno::Any >& OutParam) throw(css::lang::IllegalArgumentException, css::script::CannotConvertException, css::reflection::InvocationTargetException, css::uno::RuntimeException); + virtual void SAL_CALL setValue(const rtl::OUString& PropertyName, const css::uno::Any& Value) throw(css::beans::UnknownPropertyException, css::script::CannotConvertException, css::reflection::InvocationTargetException, css::uno::RuntimeException); + virtual css::uno::Any SAL_CALL getValue(const rtl::OUString& PropertyName) throw(css::beans::UnknownPropertyException, css::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasMethod(const rtl::OUString& Name) throw(css::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasProperty(const rtl::OUString& Name) throw(css::uno::RuntimeException); + // XApplication virtual ::rtl::OUString SAL_CALL PathSeparator( ) throw (css::script::BasicErrorException, css::uno::RuntimeException); virtual void SAL_CALL setDefaultFilePath( const ::rtl::OUString& DefaultFilePath ) throw (css::script::BasicErrorException, css::uno::RuntimeException); @@ -67,8 +81,8 @@ public: virtual css::uno::Any SAL_CALL getSelection() throw (css::uno::RuntimeException); virtual css::uno::Reference< ov::excel::XWorkbook > SAL_CALL getActiveWorkbook() throw (css::uno::RuntimeException); virtual css::uno::Reference< ov::excel::XRange > SAL_CALL getActiveCell() throw ( css::uno::RuntimeException); - virtual css::uno::Reference< ov::excel::XWindow > SAL_CALL getActiveWindow() throw (css::uno::RuntimeException); - virtual css::uno::Reference< ov::excel::XWorksheet > SAL_CALL getActiveSheet() throw (css::uno::RuntimeException); + virtual css::uno::Reference< ov::excel::XWindow > SAL_CALL getActiveWindow() throw (css::uno::RuntimeException); + virtual css::uno::Reference< ov::excel::XWorksheet > SAL_CALL getActiveSheet() throw (css::uno::RuntimeException); virtual ::sal_Bool SAL_CALL getDisplayFormulaBar() throw ( css::uno::RuntimeException ); virtual void SAL_CALL setDisplayFormulaBar( ::sal_Bool _displayformulabar ) throw ( css::uno::RuntimeException ); @@ -86,8 +100,6 @@ public: virtual ::sal_Int32 SAL_CALL getCursor() throw (css::uno::RuntimeException); virtual void SAL_CALL setCursor( ::sal_Int32 _cursor ) throw (css::uno::RuntimeException); - virtual double SAL_CALL CountA( const css::uno::Any& arg1 ) throw (css::uno::RuntimeException) ; - virtual css::uno::Any SAL_CALL Windows( const css::uno::Any& aIndex ) throw (css::uno::RuntimeException); virtual void SAL_CALL wait( double time ) throw (css::uno::RuntimeException); virtual css::uno::Any SAL_CALL Range( const css::uno::Any& Cell1, const css::uno::Any& Cell2 ) throw (css::uno::RuntimeException); diff --git a/sc/source/ui/vba/vbacomment.cxx b/sc/source/ui/vba/vbacomment.cxx index a8026f151c79..9c50a25b8b7c 100644 --- a/sc/source/ui/vba/vbacomment.cxx +++ b/sc/source/ui/vba/vbacomment.cxx @@ -27,14 +27,17 @@ #include "vbacomment.hxx" #include <ooo/vba/excel/XlCreator.hpp> +#include <com/sun/star/drawing/XDrawPageSupplier.hpp> #include <com/sun/star/sheet/XSpreadsheet.hpp> #include <com/sun/star/sheet/XSheetAnnotationAnchor.hpp> #include <com/sun/star/sheet/XSheetAnnotationsSupplier.hpp> +#include <com/sun/star/sheet/XSheetAnnotationShapeSupplier.hpp> #include <com/sun/star/sheet/XSheetCellRange.hpp> #include <com/sun/star/table/CellAddress.hpp> #include <com/sun/star/table/XCell.hpp> #include <com/sun/star/text/XText.hpp> +#include <vbahelper/vbashape.hxx> #include "vbaglobals.hxx" #include "vbacomments.hxx" @@ -42,8 +45,14 @@ using namespace ::ooo::vba; using namespace ::com::sun::star; -ScVbaComment::ScVbaComment( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< table::XCellRange >& xRange ) throw( lang::IllegalArgumentException ) -: ScVbaComment_BASE( xParent, xContext ), mxRange( xRange ) +ScVbaComment::ScVbaComment( + const uno::Reference< XHelperInterface >& xParent, + const uno::Reference< uno::XComponentContext >& xContext, + const uno::Reference< frame::XModel >& xModel, + const uno::Reference< table::XCellRange >& xRange ) throw( lang::IllegalArgumentException ) : + ScVbaComment_BASE( xParent, xContext ), + mxModel( xModel, uno::UNO_SET_THROW ), + mxRange( xRange ) { if ( !xRange.is() ) throw lang::IllegalArgumentException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "range is not set " ) ), uno::Reference< uno::XInterface >() , 1 ); @@ -100,7 +109,7 @@ ScVbaComment::getCommentByIndex( sal_Int32 Index ) throw (uno::RuntimeException) { uno::Reference< container::XIndexAccess > xIndexAccess( getAnnotations(), uno::UNO_QUERY_THROW ); // parent is sheet ( parent of the range which is the parent of the comment ) - uno::Reference< XCollection > xColl( new ScVbaComments( getParent()->getParent(), mxContext, xIndexAccess ) ); + uno::Reference< XCollection > xColl( new ScVbaComments( getParent()->getParent(), mxContext, mxModel, xIndexAccess ) ); return uno::Reference< excel::XComment > ( xColl->Item( uno::makeAny( Index ), uno::Any() ), uno::UNO_QUERY_THROW ); } @@ -119,6 +128,17 @@ ScVbaComment::setAuthor( const rtl::OUString& /*_author*/ ) throw (uno::RuntimeE // #TODO #FIXME implementation needed } +uno::Reference< msforms::XShape > SAL_CALL +ScVbaComment::getShape() throw (uno::RuntimeException) +{ + uno::Reference< sheet::XSheetAnnotationShapeSupplier > xAnnoShapeSupp( getAnnotation(), uno::UNO_QUERY_THROW ); + uno::Reference< drawing::XShape > xAnnoShape( xAnnoShapeSupp->getAnnotationShape(), uno::UNO_SET_THROW ); + uno::Reference< sheet::XSheetCellRange > xCellRange( mxRange, uno::UNO_QUERY_THROW ); + uno::Reference< drawing::XDrawPageSupplier > xDrawPageSupp( xCellRange->getSpreadsheet(), uno::UNO_QUERY_THROW ); + uno::Reference< drawing::XShapes > xShapes( xDrawPageSupp->getDrawPage(), uno::UNO_QUERY_THROW ); + return new ScVbaShape( this, mxContext, xAnnoShape, xShapes, mxModel, office::MsoShapeType::msoComment ); +} + sal_Bool SAL_CALL ScVbaComment::getVisible() throw (uno::RuntimeException) { @@ -186,12 +206,15 @@ ScVbaComment::Text( const uno::Any& aText, const uno::Any& aStart, const uno::An uno::Reference< text::XTextRange > xRange( xTextCursor, uno::UNO_QUERY_THROW ); xAnnoText->insertString( xRange, sText, bOverwrite ); + return xAnnoText->getString(); } - else - throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ScVbaComment::Text - bad Start value " ) ), uno::Reference< uno::XInterface >() ); + throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ScVbaComment::Text - bad Start value " ) ), uno::Reference< uno::XInterface >() ); } else if ( aText.hasValue() ) + { xAnnoText->setString( sText ); + return sText; + } return sAnnoText; } diff --git a/sc/source/ui/vba/vbacomment.hxx b/sc/source/ui/vba/vbacomment.hxx index 91d8a8a8e437..4a7d2fab91ef 100644 --- a/sc/source/ui/vba/vbacomment.hxx +++ b/sc/source/ui/vba/vbacomment.hxx @@ -31,6 +31,7 @@ #include <ooo/vba/excel/XComment.hpp> #include <ooo/vba/excel/XApplication.hpp> +#include <ooo/vba/msforms/XShape.hpp> #include <com/sun/star/sheet/XSheetAnnotations.hpp> #include <com/sun/star/sheet/XSheetAnnotation.hpp> #include <com/sun/star/table/XCellRange.hpp> @@ -42,6 +43,7 @@ typedef InheritedHelperInterfaceImpl1< ov::excel::XComment > ScVbaComment_BASE; class ScVbaComment : public ScVbaComment_BASE { + css::uno::Reference< css::frame::XModel > mxModel; css::uno::Reference< css::table::XCellRange > mxRange; private: @@ -50,13 +52,18 @@ private: sal_Int32 SAL_CALL getAnnotationIndex() throw (css::uno::RuntimeException); css::uno::Reference< ov::excel::XComment > SAL_CALL getCommentByIndex( sal_Int32 Index ) throw (css::uno::RuntimeException); public: - ScVbaComment( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::table::XCellRange >& xRange ) throw ( css::lang::IllegalArgumentException ); + ScVbaComment( + const css::uno::Reference< ov::XHelperInterface >& xParent, + const css::uno::Reference< css::uno::XComponentContext >& xContext, + const css::uno::Reference< css::frame::XModel >& xModel, + const css::uno::Reference< css::table::XCellRange >& xRange ) throw ( css::lang::IllegalArgumentException ); virtual ~ScVbaComment() {} // Attributes virtual rtl::OUString SAL_CALL getAuthor() throw (css::uno::RuntimeException); virtual void SAL_CALL setAuthor( const rtl::OUString& _author ) throw (css::uno::RuntimeException); + virtual css::uno::Reference< ov::msforms::XShape > SAL_CALL getShape() throw (css::uno::RuntimeException); virtual sal_Bool SAL_CALL getVisible() throw (css::uno::RuntimeException); virtual void SAL_CALL setVisible( sal_Bool _visible ) throw (css::uno::RuntimeException); diff --git a/sc/source/ui/vba/vbacomments.cxx b/sc/source/ui/vba/vbacomments.cxx index 5090fa6f5ee6..a68dd4245741 100644 --- a/sc/source/ui/vba/vbacomments.cxx +++ b/sc/source/ui/vba/vbacomments.cxx @@ -34,30 +34,43 @@ using namespace ::ooo::vba; using namespace ::com::sun::star; -uno::Any AnnotationToComment( const uno::Any& aSource, uno::Reference< uno::XComponentContext > & xContext ) +uno::Any AnnotationToComment( const uno::Any& aSource, uno::Reference< uno::XComponentContext > & xContext, const uno::Reference< frame::XModel >& xModel ) { uno::Reference< sheet::XSheetAnnotation > xAnno( aSource, uno::UNO_QUERY_THROW ); uno::Reference< container::XChild > xChild( xAnno, uno::UNO_QUERY_THROW ); uno::Reference< table::XCellRange > xCellRange( xChild->getParent(), uno::UNO_QUERY_THROW ); // #FIXME needs to find the correct Parent - return uno::makeAny( uno::Reference< excel::XComment > ( new ScVbaComment( uno::Reference< XHelperInterface >(), xContext, xCellRange ) ) ); + return uno::makeAny( uno::Reference< excel::XComment > ( + new ScVbaComment( uno::Reference< XHelperInterface >(), xContext, xModel, xCellRange ) ) ); } class CommentEnumeration : public EnumerationHelperImpl { + css::uno::Reference< css::frame::XModel > mxModel; public: - CommentEnumeration( const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< container::XEnumeration >& xEnumeration ) throw ( uno::RuntimeException ) : EnumerationHelperImpl( xContext, xEnumeration ) {} + CommentEnumeration( + const uno::Reference< uno::XComponentContext >& xContext, + const uno::Reference< container::XEnumeration >& xEnumeration, + const uno::Reference< frame::XModel >& xModel ) throw ( uno::RuntimeException ) : + EnumerationHelperImpl( xContext, xEnumeration ), + mxModel( xModel, uno::UNO_SET_THROW ) + {} virtual uno::Any SAL_CALL nextElement() throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException) { - return AnnotationToComment( m_xEnumeration->nextElement(), m_xContext ); + return AnnotationToComment( m_xEnumeration->nextElement(), m_xContext, mxModel ); } }; -ScVbaComments::ScVbaComments( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext > & xContext, const uno::Reference< container::XIndexAccess >& xIndexAccess ) -: ScVbaComments_BASE( xParent, xContext, xIndexAccess ) +ScVbaComments::ScVbaComments( + const uno::Reference< XHelperInterface >& xParent, + const uno::Reference< uno::XComponentContext > & xContext, + const uno::Reference< frame::XModel >& xModel, + const uno::Reference< container::XIndexAccess >& xIndexAccess ) : + ScVbaComments_BASE( xParent, xContext, xIndexAccess ), + mxModel( xModel, uno::UNO_SET_THROW ) { } @@ -68,13 +81,13 @@ ScVbaComments::createEnumeration() throw (uno::RuntimeException) { uno::Reference< container::XEnumerationAccess > xEnumAccess( m_xIndexAccess, uno::UNO_QUERY_THROW ); - return new CommentEnumeration( mxContext, xEnumAccess->createEnumeration() ); + return new CommentEnumeration( mxContext, xEnumAccess->createEnumeration(), mxModel ); } uno::Any ScVbaComments::createCollectionObject( const css::uno::Any& aSource ) { - return AnnotationToComment( aSource, mxContext ); + return AnnotationToComment( aSource, mxContext, mxModel ); } uno::Type diff --git a/sc/source/ui/vba/vbacomments.hxx b/sc/source/ui/vba/vbacomments.hxx index 0ab11e8d5e97..2f98e5b71897 100644 --- a/sc/source/ui/vba/vbacomments.hxx +++ b/sc/source/ui/vba/vbacomments.hxx @@ -40,7 +40,11 @@ typedef CollTestImplHelper< ov::excel::XComments > ScVbaComments_BASE; class ScVbaComments : public ScVbaComments_BASE { public: - ScVbaComments( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext > & xContext, const css::uno::Reference< css::container::XIndexAccess >& xIndexAccess ); + ScVbaComments( + const css::uno::Reference< ov::XHelperInterface >& xParent, + const css::uno::Reference< css::uno::XComponentContext > & xContext, + const css::uno::Reference< css::frame::XModel >& xModel, + const css::uno::Reference< css::container::XIndexAccess >& xIndexAccess ); virtual ~ScVbaComments() {} @@ -53,6 +57,8 @@ public: virtual rtl::OUString& getServiceImplName(); virtual css::uno::Sequence<rtl::OUString> getServiceNames(); +private: + css::uno::Reference< css::frame::XModel > mxModel; }; #endif /* SC_VBA_COMMENTS_HXX */ diff --git a/sc/source/ui/vba/vbafont.cxx b/sc/source/ui/vba/vbafont.cxx index a8aac44770a9..5894d3ea8c71 100644 --- a/sc/source/ui/vba/vbafont.cxx +++ b/sc/source/ui/vba/vbafont.cxx @@ -36,6 +36,7 @@ #include <ooo/vba/excel/XlColorIndex.hpp> #include <ooo/vba/excel/XlUnderlineStyle.hpp> #include <svl/itemset.hxx> +#include "excelvbahelper.hxx" #include "vbafont.hxx" #include "scitems.hxx" #include "cellsuno.hxx" @@ -43,15 +44,22 @@ using namespace ::ooo::vba; using namespace ::com::sun::star; -ScVbaFont::ScVbaFont( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const ScVbaPalette& dPalette, uno::Reference< beans::XPropertySet > xPropertySet, ScCellRangeObj* pRangeObj ) throw ( uno::RuntimeException ) : ScVbaFont_BASE( xParent, xContext, dPalette.getPalette(), xPropertySet ), mPalette( dPalette ), mpRangeObj( pRangeObj ) +ScVbaFont::ScVbaFont( + const uno::Reference< XHelperInterface >& xParent, + const uno::Reference< uno::XComponentContext >& xContext, + const ScVbaPalette& dPalette, + const uno::Reference< beans::XPropertySet >& xPropertySet, + ScCellRangeObj* pRangeObj, bool bFormControl ) throw ( uno::RuntimeException ) : + ScVbaFont_BASE( xParent, xContext, dPalette.getPalette(), xPropertySet, bFormControl ), + mPalette( dPalette ), + mpRangeObj( pRangeObj ) { } SfxItemSet* ScVbaFont::GetDataSet() { - SfxItemSet* pDataSet = excel::ScVbaCellRangeAccess::GetDataSet( mpRangeObj ); - return pDataSet; + return mpRangeObj ? excel::ScVbaCellRangeAccess::GetDataSet( mpRangeObj ) : 0; } ScVbaFont::~ScVbaFont() diff --git a/sc/source/ui/vba/vbafont.hxx b/sc/source/ui/vba/vbafont.hxx index 4cbcd483b2d8..3ef52c6d240f 100644 --- a/sc/source/ui/vba/vbafont.hxx +++ b/sc/source/ui/vba/vbafont.hxx @@ -46,7 +46,12 @@ class ScVbaFont : public ScVbaFont_BASE ScCellRangeObj* mpRangeObj; SfxItemSet* GetDataSet(); public: - ScVbaFont( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const ScVbaPalette& dPalette, css::uno::Reference< css::beans::XPropertySet > xPropertySet, ScCellRangeObj* pRangeObj = NULL ) throw ( css::uno::RuntimeException ); + ScVbaFont( + const css::uno::Reference< ov::XHelperInterface >& xParent, + const css::uno::Reference< css::uno::XComponentContext >& xContext, + const ScVbaPalette& dPalette, + const css::uno::Reference< css::beans::XPropertySet >& xPropertySet, + ScCellRangeObj* pRangeObj = 0, bool bFormControl = false ) throw ( css::uno::RuntimeException ); virtual ~ScVbaFont();// {} // Attributes diff --git a/sc/source/ui/vba/vbaformat.cxx b/sc/source/ui/vba/vbaformat.cxx index 23c2bf96a810..d08451af63f4 100644 --- a/sc/source/ui/vba/vbaformat.cxx +++ b/sc/source/ui/vba/vbaformat.cxx @@ -40,6 +40,7 @@ #include <rtl/math.hxx> +#include "excelvbahelper.hxx" #include "vbaborders.hxx" #include "vbapalette.hxx" #include "vbafont.hxx" diff --git a/sc/source/ui/vba/vbahelper.cxx b/sc/source/ui/vba/vbahelper.cxx index 4bc57e150c8f..cc76b1e60125 100644 --- a/sc/source/ui/vba/vbahelper.cxx +++ b/sc/source/ui/vba/vbahelper.cxx @@ -160,73 +160,6 @@ public: } }; -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<frame::XController> xController = xModel->getCurrentController(); - uno::Reference<frame::XFrame> xFrame = xController->getFrame(); - uno::Reference<frame::XDispatchProvider> xDispatchProvider (xFrame,uno::UNO_QUERY_THROW); - try - { - uno::Reference< beans::XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW ); - uno::Reference<uno::XComponentContext > xContext( xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))), uno::UNO_QUERY_THROW ); - if ( !xContext.is() ) - { - return ; - } - - uno::Reference<lang::XMultiComponentFactory > xServiceManager( - xContext->getServiceManager() ); - if ( !xServiceManager.is() ) - { - return ; - } - uno::Reference<util::XURLTransformer> 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 ( uno::Exception & /*e*/ ) - { - return ; - } - - uno::Reference<frame::XDispatch> xDispatcher = xDispatchProvider->queryDispatch(url,emptyString,0); - - uno::Sequence<beans::PropertyValue> 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; index<nProps; ++index, ++pSrc, ++pDest ) - *pDest = *pSrc; - } - - (*pDest).Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Silent" )); - (*pDest).Value <<= (sal_Bool)sal_True; - - if (xDispatcher.is()) - xDispatcher->dispatch( url, dispatchProps ); -} - -void -dispatchRequests (uno::Reference< frame::XModel>& xModel,rtl::OUString & aUrl) -{ - uno::Sequence<beans::PropertyValue> dispatchProps; - dispatchRequests( xModel, aUrl, dispatchProps ); -} - - void dispatchExecute(css::uno::Reference< css::frame::XModel>& xModel, USHORT nSlot, SfxCallMode nCall) { ScTabViewShell* pViewShell = getBestViewShell( xModel ); @@ -821,7 +754,5 @@ ScVbaCellRangeAccess::GetDataSet( ScCellRangeObj* pRangeObj ) } -} // openoffice -} //org -======= ->>>>>>> other +} // vba +} // ooo diff --git a/sc/source/ui/vba/vbahyperlink.cxx b/sc/source/ui/vba/vbahyperlink.cxx index f3203b130bf2..e37df1e118b4 100644 --- a/sc/source/ui/vba/vbahyperlink.cxx +++ b/sc/source/ui/vba/vbahyperlink.cxx @@ -24,100 +24,213 @@ * for a copy of the LGPLv3 License. * ************************************************************************/ -#include <vbahelper/helperdecl.hxx> + #include "vbahyperlink.hxx" +#include <vbahelper/helperdecl.hxx> #include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/text/XText.hpp> #include <com/sun/star/text/XTextFieldsSupplier.hpp> #include <com/sun/star/container/XEnumerationAccess.hpp> +#include <ooo/vba/office/MsoHyperlinkType.hpp> +#include <ooo/vba/msforms/XShape.hpp> #include "vbarange.hxx" using namespace ::ooo::vba; using namespace ::com::sun::star; +using ::rtl::OUString; +using ::rtl::OUStringBuffer; -ScVbaHyperlink::ScVbaHyperlink( uno::Sequence< uno::Any> const & args, - uno::Reference< uno::XComponentContext> const & xContext ) throw ( lang::IllegalArgumentException ) : HyperlinkImpl_BASE( getXSomethingFromArgs< XHelperInterface >( args, 0 ), xContext ), mxCell( getXSomethingFromArgs< table::XCell >( args, 1, false ) ) +// ============================================================================ + +ScVbaHyperlink::ScVbaHyperlink( const uno::Sequence< uno::Any >& rArgs, + const uno::Reference< uno::XComponentContext >& rxContext ) throw (lang::IllegalArgumentException) : + HyperlinkImpl_BASE( getXSomethingFromArgs< XHelperInterface >( rArgs, 0 ), rxContext ), + mxCell( getXSomethingFromArgs< table::XCell >( rArgs, 1, false ) ), + mnType( office::MsoHyperlinkType::msoHyperlinkRange ) { - mxCell = getXSomethingFromArgs< table::XCell >( args, 1, false ); uno::Reference< text::XTextFieldsSupplier > xTextFields( mxCell, uno::UNO_QUERY_THROW ); uno::Reference< container::XIndexAccess > xIndex( xTextFields->getTextFields(), uno::UNO_QUERY_THROW ); mxTextField.set( xIndex->getByIndex(0), uno::UNO_QUERY_THROW ); } -ScVbaHyperlink::~ScVbaHyperlink() +ScVbaHyperlink::ScVbaHyperlink( const uno::Reference< XHelperInterface >& rxAnchor, + const uno::Reference< uno::XComponentContext >& rxContext, + const uno::Any& rAddress, const uno::Any& rSubAddress, + const uno::Any& rScreenTip, const uno::Any& rTextToDisplay ) throw (uno::RuntimeException) : + HyperlinkImpl_BASE( rxAnchor, rxContext ) // parent of Hyperlink is the anchor object { -} + // extract parameters, Address must not be empty + UrlComponents aUrlComp; + OUString aTextToDisplay; + if( !(rAddress >>= aUrlComp.first) || (aUrlComp.first.getLength() == 0) ) + throw uno::RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM( "Cannot get address" ) ), uno::Reference< uno::XInterface >() ); + rSubAddress >>= aUrlComp.second; + rScreenTip >>= maScreenTip; + rTextToDisplay >>= aTextToDisplay; -::rtl::OUString -ScVbaHyperlink::getAddress() throw (css::uno::RuntimeException) -{ - rtl::OUString aAddress; - uno::Any aValue = mxTextField->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ) ); - aValue >>= aAddress; - return aAddress; + // get anchor range or anchor shape + uno::Reference< excel::XRange > xAnchorRange( rxAnchor, uno::UNO_QUERY ); + if( xAnchorRange.is() ) + { + mnType = office::MsoHyperlinkType::msoHyperlinkRange; + // only single ranges are allowed + uno::Reference< table::XCellRange > xUnoRange( ScVbaRange::getCellRange( xAnchorRange ), uno::UNO_QUERY_THROW ); + // insert the hyperlink into the top-left cell only + mxCell.set( xUnoRange->getCellByPosition( 0, 0 ), uno::UNO_SET_THROW ); + uno::Reference< text::XText > xText( mxCell, uno::UNO_QUERY_THROW ); + // use cell text or URL if no TextToDisplay has been passed + if( aTextToDisplay.getLength() == 0 ) + { + aTextToDisplay = xText->getString(); + if( aTextToDisplay.getLength() == 0 ) + { + OUStringBuffer aBuffer( aUrlComp.first ); + if( aUrlComp.second.getLength() > 0 ) + aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( " - " ) ).append( aUrlComp.second ); + aTextToDisplay = aBuffer.makeStringAndClear(); + } + } + // create and initialize a new URL text field + uno::Reference< lang::XMultiServiceFactory > xFactory( ScVbaRange::getUnoModel( xAnchorRange ), uno::UNO_QUERY_THROW ); + uno::Reference< text::XTextContent > xUrlField( xFactory->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.TextField.URL" ) ) ), uno::UNO_QUERY_THROW ); + mxTextField.set( xUrlField, uno::UNO_QUERY_THROW ); + setUrlComponents( aUrlComp ); + setTextToDisplay( aTextToDisplay ); + // insert the text field into the document + xText->setString( OUString() ); + uno::Reference< text::XTextRange > xRange( xText->createTextCursor(), uno::UNO_QUERY_THROW ); + xText->insertTextContent( xRange, xUrlField, sal_False ); + } + else + { + uno::Reference< msforms::XShape > xAnchorShape( rxAnchor, uno::UNO_QUERY_THROW ); + mnType = office::MsoHyperlinkType::msoHyperlinkShape; + // FIXME: insert hyperlink into shape + throw uno::RuntimeException(); + } } -void -ScVbaHyperlink::setAddress( const ::rtl::OUString & rAddress ) throw (css::uno::RuntimeException) +ScVbaHyperlink::~ScVbaHyperlink() { - uno::Any aValue; - aValue <<= rAddress; - mxTextField->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ), aValue ); } -::rtl::OUString -ScVbaHyperlink::getName() throw (css::uno::RuntimeException) +OUString ScVbaHyperlink::getName() throw (uno::RuntimeException) { // it seems this attribute is same as TextToDisplay return getTextToDisplay(); } -void -ScVbaHyperlink::setName( const ::rtl::OUString & rName ) throw (css::uno::RuntimeException) +void ScVbaHyperlink::setName( const OUString& rName ) throw (uno::RuntimeException) { setTextToDisplay( rName ); } -::rtl::OUString -ScVbaHyperlink::getTextToDisplay() throw (css::uno::RuntimeException) +OUString ScVbaHyperlink::getAddress() throw (uno::RuntimeException) { - rtl::OUString aTextToDisplay; - uno::Any aValue = mxTextField->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Representation" ) ) ); - aValue >>= aTextToDisplay; - return aTextToDisplay; + return getUrlComponents().first; +} + +void ScVbaHyperlink::setAddress( const OUString& rAddress ) throw (uno::RuntimeException) +{ + UrlComponents aUrlComp = getUrlComponents(); + aUrlComp.first = rAddress; + setUrlComponents( aUrlComp ); +} + +OUString ScVbaHyperlink::getSubAddress() throw (uno::RuntimeException) +{ + return getUrlComponents().second; +} + +void ScVbaHyperlink::setSubAddress( const OUString& rSubAddress ) throw (uno::RuntimeException) +{ + UrlComponents aUrlComp = getUrlComponents(); + aUrlComp.second = rSubAddress; + setUrlComponents( aUrlComp ); } -void -ScVbaHyperlink::setTextToDisplay( const ::rtl::OUString & rTextToDisplay ) throw (css::uno::RuntimeException) +OUString SAL_CALL ScVbaHyperlink::getScreenTip() throw (uno::RuntimeException) { - uno::Any aValue; - aValue <<= rTextToDisplay; - mxTextField->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Representation" ) ), aValue ); + return maScreenTip; } -css::uno::Reference< ov::excel::XRange > SAL_CALL ScVbaHyperlink::Range() throw (css::uno::RuntimeException) +void SAL_CALL ScVbaHyperlink::setScreenTip( const OUString& rScreenTip ) throw (uno::RuntimeException) { - uno::Reference< table::XCellRange > xRange( mxCell,uno::UNO_QUERY_THROW ); - // FIXME: need to pass current worksheet as the parent of XRange. - return uno::Reference< excel::XRange >( new ScVbaRange( uno::Reference< XHelperInterface > (), mxContext, xRange ) ); + maScreenTip = rScreenTip; } -rtl::OUString& -ScVbaHyperlink::getServiceImplName() +OUString ScVbaHyperlink::getTextToDisplay() throw (uno::RuntimeException) { - static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("ScVbaHyperlink") ); - return sImplName; + ensureTextField(); + OUString aTextToDisplay; + mxTextField->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Representation" ) ) ) >>= aTextToDisplay; + return aTextToDisplay; +} + +void ScVbaHyperlink::setTextToDisplay( const OUString& rTextToDisplay ) throw (uno::RuntimeException) +{ + ensureTextField(); + mxTextField->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Representation" ) ), uno::Any( rTextToDisplay ) ); } -uno::Sequence< rtl::OUString > -ScVbaHyperlink::getServiceNames() +sal_Int32 SAL_CALL ScVbaHyperlink::getType() throw (uno::RuntimeException) { - static uno::Sequence< rtl::OUString > aServiceNames; - if ( aServiceNames.getLength() == 0 ) + return mnType; +} + +uno::Reference< excel::XRange > SAL_CALL ScVbaHyperlink::getRange() throw (uno::RuntimeException) +{ + if( mnType == office::MsoHyperlinkType::msoHyperlinkRange ) { - aServiceNames.realloc( 1 ); - aServiceNames[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.excel.Hyperlink" ) ); + // if constructed from Hyperlinks object, range has been passed as parent + uno::Reference< excel::XRange > xAnchorRange( getParent(), uno::UNO_QUERY ); + if( !xAnchorRange.is() ) + { + // if constructed via service c'tor, create new range based on cell + uno::Reference< table::XCellRange > xRange( mxCell, uno::UNO_QUERY_THROW ); + // FIXME: need to pass current worksheet as the parent of XRange. + xAnchorRange.set( new ScVbaRange( uno::Reference< XHelperInterface >(), mxContext, xRange ) ); + } + return xAnchorRange; } - return aServiceNames; + // error if called at a shape Hyperlink object + throw uno::RuntimeException(); +} + +uno::Reference< msforms::XShape > SAL_CALL ScVbaHyperlink::getShape() throw (uno::RuntimeException) +{ + // error if called at a range Hyperlink object + return uno::Reference< msforms::XShape >( getParent(), uno::UNO_QUERY_THROW ); +} + +VBAHELPER_IMPL_XHELPERINTERFACE( ScVbaHyperlink, "ooo.vba.excel.Hyperlink" ) + +// private -------------------------------------------------------------------- + +void ScVbaHyperlink::ensureTextField() throw (uno::RuntimeException) +{ + if( !mxTextField.is() ) + throw uno::RuntimeException(); +} + +ScVbaHyperlink::UrlComponents ScVbaHyperlink::getUrlComponents() throw (uno::RuntimeException) +{ + ensureTextField(); + OUString aUrl; + mxTextField->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ) ) >>= aUrl; + sal_Int32 nHashPos = aUrl.indexOf( '#' ); + if( nHashPos < 0 ) + return UrlComponents( aUrl, OUString() ); + return UrlComponents( aUrl.copy( 0, nHashPos ), aUrl.copy( nHashPos + 1 ) ); +} + +void ScVbaHyperlink::setUrlComponents( const UrlComponents& rUrlComp ) throw (uno::RuntimeException) +{ + ensureTextField(); + OUStringBuffer aUrl( rUrlComp.first ); + if( rUrlComp.second.getLength() > 0 ) + aUrl.append( sal_Unicode( '#' ) ).append( rUrlComp.second ); + mxTextField->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ), uno::Any( aUrl.makeStringAndClear() ) ); } namespace hyperlink @@ -129,3 +242,5 @@ extern sdecl::ServiceDecl const serviceDecl( "ScVbaHyperlink", "ooo.vba.excel.Hyperlink" ); } + +// ============================================================================ diff --git a/sc/source/ui/vba/vbahyperlink.hxx b/sc/source/ui/vba/vbahyperlink.hxx index 570ecdcc2f45..e1520b59c15a 100644 --- a/sc/source/ui/vba/vbahyperlink.hxx +++ b/sc/source/ui/vba/vbahyperlink.hxx @@ -24,6 +24,7 @@ * for a copy of the LGPLv3 License. * ************************************************************************/ + #ifndef SC_VBA_HYPERLINK_HXX #define SC_VBA_HYPERLINK_HXX @@ -38,27 +39,50 @@ typedef InheritedHelperInterfaceImpl1< ov::excel::XHyperlink > HyperlinkImpl_BAS class ScVbaHyperlink : public HyperlinkImpl_BASE { - css::uno::Reference< css::table::XCell > mxCell; - css::uno::Reference< css::beans::XPropertySet > mxTextField; - public: - ScVbaHyperlink( css::uno::Sequence< css::uno::Any > const& aArgs, css::uno::Reference< css::uno::XComponentContext > const& xContext ) throw ( css::lang::IllegalArgumentException ); + ScVbaHyperlink( + const css::uno::Sequence< css::uno::Any >& rArgs, + const css::uno::Reference< css::uno::XComponentContext >& rxContext ) throw (css::lang::IllegalArgumentException); + + ScVbaHyperlink( + const css::uno::Reference< ov::XHelperInterface >& rxAnchor, + const css::uno::Reference< css::uno::XComponentContext >& rxContext, + const css::uno::Any& rAddress, const css::uno::Any& rSubAddress, + const css::uno::Any& rScreenTip, const css::uno::Any& rTextToDisplay ) throw (css::uno::RuntimeException); + virtual ~ScVbaHyperlink(); // Attributes - virtual ::rtl::OUString SAL_CALL getAddress() throw (css::uno::RuntimeException); - virtual void SAL_CALL setAddress( const ::rtl::OUString &rAddress ) throw (css::uno::RuntimeException); virtual ::rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException); - virtual void SAL_CALL setName( const ::rtl::OUString &rName ) throw (css::uno::RuntimeException); + virtual void SAL_CALL setName( const ::rtl::OUString& rName ) throw (css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getAddress() throw (css::uno::RuntimeException); + virtual void SAL_CALL setAddress( const ::rtl::OUString& rAddress ) throw (css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getSubAddress() throw (css::uno::RuntimeException); + virtual void SAL_CALL setSubAddress( const ::rtl::OUString& rSubAddress ) throw (css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getScreenTip() throw (css::uno::RuntimeException); + virtual void SAL_CALL setScreenTip( const ::rtl::OUString& rScreenTip ) throw (css::uno::RuntimeException); virtual ::rtl::OUString SAL_CALL getTextToDisplay() throw (css::uno::RuntimeException); - virtual void SAL_CALL setTextToDisplay( const ::rtl::OUString &rTextToDisplay ) throw (css::uno::RuntimeException); - - // Methods - virtual css::uno::Reference< ov::excel::XRange > SAL_CALL Range() throw (css::uno::RuntimeException); + virtual void SAL_CALL setTextToDisplay( const ::rtl::OUString& rTextToDisplay ) throw (css::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getType() throw (css::uno::RuntimeException); + virtual css::uno::Reference< ov::excel::XRange > SAL_CALL getRange() throw (css::uno::RuntimeException); + virtual css::uno::Reference< ov::msforms::XShape > SAL_CALL getShape() throw (css::uno::RuntimeException); // XHelperInterface - virtual rtl::OUString& getServiceImplName(); - virtual css::uno::Sequence<rtl::OUString> getServiceNames(); + VBAHELPER_DECL_XHELPERINTERFACE + +private: + typedef ::std::pair< ::rtl::OUString, ::rtl::OUString > UrlComponents; + + void ensureTextField() throw (css::uno::RuntimeException); + UrlComponents getUrlComponents() throw (css::uno::RuntimeException); + void setUrlComponents( const UrlComponents& rUrlComp ) throw (css::uno::RuntimeException); + +private: + css::uno::Reference< css::table::XCell > mxCell; + css::uno::Reference< css::beans::XPropertySet > mxTextField; + ::rtl::OUString maScreenTip; + long mnType; }; + #endif /* SC_VBA_HYPERLINK_HXX */ diff --git a/sc/source/ui/vba/vbahyperlinks.cxx b/sc/source/ui/vba/vbahyperlinks.cxx new file mode 100755 index 000000000000..89a8109e6aa2 --- /dev/null +++ b/sc/source/ui/vba/vbahyperlinks.cxx @@ -0,0 +1,293 @@ +/************************************************************************* + * + * 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 "vbahyperlinks.hxx" +#include <algorithm> +#include <vector> +#include <ooo/vba/office/MsoHyperlinkType.hpp> +#include "rangelst.hxx" +#include "vbahyperlink.hxx" +#include "vbarange.hxx" + +using namespace ::ooo::vba; +using namespace ::com::sun::star; +using ::rtl::OUString; + +// ============================================================================ + +namespace { + +/** Returns true, if every range of rxInner is contained in any range of rScOuter. */ +bool lclContains( const ScRangeList& rScOuter, const uno::Reference< excel::XRange >& rxInner ) throw (uno::RuntimeException) +{ + const ScRangeList& rScInner = ScVbaRange::getScRangeList( rxInner ); + if( (rScInner.Count() == 0) || (rScOuter.Count() == 0) ) + throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Empty range objects" ) ), uno::Reference< uno::XInterface >() ); + + for( ULONG nIndex = 0, nCount = rScInner.Count(); nIndex < nCount; ++nIndex ) + if( !rScOuter.In( *rScInner.GetObject( nIndex ) ) ) + return false; + return true; +} + +// ---------------------------------------------------------------------------- + +/** Functor to decide whether the anchors of two Hyperlink objects are equal. */ +struct EqualAnchorFunctor +{ + uno::Reference< excel::XRange > mxAnchorRange; + uno::Reference< msforms::XShape > mxAnchorShape; + sal_Int32 mnType; + EqualAnchorFunctor( const uno::Reference< excel::XHyperlink >& rxHlink ) throw (uno::RuntimeException); + bool operator()( const uno::Reference< excel::XHyperlink >& rxHlink ) const throw (uno::RuntimeException); +}; + +EqualAnchorFunctor::EqualAnchorFunctor( const uno::Reference< excel::XHyperlink >& rxHlink ) throw (uno::RuntimeException) : + mnType( rxHlink->getType() ) +{ + switch( mnType ) + { + case office::MsoHyperlinkType::msoHyperlinkRange: + mxAnchorRange.set( rxHlink->getRange(), uno::UNO_QUERY_THROW ); + break; + case office::MsoHyperlinkType::msoHyperlinkShape: + case office::MsoHyperlinkType::msoHyperlinkInlineShape: + mxAnchorShape.set( rxHlink->getShape(), uno::UNO_QUERY_THROW ); + break; + default: + throw uno::RuntimeException(); + } +} + +bool EqualAnchorFunctor::operator()( const uno::Reference< excel::XHyperlink >& rxHlink ) const throw (uno::RuntimeException) +{ + sal_Int32 nType = rxHlink->getType(); + if( nType != mnType ) + return false; + + switch( nType ) + { + case office::MsoHyperlinkType::msoHyperlinkRange: + { + uno::Reference< excel::XRange > xAnchorRange( rxHlink->getRange(), uno::UNO_QUERY_THROW ); + const ScRangeList& rScRanges1 = ScVbaRange::getScRangeList( xAnchorRange ); + const ScRangeList& rScRanges2 = ScVbaRange::getScRangeList( mxAnchorRange ); + return (rScRanges1.Count() == 1) && (rScRanges2.Count() == 1) && (*rScRanges1.GetObject( 0 ) == *rScRanges2.GetObject( 0 )); + } + case office::MsoHyperlinkType::msoHyperlinkShape: + case office::MsoHyperlinkType::msoHyperlinkInlineShape: + { + uno::Reference< msforms::XShape > xAnchorShape( rxHlink->getShape(), uno::UNO_QUERY_THROW ); + return xAnchorShape.get() == mxAnchorShape.get(); + } + default: + throw uno::RuntimeException(); + } +} + +} // namespace + +// ============================================================================ + +namespace detail { + +class ScVbaHlinkContainer : public ::cppu::WeakImplHelper1< container::XIndexAccess > +{ +public: + explicit ScVbaHlinkContainer() throw (uno::RuntimeException); + explicit ScVbaHlinkContainer( const ScVbaHlinkContainerRef& rxSheetContainer, const ScRangeList& rScRanges ) throw (uno::RuntimeException); + virtual ~ScVbaHlinkContainer(); + + /** Inserts the passed hyperlink into the collection. Will remove a + Hyperlink object with the same anchor as the passed Hyperlink object. */ + void insertHyperlink( const uno::Reference< excel::XHyperlink >& rxHlink ) throw (uno::RuntimeException); + + // XIndexAccess + virtual sal_Int32 SAL_CALL getCount() throw (uno::RuntimeException); + virtual uno::Any SAL_CALL getByIndex( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException); + + // XElementAccess + virtual uno::Type SAL_CALL getElementType() throw (uno::RuntimeException); + virtual sal_Bool SAL_CALL hasElements() throw (uno::RuntimeException); + +private: + typedef ::std::vector< uno::Reference< excel::XHyperlink > > HyperlinkVector; + HyperlinkVector maHlinks; +}; + +// ---------------------------------------------------------------------------- + +ScVbaHlinkContainer::ScVbaHlinkContainer() throw (uno::RuntimeException) +{ + // TODO FIXME: fill with existing hyperlinks +} + +ScVbaHlinkContainer::ScVbaHlinkContainer( const ScVbaHlinkContainerRef& rxSheetContainer, + const ScRangeList& rScRanges ) throw (uno::RuntimeException) +{ + for( sal_Int32 nIndex = 0, nCount = rxSheetContainer->getCount(); nIndex < nCount; ++nIndex ) + { + uno::Reference< excel::XHyperlink > xHlink( rxSheetContainer->getByIndex( nIndex ), uno::UNO_QUERY_THROW ); + uno::Reference< excel::XRange > xHlinkRange( xHlink->getRange(), uno::UNO_QUERY_THROW ); + if( lclContains( rScRanges, xHlinkRange ) ) + maHlinks.push_back( xHlink ); + } +} + +ScVbaHlinkContainer::~ScVbaHlinkContainer() +{ +} + +void ScVbaHlinkContainer::insertHyperlink( const uno::Reference< excel::XHyperlink >& rxHlink ) throw (uno::RuntimeException) +{ + HyperlinkVector::iterator aIt = ::std::find_if( maHlinks.begin(), maHlinks.end(), EqualAnchorFunctor( rxHlink ) ); + if( aIt == maHlinks.end() ) + maHlinks.push_back( rxHlink ); + else + *aIt = rxHlink; +} + +sal_Int32 SAL_CALL ScVbaHlinkContainer::getCount() throw (uno::RuntimeException) +{ + return static_cast< sal_Int32 >( maHlinks.size() ); +} + +uno::Any SAL_CALL ScVbaHlinkContainer::getByIndex( sal_Int32 nIndex ) + throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException) +{ + if( (0 <= nIndex) && (nIndex < getCount()) ) + return uno::Any( maHlinks[ static_cast< size_t >( nIndex ) ] ); + throw lang::IndexOutOfBoundsException(); +} + +uno::Type SAL_CALL ScVbaHlinkContainer::getElementType() throw (uno::RuntimeException) +{ + return excel::XHyperlink::static_type( 0 ); +} + +sal_Bool SAL_CALL ScVbaHlinkContainer::hasElements() throw (uno::RuntimeException) +{ + return !maHlinks.empty(); +} + +// ============================================================================ + +ScVbaHlinkContainerMember::ScVbaHlinkContainerMember( ScVbaHlinkContainer* pContainer ) : + mxContainer( pContainer ) +{ +} + +ScVbaHlinkContainerMember::~ScVbaHlinkContainerMember() +{ +} + +} // namespace detail + +// ============================================================================ + +ScVbaHyperlinks::ScVbaHyperlinks( const uno::Reference< XHelperInterface >& rxParent, + const uno::Reference< uno::XComponentContext >& rxContext ) throw (uno::RuntimeException) : + detail::ScVbaHlinkContainerMember( new detail::ScVbaHlinkContainer ), + ScVbaHyperlinks_BASE( rxParent, rxContext, uno::Reference< container::XIndexAccess >( mxContainer.get() ) ) +{ +} + +ScVbaHyperlinks::ScVbaHyperlinks( const uno::Reference< XHelperInterface >& rxParent, + const uno::Reference< uno::XComponentContext >& rxContext, + const ScVbaHyperlinksRef& rxSheetHlinks, const ScRangeList& rScRanges ) throw (uno::RuntimeException) : + detail::ScVbaHlinkContainerMember( new detail::ScVbaHlinkContainer( rxSheetHlinks->mxContainer, rScRanges ) ), + ScVbaHyperlinks_BASE( rxParent, rxContext, uno::Reference< container::XIndexAccess >( mxContainer.get() ) ), + mxSheetHlinks( rxSheetHlinks ) +{ +} + +ScVbaHyperlinks::~ScVbaHyperlinks() +{ +} + +// XHyperlinks ---------------------------------------------------------------- + +uno::Reference< excel::XHyperlink > SAL_CALL ScVbaHyperlinks::Add( + const uno::Any& rAnchor, const uno::Any& rAddress, const uno::Any& rSubAddress, + const uno::Any& rScreenTip, const uno::Any& rTextToDisplay ) throw (uno::RuntimeException) +{ + /* If this Hyperlinks object has been craeted from a Range object, the + call to Add() is passed to the Hyperlinks object of the parent + worksheet. This container will not be modified (it will not contain the + inserted hyperlink). + For details, see documentation in hyperlinks.hxx. + */ + if( mxSheetHlinks.is() ) + return mxSheetHlinks->Add( rAnchor, rAddress, rSubAddress, rScreenTip, rTextToDisplay ); + + // get anchor object (can be a Range or a Shape object) + uno::Reference< XHelperInterface > xAnchor( rAnchor, uno::UNO_QUERY_THROW ); + + /* Create the Hyperlink object, this tries to insert the hyperlink into + the spreadsheet document. Parent of the Hyperlink is the anchor object. */ + uno::Reference< excel::XHyperlink > xHlink( new ScVbaHyperlink( + xAnchor, mxContext, rAddress, rSubAddress, rScreenTip, rTextToDisplay ) ); + + /* If creation of the hyperlink did not throw, insert it into the + collection. */ + mxContainer->insertHyperlink( xHlink ); + return xHlink; +} + +void SAL_CALL ScVbaHyperlinks::Delete() throw (uno::RuntimeException) +{ + // FIXME not implemented + throw uno::RuntimeException(); +} + +// XEnumerationAccess --------------------------------------------------------- + +uno::Reference< container::XEnumeration > SAL_CALL ScVbaHyperlinks::createEnumeration() throw (uno::RuntimeException) +{ + return new SimpleIndexAccessToEnumeration( m_xIndexAccess ); +} + +// XElementAccess ------------------------------------------------------------- + +uno::Type SAL_CALL ScVbaHyperlinks::getElementType() throw (uno::RuntimeException) +{ + return excel::XHyperlink::static_type( 0 ); +} + +// ScVbaCollectionBase -------------------------------------------------------- + +uno::Any ScVbaHyperlinks::createCollectionObject( const uno::Any& rSource ) +{ + // container stores XHyperlink objects, just return the passed object + return rSource; +} + +// XHelperInterface ----------------------------------------------------------- + +VBAHELPER_IMPL_XHELPERINTERFACE( ScVbaHyperlinks, "ooo.vba.excel.Hyperlinks" ) + +// ============================================================================ diff --git a/sc/source/ui/vba/vbahyperlinks.hxx b/sc/source/ui/vba/vbahyperlinks.hxx new file mode 100755 index 000000000000..ca7d990ad6a8 --- /dev/null +++ b/sc/source/ui/vba/vbahyperlinks.hxx @@ -0,0 +1,150 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef SC_VBA_HYPERLINKS_HXX +#define SC_VBA_HYPERLINKS_HXX + +#include <ooo/vba/excel/XHyperlinks.hpp> +#include <rtl/ref.hxx> +#include <vbahelper/vbacollectionimpl.hxx> + +class ScRangeList; + +// ============================================================================ + +namespace detail { + +class ScVbaHlinkContainer; +typedef ::rtl::Reference< ScVbaHlinkContainer > ScVbaHlinkContainerRef; + +/** Base class for ScVbaHyperlinks to get an initialized ScVbaHlinkContainer + class member before the ScVbaHyperlinks_BASE base class will be constructed. + */ +struct ScVbaHlinkContainerMember +{ + ScVbaHlinkContainerRef mxContainer; + + explicit ScVbaHlinkContainerMember( ScVbaHlinkContainer* pContainer ); + ~ScVbaHlinkContainerMember(); +}; + +} // namespace detail + +// ============================================================================ + +class ScVbaHyperlinks; +typedef ::rtl::Reference< ScVbaHyperlinks > ScVbaHyperlinksRef; + +typedef CollTestImplHelper< ov::excel::XHyperlinks > ScVbaHyperlinks_BASE; + +/** Represents a collection of hyperlinks of a worksheet or of a range. + + When a Hyperlinks collection object has been constructed from a VBA + Worksheet object, it will always represent the current set of all + hyperlinks existing in the sheet. Insertion and deletion of hyperlinks will + be reflected by the instance. + + When a Hyperlinks collection object has been constructed from a VBA Range + object, it will represent the set of hyperlinks that have existed at its + construction time, and that are located completely inside the range(s) + represented by the Range object. Insertion and deletion of hyperlinks will + *not* be reflected by that instance. The instance will always offer all + hyperlinks it has been constructed with, even if they no longer exist. + Furthermore, the instance will not offer hyperlinks inserted later, even if + the instance itself has been used to insert the new hyperlinks. + + VBA code example: + + With ThisWorkbook.Worksheets(1) + + Set hlinks = .Hyperlinks ' global Hyperlinks object + Set myrange = .Range("A1:C3") + Set rangelinks1 = myrange.Hyperlinks ' hyperlinks of range A1:C3 + + MsgBox hlinks.Count ' 0 + MsgBox rangelinks1.Count ' 0 + + hlinks.Add .Range("A1"), "http://example.com" + ' a new hyperlink has been added in cell A1 + + MsgBox hlinks.Count ' 1 + MsgBox rangelinks1.Count ' still 0! + Set rangelinks2 = myrange.Hyperlinks ' hyperlinks of range A1:C3 + MsgBox rangelinks2.Count ' 1 (constructed after Add) + + rangelinks1.Add .Range("A2"), "http://example.com" + ' a new hyperlink has been constructed via the rangelinks1 object + ' but this addition has been done by the worksheet Hyperlinks object + + MsgBox hlinks.Count ' 2 + MsgBox rangelinks1.Count ' still 0!!! + MsgBox rangelinks2.Count ' still 1!!! + MsgBox myrange.Hyperlinks.Count ' 2 (constructed after Add) + + End With + */ +class ScVbaHyperlinks : private detail::ScVbaHlinkContainerMember, public ScVbaHyperlinks_BASE +{ +public: + explicit ScVbaHyperlinks( + const css::uno::Reference< ov::XHelperInterface >& rxParent, + const css::uno::Reference< css::uno::XComponentContext >& rxContext ) throw (css::uno::RuntimeException); + + explicit ScVbaHyperlinks( + const css::uno::Reference< ov::XHelperInterface >& rxParent, + const css::uno::Reference< css::uno::XComponentContext >& rxContext, + const ScVbaHyperlinksRef& rxSheetHlinks, const ScRangeList& rScRanges ) throw (css::uno::RuntimeException); + + virtual ~ScVbaHyperlinks(); + + // XHyperlinks + virtual css::uno::Reference< ov::excel::XHyperlink > SAL_CALL Add( + const css::uno::Any& rAnchor, const css::uno::Any& rAddress, const css::uno::Any& rSubAddress, + const css::uno::Any& rScreenTip, const css::uno::Any& rTextToDisplay ) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL Delete() throw (css::uno::RuntimeException); + + // XEnumerationAccess + virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createEnumeration() throw (css::uno::RuntimeException); + + // XElementAccess + virtual css::uno::Type SAL_CALL getElementType() throw (css::uno::RuntimeException); + + // ScVbaCollectionBase + virtual css::uno::Any createCollectionObject( const css::uno::Any& rSource ); + + // XHelperInterface + VBAHELPER_DECL_XHELPERINTERFACE + +private: + ScVbaHyperlinksRef mxSheetHlinks; +}; + +// ============================================================================ + +#endif diff --git a/sc/source/ui/vba/vbainterior.cxx b/sc/source/ui/vba/vbainterior.cxx index 3af6243e0fa7..face47767bdc 100644 --- a/sc/source/ui/vba/vbainterior.cxx +++ b/sc/source/ui/vba/vbainterior.cxx @@ -40,10 +40,13 @@ #include <comphelper/processfactory.hxx> #include <cppuhelper/queryinterface.hxx> +#include <map> + #include <svx/xtable.hxx> #include "vbainterior.hxx" #include "vbapalette.hxx" +#include "document.hxx" #define STATIC_TABLE_SIZE( array ) (sizeof(array)/sizeof(*(array))) #define COLORMAST 0xFFFFFF diff --git a/sc/source/ui/vba/vbainterior.hxx b/sc/source/ui/vba/vbainterior.hxx index f0d4db1334fd..027d06040af9 100644 --- a/sc/source/ui/vba/vbainterior.hxx +++ b/sc/source/ui/vba/vbainterior.hxx @@ -36,6 +36,8 @@ #include <com/sun/star/script/XInvocation.hpp> #include <vbahelper/vbahelperinterface.hxx> +#include <tools/color.hxx> + class ScDocument; typedef InheritedHelperInterfaceImpl1< ov::excel::XInterior > ScVbaInterior_BASE; diff --git a/sc/source/ui/vba/vbaname.cxx b/sc/source/ui/vba/vbaname.cxx index bc0b016177c7..a6e8a402425f 100644 --- a/sc/source/ui/vba/vbaname.cxx +++ b/sc/source/ui/vba/vbaname.cxx @@ -232,7 +232,10 @@ ScVbaName::setRefersToR1C1Local( const ::rtl::OUString & rRefersTo ) throw (css: css::uno::Reference< ov::excel::XRange > ScVbaName::getRefersToRange() throw (css::uno::RuntimeException) { - uno::Reference< ov::excel::XRange > xRange = ScVbaRange::getRangeObjectForName( mxContext, mxNamedRange->getName(), excel::getDocShell( mxModel ), formula::FormulaGrammar::CONV_XL_R1C1 ); + // FIXME: pass proper Worksheet parent + uno::Reference< ov::excel::XRange > xRange = ScVbaRange::getRangeObjectForName( + uno::Reference< XHelperInterface >(), mxContext, + mxNamedRange->getName(), excel::getDocShell( mxModel ), formula::FormulaGrammar::CONV_XL_R1C1 ); return xRange; } diff --git a/sc/source/ui/vba/vbapalette.cxx b/sc/source/ui/vba/vbapalette.cxx index 0ce55547d4a1..c6ae5c488a20 100644 --- a/sc/source/ui/vba/vbapalette.cxx +++ b/sc/source/ui/vba/vbapalette.cxx @@ -24,10 +24,12 @@ * for a copy of the LGPLv3 License. * ************************************************************************/ + #include "vbapalette.hxx" #include <cppuhelper/implbase1.hxx> #include <com/sun/star/beans/XPropertySet.hpp> - +#include <com/sun/star/container/XIndexAccess.hpp> +#include "excelvbahelper.hxx" using namespace ::com::sun::star; using namespace ::ooo::vba; @@ -82,6 +84,11 @@ public: }; +ScVbaPalette::ScVbaPalette( const uno::Reference< frame::XModel >& rxModel ) : + m_pShell( excel::getDocShell( rxModel ) ) +{ +} + uno::Reference< container::XIndexAccess > ScVbaPalette::getDefaultPalette() { diff --git a/sc/source/ui/vba/vbapalette.hxx b/sc/source/ui/vba/vbapalette.hxx index 9c7ea2ebc3f1..b51483772674 100644 --- a/sc/source/ui/vba/vbapalette.hxx +++ b/sc/source/ui/vba/vbapalette.hxx @@ -24,19 +24,26 @@ * for a copy of the LGPLv3 License. * ************************************************************************/ + #ifndef SC_VBAPALETTE_HXX #define SC_VBAPALETTE_HXX -#include "excelvbahelper.hxx" -#include <document.hxx> -#include <com/sun/star/container/XIndexAccess.hpp> +#include <vbahelper/vbahelper.hxx> + +namespace com { namespace sun { namespace star { + namespace container { class XIndexAccess; } + namespace frame { class XModel; } +} } } + +class SfxObjectShell; class ScVbaPalette { private: SfxObjectShell* m_pShell; public: - ScVbaPalette( SfxObjectShell* pShell = NULL ) : m_pShell( pShell ){} + ScVbaPalette( SfxObjectShell* pShell = 0 ) : m_pShell( pShell ) {} + ScVbaPalette( const css::uno::Reference< css::frame::XModel >& rxModel ); // if no palette available e.g. because the document doesn't have a // palette defined then a default palette will be returned. css::uno::Reference< css::container::XIndexAccess > getPalette() const; diff --git a/sc/source/ui/vba/vbapane.cxx b/sc/source/ui/vba/vbapane.cxx index 263529dde145..29d7a286b402 100644 --- a/sc/source/ui/vba/vbapane.cxx +++ b/sc/source/ui/vba/vbapane.cxx @@ -24,18 +24,26 @@ * for a copy of the LGPLv3 License. * ************************************************************************/ -#include<com/sun/star/table/CellRangeAddress.hpp> -#include<vbapane.hxx> + +#include "vbapane.hxx" +#include <com/sun/star/sheet/XSpreadsheet.hpp> +#include <com/sun/star/sheet/XSpreadsheetDocument.hpp> +#include <com/sun/star/table/CellRangeAddress.hpp> +#include "vbarange.hxx" using namespace com::sun::star; using namespace ooo::vba; -/* -ScVbaPane::ScVbaPane( uno::Reference< uno::XComponentContext > xContext, uno::Refrence< sheet::XViewPane > xViewPane ) - : m_xContext( xContext ), m_xViewPane( xViewPane ) +ScVbaPane::ScVbaPane( + const css::uno::Reference< ov::XHelperInterface >& xParent, + const uno::Reference< uno::XComponentContext >& xContext, + const uno::Reference< frame::XModel >& xModel, + const uno::Reference< sheet::XViewPane > xViewPane ) throw (uno::RuntimeException) : + ScVbaPane_BASE( xParent, xContext ), + m_xModel( xModel, uno::UNO_SET_THROW ), + m_xViewPane( xViewPane, uno::UNO_SET_THROW ) { } -*/ sal_Int32 SAL_CALL ScVbaPane::getScrollColumn() throw (uno::RuntimeException) @@ -71,6 +79,19 @@ ScVbaPane::setScrollRow( sal_Int32 _scrollrow ) throw (uno::RuntimeException) m_xViewPane->setFirstVisibleRow( _scrollrow - 1 ); } +uno::Reference< excel::XRange > SAL_CALL +ScVbaPane::getVisibleRange() throw (uno::RuntimeException) +{ + // TODO: Excel includes partly visible rows/columns, Calc does not + table::CellRangeAddress aRangeAddr = m_xViewPane->getVisibleRange(); + uno::Reference< sheet::XSpreadsheetDocument > xDoc( m_xModel, uno::UNO_QUERY_THROW ); + uno::Reference< container::XIndexAccess > xSheetsIA( xDoc->getSheets(), uno::UNO_QUERY_THROW ); + uno::Reference< sheet::XSpreadsheet > xSheet( xSheetsIA->getByIndex( aRangeAddr.Sheet ), uno::UNO_QUERY_THROW ); + uno::Reference< table::XCellRange > xRange( xSheet->getCellRangeByPosition( aRangeAddr.StartColumn, aRangeAddr.StartRow, aRangeAddr.EndColumn, aRangeAddr.EndRow ), uno::UNO_SET_THROW ); + // TODO: getParent() returns the window, Range needs the worksheet + return new ScVbaRange( getParent(), mxContext, xRange ); +} + //Method void SAL_CALL ScVbaPane::SmallScroll( const uno::Any& Down, const uno::Any& Up, const uno::Any& ToRight, const uno::Any& ToLeft ) throw (uno::RuntimeException) @@ -83,54 +104,34 @@ ScVbaPane::SmallScroll( const uno::Any& Down, const uno::Any& Up, const uno::Any if( Down.hasValue() ) { sal_Int32 down = 0; - try - { - Down >>= down; + if( Down >>= down ) downRows += down; - } - catch ( uno::Exception ) - { + else messageBuffer += rtl::OUString::createFromAscii( "Error getting parameter: Down\n" ); - } } if( Up.hasValue() ) { sal_Int32 up = 0; - try - { - Up >>= up; + if( Up >>= up ) downRows -= up; - } - catch ( uno::Exception ) - { + else messageBuffer += rtl::OUString::createFromAscii( "Error getting parameter: Up\n" ); - } } if( ToRight.hasValue() ) { sal_Int32 right = 0; - try - { - ToRight >>= right; + if( ToRight >>= right ) rightCols += right; - } - catch ( uno::Exception ) - { + else messageBuffer += rtl::OUString::createFromAscii( "Error getting parameter: ToRight\n" ); - } } if( ToLeft.hasValue() ) { sal_Int32 left = 0; - try - { - ToLeft >>= left; + if( ToLeft >>= left ) rightCols -= left; - } - catch ( uno::Exception ) - { + else messageBuffer += rtl::OUString::createFromAscii( "Error getting parameter: ToLeft\n" ); - } } if( messageBuffer.getLength() > 0 ) throw(uno::RuntimeException( messageBuffer, uno::Reference< uno::XInterface >() ) ); @@ -158,56 +159,35 @@ ScVbaPane::LargeScroll( const uno::Any& Down, const uno::Any& Up, const uno::Any if( Down.hasValue() ) { sal_Int32 down = 0; - try - { - Down >>= down; + if( Down >>= down ) downPages += down; - } - catch ( uno::Exception ) - { + else messageBuffer += rtl::OUString::createFromAscii( "Error getting parameter: Down\n" ); - } } if( Up.hasValue() ) { sal_Int32 up = 0; - try - { - Up >>= up; + if( Up >>= up ) downPages -= up; - } - catch ( uno::Exception ) - { + else messageBuffer += rtl::OUString::createFromAscii( "Error getting parameter: Up\n" ); - } } if( ToRight.hasValue() ) { sal_Int32 right = 0; - try - { - ToRight >>= right; + if( ToRight >>= right ) acrossPages += right; - } - catch ( uno::Exception ) - { + else messageBuffer += rtl::OUString::createFromAscii( "Error getting parameter: ToRight\n" ); - } } if( ToLeft.hasValue() ) { sal_Int32 left = 0; - try - { - ToLeft >>= left; + if( ToLeft >>= left ) acrossPages -= left; - } - catch ( uno::Exception ) - { + else messageBuffer += rtl::OUString::createFromAscii( "Error getting parameter: ToLeft\n" ); - } } - if( messageBuffer.getLength() > 0 ) throw(uno::RuntimeException( messageBuffer, uno::Reference< uno::XInterface >() ) ); @@ -220,3 +200,7 @@ ScVbaPane::LargeScroll( const uno::Any& Down, const uno::Any& Up, const uno::Any m_xViewPane->setFirstVisibleRow( newStartRow ); m_xViewPane->setFirstVisibleColumn( newStartCol ); } + +// XHelperInterface + +VBAHELPER_IMPL_XHELPERINTERFACE( ScVbaPane, "ooo.vba.excel.Pane" ) diff --git a/sc/source/ui/vba/vbapane.hxx b/sc/source/ui/vba/vbapane.hxx index 0fa1d49709de..ff87a9966d80 100644 --- a/sc/source/ui/vba/vbapane.hxx +++ b/sc/source/ui/vba/vbapane.hxx @@ -27,34 +27,41 @@ #ifndef SC_VBA_PANE_HXX #define SC_VBA_PANE_HXX -#include<cppuhelper/implbase1.hxx> -#include<com/sun/star/sheet/XViewPane.hpp> -#include<ooo/vba/excel/XPane.hpp> +#include <com/sun/star/sheet/XViewPane.hpp> +#include <ooo/vba/excel/XPane.hpp> +#include <vbahelper/vbahelperinterface.hxx> +#include "excelvbahelper.hxx" -#include"excelvbahelper.hxx" +typedef InheritedHelperInterfaceImpl1< ov::excel::XPane > ScVbaPane_BASE; -typedef cppu::WeakImplHelper1< ov::excel::XPane > PaneImpl_Base; - -class ScVbaPane : public PaneImpl_Base +class ScVbaPane : public ScVbaPane_BASE { -protected: - css::uno::Reference< css::uno::XComponentContext > m_xContext; - css::uno::Reference< css::sheet::XViewPane > m_xViewPane; public: - ScVbaPane( const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::sheet::XViewPane > xViewPane ) : m_xContext( xContext ), m_xViewPane( xViewPane ) {} + ScVbaPane( + const css::uno::Reference< ov::XHelperInterface >& xParent, + const css::uno::Reference< css::uno::XComponentContext >& xContext, + const css::uno::Reference< css::frame::XModel >& xModel, + const css::uno::Reference< css::sheet::XViewPane > xViewPane ) throw (css::uno::RuntimeException); css::uno::Reference< css::sheet::XViewPane > getViewPane() { return m_xViewPane; } - //Attribute + // XPane attributes virtual sal_Int32 SAL_CALL getScrollColumn() throw (css::uno::RuntimeException); virtual void SAL_CALL setScrollColumn( sal_Int32 _scrollcolumn ) throw (css::uno::RuntimeException); virtual sal_Int32 SAL_CALL getScrollRow() throw (css::uno::RuntimeException); virtual void SAL_CALL setScrollRow( sal_Int32 _scrollrow ) throw (css::uno::RuntimeException); + virtual css::uno::Reference< ov::excel::XRange > SAL_CALL getVisibleRange() throw (css::uno::RuntimeException); - //Method + // XPane methods virtual void SAL_CALL SmallScroll( const css::uno::Any& Down, const css::uno::Any& Up, const css::uno::Any& ToRight, const css::uno::Any& ToLeft ) throw (css::uno::RuntimeException); virtual void SAL_CALL LargeScroll( const css::uno::Any& Down, const css::uno::Any& Up, const css::uno::Any& ToRight, const css::uno::Any& ToLeft ) throw (css::uno::RuntimeException); + // XHelperInterface + VBAHELPER_DECL_XHELPERINTERFACE + +protected: + css::uno::Reference< css::frame::XModel > m_xModel; + css::uno::Reference< css::sheet::XViewPane > m_xViewPane; }; -#endif//SC_VBA_PANE_HXX +#endif //SC_VBA_PANE_HXX diff --git a/sc/source/ui/vba/vbarange.cxx b/sc/source/ui/vba/vbarange.cxx index 1a153b440b15..71d29734fc76 100644 --- a/sc/source/ui/vba/vbarange.cxx +++ b/sc/source/ui/vba/vbarange.cxx @@ -81,6 +81,7 @@ #include <com/sun/star/sheet/XSheetFilterable.hpp> #include <com/sun/star/sheet/FilterConnection.hpp> #include <com/sun/star/util/CellProtection.hpp> +#include <com/sun/star/util/TriState.hpp> #include <com/sun/star/style/XStyleFamiliesSupplier.hpp> #include <com/sun/star/awt/XDevice.hpp> @@ -141,6 +142,7 @@ #include "vbaborders.hxx" #include "vbaworksheet.hxx" #include "vbavalidation.hxx" +#include "vbahyperlinks.hxx" #include "tabvwsh.hxx" #include "rangelst.hxx" @@ -367,7 +369,7 @@ ScVbaRangeAreas::createCollectionObject( const uno::Any& aSource ) ScDocShell* getDocShellFromIf( const uno::Reference< uno::XInterface >& xIf ) throw ( uno::RuntimeException ) { - ScCellRangesBase* pUno= dynamic_cast< ScCellRangesBase* >( xIf.get() ); + ScCellRangesBase* pUno = ScCellRangesBase::getImplementation( xIf ); if ( !pUno ) throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Failed to access underlying uno range object" ) ), uno::Reference< uno::XInterface >() ); return pUno->GetDocShell(); @@ -381,6 +383,14 @@ getDocShellFromRange( const uno::Reference< table::XCellRange >& xRange ) throw return getDocShellFromIf(xIf ); } +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 getDocShellFromIf(xIf ); +} + uno::Reference< frame::XModel > getModelFromXIf( const uno::Reference< uno::XInterface >& xIf ) throw ( uno::RuntimeException ) { ScDocShell* pDocShell = getDocShellFromIf(xIf ); @@ -405,7 +415,7 @@ getDocumentFromRange( const uno::Reference< table::XCellRange >& xRange ) ScDocument* -ScVbaRange::getScDocument() +ScVbaRange::getScDocument() throw (uno::RuntimeException) { if ( mxRanges.is() ) { @@ -417,7 +427,7 @@ ScVbaRange::getScDocument() } ScDocShell* -ScVbaRange::getScDocShell() +ScVbaRange::getScDocShell() throw (uno::RuntimeException) { if ( mxRanges.is() ) { @@ -428,6 +438,41 @@ ScVbaRange::getScDocShell() return getDocShellFromRange( mxRange ); } +/*static*/ ScVbaRange* ScVbaRange::getImplementation( const uno::Reference< excel::XRange >& rxRange ) +{ + // FIXME: always save to use dynamic_cast? Or better to (implement and) use XTunnel? + return dynamic_cast< ScVbaRange* >( rxRange.get() ); +} + +uno::Reference< frame::XModel > ScVbaRange::getUnoModel() throw (uno::RuntimeException) +{ + if( ScDocShell* pDocShell = getScDocShell() ) + return pDocShell->GetModel(); + throw uno::RuntimeException(); +} + +/*static*/ uno::Reference< frame::XModel > ScVbaRange::getUnoModel( const uno::Reference< excel::XRange >& rxRange ) throw (uno::RuntimeException) +{ + if( ScVbaRange* pScVbaRange = getImplementation( rxRange ) ) + return pScVbaRange->getUnoModel(); + throw uno::RuntimeException(); +} + +const ScRangeList& ScVbaRange::getScRangeList() throw (uno::RuntimeException) +{ + if( ScCellRangesBase* pScRangesBase = getCellRangesBase() ) + return pScRangesBase->GetRangeList(); + throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Cannot obtain UNO range implementation object" ) ), uno::Reference< uno::XInterface >() ); +} + +/*static*/ const ScRangeList& ScVbaRange::getScRangeList( const uno::Reference< excel::XRange >& rxRange ) throw (uno::RuntimeException) +{ + if( ScVbaRange* pScVbaRange = getImplementation( rxRange ) ) + return pScVbaRange->getScRangeList(); + throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Cannot obtain VBA range implementation object" ) ), uno::Reference< uno::XInterface >() ); +} + + class NumFormatHelper { uno::Reference< util::XNumberFormatsSupplier > mxSupplier; @@ -472,7 +517,7 @@ public: rtl::OUString getNumberFormatString() { uno::Reference< uno::XInterface > xIf( mxRangeProps, uno::UNO_QUERY_THROW ); - ScCellRangeObj* pUnoCellRange = dynamic_cast< ScCellRangeObj* >( xIf.get() ); + ScCellRangesBase* pUnoCellRange = ScCellRangesBase::getImplementation( xIf ); if ( pUnoCellRange ) { @@ -577,20 +622,17 @@ class CellsEnumeration : public CellsEnumeration_BASE uno::Reference< XCollection > m_xAreas; vCellPos m_CellPositions; vCellPos::const_iterator m_it; + uno::Reference< table::XCellRange > getArea( sal_Int32 nVBAIndex ) throw ( uno::RuntimeException ) { if ( nVBAIndex < 1 || nVBAIndex > m_xAreas->getCount() ) throw uno::RuntimeException(); uno::Reference< excel::XRange > xRange( m_xAreas->Item( uno::makeAny(nVBAIndex), uno::Any() ), uno::UNO_QUERY_THROW ); - ScVbaRange* pRange = dynamic_cast< ScVbaRange* >( xRange.get() ); - uno::Reference< table::XCellRange > xCellRange; - if ( !pRange ) - throw uno::RuntimeException(); - xCellRange.set( pRange->getCellRange(), uno::UNO_QUERY_THROW );; + uno::Reference< table::XCellRange > xCellRange( ScVbaRange::getCellRange( xRange ), uno::UNO_QUERY_THROW ); return xCellRange; - } - void populateArea( sal_Int32 nVBAIndex ) + + void populateArea( sal_Int32 nVBAIndex ) { uno::Reference< table::XCellRange > xRange = getArea( nVBAIndex ); uno::Reference< table::XColumnRowRange > xColumnRowRange(xRange, uno::UNO_QUERY_THROW ); @@ -1136,7 +1178,7 @@ bool getScRangeListForAddress( const rtl::OUString& sName, ScDocShell* pDocSh, S ScVbaRange* -getRangeForName( const uno::Reference< uno::XComponentContext >& xContext, const rtl::OUString& sName, ScDocShell* pDocSh, table::CellRangeAddress& pAddr, formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::CONV_XL_A1 ) throw ( uno::RuntimeException ) +getRangeForName( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const rtl::OUString& sName, ScDocShell* pDocSh, table::CellRangeAddress& pAddr, formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::CONV_XL_A1 ) throw ( uno::RuntimeException ) { ScRangeList aCellRanges; ScRange refRange; @@ -1147,20 +1189,107 @@ getRangeForName( const uno::Reference< uno::XComponentContext >& xContext, const if ( aCellRanges.First() == aCellRanges.Last() ) { uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( pDocSh, *aCellRanges.First() ) ); - // #FIXME need proper (WorkSheet) parent - return new ScVbaRange( uno::Reference< XHelperInterface >(), xContext, xRange ); + return new ScVbaRange( xParent, xContext, xRange ); } uno::Reference< sheet::XSheetCellRangeContainer > xRanges( new ScCellRangesObj( pDocSh, aCellRanges ) ); + return new ScVbaRange( xParent, xContext, xRanges ); +} - // #FIXME need proper (WorkSheet) parent - return new ScVbaRange( uno::Reference< XHelperInterface >(), xContext, xRanges ); +// ---------------------------------------------------------------------------- + +namespace { + +template< typename RangeType > +inline table::CellRangeAddress lclGetRangeAddress( const uno::Reference< RangeType >& rxCellRange ) throw (uno::RuntimeException) +{ + return uno::Reference< sheet::XCellRangeAddressable >( rxCellRange, uno::UNO_QUERY_THROW )->getRangeAddress(); +} + +uno::Reference< sheet::XSheetCellRange > lclExpandToMerged( const uno::Reference< table::XCellRange >& rxCellRange, bool bRecursive ) throw (uno::RuntimeException) +{ + uno::Reference< sheet::XSheetCellRange > xNewCellRange( rxCellRange, uno::UNO_QUERY_THROW ); + uno::Reference< sheet::XSpreadsheet > xSheet( xNewCellRange->getSpreadsheet(), uno::UNO_SET_THROW ); + table::CellRangeAddress aNewAddress = lclGetRangeAddress( xNewCellRange ); + table::CellRangeAddress aOldAddress; + // expand as long as there are new merged ranges included + do + { + aOldAddress = aNewAddress; + uno::Reference< sheet::XSheetCellCursor > xCursor( xSheet->createCursorByRange( xNewCellRange ), uno::UNO_SET_THROW ); + xCursor->collapseToMergedArea(); + xNewCellRange.set( xCursor, uno::UNO_QUERY_THROW ); + aNewAddress = lclGetRangeAddress( xNewCellRange ); + } + while( bRecursive && (aOldAddress != aNewAddress) ); + return xNewCellRange; } +uno::Reference< sheet::XSheetCellRangeContainer > lclExpandToMerged( const uno::Reference< sheet::XSheetCellRangeContainer >& rxCellRanges, bool bRecursive ) throw (uno::RuntimeException) +{ + if( !rxCellRanges.is() ) + throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Missing cell ranges object" ) ), uno::Reference< uno::XInterface >() ); + sal_Int32 nCount = rxCellRanges->getCount(); + if( nCount < 1 ) + throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Missing cell ranges object" ) ), uno::Reference< uno::XInterface >() ); + + ScRangeList aScRanges; + for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex ) + { + uno::Reference< table::XCellRange > xRange( rxCellRanges->getByIndex( nIndex ), uno::UNO_QUERY_THROW ); + table::CellRangeAddress aRangeAddr = lclGetRangeAddress( lclExpandToMerged( xRange, bRecursive ) ); + ScRange aScRange; + ScUnoConversion::FillScRange( aScRange, aRangeAddr ); + aScRanges.Append( aScRange ); + } + return new ScCellRangesObj( getDocShellFromRanges( rxCellRanges ), aScRanges ); +} + +void lclExpandAndMerge( const uno::Reference< table::XCellRange >& rxCellRange, bool bMerge ) throw (uno::RuntimeException) +{ + uno::Reference< util::XMergeable > xMerge( lclExpandToMerged( rxCellRange, true ), uno::UNO_QUERY_THROW ); + // Calc cannot merge over merged ranges, always unmerge first + xMerge->merge( sal_False ); + if( bMerge ) + xMerge->merge( sal_True ); + // FIXME need to check whether all the cell contents are retained or lost by popping up a dialog +} + +util::TriState lclGetMergedState( const uno::Reference< table::XCellRange >& rxCellRange ) throw (uno::RuntimeException) +{ + /* 1) Check if range is completely inside one single merged range. To do + this, try to extend from top-left cell only (not from entire range). + This will excude cases where this range consists of several merged + ranges (or parts of them). */ + table::CellRangeAddress aRangeAddr = lclGetRangeAddress( rxCellRange ); + uno::Reference< table::XCellRange > xTopLeft( rxCellRange->getCellRangeByPosition( 0, 0, 0, 0 ), uno::UNO_SET_THROW ); + uno::Reference< sheet::XSheetCellRange > xExpanded( lclExpandToMerged( xTopLeft, false ), uno::UNO_SET_THROW ); + table::CellRangeAddress aExpAddr = lclGetRangeAddress( xExpanded ); + // check that expanded range has more than one cell (really merged) + if( ((aExpAddr.StartColumn < aExpAddr.EndColumn) || (aExpAddr.StartRow < aExpAddr.EndRow)) && ScUnoConversion::Contains( aExpAddr, aRangeAddr ) ) + return util::TriState_YES; + + /* 2) Check if this range contains any merged cells (completely or + partly). This seems to be hardly possible via API, as + XMergeable::getIsMerged() returns only true, if the top-left cell of a + merged range is part of this range, so cases where just the lower part + of a merged range is part of this range are not covered. */ + ScRange aScRange; + ScUnoConversion::FillScRange( aScRange, aRangeAddr ); + bool bHasMerged = getDocumentFromRange( rxCellRange )->HasAttrib( aScRange, HASATTR_MERGED | HASATTR_OVERLAPPED ); + return bHasMerged ? util::TriState_INDETERMINATE : util::TriState_NO; +} + +} // namespace + +// ---------------------------------------------------------------------------- + css::uno::Reference< excel::XRange > -ScVbaRange::getRangeObjectForName( const uno::Reference< uno::XComponentContext >& xContext, const rtl::OUString& sRangeName, ScDocShell* pDocSh, formula::FormulaGrammar::AddressConvention eConv ) throw ( uno::RuntimeException ) +ScVbaRange::getRangeObjectForName( const css::uno::Reference< ov::XHelperInterface >& xParent, + const uno::Reference< uno::XComponentContext >& xContext, const rtl::OUString& sRangeName, + ScDocShell* pDocSh, formula::FormulaGrammar::AddressConvention eConv ) throw ( uno::RuntimeException ) { table::CellRangeAddress refAddr; - return getRangeForName( xContext, sRangeName, pDocSh, refAddr, eConv ); + return getRangeForName( xParent, xContext, sRangeName, pDocSh, refAddr, eConv ); } @@ -1196,9 +1325,7 @@ table::CellRangeAddress getCellRangeAddressForVBARange( const uno::Any& aParam, default: throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Can't extact CellRangeAddress from type" ) ), uno::Reference< uno::XInterface >() ); } - uno::Reference< sheet::XCellRangeAddressable > xAddressable( xRangeParam, uno::UNO_QUERY_THROW ); - return xAddressable->getRangeAddress(); - + return lclGetRangeAddress( xRangeParam ); } uno::Reference< XCollection > @@ -1398,7 +1525,7 @@ ScVbaRange::ClearContents( sal_Int32 nFlags ) throw (uno::RuntimeException) for ( sal_Int32 index=1; index <= nItems; ++index ) { uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW ); - ScVbaRange* pRange = dynamic_cast< ScVbaRange* >( xRange.get() ); + ScVbaRange* pRange = getImplementation( xRange ); if ( pRange ) pRange->ClearContents( nFlags ); } @@ -1595,7 +1722,7 @@ ScVbaRange::fillSeries( sheet::FillDirection nFillDirection, sheet::FillMode nFi for ( sal_Int32 index = 1; index <= xCollection->getCount(); ++index ) { uno::Reference< excel::XRange > xRange( xCollection->Item( uno::makeAny( index ), uno::Any() ), uno::UNO_QUERY_THROW ); - ScVbaRange* pThisRange = dynamic_cast< ScVbaRange* >( xRange.get() ); + ScVbaRange* pThisRange = getImplementation( xRange ); pThisRange->fillSeries( nFillDirection, nFillMode, nFillDateMode, fStep, fEndValue ); } @@ -1975,9 +2102,9 @@ ScVbaRange::Select() throw (uno::RuntimeException) uno::Reference< frame::XModel > xModel( pShell->GetModel(), uno::UNO_QUERY_THROW ); uno::Reference< view::XSelectionSupplier > xSelection( xModel->getCurrentController(), uno::UNO_QUERY_THROW ); if ( mxRanges.is() ) - xSelection->select( uno::makeAny( mxRanges ) ); + xSelection->select( uno::Any( lclExpandToMerged( mxRanges, true ) ) ); else - xSelection->select( uno::makeAny( mxRange ) ); + xSelection->select( uno::Any( lclExpandToMerged( mxRange, true ) ) ); // set focus on document e.g. // ThisComponent.CurrentController.Frame.getContainerWindow.SetFocus try @@ -1990,7 +2117,6 @@ ScVbaRange::Select() throw (uno::RuntimeException) catch( uno::Exception& ) { } - } } @@ -2168,36 +2294,65 @@ ScVbaRange::Columns(const uno::Any& aIndex ) throw (uno::RuntimeException) void ScVbaRange::setMergeCells( const uno::Any& aIsMerged ) throw (script::BasicErrorException, uno::RuntimeException) { - sal_Bool bIsMerged = sal_False; - aIsMerged >>= bIsMerged; - uno::Reference< util::XMergeable > xMerge( mxRange, ::uno::UNO_QUERY_THROW ); - //FIXME need to check whether all the cell contents are retained or lost by popping up a dialog - xMerge->merge( bIsMerged ); + bool bMerge = false; + aIsMerged >>= bMerge; + + if( mxRanges.is() ) + { + sal_Int32 nCount = mxRanges->getCount(); + + // VBA does nothing (no error) if the own ranges overlap somehow + ::std::vector< table::CellRangeAddress > aList; + for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex ) + { + uno::Reference< sheet::XCellRangeAddressable > xRangeAddr( mxRanges->getByIndex( nIndex ), uno::UNO_QUERY_THROW ); + table::CellRangeAddress aAddress = xRangeAddr->getRangeAddress(); + for( ::std::vector< table::CellRangeAddress >::const_iterator aIt = aList.begin(), aEnd = aList.end(); aIt != aEnd; ++aIt ) + if( ScUnoConversion::Intersects( *aIt, aAddress ) ) + return; + aList.push_back( aAddress ); + } + + // (un)merge every range after it has been extended to intersecting merged ranges from sheet + for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex ) + { + uno::Reference< table::XCellRange > xRange( mxRanges->getByIndex( nIndex ), uno::UNO_QUERY_THROW ); + lclExpandAndMerge( xRange, bMerge ); + } + return; + } + + // otherwise, merge single range + lclExpandAndMerge( mxRange, bMerge ); } uno::Any ScVbaRange::getMergeCells() throw (script::BasicErrorException, uno::RuntimeException) { - sal_Int32 nItems = m_Areas->getCount(); - - if ( nItems > 1 ) + if( mxRanges.is() ) { - uno::Any aResult = aNULL(); - for ( sal_Int32 index=1; index != nItems; ++index ) + sal_Int32 nCount = mxRanges->getCount(); + for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex ) { - uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW ); - if ( index > 1 ) - if ( aResult != xRange->getMergeCells() ) - return aNULL(); - aResult = xRange->getMergeCells(); - if ( aNULL() == aResult ) + uno::Reference< table::XCellRange > xRange( mxRanges->getByIndex( nIndex ), uno::UNO_QUERY_THROW ); + util::TriState eMerged = lclGetMergedState( xRange ); + /* Excel always returns NULL, if one range of the range list is + partly or completely merged. Even if all ranges are completely + merged, the return value is still NULL. */ + if( eMerged != util::TriState_NO ) return aNULL(); } - return aResult; + // no range is merged anyhow, return false + return uno::Any( false ); + } + // otherwise, check single range + switch( lclGetMergedState( mxRange ) ) + { + case util::TriState_YES: return uno::Any( true ); + case util::TriState_NO: return uno::Any( false ); + default: return aNULL(); } - uno::Reference< util::XMergeable > xMerge( mxRange, ::uno::UNO_QUERY_THROW ); - return uno::makeAny( xMerge->getIsMerged() ); } void @@ -2425,7 +2580,7 @@ ScVbaRange::Range( const uno::Any &Cell1, const uno::Any &Cell2, bool bForceUseI Cell1 >>= sName; RangeHelper referRange( xReferrer ); table::CellRangeAddress referAddress = referRange.getCellRangeAddressable()->getRangeAddress(); - return getRangeForName( mxContext, sName, getScDocShell(), referAddress ); + return getRangeForName( getParent(), mxContext, sName, getScDocShell(), referAddress ); } else @@ -2488,8 +2643,7 @@ ScVbaRange::Range( const uno::Any &Cell1, const uno::Any &Cell2, bool bForceUseI // Allow access to underlying openoffice uno api ( useful for debugging // with openoffice basic ) -::com::sun::star::uno::Any SAL_CALL -ScVbaRange::getCellRange( ) throw (::com::sun::star::uno::RuntimeException) +uno::Any SAL_CALL ScVbaRange::getCellRange( ) throw (uno::RuntimeException) { uno::Any aAny; if ( mxRanges.is() ) @@ -2499,6 +2653,13 @@ ScVbaRange::getCellRange( ) throw (::com::sun::star::uno::RuntimeException) return aAny; } +/*static*/ uno::Any ScVbaRange::getCellRange( const uno::Reference< excel::XRange >& rxRange ) throw (uno::RuntimeException) +{ + if( ScVbaRange* pVbaRange = getImplementation( rxRange ) ) + return pVbaRange->getCellRange(); + throw uno::RuntimeException(); +} + static USHORT getPasteFlags (sal_Int32 Paste) { @@ -2632,14 +2793,25 @@ ScVbaRange::getEntireColumn() throw (uno::RuntimeException) uno::Reference< excel::XComment > SAL_CALL ScVbaRange::AddComment( const uno::Any& Text ) throw (uno::RuntimeException) { + // if there is already a comment in the top-left cell then throw + if( getComment().is() ) + throw uno::RuntimeException(); - uno::Reference< excel::XComment > xComment( new ScVbaComment( this, mxContext, mxRange ) ); - // if you don't pass a valid text or if there is already a comment - // associated with the range then return NULL - if ( !xComment->Text( Text, uno::Any(), uno::Any() ).getLength() - || xComment->Text( uno::Any(), uno::Any(), uno::Any() ).getLength() ) - return NULL; - return xComment; + // workaround: Excel allows to create empty comment, Calc does not + ::rtl::OUString aNoteText; + if( Text.hasValue() && !(Text >>= aNoteText) ) + throw uno::RuntimeException(); + if( aNoteText.getLength() == 0 ) + aNoteText = ::rtl::OUString( sal_Unicode( ' ' ) ); + + // try to create a new annotation + table::CellRangeAddress aRangePos = lclGetRangeAddress( mxRange ); + table::CellAddress aNotePos( aRangePos.Sheet, aRangePos.StartColumn, aRangePos.StartRow ); + uno::Reference< sheet::XSheetCellRange > xCellRange( mxRange, uno::UNO_QUERY_THROW ); + uno::Reference< sheet::XSheetAnnotationsSupplier > xAnnosSupp( xCellRange->getSpreadsheet(), uno::UNO_QUERY_THROW ); + uno::Reference< sheet::XSheetAnnotations > xAnnos( xAnnosSupp->getAnnotations(), uno::UNO_SET_THROW ); + xAnnos->insertNew( aNotePos, aNoteText ); + return new ScVbaComment( this, mxContext, getUnoModel(), mxRange ); } uno::Reference< excel::XComment > SAL_CALL @@ -2647,7 +2819,7 @@ ScVbaRange::getComment() throw (uno::RuntimeException) { // intentional behavior to return a null object if no // comment defined - uno::Reference< excel::XComment > xComment( new ScVbaComment( this, mxContext, mxRange ) ); + uno::Reference< excel::XComment > xComment( new ScVbaComment( this, mxContext, getUnoModel(), mxRange ) ); if ( !xComment->Text( uno::Any(), uno::Any(), uno::Any() ).getLength() ) return NULL; return xComment; @@ -2976,7 +3148,7 @@ uno::Reference< table::XCellRange > processKey( const uno::Any& Key, uno::Refere table::CellRangeAddress aRefAddr; if ( !pDocSh ) throw uno::RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Range::Sort no docshell to calculate key param")), uno::Reference< uno::XInterface >() ); - xKeyRange = getRangeForName( xContext, sRangeName, pDocSh, aRefAddr ); + xKeyRange = getRangeForName( uno::Reference< XHelperInterface >(), xContext, sRangeName, pDocSh, aRefAddr ); } else throw uno::RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Range::Sort illegal type value for key param")), uno::Reference< uno::XInterface >() ); @@ -4147,7 +4319,7 @@ ScVbaRange::AutoFilter( const uno::Any& Field, const uno::Any& Criteria1, const uno::Reference< excel::XRange > xCurrent( CurrentRegion() ); if ( xCurrent.is() ) { - ScVbaRange* pRange = dynamic_cast< ScVbaRange* >( xCurrent.get() ); + ScVbaRange* pRange = getImplementation( xCurrent ); if ( pRange->isSingleCellRange() ) throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Can't create AutoFilter") ), uno::Reference< uno::XInterface >() ); if ( pRange ) @@ -4569,6 +4741,27 @@ ScVbaRange::TextToColumns( const css::uno::Any& Destination, const css::uno::Any //TODO* TrailingMinusNumbers Optional Variant. Numbers that begin with a minus character. } +uno::Any SAL_CALL +ScVbaRange::Hyperlinks( const uno::Any& aIndex ) throw (uno::RuntimeException) +{ + /* The range object always returns a new Hyperlinks object containing a + fixed list of existing hyperlinks in the range. + See vbahyperlinks.hxx for more details. */ + + // get the global hyperlink object of the sheet (sheet should always be the parent of a Range object) + uno::Reference< excel::XWorksheet > xWorksheet( getParent(), uno::UNO_QUERY_THROW ); + uno::Reference< excel::XHyperlinks > xSheetHlinks( xWorksheet->Hyperlinks( uno::Any() ), uno::UNO_QUERY_THROW ); + ScVbaHyperlinksRef xScSheetHlinks( dynamic_cast< ScVbaHyperlinks* >( xSheetHlinks.get() ) ); + if( !xScSheetHlinks.is() ) + throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Cannot obtain hyperlinks implementation object" ) ), uno::Reference< uno::XInterface >() ); + + // create a new local hyperlinks object based on the sheet hyperlinks + ScVbaHyperlinksRef xHlinks( new ScVbaHyperlinks( getParent(), mxContext, xScSheetHlinks, getScRangeList() ) ); + if( aIndex.hasValue() ) + return xHlinks->Item( aIndex, uno::Any() ); + return uno::Any( uno::Reference< excel::XHyperlinks >( xHlinks.get() ) ); +} + css::uno::Reference< excel::XValidation > SAL_CALL ScVbaRange::getValidation() throw (css::uno::RuntimeException) { @@ -4577,6 +4770,97 @@ ScVbaRange::getValidation() throw (css::uno::RuntimeException) return m_xValidation; } +namespace { + +sal_Unicode lclGetPrefixChar( const uno::Reference< table::XCell >& rxCell ) throw (uno::RuntimeException) +{ + /* TODO/FIXME: We need an apostroph-prefix property at the cell to + implement this correctly. For now, return an apostroph for every text + cell. + + TODO/FIXME: When Application.TransitionNavigKeys is supported and true, + this function needs to inspect the cell formatting and return different + prefixes according to the horizontal cell alignment. + */ + return (rxCell->getType() == table::CellContentType_TEXT) ? '\'' : 0; +} + +sal_Unicode lclGetPrefixChar( const uno::Reference< table::XCellRange >& rxRange ) throw (uno::RuntimeException) +{ + /* This implementation is able to handle different prefixes (needed if + Application.TransitionNavigKeys is true). The function lclGetPrefixChar + for single cells called from here may return any prefix. If that + function returns an empty prefix (NUL character) or different non-empty + prefixes for two cells, this function returns 0. + */ + sal_Unicode cCurrPrefix = 0; + table::CellRangeAddress aRangeAddr = lclGetRangeAddress( rxRange ); + sal_Int32 nEndCol = aRangeAddr.EndColumn - aRangeAddr.StartColumn; + sal_Int32 nEndRow = aRangeAddr.EndRow - aRangeAddr.StartRow; + for( sal_Int32 nRow = 0; nRow <= nEndRow; ++nRow ) + { + for( sal_Int32 nCol = 0; nCol <= nEndCol; ++nCol ) + { + uno::Reference< table::XCell > xCell( rxRange->getCellByPosition( nCol, nRow ), uno::UNO_SET_THROW ); + sal_Unicode cNewPrefix = lclGetPrefixChar( xCell ); + if( (cNewPrefix == 0) || ((cCurrPrefix != 0) && (cNewPrefix != cCurrPrefix)) ) + return 0; + cCurrPrefix = cNewPrefix; + } + } + // all cells contain the same prefix - return it + return cCurrPrefix; +} + +sal_Unicode lclGetPrefixChar( const uno::Reference< sheet::XSheetCellRangeContainer >& rxRanges ) throw (uno::RuntimeException) +{ + sal_Unicode cCurrPrefix = 0; + uno::Reference< container::XEnumerationAccess > xRangesEA( rxRanges, uno::UNO_QUERY_THROW ); + uno::Reference< container::XEnumeration > xRangesEnum( xRangesEA->createEnumeration(), uno::UNO_SET_THROW ); + while( xRangesEnum->hasMoreElements() ) + { + uno::Reference< table::XCellRange > xRange( xRangesEnum->nextElement(), uno::UNO_QUERY_THROW ); + sal_Unicode cNewPrefix = lclGetPrefixChar( xRange ); + if( (cNewPrefix == 0) || ((cCurrPrefix != 0) && (cNewPrefix != cCurrPrefix)) ) + return 0; + cCurrPrefix = cNewPrefix; + } + // all ranges contain the same prefix - return it + return cCurrPrefix; +} + +inline uno::Any lclGetPrefixVariant( sal_Unicode cPrefixChar ) +{ + return uno::Any( (cPrefixChar == 0) ? ::rtl::OUString() : ::rtl::OUString( cPrefixChar ) ); +} + +} // namespace + +uno::Any SAL_CALL ScVbaRange::getPrefixCharacter() throw (uno::RuntimeException) +{ + /* (1) If Application.TransitionNavigKeys is false, this function returns + an apostroph character if the text cell begins with an apostroph + character (formula return values are not taken into account); otherwise + an empty string. + + (2) If Application.TransitionNavigKeys is true, this function returns + an apostroph character, if the cell is left-aligned; a double-quote + character, if the cell is right-aligned; a circumflex character, if the + cell is centered; a backslash character, if the cell is set to filled; + or an empty string, if nothing of the above. + + If a range or a list of ranges contains texts with leading apostroph + character as well as other cells, this function returns an empty + string. + */ + + if( mxRange.is() ) + return lclGetPrefixVariant( lclGetPrefixChar( mxRange ) ); + if( mxRanges.is() ) + return lclGetPrefixVariant( lclGetPrefixChar( mxRanges ) ); + throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unexpected empty Range object" ) ), uno::Reference< uno::XInterface >() ); +} + uno::Any ScVbaRange::getShowDetail() throw ( css::uno::RuntimeException) { // #FIXME, If the specified range is in a PivotTable report @@ -4701,7 +4985,7 @@ ScVbaRange::PrintOut( const uno::Any& From, const uno::Any& To, const uno::Any& table::CellRangeAddress rangeAddress = thisRange.getCellRangeAddressable()->getRangeAddress(); if ( index == 1 ) { - ScVbaRange* pRange = dynamic_cast< ScVbaRange* >( xRange.get() ); + ScVbaRange* pRange = getImplementation( xRange ); // initialise the doc shell and the printareas pShell = getDocShellFromRange( pRange->mxRange ); xPrintAreas.set( thisRange.getSpreadSheet(), uno::UNO_QUERY_THROW ); @@ -4723,7 +5007,7 @@ void SAL_CALL ScVbaRange::AutoFill( const uno::Reference< excel::XRange >& Destination, const uno::Any& Type ) throw (uno::RuntimeException) { uno::Reference< excel::XRange > xDest( Destination, uno::UNO_QUERY_THROW ); - ScVbaRange* pRange = dynamic_cast< ScVbaRange* >( xDest.get() ); + ScVbaRange* pRange = getImplementation( xDest ); RangeHelper destRangeHelper( pRange->mxRange ); table::CellRangeAddress destAddress = destRangeHelper.getCellRangeAddressable()->getRangeAddress(); @@ -5133,7 +5417,7 @@ ScVbaRange::SpecialCells( const uno::Any& _oType, const uno::Any& _oValue) throw { uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW ); xRange = xRange->SpecialCells( _oType, _oValue); - ScVbaRange* pRange = dynamic_cast< ScVbaRange* >( xRange.get() ); + ScVbaRange* pRange = getImplementation( xRange ); if ( xRange.is() && pRange ) { sal_Int32 nElems = ( pRange->m_Areas->getCount() + 1 ); diff --git a/sc/source/ui/vba/vbarange.hxx b/sc/source/ui/vba/vbarange.hxx index 1f161a79d973..a9147a0d7840 100644 --- a/sc/source/ui/vba/vbarange.hxx +++ b/sc/source/ui/vba/vbarange.hxx @@ -60,6 +60,7 @@ class ScCellRangeObj; class ScCellRangesObj; class ScDocShell; class ScDocument; +class ScRangeList; //typedef InheritedHelperInterfaceImpl1< ov::excel::XRange > ScVbaRange_BASE; typedef ScVbaFormat< ov::excel::XRange > ScVbaRange_BASE; @@ -127,13 +128,27 @@ public: ScVbaRange( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::sheet::XSheetCellRangeContainer >& xRanges, sal_Bool bIsRows = false, sal_Bool bIsColumns = false ) throw ( css::lang::IllegalArgumentException ); ScVbaRange( css::uno::Sequence< css::uno::Any > const& aArgs, css::uno::Reference< css::uno::XComponentContext >const& xContext ) throw ( css::lang::IllegalArgumentException ); - ScDocument* getScDocument(); - ScDocShell* getScDocShell(); + ScDocument* getScDocument() throw (css::uno::RuntimeException); + ScDocShell* getScDocShell() throw (css::uno::RuntimeException); + + /** Returns the ScVbaRange implementation object for the passed VBA Range object. */ + static ScVbaRange* getImplementation( const css::uno::Reference< ov::excel::XRange >& rxRange ); + + css::uno::Reference< css::frame::XModel > getUnoModel() throw (css::uno::RuntimeException); + static css::uno::Reference< css::frame::XModel > getUnoModel( const css::uno::Reference< ov::excel::XRange >& rxRange ) throw (css::uno::RuntimeException); + + const ScRangeList& getScRangeList() throw (css::uno::RuntimeException); + static const ScRangeList& getScRangeList( const css::uno::Reference< ov::excel::XRange >& rxRange ) throw (css::uno::RuntimeException); virtual ~ScVbaRange(); virtual css::uno::Reference< ov::XHelperInterface > thisHelperIface() { return this; } bool isSingleCellRange(); - static css::uno::Reference< ov::excel::XRange > getRangeObjectForName( const css::uno::Reference< css::uno::XComponentContext >& xContext, const rtl::OUString& sRangeName, ScDocShell* pDocSh, formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::CONV_XL_A1 ) throw ( css::uno::RuntimeException ); + + static css::uno::Reference< ov::excel::XRange > getRangeObjectForName( + const css::uno::Reference< ov::XHelperInterface >& xParent, + const css::uno::Reference< css::uno::XComponentContext >& xContext, + const rtl::OUString& sRangeName, ScDocShell* pDocSh, + formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::CONV_XL_A1 ) throw ( css::uno::RuntimeException ); // Attributes virtual css::uno::Any SAL_CALL getValue() throw (css::uno::RuntimeException); @@ -173,6 +188,7 @@ public: virtual css::uno::Any SAL_CALL getPageBreak() throw (css::uno::RuntimeException); virtual void SAL_CALL setPageBreak( const css::uno::Any& _pagebreak ) throw (css::uno::RuntimeException); virtual css::uno::Reference< ov::excel::XValidation > SAL_CALL getValidation() throw (css::uno::RuntimeException); + virtual css::uno::Any SAL_CALL getPrefixCharacter() throw (css::uno::RuntimeException); virtual css::uno::Any SAL_CALL getShowDetail() throw (css::uno::RuntimeException); virtual void SAL_CALL setShowDetail(const css::uno::Any& aShowDetail) throw (css::uno::RuntimeException); // Methods @@ -212,6 +228,7 @@ public: virtual css::uno::Reference< ov::excel::XRange > SAL_CALL Range( const css::uno::Any &Cell1, const css::uno::Any &Cell2 ) throw (css::uno::RuntimeException); virtual css::uno::Reference< ov::excel::XRange > Range( const css::uno::Any &Cell1, const css::uno::Any &Cell2, bool bForceUseInpuRangeTab ) throw (css::uno::RuntimeException); virtual css::uno::Any SAL_CALL getCellRange( ) throw (css::uno::RuntimeException); + static css::uno::Any getCellRange( const css::uno::Reference< ov::excel::XRange >& rxRange ) throw (css::uno::RuntimeException); virtual void SAL_CALL PasteSpecial( const css::uno::Any& Paste, const css::uno::Any& Operation, const css::uno::Any& SkipBlanks, const css::uno::Any& Transpose ) throw (css::uno::RuntimeException); virtual ::sal_Bool SAL_CALL Replace( const ::rtl::OUString& What, const ::rtl::OUString& Replacement, const css::uno::Any& LookAt, const css::uno::Any& SearchOrder, const css::uno::Any& MatchCase, const css::uno::Any& MatchByte, const css::uno::Any& SearchFormat, const css::uno::Any& ReplaceFormat ) throw (css::uno::RuntimeException); virtual css::uno::Reference< ov::excel::XRange > SAL_CALL Find( const css::uno::Any& What, const css::uno::Any& After, const css::uno::Any& LookIn, const css::uno::Any& LookAt, const css::uno::Any& SearchOrder, const css::uno::Any& SearchDirection, const css::uno::Any& MatchCase, const css::uno::Any& MatchByte, const css::uno::Any& SearchFormat ) throw (css::uno::RuntimeException); @@ -227,6 +244,7 @@ public: const css::uno::Any& ConsecutinveDelimiter, const css::uno::Any& Tab, const css::uno::Any& Semicolon, const css::uno::Any& Comma, const css::uno::Any& Space, const css::uno::Any& Other, const css::uno::Any& OtherChar, const css::uno::Any& FieldInfo, const css::uno::Any& DecimalSeparator, const css::uno::Any& ThousandsSeparator, const css::uno::Any& TrailingMinusNumbers ) throw (css::uno::RuntimeException); + virtual css::uno::Any SAL_CALL Hyperlinks( const css::uno::Any& aIndex ) throw (css::uno::RuntimeException); virtual void SAL_CALL AutoFilter( const css::uno::Any& Field, const css::uno::Any& Criteria1, const css::uno::Any& Operator, const css::uno::Any& Criteria2, const css::uno::Any& VisibleDropDown ) throw (css::uno::RuntimeException); virtual void SAL_CALL Insert( const css::uno::Any& Shift, const css::uno::Any& CopyOrigin ) throw (css::uno::RuntimeException); diff --git a/sc/source/ui/vba/vbasheetobject.cxx b/sc/source/ui/vba/vbasheetobject.cxx new file mode 100755 index 000000000000..4bd0f1d60547 --- /dev/null +++ b/sc/source/ui/vba/vbasheetobject.cxx @@ -0,0 +1,517 @@ +/************************************************************************* + * + * 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 "vbasheetobject.hxx" +#include <com/sun/star/awt/TextAlign.hpp> +#include <com/sun/star/container/XIndexContainer.hpp> +#include <com/sun/star/drawing/XControlShape.hpp> +#include <com/sun/star/script/ScriptEventDescriptor.hpp> +#include <com/sun/star/script/XEventAttacherManager.hpp> +#include <com/sun/star/style/VerticalAlignment.hpp> +#include <ooo/vba/excel/Constants.hpp> +#include <ooo/vba/excel/XlOrientation.hpp> +#include <ooo/vba/excel/XlPlacement.hpp> +#include <rtl/ustrbuf.hxx> +#include <filter/msfilter/msvbahelper.hxx> +#include <oox/helper/helper.hxx> +#include "vbafont.hxx" + +using ::rtl::OUString; +using namespace ::com::sun::star; +using namespace ::ooo::vba; + +// ============================================================================ + +ScVbaButtonCharacters::ScVbaButtonCharacters( + const uno::Reference< XHelperInterface >& rxParent, + const uno::Reference< uno::XComponentContext >& rxContext, + const uno::Reference< beans::XPropertySet >& rxPropSet, + const ScVbaPalette& rPalette, + const uno::Any& rStart, + const uno::Any& rLength ) throw (uno::RuntimeException) : + ScVbaButtonCharacters_BASE( rxParent, rxContext ), + maPalette( rPalette ), + mxPropSet( rxPropSet, uno::UNO_SET_THROW ) +{ + // extract optional start parameter (missing or invalid -> from beginning) + if( !(rStart >>= mnStart) || (mnStart < 1) ) + mnStart = 1; + --mnStart; // VBA is 1-based, rtl string is 0-based + + // extract optional length parameter (missing or invalid -> to end) + if( !(rLength >>= mnLength) || (mnLength < 1) ) + mnLength = SAL_MAX_INT32; +} + +ScVbaButtonCharacters::~ScVbaButtonCharacters() +{ +} + +// XCharacters attributes + +OUString SAL_CALL ScVbaButtonCharacters::getCaption() throw (uno::RuntimeException) +{ + // ignore invalid mnStart and/or mnLength members + OUString aString = getFullString(); + sal_Int32 nStart = ::std::min( mnStart, aString.getLength() ); + sal_Int32 nLength = ::std::min( mnLength, aString.getLength() - nStart ); + return aString.copy( nStart, nLength ); +} + +void SAL_CALL ScVbaButtonCharacters::setCaption( const OUString& rCaption ) throw (uno::RuntimeException) +{ + /* Replace the covered text with the passed text, ignore invalid mnStart + and/or mnLength members. This operation does not affect the mnLength + parameter. If the inserted text is longer than mnLength, the additional + characters are not covered by this object. If the inserted text is + shorter than mnLength, other uncovered characters from the original + string will be covered now, thus may be changed with subsequent + operations. */ + OUString aString = getFullString(); + sal_Int32 nStart = ::std::min( mnStart, aString.getLength() ); + sal_Int32 nLength = ::std::min( mnLength, aString.getLength() - nStart ); + setFullString( aString.replaceAt( nStart, nLength, rCaption ) ); +} + +sal_Int32 SAL_CALL ScVbaButtonCharacters::getCount() throw (uno::RuntimeException) +{ + // always return the total length of the caption + return getFullString().getLength(); +} + +OUString SAL_CALL ScVbaButtonCharacters::getText() throw (uno::RuntimeException) +{ + // Text attribute same as Caption attribute? + return getCaption(); +} + +void SAL_CALL ScVbaButtonCharacters::setText( const OUString& rText ) throw (uno::RuntimeException) +{ + // Text attribute same as Caption attribute? + setCaption( rText ); +} + +uno::Reference< excel::XFont > SAL_CALL ScVbaButtonCharacters::getFont() throw (uno::RuntimeException) +{ + return new ScVbaFont( this, mxContext, maPalette, mxPropSet, 0, true ); +} + +void SAL_CALL ScVbaButtonCharacters::setFont( const uno::Reference< excel::XFont >& /*rxFont*/ ) throw (uno::RuntimeException) +{ + // TODO +} + +// XCharacters methods + +void SAL_CALL ScVbaButtonCharacters::Insert( const OUString& rString ) throw (uno::RuntimeException) +{ + /* The Insert() operation is in fact "replace covered characters", at + least for buttons... It seems there is no easy way to really insert a + substring. This operation does not affect the mnLength parameter. */ + setCaption( rString ); +} + +void SAL_CALL ScVbaButtonCharacters::Delete() throw (uno::RuntimeException) +{ + /* The Delete() operation is nothing else than "replace with empty string". + This does not affect the mnLength parameter, multiple calls of Delete() + will remove characters as long as there are some more covered by this + object. */ + setCaption( OUString() ); +} + +// XHelperInterface + +VBAHELPER_IMPL_XHELPERINTERFACE( ScVbaButtonCharacters, "ooo.vba.excel.Characters" ) + +// private + +OUString ScVbaButtonCharacters::getFullString() const throw (uno::RuntimeException) +{ + return mxPropSet->getPropertyValue( CREATE_OUSTRING( "Label" ) ).get< OUString >(); +} + +void ScVbaButtonCharacters::setFullString( const OUString& rString ) throw (uno::RuntimeException) +{ + mxPropSet->setPropertyValue( CREATE_OUSTRING( "Label" ), uno::Any( rString ) ); +} + +// ============================================================================ + +ScVbaSheetObjectBase::ScVbaSheetObjectBase( + const uno::Reference< XHelperInterface >& rxParent, + const uno::Reference< uno::XComponentContext >& rxContext, + const uno::Reference< frame::XModel >& rxModel, + const uno::Reference< drawing::XShape >& rxShape ) throw (uno::RuntimeException) : + ScVbaSheetObject_BASE( rxParent, rxContext ), + maPalette( rxModel ), + mxModel( rxModel, uno::UNO_SET_THROW ), + mxShape( rxShape, uno::UNO_SET_THROW ), + mxShapeProps( rxShape, uno::UNO_QUERY_THROW ) +{ +} + +// XSheetObject attributes + +double SAL_CALL ScVbaSheetObjectBase::getLeft() throw (uno::RuntimeException) +{ + return HmmToPoints( mxShape->getPosition().X ); +} + +void SAL_CALL ScVbaSheetObjectBase::setLeft( double fLeft ) throw (uno::RuntimeException) +{ + if( fLeft < 0.0 ) + throw uno::RuntimeException(); + mxShape->setPosition( awt::Point( PointsToHmm( fLeft ), mxShape->getPosition().Y ) ); +} + +double SAL_CALL ScVbaSheetObjectBase::getTop() throw (uno::RuntimeException) +{ + return HmmToPoints( mxShape->getPosition().Y ); +} + +void SAL_CALL ScVbaSheetObjectBase::setTop( double fTop ) throw (uno::RuntimeException) +{ + if( fTop < 0.0 ) + throw uno::RuntimeException(); + mxShape->setPosition( awt::Point( mxShape->getPosition().X, PointsToHmm( fTop ) ) ); +} + +double SAL_CALL ScVbaSheetObjectBase::getWidth() throw (uno::RuntimeException) +{ + return HmmToPoints( mxShape->getSize().Width ); +} + +void SAL_CALL ScVbaSheetObjectBase::setWidth( double fWidth ) throw (uno::RuntimeException) +{ + if( fWidth <= 0.0 ) + throw uno::RuntimeException(); + mxShape->setSize( awt::Size( PointsToHmm( fWidth ), mxShape->getSize().Height ) ); +} + +double SAL_CALL ScVbaSheetObjectBase::getHeight() throw (uno::RuntimeException) +{ + return HmmToPoints( mxShape->getSize().Height ); +} + +void SAL_CALL ScVbaSheetObjectBase::setHeight( double fHeight ) throw (uno::RuntimeException) +{ + if( fHeight <= 0.0 ) + throw uno::RuntimeException(); + mxShape->setSize( awt::Size( mxShape->getSize().Width, PointsToHmm( fHeight ) ) ); +} + +OUString SAL_CALL ScVbaSheetObjectBase::getName() throw (uno::RuntimeException) +{ + return mxShapeProps->getPropertyValue( CREATE_OUSTRING( "Name" ) ).get< OUString >(); +} + +void SAL_CALL ScVbaSheetObjectBase::setName( const OUString& rName ) throw (uno::RuntimeException) +{ + mxShapeProps->setPropertyValue( CREATE_OUSTRING( "Name" ), uno::Any( rName ) ); +} + +sal_Int32 SAL_CALL ScVbaSheetObjectBase::getPlacement() throw (uno::RuntimeException) +{ + // TODO + return excel::XlPlacement::xlMoveAndSize; +} + +void SAL_CALL ScVbaSheetObjectBase::setPlacement( sal_Int32 /*nPlacement*/ ) throw (uno::RuntimeException) +{ + // TODO +} + +sal_Bool SAL_CALL ScVbaSheetObjectBase::getPrintObject() throw (uno::RuntimeException) +{ + // not supported + return sal_True; +} + +void SAL_CALL ScVbaSheetObjectBase::setPrintObject( sal_Bool /*bPrintObject*/ ) throw (uno::RuntimeException) +{ + // not supported +} + +// private + +void ScVbaSheetObjectBase::setDefaultProperties( sal_Int32 nIndex ) throw (uno::RuntimeException) +{ + OUString aName = ::rtl::OUStringBuffer( implGetBaseName() ).append( sal_Unicode( ' ' ) ).append( nIndex + 1 ).makeStringAndClear(); + setName( aName ); + implSetDefaultProperties(); +} + +void ScVbaSheetObjectBase::implSetDefaultProperties() throw (uno::RuntimeException) +{ +} + +// ============================================================================ + +ScVbaControlObjectBase::ScVbaControlObjectBase( + const uno::Reference< XHelperInterface >& rxParent, + const uno::Reference< uno::XComponentContext >& rxContext, + const uno::Reference< frame::XModel >& rxModel, + const uno::Reference< container::XIndexContainer >& rxFormIC, + const uno::Reference< drawing::XControlShape >& rxControlShape, + ListenerType eListenerType ) throw (uno::RuntimeException) : + ScVbaControlObject_BASE( rxParent, rxContext, rxModel, uno::Reference< drawing::XShape >( rxControlShape, uno::UNO_QUERY_THROW ) ), + mxFormIC( rxFormIC, uno::UNO_SET_THROW ), + mxControlProps( rxControlShape->getControl(), uno::UNO_QUERY_THROW ) +{ + // set listener and event name to be used for OnAction attribute + switch( eListenerType ) + { + case LISTENER_ACTION: + maListenerType = CREATE_OUSTRING( "XActionListener" ); + maEventMethod = CREATE_OUSTRING( "actionPerformed" ); + break; + case LISTENER_MOUSE: + maListenerType = CREATE_OUSTRING( "XMouseListener" ); + maEventMethod = CREATE_OUSTRING( "mouseReleased" ); + break; + case LISTENER_TEXT: + maListenerType = CREATE_OUSTRING( "XTextListener" ); + maEventMethod = CREATE_OUSTRING( "textChanged" ); + break; + case LISTENER_VALUE: + maListenerType = CREATE_OUSTRING( "XAdjustmentListener" ); + maEventMethod = CREATE_OUSTRING( "adjustmentValueChanged" ); + break; + case LISTENER_CHANGE: + maListenerType = CREATE_OUSTRING( "XChangeListener" ); + maEventMethod = CREATE_OUSTRING( "changed" ); + break; + // no default, to let the compiler complain about missing case + } +} + +// XSheetObject attributes + +OUString SAL_CALL ScVbaControlObjectBase::getName() throw (uno::RuntimeException) +{ + return mxControlProps->getPropertyValue( CREATE_OUSTRING( "Name" ) ).get< OUString >(); +} + +void SAL_CALL ScVbaControlObjectBase::setName( const OUString& rName ) throw (uno::RuntimeException) +{ + mxControlProps->setPropertyValue( CREATE_OUSTRING( "Name" ), uno::Any( rName ) ); +} + +OUString SAL_CALL ScVbaControlObjectBase::getOnAction() throw (uno::RuntimeException) +{ + uno::Reference< script::XEventAttacherManager > xEventMgr( mxFormIC, uno::UNO_QUERY_THROW ); + sal_Int32 nIndex = getModelIndexInForm(); + uno::Sequence< script::ScriptEventDescriptor > aEvents = xEventMgr->getScriptEvents( nIndex ); + if( aEvents.hasElements() ) + { + const script::ScriptEventDescriptor* pEvent = aEvents.getConstArray(); + const script::ScriptEventDescriptor* pEventEnd = pEvent + aEvents.getLength(); + const OUString aScriptType = CREATE_OUSTRING( "Script" ); + for( ; pEvent < pEventEnd; ++pEvent ) + if( (pEvent->ListenerType == maListenerType) && (pEvent->EventMethod == maEventMethod) && (pEvent->ScriptType == aScriptType) ) + return extractMacroName( pEvent->ScriptCode ); + } + return OUString(); +} + +void SAL_CALL ScVbaControlObjectBase::setOnAction( const OUString& rMacroName ) throw (uno::RuntimeException) +{ + uno::Reference< script::XEventAttacherManager > xEventMgr( mxFormIC, uno::UNO_QUERY_THROW ); + sal_Int32 nIndex = getModelIndexInForm(); + + // first, remove a registered event (try/catch just in case implementation throws) + try { xEventMgr->revokeScriptEvent( nIndex, maListenerType, maEventMethod, OUString() ); } catch( uno::Exception& ) {} + + // if a macro name has been passed, try to attach it to the event + if( rMacroName.getLength() > 0 ) + { + VBAMacroResolvedInfo aResolvedMacro = resolveVBAMacro( getSfxObjShell( mxModel ), rMacroName ); + if( !aResolvedMacro.IsResolved() ) + throw uno::RuntimeException(); + script::ScriptEventDescriptor aDescriptor; + aDescriptor.ListenerType = maListenerType; + aDescriptor.EventMethod = maEventMethod; + aDescriptor.ScriptType = CREATE_OUSTRING( "Script" ); + aDescriptor.ScriptCode = makeMacroURL( aResolvedMacro.ResolvedMacro() ); + xEventMgr->registerScriptEvent( nIndex, aDescriptor ); + } +} + +sal_Bool SAL_CALL ScVbaControlObjectBase::getPrintObject() throw (uno::RuntimeException) +{ + return mxControlProps->getPropertyValue( CREATE_OUSTRING( "Printable" ) ).get< sal_Bool >(); +} + +void SAL_CALL ScVbaControlObjectBase::setPrintObject( sal_Bool bPrintObject ) throw (uno::RuntimeException) +{ + mxControlProps->setPropertyValue( CREATE_OUSTRING( "Printable" ), uno::Any( bPrintObject ) ); +} + +// XControlObject attributes + +sal_Bool SAL_CALL ScVbaControlObjectBase::getAutoSize() throw (uno::RuntimeException) +{ + // not supported + return sal_False; +} + +void SAL_CALL ScVbaControlObjectBase::setAutoSize( sal_Bool /*bAutoSize*/ ) throw (uno::RuntimeException) +{ + // not supported +} + +// private + +sal_Int32 ScVbaControlObjectBase::getModelIndexInForm() const throw (uno::RuntimeException) +{ + for( sal_Int32 nIndex = 0, nCount = mxFormIC->getCount(); nIndex < nCount; ++nIndex ) + { + uno::Reference< beans::XPropertySet > xProps( mxFormIC->getByIndex( nIndex ), uno::UNO_QUERY_THROW ); + if( mxControlProps.get() == xProps.get() ) + return nIndex; + } + throw uno::RuntimeException(); +} + +// ============================================================================ + +ScVbaButton::ScVbaButton( + const uno::Reference< XHelperInterface >& rxParent, + const uno::Reference< uno::XComponentContext >& rxContext, + const uno::Reference< frame::XModel >& rxModel, + const uno::Reference< container::XIndexContainer >& rxFormIC, + const uno::Reference< drawing::XControlShape >& rxControlShape ) throw (uno::RuntimeException) : + ScVbaButton_BASE( rxParent, rxContext, rxModel, rxFormIC, rxControlShape, LISTENER_ACTION ) +{ +} + +// XButton attributes + +OUString SAL_CALL ScVbaButton::getCaption() throw (uno::RuntimeException) +{ + return mxControlProps->getPropertyValue( CREATE_OUSTRING( "Label" ) ).get< OUString >(); +} + +void SAL_CALL ScVbaButton::setCaption( const OUString& rCaption ) throw (uno::RuntimeException) +{ + mxControlProps->setPropertyValue( CREATE_OUSTRING( "Label" ), uno::Any( rCaption ) ); +} + +uno::Reference< excel::XFont > SAL_CALL ScVbaButton::getFont() throw (uno::RuntimeException) +{ + return new ScVbaFont( this, mxContext, maPalette, mxControlProps, 0, true ); +} + +void SAL_CALL ScVbaButton::setFont( const uno::Reference< excel::XFont >& /*rxFont*/ ) throw (uno::RuntimeException) +{ + // TODO +} + +sal_Int32 SAL_CALL ScVbaButton::getHorizontalAlignment() throw (uno::RuntimeException) +{ + switch( mxControlProps->getPropertyValue( CREATE_OUSTRING( "Align" ) ).get< sal_Int16 >() ) + { + case awt::TextAlign::LEFT: return excel::Constants::xlLeft; + case awt::TextAlign::RIGHT: return excel::Constants::xlRight; + case awt::TextAlign::CENTER: return excel::Constants::xlCenter; + } + return excel::Constants::xlCenter; +} + +void SAL_CALL ScVbaButton::setHorizontalAlignment( sal_Int32 nAlign ) throw (uno::RuntimeException) +{ + sal_Int32 nAwtAlign = awt::TextAlign::CENTER; + switch( nAlign ) + { + case excel::Constants::xlLeft: nAwtAlign = awt::TextAlign::LEFT; break; + case excel::Constants::xlRight: nAwtAlign = awt::TextAlign::RIGHT; break; + case excel::Constants::xlCenter: nAwtAlign = awt::TextAlign::CENTER; break; + } + // form controls expect short value + mxControlProps->setPropertyValue( CREATE_OUSTRING( "Align" ), uno::Any( static_cast< sal_Int16 >( nAwtAlign ) ) ); +} + +sal_Int32 SAL_CALL ScVbaButton::getVerticalAlignment() throw (uno::RuntimeException) +{ + switch( mxControlProps->getPropertyValue( CREATE_OUSTRING( "VerticalAlign" ) ).get< style::VerticalAlignment >() ) + { + case style::VerticalAlignment_TOP: return excel::Constants::xlTop; + case style::VerticalAlignment_BOTTOM: return excel::Constants::xlBottom; + case style::VerticalAlignment_MIDDLE: return excel::Constants::xlCenter; + default:; + } + return excel::Constants::xlCenter; +} + +void SAL_CALL ScVbaButton::setVerticalAlignment( sal_Int32 nAlign ) throw (uno::RuntimeException) +{ + style::VerticalAlignment eAwtAlign = style::VerticalAlignment_MIDDLE; + switch( nAlign ) + { + case excel::Constants::xlTop: eAwtAlign = style::VerticalAlignment_TOP; break; + case excel::Constants::xlBottom: eAwtAlign = style::VerticalAlignment_BOTTOM; break; + case excel::Constants::xlCenter: eAwtAlign = style::VerticalAlignment_MIDDLE; break; + } + mxControlProps->setPropertyValue( CREATE_OUSTRING( "VerticalAlign" ), uno::Any( eAwtAlign ) ); +} + +sal_Int32 SAL_CALL ScVbaButton::getOrientation() throw (uno::RuntimeException) +{ + // not supported + return excel::XlOrientation::xlHorizontal; +} + +void SAL_CALL ScVbaButton::setOrientation( sal_Int32 /*nOrientation*/ ) throw (uno::RuntimeException) +{ + // not supported +} + +// XButton methods + +uno::Reference< excel::XCharacters > SAL_CALL ScVbaButton::Characters( const uno::Any& rStart, const uno::Any& rLength ) throw (uno::RuntimeException) +{ + return new ScVbaButtonCharacters( this, mxContext, mxControlProps, maPalette, rStart, rLength ); +} + +// XHelperInterface + +VBAHELPER_IMPL_XHELPERINTERFACE( ScVbaButton, "ooo.vba.excel.Button" ) + +// private + +OUString ScVbaButton::implGetBaseName() const +{ + return CREATE_OUSTRING( "Button" ); +} + +void ScVbaButton::implSetDefaultProperties() throw (uno::RuntimeException) +{ + setCaption( getName() ); +} + +// ============================================================================ diff --git a/sc/source/ui/vba/vbasheetobject.hxx b/sc/source/ui/vba/vbasheetobject.hxx new file mode 100755 index 000000000000..b2546ca09c93 --- /dev/null +++ b/sc/source/ui/vba/vbasheetobject.hxx @@ -0,0 +1,220 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef SC_VBA_SHEETOBJECT_HXX +#define SC_VBA_SHEETOBJECT_HXX + +#include <memory> +#include <ooo/vba/excel/XButton.hpp> +#include <ooo/vba/excel/XControlObject.hpp> +#include <ooo/vba/excel/XSheetObject.hpp> +#include <vbahelper/vbahelperinterface.hxx> +#include "vbapalette.hxx" + +namespace com { namespace sun { namespace star { + namespace container { class XIndexContainer; } + namespace drawing { class XControlShape; } +} } } + +// ============================================================================ + +typedef InheritedHelperInterfaceImpl1< ov::excel::XCharacters > ScVbaButtonCharacters_BASE; + +/** Simple implementation of the Characters symbol for drawing button objects. */ +class ScVbaButtonCharacters : public ScVbaButtonCharacters_BASE +{ +public: + explicit ScVbaButtonCharacters( + const css::uno::Reference< ov::XHelperInterface >& rxParent, + const css::uno::Reference< css::uno::XComponentContext >& rxContext, + const css::uno::Reference< css::beans::XPropertySet >& rxPropSet, + const ScVbaPalette& rPalette, + const css::uno::Any& rStart, + const css::uno::Any& rLength ) throw (css::uno::RuntimeException); + virtual ~ScVbaButtonCharacters(); + + // XCharacters attributes + virtual ::rtl::OUString SAL_CALL getCaption() throw (css::uno::RuntimeException); + virtual void SAL_CALL setCaption( const ::rtl::OUString& rCaption ) throw (css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getText() throw (css::uno::RuntimeException); + virtual void SAL_CALL setText( const ::rtl::OUString& rText ) throw (css::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getCount() throw (css::uno::RuntimeException); + virtual css::uno::Reference< ov::excel::XFont > SAL_CALL getFont() throw (css::uno::RuntimeException); + virtual void SAL_CALL setFont( const css::uno::Reference< ov::excel::XFont >& rxFont ) throw (css::uno::RuntimeException); + + // XCharacters methods + virtual void SAL_CALL Insert( const ::rtl::OUString& rString ) throw (css::uno::RuntimeException); + virtual void SAL_CALL Delete() throw (css::uno::RuntimeException); + + // XHelperInterface + VBAHELPER_DECL_XHELPERINTERFACE + +private: + ::rtl::OUString getFullString() const throw (css::uno::RuntimeException); + void setFullString( const ::rtl::OUString& rString ) throw (css::uno::RuntimeException); + +private: + ScVbaPalette maPalette; + css::uno::Reference< css::beans::XPropertySet > mxPropSet; + sal_Int32 mnStart; + sal_Int32 mnLength; +}; + +// ============================================================================ + +typedef InheritedHelperInterfaceImpl1< ov::excel::XSheetObject > ScVbaSheetObject_BASE; + +/** Base class for drawing objects embedded in sheets. */ +class ScVbaSheetObjectBase : public ScVbaSheetObject_BASE +{ +public: + explicit ScVbaSheetObjectBase( + const css::uno::Reference< ov::XHelperInterface >& rxParent, + const css::uno::Reference< css::uno::XComponentContext >& rxContext, + const css::uno::Reference< css::frame::XModel >& rxModel, + const css::uno::Reference< css::drawing::XShape >& rxShape ) throw (css::uno::RuntimeException); + + // XSheetObject attributes + virtual double SAL_CALL getLeft() throw (css::uno::RuntimeException); + virtual void SAL_CALL setLeft( double fLeft ) throw (css::uno::RuntimeException); + virtual double SAL_CALL getTop() throw (css::uno::RuntimeException); + virtual void SAL_CALL setTop( double fTop ) throw (css::uno::RuntimeException); + virtual double SAL_CALL getWidth() throw (css::uno::RuntimeException); + virtual void SAL_CALL setWidth( double fWidth ) throw (css::uno::RuntimeException); + virtual double SAL_CALL getHeight() throw (css::uno::RuntimeException); + virtual void SAL_CALL setHeight( double fHeight ) throw (css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException); + virtual void SAL_CALL setName( const ::rtl::OUString& rName ) throw (css::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getPlacement() throw (css::uno::RuntimeException); + virtual void SAL_CALL setPlacement( sal_Int32 nPlacement ) throw (css::uno::RuntimeException); + virtual sal_Bool SAL_CALL getPrintObject() throw (css::uno::RuntimeException); + virtual void SAL_CALL setPrintObject( sal_Bool bPrintObject ) throw (css::uno::RuntimeException); + + /** Sets default properties after a new object has been created. */ + void setDefaultProperties( sal_Int32 nIndex ) throw (css::uno::RuntimeException); + +protected: + /** Derived classes return the base name used for new objects. */ + virtual ::rtl::OUString implGetBaseName() const = 0; + /** Derived classes set default properties for new drawing objects. */ + virtual void implSetDefaultProperties() throw (css::uno::RuntimeException); + +protected: + ScVbaPalette maPalette; + css::uno::Reference< css::frame::XModel > mxModel; + css::uno::Reference< css::drawing::XShape > mxShape; + css::uno::Reference< css::beans::XPropertySet > mxShapeProps; +}; + +// ============================================================================ + +typedef ::cppu::ImplInheritanceHelper1< ScVbaSheetObjectBase, ov::excel::XControlObject > ScVbaControlObject_BASE; + +class ScVbaControlObjectBase : public ScVbaControlObject_BASE +{ +public: + /** Specifies the listener used for OnAction events. */ + enum ListenerType + { + LISTENER_ACTION, /// XActionListener.actionPerformed + LISTENER_MOUSE, /// XMouseListener.mouseReleased + LISTENER_TEXT, /// XTextListener.textChanged + LISTENER_VALUE, /// XAdjustmentListener.adjustmentValueChanged + LISTENER_CHANGE /// XChangeListener.changed + }; + + explicit ScVbaControlObjectBase( + const css::uno::Reference< ov::XHelperInterface >& rxParent, + const css::uno::Reference< css::uno::XComponentContext >& rxContext, + const css::uno::Reference< css::frame::XModel >& rxModel, + const css::uno::Reference< css::container::XIndexContainer >& rxFormIC, + const css::uno::Reference< css::drawing::XControlShape >& rxControlShape, + ListenerType eListenerType ) throw (css::uno::RuntimeException); + + // XSheetObject attributes + virtual ::rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException); + virtual void SAL_CALL setName( const ::rtl::OUString& rName ) throw (css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getOnAction() throw (css::uno::RuntimeException); + virtual void SAL_CALL setOnAction( const ::rtl::OUString& rMacroName ) throw (css::uno::RuntimeException); + virtual sal_Bool SAL_CALL getPrintObject() throw (css::uno::RuntimeException); + virtual void SAL_CALL setPrintObject( sal_Bool bPrintObject ) throw (css::uno::RuntimeException); + + // XControlObject attributes + virtual sal_Bool SAL_CALL getAutoSize() throw (css::uno::RuntimeException); + virtual void SAL_CALL setAutoSize( sal_Bool bAutoSize ) throw (css::uno::RuntimeException); + +protected: + sal_Int32 getModelIndexInForm() const throw (css::uno::RuntimeException); + +protected: + css::uno::Reference< css::container::XIndexContainer > mxFormIC; + css::uno::Reference< css::beans::XPropertySet > mxControlProps; + ::rtl::OUString maListenerType; + ::rtl::OUString maEventMethod; +}; + +// ============================================================================ + +typedef ::cppu::ImplInheritanceHelper1< ScVbaControlObjectBase, ov::excel::XButton > ScVbaButton_BASE; + +class ScVbaButton : public ScVbaButton_BASE +{ +public: + explicit ScVbaButton( + const css::uno::Reference< ov::XHelperInterface >& rxParent, + const css::uno::Reference< css::uno::XComponentContext >& rxContext, + const css::uno::Reference< css::frame::XModel >& rxModel, + const css::uno::Reference< css::container::XIndexContainer >& rxFormIC, + const css::uno::Reference< css::drawing::XControlShape >& rxControlShape ) throw (css::uno::RuntimeException); + + // XButton attributes + virtual ::rtl::OUString SAL_CALL getCaption() throw (css::uno::RuntimeException); + virtual void SAL_CALL setCaption( const ::rtl::OUString& rCaption ) throw (css::uno::RuntimeException); + virtual css::uno::Reference< ov::excel::XFont > SAL_CALL getFont() throw (css::uno::RuntimeException); + virtual void SAL_CALL setFont( const css::uno::Reference< ov::excel::XFont >& rxFont ) throw (css::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getHorizontalAlignment() throw (css::uno::RuntimeException); + virtual void SAL_CALL setHorizontalAlignment( sal_Int32 nAlign ) throw (css::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getVerticalAlignment() throw (css::uno::RuntimeException); + virtual void SAL_CALL setVerticalAlignment( sal_Int32 nAlign ) throw (css::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getOrientation() throw (css::uno::RuntimeException); + virtual void SAL_CALL setOrientation( sal_Int32 nOrientation ) throw (css::uno::RuntimeException); + + // XButton methods + css::uno::Reference< ov::excel::XCharacters > SAL_CALL Characters( + const css::uno::Any& rStart, const css::uno::Any& rLength ) throw (css::uno::RuntimeException); + + // XHelperInterface + VBAHELPER_DECL_XHELPERINTERFACE + +protected: + virtual ::rtl::OUString implGetBaseName() const; + virtual void implSetDefaultProperties() throw (css::uno::RuntimeException); +}; + +// ============================================================================ + +#endif diff --git a/sc/source/ui/vba/vbasheetobjects.cxx b/sc/source/ui/vba/vbasheetobjects.cxx new file mode 100755 index 000000000000..ced94db5ba76 --- /dev/null +++ b/sc/source/ui/vba/vbasheetobjects.cxx @@ -0,0 +1,534 @@ +/************************************************************************* + * + * 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 "vbasheetobjects.hxx" +#include <vector> +#include <rtl/math.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XIndexContainer.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/drawing/XControlShape.hpp> +#include <com/sun/star/drawing/XDrawPageSupplier.hpp> +#include <com/sun/star/drawing/XShapes.hpp> +#include <com/sun/star/form/FormComponentType.hpp> +#include <com/sun/star/form/XForm.hpp> +#include <com/sun/star/form/XFormComponent.hpp> +#include <com/sun/star/form/XFormsSupplier.hpp> +#include <oox/helper/helper.hxx> +#include "vbasheetobject.hxx" + +using ::rtl::OUString; +using namespace ::com::sun::star; +using namespace ::ooo::vba; + +// ============================================================================ + +namespace { + +template< typename Type > +inline bool lclGetProperty( Type& orValue, const uno::Reference< beans::XPropertySet >& rxPropSet, const OUString& rPropName ) +{ + try + { + return rxPropSet->getPropertyValue( rPropName ) >>= orValue; + } + catch( uno::Exception& ) + { + } + return false; +} + +/** Rounds the passed value to a multiple of 0.75 and converts it to 1/100 mm. */ +inline double lclPointsToHmm( const uno::Any& rPoints ) throw (uno::RuntimeException) +{ + return PointsToHmm( ::rtl::math::approxFloor( rPoints.get< double >() / 0.75 ) * 0.75 ); +} + +} // namespace + +// ============================================================================ +// Base implementations +// ============================================================================ + +/** Container for a specific type of drawing object in a spreadsheet. + + Derived classes provide all required functionality specific to the type of + shapes covered by the container. + */ +class ScVbaObjectContainer : public ::cppu::WeakImplHelper1< container::XIndexAccess > +{ +public: + explicit ScVbaObjectContainer( + const uno::Reference< XHelperInterface >& rxParent, + const uno::Reference< uno::XComponentContext >& rxContext, + const uno::Reference< frame::XModel >& rxModel, + const uno::Reference< sheet::XSpreadsheet >& rxSheet, + const uno::Type& rVbaType ) throw (uno::RuntimeException); + + /** Returns the VBA helper interface of the VBA collection object. */ + inline const uno::Reference< XHelperInterface >& getParent() const { return mxParent; } + /** Returns the component context of the VBA collection object. */ + inline const uno::Reference< uno::XComponentContext >& getContext() const { return mxContext; } + /** Returns the VBA type information of the objects in this container. */ + inline const uno::Type& getVbaType() const { return maVbaType; } + + /** Collects all shapes supported by this instance and inserts them into + the internal shape vector. */ + void collectShapes() throw (uno::RuntimeException); + /** Creates and returns a new UNO shape. */ + uno::Reference< drawing::XShape > createShape( const awt::Point& rPos, const awt::Size& rSize ) throw (uno::RuntimeException); + /** Inserts the passed shape into the draw page and into this container, and returns its index in the draw page. */ + sal_Int32 insertShape( const uno::Reference< drawing::XShape >& rxShape ) throw (uno::RuntimeException); + /** Creates and returns a new VBA implementation object for the passed shape. */ + ::rtl::Reference< ScVbaSheetObjectBase > createVbaObject( const uno::Reference< drawing::XShape >& rxShape ) throw (uno::RuntimeException); + /** Creates and returns a new VBA implementation object for the passed shape in an Any. */ + uno::Any createCollectionObject( const uno::Any& rSource ) throw (uno::RuntimeException); + /** Returns the VBA implementation object with the specified name. */ + uno::Any getItemByStringIndex( const OUString& rIndex ) throw (uno::RuntimeException); + + // XIndexAccess + virtual sal_Int32 SAL_CALL getCount() throw (uno::RuntimeException); + virtual uno::Any SAL_CALL getByIndex( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException); + + // XElementAccess + virtual uno::Type SAL_CALL getElementType() throw (uno::RuntimeException); + virtual sal_Bool SAL_CALL hasElements() throw (uno::RuntimeException); + +protected: + /** Derived classes return true, if the passed shape is supported by the instance. */ + virtual bool implPickShape( const uno::Reference< drawing::XShape >& rxShape ) const = 0; + /** Derived classes create and return a new VBA implementation object for the passed shape. */ + virtual ScVbaSheetObjectBase* implCreateVbaObject( const uno::Reference< drawing::XShape >& rxShape ) throw (uno::RuntimeException) = 0; + /** Derived classes return the service name of the UNO shape. */ + virtual OUString implGetShapeServiceName() const = 0; + + /** Returns the shape name via 'Name' property of the UNO shape. May be overwritten. */ + virtual OUString implGetShapeName( const uno::Reference< drawing::XShape >& rxShape ) const throw (uno::RuntimeException); + /** Is called when a new UNO shape has been created but not yet inserted into the drawing page. */ + virtual void implOnShapeCreated( const uno::Reference< drawing::XShape >& rxShape ) throw (uno::RuntimeException); + /** Is called when a new UNO shape has been inserted into the drawing page. */ + virtual void implOnShapeInserted( const uno::Reference< drawing::XShape >& rxShape ) throw (uno::RuntimeException); + +protected: + uno::Reference< XHelperInterface > mxParent; + uno::Reference< uno::XComponentContext > mxContext; + uno::Reference< frame::XModel > mxModel; + uno::Reference< lang::XMultiServiceFactory > mxFactory; + uno::Reference< drawing::XShapes > mxShapes; + +private: + typedef ::std::vector< uno::Reference< drawing::XShape > > ShapeVector; + const uno::Type maVbaType; + ShapeVector maShapes; +}; + +// ---------------------------------------------------------------------------- + +ScVbaObjectContainer::ScVbaObjectContainer( + const uno::Reference< XHelperInterface >& rxParent, + const uno::Reference< uno::XComponentContext >& rxContext, + const uno::Reference< frame::XModel >& rxModel, + const uno::Reference< sheet::XSpreadsheet >& rxSheet, + const uno::Type& rVbaType ) throw (uno::RuntimeException) : + mxParent( rxParent ), + mxContext( rxContext ), + mxModel( rxModel, uno::UNO_SET_THROW ), + mxFactory( rxModel, uno::UNO_QUERY_THROW ), + maVbaType( rVbaType ) +{ + uno::Reference< drawing::XDrawPageSupplier > xDrawPageSupp( rxSheet, uno::UNO_QUERY_THROW ); + mxShapes.set( xDrawPageSupp->getDrawPage(), uno::UNO_QUERY_THROW ); +} + +void ScVbaObjectContainer::collectShapes() throw (uno::RuntimeException) +{ + maShapes.clear(); + for( sal_Int32 nIndex = 0, nCount = mxShapes->getCount(); nIndex < nCount; ++nIndex ) + { + uno::Reference< drawing::XShape > xShape( mxShapes->getByIndex( nIndex ), uno::UNO_QUERY_THROW ); + if( implPickShape( xShape ) ) + maShapes.push_back( xShape ); + } +} + +uno::Reference< drawing::XShape > ScVbaObjectContainer::createShape( const awt::Point& rPos, const awt::Size& rSize ) throw (uno::RuntimeException) +{ + uno::Reference< drawing::XShape > xShape( mxFactory->createInstance( implGetShapeServiceName() ), uno::UNO_QUERY_THROW ); + xShape->setPosition( rPos ); + xShape->setSize( rSize ); + implOnShapeCreated( xShape ); + return xShape; +} + +sal_Int32 ScVbaObjectContainer::insertShape( const uno::Reference< drawing::XShape >& rxShape ) throw (uno::RuntimeException) +{ + mxShapes->add( rxShape ); + maShapes.push_back( rxShape ); + implOnShapeInserted( rxShape ); + return mxShapes->getCount() - 1; +} + +::rtl::Reference< ScVbaSheetObjectBase > ScVbaObjectContainer::createVbaObject( + const uno::Reference< drawing::XShape >& rxShape ) throw (uno::RuntimeException) +{ + return implCreateVbaObject( rxShape ); +} + +uno::Any ScVbaObjectContainer::createCollectionObject( const uno::Any& rSource ) throw (uno::RuntimeException) +{ + uno::Reference< drawing::XShape > xShape( rSource, uno::UNO_QUERY_THROW ); + uno::Reference< excel::XSheetObject > xSheetObject( implCreateVbaObject( xShape ) ); + return uno::Any( xSheetObject ); +} + +uno::Any ScVbaObjectContainer::getItemByStringIndex( const OUString& rIndex ) throw (uno::RuntimeException) +{ + for( ShapeVector::iterator aIt = maShapes.begin(), aEnd = maShapes.end(); aIt != aEnd; ++aIt ) + if( rIndex == implGetShapeName( *aIt ) ) + return createCollectionObject( uno::Any( *aIt ) ); + throw uno::RuntimeException(); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScVbaObjectContainer::getCount() throw (uno::RuntimeException) +{ + return static_cast< sal_Int32 >( maShapes.size() ); +} + +uno::Any SAL_CALL ScVbaObjectContainer::getByIndex( sal_Int32 nIndex ) + throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException) +{ + if( (0 <= nIndex) && (nIndex < getCount()) ) + return uno::Any( maShapes[ static_cast< size_t >( nIndex ) ] ); + throw lang::IndexOutOfBoundsException(); +} + +// XElementAccess + +uno::Type SAL_CALL ScVbaObjectContainer::getElementType() throw (uno::RuntimeException) +{ + return drawing::XShape::static_type( 0 ); +} + +sal_Bool SAL_CALL ScVbaObjectContainer::hasElements() throw (uno::RuntimeException) +{ + return !maShapes.empty(); +} + +// private + +OUString ScVbaObjectContainer::implGetShapeName( const uno::Reference< drawing::XShape >& rxShape ) const throw (uno::RuntimeException) +{ + uno::Reference< beans::XPropertySet > xPropSet( rxShape, uno::UNO_QUERY_THROW ); + return xPropSet->getPropertyValue( CREATE_OUSTRING( "Name" ) ).get< OUString >(); +} + +void ScVbaObjectContainer::implOnShapeCreated( const uno::Reference< drawing::XShape >& /*rxShape*/ ) throw (uno::RuntimeException) +{ +} + +void ScVbaObjectContainer::implOnShapeInserted( const uno::Reference< drawing::XShape >& /*rxShape*/ ) throw (uno::RuntimeException) +{ +} + +// ============================================================================ + +class ScVbaObjectEnumeration : public SimpleEnumerationBase +{ +public: + explicit ScVbaObjectEnumeration( const ScVbaObjectContainerRef& rxContainer ); + virtual uno::Any createCollectionObject( const uno::Any& rSource ); + +private: + ScVbaObjectContainerRef mxContainer; +}; + +// ---------------------------------------------------------------------------- + +ScVbaObjectEnumeration::ScVbaObjectEnumeration( const ScVbaObjectContainerRef& rxContainer ) : + SimpleEnumerationBase( rxContainer->getParent(), rxContainer->getContext(), rxContainer.get() ), + mxContainer( rxContainer ) +{ +} + +uno::Any ScVbaObjectEnumeration::createCollectionObject( const uno::Any& rSource ) +{ + return mxContainer->createCollectionObject( rSource ); +} + +// ============================================================================ + +ScVbaSheetObjectsBase::ScVbaSheetObjectsBase( const ScVbaObjectContainerRef& rxContainer ) throw (css::uno::RuntimeException) : + ScVbaSheetObjects_BASE( rxContainer->getParent(), rxContainer->getContext(), rxContainer.get() ), + mxContainer( rxContainer ) +{ + mxContainer->collectShapes(); +} + +ScVbaSheetObjectsBase::~ScVbaSheetObjectsBase() +{ +} + +void ScVbaSheetObjectsBase::collectShapes() throw (uno::RuntimeException) +{ + mxContainer->collectShapes(); +} + +// XEnumerationAccess + +uno::Reference< container::XEnumeration > SAL_CALL ScVbaSheetObjectsBase::createEnumeration() throw (uno::RuntimeException) +{ + return new ScVbaObjectEnumeration( mxContainer ); +} + +// XElementAccess + +uno::Type SAL_CALL ScVbaSheetObjectsBase::getElementType() throw (uno::RuntimeException) +{ + return mxContainer->getVbaType(); +} + +// ScVbaCollectionBase + +uno::Any ScVbaSheetObjectsBase::createCollectionObject( const uno::Any& rSource ) +{ + return mxContainer->createCollectionObject( rSource ); +} + +uno::Any ScVbaSheetObjectsBase::getItemByStringIndex( const OUString& rIndex ) throw (uno::RuntimeException) +{ + return mxContainer->getItemByStringIndex( rIndex ); +} + +// ============================================================================ +// Graphic object containers supporting ooo.vba.excel.XGraphicObject +// ============================================================================ + +ScVbaGraphicObjectsBase::ScVbaGraphicObjectsBase( const ScVbaObjectContainerRef& rxContainer ) throw (uno::RuntimeException) : + ScVbaGraphicObjects_BASE( rxContainer ) +{ +} + +// XGraphicObjects + +uno::Any SAL_CALL ScVbaGraphicObjectsBase::Add( const uno::Any& rLeft, const uno::Any& rTop, const uno::Any& rWidth, const uno::Any& rHeight ) throw (uno::RuntimeException) +{ + /* Extract double values from passed Anys (the lclPointsToHmm() helper + function will throw a RuntimeException on any error), and convert from + points to 1/100 mm. */ + awt::Point aPos( lclPointsToHmm( rLeft ), lclPointsToHmm( rTop ) ); + awt::Size aSize( lclPointsToHmm( rWidth ), lclPointsToHmm( rHeight ) ); + // TODO: translate coordinates for RTL sheets + if( (aPos.X < 0) || (aPos.Y < 0) || (aSize.Width <= 0) || (aSize.Height <= 0) ) + throw uno::RuntimeException(); + + // create the UNO shape + uno::Reference< drawing::XShape > xShape( mxContainer->createShape( aPos, aSize ), uno::UNO_SET_THROW ); + sal_Int32 nIndex = mxContainer->insertShape( xShape ); + + // create and return the VBA object + ::rtl::Reference< ScVbaSheetObjectBase > xVbaObject = mxContainer->createVbaObject( xShape ); + xVbaObject->setDefaultProperties( nIndex ); + return uno::Any( uno::Reference< excel::XSheetObject >( xVbaObject.get() ) ); +} + +// ============================================================================ +// Drawing controls +// ============================================================================ + +class ScVbaControlContainer : public ScVbaObjectContainer +{ +public: + explicit ScVbaControlContainer( + const uno::Reference< XHelperInterface >& rxParent, + const uno::Reference< uno::XComponentContext >& rxContext, + const uno::Reference< frame::XModel >& rxModel, + const uno::Reference< sheet::XSpreadsheet >& rxSheet, + const uno::Type& rVbaType, + const OUString& rModelServiceName, + sal_Int16 nComponentType ) throw (uno::RuntimeException); + +protected: + uno::Reference< container::XIndexContainer > createForm() throw (uno::RuntimeException); + + virtual bool implPickShape( const uno::Reference< drawing::XShape >& rxShape ) const; + virtual OUString implGetShapeServiceName() const; + virtual bool implCheckProperties( const uno::Reference< beans::XPropertySet >& rxModelProps ) const; + virtual OUString implGetShapeName( const uno::Reference< drawing::XShape >& rxShape ) const throw (uno::RuntimeException); + virtual void implOnShapeCreated( const uno::Reference< drawing::XShape >& rxShape ) throw (uno::RuntimeException); + +protected: + uno::Reference< container::XIndexContainer > mxFormIC; + OUString maModelServiceName; + sal_Int16 mnComponentType; +}; + +// ---------------------------------------------------------------------------- + +ScVbaControlContainer::ScVbaControlContainer( + const uno::Reference< XHelperInterface >& rxParent, + const uno::Reference< uno::XComponentContext >& rxContext, + const uno::Reference< frame::XModel >& rxModel, + const uno::Reference< sheet::XSpreadsheet >& rxSheet, + const uno::Type& rVbaType, + const OUString& rModelServiceName, + sal_Int16 nComponentType ) throw (uno::RuntimeException) : + ScVbaObjectContainer( rxParent, rxContext, rxModel, rxSheet, rVbaType ), + maModelServiceName( rModelServiceName ), + mnComponentType( nComponentType ) +{ +} + +uno::Reference< container::XIndexContainer > ScVbaControlContainer::createForm() throw (uno::RuntimeException) +{ + if( !mxFormIC.is() ) + { + uno::Reference< form::XFormsSupplier > xFormsSupp( mxShapes, uno::UNO_QUERY_THROW ); + uno::Reference< container::XNameContainer > xFormsNC( xFormsSupp->getForms(), uno::UNO_SET_THROW ); + OUString aFormName = CREATE_OUSTRING( "Standard" ); + if( xFormsNC->hasByName( aFormName ) ) + { + mxFormIC.set( xFormsNC->getByName( aFormName ), uno::UNO_QUERY_THROW ); + } + else + { + uno::Reference< form::XForm > xForm( mxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.form.component.Form" ) ), uno::UNO_QUERY_THROW ); + xFormsNC->insertByName( aFormName, uno::Any( xForm ) ); + mxFormIC.set( xForm, uno::UNO_QUERY_THROW ); + } + } + return mxFormIC; +} + +bool ScVbaControlContainer::implPickShape( const uno::Reference< drawing::XShape >& rxShape ) const +{ + try + { + uno::Reference< drawing::XControlShape > xControlShape( rxShape, uno::UNO_QUERY_THROW ); + uno::Reference< beans::XPropertySet > xModelProps( xControlShape->getControl(), uno::UNO_QUERY_THROW ); + sal_Int16 nClassId = -1; + return lclGetProperty( nClassId, xModelProps, CREATE_OUSTRING( "ClassId" ) ) && + (nClassId == mnComponentType) && implCheckProperties( xModelProps ); + } + catch( uno::Exception& ) + { + } + return false; +} + +OUString ScVbaControlContainer::implGetShapeServiceName() const +{ + return CREATE_OUSTRING( "com.sun.star.drawing.ControlShape" ); +} + +bool ScVbaControlContainer::implCheckProperties( const uno::Reference< beans::XPropertySet >& /*rxModelProps*/ ) const +{ + return true; +} + +OUString ScVbaControlContainer::implGetShapeName( const uno::Reference< drawing::XShape >& rxShape ) const throw (uno::RuntimeException) +{ + uno::Reference< drawing::XControlShape > xControlShape( rxShape, uno::UNO_QUERY_THROW ); + return uno::Reference< container::XNamed >( xControlShape->getControl(), uno::UNO_QUERY_THROW )->getName(); +} + +void ScVbaControlContainer::implOnShapeCreated( const uno::Reference< drawing::XShape >& rxShape ) throw (uno::RuntimeException) +{ + // passed shape must be a control shape + uno::Reference< drawing::XControlShape > xControlShape( rxShape, uno::UNO_QUERY_THROW ); + + // create the UNO control model + uno::Reference< form::XFormComponent > xFormComponent( mxFactory->createInstance( maModelServiceName ), uno::UNO_QUERY_THROW ); + uno::Reference< awt::XControlModel > xControlModel( xFormComponent, uno::UNO_QUERY_THROW ); + + // insert the control model into the form and the shape + createForm(); + mxFormIC->insertByIndex( mxFormIC->getCount(), uno::Any( xFormComponent ) ); + xControlShape->setControl( xControlModel ); +} + +// ============================================================================ +// Push button +// ============================================================================ + +class ScVbaButtonContainer : public ScVbaControlContainer +{ +public: + explicit ScVbaButtonContainer( + const uno::Reference< XHelperInterface >& rxParent, + const uno::Reference< uno::XComponentContext >& rxContext, + const uno::Reference< frame::XModel >& rxModel, + const uno::Reference< sheet::XSpreadsheet >& rxSheet ) throw (uno::RuntimeException); + +protected: + virtual ScVbaSheetObjectBase* implCreateVbaObject( const uno::Reference< drawing::XShape >& rxShape ) throw (uno::RuntimeException); + virtual bool implCheckProperties( const uno::Reference< beans::XPropertySet >& rxModelProps ) const; +}; + +// ---------------------------------------------------------------------------- + +ScVbaButtonContainer::ScVbaButtonContainer( + const uno::Reference< XHelperInterface >& rxParent, + const uno::Reference< uno::XComponentContext >& rxContext, + const uno::Reference< frame::XModel >& rxModel, + const uno::Reference< sheet::XSpreadsheet >& rxSheet ) throw (uno::RuntimeException) : + ScVbaControlContainer( + rxParent, rxContext, rxModel, rxSheet, + excel::XButton::static_type( 0 ), + CREATE_OUSTRING( "com.sun.star.form.component.CommandButton" ), + form::FormComponentType::COMMANDBUTTON ) +{ +} + +ScVbaSheetObjectBase* ScVbaButtonContainer::implCreateVbaObject( const uno::Reference< drawing::XShape >& rxShape ) throw (uno::RuntimeException) +{ + uno::Reference< drawing::XControlShape > xControlShape( rxShape, uno::UNO_QUERY_THROW ); + return new ScVbaButton( mxParent, mxContext, mxModel, createForm(), xControlShape ); +} + +bool ScVbaButtonContainer::implCheckProperties( const uno::Reference< beans::XPropertySet >& rxModelProps ) const +{ + // do not insert toggle buttons into the 'Buttons' collection + bool bToggle = false; + return lclGetProperty( bToggle, rxModelProps, CREATE_OUSTRING( "Toggle" ) ) && !bToggle; +} + +// ============================================================================ + +ScVbaButtons::ScVbaButtons( + const uno::Reference< XHelperInterface >& rxParent, + const uno::Reference< uno::XComponentContext >& rxContext, + const uno::Reference< frame::XModel >& rxModel, + const uno::Reference< sheet::XSpreadsheet >& rxSheet ) throw (uno::RuntimeException) : + ScVbaGraphicObjectsBase( new ScVbaButtonContainer( rxParent, rxContext, rxModel, rxSheet ) ) +{ +} + +VBAHELPER_IMPL_XHELPERINTERFACE( ScVbaButtons, "ooo.vba.excel.Buttons" ) + +// ============================================================================ diff --git a/sc/source/ui/vba/vbasheetobjects.hxx b/sc/source/ui/vba/vbasheetobjects.hxx new file mode 100755 index 000000000000..fd69d4927a20 --- /dev/null +++ b/sc/source/ui/vba/vbasheetobjects.hxx @@ -0,0 +1,113 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef SC_VBA_SHEETOBJECTS_HXX +#define SC_VBA_SHEETOBJECTS_HXX + +#include <ooo/vba/excel/XGraphicObjects.hpp> +#include <vbahelper/vbacollectionimpl.hxx> +#include <rtl/ref.hxx> + +namespace com { namespace sun { namespace star { + namespace container { class XEnumeration; } + namespace frame { class XModel; } + namespace sheet { class XSpreadsheet; } +} } } + +// ============================================================================ + +class ScVbaObjectContainer; +typedef ::rtl::Reference< ScVbaObjectContainer > ScVbaObjectContainerRef; + +// ============================================================================ + +typedef CollTestImplHelper< ov::XCollection > ScVbaSheetObjects_BASE; + +/** Base class for collections containing a specific type of drawing object + embedded in a sheet (worksheet, chart sheet, or dialog sheet). + */ +class ScVbaSheetObjectsBase : public ScVbaSheetObjects_BASE +{ +public: + explicit ScVbaSheetObjectsBase( const ScVbaObjectContainerRef& rxContainer ) throw (css::uno::RuntimeException); + virtual ~ScVbaSheetObjectsBase(); + + /** Updates the collection by fetching all shapes from the draw page. */ + void collectShapes() throw (css::uno::RuntimeException); + + // XEnumerationAccess + virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createEnumeration() throw (css::uno::RuntimeException); + + // XElementAccess + virtual css::uno::Type SAL_CALL getElementType() throw (css::uno::RuntimeException); + + // ScVbaCollectionBase + virtual css::uno::Any createCollectionObject( const css::uno::Any& rSource ); + virtual css::uno::Any getItemByStringIndex( const ::rtl::OUString& rIndex ) throw (css::uno::RuntimeException); + +protected: + ScVbaObjectContainerRef mxContainer; +}; + +// ============================================================================ + +typedef ::cppu::ImplInheritanceHelper1< ScVbaSheetObjectsBase, ov::excel::XGraphicObjects > ScVbaGraphicObjects_BASE; + +/** Base class for collections containing a specific type of graphic object + from a sheet. + */ +class ScVbaGraphicObjectsBase : public ScVbaGraphicObjects_BASE +{ +public: + explicit ScVbaGraphicObjectsBase( const ScVbaObjectContainerRef& rxContainer ) throw (css::uno::RuntimeException); + + // XGraphicObjects + virtual css::uno::Any SAL_CALL Add( + const css::uno::Any& rLeft, + const css::uno::Any& rTop, + const css::uno::Any& rWidth, + const css::uno::Any& rHeight ) throw (css::uno::RuntimeException); +}; + +// ============================================================================ + +/** Collection containing all button controls from a sheet (not ActiveX controls). */ +class ScVbaButtons : public ScVbaGraphicObjectsBase +{ +public: + explicit ScVbaButtons( + const css::uno::Reference< ov::XHelperInterface >& rxParent, + const css::uno::Reference< css::uno::XComponentContext >& rxContext, + const css::uno::Reference< css::frame::XModel >& rxModel, + const css::uno::Reference< css::sheet::XSpreadsheet >& rxSheet ) throw (css::uno::RuntimeException); + + VBAHELPER_DECL_XHELPERINTERFACE +}; + +// ============================================================================ + +#endif diff --git a/sc/source/ui/vba/vbawindow.cxx b/sc/source/ui/vba/vbawindow.cxx index f0aafe83908b..10dad39341b7 100644 --- a/sc/source/ui/vba/vbawindow.cxx +++ b/sc/source/ui/vba/vbawindow.cxx @@ -55,9 +55,6 @@ using namespace ::com::sun::star; using namespace ::ooo::vba; using namespace ::ooo::vba::excel::XlWindowState; -// nameExists defined in vbaworksheet.cxx -bool nameExists( uno::Reference <sheet::XSpreadsheetDocument>& xSpreadDoc, ::rtl::OUString & name, SCTAB& nTab ) throw ( lang::IllegalArgumentException ); - typedef std::hash_map< rtl::OUString, SCTAB, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > NameIndexHash; @@ -213,18 +210,25 @@ ScVbaWindow::ScVbaWindow( uno::Sequence< uno::Any > const & args, uno::Reference { init(); } + void ScVbaWindow::init() { + /* This method is called from the constructor, thus the own refcount is + still zero. The implementation of ActivePane() uses a UNO reference of + this (to set this window as parent of the pane obejct). This requires + the own refcount to be non-zero, otherwise this instance will be + desctructed immediately! */ + osl_incrementInterlockedCount( &m_refCount ); uno::Reference< frame::XController > xController( m_xModel->getCurrentController(), uno::UNO_QUERY_THROW ); m_xViewPane.set( xController, uno::UNO_QUERY_THROW ); m_xViewFreezable.set( xController, uno::UNO_QUERY_THROW ); m_xViewSplitable.set( xController, uno::UNO_QUERY_THROW ); m_xPane.set( ActivePane(), uno::UNO_QUERY_THROW ); m_xDevice.set( xController->getFrame()->getComponentWindow(), uno::UNO_QUERY_THROW ); + osl_decrementInterlockedCount( &m_refCount ); } - void ScVbaWindow::Scroll( const uno::Any& Down, const uno::Any& Up, const uno::Any& ToRight, const uno::Any& ToLeft, bool bLargeScroll ) throw (uno::RuntimeException) { @@ -233,11 +237,13 @@ ScVbaWindow::Scroll( const uno::Any& Down, const uno::Any& Up, const uno::Any& T else m_xPane->SmallScroll( Down, Up, ToRight, ToLeft ); } + void SAL_CALL ScVbaWindow::SmallScroll( const uno::Any& Down, const uno::Any& Up, const uno::Any& ToRight, const uno::Any& ToLeft ) throw (uno::RuntimeException) { Scroll( Down, Up, ToRight, ToLeft ); } + void SAL_CALL ScVbaWindow::LargeScroll( const uno::Any& Down, const uno::Any& Up, const uno::Any& ToRight, const uno::Any& ToLeft ) throw (uno::RuntimeException) { @@ -450,7 +456,7 @@ ScVbaWindow::Close( const uno::Any& SaveChanges, const uno::Any& FileName, const uno::Reference< excel::XPane > SAL_CALL ScVbaWindow::ActivePane() throw (script::BasicErrorException, uno::RuntimeException) { - return new ScVbaPane( mxContext, m_xViewPane ); + return new ScVbaPane( this, mxContext, m_xModel, m_xViewPane ); } uno::Reference< excel::XRange > SAL_CALL @@ -467,6 +473,14 @@ ScVbaWindow::Selection( ) throw (script::BasicErrorException, uno::RuntimeExcep return xApplication->getSelection(); } +uno::Reference< excel::XRange > SAL_CALL +ScVbaWindow::RangeSelection() throw (script::BasicErrorException, uno::RuntimeException) +{ + /* TODO / FIXME: According to documentation, this method returns the range + selection even if shapes are selected. */ + return uno::Reference< excel::XRange >( Selection(), uno::UNO_QUERY_THROW ); +} + ::sal_Bool SAL_CALL ScVbaWindow::getDisplayGridlines() throw (uno::RuntimeException) { @@ -732,9 +746,7 @@ ScVbaWindow::setZoom( const uno::Any& _zoom ) throw (uno::RuntimeException) uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( m_xModel, uno::UNO_QUERY_THROW ); uno::Reference< excel::XWorksheet > xActiveSheet = ActiveSheet(); SCTAB nTab = 0; - rtl::OUString sName = xActiveSheet->getName(); - bool bSheetExists = nameExists (xSpreadDoc, sName, nTab); - if ( !bSheetExists ) + if ( !ScVbaWorksheets::nameExists (xSpreadDoc, xActiveSheet->getName(), nTab) ) throw uno::RuntimeException(); std::vector< SCTAB > vTabs; vTabs.push_back( nTab ); @@ -778,6 +790,15 @@ ScVbaWindow::setView( const uno::Any& _view) throw (uno::RuntimeException) dispatchExecute( pViewShell, nSlot ); } +uno::Reference< excel::XRange > SAL_CALL +ScVbaWindow::getVisibleRange() throw (uno::RuntimeException) +{ + uno::Reference< container::XIndexAccess > xPanesIA( m_xViewPane, uno::UNO_QUERY_THROW ); + uno::Reference< sheet::XViewPane > xTopLeftPane( xPanesIA->getByIndex( 0 ), uno::UNO_QUERY_THROW ); + uno::Reference< excel::XPane > xPane( new ScVbaPane( this, mxContext, m_xModel, xTopLeftPane ) ); + return xPane->getVisibleRange(); +} + sal_Int32 SAL_CALL ScVbaWindow::PointsToScreenPixelsX(sal_Int32 _points) throw (css::script::BasicErrorException, css::uno::RuntimeException) { diff --git a/sc/source/ui/vba/vbawindow.hxx b/sc/source/ui/vba/vbawindow.hxx index e72401a2baac..d58d2a07cb4b 100644 --- a/sc/source/ui/vba/vbawindow.hxx +++ b/sc/source/ui/vba/vbawindow.hxx @@ -26,6 +26,7 @@ ************************************************************************/ #ifndef SC_VBA_WINDOW_HXX #define SC_VBA_WINDOW_HXX + #include <cppuhelper/implbase1.hxx> #include <ooo/vba/excel/XWindow.hpp> #include <com/sun/star/uno/XComponentContext.hpp> @@ -40,7 +41,6 @@ #include <vbahelper/vbawindowbase.hxx> #include "vbaworkbook.hxx" -//typedef InheritedHelperInterfaceImpl1<ov::excel::XWindow > WindowImpl_BASE; typedef cppu::ImplInheritanceHelper1< VbaWindowBase, ov::excel::XWindow > WindowImpl_BASE; class ScVbaWindow : public WindowImpl_BASE @@ -96,6 +96,7 @@ public: virtual void SAL_CALL setScrollColumn( const css::uno::Any& _scrollcolumn ) throw (css::uno::RuntimeException) ; virtual css::uno::Any SAL_CALL getView() throw (css::uno::RuntimeException); virtual void SAL_CALL setView( const css::uno::Any& _view ) throw (css::uno::RuntimeException); + virtual css::uno::Reference< ov::excel::XRange > SAL_CALL getVisibleRange() throw (css::uno::RuntimeException); virtual css::uno::Any SAL_CALL getWindowState() throw (css::uno::RuntimeException); virtual void SAL_CALL setWindowState( const css::uno::Any& _windowstate ) throw (css::uno::RuntimeException); virtual css::uno::Any SAL_CALL getZoom() throw (css::uno::RuntimeException); @@ -108,11 +109,12 @@ public: virtual void SAL_CALL ScrollWorkbookTabs( const css::uno::Any& Sheets, const css::uno::Any& Position ) throw (css::uno::RuntimeException); virtual void SAL_CALL Activate( ) throw (css::uno::RuntimeException); virtual void SAL_CALL Close( const css::uno::Any& SaveChanges, const css::uno::Any& FileName, const css::uno::Any& RouteWorkBook ) throw (css::uno::RuntimeException); - virtual css::uno::Any SAL_CALL Selection( ) throw (css::script::BasicErrorException, css::uno::RuntimeException); - virtual sal_Int32 SAL_CALL PointsToScreenPixelsX(sal_Int32 _points) throw (css::script::BasicErrorException, css::uno::RuntimeException); - virtual sal_Int32 SAL_CALL PointsToScreenPixelsY(sal_Int32 _points) throw (css::script::BasicErrorException, css::uno::RuntimeException); - virtual void SAL_CALL PrintOut( const css::uno::Any& From, const css::uno::Any&To, const css::uno::Any& Copies, const css::uno::Any& Preview, const css::uno::Any& ActivePrinter, const css::uno::Any& PrintToFile, const css::uno::Any& Collate, const css::uno::Any& PrToFileName ) throw (css::script::BasicErrorException, css::uno::RuntimeException); - virtual void SAL_CALL PrintPreview( const css::uno::Any& EnableChanges ) throw (css::script::BasicErrorException, css::uno::RuntimeException); + virtual css::uno::Any SAL_CALL Selection( ) throw (css::script::BasicErrorException, css::uno::RuntimeException); + virtual css::uno::Reference< ov::excel::XRange > SAL_CALL RangeSelection() throw (css::script::BasicErrorException, css::uno::RuntimeException); + virtual sal_Int32 SAL_CALL PointsToScreenPixelsX(sal_Int32 _points) throw (css::script::BasicErrorException, css::uno::RuntimeException); + virtual sal_Int32 SAL_CALL PointsToScreenPixelsY(sal_Int32 _points) throw (css::script::BasicErrorException, css::uno::RuntimeException); + virtual void SAL_CALL PrintOut( const css::uno::Any& From, const css::uno::Any&To, const css::uno::Any& Copies, const css::uno::Any& Preview, const css::uno::Any& ActivePrinter, const css::uno::Any& PrintToFile, const css::uno::Any& Collate, const css::uno::Any& PrToFileName ) throw (css::script::BasicErrorException, css::uno::RuntimeException); + virtual void SAL_CALL PrintPreview( const css::uno::Any& EnableChanges ) throw (css::script::BasicErrorException, css::uno::RuntimeException); // XHelperInterface virtual rtl::OUString& getServiceImplName(); virtual css::uno::Sequence<rtl::OUString> getServiceNames(); diff --git a/sc/source/ui/vba/vbaworkbook.cxx b/sc/source/ui/vba/vbaworkbook.cxx index 6694f4e5e135..365c8b35a00c 100644 --- a/sc/source/ui/vba/vbaworkbook.cxx +++ b/sc/source/ui/vba/vbaworkbook.cxx @@ -345,32 +345,8 @@ ScVbaWorkbook::getServiceNames() ::rtl::OUString SAL_CALL ScVbaWorkbook::getCodeName() throw (css::uno::RuntimeException) { -#ifdef VBA_OOBUILD_HACK - uno::Reference< frame::XModel > xModel( getModel(), uno::UNO_QUERY_THROW ); - ScDocument* pDoc = excel::getDocShell( xModel )->GetDocument(); - ScExtDocOptions* pExtOptions = pDoc->GetExtDocOptions(); - ScExtDocSettings pExtSettings = pExtOptions->GetDocSettings(); - ::rtl::OUString sGlobCodeName = pExtSettings.maGlobCodeName; - return sGlobCodeName; -#else - throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Not implemented") ), uno::Reference< uno::XInterface >() ); -#endif -} -#ifdef VBA_OOBUILD_HACK -void SAL_CALL -ScVbaWorkbook::setCodeName( const ::rtl::OUString& sGlobCodeName ) throw (css::uno::RuntimeException) -{ - uno::Reference< frame::XModel > xModel( getModel(), uno::UNO_QUERY_THROW ); - ScDocument* pDoc = excel::getDocShell( xModel )->GetDocument(); - ScExtDocOptions* pExtOptions = pDoc->GetExtDocOptions(); - ScExtDocSettings pExtSettings = pExtOptions->GetDocSettings(); - pExtSettings.maGlobCodeName = sGlobCodeName; -#else -void SAL_CALL -ScVbaWorkbook::setCodeName( const ::rtl::OUString& ) throw (css::uno::RuntimeException) -{ - throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Not implemented") ), uno::Reference< uno::XInterface >() ); -#endif + uno::Reference< beans::XPropertySet > xModelProp( getModel(), uno::UNO_QUERY_THROW ); + return xModelProp->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CodeName" ) ) ).get< ::rtl::OUString >(); } namespace workbook diff --git a/sc/source/ui/vba/vbaworkbook.hxx b/sc/source/ui/vba/vbaworkbook.hxx index 40234aca21d7..4aff58078403 100644 --- a/sc/source/ui/vba/vbaworkbook.hxx +++ b/sc/source/ui/vba/vbaworkbook.hxx @@ -71,7 +71,6 @@ public: virtual void SAL_CALL SaveCopyAs( const rtl::OUString& Filename ) throw ( css::uno::RuntimeException); // code name virtual ::rtl::OUString SAL_CALL getCodeName() throw ( css::uno::RuntimeException); - virtual void SAL_CALL setCodeName( const ::rtl::OUString& sGlobCodeName ) throw (css::uno::RuntimeException); // XHelperInterface virtual rtl::OUString& getServiceImplName(); diff --git a/sc/source/ui/vba/vbaworksheet.cxx b/sc/source/ui/vba/vbaworksheet.cxx index be988509aa68..5b1963e3d242 100644 --- a/sc/source/ui/vba/vbaworksheet.cxx +++ b/sc/source/ui/vba/vbaworksheet.cxx @@ -24,9 +24,12 @@ * for a copy of the LGPLv3 License. * ************************************************************************/ + #include <vbahelper/helperdecl.hxx> #include <cppuhelper/queryinterface.hxx> +#include "vbaworksheet.hxx" + #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/beans/XIntrospectionAccess.hpp> #include <com/sun/star/beans/XIntrospection.hpp> @@ -60,14 +63,15 @@ #include <ooo/vba/XControlProvider.hpp> #include <comphelper/processfactory.hxx> +#include <vbahelper/vbashapes.hxx> #include <tools/string.hxx> //zhangyun showdataform #include <sfx2/sfxdlg.hxx> -#include <scabstdlg.hxx> -#include <tabvwsh.hxx> -#include <scitems.hxx> +#include "scabstdlg.hxx" +#include "tabvwsh.hxx" +#include "scitems.hxx" #include <svx/svdouno.hxx> #include <svx/svdpage.hxx> @@ -79,43 +83,22 @@ #include "vbaoutline.hxx" #include "vbarange.hxx" #include "vbacomments.hxx" -#include "vbaworksheet.hxx" #include "vbachartobjects.hxx" #include "vbapivottables.hxx" #include "vbaoleobject.hxx" #include "vbaoleobjects.hxx" -#include <vbahelper/vbashapes.hxx> #include "vbapagesetup.hxx" #include "vbapagebreaks.hxx" +#include "vbaworksheets.hxx" +#include "vbahyperlinks.hxx" +#include "vbasheetobjects.hxx" #define STANDARDWIDTH 2267 #define STANDARDHEIGHT 427 #define DOESNOTEXIST -1 + using namespace com::sun::star; using namespace ooo::vba; -bool -nameExists( uno::Reference <sheet::XSpreadsheetDocument>& xSpreadDoc, ::rtl::OUString & name, SCTAB& nTab ) throw ( lang::IllegalArgumentException ) -{ - if (!xSpreadDoc.is()) - throw lang::IllegalArgumentException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nameExists() xSpreadDoc is null" ) ), uno::Reference< uno::XInterface >(), 1 ); - uno::Reference <sheet::XSpreadsheets> xSheets = xSpreadDoc->getSheets(); - uno::Reference <container::XIndexAccess> xIndex( xSheets, uno::UNO_QUERY ); - if ( xIndex.is() ) - { - SCTAB nCount = static_cast< SCTAB >( xIndex->getCount() ); - for (SCTAB i=0; i < nCount; i++) - { - uno::Reference< sheet::XSpreadsheet > xSheet(xIndex->getByIndex(i), uno::UNO_QUERY); - uno::Reference< container::XNamed > xNamed( xSheet, uno::UNO_QUERY_THROW ); - if (xNamed->getName() == name) - { - nTab = i; - return true; - } - } - } - return false; -} static void getNewSpreadsheetName (rtl::OUString &aNewName, rtl::OUString aOldName, uno::Reference <sheet::XSpreadsheetDocument>& xSpreadDoc ) { @@ -125,7 +108,7 @@ static void getNewSpreadsheetName (rtl::OUString &aNewName, rtl::OUString aOldNa int currentNum =2; aNewName = aOldName + aUnderScre+ String::CreateFromInt32(currentNum) ; SCTAB nTab = 0; - while ( nameExists(xSpreadDoc,aNewName, nTab ) ) + while ( ScVbaWorksheets::nameExists(xSpreadDoc,aNewName, nTab ) ) { aNewName = aOldName + aUnderScre + String::CreateFromInt32(++currentNum) ; @@ -152,7 +135,8 @@ static void removeAllSheets( uno::Reference <sheet::XSpreadsheetDocument>& xSpre } } - uno::Reference< sheet::XSpreadsheet > xSheet(xIndex->getByIndex(0), uno::UNO_QUERY); uno::Reference< container::XNamed > xNamed( xSheet, uno::UNO_QUERY_THROW ); + uno::Reference< sheet::XSpreadsheet > xSheet(xIndex->getByIndex(0), uno::UNO_QUERY); + uno::Reference< container::XNamed > xNamed( xSheet, uno::UNO_QUERY_THROW ); if (xNamed.is()) { xNamed->setName(aSheetName); @@ -196,6 +180,7 @@ openNewDoc(rtl::OUString aSheetName ) ScVbaWorksheet::ScVbaWorksheet( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext ) : WorksheetImpl_BASE( xParent, xContext ) { } + ScVbaWorksheet::ScVbaWorksheet(const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< sheet::XSpreadsheet >& xSheet, const uno::Reference< frame::XModel >& xModel ) throw (uno::RuntimeException) : WorksheetImpl_BASE( xParent, xContext ), mxSheet( xSheet ), mxModel(xModel) @@ -216,6 +201,10 @@ ScVbaWorksheet::ScVbaWorksheet( uno::Sequence< uno::Any> const & args, mxSheet.set( xNameAccess->getByName( sSheetName ), uno::UNO_QUERY_THROW ); } +ScVbaWorksheet::~ScVbaWorksheet() +{ +} + ::rtl::OUString ScVbaWorksheet::getName() throw (uno::RuntimeException) { @@ -261,9 +250,7 @@ ScVbaWorksheet::getEnableSelection() throw (uno::RuntimeException) { uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( getModel(), uno::UNO_QUERY_THROW ); SCTAB nTab = 0; - rtl::OUString aSheetName = getName(); - bool bSheetExists = nameExists (xSpreadDoc, aSheetName, nTab); - if ( bSheetExists ) + if ( ScVbaWorksheets::nameExists(xSpreadDoc, getName(), nTab) ) { uno::Reference< frame::XModel > xModel( getModel(), uno::UNO_QUERY_THROW ); ScDocument* pDoc = excel::getDocShell( xModel )->GetDocument(); @@ -301,9 +288,7 @@ ScVbaWorksheet::setEnableSelection( sal_Int32 nSelection ) throw (uno::RuntimeEx uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( getModel(), uno::UNO_QUERY_THROW ); SCTAB nTab = 0; - rtl::OUString aSheetName = getName(); - bool bSheetExists = nameExists (xSpreadDoc, aSheetName, nTab); - if ( bSheetExists ) + if ( ScVbaWorksheets::nameExists(xSpreadDoc, getName(), nTab) ) { uno::Reference< frame::XModel > xModel( getModel(), uno::UNO_QUERY_THROW ); ScDocument* pDoc = excel::getDocShell( xModel )->GetDocument(); @@ -426,9 +411,8 @@ ScVbaWorksheet::Select() throw (uno::RuntimeException) void ScVbaWorksheet::Move( const uno::Any& Before, const uno::Any& After ) throw (uno::RuntimeException) { - rtl::OUString aSheetName; uno::Reference<excel::XWorksheet> xSheet; - rtl::OUString aCurrSheetName =getName(); + rtl::OUString aCurrSheetName = getName(); if (!(Before >>= xSheet) && !(After >>=xSheet)&& !(Before.hasValue()) && !(After.hasValue())) { @@ -451,9 +435,7 @@ ScVbaWorksheet::Move( const uno::Any& Before, const uno::Any& After ) throw (uno uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( getModel(), uno::UNO_QUERY_THROW ); SCTAB nDest = 0; - aSheetName = xSheet->getName(); - bool bSheetExists = nameExists (xSpreadDoc, aSheetName, nDest); - if ( bSheetExists ) + if ( ScVbaWorksheets::nameExists (xSpreadDoc, xSheet->getName(), nDest) ) { sal_Bool bAfter = After.hasValue(); if (bAfter) @@ -466,7 +448,6 @@ ScVbaWorksheet::Move( const uno::Any& Before, const uno::Any& After ) throw (uno void ScVbaWorksheet::Copy( const uno::Any& Before, const uno::Any& After ) throw (uno::RuntimeException) { - rtl::OUString aSheetName; uno::Reference<excel::XWorksheet> xSheet; rtl::OUString aCurrSheetName =getName(); if (!(Before >>= xSheet) && !(After >>=xSheet)&& !(Before.hasValue()) && !(After.hasValue())) @@ -488,10 +469,8 @@ ScVbaWorksheet::Copy( const uno::Any& Before, const uno::Any& After ) throw (uno uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( getModel(), uno::UNO_QUERY ); SCTAB nDest = 0; - aSheetName = xSheet->getName(); - bool bSheetExists = nameExists (xSpreadDoc, aSheetName, nDest ); - - if ( bSheetExists ) + rtl::OUString aSheetName = xSheet->getName(); + if ( ScVbaWorksheets::nameExists (xSpreadDoc, aSheetName, nDest ) ) { sal_Bool bAfter = After.hasValue(); if(bAfter) @@ -521,7 +500,7 @@ ScVbaWorksheet::Delete() throw (uno::RuntimeException) if ( xSpreadDoc.is() ) { SCTAB nTab = 0; - if (!nameExists(xSpreadDoc, aSheetName, nTab )) + if (!ScVbaWorksheets::nameExists(xSpreadDoc, aSheetName, nTab )) { return; } @@ -539,11 +518,8 @@ ScVbaWorksheet::getSheetAtOffset(SCTAB offset) throw (uno::RuntimeException) uno::Reference <sheet::XSpreadsheets> xSheets( xSpreadDoc->getSheets(), uno::UNO_QUERY_THROW ); uno::Reference <container::XIndexAccess> xIndex( xSheets, uno::UNO_QUERY_THROW ); - rtl::OUString aName = getName(); SCTAB nIdx = 0; - bool bSheetExists = nameExists (xSpreadDoc, aName, nIdx ); - - if ( !bSheetExists ) + 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); @@ -677,13 +653,25 @@ ScVbaWorksheet::Comments( const uno::Any& Index ) throw (uno::RuntimeException) uno::Reference< sheet::XSheetAnnotationsSupplier > xAnnosSupp( xSheet, uno::UNO_QUERY_THROW ); uno::Reference< sheet::XSheetAnnotations > xAnnos( xAnnosSupp->getAnnotations(), uno::UNO_QUERY_THROW ); uno::Reference< container::XIndexAccess > xIndexAccess( xAnnos, uno::UNO_QUERY_THROW ); - uno::Reference< XCollection > xColl( new ScVbaComments( this, mxContext, xIndexAccess ) ); + uno::Reference< XCollection > xColl( new ScVbaComments( this, mxContext, mxModel, xIndexAccess ) ); if ( Index.hasValue() ) return xColl->Item( Index, uno::Any() ); return uno::makeAny( xColl ); } uno::Any SAL_CALL +ScVbaWorksheet::Hyperlinks( const uno::Any& aIndex ) throw (uno::RuntimeException) +{ + /* 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::OLEObjects( const uno::Any& Index ) throw (uno::RuntimeException) { ScVbaOLEObjects* aOleObjects; @@ -716,6 +704,66 @@ ScVbaWorksheet::Shapes( const uno::Any& aIndex ) throw (uno::RuntimeException) return uno::makeAny( xVbaShapes ); } +uno::Any SAL_CALL +ScVbaWorksheet::Buttons( const uno::Any& rIndex ) throw (uno::RuntimeException) +{ + if( !mxButtons.is() ) + mxButtons.set( new ScVbaButtons( this, mxContext, mxModel, mxSheet ) ); + else + mxButtons->collectShapes(); + if( rIndex.hasValue() ) + return mxButtons->Item( rIndex, uno::Any() ); + return uno::Any( uno::Reference< XCollection >( mxButtons.get() ) ); +} + +uno::Any SAL_CALL +ScVbaWorksheet::CheckBoxes( const uno::Any& /*rIndex*/ ) throw (uno::RuntimeException) +{ + throw uno::RuntimeException(); +} + +uno::Any SAL_CALL +ScVbaWorksheet::DropDowns( const uno::Any& /*rIndex*/ ) throw (uno::RuntimeException) +{ + throw uno::RuntimeException(); +} + +uno::Any SAL_CALL +ScVbaWorksheet::GroupBoxes( const uno::Any& /*rIndex*/ ) throw (uno::RuntimeException) +{ + throw uno::RuntimeException(); +} + +uno::Any SAL_CALL +ScVbaWorksheet::Labels( const uno::Any& /*rIndex*/ ) throw (uno::RuntimeException) +{ + throw uno::RuntimeException(); +} + +uno::Any SAL_CALL +ScVbaWorksheet::ListBoxes( const uno::Any& /*rIndex*/ ) throw (uno::RuntimeException) +{ + throw uno::RuntimeException(); +} + +uno::Any SAL_CALL +ScVbaWorksheet::OptionButtons( const uno::Any& /*rIndex*/ ) throw (uno::RuntimeException) +{ + throw uno::RuntimeException(); +} + +uno::Any SAL_CALL +ScVbaWorksheet::ScrollBars( const uno::Any& /*rIndex*/ ) throw (uno::RuntimeException) +{ + throw uno::RuntimeException(); +} + +uno::Any SAL_CALL +ScVbaWorksheet::Spinners( const uno::Any& /*rIndex*/ ) throw (uno::RuntimeException) +{ + throw uno::RuntimeException(); +} + void SAL_CALL ScVbaWorksheet::ShowDataForm( ) throw (uno::RuntimeException) { @@ -882,52 +930,8 @@ ScVbaWorksheet::getServiceNames() rtl::OUString SAL_CALL ScVbaWorksheet::getCodeName() throw (css::uno::RuntimeException) { -#ifdef VBA_OOBUILD_HACK - uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( getModel(), uno::UNO_QUERY_THROW ); - SCTAB nTab = 0; - rtl::OUString aSheetName = getName(); - bool bSheetExists = nameExists (xSpreadDoc, aSheetName, nTab); - if ( bSheetExists ) - { - uno::Reference< frame::XModel > xModel( getModel(), uno::UNO_QUERY_THROW ); - ScDocument* pDoc = getDocShell( xModel )->GetDocument(); - ScExtDocOptions* pExtOptions = pDoc->GetExtDocOptions(); - rtl::OUString sCodeName = pExtOptions->GetCodeName( nTab ); - return sCodeName; - } - else - throw uno::RuntimeException(::rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( "Sheet Name does not exist. ") ), - uno::Reference< XInterface >() ); -#else - throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Not implemented") ), uno::Reference< uno::XInterface >() ); -#endif -} -#ifdef VBA_OOBUILD_HACK -void SAL_CALL -ScVbaWorksheet::setCodeName( const rtl::OUString& sCodeName ) throw (css::uno::RuntimeException) -{ - uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( getModel(), uno::UNO_QUERY_THROW ); - SCTAB nTab = 0; - rtl::OUString aSheetName = getName(); - bool bSheetExists = nameExists (xSpreadDoc, aSheetName, nTab); - if ( bSheetExists ) - { - uno::Reference< frame::XModel > xModel( getModel(), uno::UNO_QUERY_THROW ); - ScDocument* pDoc = getDocShell( xModel )->GetDocument(); - ScExtDocOptions* pExtOptions = pDoc->GetExtDocOptions(); - pExtOptions->SetCodeName( sCodeName, nTab ); - } - else - throw uno::RuntimeException(::rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( "Sheet Name does not exist. ") ), - uno::Reference< XInterface >() ); -#else -void SAL_CALL -ScVbaWorksheet::setCodeName( const rtl::OUString& ) throw (css::uno::RuntimeException) -{ - throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Not implemented") ), uno::Reference< uno::XInterface >() ); -#endif + uno::Reference< beans::XPropertySet > xSheetProp( mxSheet, uno::UNO_QUERY_THROW ); + return xSheetProp->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CodeName" ) ) ).get< ::rtl::OUString >(); } sal_Int16 diff --git a/sc/source/ui/vba/vbaworksheet.hxx b/sc/source/ui/vba/vbaworksheet.hxx index 5fe1343f9237..d07cc1a8d55c 100644 --- a/sc/source/ui/vba/vbaworksheet.hxx +++ b/sc/source/ui/vba/vbaworksheet.hxx @@ -42,11 +42,17 @@ #include <ooo/vba/excel/XPageSetup.hpp> #include <ooo/vba/excel/XHPageBreaks.hpp> #include <ooo/vba/excel/XVPageBreaks.hpp> -#include <ooo/vba/excel/XChartObjects.hpp> #include <vbahelper/vbahelperinterface.hxx> #include "address.hxx" +namespace ooo { namespace vba { namespace excel { + class XChartObjects; + class XHyperlinks; +} } } + +class ScVbaSheetObjectsBase; + typedef InheritedHelperInterfaceImpl1< ov::excel::XWorksheet > WorksheetImpl_BASE; class ScVbaWorksheet : public WorksheetImpl_BASE @@ -54,6 +60,8 @@ class ScVbaWorksheet : public WorksheetImpl_BASE css::uno::Reference< css::sheet::XSpreadsheet > mxSheet; css::uno::Reference< css::frame::XModel > mxModel; css::uno::Reference< ov::excel::XChartObjects > mxCharts; + css::uno::Reference< ov::excel::XHyperlinks > mxHlinks; + ::rtl::Reference< ScVbaSheetObjectsBase > mxButtons; css::uno::Reference< ov::excel::XWorksheet > getSheetAtOffset(SCTAB offset) throw (css::uno::RuntimeException); css::uno::Reference< ov::excel::XRange > getSheetRange() throw (css::uno::RuntimeException); @@ -70,7 +78,7 @@ public: const css::uno::Reference< css::frame::XModel >& xModel )throw (css::uno::RuntimeException) ; ScVbaWorksheet( css::uno::Sequence< css::uno::Any > const& aArgs, css::uno::Reference< css::uno::XComponentContext >const& xContext ) throw ( css::lang::IllegalArgumentException ); - virtual ~ScVbaWorksheet() {} + virtual ~ScVbaWorksheet(); virtual css::uno::Reference< css::frame::XModel > getModel() { return mxModel; } @@ -120,9 +128,21 @@ public: virtual css::uno::Any SAL_CALL Evaluate( const ::rtl::OUString& Name ) throw (css::uno::RuntimeException); virtual css::uno::Any SAL_CALL PivotTables( const css::uno::Any& Index ) throw (css::uno::RuntimeException); virtual css::uno::Any SAL_CALL Comments( const css::uno::Any& Index ) throw (css::uno::RuntimeException); + virtual css::uno::Any SAL_CALL Hyperlinks( const css::uno::Any& aIndex ) throw (css::uno::RuntimeException); virtual css::uno::Any SAL_CALL OLEObjects( const css::uno::Any& Index ) throw (css::uno::RuntimeException); virtual css::uno::Any SAL_CALL Shapes( const css::uno::Any& aIndex ) throw (css::uno::RuntimeException); + + virtual css::uno::Any SAL_CALL Buttons( const css::uno::Any& rIndex ) throw (css::uno::RuntimeException); + virtual css::uno::Any SAL_CALL CheckBoxes( const css::uno::Any& rIndex ) throw (css::uno::RuntimeException); + virtual css::uno::Any SAL_CALL DropDowns( const css::uno::Any& rIndex ) throw (css::uno::RuntimeException); + virtual css::uno::Any SAL_CALL GroupBoxes( const css::uno::Any& rIndex ) throw (css::uno::RuntimeException); + virtual css::uno::Any SAL_CALL Labels( const css::uno::Any& rIndex ) throw (css::uno::RuntimeException); + virtual css::uno::Any SAL_CALL ListBoxes( const css::uno::Any& rIndex ) throw (css::uno::RuntimeException); + virtual css::uno::Any SAL_CALL OptionButtons( const css::uno::Any& rIndex ) throw (css::uno::RuntimeException); + virtual css::uno::Any SAL_CALL ScrollBars( const css::uno::Any& rIndex ) throw (css::uno::RuntimeException); + virtual css::uno::Any SAL_CALL Spinners( const css::uno::Any& rIndex ) throw (css::uno::RuntimeException); + virtual void SAL_CALL setEnableCalculation( ::sal_Bool EnableCalculation ) throw ( css::script::BasicErrorException, css::uno::RuntimeException); virtual ::sal_Bool SAL_CALL getEnableCalculation( ) throw (css::script::BasicErrorException, css::uno::RuntimeException); virtual void SAL_CALL ShowDataForm( ) throw (css::uno::RuntimeException); @@ -135,7 +155,6 @@ public: virtual ::sal_Bool SAL_CALL hasProperty( const ::rtl::OUString& aName ) throw (css::uno::RuntimeException); // CodeName virtual rtl::OUString SAL_CALL getCodeName() throw (css::uno::RuntimeException); - virtual void SAL_CALL setCodeName( const rtl::OUString& sCodeName ) throw (css::uno::RuntimeException); sal_Int16 getSheetID() throw (css::uno::RuntimeException); virtual void SAL_CALL PrintOut( const css::uno::Any& From, const css::uno::Any& To, const css::uno::Any& Copies, const css::uno::Any& Preview, const css::uno::Any& ActivePrinter, const css::uno::Any& PrintToFile, const css::uno::Any& Collate, const css::uno::Any& PrToFileName, const css::uno::Any& IgnorePrintAreas ) throw (css::uno::RuntimeException); diff --git a/sc/source/ui/vba/vbaworksheets.cxx b/sc/source/ui/vba/vbaworksheets.cxx index e7de0b82fcaa..60cf7b904026 100644 --- a/sc/source/ui/vba/vbaworksheets.cxx +++ b/sc/source/ui/vba/vbaworksheets.cxx @@ -435,3 +435,24 @@ ScVbaWorksheets::getServiceNames() } return sNames; } + +/*static*/ bool ScVbaWorksheets::nameExists( uno::Reference <sheet::XSpreadsheetDocument>& xSpreadDoc, const ::rtl::OUString & name, SCTAB& nTab ) throw ( lang::IllegalArgumentException ) +{ + if (!xSpreadDoc.is()) + throw lang::IllegalArgumentException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nameExists() xSpreadDoc is null" ) ), uno::Reference< uno::XInterface >(), 1 ); + uno::Reference <container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY ); + if ( xIndex.is() ) + { + SCTAB nCount = static_cast< SCTAB >( xIndex->getCount() ); + for (SCTAB i=0; i < nCount; i++) + { + uno::Reference< container::XNamed > xNamed( xIndex->getByIndex(i), uno::UNO_QUERY_THROW ); + if (xNamed->getName() == name) + { + nTab = i; + return true; + } + } + } + return false; +} diff --git a/sc/source/ui/vba/vbaworksheets.hxx b/sc/source/ui/vba/vbaworksheets.hxx index 4c8120084b02..2ced68bc9e27 100644 --- a/sc/source/ui/vba/vbaworksheets.hxx +++ b/sc/source/ui/vba/vbaworksheets.hxx @@ -31,11 +31,14 @@ #include <ooo/vba/excel/XWorksheets.hpp> #include <com/sun/star/sheet/XSpreadsheets.hpp> +#include <com/sun/star/sheet/XSpreadsheetDocument.hpp> #include <com/sun/star/container/XEnumerationAccess.hpp> #include <com/sun/star/uno/XComponentContext.hpp> #include <vbahelper/vbacollectionimpl.hxx> +#include "address.hxx" + class ScModelObj; @@ -74,6 +77,7 @@ public: virtual rtl::OUString& getServiceImplName(); virtual css::uno::Sequence<rtl::OUString> getServiceNames(); + static bool nameExists( css::uno::Reference <css::sheet::XSpreadsheetDocument>& xSpreadDoc, const ::rtl::OUString & name, SCTAB& nTab ) throw ( css::lang::IllegalArgumentException ); }; #endif /* SC_VBA_WORKSHEETS_HXX */ diff --git a/sc/source/ui/vba/vbawsfunction.cxx b/sc/source/ui/vba/vbawsfunction.cxx index c355244f6815..60daa7303f2e 100644 --- a/sc/source/ui/vba/vbawsfunction.cxx +++ b/sc/source/ui/vba/vbawsfunction.cxx @@ -31,6 +31,7 @@ #include <com/sun/star/beans/XIntrospectionAccess.hpp> #include <com/sun/star/sheet/XFunctionAccess.hpp> #include <com/sun/star/sheet/XCellRangesQuery.hpp> +#include <com/sun/star/sheet/XCellRangeAddressable.hpp> #include <com/sun/star/sheet/CellFlags.hpp> #include <com/sun/star/reflection/XIdlMethod.hpp> #include <com/sun/star/beans/MethodConcept.hpp> @@ -44,10 +45,27 @@ using namespace com::sun::star; using namespace ooo::vba; -ScVbaWSFunction::ScVbaWSFunction( const uno::Reference< XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext): ScVbaWSFunction_BASE( xParent, xContext ) +namespace { + +void lclConvertDoubleToBoolean( uno::Any& rAny ) { + if( rAny.has< double >() ) + { + double fValue = rAny.get< double >(); + if( fValue == 0.0 ) + rAny <<= false; + else if( fValue == 1.0 ) + rAny <<= true; + // do nothing for other values or types + } } +} // namespace + +ScVbaWSFunction::ScVbaWSFunction( const uno::Reference< XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext ) : + ScVbaWSFunction_BASE( xParent, xContext ) +{ +} uno::Reference< beans::XIntrospectionAccess > ScVbaWSFunction::getIntrospection(void) throw(uno::RuntimeException) @@ -58,33 +76,101 @@ ScVbaWSFunction::getIntrospection(void) throw(uno::RuntimeException) uno::Any SAL_CALL ScVbaWSFunction::invoke(const rtl::OUString& FunctionName, const uno::Sequence< uno::Any >& Params, uno::Sequence< sal_Int16 >& /*OutParamIndex*/, uno::Sequence< uno::Any >& /*OutParam*/) throw(lang::IllegalArgumentException, script::CannotConvertException, reflection::InvocationTargetException, uno::RuntimeException) { - uno::Reference< lang::XMultiComponentFactory > xSMgr( mxContext->getServiceManager(), uno::UNO_QUERY_THROW ); - uno::Reference< sheet::XFunctionAccess > xFunctionAccess( - xSMgr->createInstanceWithContext(::rtl::OUString::createFromAscii( - "com.sun.star.sheet.FunctionAccess"), mxContext), - ::uno::UNO_QUERY_THROW); - uno::Sequence< uno::Any > aParamTemp; - sal_Int32 nParamCount = Params.getLength(); - aParamTemp.realloc(nParamCount); - const uno::Any* aArray = Params.getConstArray(); - uno::Any* aArrayTemp = aParamTemp.getArray(); - - for (int i=0; i < Params.getLength();i++) + // create copy of parameters, replace Excel range objects with UNO range objects + uno::Sequence< uno::Any > aParamTemp( Params ); + if( aParamTemp.hasElements() ) + { + uno::Any* pArray = aParamTemp.getArray(); + uno::Any* pArrayEnd = pArray + aParamTemp.getLength(); + for( ; pArray < pArrayEnd; ++pArray ) + { + uno::Reference< excel::XRange > myRange( *pArray, uno::UNO_QUERY ); + if( myRange.is() ) + *pArray = myRange->getCellRange(); + OSL_TRACE("Param[%d] is %s", (int)(pArray - aParamTemp.getConstArray()), rtl::OUStringToOString( comphelper::anyToString( *pArray ), RTL_TEXTENCODING_UTF8 ).getStr() ); + } + } + + uno::Any aRet; + bool bAsArray = true; + + // special handing for some functions that don't work correctly in FunctionAccess + ScCompiler aCompiler( 0, ScAddress() ); + OpCode eOpCode = aCompiler.GetEnglishOpCode( FunctionName.toAsciiUpperCase() ); + switch( eOpCode ) { - uno::Reference<excel::XRange> myRange( aArray[ i ], uno::UNO_QUERY ); - if ( myRange.is() ) + // ISLOGICAL does not work in array formula mode + case ocIsLogical: { - aArrayTemp[i] = myRange->getCellRange(); - continue; + if( aParamTemp.getLength() != 1 ) + throw lang::IllegalArgumentException(); + const uno::Any& rParam = aParamTemp[ 0 ]; + if( rParam.has< bool >() ) + { + aRet <<= true; + } + else if( rParam.has< uno::Reference< table::XCellRange > >() ) try + { + uno::Reference< sheet::XCellRangeAddressable > xRangeAddr( rParam, uno::UNO_QUERY_THROW ); + table::CellRangeAddress aRangeAddr = xRangeAddr->getRangeAddress(); + bAsArray = (aRangeAddr.StartColumn != aRangeAddr.EndColumn) || (aRangeAddr.StartRow != aRangeAddr.EndRow); + } + catch( uno::Exception& ) + { + } } - aArrayTemp[i]= aArray[i]; + break; + default:; } - for ( int count=0; count < aParamTemp.getLength(); ++count ) - OSL_TRACE("Param[%d] is %s", - count, rtl::OUStringToOString( comphelper::anyToString( aParamTemp[count] ), RTL_TEXTENCODING_UTF8 ).getStr() ); + if( !aRet.hasValue() ) + { + uno::Reference< lang::XMultiComponentFactory > xSMgr( mxContext->getServiceManager(), uno::UNO_QUERY_THROW ); + uno::Reference< sheet::XFunctionAccess > xFunctionAccess( xSMgr->createInstanceWithContext( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.FunctionAccess" ) ), mxContext ), + uno::UNO_QUERY_THROW ); + uno::Reference< beans::XPropertySet > xPropSet( xFunctionAccess, uno::UNO_QUERY_THROW ); + xPropSet->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsArrayFunction" ) ), uno::Any( bAsArray ) ); + aRet = xFunctionAccess->callFunction( FunctionName, aParamTemp ); + } - uno::Any aRet = xFunctionAccess->callFunction(FunctionName,aParamTemp); + /* Convert return value from double to to Boolean for some functions that + return Booleans. */ + typedef uno::Sequence< uno::Sequence< uno::Any > > AnySeqSeq; + if( (eOpCode == ocIsEmpty) || (eOpCode == ocIsString) || (eOpCode == ocIsNonString) || (eOpCode == ocIsLogical) || + (eOpCode == ocIsRef) || (eOpCode == ocIsValue) || (eOpCode == ocIsFormula) || (eOpCode == ocIsNA) || + (eOpCode == ocIsErr) || (eOpCode == ocIsError) || (eOpCode == ocIsEven) || (eOpCode == ocIsOdd) || + (eOpCode == ocAnd) || (eOpCode == ocOr) || (eOpCode == ocNot) || (eOpCode == ocTrue) || (eOpCode == ocFalse) ) + { + if( aRet.has< AnySeqSeq >() ) + { + AnySeqSeq aAnySeqSeq = aRet.get< AnySeqSeq >(); + for( sal_Int32 nRow = 0; nRow < aAnySeqSeq.getLength(); ++nRow ) + for( sal_Int32 nCol = 0; nCol < aAnySeqSeq[ nRow ].getLength(); ++nCol ) + lclConvertDoubleToBoolean( aAnySeqSeq[ nRow ][ nCol ] ); + aRet <<= aAnySeqSeq; + } + else + { + lclConvertDoubleToBoolean( aRet ); + } + } + + /* Hack/workaround (?): shorten single-row matrix to simple array, shorten + 1x1 matrix to single value. */ + if( aRet.has< AnySeqSeq >() ) + { + AnySeqSeq aAnySeqSeq = aRet.get< AnySeqSeq >(); + if( aAnySeqSeq.getLength() == 1 ) + { + if( aAnySeqSeq[ 0 ].getLength() == 1 ) + aRet = aAnySeqSeq[ 0 ][ 0 ]; + else + aRet <<= aAnySeqSeq[ 0 ]; + } + } + +#if 0 // MATCH function should alwayse return a double value, but currently if the first argument is XCellRange, MATCH function returns an array instead of a double value. Don't know why? // To fix this issue in safe, current solution is to convert this array to a double value just for MATCH function. String aUpper( FunctionName ); @@ -101,6 +187,8 @@ ScVbaWSFunction::invoke(const rtl::OUString& FunctionName, const uno::Sequence< throw uno::RuntimeException(); aRet <<= fVal; } +#endif + return aRet; } @@ -122,7 +210,7 @@ ScVbaWSFunction::hasMethod(const rtl::OUString& Name) throw(uno::RuntimeExcepti sal_Bool bIsFound = sal_False; try { - // the function name contained in the com.sun.star.sheet.FunctionDescription service is alwayse localized. + // the function name contained in the com.sun.star.sheet.FunctionDescription service is alwayse localized. // but the function name used in WorksheetFunction is a programmatic name (seems English). // So m_xNameAccess->hasByName( Name ) may fail to find name when a function name has a localized name. ScCompiler aCompiler( NULL, ScAddress() ); diff --git a/sc/source/ui/vba/vbawsfunction.hxx b/sc/source/ui/vba/vbawsfunction.hxx index 58a895f6d47b..ffd33849afe5 100644 --- a/sc/source/ui/vba/vbawsfunction.hxx +++ b/sc/source/ui/vba/vbawsfunction.hxx @@ -52,7 +52,6 @@ public: // XHelperInterface virtual rtl::OUString& getServiceImplName(); virtual css::uno::Sequence<rtl::OUString> getServiceNames(); - }; #endif diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx index 87740a88e4df..ff40bdeb7390 100644 --- a/sc/source/ui/view/gridwin.cxx +++ b/sc/source/ui/view/gridwin.cxx @@ -2405,6 +2405,7 @@ void lcl_InitMouseEvent( ::com::sun::star::awt::MouseEvent& rEvent, const MouseE long ScGridWindow::PreNotify( NotifyEvent& rNEvt ) { + bool bDone = false; USHORT nType = rNEvt.GetType(); if ( nType == EVENT_MOUSEBUTTONUP || nType == EVENT_MOUSEBUTTONDOWN ) { @@ -2425,16 +2426,31 @@ long ScGridWindow::PreNotify( NotifyEvent& rNEvt ) if ( rNEvt.GetWindow() ) aEvent.Source = rNEvt.GetWindow()->GetComponentInterface(); if ( nType == EVENT_MOUSEBUTTONDOWN) - pImp->MousePressed( aEvent ); + bDone = pImp->MousePressed( aEvent ); else - pImp->MouseReleased( aEvent ); + bDone = pImp->MouseReleased( aEvent ); } } } } } + if (bDone) // event consumed by a listener + { + if ( nType == EVENT_MOUSEBUTTONDOWN ) + { + const MouseEvent* pMouseEvent = rNEvt.GetMouseEvent(); + if ( pMouseEvent->IsRight() && pMouseEvent->GetClicks() == 1 ) + { + // If a listener returned true for a right-click call, also prevent opening the context menu + // (this works only if the context menu is opened on mouse-down) + nMouseStatus = SC_GM_IGNORE; + } + } - return Window::PreNotify( rNEvt ); + return 1; + } + else + return Window::PreNotify( rNEvt ); } void ScGridWindow::Tracking( const TrackingEvent& rTEvt ) @@ -2678,6 +2694,10 @@ void __EXPORT ScGridWindow::Command( const CommandEvent& rCEvt ) if ( nCmd == COMMAND_CONTEXTMENU && !SC_MOD()->GetIsWaterCan() ) { + BOOL bMouse = rCEvt.IsMouseEvent(); + if ( bMouse && nMouseStatus == SC_GM_IGNORE ) + return; + if (pViewData->IsAnyFillMode()) { pViewData->GetView()->StopRefMode(); @@ -2688,7 +2708,6 @@ void __EXPORT ScGridWindow::Command( const CommandEvent& rCEvt ) Point aPosPixel = rCEvt.GetMousePosPixel(); Point aMenuPos = aPosPixel; - BOOL bMouse = rCEvt.IsMouseEvent(); if ( bMouse ) { diff --git a/sc/source/ui/view/tabvwshf.cxx b/sc/source/ui/view/tabvwshf.cxx index 313b15628239..20a10f149a3a 100644 --- a/sc/source/ui/view/tabvwshf.cxx +++ b/sc/source/ui/view/tabvwshf.cxx @@ -28,18 +28,19 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sc.hxx" - - -// INCLUDE --------------------------------------------------------------- +#include <boost/scoped_ptr.hpp> #include "scitems.hxx" #include <sfx2/request.hxx> +#include <sfx2/viewfrm.hxx> #include <basic/sbstar.hxx> #include <layout/layout.hxx> #include <svl/languageoptions.hxx> #include <svl/stritem.hxx> #include <svl/whiter.hxx> #include <vcl/msgbox.hxx> +#include <svx/svxdlg.hxx> +#include <editeng/colritem.hxx> #include "tabvwsh.hxx" #include "sc.hrc" @@ -52,16 +53,15 @@ //CHINA001 #include "strindlg.hxx" //CHINA001 #include "mvtabdlg.hxx" #include "docfunc.hxx" +#include "eventuno.hxx" #include "scabstdlg.hxx" //CHINA001 #include "tabbgcolor.hxx" #include "tabbgcolordlg.hxx" -#include "editeng/colritem.hxx" - -#include <boost/scoped_ptr.hpp> using ::boost::scoped_ptr; +using namespace com::sun::star; #define IS_AVAILABLE(WhichId,ppItem) \ (pReqArgs->GetItemState((WhichId), TRUE, ppItem ) == SFX_ITEM_SET) @@ -696,11 +696,9 @@ void ScTabViewShell::ExecuteTable( SfxRequest& rReq ) { if ( nSlot == FID_TAB_MENU_SET_TAB_BG_COLOR ) nSlot = FID_TAB_SET_TAB_BG_COLOR; - SCTAB nTabNr = pViewData->GetTabNo(); ScMarkData& rMark = pViewData->GetMarkData(); SCTAB nTabSelCount = rMark.GetSelectCount(); - if ( !pDoc->IsDocEditable() ) break; @@ -802,6 +800,25 @@ void ScTabViewShell::ExecuteTable( SfxRequest& rReq ) } } break; + + case FID_TAB_EVENTS: + { + ScDocShell* pDocSh = pViewData->GetDocShell(); + uno::Reference<container::XNameReplace> xEvents( new ScSheetEventsObj( pDocSh, nCurrentTab ) ); + uno::Reference<frame::XFrame> xFrame = GetViewFrame()->GetFrame().GetFrameInterface(); + SvxAbstractDialogFactory* pDlgFactory = SvxAbstractDialogFactory::Create(); + if (pDlgFactory) + { + std::auto_ptr<VclAbstractDialog> pDialog( pDlgFactory->CreateSvxMacroAssignDlg( + GetDialogParent(), xFrame, false, xEvents, 0 ) ); + if ( pDialog.get() && pDialog->Execute() == RET_OK ) + { + // the dialog modifies the settings directly + } + } + } + break; + default: DBG_ERROR("Unbekannte Message bei ViewShell"); break; diff --git a/sc/source/ui/view/viewfun2.cxx b/sc/source/ui/view/viewfun2.cxx index ea11ee222770..34fbbfdad5b5 100644 --- a/sc/source/ui/view/viewfun2.cxx +++ b/sc/source/ui/view/viewfun2.cxx @@ -2203,6 +2203,7 @@ BOOL ScViewFunc::DeleteTables(const SvShorts &TheTabs, BOOL bRecord ) } pUndoDoc->SetVisible( nTab, pDoc->IsVisible( nTab ) ); pUndoDoc->SetTabBgColor( nTab, pDoc->GetTabBgColor(nTab) ); + pUndoDoc->SetSheetEvents( nTab, pDoc->GetSheetEvents( nTab ) ); if ( pDoc->IsTabProtected( nTab ) ) pUndoDoc->SetTabProtection(nTab, pDoc->GetTabProtection(nTab)); diff --git a/sc/util/makefile.mk b/sc/util/makefile.mk index d9e23b5f3623..980d271ae7c0 100644 --- a/sc/util/makefile.mk +++ b/sc/util/makefile.mk @@ -315,7 +315,7 @@ SHL9STDLIBS= \ $(ISCLIB) \ $(VCLLIB) \ $(TKLIB) \ - $(SVXMSFILTERLIB) \ + $(MSFILTERLIB) \ $(FORLIB) SHL9DEPN=$(SHL1TARGETN) $(SHL8TARGETN) |