More ways to reference Excel workbooks and sheets using VBA

Susan Harkins writes a column for TechRepublic with Office tips, including VBA code samples. In 10 ways to reference Excel workbooks and sheets using VBA, she posts a few methods for manipulating worksheets and workbooks through Excel VBA. I'd like to expand on a few of her samples.

1: Reference the active workbook

Her code:

Sub CloseActiveWBNoSave()
  'Close the active workbook without saving.
  ActiveWorkbook.Close False
End Sub

Sub CloseActiveWBWithSave()
  'Close the active workbook and save.
  ActiveWorkbook.Close True
End Sub

Sub CloseActiveWB()
  'Close the active workbook.
  'Let user choose whether to save.
  ActiveWorkbook.Close
End Sub

She mentions that these could be combined into a single function. It would go something like

Function CloseActiveWB(Optional bSave As Variant)
' close active workbook
' bSave should be True to save changes,
' False to discard changes,
' blank to prompt user

Dim wb As Excel.Workbook

  Set wb = Excel.ActiveWorkbook

  If IsMissing(bSave) Then
    wb.Close
  Else
    wb.Close SaveChanges:=bSave
  End If
End Function

She mentions Select Case, but I'm not sure how you would use it in this case.

The next two samples return the path and filename of the active workbook and the workbook that contains the code. She uses:

Function GetActiveWB() As String
  GetActiveWB = ActiveWorkbook.Path & "\" & ActiveWorkbook.Name
End Function
Function GetThisWB() As String
  GetThisWB = ThisWorkbook.Path & "\" & ThisWorkbook.Name
End Function

But the Workbook.FullName Property returns this information in one go. So we can rewrite these as

Function GetActiveWB() As String
  GetActiveWB = ActiveWorkbook.FullName
End Function
Function GetThisWB() As String
  GetThisWB = ThisWorkbook.FullName
End Function

Note that if the workbook isn't saved, FullName returns an empty String ("").


3: Reference workbooks in the Workbooks collection

Susan's code for opening all the workbooks in a folder is:

Sub OpenAllWB()
  'Open all workbooks in specified folder.
  Dim i As Integer
  With Application.FileSearch
    .LookIn = "C:\Examples"
    .FileType = msoFileTypeExcelWorkbooks
      'There are wb's
      If .Execute > 0 Then
        For i = 1 To .FoundFiles.Count
          Workbooks.Open (.FoundFiles(i))
        Next i
      'There are no wb's
      Else
        MsgBox "There are no workbooks to open", vbOKOnly
      End If
  End With
End Sub

Problem is, FileSearch has been deprecated in Excel 2007. I'd use the Dir function instead, with a technique I describe in List matching files in a directory and Attach files in a folder to one email.


4: Explicitly reference a workbook

To activate a workbook, Susan provides the following code:

Function ActivateWB(wbname As String)
  'Open wbname.
  Workbooks(wbname).Activate
End Function

I'd prefer to return a reference to the workbook, like this:

Function ActivateWB(wbname As String) As Excel.Workbook
'Open wbname.
  Set ActivateWB = Workbooks(wbname)
  ActivateWB.Activate
End Function

Sample usage:

Sub tst()
Dim wb As Excel.Workbook

  Set wb = ActivateWB("book1")
  ' test out returned reference
  Debug.Print wb.Name
End Sub

Update 9/4/2009 2:00 PM: Just realized I forgot to link to Susan Harkins' TechRepublic blog. Here's the feed: Microsoft Office

Related Articles:

About JP

I'm just an average guy who writes VBA code for a living. This is my personal blog. Excel and Outlook are my thing, with a sprinkle of Access and Word here and there. Follow this space to learn more about VBA. Keep Reading »

Share This Article:

Share and bookmark this articledelicious buttonfacebook buttonlinkedin buttonstumbleupon buttontwitter button

comment bubble 6 Comments:

  1. Peder Schmedling writes:

    Interesting post JP :-)

    Referring to the CloseActiveWB() function there is a comment line I don't think should be there "blank to prompt user", that's actually wrong.. Blank (ie. not passing anything) would result in close without changes.

    Also, I'll suggest the following improvements of the function: convert to sub (it doesn't return anything, use scope if you want to hide it from the run macro dialog), avoid using variants as well as implement default value for optional parameters the proper way:

    Private Sub CloseActiveWB(Optional bSave As Boolean = False)
    ' Close active workbook
    ' bSave should be True to save changes,
    ' False to discard changes (default)
        Dim wb As Excel.Workbook
    
        Set wb = Application.ActiveWorkbook
        wb.Close SaveChanges:=bSave
    End Sub

    What do you think?

    I also changed Excel.ActiveWorkbook to Application.ActiveWorkbook, ActiveWorkbook is a child object of the Application class, not the Excel library.. Not sure why Excel.ActiveWorkbook works? Must be because ActiveWorkbook also is a member of the hidden class Global..

    • JP writes:

      Thanks for sharing, Peder. I'd go with the Help file on this one, it's actually correct.

      The SaveChanges flag for the Close method of the Workbook object is optional.

      True = Saves the changes to the workbook. If there is not yet a file name associated with the workbook, then FileName is used. If FileName is omitted, the user is asked to supply a file name.

      False = Does not save the changes to this file.
      Omitted = Displays a dialog box asking the user whether or not to save changes.

      If you call the procedure I wrote and omit the bSave parameter, you'll get the following dialog:

      As far as Application vs. Excel, I guess I'm used to writing the application name. But it shouldn't matter.

      • Peder Schmedling writes:

        Hehe, seems like I was a bit quick on the trigger on this one.. You are right and I am wrong :-P

        Even though, the thing I don't like about the procedure is the variant parameter; you can pass anything to the function. Just to test I passed the Application object as the bSave parameter when calling the function and it didn't fail :-P

        • JP writes:

          I agree with you, but it's the only way to check if the parameter is missing. You could always do a Typename check or use the CBool function to check if the passed value is really boolean.

  2. Peder Schmedling writes:

    Oh, forgot bbCode for the VBA source code :-P

  3. Peder Schmedling writes:

    Here's my take on an 2007-friendly alternative to the OpenAllWB() procedure (a bit laborious though):

    '******************************************************************************
    '* Author    : Peder Schmedling
    '* Purpose   :
    '*  This procedure opens all Excel files found within a given directory.
    '* Input     :
    '*  strFolder, the folder to look for Excel files within
    '******************************************************************************
    Sub OpenAllWBInFolder(strFolder As String)
        On Error GoTo ErrorHandler:
        Dim objFSO As Object
        Dim objDir As Object
        Dim objFile As Object
        Dim lngWbCnt As Long
    
        Set objFSO = CreateObject("Scripting.FileSystemObject")
        Set objDir = objFSO.GetFolder(strFolder)
        lngWbCnt = Workbooks.Count
    
        'Loop all files in given directory, looking for Excel files
        For Each objFile In objDir.Files
            If objFile.Type Like "Microsoft Office Excel*Worksheet" Then
                Workbooks.Open objFile.Path
            End If
        Next objFile
    
        'Warn the user if no files was found to open
        If lngWbCnt = Workbooks.Count Then
            MsgBox "There are no workbooks to open", vbOKOnly + vbInformation, _
             "OpenAllWBInFolder"
        End If
    
    ExitProc:
        On Error Resume Next
        Set objFSO = Nothing
        Set objDir = Nothing
        Set objFile = Nothing
        Exit Sub
    
    ErrorHandler:
        Select Case Err.Number
            Case 5, 76
                ' 5 = Invalid procedure call or argument
                '76 = Path not found
                MsgBox "Invalid path specified", vbOKOnly + vbInformation, _
                 "OpenAllWBInFolder"
            Case 429 'Can't create ActiveX
                'Microsoft scripting runtime probably not installed
                MsgBox "'Microsoft scripting runtime' must be installed in order" _
                 & vbCr & "for this procedure to work.", _
                 vbOKOnly + vbInformation, "OpenAllWBInFolder"
            Case Else
                MsgBox "[" & Err.Source & "]" & vbCrLf & "An unexpected run-time" _
                 & " error occured '" & CStr(Err.Number) & "':" & vbCrLf _
                 & vbCrLf & Err.Description, vbExclamation, "OpenAllWBInFolder", _
                 Err.HelpFile, Err.HelpContext
        End Select
        Resume ExitProc:
    End Sub
    
Comments on this article are closed. Why?

Site last updated: February 12, 2012