让我们逐行浏览代码。如果我太基本,我会提前道歉;但是,其他人可能会发现这些信息很有帮助。
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循环从LR(For 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 语句,它测试一个或多个条件,如果条件是True,Then 会执行一些代码。您可能会猜到If 语句在这里做了什么,但我还是会解释一下。
该语句测试Range("f & i) <> "*some name*" 的计算结果是否为True 的值。 Range("f" & i) 在ActiveSheet 中返回一个Range 对象,其单元格地址为F 列,行i(请记住i 从LR 开始,然后倒数到2)。 <> 部分是一个运算符,仅表示“不等于”。 And 部分是另一个运算符;它只是同时评估多个条件。因此,如果AND 运算符两边的两个条件都是True,则整个语句的计算结果为真。如果其中一个或两个都是False,那么你得到一个错误。当您将ANDs 串在一起时,它们都必须是True 才能获得True。因此,在第一次通过For 循环时,如果LR 列F 中的值不等于列表中的任何名称,则将执行If 语句的主体。
进一步解释这里到底发生了什么:VBA 会自动做一些事情,以使事情变得更容易一些。其中一件事是解释你的意图,即使它实际上没有意义。如果您考虑一下,将Range 对象与像 "Amanda Weaver" 这样的字符串进行比较是没有意义的。 Range 对象不仅仅是它包含的字符串值;这是Range 中除值之外的一小部分内容:公式、名称、背景颜色、文本颜色、文本格式、地址、父级、行和列,以及许多其他事情。但是,VBA 假定当您说 IF Range(F100) <> "Amanda Weaver" 时,您希望它比较单元格 F100 的 值 与“Amanda Weaver”,而不是任何其他部分。
Range("f" & i).EntireRow.Delete Shift:=xlUp
这是If 块的主体。如果上面的测试条件评估为True,则此处的任何内容都会发生。
Range("f" & i) 部分前面已经解释过了。 EntireRow.Delete 部分表示删除 Range 对象所属的整行(记住:它只删除行 if F 列中的值不包含列表中的任何名称)。最后一位 Shift:=xlUp 告诉 Excel 如何 删除该行。这意味着被删除单元格下方的所有单元格都将向上移动(而不是被删除单元格右侧的所有单元格都向左移动)。
End If
Duh - 这结束了您的 If 块。
Next i
请记住,我们一直处于 For 循环中。从 For 到现在的所有内容都将再次执行,除了 i 的值比最近的值小 1(直到它等于 2,包括)。
Application.ScreenUpdating = True
正如我上面解释的,这条线可能不是必需的。但是,这并不是一件坏事,养成在代码中明确说出您打算发生的事情的习惯是一种很好的做法,即使它们是自动发生的,原因有两个:
- 稍后当您回来查看您的代码时,您会忘记您的意思。说真的,你完全是。不要争论。
- 当其他人要使用您的代码时,您不能假设他们知道您所知道的一切。因此,要尽可能地明确你打算发生的事情。
_
End Sub
此过程结束。耶。
如何学习 VBA
学习 VBA 可能是一种令人沮丧的经历(对我来说一直如此),而找到自己的答案通常会非常令人满意。考虑到这一点,让我提供一些建议。
我找到了一个很好的地方来获取关于不熟悉的VBA代码含义的信息是MSDN;然而,实际上查找 MSDN 上的任何东西都可能是一个真正的技巧,所以我改用 Google。一个很好的搜索技术是:“MSDN VBA 这里有不熟悉的代码”。
Here is the MSDN page 描述了For To Next 循环结构。
每当您遇到以前从未见过的函数或关键字时,请花时间查找并阅读相关内容。我发现这是最有效的学习技巧之一。