Bottom line: Learn how to create macros that apply filters to ranges and Tables with the AutoFilter method in VBA. The post contains links to examples for filtering different data types including text, numbers, dates, colors, and icons.
Skill level: Intermediate
Download the File
The Excel file that contains the code can be downloaded below. This file contains code for filtering different data types and filter types.
Writing Macros for Filters in Excel
Filters are a great tool for analyzing data in Excel. For most analysts and frequent Excel users, filters are a part of our daily lives. We use the filter drop-down menus to apply filters to individual columns in a data set. This helps us tie out numbers with reports and do investigative work on our data.
Filtering can also be a time consuming process. Especially when we are applying filters to multiple columns on large worksheets, or filtering data to then copy/paste it to other worksheets or workbooks.
This article explains how to create macros to automate the filtering process. This is an extensive guide on the AutoFilter method in VBA.
I also have articles with examples for different filters and data types including: blanks, text, numbers, dates, colors & icons, and clearing filters.
The Macro Recorder is Your Friend (& Enemy)
We can easily get the VBA code for filters by turning on the macro recorder, then applying one or more filters to a range/Table.
Here are the steps to create a filter macro with the macro recorder:
- Turn the macro recorder on:
- Developer tab > Record Macro.
- Give the macro a name, choose where you want the code saved, and press OK.
- Apply one or more filters using the filter drop-down menus.
- Stop the recorder.
- Open the VB Editor (Developer tab > Visual Basic) to view the code.
If you’ve already used the macro recorder for this process, then you know how useful it can be. Especially as our filter criteria gets more complex.
The code will look something like the following.
Sub Filters_Macro_Recorder()
'
' Filters_Macro_Recorder Macro
'
'
ActiveSheet.ListObjects("tblData").Range.AutoFilter Field:=4, Criteria1:= _
"Product 2"
ActiveSheet.ListObjects("tblData").Range.AutoFilter Field:=4
ActiveSheet.ListObjects("tblData").Range.AutoFilter Field:=5, Criteria1:= _
">=500", Operator:=xlAnd, Criteria2:="<=1000"
End Sub
We can see that each line uses the AutoFilter method to apply the filter to the column. It also contains information about the criteria for the filter.
This is where it can get complex, confusing, and frustrating. It can be difficult to understand what the code means when trying to modify it for a different data set or scenario. So let’s take a look at how the AutoFilter method works.
The AutoFilter Method Explained
The AutoFilter method is used to clear and apply filters to a single column in a range or Table in VBA. It automates the process of applying filters through the filter drop-down menus, and does all that work for us. 🙂
It can be used to apply filters to multiple columns by writing multiple lines of code, one for each column. We can also use AutoFilter to apply multiple filter criteria to a single column, just like you would in the filter drop-down menu by selecting multiple check boxes or specifying a date range.
Writing AutoFilter Code
Here are step-by-step instructions for writing a line of code for AutoFilter
Step 1 : Referencing the Range or Table
The AutoFilter method is a member of the Range object. So we must reference a range or Table that the filters are applied to on the sheet. This will be the entire range that the filters are applied to.
The following examples will enable/disable filters on range B3:G1000 on the AutoFilter Guide sheet.
Sub AutoFilter_Range()
'AutoFilter is a member of the Range object
'Reference the entire range that the filters are applied to
'AutoFilter turns filters on/off when no parameters are specified.
Sheet1.Range("B3:G1000").AutoFilter
'Fully qualified reference starting at Workbook level
ThisWorkbook.Worksheets("AutoFilter Guide").Range("B3:G1000").AutoFilter
End Sub
Here is an example using Excel Tables.
Sub AutoFilter_Table()
'AutoFilters on Tables work the same way.
Dim lo As ListObject 'Excel Table
'Set the ListObject (Table) variable
Set lo = Sheet1.ListObjects(1)
'AutoFilter is member of Range object
'The parent of the Range object is the List Object
lo.Range.AutoFilter
End Sub
The AutoFilter method has 5 optional parameters, which we’ll look at next. If we don’t specify any of the parameters, like the examples above, then the AutoFilter method will turn the filters on/off for the referenced range. It is toggle. If the filters are on they will be turned off, and vice-versa.
Ranges or Tables?
Filters work the same on both regular ranges and Excel Tables.
My preferred method is to use Tables because we don’t have to worry about changing range references as the table grows or shrinks. However, the code will be the same for both objects. The rest of the code examples use Excel tables, but you can easily modify this for regular ranges.
The 5 (or 6) AutoFilter Paramaters
The AutoFilter method has 5 (or 6) optional parameters that are used to specify the filter criteria for a column. Here is a list of the parameters.
Name | Req/Opt | Description |
---|---|---|
Field | Optional | The number of the column within the filter range that the filter will be applied to. This is the column number within the filter range, NOT the column number of the worksheet. |
Criteria1 | Optional | A string wrapped in quotation marks that is used to specify the filter criteria. Comparison operators can be included for less than or greater than filters. Many rules apply depending on the data type of the column. See examples below. |
Operator | Optional | Specifies the type of filter for different data types and criteria by using one of the XlAutoFilterOperator constants. See this MSDN help page for a detailed list, and list in macro examples below. |
Criteria2 | Optional | Used in combination with the Operator parameter and Criteria1 to create filters for multiple criteria or ranges. Also used for specific date filters for multiple items. |
VisibleDropDown | Optional | Displays or hides the filter drop-down button for an individual column (field). |
Subfield | Optional | Not sure yet… |
We can use a combination of these parameters to apply various filter criteria for different data types. The first four are the most important, so let’s take a look at how to apply those.
Step 2: The Field Parameter
The first parameter is the Field. For the Field parameter we specify a number that is the column number that the filter will be applied to. This is the column number within the filter range that is the parent of the AutoFilter method. It is NOT number of the column on the worksheet.
In the example below Field 4 is the Product column because it is the 4th column in the filter range/Table.
The column filter is cleared when we only specify the the Field parameter, and no other criteria.
We can also use a variable for the Field parameter and set it dynamically. I explain that in more detail below.
Step 3: The Criteria Parameters
There are two parameters that can be used to specify the filter Criteria, Criteria1 and Criteria2. We use a combination of these parameters and the Operator parameter for different types of filters. This is where things get tricky, so let’s start with a simple example.
'Filter the Product column for a single item
lo.Range.AutoFilter Field:=4, Criteria1:="Product 2"
This would be the same as selecting a single item from the checkbox list in the filter drop-down menu.
General Rules for Criteria1 and Criteria2
The values we specify for Criteria1 and Criteria2 can get tricky. Here are some general guidelines for how to reference the Criteria parameter values.
- The criteria value is a string wrapped in quotation marks. There are a few exceptions where the criteria is a constant for date time period and above/below average.
- When specifying filters for single numbers or dates, the number formatting must match the number formatting that is applied in the range/table.
- The comparison operator for greater/less than is also included inside the quotation marks, before the number.
- Quotation marks are also used for filters for blanks “=” and non-blanks “<>”.
'Filter for date greater than or equal to Jan 1 2015
lo.Range.AutoFilter Field:=1, Criteria1:=">=1/1/2015"
' The comparison operator >= is inside the quotation marks
' for the Criteria1 parameter.
' The date formatting in the code matches the formatting
' applied to the cells in the worksheet.
Step 4: The Operator Parameter
What if we want to select multiple items from the filter drop-down? Or do a filter for a range of dates or numbers?
For this we need the Operator. The Operator parameter is used to specify what type of filter we want to apply. This can vary based on the type of data in the column. One of the following 11 constants must be used for the Operator.
Name | Value | Description |
---|---|---|
xlAnd | 1 | Include both Criteria1 and Criteria2. Can be used for date or number ranges. |
xlBottom10Items | 4 | Lowest-valued items displayed (number of items specified in Criteria1). |
xlBottom10Percent | 6 | Lowest-valued items displayed (percentage specified in Criteria1). |
xlFilterCellColor | 8 | Fill Color of the cell |
xlFilterDynamic | 11 | Dynamic filter used for Above/Below Average and Date Periods |
xlFilterFontColor | 9 | Color of the font in the cell |
xlFilterIcon | 10 | Filter icon created by conditional formatting |
xlFilterValues | 7 | Used for filters with multiple criteria specified with an Array function. |
xlOr | 2 | Include either Criteria1 or Criteria2. Can be used for date and number ranges. |
xlTop10Items | 3 | Highest-valued items displayed (number of items specified in Criteria1). |
xlTop10Percent | 5 | Highest-valued items displayed (percentage specified in Criteria1). |
Here is a link to the MSDN help page that contains the list of constants for XlAutoFilterOperator Enumeration.
The operator is used in combination with Criteria1 and/or Criteria2, depending on the data type and filter type. Here are a few examples.
'Filter for list of multiple items, Operator is xlFilterValues
lo.Range.AutoFilter _
Field:=iCol, _
Criteria1:=Array("Product 4", "Product 5", "Product 6"), _
Operator:=xlFilterValues
'Filter for Date Range (between dates), Operator is xlAnd
lo.Range.AutoFilter _
Field:=iCol, _
Criteria1:=">=1/1/2014", _
Operator:=xlAnd, _
Criteria2:="<=12/31/2015"
So that is the basics of writing a line of code for the AutoFilter method. It gets more complex with different data types. So I’ve provided many examples below that contain most of the combinations of Criteria and Operator for different types of filters.
AutoFilter is NOT Additive
When an AutoFilter line of code is run, it first clears any filters applied to that column (Field), then applies the filter criteria that is specified in the line of code.
This means it is NOT additive. The following 2 lines will NOT create a filter for Product 1 and Product 2. After the macro is run, the Product column will only be filtered for Product 2.
'AutoFilter is NOT addititive. It first any filters applied
'in the column before applying the new filter
lo.Range.AutoFilter Field:=4, Criteria1:="Product 3"
'This line of code will filter the column for Product 2 only
'The filter for Product 3 above will be cleared when this line runs.
lo.Range.AutoFilter Field:=4, Criteria1:="Product 2"
If you want to apply a filter with multiple criteria to a single column, then you can specify that with the Criteria and Operator parameters.
How to Set the Field Number Dynamically
If we add/delete/move columns in the filter range, then the field number for a filtered column might change. Therefore, I try to avoid hard-coding a number for the Field parameter whenever possible.
We can use a variable instead and use some code to find the column number by it’s name. Here are two examples for regular ranges and Tables.
Sub Dynamic_Field_Number()
'Techniques to find and set the Field based on the column name.
Dim lo As ListObject
Dim iCol As Long
'Set reference to the first Table on the sheet
Set lo = Sheet1.ListObjects(1)
'Set filter field
iCol = lo.ListColumns("Product").Index
'Use Match function for regular ranges
'iCol = WorksheetFunction.Match("Product", Sheet1.Range("B3:G3"), 0)
'Use the variable for the Field parameter value
lo.Range.AutoFilter Field:=iCol, Criteria1:="Product 3"
End Sub
The column number will be found every time we run the macro. We don’t have to worry about changing the field number when the column moves. This saves time and prevents errors (win-win)! 🙂
Use Excel Tables with Filters
There are a lot of advantages to using Excel Tables, especially with the AutoFilter method. Here are a few of the major reasons I prefer Tables.
- We don’t have to redefine the range in VBA as the data range changes size (rows/columns are added/deleted). The entire Table is referenced with the ListObject object.
- It’s easy to reference the data in the Table after filters are applied. We can use the DataBodyRange property to reference visible rows to copy/paste, format, modify values, etc.
- We can have multiple Tables on the same sheet, and therefore multiple filter ranges. With regular ranges we can only have one filtered range per sheet.
- The code to clear all filters on a Table is easier to write.
Filters & Data Types
The filter drop-down menu options change based on what type of data is in the column. We have different filters for text, numbers, dates, and colors. This creates A LOT of different combinations of Operators and Criteria for each type of filter.
I created separate posts for each of these filter types. The posts contain explanations and VBA code examples.
- How to Clear Filters with VBA
- How to Filter for Blank & Non-Blank Cells
- How to Filter for Text with VBA
- How to Filter for Numbers with VBA
- How to Filter for Dates with VBA
- How to Filter for Colors & Icons with VBA
The file in the downloads section above contains all of these code samples in one place. You can add it to your Personal Macro Workbook and use the macros in your projects.
Why is the AutoFilter Method so Complex?
This post was inspired by a question from Chris, a member of The VBA Pro Course. The combinations of Criteria and Operators can be confusing and complex. Why is this?
Well, filters have evolved over the years. We saw a lot of new filter types introduced in Excel 2010, and the feature is continuing to be improved. However, the parameters of the AutoFilter method haven’t changed. This is great for compatibility with older versions, but also means the new filter types are being worked into the existing parameters.
Most of the filter code makes sense, but can be tricky to figure out at first. Fortunately we have the macro recorder to help with that.
I hope you can use this post and Excel file as a guide to writing macros for filters. Automating filters can save us and our users a ton of time, especially when using these techniques in a larger data automation project.
Please leave a comment below with any questions or suggestions. Thank you! 🙂
I had a similar issue, combined with Conditional Formatting applying to multiple areas after cutting and pasting cells. E.g., (E4:G4, E6:G6, etc.).
Basically, I had to determine the extent of the ranges and then used ModifyAppliesToRange to update it.
Sub FixCondFormatDupRules()
'
Dim ws As Worksheet
Dim MyList As ListObject
Dim lRows As Long
Dim rngData As Range
Dim rngRow1 As Range
Dim rngRow2 As Range
Dim rngRowLast As Range
Set ws = ActiveSheet
Set MyList = ws.ListObjects(1) 'Note this only captures the first table in the ActiveSheet. Wouldn't work if >1 table.
Set rngData = MyList.DataBodyRange
lRows = rngData.Rows.Count
Set rngRow1 = rngData.Rows(1)
Set rngRow2 = rngData.Rows(2)
Set rngRowLast = rngData.Rows(lRows)
With ws.Range(rngRow2, rngRowLast)
.FormatConditions.Delete
End With
' Expanding the Conditional Formatting AppliesTo range to the extent of the ranges and to include the entire table column.
For Each col In rngRow1.Columns
For Each fc In Range(col.Address).FormatConditions
Set FirstCell = col 'Find upper-left cell (lowest row, lowest col)
Set LastCell = Cells(rngRowLast.Row, col.Column) 'Find lower-right cell (highest row, highest col)
For Each xCell In fc.AppliesTo.Cells
If xCell.Column < FirstCell.Column Then Set FirstCell = Cells(FirstCell.Row, xCell.Column)
If xCell.Column > LastCell.Column Then Set LastCell = Cells(LastCell.Row, xCell.Column)
If xCell.Row < FirstCell.Row Then Set FirstCell = Cells(xCell.Row, FirstCell.Column)
If xCell.Row > LastCell.Row Then Set LastCell = Cells(xCell.Row, LastCell.Column)
Next xCell
fc.ModifyAppliesToRange Range(FirstCell, LastCell)
Next fc
Next col
rngRow1.Cells(1, 1).Select
Application.CutCopyMode = False
End Sub
VBA (Visual Basic for Applications) is a programming language that empowers you to automate almost every in Excel. With VBA, you can refer to the Excel Objects and use the properties, methods, and events associated with them. For example, you can create a pivot table, insert a chart, and show a message box to the user using a macro.
The crazy thing is:
For all the tasks which you perform manually in minutes, VBA can do it in seconds, with a single click, with the same accuracy. Even you can write VBA codes that can run automatically when you open a document, a workbook, or even at a specific time.
Let me show you a real-life example:
Every morning when I go to the office, the first thing I need to do is to create a pivot table for the month-to-date sales and present it to my boss. This includes the same steps, every day. But when I realized that I can use VBA to create a pivot table and insert it in a single click, it saved me 5 minutes every day.
Note: VBA is one of the Advanced Excel Skills.
How VBA Works
VBA is an Object-Oriented Language and as an object-oriented language, in VBA, we structure our codes in a way where we are using objects and then defining their properties.
In simple words, first, we define the object and then the activity which we want to perform. There are objects, collections, methods, and properties which you can use in VBA to write your code.
[icon name=”bell” class=””] Don’t miss this: Let’s say you want to tell someone to open a box. The words you will use would be “Open the Box”. It’s plain English, Right? But when it comes to VBA and writing a macro this will be:
Box.Open
As you can see, the above code is started with the box which is our object here, and then we have used the method “Open” for it. Let’s go a bit specific, let say if you want to open the box which is RED in color. And for this the code will be:
Boxes(“Red”).Open
In the above code, boxes are the collection, and open is the method. If you have multiple boxes we are defining a specific box here. Here’s another way:
Box(“Red”).Unlock = True
In the above code, again boxes are the collection, and Unlock is the property that is set to TRUE.
What is VBA used for in Excel?
In Excel, you can use VBA for different things. Here are a few:
- Enter Data: You can enter data in a cell, range of cells. You can also copy and paste data from one section to another.
- Task Automation: You can automate tasks that want you to spend a lot of time. The best example I can give is using a macro to create a pivot table.
- Create a Custom Excel Function: With VBA, you can also create a Custom User Defined Function and use it in the worksheet.
- Create Add-Ins: In Excel, you can convert your VBA codes into add-ins and share them with others as well.
- Integrate with other Microsoft Applications: You can also integrate Excel with other Microsoft applications. Like, you can enter data into a text file.
Excel Programming Fundamentals
A procedure in VBA is a set of codes or a single line of code that performs a specific activity.
- SUB: Sub procedure can perform actions but doesn’t return a value (but you can use an object to get that value).
- Function: With the help of the Function procedure, you create your function, which you can use in the worksheet or the other SUB and FUNCTION procedures (See this: VBA Function).
2. Variables and Constants
You need variables and constants to use values in the code multiple times.
- Variable: A Variable can store a value, it has a name, you need to define its data type, and you can change the value it stores. As the name suggests, “VARIABLE” has no fixed value. It is like a storage box that is stored in the system.
- Constant: A constant also can store a value, but you can’t change the value during the execution of the code.
3. Data Types
You need to declare the data type for VARIABLES and CONSTANTS.
When you specify the data type for a variable or a constant, it ensures the validity of your data. If you omit the data type, VBA applies the Variant data type to your variable (it’s the most flexible), VBA won’t guess what the data type should be.
Tip: VBA Option Explicit
4. Objects, Properties, and Methods
Visual Basic for Applications is an Object-Oriented language, and to make the best out of it; you need to understand Excel Objects.
The workbook you use in Excel has different objects, and with all those objects, there are several properties that you can access and methods that you can use.
5. Events
Whenever you do something in Excel, that’s an event: enter a value in a cell, insert a new worksheet, or insert a chart. Below is the classification of events based on the objects:
- Application Events: These are events that are associated with the Excel application itself.
- Workbook Events: These are events that are associated with the actions that happen in a workbook.
- Worksheet Events: These events are associated with the action that happens in a worksheet.
- Chart Events: These events are associated with the chart sheets (which are different from worksheets).
- Userform Events: These events are associated with the action that happens with a user form.
- OnTime Events: OnTime events are those which can trigger code at a particular point in time.
- OnKey Events: OnKey events are those which can trigger code when a particular key is pressed.
6. Range
The range object is the most common and popular way to refer to a range in your VBA codes. You need to refer to the cell address, let me tell you the syntax.
Worksheets(“Sheet1”).Range(“A1”)
7. Conditions
Just like any other programming language, you can also write codes to test conditions in VBA. It allows you to do it in two different ways.
- IF THEN ELSE: It’s an IF statement that you can use to test a condition and then run a line of code if that condition is TRUE. You can also write nesting conditions with it
- SELECT CASE: In the select case, you can specify a condition and then different cases for outcomes to test to run different lines of code to run. It’s a little more structured than the IF statement.
8. VBA Loops
You can write codes that can repeat and re-repeat an action in VBA, and there are multiple ways that you can use to write code like this.
- For Next: The best fit for using For Next is when you want to repeat a set of actions a fixed number of times.
- For Each Next: It’s perfect to use when you want to loop through a group of objects from a collection of objects.
- Do While Loop: The simple idea behind the Do While Loop is to perform an activity while a condition is true.
- Do Until Loop: In the Do Until, VBA runs a loop and continues to run it if the condition is FALSE.
9. Input Box and Message Box
- Input Box: The input Box is a function that shows an input box to the user and collects a response.
- Message Box: Message Box helps you show a message to the user but, you have an option to add buttons to the message box to get the response of the user.
10. Errors
Excel has no luck when it comes to programming errors, and you have to deal with them, no matter what.
- Syntax Errors: It’s like typos that you do while writing codes, but VBA can help you by pointing out these errors.
- Compile Errors: It comes when you write code to perform an activity, but that activity is not valid.
- Runtime Errors: A RUNTIME error occurs at the time of executing the code. It stops the code and shows you the error dialog box.
- Logical Error: It’s not an error but a mistake while writing code and sometimes can give you nuts while finding and correcting them.
Write a Macro (VBA Program) in Excel
I have a strong belief that in the initial time when someone is starting programming in Excel, HE/SHE should write more and more codes from scratch. The more codes you write from scratch, the more you understand how VBA works.
But you need to start with writing simple codes instead of jumping into complex ones. That’s WHY I don’t want you to think about anything complex right now.
You can even write a macro code to create a pivot table, but right now, I don’t want you to think that far. Let’s think about an activity that you want to perform in your worksheet, and you can write code for it.
- Go to the Developer Tab and open the Visual Basic Editor from the “Visual Basic” button.
- After that, insert a new module from the “Project Window” (Right-click ➢ Insert ➢ Module).
- After that, come to the code window and create a macro with the name “Enter Done” (we are creating a SUB procedure), just like I have below.
- From here, you need to write a code which we have just discussed above. Hold for second and think like this: You need to specify the cell where you want to insert the value and then the value which you wish to enter.
- Enter the cell reference, and for this, you need to use RANGE object and specify the cell address in it, like below:
- After that, enter a dot, and the moment you add a dot, you’ll have a list of properties that you can define and activities that you can do with the range.
- From here, you need to select the “Value” property and set the text which you want to insert in the cell “A1” and when to do it, your code with look something like below.
- Finally, above the line of code, enter the text (‘this code enters the value “Done” in the cell A5). It’s a VBA Comment that you can insert to define the line of code that you have written.
Sub Enter_Done()
'this code enters the value “Done” in the cell A5
Range("A1").Value = "Done"
End Sub
Let’s understand this…
You can split this code into two different parts.
- In the FIRST part, we have specified the cell address by using the RANGE object. And, to refer to a cell using a range object you need to wrap the cell address with double quotes (you can also use square brackets).
- In the SECOND part, we have specified the value to enter into the cell. What you have done is, you have defined the value property for cell A5 by using “.Value”. After that, the next thing that you have specified is the value against the value property. Whenever you are defining a value (if it’s text), you need to wrap that value inside double quotation marks.
Here I have listed some of the most amazing tutorials (not in any particular sequence) that can help you learn VBA in NO TIME.
Introduction
This is a tutorial about writing code in Excel spreadsheets using Visual Basic for Applications (VBA).
Excel is one of Microsoft’s most popular products. In 2016, the CEO of Microsoft said «Think about a world without Excel. That’s just impossible for me.” Well, maybe the world can’t think without Excel.
- In 1996, there were over 30 million users of Microsoft Excel (source).
- Today, there are an estimated 750 million users of Microsoft Excel. That’s a little more than the population of Europe and 25x more users than there were in 1996.
We’re one big happy family!
In this tutorial, you’ll learn about VBA and how to write code in an Excel spreadsheet using Visual Basic.
Prerequisites
You don’t need any prior programming experience to understand this tutorial. However, you will need:
- Basic to intermediate familiarity with Microsoft Excel
- If you want to follow along with the VBA examples in this article, you will need access to Microsoft Excel, preferably the latest version (2019) but Excel 2016 and Excel 2013 will work just fine.
- A willingness to try new things
Learning Objectives
Over the course of this article, you will learn:
- What VBA is
- Why you would use VBA
- How to get set up in Excel to write VBA
- How to solve some real-world problems with VBA
Important Concepts
Here are some important concepts that you should be familiar with to fully understand this tutorial.
Objects: Excel is object-oriented, which means everything is an object — the Excel window, the workbook, a sheet, a chart, a cell. VBA allows users to manipulate and perform actions with objects in Excel.
If you don’t have any experience with object-oriented programming and this is a brand new concept, take a second to let that sink in!
Procedures: a procedure is a chunk of VBA code, written in the Visual Basic Editor, that accomplishes a task. Sometimes, this is also referred to as a macro (more on macros below). There are two types of procedures:
- Subroutines: a group of VBA statements that performs one or more actions
- Functions: a group of VBA statements that performs one or more actions and returns one or more values
Note: you can have functions operating inside of subroutines. You’ll see later.
Macros: If you’ve spent any time learning more advanced Excel functionality, you’ve probably encountered the concept of a “macro.” Excel users can record macros, consisting of user commands/keystrokes/clicks, and play them back at lightning speed to accomplish repetitive tasks. Recorded macros generate VBA code, which you can then examine. It’s actually quite fun to record a simple macro and then look at the VBA code.
Please keep in mind that sometimes it may be easier and faster to record a macro rather than hand-code a VBA procedure.
For example, maybe you work in project management. Once a week, you have to turn a raw exported report from your project management system into a beautifully formatted, clean report for leadership. You need to format the names of the over-budget projects in bold red text. You could record the formatting changes as a macro and run that whenever you need to make the change.
What is VBA?
Visual Basic for Applications is a programming language developed by Microsoft. Each software program in the Microsoft Office suite is bundled with the VBA language at no extra cost. VBA allows Microsoft Office users to create small programs that operate within Microsoft Office software programs.
Think of VBA like a pizza oven within a restaurant. Excel is the restaurant. The kitchen comes with standard commercial appliances, like large refrigerators, stoves, and regular ole’ ovens — those are all of Excel’s standard features.
But what if you want to make wood-fired pizza? Can’t do that in a standard commercial baking oven. VBA is the pizza oven.
Yum.
Why use VBA in Excel?
Because wood-fired pizza is the best!
But seriously.
A lot of people spend a lot of time in Excel as a part of their jobs. Time in Excel moves differently, too. Depending on the circumstances, 10 minutes in Excel can feel like eternity if you’re not able to do what you need, or 10 hours can go by very quickly if everything is going great. Which is when you should ask yourself, why on earth am I spending 10 hours in Excel?
Sometimes, those days are inevitable. But if you’re spending 8-10 hours everyday in Excel doing repetitive tasks, repeating a lot of the same processes, trying to clean up after other users of the file, or even updating other files after changes are made to the Excel file, a VBA procedure just might be the solution for you.
You should consider using VBA if you need to:
- Automate repetitive tasks
- Create easy ways for users to interact with your spreadsheets
- Manipulate large amounts of data
Getting Set Up to Write VBA in Excel
Developer Tab
To write VBA, you’ll need to add the Developer tab to the ribbon, so you’ll see the ribbon like this.
To add the Developer tab to the ribbon:
- On the File tab, go to Options > Customize Ribbon.
- Under Customize the Ribbon and under Main Tabs, select the Developer check box.
After you show the tab, the Developer tab stays visible, unless you clear the check box or have to reinstall Excel. For more information, see Microsoft help documentation.
VBA Editor
Navigate to the Developer Tab, and click the Visual Basic button. A new window will pop up — this is the Visual Basic Editor. For the purposes of this tutorial, you just need to be familiar with the Project Explorer pane and the Property Properties pane.
Excel VBA Examples
First, let’s create a file for us to play around in.
- Open a new Excel file
- Save it as a macro-enabled workbook (. xlsm)
- Select the Developer tab
- Open the VBA Editor
Let’s rock and roll with some easy examples to get you writing code in a spreadsheet using Visual Basic.
Example #1: Display a Message when Users Open the Excel Workbook
In the VBA Editor, select Insert -> New Module
Write this code in the Module window (don’t paste!):
Sub Auto_Open()
MsgBox («Welcome to the XYZ Workbook.»)
End Sub
Save, close the workbook, and reopen the workbook. This dialog should display.
Ta da!
How is it doing that?
Depending on your familiarity with programming, you may have some guesses. It’s not particularly complex, but there’s quite a lot going on:
- Sub (short for “Subroutine): remember from the beginning, “a group of VBA statements that performs one or more actions.”
- Auto_Open: this is the specific subroutine. It automatically runs your code when the Excel file opens — this is the event that triggers the procedure. Auto_Open will only run when the workbook is opened manually; it will not run if the workbook is opened via code from another workbook (Workbook_Open will do that, learn more about the difference between the two).
- By default, a subroutine’s access is public. This means any other module can use this subroutine. All examples in this tutorial will be public subroutines. If needed, you can declare subroutines as private. This may be needed in some situations. Learn more about subroutine access modifiers.
- msgBox: this is a function — a group of VBA statements that performs one or more actions and returns a value. The returned value is the message “Welcome to the XYZ Workbook.”
In short, this is a simple subroutine that contains a function.
When could I use this?
Maybe you have a very important file that is accessed infrequently (say, once a quarter), but automatically updated daily by another VBA procedure. When it is accessed, it’s by many people in multiple departments, all across the company.
- Problem: Most of the time when users access the file, they are confused about the purpose of this file (why it exists), how it is updated so often, who maintains it, and how they should interact with it. New hires always have tons of questions, and you have to field these questions over and over and over again.
- Solution: create a user message that contains a concise answer to each of these frequently answered questions.
Real World Examples
- Use the MsgBox function to display a message when there is any event: user closes an Excel workbook, user prints, a new sheet is added to the workbook, etc.
- Use the MsgBox function to display a message when a user needs to fulfill a condition before closing an Excel workbook
- Use the InputBox function to get information from the user
Example #2: Allow User to Execute another Procedure
In the VBA Editor, select Insert -> New Module
Write this code in the Module window (don’t paste!):
Sub UserReportQuery()
Dim UserInput As Long
Dim Answer As Integer
UserInput = vbYesNo
Answer = MsgBox(«Process the XYZ Report?», UserInput)
If Answer = vbYes Then ProcessReport
End Sub
Sub ProcessReport()
MsgBox («Thanks for processing the XYZ Report.»)
End Sub
Save and navigate back to the Developer tab of Excel and select the “Button” option. Click on a cell and assign the UserReportQuery macro to the button.
Now click the button. This message should display:
Click “yes” or hit Enter.
Once again, tada!
Please note that the secondary subroutine, ProcessReport, could be anything. I’ll demonstrate more possibilities in example #3. But first…
How is it doing that?
This example builds on the previous example and has quite a few new elements. Let’s go over the new stuff:
- Dim UserInput As Long: Dim is short for “dimension” and allows you to declare variable names. In this case, UserInput is the variable name and Long is the data type. In plain English, this line means “Here’s a variable called “UserInput”, and it’s a Long variable type.”
- Dim Answer As Integer: declares another variable called “Answer,” with a data type of Integer. Learn more about data types here.
- UserInput = vbYesNo: assigns a value to the variable. In this case, vbYesNo, which displays Yes and No buttons. There are many button types, learn more here.
- Answer = MsgBox(“Process the XYZ Report?”, UserInput): assigns the value of the variable Answer to be a MsgBox function and the UserInput variable. Yes, a variable within a variable.
- If Answer = vbYes Then ProcessReport: this is an “If statement,” a conditional statement, which allows us to say if x is true, then do y. In this case, if the user has selected “Yes,” then execute the ProcessReport subroutine.
When could I use this?
This could be used in many, many ways. The value and versatility of this functionality is more so defined by what the secondary subroutine does.
For example, maybe you have a file that is used to generate 3 different weekly reports. These reports are formatted in dramatically different ways.
- Problem: Each time one of these reports needs to be generated, a user opens the file and changes formatting and charts; so on and so forth. This file is being edited extensively at least 3 times per week, and it takes at least 30 minutes each time it’s edited.
- Solution: create 1 button per report type, which automatically reformats the necessary components of the reports and generates the necessary charts.
Real World Examples
- Create a dialog box for user to automatically populate certain information across multiple sheets
- Use the InputBox function to get information from the user, which is then populated across multiple sheets
Example #3: Add Numbers to a Range with a For-Next Loop
For loops are very useful if you need to perform repetitive tasks on a specific range of values — arrays or cell ranges. In plain English, a loop says “for each x, do y.”
In the VBA Editor, select Insert -> New Module
Write this code in the Module window (don’t paste!):
Sub LoopExample()
Dim X As Integer
For X = 1 To 100
Range(«A» & X).Value = X
Next X
End Sub
Save and navigate back to the Developer tab of Excel and select the Macros button. Run the LoopExample macro.
This should happen:
Etc, until the 100th row.
How is it doing that?
- Dim X As Integer: declares the variable X as a data type of Integer.
- For X = 1 To 100: this is the start of the For loop. Simply put, it tells the loop to keep repeating until X = 100. X is the counter. The loop will keep executing until X = 100, execute one last time, and then stop.
- Range(«A» & X).Value = X: this declares the range of the loop and what to put in that range. Since X = 1 initially, the first cell will be A1, at which point the loop will put X into that cell.
- Next X: this tells the loop to run again
When could I use this?
The For-Next loop is one of the most powerful functionalities of VBA; there are numerous potential use cases. This is a more complex example that would require multiple layers of logic, but it communicates the world of possibilities in For-Next loops.
Maybe you have a list of all products sold at your bakery in Column A, the type of product in Column B (cakes, donuts, or muffins), the cost of ingredients in Column C, and the market average cost of each product type in another sheet.
You need to figure out what should be the retail price of each product. You’re thinking it should be the cost of ingredients plus 20%, but also 1.2% under market average if possible. A For-Next loop would allow you to do this type of calculation.
Real World Examples
- Use a loop with a nested if statement to add specific values to a separate array only if they meet certain conditions
- Perform mathematical calculations on each value in a range, e.g. calculate additional charges and add them to the value
- Loop through each character in a string and extract all numbers
- Randomly select a number of values from an array
Conclusion
Now that we’ve talked about pizza and muffins and oh-yeah, how to write VBA code in Excel spreadsheets, let’s do a learning check. See if you can answer these questions.
- What is VBA?
- How do I get set up to start using VBA in Excel?
- Why and when would you use VBA?
- What are some problems I could solve with VBA?
If you have a fair idea of how to you could answer these questions, then this was successful.
Whether you’re an occasional user or a power user, I hope this tutorial provided useful information about what can be accomplished with just a bit of code in your Excel spreadsheets.
Happy coding!
Learning Resources
- Excel VBA Programming for Dummies, John Walkenbach
- Get Started with VBA, Microsoft Documentation
- Learning VBA in Excel, Lynda
A bit about me
I’m Chloe Tucker, an artist and developer in Portland, Oregon. As a former educator, I’m continuously searching for the intersection of learning and teaching, or technology and art. Reach out to me on Twitter @_chloetucker and check out my website at chloe.dev.
Learn to code for free. freeCodeCamp’s open source curriculum has helped more than 40,000 people get jobs as developers. Get started
Whether you’re new to Excel VBA or just want a refresher, this tutorial is for you. In 20 minutes (or less!), we’ll take you through the basics of working with VBA code. You’ll learn to write and run VBA code, use the macro recorder, and more! We also give you some common examples when working on VBA Excel. So, buckle up as we’re going to get started! 😉
What is VBA in Excel?
VBA stands for Visual Basic for Applications. It’s a programming language used to automate tasks in Microsoft Office products, including Excel, Word, and Outlook. With VBA Excel, you can write code to automate tasks, create custom functions, and even move data between Office programs.
This programming language was introduced with Excel 5.0 in 1993. It might be hard to believe that the Excel and VBA combo has been around for almost 30 years now. And as you can see, we’re still talking about it today! This means that this language is still popular among spreadsheet users—which makes sense considering what it offers and that few other spreadsheet apps can compete with this.
Why is VBA important?
VBA is important because of all the things it can do, but mainly its ability to automate mundane tasks that take a lot of time is particularly useful. As well as that, here are some common uses of VBA in Excel:
- Create custom functions. If you find yourself using the same complex formula over and over again, you can save yourself some time by creating a custom function using VBA.
- Create custom add-ins for Excel. Add-ins are small programs that extend the functionality of Excel. You can, for example, create an add-in that allows you to apply formatting to selected cells, generate random numbers, apply formulas, or anything else you may want to improve productivity.
- Simplify the data entry process. With Excel VBA, you can create custom forms that will simplify data entry and eliminate errors. You’ll be able to enter all information in one place with consistent formats. It’s easier for everyone involved.
- Automate tasks that you would otherwise have to do manually. Automating tedious, manual tasks with VBA Excel code is an easy way to save time and avoid mistakes. Here’s a common example. You might need to frequently update your spreadsheets by pulling data from various sources such as QuickBooks or Xero. However, doing this manually every day can prove costly in both efficiency and accuracy due to human error.
Are there no-code ways to automate workflows in Excel?
If you want to automate such processes without coding, Power Query is one of your best options. However, it’s not always ideal if any of your data sources isn’t supported by Power Query.
In this case, try using third-party integration tools like Coupler.io, which is a solution to import data from different sources into Excel automatically. You can even set up a schedule to refresh your data (hourly, daily, monthly, etc.) to keep it always up-to-date.
Coupler.io allows you to pull data from CRM applications like Pipedrive, time-tracking tools like Clockify and many other apps and sources including Microsoft Excel. Check out all the available Excel integrations to choose the ones you need. So, you basically can automate data flow between your workbooks or even merge Excel files using it.
Excel VBA programming: Before you get started
Before we get started with Excel VBA programming, let’s understand a few basic terminologies and how to open the Visual Basic Editor (VBE).
A few basic terminologies
Here are a few terminologies we’ll be looking at in this article:
- A macro is simply a procedure written in VBA Excel. You can write macros by using the macro recorder or write your own code.
- A module is where you will store your code. Think of it as a blank canvas where you can write whatever you want.
- A procedure is an instruction or a set of instructions. The two main types of procedures are Sub procedure and Function procedure.
- A Sub procedure (or Sub) is a procedure that only performs actions and does not return a value.
- A Function procedure (or Function) is a procedure that returns a value.
How to open VBA editor in Excel
To use VBA in Excel, you first need to open the Visual Basic Editor (VBE) by simply pressing Alt+F11 on your keyboard.
Alternatively, click on the Developer tab from the ribbon menu, then click on the Visual Basic button. If the Developer tab is not visible, see the section below on how to show the Developer tab in Excel.
After the Visual Basic Editor is open, you’ll be able to find multiple sections described below:
- Menu bar. This is the main menu of the VBE and contains various commands. Many of the commands have shortcut keys associated with them.
- Code pane. This area is where the macro/code can be found. Here are all declaration variables, procedures, functions, etc.
- Toolbar. It contains most of the useful commands that are used while codding. You can customize it by clicking View > Toolbars, then customize as you see fit. Most people just leave them as they are.
- Project Explorer. The Project Explorer Window can usually be found on the top left side of the VBA Excel editor, showing a hierarchical list of open projects. This list contains Microsoft Excel Objects (Sheets and ThisWorkbook section), Forms (all User Forms created in the project), Modules (all macro modules), and Class Modules.
- Properties Window. The Properties Window is where you can set all the properties for all objects from your application. The properties can be sorted alphabetically or by category.
How to show the Developer tab in Excel
The Developer tab is hidden by default in Excel, but you can easily show it if you need to access the features it contains. To do so, here’s a quick guide:
- First, click on File > Options.
- In the Excel Options dialog box, click on Customize Ribbon.
- On the right pane, check the box next to Developer.
- Click OK to save your changes and close the dialog box.
Just that! Now when you open Excel, you will see the Developer tab listed among the other tabs at the top of the window.
How to use VBA in Excel
Most of the code people write in VBA are Sub and Function procedures. So, in this section, we’ll mostly learn about how to write, edit, and run them.
How to write VBA code in Excel manually
To write VBA code manually, follow the steps below:
- Create a new Excel workbook.
- Press Alt+F11 to activate the VBE.
- Click Insert > Module in the menu bar.
- Type manually or copy-paste the following code in the editor:
Sub ShowHello() MsgBox "Hello, " & Application.UserName & "!" End Sub Function ShowCurrentTime() ShowCurrentTime = "Current time: " & Now End Function
- If you want, save the code by pressing Ctrl+S. The extension of the file needs to be XLSM because it contains a macro.
Code explanation:
- The ShowHello() is an example of a Sub procedure. Every Sub procedure starts with the keyword Sub and ends with an End Sub.
- The ShowCurrentTime() is an example of an Excel VBA Function procedure. Every Function procedure starts with the keyword Function and ends with an End Function.
How to run VBA code in Excel
Sub and Function procedures are run differently in Excel. Both can be executed in several ways, but we will cover only a few of them.
To execute an Excel VBA Function procedure:
You can click the Run button in the VBE toolbar or simply press F5 for the same command. Excel executes the Sub procedure in which the cursor is located.
Alternatively, you can execute Sub procedures from Excel by pressing the Macros button in the Developer tab:
To execute a Function procedure:
You can use it in a worksheet or call it from another procedure (a Sub or another Function procedure).
As an example, let’s see how to execute the ShowCurrentTime function by using it as a worksheet formula. To do that, simply type =ShowCurrentTime() in a cell, then press Enter. See the image below:
How to record VBA code in Excel
Another way you can get code into a VBA module is by recording your actions using the Excel Macro Recorder. The result is always a Sub procedure. So, we cannot use this tool as an alternative method of creating functions — they must be manually entered by writing and editing the code ourselves.
Here is the step-by-step for recording a macro:
- Go to the Developer tab and click the Record Macro button.
- In the Record Macro dialog box, enter a name for the macro. Optionally, you can enter a shortcut key, macro location, and description.
- Click OK to start recording.
- Perform all the actions that need to be recorded. For example, let’s just enter 1 to 10 from A1 to A10 manually:
- When you finish, click the Stop Recording button in the Developer tab.
How to edit recorded VBA code in Excel
After you record a macro, you may be curious to see what the code looks like. You might even wonder where your recorded macros are stored, right? Well, by default, they’re stored in a module.
So, to view and edit recorded macros, first, you need to activate the VBE by pressing Alt+F11 on your keyboard. After that, double-click the new module created and locate the code you want to edit.
For example, here is the AssignRowNumber macro we recorded previously:
Sub AssignRowNumber() ' ' AssignRowNumber Macro ' This procedure inserts row numbers to cells, 1 to 10. ' ' Keyboard Shortcut: Ctrl+Shift+M ' ActiveCell.FormulaR1C1 = "1" Range("A2").Select ActiveCell.FormulaR1C1 = "2" Range("A3").Select ActiveCell.FormulaR1C1 = "3" Range("A4").Select ActiveCell.FormulaR1C1 = "4" Range("A5").Select ActiveCell.FormulaR1C1 = "5" Range("A6").Select ActiveCell.FormulaR1C1 = "6" Range("A7").Select ActiveCell.FormulaR1C1 = "7" Range("A8").Select ActiveCell.FormulaR1C1 = "8" Range("A9").Select ActiveCell.FormulaR1C1 = "9" Range("A10").Select ActiveCell.FormulaR1C1 = "10" End Sub
However, you may agree that the above code is not the best way to assign values to the cells. It selects a cell, assigns value as a formula, and then moves to the next cell. We can make the code more compact, readable, and dynamic using the following code:
Sub AssignRowNumber() ' ' AssignRowNumber Macro ' This procedure inserts row numbers to cells, 1 to 10. ' ' Keyboard Shortcut: Ctrl+Shift+M ' For i = 1 To 10 ActiveSheet.Cells(i, 1).Value = i Next i End Sub
In conclusion, the Macro Recorder is a great way to get into VBA programming. However, it can be complicated sometimes to understand the macro recorded. The good news is that recorded macros can be customized after they’re created, giving you even more control over what your program does and how it operates!
How to assign VBA code to a button in Excel
You can easily add a button to an Excel sheet and assign a macro to it. A few simple steps can do this.
For example, let’s take the running ShowHello() Sub procedure one step further by executing it on a button click.
Here are the steps:
- Click the Developer tab, then click Insert > Button (Form Control).
- Click and drag anywhere on the worksheet to create a button.
- In the Assign Macro dialog, select ShowHello, then click OK.
- By default, a “Button 1” is created. Click the button’s text and type “Show Hello” to rename it.
- To test the button, click on it. You’ll see a message box appear showing Hello to you 😉
More VBA Excel examples
This section contains several examples that demonstrate common VBA programming concepts. You may be able to use or adapt these pieces for your own needs.
Example #1: Looping through a range of cells
Many macros operate on each cell in a range, or they perform selected actions based on each cell’s value. These macros usually include a ForEach-Next loop that processes each cell in the range.
The following SUMODDNUMBERS function demonstrates how to loop through a range of cells to sum all the odd numbers.
Function SUMODDNUMBERS(range As range) Dim cell As range For Each cell In range If cell.Value Mod 2 = 1 Then SUMODDNUMBERS = SUMODDNUMBERS + cell.Value End If Next cell End Function
To use the function, type =SUMODDNUMBERS() in a cell and input a range of cells in the parameter. See the screenshot below:
Example #2: Conditional structure
The following example shows how to use a decision structure using a Select-Case statement. Many programmers like the Select-Case structure over If-Then-Else because the code looks more readable when checking multiple conditions.
Sub ShowBudgetText() Dim Budget As Long Dim Result As String Budget = InputBox("Enter project budget: ") Select Case Budget Case 0 To 5000: Result = "LOW" Case 5001 To 10000: Result = "MEDIUM" Case Is > 10000: Result = "HIGH" End Select MsgBox "You have a " & Result & " budget." End Sub
Code explanation:
The code prompts the user for a value, evaluates it, and then outputs a result. It evaluates the Budget variable and checks for three different cases (0–5000, 5001-10000, and greater than 10000). The Select-Case structure is exited as soon as VBA finds a TRUE case and executes the statements for that particular block.
Example #3: Error handling
You can’t always anticipate every error that might occur. But if possible, you should trap them to ensure your program doesn’t crash at runtime.
Below are the three methods of error handling in VBA. Each has its own benefits and drawbacks, so it’s important to choose the right one for your needs.
- On Error Resume Next ignores any encountered errors and prevents the code from stopping.
- On Error GoTo 0 stops the code on the line that causes the error and shows a message box describing the error.
- On Error GoTo [Label] allows you to specify what you want to do with the errors.
Let’s see an example. We’ll add an On Error GoTo [Label] error handling method to our previous ShowBudgetText Sub. This will trap any type of runtime error and then display the error in a warning message box.
Sub ShowBudgetText() Dim Budget As Long Dim Result As String On Error GoTo ErrorHandler Budget = InputBox("Enter project budget: ") Select Case Budget Case 0 To 5000: Result = "LOW" Case 5001 To 10000: Result = "MEDIUM" Case Is > 10000: Result = "HIGH" End Select MsgBox "You have a " & Result & " budget." ErrorHandler: MsgBox "Please enter a valid input.", vbExclamation End Sub
5 Tips for mastering Excel VBA programming
Learning any new programming language can be daunting at first, but we hope this article has given you a good start in learning Excel VBA.
In this last section, we’ve included five of our top tips that will help you on your journey to mastering the language:
- Start by learning the basics of programming. If you’re new to programming, it’s important to start with understanding what a variable is, various data types in VBA, how to use loops and conditions, etc.
- Make use of online resources. Fortunately, there are plenty of resources available to help you learn the basics. Once you have a good understanding of programming fundamentals, you’ll be able to start taking advantage of Excel VBA’s more advanced features.
- Familiarize yourself with common Excel VBA objects and methods. Some of the most commonly used Excel VBA objects include Range, Worksheet, and Workbook.
- Experiment with the Record Macro feature. This is a great way to get a feel for Excel VBA without having to write any code yourself. Simply record a macro and then edit the resulting code to customize it to your needs.
- Don’t forget to have fun! Excel VBA can be a powerful tool, but it’s also meant to be enjoyable. So relax and enjoy the process of learning something new.
Finally, thanks for reading, and have fun! 😊
-
Senior analyst programmer
Back to Blog
Focus on your business
goals while we take care of your data!
Try Coupler.io
Время на прочтение
7 мин
Количество просмотров 311K
Приветствую всех.
В этом посте я расскажу, что такое VBA и как с ним работать в Microsoft Excel 2007/2010 (для более старых версий изменяется лишь интерфейс — код, скорее всего, будет таким же) для автоматизации различной рутины.
VBA (Visual Basic for Applications) — это упрощенная версия Visual Basic, встроенная в множество продуктов линейки Microsoft Office. Она позволяет писать программы прямо в файле конкретного документа. Вам не требуется устанавливать различные IDE — всё, включая отладчик, уже есть в Excel.
Еще при помощи Visual Studio Tools for Office можно писать макросы на C# и также встраивать их. Спасибо, FireStorm.
Сразу скажу — писать на других языках (C++/Delphi/PHP) также возможно, но требуется научится читать, изменять и писать файлы офиса — встраивать в документы не получится. А интерфейсы Microsoft работают через COM. Чтобы вы поняли весь ужас, вот Hello World с использованием COM.
Поэтому, увы, будем учить Visual Basic.
Чуть-чуть подготовки и постановка задачи
Итак, поехали. Открываем Excel.
Для начала давайте добавим в Ribbon панель «Разработчик». В ней находятся кнопки, текстовые поля и пр. элементы для конструирования форм.
Появилась вкладка.
Теперь давайте подумаем, на каком примере мы будем изучать VBA. Недавно мне потребовалось красиво оформить прайс-лист, выглядевший, как таблица. Идём в гугл, набираем «прайс-лист» и качаем любой, который оформлен примерно так (не сочтите за рекламу, пожалуйста):
То есть требуется, чтобы было как минимум две группы, по которым можно объединить товары (в нашем случае это будут Тип и Производитель — в таком порядке). Для того, чтобы предложенный мною алгоритм работал корректно, отсортируйте товары так, чтобы товары из одной группы стояли подряд (сначала по Типу, потом по Производителю).
Результат, которого хотим добиться, выглядит примерно так:
Разумеется, если смотреть прайс только на компьютере, то можно добавить фильтры и будет гораздо удобнее искать нужный товар. Однако мы хотим научится кодить и задача вполне подходящая, не так ли?
Кодим
Для начала требуется создать кнопку, при нажатии на которую будет вызываться наша програма. Кнопки находятся в панели «Разработчик» и появляются по кнопке «Вставить». Вам нужен компонент формы «Кнопка». Нажали, поставили на любое место в листе. Далее, если не появилось окно назначения макроса, надо нажать правой кнопкой и выбрать пункт «Назначить макрос». Назовём его FormatPrice. Важно, чтобы перед именем макроса ничего не было — иначе он создастся в отдельном модуле, а не в пространстве имен книги. В этому случае вам будет недоступно быстрое обращение к выделенному листу. Нажимаем кнопку «Новый».
И вот мы в среде разработки VB. Также её можно вызвать из контекстного меню командой «Исходный текст»/«View code».
Перед вами окно с заглушкой процедуры. Можете его развернуть. Код должен выглядеть примерно так:
Sub FormatPrice()End Sub
Напишем Hello World:
Sub FormatPrice()
MsgBox "Hello World!"
End Sub
И запустим либо щелкнув по кнопке (предварительно сняв с неё выделение), либо клавишей F5 прямо из редактора.
Тут, пожалуй, следует отвлечься на небольшой ликбез по поводу синтаксиса VB. Кто его знает — может смело пропустить этот раздел до конца. Основное отличие Visual Basic от Pascal/C/Java в том, что команды разделяются не ;, а переносом строки или двоеточием (:), если очень хочется написать несколько команд в одну строку. Чтобы понять основные правила синтаксиса, приведу абстрактный код.
Примеры синтаксиса
' Процедура. Ничего не возвращает
' Перегрузка в VBA отсутствует
Sub foo(a As String, b As String)
' Exit Sub ' Это значит "выйти из процедуры"
MsgBox a + ";" + b
End Sub' Функция. Вовращает Integer
Function LengthSqr(x As Integer, y As Integer) As Integer
' Exit Function
LengthSqr = x * x + y * y
End FunctionSub FormatPrice()
Dim s1 As String, s2 As String
s1 = "str1"
s2 = "str2"
If s1 <> s2 Then
foo "123", "456" ' Скобки при вызове процедур запрещены
End IfDim res As sTRING ' Регистр в VB не важен. Впрочем, редактор Вас поправит
Dim i As Integer
' Цикл всегда состоит из нескольких строк
For i = 1 To 10
res = res + CStr(i) ' Конвертация чего угодно в String
If i = 5 Then Exit For
Next iDim x As Double
x = Val("1.234") ' Парсинг чисел
x = x + 10
MsgBox xOn Error Resume Next ' Обработка ошибок - игнорировать все ошибки
x = 5 / 0
MsgBox xOn Error GoTo Err ' При ошибке перейти к метке Err
x = 5 / 0
MsgBox "OK!"
GoTo ne
Err:
MsgBox
"Err!"
ne:
On Error GoTo 0 ' Отключаем обработку ошибок
' Циклы бывает, какие захотите
Do While True
Exit DoLoop 'While True
Do 'Until False
Exit Do
Loop Until False
' А вот при вызове функций, от которых хотим получить значение, скобки нужны.
' Val также умеет возвращать Integer
Select Case LengthSqr(Len("abc"), Val("4"))
Case 24
MsgBox "0"
Case 25
MsgBox "1"
Case 26
MsgBox "2"
End Select' Двухмерный массив.
' Можно также менять размеры командой ReDim (Preserve) - см. google
Dim arr(1 to 10, 5 to 6) As Integer
arr(1, 6) = 8Dim coll As New Collection
Dim coll2 As Collection
coll.Add "item", "key"
Set coll2 = coll ' Все присваивания объектов должны производится командой Set
MsgBox coll2("key")
Set coll2 = New Collection
MsgBox coll2.Count
End Sub
Грабли-1. При копировании кода из IDE (в английском Excel) есь текст конвертируется в 1252 Latin-1. Поэтому, если хотите сохранить русские комментарии — надо сохранить крокозябры как Latin-1, а потом открыть в 1251.
Грабли-2. Т.к. VB позволяет использовать необъявленные переменные, я всегда в начале кода (перед всеми процедурами) ставлю строчку Option Explicit. Эта директива запрещает интерпретатору заводить переменные самостоятельно.
Грабли-3. Глобальные переменные можно объявлять только до первой функции/процедуры. Локальные — в любом месте процедуры/функции.
Еще немного дополнительных функций, которые могут пригодится: InPos, Mid, Trim, LBound, UBound. Также ответы на все вопросы по поводу работы функций/их параметров можно получить в MSDN.
Надеюсь, что этого Вам хватит, чтобы не пугаться кода и самостоятельно написать какое-нибудь домашнее задание по информатике. По ходу поста я буду ненавязчиво знакомить Вас с новыми конструкциями.
Кодим много и под Excel
В этой части мы уже начнём кодить нечто, что умеет работать с нашими листами в Excel. Для начала создадим отдельный лист с именем result (лист с данными назовём data). Теперь, наверное, нужно этот лист очистить от того, что на нём есть. Также мы «выделим» лист с данными, чтобы каждый раз не писать длинное обращение к массиву с листами.
Sub FormatPrice()
Sheets("result").Cells.Clear
Sheets("data").Activate
End Sub
Работа с диапазонами ячеек
Вся работа в Excel VBA производится с диапазонами ячеек. Они создаются функцией Range и возвращают объект типа Range. У него есть всё необходимое для работы с данными и/или оформлением. Кстати сказать, свойство Cells листа — это тоже Range.
Примеры работы с Range
Sheets("result").Activate
Dim r As Range
Set r = Range("A1")
r.Value = "123"
Set r = Range("A3,A5")
r.Font.Color = vbRed
r.Value = "456"
Set r = Range("A6:A7")
r.Value = "=A1+A3"
Теперь давайте поймем алгоритм работы нашего кода. Итак, у каждой строчки листа data, начиная со второй, есть некоторые данные, которые нас не интересуют (ID, название и цена) и есть две вложенные группы, к которым она принадлежит (тип и производитель). Более того, эти строки отсортированы. Пока мы забудем про пропуски перед началом новой группы — так будет проще. Я предлагаю такой алгоритм:
- Считали группы из очередной строки.
- Пробегаемся по всем группам в порядке приоритета (вначале более крупные)
- Если текущая группа не совпадает, вызываем процедуру AddGroup(i, name), где i — номер группы (от номера текущей до максимума), name — её имя. Несколько вызовов необходимы, чтобы создать не только наш заголовок, но и всё более мелкие.
- После отрисовки всех необходимых заголовков делаем еще одну строку и заполняем её данными.
Для упрощения работы рекомендую определить следующие функции-сокращения:
Function GetCol(Col As Integer) As String
GetCol = Chr(Asc("A") + Col)
End FunctionFunction GetCellS(Sheet As String, Col As Integer, Row As Integer) As Range
Set GetCellS = Sheets(Sheet).Range(GetCol(Col) + CStr(Row))
End FunctionFunction GetCell(Col As Integer, Row As Integer) As Range
Set GetCell = Range(GetCol(Col) + CStr(Row))
End Function
Далее определим глобальную переменную «текущая строчка»: Dim CurRow As Integer. В начале процедуры её следует сделать равной единице. Еще нам потребуется переменная-«текущая строка в data», массив с именами групп текущей предыдущей строк. Потом можно написать цикл «пока первая ячейка в строке непуста».
Глобальные переменные
Option Explicit ' про эту строчку я уже рассказывал
Dim CurRow As Integer
Const GroupsCount As Integer = 2
Const DataCount As Integer = 3
FormatPrice
Sub FormatPrice()
Dim I As Integer ' строка в data
CurRow = 1
Dim Groups(1 To GroupsCount) As String
Dim PrGroups(1 To GroupsCount) As String
Sheets(
"data").Activate
I = 2
Do While True
If GetCell(0, I).Value = "" Then Exit Do
' ...
I = I + 1
Loop
End Sub
Теперь надо заполнить массив Groups:
На месте многоточия
Dim I2 As Integer
For I2 = 1 To GroupsCount
Groups(I2) = GetCell(I2, I)
Next I2
' ...
For I2 = 1 To GroupsCount ' VB не умеет копировать массивы
PrGroups(I2) = Groups(I2)
Next I2
I = I + 1
И создать заголовки:
На месте многоточия в предыдущем куске
For I2 = 1 To GroupsCount
If Groups(I2) <> PrGroups(I2) Then
Dim I3 As Integer
For I3 = I2 To GroupsCount
AddHeader I3, Groups(I3)
Next I3
Exit For
End If
Next I2
Не забудем про процедуру AddHeader:
Перед FormatPrice
Sub AddHeader(Ty As Integer, Name As String)
GetCellS("result", 1, CurRow).Value = Name
CurRow = CurRow + 1
End Sub
Теперь надо перенести всякую информацию в result
For I2 = 0 To DataCount - 1
GetCellS("result", I2, CurRow).Value = GetCell(I2, I)
Next I2
Подогнать столбцы по ширине и выбрать лист result для показа результата
После цикла в конце FormatPrice
Sheets("Result").Activate
Columns.AutoFit
Всё. Можно любоваться первой версией.
Некрасиво, но похоже. Давайте разбираться с форматированием. Сначала изменим процедуру AddHeader:
Sub AddHeader(Ty As Integer, Name As String)
Sheets("result").Range("A" + CStr(CurRow) + ":C" + CStr(CurRow)).Merge
' Чтобы не заводить переменную и не писать каждый раз длинный вызов
' можно воспользоваться блоком With
With GetCellS("result", 0, CurRow)
.Value = Name
.Font.Italic = True
.Font.Name = "Cambria"
Select Case Ty
Case 1 ' Тип
.Font.Bold = True
.Font.Size = 16
Case 2 ' Производитель
.Font.Size = 12
End Select
.HorizontalAlignment = xlCenter
End With
CurRow = CurRow + 1
End Sub
Уже лучше:
Осталось только сделать границы. Тут уже нам требуется работать со всеми объединёнными ячейками, иначе бордюр будет только у одной:
Поэтому чуть-чуть меняем код с добавлением стиля границ:
Sub AddHeader(Ty As Integer, Name As String)
With Sheets("result").Range("A" + CStr(CurRow) + ":C" + CStr(CurRow))
.Merge
.Value = Name
.Font.Italic = True
.Font.Name = "Cambria"
.HorizontalAlignment = xlCenterSelect Case Ty
Case 1 ' Тип
.Font.Bold = True
.Font.Size = 16
.Borders(xlTop).Weight = xlThick
Case 2 ' Производитель
.Font.Size = 12
.Borders(xlTop).Weight = xlMedium
End Select
.Borders(xlBottom).Weight = xlMedium ' По убыванию: xlThick, xlMedium, xlThin, xlHairline
End With
CurRow = CurRow + 1
End Sub
Осталось лишь добится пропусков перед началом новой группы. Это легко:
В начале FormatPrice
Dim I As Integer ' строка в data
CurRow = 0 ' чтобы не было пропуска в самом начале
Dim Groups(1 To GroupsCount) As String
В цикле расстановки заголовков
If Groups(I2) <> PrGroups(I2) Then
CurRow = CurRow + 1
Dim I3 As Integer
В точности то, что и хотели.
Надеюсь, что эта статья помогла вам немного освоится с программированием для Excel на VBA. Домашнее задание — добавить заголовки «ID, Название, Цена» в результат. Подсказка: CurRow = 0 CurRow = 1.
Файл можно скачать тут (min.us) или тут (Dropbox). Не забудьте разрешить исполнение макросов. Если кто-нибудь подскажет человеческих файлохостинг, залью туда.
Спасибо за внимание.
Буду рад конструктивной критике в комментариях.
UPD: Перезалил пример на Dropbox и min.us.
UPD2: На самом деле, при вызове процедуры с одним параметром скобки можно поставить. Либо использовать конструкцию Call Foo(«bar», 1, 2, 3) — тут скобки нужны постоянно.