Skip to main content
Announcements
See what Drew Clarke has to say about the Qlik Talend Cloud launch! READ THE BLOG
cancel
Showing results for 
Search instead for 
Did you mean: 
mrthomasshelby
Creator III
Creator III

Error in Macro to export multiple tables to Multiple Excel Tabs

Hello,

I have 5 tables in my QV app attached and I'm trying to export these 5 tables to 5 different tabs in an excel file. I have used this nice macro that I found here. But the macro doesn't run and I get a popup of the macro module instead as below:

Error1.PNG

Can someone help me understand the mistake that I'm making here? I'm attaching the sample app for your reference. Thanks in advance!

tamilarasujagan

1 Solution

Accepted Solutions
Frank_Hartmann
Master II
Master II

Try this:

you will only have to adapt the path of excel export in line 39:

sub exportToExcel

timestamp = date()

'// Array for export definitions

Dim aryExport(4,3)

aryExport(0,0) = "CH391"

aryExport(0,1) = "T1"

aryExport(0,2) = "A1"

aryExport(0,3) = "data"

aryExport(1,0) = "CH392"

aryExport(1,1) = "T2"

aryExport(1,2) = "A1"

aryExport(1,3) = "data"

aryExport(2,0) = "CH393"

aryExport(2,1) = "T3"

aryExport(2,2) = "A1"

aryExport(2,3) = "data"

aryExport(3,0) = "CH394"

aryExport(3,1) = "T4"

aryExport(3,2) = "A1"

aryExport(3,3) = "data"

aryExport(4,0) = "CH395"

aryExport(4,1) = "T5"

aryExport(4,2) = "A1"

aryExport(4,3) = "data"

Dim objExcelWorkbook 'as Excel.Workbook

Set objExcelWorkbook = copyObjectsToExcelSheet(ActiveDocument, aryExport)

filePath = "C:\Users\Admin\Desktop\TEST "&"-"&timestamp&".xlsx"

objExcelWorkbook.SaveAs filePath

objExcelWorkbook.Close

objExcelDoc.Quit

end sub

Private Function copyObjectsToExcelSheet(qvDoc, aryExportDefinition) 'as Excel.Workbook

Dim i 'as Integer

Dim objExcelApp 'as Excel.Application

Dim objExcelDoc 'as Excel.Workbook

Set objExcelApp = CreateObject("Excel.Application")

objExcelApp.Visible = hide 'false if you want to hide Excel

objExcelApp.DisplayAlerts = false

 

Set objExcelDoc = objExcelApp.Workbooks.Add

Dim strSourceObject

Dim qvObjectId 'as String

Dim sheetName

Dim sheetRange

Dim pasteMode

Dim objSource

Dim objCurrentSheet

Dim objExcelSheet

for i = 0 to UBOUND(aryExportDefinition)

'// Get the properties of the exportDefinition array

qvObjectId = aryExportDefinition(i,0)

sheetName = aryExportDefinition(i,1)

sheetRange = aryExportDefinition(i,2)

pasteMode = aryExportDefinition(i,3)

              

Set objExcelSheet = Excel_GetSheetByName(objExcelDoc, sheetName)

if (objExcelSheet is nothing) then

Set objExcelSheet = Excel_AddSheet(objExcelApp, sheetName)

if (objExcelSheet is nothing) then

msgbox("No sheet could be created, this should not occur!!!")

end if

end if

              

    objExcelSheet.Select          

set objSource = qvDoc.GetSheetObject(qvObjectId)

Call objSource.GetSheet().Activate()

objSource.Maximize

qvDoc.GetApplication.WaitForIdle

if (not objSource is nothing) then

if (pasteMode = "image") then

Call objSource.CopyBitmapToClipboard()

else

Call objSource.CopyTableToClipboard(true) '// default & fallback

end if

Set objCurrentSheet = objExcelDoc.Sheets(sheetName)

objExcelDoc.Sheets(sheetName).Range(sheetRange).Select

objExcelDoc.Sheets(sheetName).Paste

if (pasteMode <> "image") then

With objExcelApp.Selection

            .WrapText = False

            .ShrinkToFit = False

End With                   

end if      

objCurrentSheet.Range("A1").Select  

end if

             

             

next  

Call Excel_DeleteBlankSheets(objExcelDoc)

'// Finally select the first sheet

objExcelDoc.Sheets(1).Select

'// Return value

Set copyObjectsToExcelSheet = objExcelDoc

end function

'// ________________________________________________________________

'// ****************************************************************

'// Internal function for getting the Excel sheet by sheetName

'// ****************************************************************

Private Function Excel_GetSheetByName(ByRef objExcelDoc, sheetName) 'as Excel.Sheet

For Each ws In objExcelDoc.Worksheets

If (trim(ws.Name) = Excel_GetSafeSheetName(sheetName)) then

Set Excel_GetSheetByName = ws

exit function

End If

Next

'// default return value

Set Excel_GetSheetByName = nothing

                           

End Function

'// ________________________________________________________________

Private Function Excel_GetSafeSheetName(sheetName)

'// can be max 31 characters long

retVal = trim(left(sheetName, 31))

Excel_GetSafeSheetName = retVal

End Function

'// ****************************************************************

'// Internal function for adding a new sheet

'// ****************************************************************

Private Function Excel_AddSheet(objExcelApplication, sheetName) ' as Excel.Sheet

'// add a sheet to the last position

objExcelApplication.Sheets.Add , objExcelApplication.Sheets(objExcelApplication.Sheets.Count)

Dim objNewSheet

Set objNewSheet = objExcelApplication.Sheets(objExcelApplication.Sheets.Count)

objNewSheet.Name = left(sheetName,31)

'// return the newly created sheet

Set Excel_AddSheet = objNewSheet

End function

'// ________________________________________________________________

'// ****************************************************************

'// Delete all empty sheets

'// ****************************************************************

Private Sub Excel_DeleteBlankSheets(ByRef objExcelDoc)

For Each ws In objExcelDoc.Worksheets

If (not HasOtherObjects(ws)) then

If objExcelDoc.Application.WorksheetFunction.CountA(ws.Cells) = 0 Then

On Error Resume Next

Call ws.Delete()

End If

End If

Next

  

End Sub

'// ________________________________________________________________

'// ****************************************************************

'// Helper function to determine if there are other objects placed

'// on the sheet ...

'// ****************************************************************

Public Function HasOtherObjects(ByRef objSheet) 'As Boolean

    Dim c

    If (objSheet.ChartObjects.Count > 0) Then

    HasOtherObjects = true

    Exit function

    End If

    If (objSheet.Pictures.Count > 0) Then

    HasOtherObjects = true

    Exit function

    End If

    If (objSheet.Shapes.Count > 0) Then

    HasOtherObjects = true

    Exit function

    End If

  

  

    HasOtherObjects = false

End Function

'//__________________________________________________________________

hope this helps

View solution in original post

6 Replies
olivierrobin
Specialist III
Specialist III

hello

the code for

copyObjectsToExcelSheet is missing

I think you didn't copy all the code for the macro to work

Frank_Hartmann
Master II
Master II

Try this:

you will only have to adapt the path of excel export in line 39:

sub exportToExcel

timestamp = date()

'// Array for export definitions

Dim aryExport(4,3)

aryExport(0,0) = "CH391"

aryExport(0,1) = "T1"

aryExport(0,2) = "A1"

aryExport(0,3) = "data"

aryExport(1,0) = "CH392"

aryExport(1,1) = "T2"

aryExport(1,2) = "A1"

aryExport(1,3) = "data"

aryExport(2,0) = "CH393"

aryExport(2,1) = "T3"

aryExport(2,2) = "A1"

aryExport(2,3) = "data"

aryExport(3,0) = "CH394"

aryExport(3,1) = "T4"

aryExport(3,2) = "A1"

aryExport(3,3) = "data"

aryExport(4,0) = "CH395"

aryExport(4,1) = "T5"

aryExport(4,2) = "A1"

aryExport(4,3) = "data"

Dim objExcelWorkbook 'as Excel.Workbook

Set objExcelWorkbook = copyObjectsToExcelSheet(ActiveDocument, aryExport)

filePath = "C:\Users\Admin\Desktop\TEST "&"-"&timestamp&".xlsx"

objExcelWorkbook.SaveAs filePath

objExcelWorkbook.Close

objExcelDoc.Quit

end sub

Private Function copyObjectsToExcelSheet(qvDoc, aryExportDefinition) 'as Excel.Workbook

Dim i 'as Integer

Dim objExcelApp 'as Excel.Application

Dim objExcelDoc 'as Excel.Workbook

Set objExcelApp = CreateObject("Excel.Application")

objExcelApp.Visible = hide 'false if you want to hide Excel

objExcelApp.DisplayAlerts = false

 

Set objExcelDoc = objExcelApp.Workbooks.Add

Dim strSourceObject

Dim qvObjectId 'as String

Dim sheetName

Dim sheetRange

Dim pasteMode

Dim objSource

Dim objCurrentSheet

Dim objExcelSheet

for i = 0 to UBOUND(aryExportDefinition)

'// Get the properties of the exportDefinition array

qvObjectId = aryExportDefinition(i,0)

sheetName = aryExportDefinition(i,1)

sheetRange = aryExportDefinition(i,2)

pasteMode = aryExportDefinition(i,3)

              

Set objExcelSheet = Excel_GetSheetByName(objExcelDoc, sheetName)

if (objExcelSheet is nothing) then

Set objExcelSheet = Excel_AddSheet(objExcelApp, sheetName)

if (objExcelSheet is nothing) then

msgbox("No sheet could be created, this should not occur!!!")

end if

end if

              

    objExcelSheet.Select          

set objSource = qvDoc.GetSheetObject(qvObjectId)

Call objSource.GetSheet().Activate()

objSource.Maximize

qvDoc.GetApplication.WaitForIdle

if (not objSource is nothing) then

if (pasteMode = "image") then

Call objSource.CopyBitmapToClipboard()

else

Call objSource.CopyTableToClipboard(true) '// default & fallback

end if

Set objCurrentSheet = objExcelDoc.Sheets(sheetName)

objExcelDoc.Sheets(sheetName).Range(sheetRange).Select

objExcelDoc.Sheets(sheetName).Paste

if (pasteMode <> "image") then

With objExcelApp.Selection

            .WrapText = False

            .ShrinkToFit = False

End With                   

end if      

objCurrentSheet.Range("A1").Select  

end if

             

             

next  

Call Excel_DeleteBlankSheets(objExcelDoc)

'// Finally select the first sheet

objExcelDoc.Sheets(1).Select

'// Return value

Set copyObjectsToExcelSheet = objExcelDoc

end function

'// ________________________________________________________________

'// ****************************************************************

'// Internal function for getting the Excel sheet by sheetName

'// ****************************************************************

Private Function Excel_GetSheetByName(ByRef objExcelDoc, sheetName) 'as Excel.Sheet

For Each ws In objExcelDoc.Worksheets

If (trim(ws.Name) = Excel_GetSafeSheetName(sheetName)) then

Set Excel_GetSheetByName = ws

exit function

End If

Next

'// default return value

Set Excel_GetSheetByName = nothing

                           

End Function

'// ________________________________________________________________

Private Function Excel_GetSafeSheetName(sheetName)

'// can be max 31 characters long

retVal = trim(left(sheetName, 31))

Excel_GetSafeSheetName = retVal

End Function

'// ****************************************************************

'// Internal function for adding a new sheet

'// ****************************************************************

Private Function Excel_AddSheet(objExcelApplication, sheetName) ' as Excel.Sheet

'// add a sheet to the last position

objExcelApplication.Sheets.Add , objExcelApplication.Sheets(objExcelApplication.Sheets.Count)

Dim objNewSheet

Set objNewSheet = objExcelApplication.Sheets(objExcelApplication.Sheets.Count)

objNewSheet.Name = left(sheetName,31)

'// return the newly created sheet

Set Excel_AddSheet = objNewSheet

End function

'// ________________________________________________________________

'// ****************************************************************

'// Delete all empty sheets

'// ****************************************************************

Private Sub Excel_DeleteBlankSheets(ByRef objExcelDoc)

For Each ws In objExcelDoc.Worksheets

If (not HasOtherObjects(ws)) then

If objExcelDoc.Application.WorksheetFunction.CountA(ws.Cells) = 0 Then

On Error Resume Next

Call ws.Delete()

End If

End If

Next

  

End Sub

'// ________________________________________________________________

'// ****************************************************************

'// Helper function to determine if there are other objects placed

'// on the sheet ...

'// ****************************************************************

Public Function HasOtherObjects(ByRef objSheet) 'As Boolean

    Dim c

    If (objSheet.ChartObjects.Count > 0) Then

    HasOtherObjects = true

    Exit function

    End If

    If (objSheet.Pictures.Count > 0) Then

    HasOtherObjects = true

    Exit function

    End If

    If (objSheet.Shapes.Count > 0) Then

    HasOtherObjects = true

    Exit function

    End If

  

  

    HasOtherObjects = false

End Function

'//__________________________________________________________________

hope this helps

mrthomasshelby
Creator III
Creator III
Author

Hi Frank! Thanks for your time. I have tried this code in my macro but still getting the same error. Can I trouble you to try running the macro in the attached qvw and see if it works for you? Thanks a lot!

Frank_Hartmann
Master II
Master II

For me it works fine!

Aufnahme_2018_05_18_12_01_28_732.gif

olivierrobin
Specialist III
Specialist III

ypu may have to change this line

filePath = "C:\Users\Admin\Desktop\TEST "&"-"&timestamp&".xlsx" 

according to your installation

mrthomasshelby
Creator III
Creator III
Author

Thanks Frank. This works now for some weird reason it wasn't before. Appreciate your time and efforts!