Reputation: 608
I'm trying to create a workbook that is used for creating other .xlsm workbooks, but can't figure out how to get the modules I need so I can add them.
My code as it stands is below (modified from the answer given here: How to add excel 2010 macro programmatically)
The place I need help is in the ImportModules sub, by the comment 'LIST MODULES HERE
How can I get an array of modules that are in the current workbook?
Private Sub SVAmaker_Click()
Dim file As String
file = InputBox("SVA Planner file name", "Name", "Name")
Application.DefaultSaveFormat = xlOpenXMLWorkbookMacroEnabled
Workbooks.Add
ActiveWorkbook.SaveAs filename:=file
Dim WB As Workbook
WB = ActiveWorkbook
Call ImportModules(VBA.CStr(WB))
End Sub
Sub ImportModules(sWorkbookname As String)
Dim cmpComponents As VBIDE.VBComponents
Dim wbkTarget As Excel.Workbook
Set wbkTarget = Workbooks.Open(sWorkbookname)
If wbkTarget.VBProject.Protection = 1 Then
Debug.Print wbkTarget.Name & " has a protected project, cannot import module"
GoTo Cancelline
End If
Set cmpComponents = wbkTarget.VBProject.VBComponents
Dim vModules As Variant
'LIST MODULES HERE
Dim i As Integer
For i = LBound(vModules) To UBound(vModules)
cmpComponents.Import vModules(i)
Next i
Cancelline:
If wbkTarget.FileFormat = xlOpenXMLWorkbook Then
wbkTarget.SaveAs wbkTarget.Name, xlOpenXMLWorkbookMacroEnabled
wbkTarget.Close SaveChanges:=False
Else
wbkTarget.Close SaveChanges:=True
End If
Set wbkTarget = Nothing
End Sub
Upvotes: 3
Views: 10680
Reputation: 350
JChristen asked for a list of those modules
I'd create a collection, based on gizlmo's proposal:
Dim vbcomp As VBComponent
Dim modules as Collection
set modules = new Collection
For Each vbcomp In ThisWorkbook.VBProject.VBComponents
'if normal or class module
If ((vbcomp.Type = vbext_ct_StdModule) _
Or _
(VBComp.Type = vbext_ct_ClassModule)) Then
modules.add VBcomp.name
End If
Next vbcomp
Later on you can use this collection like this:
Dim module as Variant
for each module in modules
' e.g. importing the module
import module
next module
hope it helps
Upvotes: 7
Reputation: 29421
Why not simply make a copy of the "master" workbook you'd import modules from
Option Explicit
Private Sub SVAmaker_Click()
Dim fso As New FileSystemObject
Dim myFile As file
Dim fileName As String
fileName = InputBox("SVA Planner file name", "Name", "Name") & ".xlsm"
Set myFile = fso.GetFile(ActiveWorkbook.FullName)
fso.CopyFile myFile, myFile.ParentFolder & "\" & fileName
End Sub
from here on you have a new workbook with all modules (and sheets) already there.
should you need to delete some worksheets you juts open it and act with "plain" VBA Excel Model Object code
in order to use FileSytemObject API, you need to reference "Microsoft Scripting Runtime"
Upvotes: 0
Reputation: 19857
This code should help. It will export all modules to the desktop, create a new workbook and import them all into it.
Public Sub ExportImportAllModules()
Dim srcVBA As Variant
Dim tgtVBA As Variant
Dim srcModule As Variant
Dim wrkBk As Workbook
Dim sDeskTop As String
On Error GoTo ERROR_HANDLER
Application.DisplayAlerts = False
Set srcVBA = ThisWorkbook.VBProject
sDeskTop = CreateObject("WScript.Shell").specialfolders("Desktop")
Set wrkBk = Workbooks.Add(xlWBATWorksheet) 'New workbook with 1 sheet.
Set tgtVBA = wrkBk.VBProject
For Each srcModule In srcVBA.vbComponents
'There may be a better way to check it's a module -
'I'm making it up as I go along.
If srcModule.Type = 1 Then 'vbext_ct_StdModule
srcModule.Export sDeskTop & "\" & srcModule.Name
tgtVBA.vbComponents.Import sDeskTop & "\" & srcModule.Name
Kill sDeskTop & "\" & srcModule.Name
End If
Next srcModule
Application.DisplayAlerts = True
On Error GoTo 0
Exit Sub
ERROR_HANDLER:
Select Case Err.Number
Case Else
MsgBox "Error " & Err.Number & vbCr & _
" (" & Err.Description & ") in procedure ExportImportAllModules."
Err.Clear
Application.EnableEvents = True
End Select
End Sub
Upvotes: 0
Reputation: 1922
You can loop through all modules with an easy For Each Loop. Requires a Reference to "Microsoft Visual Basic for Applications Extensibility"!
Dim vbcomp As VBComponent
For Each vbcomp In ThisWorkbook.VBProject.VBComponents
'if normal Module
If vbcomp.Type = vbext_ct_StdModule Then
'Do Stuff
End If
Next vbcomp
with .Type you can check the type of the Module(Form, Normal Module, ClassModule etc)
Upvotes: 1
Reputation: 577
you can go through the modules like this. Create some collection and then iterate over all objects in VBComponents of VBProject (Value of type for module is 1):
'declare some collection, which will contain modules
For Each vbc In ThisWorkbook.VBProject.VBComponents
if vbc.Type = 1 then
'add to temporary collection ... for example for name, use vbc.name
end if
Next
Upvotes: 1