Search code examples
excelvbacopyvisio

Visio VBA code to copy and paste excel sheets from one to another


I have Visio Vba macro that is supposed to take in a file path to an excel sheet from a global var. Then it opens that file, generates a new excel sheet, and takes the sheets from the old path and copies them to the generated file. My problem is copying the sheets over. The first file I give it sometimes works, but when I run another or the same file again, when it runs this specific line: PriceWs.Copy After:=excelWorkbook.Sheets("Sheet1")

I get the run time 1004 error: No such interface supported, and I can't figure out why it keeps doing that.

If it helps, I receive the file path through a global string that just holds the Filepath. Example value: C:\Users\things\Documents\TESTING.xlsx

I run this code through a command button on a user form that just runs this macro and nothing else.

Also while debugging, the PriceWs type is worksheet/worksheet if that matters, but again the code sometimes runs while it was this type.

Sub CombineExcel()
    
    Dim PriceWb As Workbook
    Dim PriceWs As Worksheet
    Dim PriceString As String
 
    'Error checking for a good file
    'Global is a global string that holds the path to an excel file
    PriceString = GlobalPriceList
    
    Debug.Print "Price String: " & PriceString
    
    On Error Resume Next
     Set PriceWb = Workbooks.Open(PriceString)
    On Error GoTo 0

    If PriceWb Is Nothing Then
        MsgBox "Error: The file is not a valid Excel file or it could not be opened.", vbCritical
        Exit Sub
    End If

      ' Initialize Excel
    Set excelApp = CreateObject("Excel.Application")
    Dim excelWorkbook As Object
    Dim excelWorksheet As Object
    
    Set excelApp = New Excel.Application
    excelApp.Visible = True ' Optional, set to True if you want Excel to be visible
    Set excelWorkbook = excelApp.Workbooks.Add
    Set excelWorksheet = excelWorkbook.Sheets(1)
    
    ' Loop through each sheet in the source workbook
    For Each PriceWs In PriceWb.Sheets
        On Error Resume Next
        PriceWs.Copy After:=excelWorkbook.Sheets(excelWorkbook.Sheets.count)
        If Err.Number <> 0 Then
            Debug.Print "Type Name is: " & TypeName(PriceWs)
            MsgBox "Error copying sheet '" & PriceWs.Name & "': " & Err.Description, vbCritical
        End If
        On Error GoTo 0
    Next PriceWs
    
    Debug.Print GlobalPriceList
    
     ' Delete the Sheet1 without prompting for confirmation
    'Application.DisplayAlerts = False ' Suppress the alert asking for confirmation
    'excelWorkbook.Sheets("Sheet1").Delete
    'Application.DisplayAlerts = True ' Restore the display alerts setting
      
    ' Release object references
    Set excelWorksheet = Nothing
    Set excelWorkbook = Nothing
    Set excelApp = Nothing
    Set PriceWs = Nothing
     
End Sub

PS: if this helps, this is the code I use to get the file path from the end user since I can't use GetOpenFilename in visio's vba:

Dim wShell As Object, sPath As String, oExec As Variant
 ' Create an instance of the WScript.Shell object
Set wShell = CreateObject("WScript.Shell")

' Execute a command line using mshta.exe with an HTML script as an argument
' The HTML script dynamically generates an HTML page with a file input   element and JavaScript code to interact with it

Set oExec = wShell.Exec("mshta.exe ""about:<input type=file id=FILE accept=.xls,.xlsx><script>FILE.click();new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).WriteLine(FILE.value);close();resizeTo(0,0);</script>""")

' Read the file path from the standard output of the executed command
sPath = oExec.StdOut.ReadLine

Solution

  • Please check description of method Worksheet.Copy

    Copies the sheet to another location in the current workbook or a new workbook.

    About Error 1004

    Source and Destination must be in the same Excel.Application instance, otherwise it will raise a runtime error '1004': No such interface supported, if something like Sheet1.Copy objWb.Sheets(1) was used, or a runtime error '1004': Copy method of Worksheet class failed, if something like ThisWorkbook.Worksheets("Sheet1").Copy objWb.Sheets(1) was used.


    I find that Worksheet.Move method (Excel) can move Worksheets between different Workbooks! I modify your code and run into Excel!
    Note: Do not create a new Excel application session to avoid the error!

    Sub CombineExcel()
        
        Dim PriceWb As Workbook
        Dim PriceWs As Worksheet
        Dim PriceString As String
     
        'Error checking for a good file
        'Global is a global string that holds the path to an excel file
        PriceString = "C:\адЪ\ЛВС.xls" ' my local workbook for tests path
        
        Debug.Print "Price String: " & PriceString
        
        On Error Resume Next
         Set PriceWb = Workbooks.Open(PriceString)
        On Error GoTo 0
    
        If PriceWb Is Nothing Then
            MsgBox "Error: The file is not a valid Excel file or it could not be opened.", vbCritical
            Exit Sub
        End If
    
          ' Initialize Excel
        Dim excelApp As Object
        Dim excelWorkbook As Object
        Dim excelWorksheet As Object
        
        ' Set excelApp = New Excel.Application 
        Set excelApp = Application ' !!! DONT CREATE NEW EXCEL's session !!!
     
        excelApp.Visible = True ' Optional, set to True if you want Excel to be visible
        Set excelWorkbook = excelApp.Workbooks.Add
        Set excelWorksheet = excelWorkbook.Sheets(1)
        
        ' Loop through each sheet in the source workbook
        For Each PriceWs In PriceWb.Sheets
            On Error Resume Next
            PriceWs.Copy After:=excelWorkbook.Sheets(excelWorkbook.Sheets.Count)
            If Err.Number <> 0 Then
                Debug.Print "Type Name is: " & TypeName(PriceWs)
                MsgBox "Error copying sheet '" & PriceWs.Name & "': " & Err.Description, vbCritical
            End If
            On Error GoTo 0
        Next PriceWs
        
        Debug.Print GlobalPriceList
        
         ' Delete the Sheet1 without prompting for confirmation
        'Application.DisplayAlerts = False ' Suppress the alert asking for confirmation
        'excelWorkbook.Sheets("Sheet1").Delete
        'Application.DisplayAlerts = True ' Restore the display alerts setting
          
        ' Release object references
        Set excelWorksheet = Nothing
        Set excelWorkbook = Nothing
        Set excelApp = Nothing
        Set PriceWs = Nothing
         
    End Sub
    

    PS What about MS Visio?
    PPS I ported code to Visio document, there you can find rows for late or early bindings

    Visio haven't build-in file dialogs which can select for open documents. Please read more in these threads:
    Open a fileDialog in visio vba
    Add Open File Dialog to VBA