Kiểm tra tên các workbook đang mở để xác định 1 file đã mở hay chưa. (2 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

friendship293a

Thành viên mới
Tham gia
9/3/08
Bài viết
25
Được thích
0
Ai có code lấy tên các workbook đang mở không cho mình tham khảo với. Thanks!
 
Hic nếu file TV nó sẽ như sau Thầy à:

Mã:
Sub Example() 
     Dim AllExcelApps As Collection, ExcelApp As Application, wb As Workbook, Pid As Long
      
     Set AllExcelApps = GetAllInstances 
     If Not AllExcelApps Is Nothing Then
        For Each ExcelApp In AllExcelApps 
            [COLOR=#ff0000]GetWindowThreadProcessId ExcelApp.hwnd, Pid [/COLOR]
            Debug.Print ExcelApp.Caption & ",  Process ID = " & Pid 
            For Each wb In ExcelApp.Workbooks 
                Debug.Print "    " & wb.Name 
            Next
        Next
     End If
End Sub



Mình test, nó không hiện thị được file có dấu tiếng Việt, ngoài ra nếu code nằm trong file có dấu tiếng Việt, nó bị lỗi tại dòng màu đỏ: GetWindowThreadProcessId ExcelApp.hwnd, Pid.

-------------------------------------------------------------

Vọc từ sáng giờ rốt cuộc cũng hoàn thiện được, không quá dài, gởi tặng mọi người.
Liệt kê được tất cả các File Excel đang mở trên tất cả các session, kể cả có dấu tiếng Việt.



P/s: Dạo này (từ khi diễn đàn có chức năng hiển thị STT các dòng code) trang nào có code thì rất khó mở, chỉ hiển thị được một ít ở phần đầu trang.Càng dài càng khó mở, phải mở nhiều lần mới được. Các bạn có ai bị vậy không?
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Bạn nào dùng Excel2010 kiểm tra file trên (Liệt kê các file Excel đang mở.xls) giùm!
 
Upvote 0
Bạn nào dùng Excel2010 kiểm tra file trên (Liệt kê các file Excel đang mở.xls) giùm!

Đã thí nghiệm code trên Excel 2010, liệt kê được các file kể cả là tên tiếng Việt có dấu
Cần nói thêm rằng máy em có 2 Office: Bộ Office 2010 được cài đặt và Office 2003 dạng Portable. Em mở 2 file trên Excel 2003 và 2 file trên Excel 2010 (gồm file của anh). Chạy code, liệt kê được chính xác 4 file
 
Upvote 0
1. Hỏi tác giả chèn code vào book1 hay book2?
2. "Bật" là gì? Là double vào tên file trong explorer, hay Open file? "Bật" lần thứ nhất là bật excel và có ngay book1, hay mở 1 file book1.xls có sẵn trên máy?
3. Nhiều khi tác giả chưa lưu file mới cho book1 không chừng ấy.

Mình test thế này. mình bật 1 workbook đầu tiên lên nó tên là book1 sau đó bật tiếp workbook 2 nó tên là book2 sau đó mình nhấn Alt+F11 -> Insert module nhập đoạn code trên vào và run nó chỉ thông báo là book2 mà không thông báo book1.
Ko biết Test thế đúng chưa bạn?

Chán kiểu viết không rõ ràng quá. Tên file cũng không đặt cho có hệ thống.
 
Lần chỉnh sửa cuối:
Upvote 0
Nó sẽ liệt kê tất tần tật những file excel đang mở.
 
Upvote 0
Nó sẽ liệt kê tất tần tật những file excel đang mở.

Nếu vậy thì phải học cách sử dụng Excel chỉ 1 session thôi: mở Excel, Open file, hoặc vào recent file và open.
Như vậy code đơn giản như bài 2 thôi là ok.

Double tên file có những cái hại:
- Mở nhằm file virus giả danh
- Mở bằng Excel version không mong muốn (nếu cài 2 Office trở lên)
- Mở bằng 2 session nếu Option của Excel bị cài đặt (mà không biết đường sửa)
- ...

Mở bằng 2 session có những cái hại sau:
- Không tạo được Công thức liên kết giữa các file đang mở
- Không paste special được giữa 2 session
- Code bình thường không liệt kê file đang mở (topic này)
- Global code không chạy cho 2 session
- ...

Túm lại, làm việc đơn giản thì sẽ đơn giản.
 
Lần chỉnh sửa cuối:
Upvote 0
Vọc từ sáng giờ rốt cuộc cũng hoàn thiện được, không quá dài, gởi tặng mọi người.
Liệt kê được tất cả các File Excel đang mở trên tất cả các session, kể cả có dấu tiếng Việt.

Bài này có liên quan đến CÁC CỬA SỔ nên chợt nghĩ đến hàm EnumWindows và AddressOf Operator
Thử làm bài này theo phương án ấy xem:
1> Trong Module:
PHP:
Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Boolean
Declare Function GetWindowText Lib "user32" Alias "GetWindowTextW" (ByVal hWnd As Long, ByVal lpString As Long, ByVal cch As Long) As Long
Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthW" (ByVal hWnd As Long) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Public Dic As Object
PHP:
Public Function EnumWindowsProc(ByVal hWnd As Long, ByVal lParam As Long) As Boolean
    Dim sSave As String, Ret As Long, wClass As String
    Ret = GetWindowTextLength(hWnd)
    sSave = Space(Ret)
    GetWindowText hWnd, StrPtr(sSave), Ret + 1
    wClass = WinClassName(hWnd)
    If (wClass = "MS-SDIb") Or (wClass = "XLMAIN") Then
      If sSave Like "Microsoft Excel - *" Then sSave = Mid(sSave, 19)
      sSave = Trim(Replace(sSave, "[Compatibility Mode]", ""))
      If Not Dic.Exists(sSave) Then Dic.Add sSave, ""
    End If
    EnumWindowsProc = True
End Function
PHP:
Function WinClassName(ByVal hWnd As Long) As String
  Dim RetVal As Long, lpClassName As String
  If hWnd <> 0 Then
    lpClassName = Space(256)
    RetVal = GetClassName(hWnd, lpClassName, 256)
    WinClassName = Left$(lpClassName, RetVal)
  End If
End Function
PHP:
Sub Main()
  Set Dic = CreateObject("Scripting.Dictionary")
  UserForm1.Show
End Sub
2> Trong UserForm (với 1 CommandButton và 1 ListBox)
PHP:
Private Sub CommandButton1_Click()
  On Error Resume Next
  EnumWindows AddressOf EnumWindowsProc, ByVal 0&
  Me.ListBox1.List() = Dic.Keys
End Sub
Hoàn toàn không có tí vòng lập nào hen
Giải thuật là:
- Cứ cửa số nào có ClassName = "XLMAIN" hoặc "MS-SDIb" thì lấy
- Lấy xong, xử lý các phần thừa để chỉ còn lại TÊN
Giải thuật là như vậy nhưng vì chưa rành API lắm, lại thông qua quá trình thí nghiệm mà suy luận nên phần triển khai có chút luộm thuộm
Rất mong các cao thủ góp ý, nhất là code trong hàm EnumWindowsProc (chưa hài lòng lắm)
Mình rất khoái thằng em "AddressOf" ---> Có vẽ như là 1 sự "tương tác 2 chiều gì đó" mà mình không mấy hiểu
 

File đính kèm

Upvote 0
Bài này có liên quan đến CÁC CỬA SỔ nên chợt nghĩ đến hàm EnumWindows và AddressOf Operator
Thử làm bài này theo phương án ấy xem:

---------------
Code
---------------

Hoàn toàn không có tí vòng lập nào hen
Giải thuật là:
- Cứ cửa số nào có ClassName = "XLMAIN" hoặc "MS-SDIb" thì lấy
- Lấy xong, xử lý các phần thừa để chỉ còn lại TÊN
Giải thuật là như vậy nhưng vì chưa rành API lắm, lại thông qua quá trình thí nghiệm mà suy luận nên phần triển khai có chút luộm thuộm
Rất mong các cao thủ góp ý, nhất là code trong hàm EnumWindowsProc (chưa hài lòng lắm)
Mình rất khoái thằng em "AddressOf" ---> Có vẽ như là 1 sự "tương tác 2 chiều gì đó" mà mình không mấy hiểu

- Mở thử nhiều file trên nhiều session, test thử và thấy: Mỗi session chỉ liệt kê được một file, chắc là tại "Hoàn toàn không có tí vòng lập nào hen"

- Mình cũng mới vọc API nhưng lại khoái hàm FindWindowEx
 
Upvote 0
- Mở thử nhiều file trên nhiều session, test thử và thấy: Mỗi session chỉ liệt kê được một file, chắc là tại "Hoàn toàn không có tí vòng lập nào hen"

Tôi kích hoạt 3 Excel 2007 và mỗi instance load 2 tập tin, tổng cộng 6 tập tin. Tìm được hết
Vui lòng nhìn hình.

View attachment 94757


Chỉ có điều "nho nhỏ", không cần test mà chỉ cần hình dung được trường hợp "cá biệt" khi đọc dòng
If Not Dic.Exists(sSave) Then Dic.Add sSave, ""
và tự hỏi: Thế nếu ...

Do ta đọc tiêu đề nên ta nhận được chỉ tên tập tin chứ không phải là tên đầy đủ - thay vì "C:\hic.xls" thì ta chỉ có "hic.xls".
Vậy nếu trong 2 instance ta mở 2 tập tin cùng tên (nhưng khác lõi) từ 2 thư mục khác nhau vd. thêm "D:\hic.xls" thì DIC sẽ bỏ 1 tên, tức ta bị mất 1 tên và ta không biết cái HIC nào đang được mở.
-----------
À, còn về code thì xin góp ý cho Tuấn thế này.
Thường thì ta chỉ có vài cửa sổ Excel đang mở, nhưng số cửa sổ mà EnumWindows "tìm thấy" sẽ nhiều hơn. Giả dụ tổng cộng sẽ tìm được 150 (tính khiêm tốn thôi chứ nhiều đấy, các bạn đếm sẽ biết) cửa sổ trong đó có 5 cửa sổ mà ta quan tâm - class MS-SDIb hoặc XLMAIN, tức hàm EnumWindowsProc được gọi 150 lần.
Như vậy cả cụm
Mã:
    Ret = GetWindowTextLength(hWnd)
    sSave = Space(Ret)
    GetWindowText hWnd, StrPtr(sSave), Ret + 1
được thực hiện 150 lần.
Nếu ta đưa cả cụm vào trong IF ... END IF thì tiết kiệm được 145 lần thực hiện cụm đó.
Chả lý gì ta thực hiện cụm 145 lần trong những trường hợp khi mà hWnd là handle của 145 cửa sổ mà ta không quan tâm.
Mà XLMAIN theo tôi có thể bỏ đi, tức chỉ có If (wClass = "MS-SDIb") Then
 
Lần chỉnh sửa cuối:
Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom