【问题标题】:Understanding VBA code using "TO" and "STEP"使用“TO”和“STEP”理解 VBA 代码
【发布时间】:2014-05-29 01:57:59
【问题描述】:

我得到了在 excel 中运行的代码,但我试图理解它的含义。我特别想知道变量部分?任何帮助将不胜感激。

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

【问题讨论】:

    标签: excel vba


    【解决方案1】:

    让我们逐行浏览代码。如果我太基本,我会提前道歉;但是,其他人可能会发现这些信息很有帮助。

    Sub SortNames()
    

    这是程序的名称

    Dim LR As Long
    

    创建一个Long 类型的变量来存储行号。

    这里使用Long 类型(而不是Integer)的原因是,在较新版本的Excel(2007 及更高版本)中,行数(1,048,576)超出了Integer 的容量。因此,在 Excel 中获取行号/计数时应始终使用Long,否则当数字变大时可能会出现错误。

    Application.ScreenUpdating = False
    

    这是一种很好的通用 VBA 编码技术;它可以防止屏幕在程序执行过程中闪烁,A. 提供更愉快的用户体验,B. 使代码运行得更快。请注意,一旦 VBA 程序完成,ScreenUpdating 会自动重新打开(否则您将无法再与 Excel 交互!)。

    Sheets("Stores").Select
    

    显然:选择名为“Stores”的工作表。由于前面的ScreenUpdating 行,用户在程序完成之前不会看到此工作表被选中。我不确定为什么程序的作者在这里选择使用Select;我认为使用With... End With 块会更好。一般来说,如果可以避免使用Select,应该可以。

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

    Cells() 函数将返回一个引用ActiveSheet(即“Stores”)的Range 对象。 Cells(Rows.Count, 1) 返回第一列中最后一行的 Range 对象(在 Excel 2007 或更高版本中为单元格 A1048576)。 .End() 方法从某个起始位置获取一行或一列中最后一个使用 单元格。 .End(xlUp) 为您获取列中最后使用的单元格,从下方开始向上。所以这整个声明说:

    “到A列的最底部,然后向上直到找到第一个使用的单元格,然后告诉我那是什么行号并将其存储在LR中。” p>

    顺便说一句:如果按照我上面的建议使用 With 块,则此行将是:

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

    请注意,此程序的编写者似乎知道他们在做什么;发现最后一个使用单元格从整个工作簿中的最后一个单元格开始,而不是从最后一个单元格开始,这是一个非常好的主意。否则,在其余过程中,Excel 将无缘无故地删除 工作簿中的每个空行!除了浪费计算机能力(嗯,谁在乎,对吧?)之外,它还需要 更多 更长的时间才能完成。以这种方式从最后一个使用的行开始是一种非常好的技术,可以加快过程。

    For i = LR To 2 Step -1
    

    这个For循环从LRFor i = LR)开始,执行循环体,然后从i中减去1(Step -1的意思是“从i中减去1每个步骤") 并再次循环。它会一直这样做,直到 i 等于 2 (To 2)。请注意,在最后一次执行循环时,i = 2(它不会跳过 2;To 语句包含在内)。

     '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
    

    这是一个相当大的If 语句,它测试一个或多个条件,如果条件是TrueThen 会执行一些代码。您可能会猜到If 语句在这里做了什么,但我还是会解释一下。

    该语句测试Range("f &amp; i) &lt;&gt; "*some name*" 的计算结果是否为True 的值。 Range("f" &amp; i)ActiveSheet 中返回一个Range 对象,其单元格地址为F 列,行i(请记住iLR 开始,然后倒数到2)。 &lt;&gt; 部分是一个运算符,仅表示“不等于”And 部分是另一个运算符;它只是同时评估多个条件。因此,如果AND 运算符两边的两个条件都是True,则整个语句的计算结果为真。如果其中一个或两个都是False,那么你得到一个错误。当您将ANDs 串在一起时,它们都必须是True 才能获得True。因此,在第一次通过For 循环时,如果LR 列F 中的值不等于列表中的任何名称,则将执行If 语句的主体。

    进一步解释这里到底发生了什么:VBA 会自动做一些事情,以使事情变得更容易一些。其中一件事是解释你的意图,即使它实际上没有意义。如果您考虑一下,将Range 对象与像 "Amanda Weaver" 这样的字符串进行比较是没有意义的。 Range 对象不仅仅是它包含的字符串值;这是Range 中除值之外的一小部分内容:公式、名称、背景颜色、文本颜色、文本格式、地址、父级、行和列,以及许多其他事情。但是,VBA 假定当您说 IF Range(F100) &lt;&gt; "Amanda Weaver" 时,您希望它比较单元格 F100 的 与“Amanda Weaver”,而不是任何其他部分。

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

    这是If 块的主体。如果上面的测试条件评估为True,则此处的任何内容都会发生。

    Range("f" &amp; i) 部分前面已经解释过了。 EntireRow.Delete 部分表示删除 Range 对象所属的整行(记住:它只删除行 if F 列中的值不包含列表中的任何名称)。最后一位 Shift:=xlUp 告诉 Excel 如何 删除该行。这意味着被删除单元格下方的所有单元格都将向上移动(而不是被删除单元格右侧的所有单元格都向左移动)。

     End If
    

    Duh - 这结束了您的 If 块。

    Next i
    

    请记住,我们一直处于 For 循环中。从 For 到现在的所有内容都将再次执行,除了 i 的值比最近的值小 1(直到它等于 2,包括)。

    Application.ScreenUpdating = True
    

    正如我上面解释的,这条线可能不是必需的。但是,这并不是一件坏事,养成在代码中明确说出您打算发生的事情的习惯是一种很好的做法,即使它们是自动发生的,原因有两个:

    1. 稍后当您回来查看您的代码时,您会忘记您的意思。说真的,你完全是。不要争论。
    2. 当其他人要使用您的代码时,您不能假设他们知道您所知道的一切。因此,要尽可能地明确你打算发生的事情。

    _

    End Sub
    

    此过程结束。耶。

    如何学习 VBA

    学习 VBA 可能是一种令人沮丧的经历(对我来说一直如此),而找到自己的答案通常会非常令人满意。考虑到这一点,让我提供一些建议。

    我找到了一个很好的地方来获取关于不熟悉的VBA代码含义的信息是MSDN;然而,实际上查找 MSDN 上的任何东西都可能是一个真正的技巧,所以我改用 Google。一个很好的搜索技术是:“MSDN VBA 这里有不熟悉的代码”。

    Here is the MSDN page 描述了For To Next 循环结构。

    每当您遇到以前从未见过的函数或关键字时,请花时间查找并阅读相关内容。我发现这是最有效的学习技巧之一。

    【讨论】:

      【解决方案2】:

      循环从底部开始(LR 是最后一行)并向上到第 2 行,每次将 -1 添加到行号。这就是您想要的,因为如果您从第 2 行开始并且每次下降 1 行,那么当您删除一行时,所有其余行都会向上移动,并且在行号上加 1 将跳过一行。跳过一行不是你想要的,所以你应该从底部开始。

      从底部开始向上移动:For i = LR To 2 Step -1

      假设有两行数据(2 和 3),4 为空。由于 LR 为 3,我们从 i = 3 开始。如果我们删除第 3 行,则第 4 行变为第 3 行,但我们不在乎,因为我们将 i 更改为 2 并继续。

      从顶部开始向下移动:For i = 2 To LR Step 1

      假设有两行数据(2 和 3),4 为空。所以 LR 是 3。我们从 i = 2 开始。如果我们删除第 2 行,则第 3 行变为第 2 行,第 4 行变为第 3 行。所以我们将 i 更改为 3,这是一个空行,我们从来没有机会检查当前第 2 行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-06-02
        • 1970-01-01
        • 1970-01-01
        • 2014-02-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-02
        相关资源
        最近更新 更多