VBA - working with data videos | How do I loop through worksheets in a closed workbook with VBA?

Posted by Andrew Gould on 09 April 2021


Looping through the collection of worksheets in a workbook is a standard technique in Excel VBA and easy to accomplish when the workbook is open. Did you know that you can do the same thing when the workbook is closed? This video explains how to do this using the ActiveX Data Objects library. You'll learn how to create a connection object and construct a connection string to talk to the closed Excel file. You'll learn how to query the schema of the workbook to return a list of the worksheets and loop through this list to read the name of each sheet. You'll also learn how to create a recordset object and populate it with data using an SQL Select statement. As a bonus you'll learn about the SQL Union All statement to select data from multiple tables at the same time and how to add criteria to a query using the Where clause.

See our full range of VBA training resources, or test your knowledge of VBA with one of our VBA skills assessment tests.

This video has the following accompanying files:

File name Type Description
Loop Through Worksheets in a Closed Workbook.xlsm Excel workbook with macros
Movies By Year.xlsx Excel workbook

Click to download a zipped copy of the above files.

There are no exercises for this video.

Making a  video bigger

You can increase the size of your video to make it fill the screen like this:

View full screen

Play your video (the icons shown won't appear until you do), then click on the full screen icon which appears as shown at its bottom right-hand corner.

 

When you've finished viewing a video in full screen mode, just press the Esc key to return to normal view.

Improving the quality of a video

To improve the quality of a video, first click on the Settings icon:

Settings icon

Make sure you're playing your video so that the icons shown appear, then click on this gear icon at the bottom right-hand corner.

 

Choose to change the video quality:

Video quality

Click on Quality as shown to bring up the submenu.

 

The higher the number you choose, the better will be your video quality (but the slower the connection speed):

Connection speed

Don't choose the HD option unless you have a fast enough connection speed to support it!

 

Is your Wise Owl speaking too slowly (or too quickly)?  You can also use the Settings menu above to change your playback speed.

This page has 2 threads Add post
11 Feb 22 at 10:50

Hi Andrew!

Great video! Quick question though as I am fairly new to coding, how can I utilise the Sheet tabs of the closed workbook instead of the Sheet Names? I've got a closed workbook that I would like to import in order but if I use the names it just doesn't work as intended.

Example: Sheet Names: Hello, Hello (1), Hello (2) etc. (The space between the () and the original name changes the order of importing.

 

Also follow up question, I would like to extract a specific range within these sheets. The first sheet "Hello" I want range ("A12:P10000") and the rest range("A8:P10000"). I was wondering if it's possible while looping through the sheets.

Appreciate the help here and great tutorials!

Regards,

Jocelyn

13 Feb 22 at 11:42

Thank you so much Andrew! I'll give it a go and will let you know how it turns out! Appreciate all the help I just received!

14 Feb 22 at 07:46

Good luck!

Jocaqu  
18 Feb 22 at 13:39

You're the greatest! Thanks!

Andrew G  
18 Feb 22 at 08:56

Hi Jocelyn, happy to hear that you got it working!

You can count the number of sheets by adding another loop through the rsSheets recordset before the loop to build the SQL string. So, after you've used the OpenSchema method to populate the rsSheets variable you can do this:


    Do Until rsSheets.EOF
        SheetCount = SheetCount + 1
        rsSheets.MoveNext
    Loop
    
    Debug.Print SheetCount
    rsSheets.MoveFirst
 

It would be nice if you could use the RecordCount property of the recordset to get the number of rows but sadly that property only works when using client side cursors and the OpenSchema method doesn't support client side cursors.

I hope it helps!

Jocaqu  
17 Feb 22 at 09:45

Hi Andrew,

Just wanted to inform you that I managed and also to thank you for the inspiration. I simply made a sheet count which temporarily opens the file to count the sheets and then insert that sheet count into a loop when a is bigger than one then i = 2 to a and insert that into Hello (i) and loop through the dataset with the target range being the next available row.

One last question, is there a way to import the sheet count without opening the file?

 

12 Feb 22 at 09:42

Hi Jocelyn!

The OpenSchema method always returns tables sorted by name and I don't know a way around this.

You could apply sorting to your results after importing them. If you're importing everything into a single worksheet you could apply the Sort method to the range https://docs.microsoft.com/en-us/office/vba/api/excel.range.sort If you're importing data into different worksheets you could apply the Move method to the "Hello" sheet to place it at the beginning https://docs.microsoft.com/en-us/office/vba/api/excel.worksheet.move

Alternatively, if you can't reliably sort things after importing you could resort to the slower method of opening the source workbook and looping through the worksheets collection (this follows the tab order from left to right) https://youtu.be/jLepKYcFvxA

If you need to reference a specific range of cells on a worksheet you might find this chapter of this video useful https://youtu.be/FNjTCwV7VhM?t=330
You can use an If statement to check if the SheetName is "Hello" or not and select from the appropriate range of cells.

I hope that helps!

27 Jun 21 at 21:23

Hey Andrew!

I started following you on YouTube, but finally found your site. I really enjoy what you've been able to produce so far. It's helped me a ton in my current role. 
 

My question is...how do I reference an excel table in the sql select statement part of the code?  I also tried a name range, but was unsuccessful. Any help would be appreciated!  
 

Thanks! 

28 Jun 21 at 07:00

Hi there, what an Excel-lent user name!

Sadly you can't reference Excel table names in an SQL query, but you can reference a range name like so:

SELECT * FROM [MyRangeName]

Make sure not to use the $ sign as you're not referencing a worksheet.

You might find this YouTube playlist useful https://youtube.com/playlist?list=PLNIs-AWhQzckUd5i0E1xeSFeBAonYIurK  Part 58.1 includes information on referencing range names.

I hope that helps!

29 Jun 21 at 23:56

Thank you very much!  I'm also trying to use an input box result in my sql query. It's a number, but when I step through the process my input box value shows it at "123456789". Would the quotation cause an issue in the query?  
 

Thanks!

Andrew G  
30 Jun 21 at 07:58

Hi there,

When you say that the value is showing with quotes do you mean in the Locals window? A VBA inputbox always returns a string value so it will always be displayed with " " around it in tools like the Locals window. The quotes won't be included if you concatenate that value into your query string (I assume that's what you're trying to do?). Remember that you can always print your SQL string to the Immediate window to check that it's correct before you run it.

Just in case it helps, we have a module on working with VBA input boxes which you can find here