Excel VBA中Outlook SendUsingAccount为何有时无需Set语句?
Outlook VBA中SendUsingAccount属性的Set语句使用疑惑
我在跟进相关讨论时发现,部分回复设置邮件项的SendUsingAccount属性时用了Set语句,部分却没有,这让我很困惑。我的VBA代码主要做两件事:
- 在Outlook可用账户中,查找与目标发件邮箱标识字符串匹配的账户对象
- 创建新邮件项并设置其发送账户
实际测试中,步骤1给对象变量赋值必须用Set,但步骤2设置SendUsingAccount属性时加Set就会触发91运行时错误,不能用。我猜测这里的账户对象可能被自动转换为SMTP地址字符串,Outlook后台通过地址匹配对应账户。
关键代码片段
a) 变量声明
Public g_olapp As outlook.Application Public g_ol_account As outlook.Account Private olmsg As outlook.MailItem
b) 初始化操作
Set g_olapp = New outlook.Application Set g_ol_account = find_account(g_from_email, b_err)
c) 账户查找函数(返回对象,必须用Set)
Private Function find_account(s As String, b As Boolean) As outlook.Account Dim p_olaccount As outlook.Account Dim s_send_from As String s_send_from = UCase(s) If s_send_from = "" Then If MsgBox("No account specified, do you want to use the default account <SPJUDGE> ?", Title:=box_title, Buttons:=vbYesNo + vbQuestion) = vbNo Then b = True Exit Function End If s_send_from = "SPJUDGE" End If Set find_account = Nothing For Each p_olaccount In g_olapp.Session.Accounts If (Not InStr(UCase(p_olaccount.SmtpAddress), s_send_from) = 0) Then Set find_account = p_olaccount s = p_olaccount.SmtpAddress Exit Function End If Next MsgBox "Account <" & s_send_from & "> not found" _ & String(2, 13) & "Program terminating", Title:=box_title, _ Buttons:=vbOKOnly + vbCritical b = True End Function
d) 创建邮件项
Set olmsg = make_new_email(g_olapp, s_email)
e) 创建邮件对象的函数
Public Function make_new_email(olapp As Object, s As String) As outlook.MailItem Dim arr() As String Dim jloc As Integer Dim jlb As Integer Dim recip As outlook.Recipient Set make_new_email = olapp.CreateItem(olMailItem) ' MsgBox g_ol_account note this does work. With make_new_email .SendUsingAccount = g_ol_account ' 此处为何不能用Set? If gb_set_reply Then .ReplyRecipients.add (g_reply_to_email) End If .OriginatorDeliveryReportRequested = b_askfor_receipts .ReadReceiptRequested = b_askfor_receipts End With s = Replace(s, "SIMON JUDGE", "", , , vbTextCompare) arr = Split(s, ";") ' changed from comma Nov 2023 jlb = LBound(arr) For jloc = jlb To UBound(arr) Set recip = make_new_email.Recipients.add(Trim(arr(jloc))) If jloc = jlb Then recip.Type = olTo Else recip.Type = olCC End If Next jloc End Function
原因解析
VBA中Set语句的作用是给对象变量赋值,而SendUsingAccount是MailItem的一个属性,虽然它的类型是Account对象,但Outlook对象模型对这个属性的设计是直接接收Account对象赋值,不需要额外加Set。
- 步骤1中
g_ol_account是一个Account类型的对象变量,给它赋值必须用Set,这是VBA对象变量赋值的语法要求。 - 步骤2中是给
MailItem的属性赋值,属性本身已经封装了对象的接收逻辑,加Set反而会违反语法规则,触发运行时错误91(对象变量或With块变量未设置)。
另外,关于你猜测的“账户对象被转换为SMTP地址”:实际上SendUsingAccount确实可以直接接收SMTP字符串赋值,Outlook会自动匹配对应账户;但直接传入Account对象也是支持的,两种方式都有效,只是语法上对象赋值不需要Set。
内容的提问来源于stack exchange,提问作者Simon J
相关产品推荐
相关产品推荐

