This question is basically regarding to loop all workbooks in all excel instances!
Asked
Active
Viewed 1,094 times
0
-
Create an array and store workbook to it as you open each one? Or even key it with dictionary for faster retrieval later instead of looping? – findwindow Mar 28 '16 at 15:53
-
Maybe this'll help? http://www.ozgrid.com/forum/showthread.php?t=182853 – Visual Vincent Mar 28 '16 at 15:58
-
1You are only ever going to get one... You are looping `Excel` processes, but ***not*** doing anything with them once found. You create a new object of `ExcelApplication` and by default it's **1** workbook. This is why you only ever see one book... – Trevor Mar 28 '16 at 16:06
-
Even the Windows API? Might be hard to find what you're looking for _if_ there isn't any simple solution. – Visual Vincent Mar 28 '16 at 16:07
-
@Markowitz Can you use API? – Trevor Mar 28 '16 at 16:23
1 Answers
1
Your main issue you are facing is you are not using any of the process's you come across. Therefore, you will not get anything that way. Inside of the loop for the process's you then create a new instance of ExcelApplication
and then try to loop through the Workbooks
. By default when you do this there is only 1 at that time, hence why you get only 1 Workbook
and also why you will only ever see 1 Workbook
.
Solution (Tried & Tested)
You need to look into Windows API calls to get what you need. A few of them are:
- GetDesktopWindow()
- EnumChildWindows()
- GetClassName()
- EnumWindowsProc()
-
Imports Microsoft.Office.Interop Imports System.Runtime.InteropServices Public Class Form1 Private Declare Function GetDesktopWindow Lib "user32" () As Integer Private Declare Function EnumChildWindows Lib "user32.dll" (ByVal WindowHandle As IntPtr, ByVal Callback As EnumWindowsProc, ByVal lParam As IntPtr) As Boolean Private Declare Function GetClassName Lib "user32.dll" Alias "GetClassNameA" (ByVal hWnd As IntPtr, ByVal lpClassName As String, ByVal nMaxCount As Integer) As Integer Private Delegate Function EnumWindowsProc(ByVal hwnd As IntPtr, ByVal lParam As Int32) As Boolean Private Declare Function AccessibleObjectFromWindow Lib "oleacc" (ByVal Hwnd As Int32, ByVal dwId As Int32, ByRef riid As Guid, <MarshalAs(UnmanagedType.IUnknown)> ByRef ppvObject As Object) As Int32 Private Const OBJID_NATIVE = &HFFFFFFF0 'Required to show the workbooks. Used in function to add to. Private lstWorkBooks As New List(Of String) Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click lstWorkBooks.Clear() GetExcelOpenWorkBooks() End Sub Private Sub GetExcelOpenWorkBooks() Try 'Get handle to desktop Dim WindowHandle As IntPtr = GetDesktopWindow() 'Enumerate through the windows (objects) that are open EnumChildWindows(WindowHandle, AddressOf GetExcelWindows, 0) 'List the workbooks out if we have something If lstWorkBooks.Count > 0 Then MsgBox(String.Join(Environment.NewLine, lstWorkBooks)) Catch ex As Exception End Try End Sub Public Function GetExcelWindows(ByVal hwnd As IntPtr, ByVal lParam As Int32) As Boolean Dim Ret As Integer = 0 Dim className As String = Space(255) 'Return the string with some padding... Ret = GetClassName(hwnd, className, 255) className = className.Substring(0, Ret) If className = "EXCEL7" Then Dim ExcelApplication As Excel.Application Dim ExcelObject As Object = Nothing Dim IDispatch As Guid AccessibleObjectFromWindow(hwnd, OBJID_NATIVE, IDispatch, ExcelObject) 'Did we get anything? If ExcelObject IsNot Nothing Then ExcelApplication = ExcelObject.Application 'Make sure we have the instance... If ExcelApplication IsNot Nothing Then 'Go through the workbooks... For Each wrk As Excel.Workbook In ExcelApplication.Workbooks 'If workbook ins't in the list then add it... If Not lstWorkBooks.Contains(wrk.Name) Then lstWorkBooks.Add(wrk.Name) End If Next End If End If End If Return True End Function End Class

Trevor
- 7,777
- 6
- 31
- 50
-
1Seriously, `I prefer vb.net code without API. But if this is not possible I accept API solution`. What is the problem? This ***answer's your issue and more***. `I prefer simple code` I wish it was that easy, if you think that's the case you have a long way to the top :) – Trevor Mar 28 '16 at 18:56
-
1@Codexer You should have deleted the answer since he appears ungrateful that you solved his issue. – Sorceri Mar 28 '16 at 19:02
-
@Markowitz Thank you, accepting answer's is how it works here. If it's helped, it is important to vote and accept answer. This helps other coming along that may have the same issue. Also without using API it's probably impossible to loop through active windows and getting that object, the only way I know of is what I posted – Trevor Mar 28 '16 at 19:49