我是编码的新手.这个宏运行缓慢,我希望有人可以帮我清理它.在此先感谢您的帮助.
我开发了代码来更新我公司的"呼叫路由器"工作表,其中包含从外部源购买的新线索.这些潜在客户以原始格式在名为Fresh Agents Leads的工作表中找到我们.一旦将"Fresh Agent Leads"表单复制到包含"Call Router"工作表的"MSS Call Routing Master List"文件中,宏就会减少原始数据,以便消除我们不使用的部分.然后它重新格式化剩余的内容以匹配旧呼叫路由器工作表的格式并合并这两者.然后,它将新的主表重命名为Call Router.
该代码旨在从包含Fresh Agent Leads Sheet的工作簿内部开始.在执行代码之前,指示用户在桌面上打开Fresh Agents Leads File和MSS Call Routing Master List.
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
Jerome Monti.. 9
虽然这段代码几乎属于CR而不是SO,因为我手上有很多时间,所以我决定至少发布一些关于代码的内容.
===
一些提示:
避免.Select
和.Activate
尽可能多地.录制宏是VBA的良好开端,但第一个重要步骤是离开这些属性提供的"舒适区".一开始,它们很好,但从长远来看它们肯定会产生问题.
阅读以下"基本"程序:复制/粘贴/插入范围,创建/删除工作表,以及确定具有相关数据的工作表或范围的最后行/列.这三个是你最好的朋友.通过学习这三个,你可以在Excel VBA中操作很多.
在(2)之后,开始学习如何标注变量和/或对象.把行话放在一边,这基本上就像给每个重要的事情你正在研究"昵称".假设您正在处理3张纸.你不想继续引用ThisWorkbook.Sheets("Sheet1")
,依此类推.你更愿意Sh1
或者更喜欢Sh2
.
了解如何一堆类似的程序一起使用Union
,With
或等.这与上面的(1)同时进行.稍后你会看到一个例子.
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中将命令绑定在一起与在宏中执行它的方式不同.由于记录了宏,所以一切都基于实时修改.在"已写入"VBA中,您可以指定一个操作,该操作将允许您对多个对象应用单个操作.例如,您想要删除列A和C,同时将所有相关数据移到左侧.
录制宏时,您可以同时选择A和C并删除它们.然而,大多数初学者走安全通道,并记录列删除每次一个它-而安全-是非常违反直觉.删除前选择两者是最佳选择.
在书面VBA中,上面的第二种方法是大规模的禁忌(或者至少,它不是常态).除非有特定和必要的原因,否则将相似的命令捆绑在一起就是惯例,因为它既可以在很大程度上消除错误,又不会占用大量资源.
在你的代码中......
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.如下所示的简洁方法将非常快速有效地解决这个问题.
Union(Range("A:A"),Range("C:C"),Range("E:E"),Range("F:O")).Delete
Union
是你早期最好的朋友之一.与数学中的集合表示法一样,您指定的范围一起放在一组范围中并同时处理(在这种情况下,.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
...可以减少到:
With Columns("C:C") .ColumnWidth = 8.29 .HorizontalAlignment = xlCenter End With With Rows(1:1) .RowHeight = 30 .WrapText = True End With
基本上,我们在这里做了两件事.首先,我们锚定在C列上,并对其执行了两个操作:设置列宽,然后设置水平对齐.在锚定到C列并修改它之后,我们将锚更改为整个第1行,我们修改它的高度并将其设置为将文本换行到单元格宽度.从24行开始,我们将宏块减少到只有8行.为简洁起见,这是怎么回事?:)
为什么我没有其他线路?与前面的示例(Union
)中一样,我们可以使用一些默认值或未修改的行.这些会有例外情况,但它们会很少而且现在有点偏离你的水平.你会到达那里.
(4)创建/修改工作表并避免.Activate
和触摸尺寸
一个在VBA初学者的陷阱是,他们使用ActiveWorkbook
,ActiveSheet
和.Activate
不少.这本身并不坏,但它也不好.它使用起来很方便,但是如果将它合并到非常复杂的子程序和函数中,它会引起无数的麻烦.
为了解决这个问题,我们首先考虑对对象进行尺寸标注或限定.这是通过首先声明关键字然后声明数据类型来完成的.我不会深入研究这个问题,因为你可以阅读很多VBA教程,所以我只想指出一些重要的教程.
假设您正在处理两个打开的工作簿.我们可以为每个人创建一个"昵称",这样你就可以参考它们,而无需输入整行参考.
Dim SourceWbk As Workbook Dim TargetWbk As Workbook
上面的两行读作:" SourceWbk
/ TargetWbk
是我的昵称,我的尺寸是工作簿,所以我期待被引用到工作簿".现在我们已经为它们创建了尺寸,我们可以指出它们将代表什么.
Set SourceWbk = ThisWorkbook Set TargetWbk = Workbooks("I AM THE MASTER REPORT")
注意这里的"=".现在,我们基本上宣称从现在开始,SourceWbk
将引用包含此代码的工作簿,并将TargetWbk
引用名为"我是主要报告" 的打开工作簿.现在,让我们来看看从复制片的简单的动作SourceWbk
来TargetWbk
.
SourceWbk.Sheets("Sheet1").Copy After:=TargetWbk.Sheets("Sheet1")
看起来很熟悉?那是因为这与您记录的代码块几乎相同:
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
在这一点上,代码已经非常非常简短和甜蜜.没有麻烦,你真正需要的唯一努力就是记住"昵称"所指的内容.需注意,您也应特定的词不被使用作为变量名.尽可能使其个性化但合理.简单地命名一个工作表Sh
是好的,但它不会让你在一个文件中,每个文件有100张不同的目的.
(5)Application
Trickbook
在Excel VBA中,您可以通过一些操作来提高代码的效率.毕竟说完了,宏只是一个重复的动作.运行录制或书面录制将带您完成操作..Select
将选择特定范围,您将看到它们被选中..Activate
会做同样的,或多或少..Copy
将向您展示那些"蚂蚁"以及它们留下的亮点.所有这些都有助于实现代码的更长且通常草率的可视化执行.这里是ScreenUpdating
"技巧"的步骤.
请注意,这不是一个绝招.大多数人认为它们是代码中非常重要的部分,但它们包含在"外行"VBA模块中仍然很有帮助.最佳实践之一是Application.ScreenUpdating = False
在子程序的开头设置,然后将其设置回True
最后.
ScreenUpdating
将"冻结"你的屏幕,让一切都发生,而不用你看到它们.您将看不到要复制的项目或范围被选中.您将看不到已关闭的工作簿被打开和关闭.虽然这只会在您调用它时影响Excel,但它仍然具有无可估量的价值.
一个快速而脏的列表(不要用它作为绝对参考!)的Application
技巧:
.ScreenUpdating(False/True):消除Excel的可视更新False
.复制粘贴或删除行时绝对必要.
.Calculation(xlCalculationAutomatic/xlCalculationSemiautomatic/xlCalculationManual):与Formulas > Calculation Options
功能区功能类似,将其设置为手动将暂停所有计算.强烈推荐,尤其是当您更新依赖于负载VLOOKUP
或INDEX
公式的范围时.
.EnableEvents(False/True):禁用基于触发事件的过程.有点高级,但足以说如果你在基于事件的更改上有一些自动宏触发,这将暂停它们以支持当前运行的宏.
还有很多其他人,了解大部分内容将符合您的最佳利益.;)
大结局
以下是从您录制的宏中获取的示例代码,它使用了上述所有技术,并考虑了您在宏上执行的过程.这不是你的整个代码.阅读本文,测试一下,修改它,你会在一天内改进很多.
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
希望这可以帮助.
虽然这段代码几乎属于CR而不是SO,因为我手上有很多时间,所以我决定至少发布一些关于代码的内容.
===
一些提示:
避免.Select
和.Activate
尽可能多地.录制宏是VBA的良好开端,但第一个重要步骤是离开这些属性提供的"舒适区".一开始,它们很好,但从长远来看它们肯定会产生问题.
阅读以下"基本"程序:复制/粘贴/插入范围,创建/删除工作表,以及确定具有相关数据的工作表或范围的最后行/列.这三个是你最好的朋友.通过学习这三个,你可以在Excel VBA中操作很多.
在(2)之后,开始学习如何标注变量和/或对象.把行话放在一边,这基本上就像给每个重要的事情你正在研究"昵称".假设您正在处理3张纸.你不想继续引用ThisWorkbook.Sheets("Sheet1")
,依此类推.你更愿意Sh1
或者更喜欢Sh2
.
了解如何一堆类似的程序一起使用Union
,With
或等.这与上面的(1)同时进行.稍后你会看到一个例子.
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中将命令绑定在一起与在宏中执行它的方式不同.由于记录了宏,所以一切都基于实时修改.在"已写入"VBA中,您可以指定一个操作,该操作将允许您对多个对象应用单个操作.例如,您想要删除列A和C,同时将所有相关数据移到左侧.
录制宏时,您可以同时选择A和C并删除它们.然而,大多数初学者走安全通道,并记录列删除每次一个它-而安全-是非常违反直觉.删除前选择两者是最佳选择.
在书面VBA中,上面的第二种方法是大规模的禁忌(或者至少,它不是常态).除非有特定和必要的原因,否则将相似的命令捆绑在一起就是惯例,因为它既可以在很大程度上消除错误,又不会占用大量资源.
在你的代码中......
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.如下所示的简洁方法将非常快速有效地解决这个问题.
Union(Range("A:A"),Range("C:C"),Range("E:E"),Range("F:O")).Delete
Union
是你早期最好的朋友之一.与数学中的集合表示法一样,您指定的范围一起放在一组范围中并同时处理(在这种情况下,.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
...可以减少到:
With Columns("C:C") .ColumnWidth = 8.29 .HorizontalAlignment = xlCenter End With With Rows(1:1) .RowHeight = 30 .WrapText = True End With
基本上,我们在这里做了两件事.首先,我们锚定在C列上,并对其执行了两个操作:设置列宽,然后设置水平对齐.在锚定到C列并修改它之后,我们将锚更改为整个第1行,我们修改它的高度并将其设置为将文本换行到单元格宽度.从24行开始,我们将宏块减少到只有8行.为简洁起见,这是怎么回事?:)
为什么我没有其他线路?与前面的示例(Union
)中一样,我们可以使用一些默认值或未修改的行.这些会有例外情况,但它们会很少而且现在有点偏离你的水平.你会到达那里.
(4)创建/修改工作表并避免.Activate
和触摸尺寸
一个在VBA初学者的陷阱是,他们使用ActiveWorkbook
,ActiveSheet
和.Activate
不少.这本身并不坏,但它也不好.它使用起来很方便,但是如果将它合并到非常复杂的子程序和函数中,它会引起无数的麻烦.
为了解决这个问题,我们首先考虑对对象进行尺寸标注或限定.这是通过首先声明关键字然后声明数据类型来完成的.我不会深入研究这个问题,因为你可以阅读很多VBA教程,所以我只想指出一些重要的教程.
假设您正在处理两个打开的工作簿.我们可以为每个人创建一个"昵称",这样你就可以参考它们,而无需输入整行参考.
Dim SourceWbk As Workbook Dim TargetWbk As Workbook
上面的两行读作:" SourceWbk
/ TargetWbk
是我的昵称,我的尺寸是工作簿,所以我期待被引用到工作簿".现在我们已经为它们创建了尺寸,我们可以指出它们将代表什么.
Set SourceWbk = ThisWorkbook Set TargetWbk = Workbooks("I AM THE MASTER REPORT")
注意这里的"=".现在,我们基本上宣称从现在开始,SourceWbk
将引用包含此代码的工作簿,并将TargetWbk
引用名为"我是主要报告" 的打开工作簿.现在,让我们来看看从复制片的简单的动作SourceWbk
来TargetWbk
.
SourceWbk.Sheets("Sheet1").Copy After:=TargetWbk.Sheets("Sheet1")
看起来很熟悉?那是因为这与您记录的代码块几乎相同:
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
在这一点上,代码已经非常非常简短和甜蜜.没有麻烦,你真正需要的唯一努力就是记住"昵称"所指的内容.需注意,您也应特定的词不被使用作为变量名.尽可能使其个性化但合理.简单地命名一个工作表Sh
是好的,但它不会让你在一个文件中,每个文件有100张不同的目的.
(5)Application
Trickbook
在Excel VBA中,您可以通过一些操作来提高代码的效率.毕竟说完了,宏只是一个重复的动作.运行录制或书面录制将带您完成操作..Select
将选择特定范围,您将看到它们被选中..Activate
会做同样的,或多或少..Copy
将向您展示那些"蚂蚁"以及它们留下的亮点.所有这些都有助于实现代码的更长且通常草率的可视化执行.这里是ScreenUpdating
"技巧"的步骤.
请注意,这不是一个绝招.大多数人认为它们是代码中非常重要的部分,但它们包含在"外行"VBA模块中仍然很有帮助.最佳实践之一是Application.ScreenUpdating = False
在子程序的开头设置,然后将其设置回True
最后.
ScreenUpdating
将"冻结"你的屏幕,让一切都发生,而不用你看到它们.您将看不到要复制的项目或范围被选中.您将看不到已关闭的工作簿被打开和关闭.虽然这只会在您调用它时影响Excel,但它仍然具有无可估量的价值.
一个快速而脏的列表(不要用它作为绝对参考!)的Application
技巧:
.ScreenUpdating(False/True):消除Excel的可视更新False
.复制粘贴或删除行时绝对必要.
.Calculation(xlCalculationAutomatic/xlCalculationSemiautomatic/xlCalculationManual):与Formulas > Calculation Options
功能区功能类似,将其设置为手动将暂停所有计算.强烈推荐,尤其是当您更新依赖于负载VLOOKUP
或INDEX
公式的范围时.
.EnableEvents(False/True):禁用基于触发事件的过程.有点高级,但足以说如果你在基于事件的更改上有一些自动宏触发,这将暂停它们以支持当前运行的宏.
还有很多其他人,了解大部分内容将符合您的最佳利益.;)
大结局
以下是从您录制的宏中获取的示例代码,它使用了上述所有技术,并考虑了您在宏上执行的过程.这不是你的整个代码.阅读本文,测试一下,修改它,你会在一天内改进很多.
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
希望这可以帮助.