简体   繁体   中英

Understanding VBA code using “TO” and “STEP”

I was given this code to run in excel but I am trying to understand what it means. I especially would like to know the Variable portion? Any help would be greatly appreciated.

sub SortNames

Dim LR As Long

Application.ScreenUpdating = False

Sheets("Stores").Select

LR = Cells(Rows.Count, 1).End(xlUp).Row

For i = LR To 2 Step -1

 'Here is where you can add the names

 If Range("f" & i) <> "Amanda Weaver" And Range("f" & i) <> "Debra Wiesemann" And _
   Range("f" & i) <> "Drew Simpson" And  Range("f" & i) <> "James Howard" And _
   Range("f" & i) <> "Jeff Hruby" And Range("f" & i) <> "Jessica Czupryn" And _
   Range("f" & i) <> "Kevin Janke" And Range("f" & i) <> "Matthew Hudspeath" And _
   Range("f" & i) <> "Maurey Peterson" And Range("f" & i) <> "Noah Hadro" And _
   Range("f" & i) <> "Thomas McHenry" And Range("f" & i) <> "Thomas McHenry" Then

  Range("f" & i).EntireRow.Delete Shift:=xlUp
 End If

Next i

Application.ScreenUpdating = True

End Sub

Let's go through the code line by line. I apologize in advance if I get too basic; however, other people might find the information helpful.

Sub SortNames()

This is the name of the procedure

Dim LR As Long

Creates a variable of type Long to store the row number.

The reason Long type is being used here (as opposed to Integer ) is because in newer versions of Excel (2007 and later), there are more rows (1,048,576) than can fit in an Integer . So you should always use Long when getting a row number/count in Excel or you could get an error when the numbers get large.

Application.ScreenUpdating = False

This is a good general VBA coding technique; it prevents the screen from flickering during execution of a procedure, which A. provides a more pleasant user experience, and B. makes the code run faster. Note that once the VBA procedures have completed, ScreenUpdating automatically gets turn back on (otherwise you wouldn't be able to interact with Excel anymore!).

Sheets("Stores").Select

Obviously: selects the Sheet named "Stores". Because of the previous ScreenUpdating line, the user will not see this sheet selected until the procedure completes. I'm not sure why the writer of the procedure chose to use Select here; I think it would be better to use a With... End With block. Generally speaking, if usage of Select can be avoided, it should be.

LR = Cells(Rows.Count, 1).End(xlUp).Row

The Cells() function will return a Range object referring to the ActiveSheet (which is "Stores"). Cells(Rows.Count, 1) returns the Range object for the very last row in the first column (which is cell A1048576 in Excel 2007 or later). The .End() method gets the last used cell in a row or a column from some starting place. .End(xlUp) gets you the last used cell in a column starting from below and going up. So this entire statement says:

"go to the very bottom of column A, then go up until you find the first used cell, then tell me what row number that is and store it in LR ."

Parenthetically: if a With block were being used as I suggested above, this line would be:

LR = .Cells(Rows.Count, 1).End(xlUp).Row

Note that the writer of this procedure seems to know what they are doing; finding that last used cell to start with, and to not start with the very last cell in the entire workbook, is a very good idea . Otherwise, in the rest of the procedure, Excel would delete every empty row in the workbook , for no reason! Apart from being a waste of computer power (meh, who cares, right?), it would take much longer to complete. Starting with the last used row in this manner is a very good technique for faster procedures.

For i = LR To 2 Step -1

This For loop with starts at LR ( For i = LR ), executes the body of the loop, then subtracts 1 from i ( Step -1 means "subtract 1 from i for each step" ) and loops again. It does this until i is equal to 2 ( To 2 ). Note that on the last execution of the loop, i = 2 (it does not skip 2; the To statement is inclusive).

 'Here is where you can add the names

This is just a comment.

 If Range("f" & i) <> "Amanda Weaver" And Range("f" & i) <> "Debra Wiesemann" And _
   Range("f" & i) <> "Drew Simpson" And Range("f" & i) <> "James Howard" And _
   Range("f" & i) <> "Jeff Hruby" And Range("f" & i) <> "Jessica Czupryn" And _
   Range("f" & i) <> "Kevin Janke" And Range("f" & i) <> "Matthew Hudspeath" And _
   Range("f" & i) <> "Maurey Peterson" And Range("f" & i) <> "Noah Hadro" And _
   Range("f" & i) <> "Thomas McHenry" And Range("f" & i) <> "Thomas McHenry" Then

This is a rather large If statement, which tests a condition or conditions, and Then executes some code if that condition is True . You can probably guess what the If statement is doing here, but I'll explain anyway.

The statement tests to see if Range("f & i) <> "*some name*" evaluates to the value of True . Range("f" & i) returns a Range object in the ActiveSheet with the cell address of column F, and row i (remember i starts at LR , then counts down to 2). The <> part is an operator that just means "is not equal to" . The And parts are another operator; it just evaluates multiple conditions at the same time. So if BOTH conditions on both sides of the AND operator are True , the entire statement evaluates to true. If either one or both are False , then you get a false. When you string the AND s together, they ALL have to be True to get a True . So on the first time through the For loop, if the value in row LR , column F is not equal to any of the names in the list, then the body of the If statement will execute.

A further word of explanation as to what exactly is happening here: VBA does some things auto-magically in order to makes things a bit easier. One of those things is interpreting what you meant to do even though it doesn't actually make sense. If you think about it, it doesn't really make sense to compare a Range object to a string like "Amanda Weaver" . The Range object is much more than just the string value it contains; here is a small list of things that are part of a Range other than its value: a formula, a name, a background color, text color, text formatting, an address, a parent, a row, and column, and many other things. However, VBA assumes that when you say IF Range(F100) <> "Amanda Weaver" , that you want it to compare the value of cell F100 to "Amanda Weaver", and not any of the other parts.

  Range("f" & i).EntireRow.Delete Shift:=xlUp

This is the body of the If block. Anything in here will occur if your test condition above evaluated to True .

The Range("f" & i) part was previously explained. The part EntireRow.Delete means to delete the entire row to which that Range object belongs (remember: it only deletes the row if the value in column F did not contain any of the names in the list). The last bit, Shift:=xlUp , tells Excel how to delete the row. It means that all of the cells below the deleted cell will be shifted up (as opposed to all the cells to the right of the deleted cell being shifted left).

 End If

Duh - this ends your If block.

Next i

Remember that this entire time we have been inside of that For loop. Everything from the For up to this point will execute again, except with i equal to a value of 1 less than the most recent value (until it is equal to 2, inclusive ).

Application.ScreenUpdating = True

As I explained above, this line is probably not necessary. However, it's not a bad thing, and it's good practice to be in the habit of explicitly saying things you intend to happen in your code, even if they happen auto-magically, for two reasons:

  1. Later when you come back and look at your code, you are going to forget what you meant. Seriously, you totally are. Don't argue.
  2. When other people are going to use your code, you can't assume they know everything you know. So make it as obvious as possible what you intend to happen.

_

End Sub

This ends the procedure. Yay.

How to learn VBA

Learning VBA can be a frustrating experience (it has been for me), and finding your own answers can often be very satisfying. With that in mind, let me offer some advice.

I have found a good place to get information on the meaning of unfamiliar VBA code is MSDN; however, actually finding anything on MSDN can be a real trick, so I use Google instead. A good search technique is: "MSDN VBA unfamiliar code here ".

Here is the MSDN page describing the For To Next loop structure.

Anytime you run into a function or keyword that you haven't seen before, take the time to look it up and read about it. I have found this to be one of the most effective learning techniques.

The loop starts at the bottom (LR is the last row) and goes up to row 2 adding -1 to the row number each time. That's what you want because if you start at row 2 and go down 1 row each time then when you delete a row all the rest of the rows shift up and adding 1 to the row number will skip a row. Skipping a row is not what you want so you should start at the bottom.

Starting at the bottom and moving up: For i = LR To 2 Step -1

Let's say there are two rows of data (2 and 3) and 4 is empty. Since LR is 3 we start with i = 3. If we delete row 3 then row 4 becomes row 3 but we don't care because we change i to 2 and continue.

Starting at the top and moving down: For i = 2 To LR Step 1

Let's say there are two rows of data (2 and 3) and 4 is empty. So LR is 3. We start with i = 2. If we delete row 2 then row 3 becomes row 2 and row 4 becomes row 3. So we change i to 3 which is an empty row and we never had the chance to check the current row 2.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM