简体   繁体   English

使用“ TO”和“ STEP”了解VBA代码

[英]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循环以LRFor 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行(请记住iLR开始,然后递减至2)。 <>部分是一个运算符 ,仅表示“不等于” And部分是另一个运算符;它只是在同一条件下评估多个条件时间,因此,如果AND运算符两侧的两个条件均为True ,则整个语句的计算结果为true;如果其中之一或两者均为False ,则您得到的是false。将AND串在一起时,它们都必须是TrueTrue ,因此在第一次通过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: 但是,这并不是一件坏事,养成在代码中明确声明您打算发生的事情的习惯是一种好习惯,即使它们是自动发生的,也有两个原因:

  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 如何学习VBA

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.

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