Outlook VBA如何提高浏览文件夹列表的速度
我目前正在编写一些代码,这样当我根据某些标准发送电子邮件时,它会将其保存在特定的文件夹中。我知道规则是这样做的,但相信我,制定这么多规则需要很长时间,而且是不现实的。这就是我要做的。发送电子邮件时,代码会查看电子邮件的标题以查找项目编号。然后弹出一个用户表单,用户可以根据自己的需要进行多项归档选择。 它首先使用VBA.SaveSetting方法保存项目编号 然后返回对象“objX”,它实际上就是正在发送的电子邮件对象。 所以在下面的代码中,我循环遍历一个公共文件夹列表。文件夹名称的第一部分是项目编号。我要查找的项目编号保存在“proj_folder”局部变量中。Outlook VBA如何提高浏览文件夹列表的速度,vba,outlook,Vba,Outlook,我目前正在编写一些代码,这样当我根据某些标准发送电子邮件时,它会将其保存在特定的文件夹中。我知道规则是这样做的,但相信我,制定这么多规则需要很长时间,而且是不现实的。这就是我要做的。发送电子邮件时,代码会查看电子邮件的标题以查找项目编号。然后弹出一个用户表单,用户可以根据自己的需要进行多项归档选择。 它首先使用VBA.SaveSetting方法保存项目编号 然后返回对象“objX”,它实际上就是正在发送的电子邮件对象。 所以在下面的代码中,我循环遍历一个公共文件夹列表。文件夹名称的第一部分是项目
所以我在所有文件夹中循环查找以“proj_folder”变量开头的文件夹名称。 它的工作很好,除了一个事实,它可以变得相当缓慢,如果有很多文件夹循环通过。 看看下面的代码,是否有人愿意分享一种方法来提高我的循环速度。现在,循环遍历30个文件夹大约需要2秒钟。有时,它可以得到多达200多个文件夹
Sub MoveProject(objX)
Dim objNS As Outlook.NameSpace
Dim projectParentFolder As Outlook.MAPIFolder
Dim objFolder As Outlook.MAPIFolder
Dim proj_folder As String
Dim intX As Long
'recall of the name of the folder saved from a previouly filed userform
proj_folder = VBA.GetSetting("mail filing", "num_projet", "num_proj", vbNullString)
sub_folder_1 = "Quebec"
sub_folder_2 = Left(proj_folder, 3)
Set objNS = Application.GetNamespace("MAPI")
Set projectParentFolder = objNS.Folders("Public Folder - UserAdress@server.com").Folders("All Public Folders").Folders(sub_folder1).Folders(sub_folder2)
'=============THIS IS THE PART WHERE I WOULD LIKE TO IMPROVE THE SPEED==============================
For intX = 1 To projectParentFolder.Folders.Count 'searching for folder name beginning
If Left(projectParentFolder.Folders.item(intX).Name, Len(proj_folder)) = proj_folder Then
Set objFolder = projectParentFolder.Folders.item(intX)
Exit For
End If
Next
objX.Move objFolder 'moving mail to objFolder
Set objX = Nothing
Set objFolder = Nothing
Set projectParentFolder = Nothing
Set objNS = Nothing
End Sub
一个循环中的点太多了。这是我的一个通用VBA速递站 设置属性或调用方法时,每个都是CPU中的函数调用。这意味着堆栈设置开销。函数调用比内联代码慢。出于同样的原因,在VBA中使用循环而不是函数 首先,不要反复指定所有这些属性。除非你改变它们,否则它们不会改变
With Selection.Find
.ClearFormatting
.Replacement.ClearFormatting
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchByte = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = False
.MatchFuzzy = False
For loop to go through each word pair
.Text = SrcText
.Replacement.Text = DestText
.Find.Execute Replace:=wdReplaceAll
Next
End With
最小化圆点
因此,如果您对性能感兴趣,请最小化点(每个点都是一个查找),尤其是在循环中
有两种方法。一种方法是,如果要多次访问,则将对象设置为最低的对象
eg(较慢)
(更快,因为每次使用对象时都会忽略一个点)
第二种方法是使用。一次只能有一个处于活动状态
这跳过了100次查找
with wsheet
For x = 1 to 100
msgbox .name
Next
end with
字符串压缩
不要一次连接一个字符的字符串。从VBScript程序员那里可以看到这一点。它需要50000字节以及许多分配和释放来生成一个100个字符的字符串
读取属性
不要重新读取未更改的属性,尤其是在进程外或后期绑定时。将它们放入一个变量中。读取变量比对象查找(也是一个函数调用,如果后期绑定,至少两个)和函数调用更快
变量
常量和文本在编译后基本相同
Const x = 5
msgbox x
与
msgbox 5
文本直接插入到代码中。字符串和对象变量具有管理器,这会产生开销。避免无缘无故地创建变量。这是一个无意义且缓慢的变量示例
x = "This is a string"
msgbox x
相比
const x = "This is a string"
msgbox x
或
对象类型
这里有两个概念-进程内或进程外和早期或晚期绑定
EXE文件连接到进程外。所有调用都通过RPC(一种网络协议)进行编组。Dllfiles正在处理中,函数调用通过跳转直接进行
早期绑定是set x=objecttype
。编写程序时会查找函数。在执行时,程序被硬编码为跳转到该函数的vtable中存储的地址
后期绑定设置为x=createobject(“objecttype”)
。每个函数调用都是这样的。“嗨,你有打印命令吗?”。“是的”,它回答说,“第三号命令”。“嗨,你能做第三个命令吗?”。“当然,结果是这样的”
来自Visual Basic概念(帮助的一部分)
通过优化Visual Basic解析对象引用的方式,可以使Visual Basic应用程序运行得更快。Visual Basic处理对象引用的速度可能受到以下因素的影响:
ActiveX组件是否已实现为进程内服务器或进程外服务器
对象引用是早期绑定还是后期绑定。通常,如果组件已作为可执行文件(.exe文件)的一部分实现,则它是进程外服务器,并在其自己的进程中运行。如果它已实现为动态链接库,则它是进程内服务器,并与客户端应用程序在同一进程中运行
使用进程内服务器的应用程序通常比使用进程外服务器的应用程序运行得更快,因为应用程序不必跨越进程边界来使用对象的属性、方法和事件。有关进程内和进程外服务器的更多信息,请参阅“进程内和进程外服务器”
如果对象引用使用声明为特定类变量的对象变量,则对象引用是早期绑定的。如果对象引用使用声明为泛型对象类变量的对象变量,则它们是后期绑定的。使用早期绑定变量的对象引用通常比使用晚期绑定变量的对象引用运行得更快
特定于Excel的
请从Microsoft人员处查看此链接。这是excel特有的,而不是VBA。自动计算和其他计算选项/屏幕更新等
.
编辑
我没有安装Outlook,所以类似这样的东西
删除点,为每个更改为枚举的,并将len
函数移到循环之外,这样就不会反复调用它
Set projectParentFolder = objNS.Folders("Public Folder - UserAdress@server.com").Folders("All Public Folders").Folders(sub_folder1).Folders(sub_folder2)
prog_folder_len = Len(Prog_Folder)
For Each Fldr in ProjectParentFolder.Folders
If Left(Fldr.Name, prog_folder_len) = proj_folder Then
Set objFolder = Fldr
Exit For
End If
Next
许多集合可以通过名称访问
类似于set objfolder=Fldr(Prog_Folder)
或set objfolder=Fldr.item(Prog_Folder)
的操作是否不起作用
集合由对象实现。所以我们不可能知道w
const x = "This is a string"
msgbox x
msgbox "This is a string"
Set projectParentFolder = objNS.Folders("Public Folder - UserAdress@server.com").Folders("All Public Folders").Folders(sub_folder1).Folders(sub_folder2)
prog_folder_len = Len(Prog_Folder)
For Each Fldr in ProjectParentFolder.Folders
If Left(Fldr.Name, prog_folder_len) = proj_folder Then
Set objFolder = Fldr
Exit For
End If
Next
set Table = CreateObject("Redemption.MAPITable")
Table.Item = projectParentFolder.Folders
Set Recordset = Table.ExecSQL("SELECT EntryID from Folder where Name like '" & proj_folder & "%' ")
If not Recordset.EOF Then
strEntryID = Recordset.Fields(0).Value
set objFolder = Application.Session.GetFolderFromID(strEntryID)
end If