Khởi động ứng Dụng Khác Bằng VBA

Menu Tự học VBA
  • Trang chủ
  • Diễn đàn Bài viết mới Tìm chủ đề
  • Có gì mới Bài viết mới Hoạt động mới nhất
Đăng nhập Đăng ký Có gì mới? Tìm kiếm

Tìm kiếm

Everywhere Chủ đề This forum This thread Chỉ tìm trong tiêu đề Bởi: Tìm Tìm kiếm nâng cao…
  • Bài viết mới
  • Tìm chủ đề
Menu Đăng nhập Đăng ký
  • Cách upload ảnh lên diễn đàn
  • Trang chủ
  • Diễn đàn
  • Kỹ thuật xử lý Excel
  • Lập trình VBA
Khởi động ứng dụng khác bằng VBA
  • Thread starter Euler
  • Ngày gửi 5/4/20
  • 1
  • 2
Tiếp 1 of 2

Đi đến trang

Tới Tiếp Last Euler

Euler

Administrator
Thành viên BQT Về cơ bản macro Excel sẽ thao tác trên Excel, đây là chức năng chính. Tuy nhiên, cũng có trường hợp chúng ta muốn thao tác với các ứng dụng ngoài Excel chẳng hạn như NotePad. Bài viết này tôi sẽ giới thiệu với các bạn điều đó. 1. Sử dụng hàm Shell để khởi động ứng dụng khác (Application) Cách đơn giản nhất để khởi động ứng dụng khác đó là sử dụng hàm Shell. Mã: Sub Sample1() Dim rc As Long rc = Shell("notepad.exe", vbNormalFocus) If rc = 0 Then MsgBox "Viec khoi dong that bai" End Sub Bạn cần đăng nhập để thấy đính kèm Chương trình Notepad ở đây là notepad.exe , thường được lưu ở C:\Windows\System32 . Đây là thiết định mặc định của Window cho nên chỉ cần nêu tên ứng dụng notepad.exe là hàm Shell có thể khởi động được nó. Tham số thứ hai trong code trên là vbNormalFocus . Nó có nghĩa như sau: Ứng dụng NotePad sẽ được hiển thị tại vị trí trên cửa sổ Window và kích thước vốn có từ trước tới nay. Mặt khác, hàm Shell nếu khởi động thành công ứng dụng khác, trong OS (hệ điều hành) sẽ được trả về trị số Task ID. Trị số Task ID này mỗi lần sẽ xuất hiện các giá trị khác nhau nhưng nếu thất bại thì trị số này sẽ là 0. Thao tác với NotePad bằng VBA thông qua hàm Shell là việc khó. Các bạn có thể sử dụng hàm SendKeys để ra mệnh lệnh từ VBA ghi nội dung lên NotePad. Ví dụ: Mã: Sub Sample2() Dim rc As Long ActiveCell.Copy rc = Shell("notepad.exe", vbNormalFocus) If rc <> 0 Then Application.SendKeys "%EP", True Else MsgBox "Khoi dong that bai" End If End Sub Kết quả: Bạn cần đăng nhập để thấy đính kèm Trước khi hàm Shell được gọi để khởi động NotePad thì macro thực hiện copy data trong ActiveCell. Sau khi NotePad được khởi động, bằng hàm SendKey chúng ta gửi Key Code là "%EP ". Điều này tương đương với thao tác bằng tay đó là bạn vừa ấn phím ALT vừa ấn phím E, tiếp theo ấn phím P. Tóm lại nó tương đương với việc bạn vào Menu Edit và chọn Paste. Tuy nhiên tùy từng điều kiện mà code trên cũng có thể thất bại. Hàm Shell sẽ khởi động NotePad nhưng VBA không thể phán đoán được việc khởi động này đã kết thúc thành công hay không. Trước khi việc mở NotePad thành công, câu lệnh SendKeys được thực thi sẽ dẫn tới là Excel (không phải NotePad) sẽ nhận được Key Code là "%EP ". Do tốc độ CPU, do bộ nhớ RAM còn nhiều hay ít, thời gian khởi động ứng dụng khác sẽ khác nhau. Vì vậy code trên cũng có trường hợp thất bại là vì thế. 2. Khởi động ứng dụng có liên quan tới File. Khi chúng ta double click vào icon của một file (ví dụ file pdf), ứng dụng đó mở nó sẽ được mở ra (ví dụ foxit reader). Đây là vì Windows quản lý mối liên quan giữa Application và phần mở rộng của File. Chúng ta dựa vào đặc điểm này để sử dụng WSH(Windows Script Host) mở ứng dụng khác rất đơn giản. Ví dụ dưới đây, chúng ta sẽ thấy điều này: Mã: Sub Sample3() With CreateObject("Wscript.Shell") .Run "C:\Data\Image.JPG", 5 End With End Sub Phương thức Run sẽ mở file có đường dẫn mà bạn truyền vào. Ứng dụng liên quan tới phần mở rộng JPG sẽ được kích hoạt mở ra. Tham số thứ nhất chúng ta phải chỉ định đường dẫn file cho phương thức RUN. Tham số thứ ba nếu được chỉ định, nó sẽ có giá trị True/False trong việc phán đoán quá trình thực thi Program đã kết thúc hay chưa. Ở code trên ta đã giản lược không dùng tham số thứ ba. Ví dụ này, chúng ta sẽ mở 3 file pdf. Mã: Sub Sample4() With CreateObject("Wscript.Shell") .Run "C:\Data\Sample1.pdf", 5 .Run "C:\Data\Sample2.pdf", 5 .Run "C:\Data\Sample3.pdf", 5 End With End Sub Trong ví dụ tiếp theo, ta sẽ chỉ định cho tham số thứ ba là True. Khi file pdf thứ nhất kết thúc, thì file pdf thứ hai được mở, quá trình mở kết thúc thì file thứ 3 sẽ được mở. Mã: Sub Sample5() With CreateObject("Wscript.Shell") .Run "C:\Data\Sample1.pdf", 5, True .Run "C:\Data\Sample2.pdf", 5, True .Run "C:\Data\Sample3.pdf", 5, True End With End Sub Ngoài ra, khi chúng ta chỉ định tham số thứ 3 của phương thức RUN là TRUE, chúng ta cũng có thể lấy giá trị trả về của Program. Ở ví dụ 6, chúng ta sẽ thực thi một file .bat, sau đó tiến hành phán đoán quá trình thực thi đó đã hoàn thành hay chưa. Mã: Sub Sample6() Dim ret As Long With CreateObject("Wscript.Shell") ret = .Run("C:\Data\DailyTask.bat", 7, True) End With If ret <> 0 Then MsgBox "That bai": Exit Sub 'Thất bại 'Xử lý khác End Sub Nguồn: Bạn cần đăng nhập để thấy link Ở bài dịch trên chúng tôi chưa thấy nhắc tới tham số thứ hai: các số 5,7 trong các ví dụ trên có ý nghĩa gì? Chúng tôi chưa có thời gian tìm hiểu. Nếu bạn đọc biết, xin hãy phản hồi bổ sung giúp chúng tôi trong topic này. Chân thành cảm ơn. N

NhanSu

SMod
Thành viên BQT Tham số thứ 2 là intWindowStyle, xác định kiểu cửa sổ xuất hiện, có các giá trị sau (theo Bạn cần đăng nhập để thấy link ): - 0: ẩn cửa sổ - 1: Kích hoạt cửa sổ với kích thước bình thường, nên sử dụng khi hiện cửa sổ lần đầu (tức là khi chạy chuơng trình) - 2: Kích hoạt và thu nhỏ cửa sổ - 3: Kích hoạt và phóng to tối đa cửa sổ - 4: Hiện cửa sổ với kích thước và vị trí thường sử dụng, không chiếm quyền điều khiển (focus) - 5: Kích hoạt cửa sổ với kích thước và vị trí bình thường - 6: Thu nhỏ cửa sổ và kích hoạt cửa sổ kế tiếp - 7: Thu nhỏ cửa sổ và giữ nguyên focus - 8: HIện cửa sổ ở trạng thái hiện tại, giữ nguyên focus - 9: Kích hoạt cửa sổ với kích thước bình thường, nên sử dụng sau khi cửa sổ này bị thu nhỏ - 10: Đặt trạng thái cửa sổ phụ thuộc vào trạng thái của chương trình gọi (tức là nếu đang có 1 chuơng trình chạy ở chế độ thu nhỏ, thì lệnh Run với tham số 10 cũng tạo ra một cửa sổ thu nhỏ) T

thanhphong

Guest
@NhanSu Bác cho em hỏi: Nếu như có nhiều ứng dụng đang mở, trong đó có cả Notepad đang mở. Vậy làm thế nào để Active Notepad và Sendkey cho nó? N

NhanSu

SMod
Thành viên BQT @thanhphong mình sử dụng FindWindow để tìm hWnd, dùng SetForegroundWindow để set focus cho cửa sổ. Mã: Public Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr Private Declare PtrSafe Function SetForegroundWindow Lib "user32" (ByVal hWnd As LongPtr) As Long Sub SendKeysToNotepad() Dim hWnd As LongPtr hWnd = FindWindow("Notepad", "a.txt - Notepad") If hWnd = 0 Then End SetForegroundWindow hWnd Application.SendKeys ("Test") End Sub N

NhanSu

SMod
Thành viên BQT Khi file mở trong Notepad đã bị thay đổi mà chưa lưu thì caption của cửa sổ có thêm dấu * ở đầu chuỗi. Vì vậy để tìm cửa sổ Notepad mở file a.txt, ta có thể phải tìm "a.txt - Notepad" và "*a.txt - Notepad". T

thanhphong

Guest
NhanSu nói: Khi file mở trong Notepad đã bị thay đổi mà chưa lưu thì caption của cửa sổ có thêm dấu * ở đầu chuỗi. Vì vậy để tìm cửa sổ Notepad mở file a.txt, ta có thể phải tìm "a.txt - Notepad" và "*a.txt - Notepad". Nhấn để mở rộng...
Có cách nào For each để mình duyệt qua từng cửa sổ đang mở không anh. N

NhanSu

SMod
Thành viên BQT Mình dựa theo Bạn cần đăng nhập để thấy link duyệt tất cả các cửa sổ Notepad rồi Sendkeys "Test": Mã: Option Explicit Declare PtrSafe Function GetDesktopWindow Lib "USER32" () As LongPtr Declare PtrSafe Function GetWindow Lib "USER32" (ByVal hwnd As LongPtr, ByVal wCmd As Long) As LongPtr Declare PtrSafe Function GetWindowText Lib "USER32" Alias "GetWindowTextA" (ByVal hwnd As LongPtr, ByVal lpString As String, ByVal cch As LongPtr) As Long Sub SendKeysToAllNotepadWindows() Dim DeskTophWnd As LongPtr Dim WindowhWnd As LongPtr Dim Buff As String * 255 Dim hwnd As Long Dim CaptionWindowsString As String CaptionWindowsString = "Notepad" DeskTophWnd = GetDesktopWindow WindowhWnd = GetWindow(DeskTophWnd, 5) Do While (WindowhWnd <> 0) Buff = String$(255, Chr$(0)) GetWindowText WindowhWnd, Buff, 255 strtext = String$(100, Chr$(0)) WindowhWnd = GetWindow(WindowhWnd, 2) If InStr(Buff, CaptionWindowsString) <> 0 Then AppActivate Buff, True DoEvents SendKeys "test", True DoEvents End If Loop End Sub P

phuonghong1997

Yêu THVBA như điếu đổ
thanhphong nói: Có cách nào For each để mình duyệt qua từng cửa sổ đang mở không anh. Nhấn để mở rộng...
For each tìm từng cửa sổ thì em cũng không biết. Nhưng nếu tìm Notepad thì anh coi code này : Mã: Dim hWnd As Long hWnd = FindWindow("Notepad", vbNullString) If hWnd = 0 Then End SetForegroundWindow hWnd SendKeys "ABCDEFGHIJKLMNOPQRSTUVWXYZ" SendKeys "{Enter}" T

thanhphong

Guest
Em cảm ơn mọi người rất nhiều. Đặc biệt là bác Smod @NhanSu . Em đã làm được rồi ạ. tuhocvba

tuhocvba

Administrator
Thành viên BQT
NhanSu nói: Mình dựa theo Bạn cần đăng nhập để thấy link duyệt tất cả các cửa sổ Notepad rồi Sendkeys "Test": Mã: String$(255, Chr$(0)) Nhấn để mở rộng...
Dòng code này nghĩa là gì, @NhanSu giải thích giúp mình được không? N

NhanSu

SMod
Thành viên BQT Buff là bộ đệm có kích thước 256 ký tự. Hàm đó trả về chuỗi gồm toàn ký tự 0 để reset lại bộ đệm sau mỗi vòng lặp vì hàm API cần chuỗi kết thúc bằng null. tuhocvba

tuhocvba

Administrator
Thành viên BQT Hai cái này khác gì nhau, chỗ này mình không hiểu, nếu @NhanSu hiểu thì giải đáp giúp mình với: Mã: chr(0) và : Mã: chr$(0) Sao tự nhiên có thêm dấu $ để làm gì vậy ta. N

NhanSu

SMod
Thành viên BQT Chr trả về variant còn chr$ trả về string. Nói chung truyền dữ liệu giữa vba và win32 api cần phải đọc thêm về con trỏ và cách lưu trữ của biến vba trong bộ nhớ. tuhocvba

tuhocvba

Administrator
Thành viên BQT Mình chạy thử code này nó đều ra là 8 : Mã: MsgBox VarType(Chr$(0)) hoặc: Mã: MsgBox VarType(Chr(0)) N

NhanSu

SMod
Thành viên BQT Vartype của 1 variant chỉ trả về variant (12) khi biến này chứa mảng các variants. tuhocvba

tuhocvba

Administrator
Thành viên BQT Cảm ơn NhanSu. Vậy câu lệnh đó giờ thay bằng: Mã: Buff = cstr(String(255, Chr(0))) chắc là vẫn ok phải không nhỉ. N

NhanSu

SMod
Thành viên BQT Cái này mình cũng không chắc, cần kiểm tra thêm bằng các chương trình đọc nội dung trực tiếp từ bộ nhớ hoặc bạn có thể tìm hiểu thêm về api CopyMemory. Sử dụng hàm này để đọc thông tin vùng nhớ chỉ định sẽ nắm được cách lưu trữ của biến trong bộ nhớ. B

bvtvba

Guest
Mọi người nếu không hiểu hàm string hay string$ thì Bạn cần đăng nhập để thấy link . N

NhanSu

SMod
Thành viên BQT @bvtvba thực ra ý mọi người đang bàn luận là nắm rõ cách lưu trữ biến trong bộ nhớ. Ví dụ khi ta khai báo một biến string bằng lệnh Dim thì biến này có địa chỉ xác định. Giá trị của vùng nhớ tại biến này là địa chỉ của chuỗi unicode kết thúc bằng null. Giá trị của 4 bytes trước chuỗi chứa LEN của chuỗi. Đây là cấu trúc của kiểu BSTR. Làm việc với win api cần nắm những thứ này để tránh lỗi. T

thuthuy2000

Guest
NhanSu nói: Chr trả về variant còn chr$ trả về string. Nhấn để mở rộng...
Bác có link dẫn không, theo em được biết thì Chr có giá trị trả về là String mà.
  • 1
  • 2
Tiếp 1 of 2

Đi đến trang

Tới Tiếp Last Bạn phải đăng nhập hoặc đăng ký để bình luận. Chia sẻ: Facebook Twitter WhatsApp Email Link
  • Trang chủ
  • Diễn đàn
  • Kỹ thuật xử lý Excel
  • Lập trình VBA
Top

Từ khóa » Khác Trong Vba