Change focus from Outlook to Excel - excel

I have Outlook VBA code that gets specific text inside 'subject' mail, then opens and searches an Excel workbook for that text and if the text exists, shows a userform.
How do I set the focus from Outlook to Excel? The userform stays hidden and only shows when I click on the Excel window to activate it.
Sub abrirexecel()
Dim ExApp As Excel.Application, planilha As String
On Error Resume Next
planilha = "'C:\Users\Dyme\" & Format(Date, "yyyy-mm-dd") & "CodesSearch.xlsm'!funcaof12"
'funcaof12 is the macro name that opens userform
Set ExApp = GetObject(, "Excel.Application")
If Not ExApp Is Nothing Then
ExApp.Run planilha
End If
End Sub
Does anyone may give a help?

You can set an Excel userform to open on Top by adding in a calling function within the userform. If you call this from Outlook it will open the form on top without activating Excel currently (some work for the calling code is needed to properly close the excel session)
For Example:
In The Userform code
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Sub UserForm_Activate()
'check if we are using XL97 or not (hWndUF global variable)
hWndUF = IIf(Val(Application.Version) < 9, FindWindow("ThunderXFrame", Me.Caption), FindWindow("ThunderDFrame", Me.Caption))
End Sub
In the Excel Module
Private Declare Function SetWindowPos Lib "user32" (ByVal hWnd As Long, ByVal hWndInsertAfter As Long, _
ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Const SWP_NOSIZE = &H1, SWP_NOMOVE = &H2, HWND_TOPMOST = -1, GW_HWNDNEXT = 2
Private Const FLAGS As Long = SWP_NOMOVE Or SWP_NOSIZE
Public hWndUF As Long
Public Function ShowUserForm()
Dim uf As Object: Set uf = UserForm1
uf.Show vbModeless
If hWndUF <> 0 Then SetWindowPos hWndUF, HWND_TOPMOST, 0, 0, 0, 0, FLAGS
End Function
Then in the Outlook module (this is dirty code and needs better object control; may look at later)
Sub ShowExcelUserForm()
' Requires reference: Microsoft Excel x.0 Data Objects library
Dim ExApp As Excel.Application: Set ExApp = New Excel.Application 'Set ExApp = GetObject(, "Excel.Application")
If Not ExApp Is Nothing Then
ExApp.Run "'C:\Users\snapier\Desktop\Stack Overflow 2019.xlsm'!ShowUserForm"
End If
End Sub

Related

Best way to activate an unsaved workbook

I have various code to create reports. The reports are added to a new workbook that does not get saved, the theory being that the user can choose whether to save the workbook or just close it after looking at the results. My code below will activate the unsaved workbook.
Sub ActivateWorkbook(wbResults As Workbook)
Dim objWindow As Window
With Application
.VBE.MainWindow.WindowState = vbext_ws_Minimize
For Each objWindow In .Windows
With objWindow
If .Caption <> wbResults.Name Then .WindowState = xlMinimized
End With
Next objWindow
With .Windows(wbResults.Name)
.WindowState = xlMaximized
.Activate
End With
End With
End Sub
This works okay with a single monitor. But if there is already more than one workbook and they are different monitors, it minimises windows in both (all) monitors and looks less than ideal. I am thinking that if I am able to identify which monitor has the active workbook, I could only minimize windows for that monitor (including the VBE, if required).
In reply to chris neilsen, I will include some basic code to illustrate what I'm calling the above procedure with. Please keep in mind that each procedure is varied in purpose and most of the code in each doesn't really pertain to this particular problem.
Sub ExampleCode()
Dim wbXXX As Workbook
Set wbXXX = Workbooks.Add
With wbXXX
'Main code here
End With
Call ActivateWorkbook(wbXXX)
Set wbXXX = Nothing
End Sub
Thanks to anybody trying to help. It is appreciated.
Okay, this seems to be working for me. It's not pretty. Note that "Microsoft Visual Basic for Applications Extensibility 5.3" is required to minimise the VBE, which is where the code is being run from, not the main Excel application. In any case, Activate has not worked for me reliably in the past. If it works for you, no need for any of this I guess. If anybody is game to test it, please let me know how you go. I have only tested on a dual monitor setup so far.
Objective: Show the new workbook in the same monitor as the active workbook when Activate does not work.
Private Declare PtrSafe Function FindWindow _
Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) _
As LongPtr
Private Declare PtrSafe Function MonitorFromWindow _
Lib "user32" _
(ByVal hwnd As LongPtr, _
ByVal dwFlags As Long) _
As LongPtr
Private Declare PtrSafe Function EnumDisplayMonitors _
Lib "user32.dll" _
(ByVal hdc As Long, _
ByRef lprcClip As Any, _
ByVal lpfnEnum As Long, _
ByVal dwData As Long) _
As Long
Private Declare PtrSafe Function GetSystemMetrics _
Lib "user32" _
(ByVal Index As Long) _
As Long
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Const MONITOR_DEFAULTTONEAREST = &H2
Private Const SM_CMONITORS As Long = 80
Private hWndMonitor As LongPtr
Private hActiveWorkbook As LongPtr
Private hVBE As LongPtr
Private lngMode As Long
Function MonitorCount() As Long
MonitorCount = GetSystemMetrics(SM_CMONITORS)
End Function
Function MonitorsAreTheSame() As Boolean
MonitorsAreTheSame = True
'Count of monitors
If MonitorCount > 1 Then
'Check the ActiveWorkbook
lngMode = 0
hWndMonitor = FindWindow("XLMAIN", Application.Caption)
EnumDisplayMonitors ByVal 0&, ByVal 0&, AddressOf MonitorEnumProc, ByVal 0&
'Check the VBE
lngMode = 1
hWndMonitor = FindWindow("wndclass_desked_gsk", Application.VBE.MainWindow.Caption)
EnumDisplayMonitors ByVal 0&, ByVal 0&, AddressOf MonitorEnumProc, ByVal 0&
MonitorsAreTheSame = CBool(hActiveWorkbook = hVBE)
End If
End Function
Private Function MonitorEnumProc(ByVal hMonitor As Long, ByVal hdcMonitor As Long, lprcMonitor As RECT, ByVal dwData As Long) As Long
If MonitorFromWindow(hWndMonitor, MONITOR_DEFAULTTONEAREST) = hMonitor Then
Select Case lngMode
Case 0
hActiveWorkbook = CStr(hMonitor)
Case 1
hVBE = CStr(hMonitor)
End Select
End If
MonitorEnumProc = MonitorCount
End Function
Sub Test()
Dim wbkTest As Workbook
Set wbkTest = Workbooks.Add
Call ActivateWorkbook(wbkTest)
Set wbkTest = Nothing
End Sub
Sub ActivateWorkbook(wbkResults As Workbook)
Dim objWindow As Window
With Application
If MonitorsAreTheSame = True Then
.VBE.MainWindow.WindowState = vbext_ws_Minimize
For Each objWindow In .Windows
With objWindow
If .Left = Application.VBE.MainWindow.Left Then
If .Caption <> wbkResults.Name Then .WindowState = xlMinimized
End If
End With
Next objWindow
Else
For Each objWindow In .Windows
With objWindow
If .Left <> Application.VBE.MainWindow.Left Then
If .Caption <> wbkResults.Name Then .WindowState = xlMinimized
End If
End With
Next objWindow
End If
.Windows(wbkResults.Name).WindowState = xlMaximized
AppActivate (.Caption)
End With
End Sub
this should be sufficient - no second sub for activation needed. These should show the new workbook in the foreground, no other windows changed.
Sub ExampleCode()
Dim wbXXX As Workbook
Set wbXXX = Workbooks.Add
With wbXXX
'Main code here
End With
wbXXX.Activate
Set wbXXX = Nothing
End Sub

Excel.exe still running after using Application.Quit

I'm trying to simplify a report template by writing VBA code that checks an Excel Workbook and fills in the Word document.
The code fails to terminate the Excel.exe process in Task Manager.
I tried solutions proposed here, other forums and in Microsoft's documentation. I gather it has to do with COM objects still existing when running the Application.Quit method but can't figure out where those come from.
When reducing the code down to it's most basic components there's no Excel.exe process still in Task Manager:
Private Sub Hämta_Click()
Dim XL As Excel.Application
Set XL = New Excel.Application
XL.Quit
Set XL = Nothing
End Sub
But as soon as I add to it, Excel.exe keeps running in Task Manager:
Private Sub Hämta_Click()
Dim XL As Excel.Application
Set XL = New Excel.Application
Dim wkb As Excel.Workbook
Set wkb = XL.Workbooks.Open("C:\Example.xls")
wkb.Close (False)
Set wkb = Nothing
XL.Quit
Set XL = Nothing
End Sub
I also tried this code with the same result:
Private Sub Hämta_Click()
Dim XL As Object
Set XL = CreateObject("Excel.Application")
Dim wkb As Object
Set wkb = XL.Workbooks.Open("K:\Uppdrag.xls")
wkb.Close (False)
Set wkb = Nothing
XL.Quit
Set XL = Nothing
End Sub
The above two macros keep creating instances of Excel.exe which are not closed.
I've seen examples where code snippets are included that kills the process via Task Manager, but I don't understand the reason for the above not working.
The only workaround I found is to not include the XL.Quit method and instead set XL.Visible = True and let the user manually close the window.
Based on the comments it does not seem to be possible to find the root cause why the newly created excel instance cannot be finished in a "normal" way.
Based on the code here one can just kill the process
Option Explicit
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Function AdjustTokenPrivileges Lib "advapi32.dll" (ByVal TokenHandle As Long, ByVal DisableAllPrivileges As Long, NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Long, PreviousState As TOKEN_PRIVILEGES, ReturnLength As Long) As Long
Private Declare Function OpenProcessToken Lib "advapi32.dll" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long
Private Declare Function LookupPrivilegeValue Lib "advapi32.dll" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, lpLuid As LUID) As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Type LUID
LowPart As Long
HighPart As Long
End Type
Private Type LUID_AND_ATTRIBUTES
pLuid As LUID
Attributes As Long
End Type
Private Type TOKEN_PRIVILEGES
PrivilegeCount As Long
TheLuid As LUID
Attributes As Long
End Type
Function ProcessTerminate(Optional lProcessID As Long, Optional lHwndWindow As Long) As Boolean
Dim lhwndProcess As Long
Dim lExitCode As Long
Dim lRetVal As Long
Dim lhThisProc As Long
Dim lhTokenHandle As Long
Dim tLuid As LUID
Dim tTokenPriv As TOKEN_PRIVILEGES, tTokenPrivNew As TOKEN_PRIVILEGES
Dim lBufferNeeded As Long
Const PROCESS_ALL_ACCESS = &H1F0FFF, PROCESS_TERMINATE = &H1
Const ANYSIZE_ARRAY = 1, TOKEN_ADJUST_PRIVILEGES = &H20
Const TOKEN_QUERY = &H8, SE_DEBUG_NAME As String = "SeDebugPrivilege"
Const SE_PRIVILEGE_ENABLED = &H2
On Error Resume Next
If lHwndWindow Then
'Get the process ID from the window handle
lRetVal = GetWindowThreadProcessId(lHwndWindow, lProcessID)
End If
If lProcessID Then
'Give Kill permissions to this process
lhThisProc = GetCurrentProcess
OpenProcessToken lhThisProc, TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY, lhTokenHandle
LookupPrivilegeValue "", SE_DEBUG_NAME, tLuid
'Set the number of privileges to be change
tTokenPriv.PrivilegeCount = 1
tTokenPriv.TheLuid = tLuid
tTokenPriv.Attributes = SE_PRIVILEGE_ENABLED
'Enable the kill privilege in the access token of this process
AdjustTokenPrivileges lhTokenHandle, False, tTokenPriv, Len(tTokenPrivNew), tTokenPrivNew, lBufferNeeded
'Open the process to kill
lhwndProcess = OpenProcess(PROCESS_TERMINATE, 0, lProcessID)
If lhwndProcess Then
'Obtained process handle, kill the process
ProcessTerminate = CBool(TerminateProcess(lhwndProcess, lExitCode))
Call CloseHandle(lhwndProcess)
End If
End If
On Error GoTo 0
End Function
And you just use the code like that
Sub TestIt()
Dim xlApp As Object
Set xlApp = CreateObject("Excel.Application")
' Do something with xlApp
'Terminate the process
ProcessTerminate , xlApp.hwnd
End Sub
Try to declare and use a workbooks variable then set it to nothing at the end of your code

How to make an Excel instance visible if there are no open workbooks using VBA

I have several instances of Excel running, maybe up to 4 instances. One of these (let's call in instance A) usually does not have an open workbook. It is used by one of the other instances (let's call it instance B) to open a workbook in instance A, add, change data, then save and close that workbook, thus the instance where these changes are being made (instance A) returns to a state where there are no open workbooks. I do it this way because it is much faster than having the workbook with the code (instance B) open a workbook, perform these tasks and then close the workbook.
My problem is this: From time to time, for debugging purposes mostly, it is desirable to make instance A visible, but what I'm finding is that an instance without an open workbook cannot be made visible, or at least this is what I'm concluding. I am using Excel 2016, 64 bit. My code to do this is:
Private Sub cmdMakeSelectionVisible_Click()
Dim strng As String
Dim lCol As Long, lRow As Long
Dim oXLApp As Excel.Application
Dim bFoundInstance As Boolean
Dim wb_Actress As Workbook
With Me.lstXL '<--| refer to your listbox: change "ListBox1" with your actual listbox name
For lRow = 0 To .ListCount - 1 '<--| loop through listbox rows
If .Selected(lRow) Then '<--| if current row selected
For lCol = 0 To .ColumnCount - 1 '<--| loop through listbox columns
strng = strng & .List(lRow, lCol) & " | " '<--| build your output string
If lCol = 1 Then
MsgBox .List(lRow, lCol)
bFoundInstance = GetReferenceToXLApp(.List(lRow, lCol), oXLApp)
MsgBox oXLApp.Caption
Set wb_Actress = oXLApp.Workbooks.Open("T:\-1996\Dummy Performer's Book.xlsm")
oXLApp.Visible = True
wb_Actress.Close
End If
Next lCol
MsgBox "you selected" & vbCrLf & Left(strng, (Len(strng) - 1)) '<--| show output string (after removing its last character ("|"))
Exit For '<-_| exit loop
End If
Next lRow
End With
End Sub
Inside the For Loops there is an If statement and in that If statement if the instance in question opens a workbook, then the code works. If the instance does not open a workbook and it contains no children, it does not work. If at that point I test to see if oXApp.Visible is true, it is true, but the instance remains hidden.
The question is, is there any way around this without opening a workbook, make the instance visible, then closing the workbook? I still consider myself a novice when it comes to VBA. There may be a totally different approach other than using the handle to the desired instance.
Thanks for looking and helping.
Edit:
The code for GetReferenceToXLApp is:
Public Function GetReferenceToXLApp(hWndXL As Long, oXLApp As Object) As Boolean
Dim hWinDesk As Long
Dim hWin7 As Long
Dim obj As Object
Dim iID As GUID
'// Rather than explaining, go read
'// http://msdn.microsoft.com/en-us/library/windows/desktop/ms687262(v=vs.85).aspx
Call IIDFromString(StrPtr(IID_IDispatch), iID)
'// We have the XL App (Class name XLMAIN)
'// This window has a child called 'XLDESK' (which I presume to mean 'XL desktop')
'// XLDesk is the container for all XL child windows....
hWinDesk = FindWindowEx(hWndXL, 0&, "XLDESK", vbNullString)
'// EXCEL7 is the class name for a Workbook window (and probably others, as well)
'// This is used to check there is actually a workbook open in this instance.
hWin7 = FindWindowEx(hWinDesk, 0&, "EXCEL7", vbNullString)
'// Deep API... read up on it if interested.
'// http://msdn.microsoft.com/en-us/library/windows/desktop/dd317978(v=vs.85).aspx
If AccessibleObjectFromWindow(hWin7, OBJID_NATIVEOM, iID, obj) = RETURN_OK Then
Set oXLApp = obj.Application
GetReferenceToXLApp = True
End If
End Function
And
Private Declare PtrSafe Function IIDFromString Lib "ole32" _
(ByVal lpsz As LongPtr, ByRef lpiid As GUID) As Long
And
Private Declare PtrSafe Function FindWindowEx Lib "User32" Alias "FindWindowExA" _
(ByVal hWnd1 As LongPtr, ByVal hWnd2 As LongPtr, ByVal lpsz1 As String, _
ByVal lpsz2 As String) As Long
Seems to work...
Dim oApp As Excel.Application
Sub TT()
Set oApp = New Excel.Application
'oApp.Workbooks.Add
oApp.Visible = True
Debug.Print oApp.HWnd, Application.HWnd
Debug.Print oApp.Caption, Application.Caption
Application.Wait Now + TimeSerial(0, 0, 2)
AppActivate Application.Caption
Application.Wait Now + TimeSerial(0, 0, 2)
AppActivate oApp.Caption
End Sub

Communication between Microsoft Office instances in VBA

I'm trying to create a VBA script on an instance A for copying basic stuff on an instance B of Word generated by a tier program with a temporary and unpredictable name , so I'm not able to use the GetObject(Path,) to get this instance with the Path because I don't have it.
My temporary solution is a PowerShell running this command from the Instance A to get the name of all Windows with "Word" in the Title... and store it in a VBA variable to detect if the name is from an other Instance than Instance A :
Get-Process |Where-Object {$_.mainWindowTitle -like "*Word*"} |format-table mainwindowtitle
It works but I can't believe there is no way to detect all running instances of an Application directly from VBA even with an unknown path.
I tried ugly stuff like this in VBA to cross over different Instances without success:
Sub GetAllInstance()
Dim WordApp As Word.Application, wordInstance As Object
Set WordApp = GetObject(, "Word.Application")
For Each wordInstance In WordApp
MsgBox (wordInstance)
Next wordInstance
End Sub
And the Immediate Command show me that the GetObject only have information about my Instance A, resulting only 1 documents even if 3 are opened on separates instance:
?WordApp.Documents.Count
1
EDIT 20/02:
With the good advices of Cindy, I changed my approch trying to work with process, I successfully detected differents PID of my running instances with the code below:
Sub IsProcessRunning()
Dim process As String
Dim objList As Object
Dim xprocess As Variant
Dim wdApp As Word.Application
process = "Word.exe"
Set objList = GetObject("winmgmts:") _
.ExecQuery("select ProcessID from win32_process where name='" & process & "'")
For Each xprocess In objList
Debug.Print xprocess.ProcessID
AppActivate (xprocess.ProcessID)
Set wdApp = GetObject(, "Word.Application")
Debug.Print wdApp.Workbooks(1).Name
Next xprocess
End Sub
Unfortunatly, activate an application do not clear the ROT, I'm now trying to find a way to clear it and refresh it to register the new activated application in the ROT and use the GetObject with the good instance.
Finally found a solution !
With the code below, because I know where my third-software generate the temporary file with the new instance, I search the name of the file using HWND and the GetWindowText from user32 lib. It permit to me to assign the GetObject using the full path and make interaction between my two documents from two separated instances. Thanks to Cindy and Mathieu for their help:
' API declaration
Const GW_HWNDNEXT = 2
Private Declare PtrSafe Function GetWindow Lib "user32" (ByVal hWnd As Long, ByVal wCmd As Long) As Long
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare PtrSafe Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Private Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Sub CommandButton1_Click()
Dim openDoc As Document, sourceDoc As Document, targetDoc As Object
Dim hWndThis As Long
Dim sTitle As String
Dim xTable As Table
''' INITIALIZATION '''
'Assign the source Document
Set sourceDoc = ActiveDocument
'Detect each instance by Window Name, then assign it to different object
hWndThis = FindWindow(vbNullString, vbNullString)
While hWndThis
sTitle = Space$(255)
sTitle = Left$(sTitle, GetWindowText(hWndThis, sTitle, Len(sTitle)))
If sTitle Like "*tmp*.DOC*" Then
FileToOpen = Left(sTitle, Len(sTitle) - 8)
Set targetDoc = GetObject("C:\Users\xxxxx\AppData\Local\Temp" & "\" & FileToOpen)
GoTo EndLoop:
End If
hWndThis = GetWindow(hWndThis, GW_HWNDNEXT)
Wend
EndLoop:
End Sub

Using timer to get Excel title

I have following code to get title of current opened excel file this code working fine. I use timer to every 10 seconds if title change then add new title in list1.
So question is there any method or event to detect if title change then my code work otherwise it not work not check. timer check every 10 seconds my pc work slow if I run this code
Private Const GW_HWNDNEXT = 2
Private Declare Function GetWindow Lib "user32" (ByVal hWnd As Long, _
ByVal wCmd As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" _
(ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
(ByVal hWnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Sub ListWins(Optional Title = "*", Optional Class = "*")
Dim hWndThis As Long
hWndThis = FindWindow(vbNullString, vbNullString)
While hWndThis
Dim sTitle As String, sClass As String
sTitle = Space$(255)
sTitle = Left$(sTitle, GetWindowText(hWndThis, sTitle, Len(sTitle)))
sClass = Space$(255)
sClass = Left$(sClass, GetClassName(hWndThis, sClass, Len(sClass)))
If sTitle Like Title And sClass Like Class Then
Debug.Print sTitle, sClass
List1.AddItem (sTitle)
End If
hWndThis = GetWindow(hWndThis, GW_HWNDNEXT)
Wend
End Sub
Private Sub Timer1_Timer()
ListWins "*.xls*"
End Sub
The answer is No. AFAIK, No there is no event as such in vb6 which will trap the title change in Excel or any other window. Also unfortunately 10 second timer might not be good. What happens if the title changes every 2 seconds? It will not retrieve all the titles
However try this alternative which does not use the Timer Control. See if your pc is still slow...
Sub Sample()
'
' ~~> Rest of your code
'
Wait 2 '<~~ Wait for 2 seconds
'
' ~~> Rest of your code
'
End Sub
Private Sub Wait(ByVal nSec As Long)
nSec = nSec + Timer
While nSec > Timer
DoEvents
Wend
End Sub
You can use the Excel COM API to do this. Unfortunately, there is no way of getting the Excel window title - but you could easily manufacture it by appending " - Microsoft Excel". Use the FullName property if you want the complete path.
Option Explicit
Private WithEvents m_oApplication As Excel.Application
Private Sub Command_Click()
' Get a reference to the FIRST instance of the Excel application.
Set m_oApplication = GetObject(, "Excel.Application")
End Sub
Private Sub m_oApplication_NewWorkbook(ByVal Wb As Excel.Workbook)
List1.AddItem Wb.Name
End Sub
Private Sub m_oApplication_WorkbookAfterSave(ByVal Wb As Excel.Workbook, ByVal Success As Boolean)
'List1.AddItem "WorkbookAfterSave: " & Wb.FullName
List1.AddItem Wb.Name
End Sub
Private Sub m_oApplication_WorkbookOpen(ByVal Wb As Excel.Workbook)
List1.AddItem Wb.Name
End Sub

Resources