我可以使这个macros更有效率或更快?

我是全新的编码。 这个macros运行缓慢,我希望有人能帮我清理它。 在此先感谢您的帮助。

我开发了代码来更新我公司的“呼叫路由器”工作表,其中包含从外部购买的新线索。 这些线索以原始格式在我们的工作表中被称为Fresh Agents Leads。 一旦“新鲜代理信息”表复制到“呼叫路由器”工作表中的“MSS呼叫路由主列表”文件中,macros将减less原始数据,从而消除我们不使用的部分。 然后,重新格式化与旧呼叫路由器工作表的格式相匹配的内容,并将两者合并。 然后将新的主表重命名为呼叫路由器。

该代码旨在从容纳新鲜代理信息表的工作簿开始。 指示用户在执行代码之前在桌面上同时打开新鲜代理线索文件和MSS呼叫路由主列表。

Sheets("Fresh Agent Leads").Select Sheets("Fresh Agent Leads").Copy After:=Workbooks( _ "MSS Call Routing Master List.xlsx").Sheets(1) Columns("F:F").Select Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove Range("A1").Select Selection.Copy Columns("F:F").Select ActiveSheet.Paste Columns("A:A").Select Application.CutCopyMode = False Selection.Delete Shift:=xlToLeft Columns("C:C").Select Selection.Delete Shift:=xlToLeft Columns("E:E").Select Selection.Delete Shift:=xlToLeft Selection.Delete Shift:=xlToLeft Columns("G:S").Select Selection.Delete Shift:=xlToLeft Rows("1:1").Select Selection.Delete Shift:=xlUp Columns("C:C").Select Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove Range("C1").Select ActiveCell.FormulaR1C1 = "=CONCATENATE(RIGHT(RC[1],4))" Range("C1").Select Selection.AutoFill Destination:=Range("C1:C1048575") Range("C1:C1048575").Select Sheets("Call Router").Select Rows("1:1").Select Selection.Copy Sheets("Fresh Agent Leads").Select Rows("1:1").Select Selection.Insert Shift:=xlDown Application.CutCopyMode = False Application.Run "PERSONAL.xlsb!MergeIdenticalWorksheets" Columns("C:C").Select Selection.NumberFormat = "0000" Range("A:A,B:B,F:F").Select Range("F1").Activate Selection.ColumnWidth = 14 Columns("E:E").Select Selection.ColumnWidth = 25 Columns("C:C").Select Selection.ColumnWidth = 8.29 With Selection .HorizontalAlignment = xlCenter .VerticalAlignment = xlBottom .WrapText = False .Orientation = 0 .AddIndent = False .IndentLevel = 0 .ShrinkToFit = False .ReadingOrder = xlContext .MergeCells = False End With Rows("1:1").Select Selection.RowHeight = 30 With Selection .VerticalAlignment = xlBottom .WrapText = True .Orientation = 0 .AddIndent = False .ShrinkToFit = False .ReadingOrder = xlContext .MergeCells = False End With With Selection.Interior .Pattern = xlSolid .PatternColorIndex = xlAutomatic .ThemeColor = xlThemeColorLight1 .TintAndShade = 0 .PatternTintAndShade = 0 End With With Selection.Font .ThemeColor = xlThemeColorDark1 .TintAndShade = 0 End With Columns("D:D").Select Selection.EntireColumn.Hidden = True Range("E2").Select ActiveWindow.FreezePanes = True Sheets(Array("Call Router", "Fresh Agent Leads")).Select Sheets("Call Router").Activate ActiveWindow.SelectedSheets.Delete Sheets("Master").Select Sheets("Master").Name = "Call Router" Range("C23").Select ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True ActiveWorkbook.Save End Sub 

虽然这段代码大部分属于CR,而不是SO,因为我有很多时间在我手中,所以我决定至less发表一些关于你的代码的东西。

===

一些提示:

  1. 避免。尽可能select和.Activate 。 录制macros对于VBA来说是一个好的开始,但是第一大步是离开这些属性提供的“舒适区”。 一开始他们都很好,但是从长远来看,这肯定会造成问题。

  2. 阅读以下“基本”程序:复制/粘贴/插入范围,创build/删除工作表,以及确定具有相关数据的工作表或范围的最后一行/列。 这三个人是你最好的朋友。 通过学习这三个核心,你可以在Excel VBA中操作很多。

  3. 在(2)之后,开始学习如何定义variables和/或对象。 把行话放在一边,这基本上就像给你每个重要的事情“绰号”一样。 假设你正在工作3张。 您不想继续参考ThisWorkbook.Sheets("Sheet1")等等。 你宁愿要Sh1Sh2来代替。

  4. 学习如何使用UnionWith或类似的方法将类似的程序捆绑在一起。 这与(1)同时进行。 你会在后面看到一个例子。

  5. Application.ScreenUpdating – 在Excel VBA中最好的时间剔除技巧之一。

现在,几个样本:

(1)避免。select|| 学习使用非常好的。 .Copy一行

这部分…

 Range("A1").Select Selection.Copy Columns("F:F").Select ActiveSheet.Paste 

…可以被缩减为:

 Range("A1").Copy Range("F:F") 

从四条线到一条。 而且它更可读。 上面的第二个代码片段基本读取“将A1的值复制到整个F列”。 请注意,这实际上是相当的内存密集型,因为在Excel 2010中,您实际上正在使用该命令粘贴到一百多行。 更好地具体,如Range("F1:F1000")

(2)将命令捆绑在一起

在“书面”VBA中将命令拼凑在一起与在macros中执行的方式不同。 由于macros被logging,一切都基于实时修改。 在“书面的”VBA中,您可以指定一个动作,使您可以对多个对象应用单个动作。 比方说,例如,要删除列A和C,同时将所有相关数据移到左侧。

录制macros时,可以同时selectA和C并删除它们。 但是,大多数初学者都采取安全的道路,并且一次一个地删除列,而且安全 – 这是非常违反直觉的。 在删除之前select两者是最好的select。

在书面VBA,上面的第二种方法是一个巨大的禁止(或至less,这不是常态)。 除非有一个特定的和必要的原因,否则将相似的命令集中在一起就是惯例,因为它既能消除很大程度的错误,又不是资源密集型的。

在你的代码中…

 Selection.Delete Shift:=xlToLeft Columns("C:C").Select Selection.Delete Shift:=xlToLeft Columns("E:E").Select Selection.Delete Shift:=xlToLeft Selection.Delete Shift:=xlToLeft Columns("G:S").Select Selection.Delete Shift:=xlToLeft 

阅读是一件很痛苦的事情。 我们不知道为什么在那里有两个删除,我们不知道列S中的数据原来是什么等。在这样的情况下,提前确定要删除的范围并执行删除是完美的方式。

让我们假设,例如你想删除A,C,E和F列到O.一个整洁的方法如下将非常快速和有效地closures它。

 Union(Range("A:A"),Range("C:C"),Range("E:E"),Range("F:O")).Delete 

Union是你早期最好的朋友之一。 与math中的设置符号一样,您指定的范围一起放在一组范围内,同时进行操作(在这种情况下,同时.Delete d)。 由于默认的移位是在左边,我们可以完全移除Shift:=xlToLeft行(另一个漂亮的VBA事实)。

(3) With一件你不能没有的东西

在这一点上,你可能会想,在这些范围上的多重行动呢? 我们只对多个范围进行单独操作,而不是相反。 这就是With进来的地方。在这种情况下, With只会用在Ranges但它几乎可以用在VBA上的任何东西上。 对象,范围,外部应用程序等我不会深究这一点,但足以说,使用With就像在一些你想要用一些程序工作的锚点上使用锚点。

在你的代码中,我们发现…

 Columns("C:C").Select Selection.ColumnWidth = 8.29 With Selection .HorizontalAlignment = xlCenter .VerticalAlignment = xlBottom .WrapText = False .Orientation = 0 .AddIndent = False .IndentLevel = 0 .ShrinkToFit = False .ReadingOrder = xlContext .MergeCells = False End With Rows("1:1").Select Selection.RowHeight = 30 With Selection .VerticalAlignment = xlBottom .WrapText = True .Orientation = 0 .AddIndent = False .ShrinkToFit = False .ReadingOrder = xlContext .MergeCells = False End With 

…可以减less到:

 With Columns("C:C") .ColumnWidth = 8.29 .HorizontalAlignment = xlCenter End With With Rows(1:1) .RowHeight = 30 .WrapText = True End With 

基本上,我们在这里做了两件事。 首先,我们在C列上进行了锚定,并对其执行了两个操作:设置列宽,然后设置水平alignment。 在锚定到C列并对其进行修改之后,我们将锚点更改为整个第1行,然后修改其高度并将其设置为将文本包装为单元格宽度。 从24行开始,我们已经把这个macros块减less到只有8行。 那简洁起来怎么样? 🙂

为什么我没有其他的路线? 和前面的例子( Union )一样,我们可以用一些或者默认值或者不修改的行来做。 这些将会有例外,但是它们会很less,而且现在有点偏离你的水平。 你会到达那里。

(4)创build/修改纸张并避免。 .Activate和触摸尺寸

VBA初学者的一个陷阱就是他们使用ActiveWorkbookActiveSheet.Activate了很多。 这本身并不坏,但也不好。 使用起来很方便,但是如果将其并入真正复杂的子程序和函数中,将会引起无数的麻烦。

为了解决这个问题,我们首先介绍一下尺寸标注或者限定对象的概念。 这是通过首先声明关键字和数据types来完成的。 我不会深入研究这一点,因为有很多VBA教程可以阅读,所以我只想指出一些重要的教程。

假设您正在处理两个打开的工作簿。 我们可以为每个人创build一个“昵称”,所以你可以参考他们,而不必键入整个参考线。

 Dim SourceWbk As Workbook Dim TargetWbk As Workbook 

上面的两行TargetWbk是:“ SourceWbk / TargetWbk是我的昵称,我被定义为一个工作簿,所以我期待被引用到一个工作簿”。 现在我们已经为它们创build了维度,我们可以指出它们将代表什么。

 Set SourceWbk = ThisWorkbook Set TargetWbk = Workbooks("I AM THE MASTER REPORT") 

注意这里的“=”。 现在,我们已经基本上宣布,从现在开始, SourceWbk将引用包含此代码的工作簿,并且TargetWbk将引用名为“我是主报告”的开放工作簿。 现在我们来看看从SourceWbk复制到TargetWbk的简单操作。

 SourceWbk.Sheets("Sheet1").Copy After:=TargetWbk.Sheets("Sheet1") 

看起来很熟悉? 这是因为这与你的代码的这个logging块几乎相同:

 Sheets("Fresh Agent Leads").Select Sheets("Fresh Agent Leads").Copy After:=Workbooks( _ "MSS Call Routing Master List.xlsx").Sheets(1) 

现在,你可以走一步,自己命名表单,然后复制它们。 示例如下:

 Dim FAL As Worksheet 'Expects a worksheet. Dim LastSheet As Worksheet Set FAL = SourceWbk.Sheets("Fresh Agent Leads") Set LastSheet = TargetWbk.Sheets("Sheet1") 'You can use a number index or specific name FAL.Copy After:=LastSheet 

在这一点上,代码已经非常,非常短暂和甜蜜。 没有麻烦,你真正需要的唯一努力就是记住“昵称”是指什么。 请注意,您应该使用特定的字词作为variables名称。 尽可能使其个性化但合理。 简单地命名为Sh是一个很好的表单,但是它在一个文件中没有任何地方,每个文件有不同的目的。

(5) Application技巧

在Excel VBA中,可以通过一些操作来提高代码的效率。 毕竟是说完了,macros只是一个重复的动作。 运行一个录制或书面的两个将带你通过行动。 .Select将select特定的范围,你会看到他们被选中。 .Activate也会这样做,或多或less。 .Copy将显示那些“ant”和他们留下的亮点。 所有这些都会导致代码的更长时间的视觉执行。 这里步骤ScreenUpdating “技巧”。

请注意,这不是一个诡计。 大多数人认为它们是代码中非常重要的部分,但是将它们纳入“外行”VBA模块仍然有帮助。 其中一个最佳实践是在子例程开始处设置Application.ScreenUpdating = False ,然后在最后将其设置为True

ScreenUpdating将“冻结”你的屏幕,使所有事情都没有看到它们。 您将看不到要复制的项目或范围被选中。 您将看不到封闭的工作簿被打开和closures。 虽然这只会影响到Excel,但它是非常宝贵的。

Application技巧的快速和肮脏的列表(不要用作绝对参考!):

  • .ScreenUpdating(False / True ):当False时消除Excel的视觉更新。 复制粘贴或删除行时绝对必要。
  • 计算( xlCalculationAutomatic / xlCalculationSemiautomatic / xlCalculationManual):与“ Formulas > Calculation Optionsfunction区function类似,将其设置为“手动”将暂停所有计算。 强烈build议,尤其是当您更新VLOOKUPINDEX公式的负载所依赖的范围时。
  • .EnableEvents(False / True ):禁用基于触发事件的过程。 有点高级,但足以说,如果你有一些基于事件的更改自动macros触发,这将暂停他们赞成当前正在运行的macros。

有大量的其他人,这将是你最好的兴趣,了解他们大部分。 ;)

大的FINALE

下面是从您录制的macros中获取的示例代码,它使用了上述所有技术,并考虑了您在macros中执行的过程。 这不是你的整个代码。 阅读这个,testing这个,修改这个,你会在一天内改善很多。

 Sub RefinedCode() Dim SourceWbk As Workbook, TargetWbk As Workbook Dim FALSht As Worksheet, FALSht2 As Worksheet, MasterSht As Worksheet Application.ScreenUpdating = False 'We won't see the copy-paste and column deletion happening but they will happen. Set SourceWbk = ThisWorkbook Set TargetWbk = Workbooks("MSS Call Routing Master List") Set FALSht = SourceWbk.Sheets("Fresh Agent Leads") With TargetWbk Set MasterSht = .Sheets("Master") 'Basically reads as Set MasterSht = TargetWbk.Sheets("Master") FAL.Copy After:= .Sheets(1) Set FALSht2 = .Sheets("Fresh Agent Leads") End With With FALSht2 Union(.Range("A:A"),.Range("C:C"),.Range("E:O")).Delete With .Rows(1) .RowHeight = 30 .WrapText = True End With .Range("A1").Copy .Range("F1:F100") End With MasterSht.Name = "Call Router" TargetWbk.Save SourceWbk.Close Application.ScreenUpdating = True 'Return to default setting. End Sub 

希望这可以帮助。

我总是使用下面的行

 Application.ScreenUpdating = False 

closures使macros运行速度更快的屏幕更新。 只需将其添加到您的macros的开始。

真棒帮助在这里。 我希望有一个简单的方法来停止更改表单时的闪烁…无论如何,Application.ScreenUpdating并没有完全消除在Excel 2013中。