From 9c4e1127b53af9725b8d4c579782ab3196effea8 Mon Sep 17 00:00:00 2001
From: Markus Mohrhard <markus.mohrhard@googlemail.com>
Date: Fri, 8 Apr 2011 02:24:00 +0200
Subject: [PATCH 2/2] add method Copy to ScVbaWorksheets

---
 sc/source/ui/vba/excelvbahelper.cxx |   80 +++++++++++++++++++++++++++++++++
 sc/source/ui/vba/excelvbahelper.hxx |    5 ++
 sc/source/ui/vba/vbaworksheet.cxx   |   83 +---------------------------------
 sc/source/ui/vba/vbaworksheets.cxx  |   77 ++++++++++++++++++++++++++++++++
 sc/source/ui/vba/vbaworksheets.hxx  |    1 +
 5 files changed, 166 insertions(+), 80 deletions(-)

diff --git a/sc/source/ui/vba/excelvbahelper.cxx b/sc/source/ui/vba/excelvbahelper.cxx
index 4f49aab..f4debd3 100644
--- a/sc/source/ui/vba/excelvbahelper.cxx
+++ b/sc/source/ui/vba/excelvbahelper.cxx
@@ -30,6 +30,7 @@
 
 #include <comphelper/processfactory.hxx>
 #include <com/sun/star/sheet/XSheetCellRange.hpp>
+#include <com/sun/star/frame/XComponentLoader.hpp>
 #include "docuno.hxx"
 #include "tabvwsh.hxx"
 #include "transobj.hxx"
@@ -38,6 +39,7 @@
 #include "compiler.hxx"
 #include "token.hxx"
 #include "tokenarray.hxx"
+#include "vbaworksheets.hxx"
 
 using namespace ::com::sun::star;
 using namespace ::ooo::vba;
@@ -460,6 +462,84 @@ getUnoSheetModuleObj( const uno::Reference< frame::XModel >& xModel, SCTAB nTab
     return getUnoSheetModuleObj( xSheet );
 }
 
+void removeAllSheets( uno::Reference <sheet::XSpreadsheetDocument>& xSpreadDoc, rtl::OUString aSheetName)
+{
+    if (!xSpreadDoc.is())
+        throw lang::IllegalArgumentException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "removeAllSheets() 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() )
+    {
+        uno::Reference<container::XNameContainer> xNameContainer(xSheets,uno::UNO_QUERY_THROW);
+        for (sal_Int32 i = xIndex->getCount()-1 ; i>= 1; i--)
+        {
+            uno::Reference< sheet::XSpreadsheet > xSheet(xIndex->getByIndex(i), uno::UNO_QUERY);
+            uno::Reference< container::XNamed > xNamed( xSheet, uno::UNO_QUERY_THROW );
+            if (xNamed.is())
+            {
+                xNameContainer->removeByName(xNamed->getName());
+            }
+        }
+        if (!aSheetName.isEmpty())
+        {
+            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);
+            }
+        }
+    }
+}
+
+void getNewSpreadsheetName (rtl::OUString &aNewName, rtl::OUString aOldName, uno::Reference <sheet::XSpreadsheetDocument>& xSpreadDoc )
+{
+    if (!xSpreadDoc.is())
+        throw lang::IllegalArgumentException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getNewSpreadsheetName() xSpreadDoc is null" ) ), uno::Reference< uno::XInterface  >(), 1 );
+    static rtl::OUString aUnderScre( RTL_CONSTASCII_USTRINGPARAM( "_" ) );
+    int currentNum =2;
+    aNewName = aOldName + aUnderScre+ String::CreateFromInt32(currentNum) ;
+    SCTAB nTab = 0;
+    while ( ScVbaWorksheets::nameExists(xSpreadDoc,aNewName, nTab ) )
+    {
+        aNewName = aOldName + aUnderScre +
+        String::CreateFromInt32(++currentNum) ;
+    }
+}
+
+uno::Reference<frame::XModel> openNewDoc(rtl::OUString aSheetName)
+{
+    uno::Reference<frame::XModel> xModel;
+    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 );
+        uno::Reference<lang::XMultiComponentFactory > xServiceManager(
+                                        xContext->getServiceManager(), uno::UNO_QUERY_THROW );
+
+        uno::Reference <frame::XComponentLoader > xComponentLoader(
+                        xServiceManager->createInstanceWithContext(
+                        rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ) ),
+                        xContext ), uno::UNO_QUERY_THROW );
+
+        uno::Reference<lang::XComponent > xComponent( xComponentLoader->loadComponentFromURL(
+                rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:factory/scalc" ) ),
+                rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_blank" ) ), 0,
+                uno::Sequence < ::com::sun::star::beans::PropertyValue >() ) );
+        uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( xComponent, uno::UNO_QUERY_THROW );
+        if ( xSpreadDoc.is() )
+        {
+            removeAllSheets(xSpreadDoc, aSheetName);
+        }
+        xModel.set(xSpreadDoc,uno::UNO_QUERY_THROW);
+    }
+    catch ( uno::Exception & /*e*/ )
+    {
+    }
+    return xModel;
+}
+
 SfxItemSet*
 ScVbaCellRangeAccess::GetDataSet( ScCellRangesBase* pRangeObj )
 {
diff --git a/sc/source/ui/vba/excelvbahelper.hxx b/sc/source/ui/vba/excelvbahelper.hxx
index 2100f4a..d1d3278 100644
--- a/sc/source/ui/vba/excelvbahelper.hxx
+++ b/sc/source/ui/vba/excelvbahelper.hxx
@@ -35,6 +35,7 @@
 #include <com/sun/star/table/XCellRange.hpp>
 #include <com/sun/star/sheet/XSheetCellRangeContainer.hpp>
 #include <com/sun/star/sheet/XSpreadsheet.hpp>
+#include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
 #include <ooo/vba/XHelperInterface.hpp>
 #include <formula/grammar.hxx>
 
@@ -76,6 +77,10 @@ ScDocShell* GetDocShellFromRanges( const css::uno::Reference< css::sheet::XSheet
 ScDocument* GetDocumentFromRange( const css::uno::Reference< css::uno::XInterface >& xRange ) throw ( css::uno::RuntimeException );
 css::uno::Reference< css::frame::XModel > GetModelFromRange( const css::uno::Reference< css::uno::XInterface >& xRange ) throw ( css::uno::RuntimeException );
 
+void removeAllSheets( css::uno::Reference < css::sheet::XSpreadsheetDocument>& xSpreadDoc, rtl::OUString aSheetName);
+void getNewSpreadsheetName (rtl::OUString &aNewName, rtl::OUString aOldName, css::uno::Reference < css::sheet::XSpreadsheetDocument>& xSpreadDoc );
+css::uno::Reference< css::frame::XModel> openNewDoc(rtl::OUString aSheetName);
+
 // ============================================================================
 
 class ScVbaCellRangeAccess
diff --git a/sc/source/ui/vba/vbaworksheet.cxx b/sc/source/ui/vba/vbaworksheet.cxx
index 94f197d..f5cdef9 100644
--- a/sc/source/ui/vba/vbaworksheet.cxx
+++ b/sc/source/ui/vba/vbaworksheet.cxx
@@ -108,83 +108,6 @@
 using namespace com::sun::star;
 using namespace ooo::vba;
 
-static void getNewSpreadsheetName (rtl::OUString &aNewName, rtl::OUString aOldName, uno::Reference <sheet::XSpreadsheetDocument>& xSpreadDoc )
-{
-    if (!xSpreadDoc.is())
-        throw lang::IllegalArgumentException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getNewSpreadsheetName() xSpreadDoc is null" ) ), uno::Reference< uno::XInterface  >(), 1 );
-    static rtl::OUString aUnderScre( RTL_CONSTASCII_USTRINGPARAM( "_" ) );
-    int currentNum =2;
-    aNewName = aOldName + aUnderScre+ String::CreateFromInt32(currentNum) ;
-    SCTAB nTab = 0;
-    while ( ScVbaWorksheets::nameExists(xSpreadDoc,aNewName, nTab ) )
-    {
-        aNewName = aOldName + aUnderScre +
-        String::CreateFromInt32(++currentNum) ;
-    }
-}
-
-static void removeAllSheets( uno::Reference <sheet::XSpreadsheetDocument>& xSpreadDoc, rtl::OUString aSheetName)
-{
-    if (!xSpreadDoc.is())
-        throw lang::IllegalArgumentException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "removeAllSheets() 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() )
-    {
-        uno::Reference<container::XNameContainer> xNameContainer(xSheets,uno::UNO_QUERY_THROW);
-        for (sal_Int32 i = xIndex->getCount() -1; i>= 1; i--)
-        {
-            uno::Reference< sheet::XSpreadsheet > xSheet(xIndex->getByIndex(i), uno::UNO_QUERY);
-            uno::Reference< container::XNamed > xNamed( xSheet, uno::UNO_QUERY_THROW );
-            if (xNamed.is())
-            {
-                xNameContainer->removeByName(xNamed->getName());
-            }
-        }
-
-        uno::Reference< sheet::XSpreadsheet > xSheet(xIndex->getByIndex(0), uno::UNO_QUERY);
-        uno::Reference< container::XNamed > xNamed( xSheet, uno::UNO_QUERY_THROW );
-        if (xNamed.is())
-        {
-            xNamed->setName(aSheetName);
-        }
-    }
-}
-
-static uno::Reference<frame::XModel>
-openNewDoc(rtl::OUString aSheetName )
-{
-    uno::Reference<frame::XModel> xModel;
-    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 );
-        uno::Reference<lang::XMultiComponentFactory > xServiceManager(
-                                        xContext->getServiceManager(), uno::UNO_QUERY_THROW );
-
-        uno::Reference <frame::XComponentLoader > xComponentLoader(
-                        xServiceManager->createInstanceWithContext(
-                        rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ) ),
-                        xContext ), uno::UNO_QUERY_THROW );
-
-        uno::Reference<lang::XComponent > xComponent( xComponentLoader->loadComponentFromURL(
-                rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:factory/scalc" ) ),
-                rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_blank" ) ), 0,
-                uno::Sequence < ::com::sun::star::beans::PropertyValue >() ) );
-        uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( xComponent, uno::UNO_QUERY_THROW );
-        if ( xSpreadDoc.is() )
-        {
-            removeAllSheets(xSpreadDoc,aSheetName);
-        }
-        xModel.set(xSpreadDoc,uno::UNO_QUERY_THROW);
-    }
-    catch ( uno::Exception & /*e*/ )
-    {
-    }
-    return xModel;
-}
-
 ScVbaWorksheet::ScVbaWorksheet( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext ) : WorksheetImpl_BASE( xParent, xContext ), mbVeryHidden( false )
 {
 }
@@ -530,7 +453,7 @@ ScVbaWorksheet::Move( const uno::Any& Before, const uno::Any& After ) throw (uno
         if (xRange.is())
             xRange->Select();
         excel::implnCopy(mxModel);
-        uno::Reference<frame::XModel> xModel = openNewDoc(aCurrSheetName);
+        uno::Reference<frame::XModel> xModel = excel::openNewDoc(aCurrSheetName);
         if (xModel.is())
         {
             excel::implnPaste(xModel);
@@ -565,7 +488,7 @@ ScVbaWorksheet::Copy( const uno::Any& Before, const uno::Any& After ) throw (uno
         if (xRange.is())
             xRange->Select();
         excel::implnCopy(mxModel);
-        uno::Reference<frame::XModel> xModel = openNewDoc(aCurrSheetName);
+        uno::Reference<frame::XModel> xModel = excel::openNewDoc(aCurrSheetName);
         if (xModel.is())
         {
             excel::implnPaste(xModel);
@@ -594,7 +517,7 @@ ScVbaWorksheet::Copy( const uno::Any& Before, const uno::Any& After ) throw (uno
               nDest++;
         uno::Reference<sheet::XSpreadsheets> xSheets = xDestDoc->getSheets();
         if ( bSameDoc || ScVbaWorksheets::nameExists( xDestDoc, aCurrSheetName, nDummy ) )
-            getNewSpreadsheetName(aSheetName,aCurrSheetName,xDestDoc);
+            excel::getNewSpreadsheetName(aSheetName,aCurrSheetName,xDestDoc);
         if ( bSameDoc )
             xSheets->copyByName(aCurrSheetName,aSheetName,nDest);
         else
diff --git a/sc/source/ui/vba/vbaworksheets.cxx b/sc/source/ui/vba/vbaworksheets.cxx
index 1bac962..f0aa623 100644
--- a/sc/source/ui/vba/vbaworksheets.cxx
+++ b/sc/source/ui/vba/vbaworksheets.cxx
@@ -53,6 +53,7 @@
 #include "vbaglobals.hxx"
 #include "vbaworksheet.hxx"
 #include "vbaworkbook.hxx"
+#include "vbarange.hxx"
 #include "unonames.hxx"
 
 using namespace ::ooo::vba;
@@ -424,6 +425,82 @@ ScVbaWorksheets::Select( const uno::Any& Replace ) throw (uno::RuntimeException)
 
 }
 
+void SAL_CALL ScVbaWorksheets::Copy( const uno::Any& Before, const uno::Any& After) throw (uno::RuntimeException)
+{
+    uno::Reference<excel::XWorksheet> xSheet;
+    sal_Int32 nElems = getCount();
+    if (!(Before >>= xSheet) && !(After >>=xSheet)&& !(Before.hasValue()) && !(After.hasValue()))
+    {
+        uno::Reference<frame::XModel> xModel = excel::openNewDoc(rtl::OUString());
+        if (xModel.is())
+        {
+            for (sal_Int32 nItem = 1; nItem <= nElems; ++nItem )
+            {
+                uno::Reference< excel::XWorksheet > xSrcSheet( Item( uno::makeAny( nItem ), uno::Any() ), uno::UNO_QUERY_THROW );
+                ScVbaWorksheet* pSrcSheet = excel::getImplFromDocModuleWrapper<ScVbaWorksheet>( xSrcSheet );
+                uno::Reference <sheet::XSpreadsheetDocument> xSrcDoc( pSrcSheet->getModel(), uno::UNO_QUERY );
+                SCTAB nSrc = 0;
+                rtl::OUString aSrcSheetName = xSrcSheet->getName();
+                ScDocShell* pDestDocShell = excel::getDocShell( xModel );
+                ScDocShell* pSrcDocShell = excel::getDocShell( pSrcSheet->getModel() );
+                ScVbaWorksheets::nameExists (xSrcDoc, aSrcSheetName, nSrc );
+                if ( pDestDocShell && pSrcDocShell )
+                    pDestDocShell->TransferTab( *pSrcDocShell, static_cast<SCTAB>(nSrc), static_cast<SCTAB>(nItem-1), true, true );
+            }
+            //can't delete this Spreadsheet before
+            uno::Reference<sheet::XSpreadsheetDocument> xSpreadDoc(xModel, uno::UNO_QUERY);
+            uno::Reference<sheet::XSpreadsheets> xSheets = xSpreadDoc->getSheets();
+            uno::Reference<container::XIndexAccess> xIndex( xSheets, uno::UNO_QUERY );
+            uno::Reference<sheet::XSpreadsheet > xDeleteSheet(xIndex->getByIndex(nElems), uno::UNO_QUERY);
+            uno::Reference<container::XNameContainer> xNameContainer(xSheets,uno::UNO_QUERY_THROW);
+            uno::Reference<container::XNamed> xNamed( xDeleteSheet, uno::UNO_QUERY_THROW );
+            if (xNamed.is())
+            {
+                xNameContainer->removeByName(xNamed->getName());
+            }
+        }
+        return;
+    }
+
+    ScVbaWorksheet* pDestSheet = excel::getImplFromDocModuleWrapper<ScVbaWorksheet>( xSheet );
+    uno::Reference <sheet::XSpreadsheetDocument> xDestDoc( pDestSheet->getModel(), uno::UNO_QUERY );
+    SCTAB nDest = 0;
+    rtl::OUString aSheetName = xSheet->getName();
+    bool bDestSheetExists = ScVbaWorksheets::nameExists (xDestDoc, aSheetName, nDest );
+    sal_Bool bAfter = After.hasValue();
+    if(bAfter)
+        nDest++;
+    for (sal_Int32 nItem = 1; nItem <= nElems; ++nItem )
+    {
+        uno::Reference< excel::XWorksheet > xSrcSheet( Item( uno::makeAny( nItem ), uno::Any() ), uno::UNO_QUERY_THROW );
+        ScVbaWorksheet* pSrcSheet = excel::getImplFromDocModuleWrapper<ScVbaWorksheet>( xSrcSheet );
+        uno::Reference <sheet::XSpreadsheetDocument> xSrcDoc( pSrcSheet->getModel(), uno::UNO_QUERY );
+        SCTAB nSrc = 0;
+        bool bSameDoc = ( pDestSheet->getModel() == pSrcSheet->getModel() );
+        rtl::OUString aSrcSheetName = xSrcSheet->getName();
+        bool bSheetExists = ScVbaWorksheets::nameExists (xSrcDoc, aSrcSheetName, nSrc );
+
+        // set sheet name to be newSheet name
+        aSheetName = aSrcSheetName;
+        if ( bSheetExists && bDestSheetExists )
+        {
+            SCTAB nDummy=0;
+            uno::Reference<sheet::XSpreadsheets> xSheets = xDestDoc->getSheets();
+            if ( bSameDoc || ScVbaWorksheets::nameExists( xDestDoc, aSrcSheetName, nDummy ) )
+                excel::getNewSpreadsheetName(aSheetName,aSrcSheetName,xDestDoc);
+            if ( bSameDoc )
+                xSheets->copyByName(aSrcSheetName,aSheetName,nDest+nItem-1);
+            else
+            {
+                ScDocShell* pDestDocShell = excel::getDocShell( pDestSheet->getModel() );
+                ScDocShell* pSrcDocShell = excel::getDocShell( pSrcSheet->getModel() );
+                if ( pDestDocShell && pSrcDocShell )
+                    pDestDocShell->TransferTab( *pSrcDocShell, static_cast<SCTAB>(nSrc), static_cast<SCTAB>(nDest+nItem-1), true, true );
+            }
+        }
+    }
+}
+
 //ScVbaCollectionBaseImpl
 uno::Any SAL_CALL 
 ScVbaWorksheets::Item( const uno::Any& Index, const uno::Any& Index2  ) throw (uno::RuntimeException)
diff --git a/sc/source/ui/vba/vbaworksheets.hxx b/sc/source/ui/vba/vbaworksheets.hxx
index 82001c0..96777f9 100644
--- a/sc/source/ui/vba/vbaworksheets.hxx
+++ b/sc/source/ui/vba/vbaworksheets.hxx
@@ -72,6 +72,7 @@ public:
     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::uno::RuntimeException);
     virtual css::uno::Any createCollectionObject( const css::uno::Any& aSource ); 
     virtual void SAL_CALL Select( const css::uno::Any& Replace ) throw (css::uno::RuntimeException);
+    virtual void SAL_CALL Copy( const css::uno::Any& Before, const css::uno::Any& After) throw (css::uno::RuntimeException);
     // ScVbaWorksheets_BASE
     virtual css::uno::Any SAL_CALL Item( const css::uno::Any& Index1, const css::uno::Any& Index2 ) throw
 (css::uno::RuntimeException);
-- 
1.7.2.5

