从VBA UserForm调用时,Outlook GAL无法成为最顶层的窗口

时间:2015-02-10 16:33:59

标签: excel vba excel-vba outlook userform

我有大约十个来自StackOverflow的回复,但没有一个回复我的问题。

我已在Excel VBA中为此特定项目创建了多个UserForms。 (注意:我没有关于VBA编程的正式培训,我所做的一切都是自学成才或通过复制其他人的代码收集。)在与多个这些表单连接时,我希望用户能够访问命令从公司的全局地址列表中选择用户名。使用表单上的命令按钮和以下功能,我可以执行此操作:

Public Function GetUsernameFromOutlook(sCap As String) As String
'fancy code to call Outlook dialog box to select names. 
'Badresult is the default, gives username of operator if they try to:
'   select more than one recipient
'   cancel out of the dialog box

Dim olApp As Object     ' Outlook.Application
Dim olDialog As Object  ' Outlook.SelectNamesDialog
Dim hwnd As Long

Set olApp = CreateObject("Outlook.Application")
Set olDialog = olApp.Session.GetSelectNamesDialog

With olDialog
    .Caption = sCap
    .ForceResolution = True
    .AllowMultipleSelection = False
    .NumberOfRecipientSelectors = olShowTo
    .ToLabel = "Select User"
    If .Display = False Then GoTo BadResult
    SetForegroundWindow (Excel.Application.hwnd)
    If .Recipients.Count <> 1 Then GoTo BadResult
    'Debug.Print .Recipients(1).Name
    'Debug.Print .Recipients(1).Address
    'Debug.Print .Recipients(1).AddressEntry.GetExchangeUser.Alias
    GetUsernameFromOutlook = .Recipients.Item(1).AddressEntry.GetExchangeUser.Alias
End With

 '   hwnd = FindWindow(vbNullString, sCap & ": Global Address List")


Set olApp = Nothing
Set olDialog = Nothing

Exit Function

BadResult:
    SetForegroundWindow (Excel.Application.hwnd)
    GetUsernameFromOutlook = Environ("UserName")

End Function

正如您所看到的,我尝试使用其他答案中建议的SetForegroundWindowFindWindow API调用。但是在导致问题之前,代码甚至没有到达这些行。

If .Display = False从Outlook中调出SelectNamesDialog框,但由于我的UserForm是模态的(我认为),它仍然是可见窗口。我被迫使用Alt-Tab切换到Outlook。然后,在选择名称或取消Outlook对话框之后,我需要再次按Alt-Tab返回Excel。
此外,因为代码正在等待来自Outlook框的响应,所以没有进一步的代码执行,因此在完成所有Alt-Tab切换之前,SetForegroundWindow甚至都不会发生。

已发布的其他解决方案提到使用MSWord调用,或从电子表格中查找信息或保存到电子表格。我正在尝试使用此调用来修改表单控件的标题或文本,例如命令按钮或文本框或文本标签。我只需要收集Outlook别名,因为我有另一个功能,可以根据别名从Outlook收集其他选定的信息,因此别名保存在表单上的标签(看不见)并转换为全名,缩写或e使用此其他功能根据需要发送邮件地址。

到目前为止,一切都很好,我真的很想将这个界面发布给我的测试人员,但我不想在他们点击“选择名称”按钮后向所有人解释使用Alt-Tab 。他们会相信他们的计算机已经锁定并重新启动。 (或者致电IT部门,他们会开始提出他们无法回答的问题。)

我很抱歉这个问题太长了,但我希望尽可能多地提供相关信息。我确信我需要澄清一些事情,所以请在回复中将您的问题发给我,我会尽力解释。谢谢你的时间。

2 个答案:

答案 0 :(得分:0)

Outlook对象模型不允许您指定通讯录对话框的父窗口 - 它始终是Outlook。

在扩展MAPI级别(C ++或Delphi)上,您可以在调用IAddbook::Address时指定窗口句柄,但不能从VBA执行此操作。

如果使用Redemption是一个选项,则可以在使用RDOSession对象之前设置RDOSelectNames。ParentWindow属性。

set Session = CreateObject("Redemption.RDOSession")
Session.MAPIOBJECT = Application.Session.MAPIOBJECT
Session.ParentWindow = Excel.Application.hwnd
set ABDialog = Session.GetSelectNamesDialog
ABDialog.Display true

答案 1 :(得分:0)

我刚刚度过了一个晚上,所以即使这个帖子已经有一年了,也应该有所帮助。 你应该尝试使用:

“olApp.ActiveWindow.Activate”

它总结了这个完全有效的功能:

enter Public Function GetUsernameFromOutlook(sCap As String) As String
'fancy code to call Outlook dialog box to select names.
  'Badresult is the default, gives username of operator if they try to:
'   select more than one recipient
'   cancel out of the dialog box

Dim olApp As Outlook.Application    ' Outlook.Application
Dim olDialog As Outlook.SelectNamesDialog
Dim hwnd As Long

Set olApp = New Outlook.Application
Set olDialog = olApp.Session.GetSelectNamesDialog
'Set olDialog = new Outlook.Application
With olDialog
.Caption = sCap
'.ForceResolution = True
.AllowMultipleSelection = False
.NumberOfRecipientSelectors = olShowTo
.ToLabel = "Select User"

olApp.ActiveWindow.Activate
 .display
If .Recipients.Count <> 1 Then GoTo BadResult
'Debug.Print .Recipients(1).Name
'Debug.Print .Recipients(1).Address
'Debug.Print .Recipients(1).AddressEntry.GetExchangeUser.Alias
GetUsernameFromOutlook = .Recipients.Item(1).AddressEntry
End With


Set olApp = Nothing
Set olDialog = Nothing

Exit Function

BadResult:

GetUsernameFromOutlook = "A voir ultérieurement"

End Function here