[英]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. 我得到了可以在excel中运行的代码,但是我试图理解它的含义。 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. 创建一个Long
类型的变量来存储行号。
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
. 之所以在这里使用Long
类型(而不是Integer
)是因为在较新版本的Excel(2007及更高版本)中,行(1,048,576)超出了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. 因此,在Excel中获取行号/计数时,应始终使用Long
,否则当数字变大时可能会出错。
Application.ScreenUpdating = False
This is a good general VBA coding technique; 这是一种很好的通用VBA编码技术。 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. 它可以防止屏幕在执行过程中闪烁,这A.提供了更舒适的用户体验,B。使代码运行更快。 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!). 请注意,一旦VBA程序完成,ScreenUpdating将自动重新打开(否则您将无法与Excel进行交互!)。
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. 由于前面有ScreenUpdating
行,因此在该过程完成之前,用户将看不到此表。 I'm not sure why the writer of the procedure chose to use Select
here; 我不确定过程的编写者为什么选择使用“ Select
此处”。 I think it would be better to use a With... End With
block. 我认为使用With... End With
块会更好。 Generally speaking, if usage of Select
can be avoided, it should be. 一般来说,如果可以避免使用Select
,则应该这样做。
LR = Cells(Rows.Count, 1).End(xlUp).Row
The Cells()
function will return a Range
object referring to the ActiveSheet
(which is "Stores"). Cells()
函数将返回一个引用ActiveSheet
(即“商店”)的Range
对象。 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). Cells(Rows.Count, 1)
返回第一列的最后一行(在Excel 2007或更高版本中为单元格A1048576 Cells(Rows.Count, 1)
的Range对象。 The .End()
method gets the last used cell in a row or a column from some starting place. .End()
方法从某个起始位置获取行或列中最后使用的单元格。 .End(xlUp)
gets you the last used cell in a column starting from below and going up. .End(xlUp)
会为您提供从下往上的列中最后使用的单元格。 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
." “转到A列的最底部,然后向上直到找到第一个使用的单元格,然后告诉我是什么行号并将其存储在LR
。”
Parenthetically: if a With
block were being used as I suggested above, this line would be: 附带说明:如果按照我上面的建议使用With
块,则此行将是:
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! 否则,在该过程的其余部分中,Excel将无故删除工作簿中的每个空行 ! Apart from being a waste of computer power (meh, who cares, right?), it would take much longer to complete. 除了是计算机电源的浪费(MEH,谁在乎,对不对?),这将需要更长的时间才能完成。 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. 此For
循环以LR
( For i = LR
)开始,执行循环的主体,然后从i
减去1( Step -1
表示“每个步骤从i
减去1” )并再次循环。 It does this until i
is equal to 2 ( To 2
). 直到i
等于2( To 2
)为止。 Note that on the last execution of the loop, i
= 2 (it does not skip 2; the To
statement is inclusive). 请注意,在循环的最后一次执行时, i
= 2(不跳过 2; To
语句包含在内)。
'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
. 这是一个相当大的If
语句,用于测试一个或多个条件, Then
在该条件为True
执行一些代码。 You can probably guess what the If
statement is doing here, but I'll explain anyway. 您可能会猜测If
语句在这里做什么,但是我还是会解释。
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. 该语句测试看看Range("f & i) <> "*some name*"
的值是否为True
Range("f" & i)
在ActiveSheet
返回一个Range
对象,其F单元格地址为F和第i
行(请记住i
从LR
开始,然后递减至2)。 <>
部分是一个运算符 ,仅表示“不等于” And
部分是另一个运算符;它只是在同一条件下评估多个条件时间,因此,如果AND
运算符两侧的两个条件均为True
,则整个语句的计算结果为true;如果其中之一或两者均为False
,则您得到的是false。将AND
串在一起时,它们都必须是True
为True
,因此在第一次通过For
循环时,如果LR
行,F列中的值不等于列表中的任何名称,则将执行If
语句的主体。
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. 关于这里到底发生了什么的进一步解释:VBA自动神奇地做一些事情,以使事情变得容易一些。 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" . 如果您考虑一下,则将Range
对象与类似“ Amanda Weaver”之类的字符串进行比较并没有任何意义。 The Range
object is much more than just the string value it contains; Range
对象不仅包含它所包含的字符串值,还包含更多内容。 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. 这是Range
值以外的一部分内容的一小部分内容:公式,名称,背景色,文本颜色,文本格式,地址,父项,行和列,以及许多其他内容。 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. 然而,VBA假设当你说IF Range(F100) <> "Amanda Weaver"
,要它来比较细胞F100为“阿曼达织女”的价值 ,而不是任何其他部分。
Range("f" & i).EntireRow.Delete Shift:=xlUp
This is the body of the If
block. 这是If
块的主体。 Anything in here will occur if your test condition above evaluated to True
. 如果您的上述测试条件评估为True
,则此处将发生任何事情。
The Range("f" & i)
part was previously explained. 前面已经解释了Range("f" & i)
部分。 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). EntireRow.Delete
部分意味着删除该Range
对象所属的整行(请记住:仅当 F列中的值不包含列表中的任何名称时,才删除该行)。 The last bit, Shift:=xlUp
, tells Excel how to delete the row. 最后一位Shift:=xlUp
告诉Excel 如何删除行。 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. h-这将结束您的If
封锁。
Next i
Remember that this entire time we have been inside of that For
loop. 请记住,我们一直都在For
循环中。 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 ). 从For
到现在为止的所有内容都将再次执行,除非i
等于小于最新值的值1(直到等于2, 包括 2为止)。
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: 但是,这并不是一件坏事,养成在代码中明确声明您打算发生的事情的习惯是一种好习惯,即使它们是自动发生的,也有两个原因:
_ _
End Sub
This ends the procedure. 这样就结束了过程。 Yay. 好极了。
Learning VBA can be a frustrating experience (it has been for me), and finding your own answers can often be very satisfying. 学习VBA可能是令人沮丧的经历(对我来说一直如此),找到自己的答案通常会非常令人满意。 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; 我找到了一个获取有关不熟悉的VBA代码含义的信息的好地方,即MSDN; however, actually finding anything on MSDN can be a real trick, so I use Google instead. 但是,实际上在MSDN上找到任何东西都是一个真正的技巧,所以我改用Google。 A good search technique is: "MSDN VBA unfamiliar code here ". 一种很好的搜索技术是:“ MSDN VBA 此处不熟悉的代码 ”。
Here is the MSDN page describing the For To Next
loop structure. 这是MSDN页面,描述了For To Next
循环结构。
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. 循环从底部开始(LR是最后一行),然后上升到第2行,每次将行号加-1。 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. 这就是您想要的,因为如果您从第2行开始,每次向下移1行,那么当您删除某行时,所有其余行都将上移并将行号加1将跳过一行。 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
从底部开始向上移动: For i = LR To 2 Step -1
Let's say there are two rows of data (2 and 3) and 4 is empty. 假设有两行数据(2和3),而4为空。 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. 由于LR为3,所以我们从i = 3开始。如果删除第3行,则第4行变为第3行,但我们不在乎,因为我们将i更改为2并继续。
Starting at the top and moving down: For i = 2 To LR Step 1
从顶部开始向下移动: For i = 2 To LR Step 1
Let's say there are two rows of data (2 and 3) and 4 is empty. 假设有两行数据(2和3),而4为空。 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. 因此LR为3。我们从i = 2开始。如果删除第2行,则第3行成为第2行,第4行成为第3行。因此,我们将i更改为3,这是一个空行,我们再也没有机会检查当前行2。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.