Skip to content

VBS - Import Excel Code

Source: https://github.com/cavo789/vbs_xls_import_code

Option Explicit

Private Const cDebugMode = True

Class clsMSExcel

    Private oApplication
    Private sFileName
    Private bVerbose, bEnableEvents, bDisplayAlerts, bScreenUpdating

    Private bAppHasBeenStarted

    Public Property Let verbose(bYesNo)
        bVerbose = bYesNo
    End Property

    Public Property Let EnableEvents(bYesNo)
        bEnableEvents = bYesNo

        If Not (oApplication Is Nothing) Then
            oApplication.EnableEvents = bYesNo
        End If
    End Property

    Public Property Let DisplayAlerts(bYesNo)
        bDisplayAlerts = bYesNo

        If Not (oApplication Is Nothing) Then
            oApplication.DisplayAlerts = bYesNo
        End If

    End Property

    Public Property Let ScreenUpdating(bYesNo)
        bScreenUpdating = bYesNo

        If Not (oApplication Is Nothing) Then
            oApplication.ScreenUpdating = bYesNo
        End If

    End Property

    Public Property Let FileName(ByVal sName)
        sFileName = sName
    End Property

    Public Property Get FileName
        FileName = sFileName
    End Property

    ' Make oApplication accessible
    Public Property Get app
        Set app = oApplication
    End Property

    Private Sub Class_Initialize()
        bVerbose = False
        bAppHasBeenStarted = False
        bEnableEvents = False
        bDisplayAlerts = False
        bScreenUpdating = True
        Set oApplication = Nothing
    End Sub

    Private Sub Class_Terminate()
        Set oApplication = Nothing
    End Sub

    ' --------------------------------------------------------
    ' Initialize the oApplication object variable : get a pointer
    ' to the current Excel.exe app if already in memory or start
    ' a new instance.
    '
    ' If a new instance has been started, initialize the variable
    ' bAppHasBeenStarted to True so the rest of the script knows
    ' that Excel should then be closed by the script.
    ' --------------------------------------------------------
    Public Function Instantiate()

        If (oApplication Is Nothing) Then

            On error Resume Next

            Set oApplication = GetObject(,"Excel.Application")

            If (Err.number <> 0) or (oApplication Is Nothing) Then
                Set oApplication = CreateObject("Excel.Application")
                ' Remember that Excel has been started by
                ' this script ==> should be released
                bAppHasBeenStarted = True
            End If

            oApplication.EnableEvents = bEnableEvents
            oApplication.DisplayAlerts = bDisplayAlerts
            oApplication.ScreenUpdating = bScreenUpdating

            Err.clear

            On error Goto 0

        End If

        ' Return True if the application was created right
        ' now
        Instantiate = bAppHasBeenStarted

    End Function

    ' --------------------------------------------------------
    ' Be sure Excel is visible
    ' --------------------------------------------------------
    Public Sub MakeVisible

        Dim objShell

        If Not (oApplication Is Nothing) Then

            With oApplication

                .Application.Visible = True
                .Application.DisplayFullScreen = False

                .WindowState = -4137 ' xlMaximized

            End With

            Set objShell = CreateObject("wScript.Shell")
            objShell.appActivate oApplication.Caption
            Set objShell = Nothing

        End If

    End Sub

    ' --------------------------------------------------------
    ' Quit Excel
    ' --------------------------------------------------------
    Public Sub Quit()
        If not (oApplication Is Nothing) Then
            oApplication.Quit
        End If
    End Sub

    ' --------------------------------------------------------
    ' Open a standard Excel file and allow to specify if the
    ' file should be opened in a read-only mode or not
    ' --------------------------------------------------------
    Public Sub Open(bReadOnly)

        If Not (oApplication Is Nothing) Then

            If bVerbose Then
                wScript.echo "Open " & sFileName & _
                    " (clsMSExcel::Open)"
            End If

            ' False = UpdateLinks
            oApplication.Workbooks.Open sFileName, False, _
                bReadOnly

        End If

    End sub

    ' --------------------------------------------------------
    ' Close the active workbook
    ' --------------------------------------------------------
    Public Sub CloseFile(sFileName)

        Dim wb
        Dim I
        Dim objFSO
        Dim sBaseName

        If Not (oApplication Is Nothing) Then

            Set objFSO = CreateObject("Scripting.FileSystemObject")

            If (sFileName = "") Then
                If Not (oApplication.ActiveWorkbook Is Nothing) Then
                    sFileName = oApplication.ActiveWorkbook.FullName
                End If
            End If

            If (sFileName <> "") Then

                If bVerbose Then
                    wScript.echo "Close " & sFileName & _
                        " (clsMSExcel::CloseFile)"
                End If

                ' Only the basename and not the full path
                sBaseName = objFSO.GetFileName(sFileName)

                On Error Resume Next
                Set wb = oApplication.Workbooks(sBaseName)
                If Not (err.number = 0) Then
                    ' Not found, workbook not loaded
                    Set wb = Nothing
                Else
                    If bVerbose Then
                        wScript.echo "    Closing " & sBaseName & _
                            " (clsMSExcel::CloseFile)"
                    End If
                    ' Close without saving
                    wb.Close False
                End If

                On Error Goto 0

            End If

            Set objFSO = Nothing

        End If

    End Sub

    ' --------------------------------------------------------
    ' Save the active workbook on disk
    ' --------------------------------------------------------
    Public Sub SaveFile()

        Dim wb, objFSO

        ' If Excel isn't loaded or has no active workbook, there
        ' is thus nothing to save.
        If Not (oApplication Is Nothing) Then

            Set objFSO = CreateObject("Scripting.FileSystemObject")
            Set wb = oApplication.Workbooks(objFSO.GetFileName(sFileName))

            If Not (wb is Nothing) Then

                If (bVerbose) Then
                    wScript.echo "Save file " & sFileName & _
                        " (clsMSExcel::SaveFile)"
                End If

                If (wb.FullName = sFileName) Then
                    wb.Save
                Else
                    ' Don't specify extension because if we've opened
                    ' a .xlsm file and save the file elsewhere, we need
                    ' to keep the same extension
                    wb.SaveAs sFileName
                End If
            End If

            Set wb = Nothing
            Set objFSO = Nothing

        End If

    End Sub

    ' --------------------------------------------------------
    ' Check if a specific file is already opened in Excel
    ' This function will return True if the file is already loaded.
    ' Documentation : https://github.com/cavo789/vbs_scripts/blob/master/src/classes/MSExcel.md#isloaded
    ' --------------------------------------------------------
    Public Function IsLoaded()

        Dim bLoaded, bShouldClose
        Dim bCheckAddins2
        Dim I, J

        bLoaded = false

        If (oApplication Is Nothing) Then
            bShouldClose = Instantiate()
        End If

        On Error Resume Next

        If bVerbose Then
            wScript.echo "Check if " & sFileName & _
                " is already loaded (clsMSExcel::IsLoaded)"
        End If

        If (Right(sFileName, 5) = ".xlam") Then

            ' The AddIns2 collection only exists since MSOffice
            ' 2014 (version 14)
            On Error Resume Next
            J = oApplication.AddIns2.Count
            bCheckAddins2 = (Err.Number = 0)
            On Error Goto 0

            If (bCheckAddins2) then

                J = oApplication.AddIns2.Count

                If J > 0 Then
                    For I = 1 To J
                        If (StrComp(oApplication.AddIns2(I).FullName,sFileName,1)=0) Then
                            bLoaded = True
                            Exit For
                        End If
                    Next ' For I = 1 To J
                End If

            End If ' If (oApplication.version >=14) then

        Else ' If (Right(sFileName, 5) = ".xlam") Then

            ' It's a .xls, .xlsm, ... file, not an AddIn
            J = oApplication.Workbooks.Count

            If J > 0 Then
                For I = 1 To J
                    If (StrComp(oApplication.Workbooks(I).FullName,sFileName,1)=0) Then
                        bLoaded = True
                        Exit For
                    End If
                Next ' For I = 1 To J
            End If ' If J > 0 Then

        End If ' If (Right(sFileName, 5) = ".xlam") Then

        On Error Goto 0

        ' Quit Excel if it was started here, in this script
        If bShouldClose then
            oApplication.Quit
            Set oApplication = Nothing
        End If

        If bVerbose Then
            wScript.echo "  " & bLoaded & " (clsMSExcel::IsLoaded)"
        End If

        IsLoaded = bLoaded

    End Function

End Class

' -------------------
' --- ENTRY POINT ---
' -------------------

Dim cExcel
Dim oApplication
Dim objFSO, objFolder, objFiles, objFile
Dim sFoldername, sFileName

' --------------------------------------------------------
'
' Variables initialization
'
' --------------------------------------------------------
Private Sub initialization()

    Set cExcel = Nothing
    Set objFSO = CreateObject("Scripting.FileSystemObject")

End Sub

' --------------------------------------------------------
'
' Finalization
'
' --------------------------------------------------------
Private Sub finalize()

    ' Restore properties
    cExcel.EnableEvents = True
    cExcel.ScreenUpdating = True
    cExcel.DisplayAlerts = True

    ' And release our Excel object
    Set cExcel = Nothing
    Set objFSO = Nothing

End Sub

' --------------------------------------------------------
'
' Instanciate Excel, create the cExcel object and make
' Excel visible
'
' --------------------------------------------------------
Private Sub instantiateExcel()

    If (cExcel Is Nothing) Then

        On Error Resume Next

        ' Due to Excel's security, Excel should be started manually ("by a human")
        ' to allow to access to VBE features like importing a VBA module through VBS.
        ' GetObject() will allow us to detect if Excel is already running.
        Set oApplication = GetObject(,"Excel.Application")

        If (oApplication Is Nothing) Then

            ' Not yet running, show an error message and quit
            Set oApplication = Nothing
            Call dieExcelNotOpened()

        End If

        On Error Goto 0

        ' Yes, Excel is already running, we can continue

        Set oApplication = Nothing

        ' Instantiate our object and run initialization code
        Set cExcel = New clsMSExcel

        cExcel.verbose = cDebugMode

        cExcel.Instantiate

        cExcel.EnableEvents = False
        cExcel.DisplayAlerts = False
        cExcel.ScreenUpdating = True

        cExcel.MakeVisible

    End If

End sub

' --------------------------------------------------------
'
' Process a file
'
' The wFile parameter is the position of the file being
' processed in the arrInputFiles array.
'
' --------------------------------------------------------
Private Sub processFile(sFileName, sSourcePath)

    Dim oMacro, oVBComp
    Dim wb
    Dim sBaseName

    ' Process the file
    If Not (sFileName = "") Then

        wScript.Echo "Process " & sFileName

        cExcel.FileName = sFileName

        ' Open the file
        cExcel.Open(False)

        ' sFileName is the full name (with paths included)
        ' Retrieve only the file name without path
        sBaseName = objFSO.GetFileName(sFileName)

        ' Be sure that the opened workbook is the active one
        cExcel.app.Workbooks(sBaseName).Activate

    Else

        ' No file to open ? Ok, create a new workbook
        Set wb = cExcel.app.Workbooks.Add
        sFileName = wb.FullName
        wb.Activate

    End If

    wScript.echo " Import files from " & sSourcePath
    wScript.echo " into " & sFileName
    wScript.echo ""

    With cExcel.app

        Set oVBComp = .VBE.ActiveVBProject.VBComponents

        Set objFolder = objFSO.GetFolder(sSourcePath)
        Set objFiles = objFolder.Files

        For Each objFile in objFiles
            If (objFSO.GetExtensionName(objFile.Name) = "cls") Or _
                (objFSO.GetExtensionName(objFile.Name) = "frm") Or _
                (objFSO.GetExtensionName(objFile.Name) = "bas") Then

                sBaseName = objFSO.GetBaseName(objFile.Name)

                wScript.echo " Import " & sBaseName

                ' remove previous version if any
                On error Resume Next
                oVBComp.Remove .VBE.ActiveVBProject.VBComponents(sBaseName)
                On error Goto 0

                Set oMacro = oVBComp.Import(objFile.path)

            End If
        Next

        wScript.echo ""
        wScript.echo " All Forms, Modules, and Classes imported"
        wScript.echo ""

        '.ActiveWorkbook.Save 

        ' Fake
        .ActiveWorkbook.Saved = true 

    End with

    ' cExcel.CloseFile(cExcel.app.ActiveWorkbook.Name)

End Sub

Sub ShowHelp()

    wScript.echo " ============================"
    wScript.echo " = Excel Import Code script ="
    wScript.echo " ============================"
    wScript.echo ""
    wScript.echo " You need to tell where source file can be retrieved. Absolute or relative path."
    wScript.echo ""
    wScript.echo " This script will open Excel, create a new workbook and import all sources in that new file."
    wScript.echo ""
    wScript.echo "     " & wScript.ScriptName & " src\"
    wScript.echo ""
    wScript.echo " If you don't want to create a new workbook but use an existing one, "
    wScript.echo " just specify his name as the second parameter."
    wScript.echo ""
    wScript.echo "      " & wScript.ScriptName & " src\ application.xlsm"
    wScript.echo ""
    wScript.quit

End sub

' --------------------------------------------------------
'
' ENTRY POINT
'
' --------------------------------------------------------

    ' Get the first argument
    If (wScript.Arguments.Count = 0) Then

        Call ShowHelp

    Else

        Call initialization() 

        ' Folder where sources are located
        sFoldername = Trim(Wscript.Arguments.Item(0))        
        sFoldername = objFso.GetAbsolutePathName(sFoldername)

        If Not (objFSO.FolderExists(sFoldername)) Then

            wScript.echo "Error, the folder " & sFoldername & " didn't exists."
            wScript.echo "Please make sure to mention an existing folder."
            wScript.Quit

        End If

        sFileName = ""

        If (wScript.Arguments.Count = 2) Then 

            sFileName = Trim(Wscript.Arguments.Item(1))
            sFileName = objFso.GetAbsolutePathName(sFileName)

            If Not (objFSO.FileExists(sFileName)) Then
                wScript.echo "Error, the file " & sFileName & " didn't exists."
                wScript.echo "Please make sure to mention an existing file."
                wScript.Quit
            End If
        End if

        ' Instantiate Excel
        Call instantiateExcel()

        'Call processFile("C:\temp\vbs_xls_import\demo.xlsm", "C:\temp\vbs_xls_import\src\")
        Call processFile(sFileName, sFolderName)

        call finalize()

    End if

Then, use the helper CMD script to call this Visual Basic script with a single parameter/argument for the excel file to export from:

cscript excel_import_code.vbs demo.xlsm //nologo
pause

See Also: VBS - Export Excel Code

Backlinks:

list from [[VBS - Excel Import Code]] AND -"Changelog"