Kính nhờ anh chị em trong diễn đàn giúp code VBA excel nào đóng file pdf từ đường dẫn cho trước (1 người xem)

Liên hệ QC

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

thanhphuccd

Thành viên mới
Tham gia
28/5/08
Bài viết
49
Được thích
2
Trong VBA excel mình tìm được code có thể mở file pdf từ excel bằng đường dẫn. Nhưng mình tìm hoài không thấy code đóng file pdf bằng đường dẫn. Mong nhận được sự giúp đỡ anh chị em trong diễn đàn. Mình xin cảm ơn
 
Trong VBA excel mình tìm được code có thể mở file pdf từ excel bằng đường dẫn. Nhưng mình tìm hoài không thấy code đóng file pdf bằng đường dẫn. Mong nhận được sự giúp đỡ anh chị em trong diễn đàn. Mình xin cảm ơn
Cái này phải dùng win api rồi.
 
Cái này phải dùng win api rồi.

Các bạn hóng gì? Các bạn có hiểu người ta muốn gì hay không mà hóng?

Tôi không hiểu cái gọi là "đóng file pdf bằng đường dẫn" mặt mũi nó thế nào. Tôi đang phân vân, không biết khả năng nào dưới đây:
1. Đã có nói
mình tìm được code có thể mở file pdf từ excel bằng đường dẫn
Tức người ta trước đó, vd. lúc 9:35, chạy code để mở tập tin PDF "bằng đường dẫn". Bây giờ, tức lúc 9:43, "đóng file pdf bằng đường dẫn" có nghĩa là chạy code để đóng cái tập tin đã được mở trước đó, lúc 9:35, "bằng đường dẫn".

2. Trên đĩa có thể có hằng hà sa số tập tin có cùng tên nhưng ở các thư mục khác nhau. Vd. tập tin tên là bí_mật.pdf ở:
- c:\bí_mật.pdf
- c:\tuyet mat\bí_mật.pdf
...
- d:\linh tinh\bí_mật.pdf

"đóng file pdf bằng đường dẫn" có nghĩa là nếu tôi nhập đường dẫn vd. d:\linh tinh\bí_mật.pdf vào A1 thì code sẽ tìm xem có tập tin PDF nào đang được người dùng mở hay không. Và có đúng đường dẫn như trong A1 hay không. Nếu đúng thì đóng. Trong trường hợp ngược lại, tức khác tên (vd. chỉ có "bí_đao.pdf" đang mở) hoặc không đúng đường dẫn (vd. chỉ c:\tuyet mat\bí_mật.pdf được mở) thì không đóng.

Các bạn có biết người ta định nói tới trường hợp nào không mà hóng?
 
Lần chỉnh sửa cuối:
Các bạn hóng gì? Các bạn có hiểu người ta muốn gì hay không mà hóng?

Tôi không hiểu cái gọi là "đóng file pdf bằng đường dẫn" mặt mũi nó thế nào. Tôi đang phân vân, không biết khả năng nào dưới đây:
1. Đã có nói

Tức người ta trước đó, vd. lúc 9:35, chạy code để mở tập tin PDF "bằng đường dẫn". Bây giờ, tức lúc 9:43, "đóng file pdf bằng đường dẫn" có nghĩa là chạy code để đóng cái tập tin đã được mở trước đó, lúc 9:35, "bằng đường dẫn".

2. Trên đĩa có thể có hằng hà sa số tập tin có cùng tên nhưng ở các thư mục khác nhau. Vd. tập tin tên là bí_mật.pdf ở:
- c:\bí_mật.pdf
- c:\tuyet mat\bí_mật.pdf
...
- d:\linh tinh\bí_mật.pdf

"đóng file pdf bằng đường dẫn" có nghĩa là nếu tôi nhập đường dẫn vd. d:\linh tinh\bí_mật.pdf vào A1 thì code sẽ tìm xem có tập tin PDF nào đang được người dùng mở hay không. Và có đúng đường dẫn như trong A1 hay không. Nếu đúng thì đóng. Trong trường hợp ngược lại, tức khác tên (vd. chỉ có "bí_đao.pdf" đang mở) hoặc không đúng đường dẫn (vd. chỉ c:\tuyet mat\bí_mật.pdf được mở) thì không đóng.

Các bạn có biết người ta định nói tới trường hợp nào không mà hóng?
hiểu theo hướng đơn giản thôi bác, tức là đóng đúng file theo đường dẫn. Với bài này em cũng chẳng phai là hóng mà chỉ là theo em phải dùng api để làm thôi.
 
Các bạn hóng gì? Các bạn có hiểu người ta muốn gì hay không mà hóng?

Tôi không hiểu cái gọi là "đóng file pdf bằng đường dẫn" mặt mũi nó thế nào. Tôi đang phân vân, không biết khả năng nào dưới đây:
1. Đã có nói

Tức người ta trước đó, vd. lúc 9:35, chạy code để mở tập tin PDF "bằng đường dẫn". Bây giờ, tức lúc 9:43, "đóng file pdf bằng đường dẫn" có nghĩa là chạy code để đóng cái tập tin đã được mở trước đó, lúc 9:35, "bằng đường dẫn".

2. Trên đĩa có thể có hằng hà sa số tập tin có cùng tên nhưng ở các thư mục khác nhau. Vd. tập tin tên là bí_mật.pdf ở:
- c:\bí_mật.pdf
- c:\tuyet mat\bí_mật.pdf
...
- d:\linh tinh\bí_mật.pdf

"đóng file pdf bằng đường dẫn" có nghĩa là nếu tôi nhập đường dẫn vd. d:\linh tinh\bí_mật.pdf vào A1 thì code sẽ tìm xem có tập tin PDF nào đang được người dùng mở hay không. Và có đúng đường dẫn như trong A1 hay không. Nếu đúng thì đóng. Trong trường hợp ngược lại, tức khác tên (vd. chỉ có "bí_đao.pdf" đang mở) hoặc không đúng đường dẫn (vd. chỉ c:\tuyet mat\bí_mật.pdf được mở) thì không đóng.

Các bạn có biết người ta định nói tới trường hợp nào không mà hóng?
Ý mình là mở một số file pdf dựa vào đường dẫn được lưu trên excel. Sau đó sẽ thực hiện đóng file bằng chính những đường dẫn đã mở.
 
Ý mình là mở một số file pdf dựa vào đường dẫn được lưu trên excel. Sau đó sẽ thực hiện đóng file bằng chính những đường dẫn đã mở.
Phải biết bạn dùng chương trình gì để mở mới dựa vào mà viết code vba đóng cửa sổ chương trình đó.chứ nếu là file excel thì mặc định mở là excel rồi chỉ cần biết tên đường dẫn cũng đóng lại được
 
Ý mình là mở một số file pdf dựa vào đường dẫn được lưu trên excel. Sau đó sẽ thực hiện đóng file bằng chính những đường dẫn đã mở.
Bạn nên đưa code mở file lên trước. Khi file pdf đang mở sẽ không xóa hay đổi tên được. Bạn vào đường dẫn đó thử đổi tên, nếu không được thì đóng cửa sổ, tùy theo bạn mở bằng chương trình gì thì cách đóng có thể khác nhau.
 
Phải biết bạn dùng chương trình gì để mở mới dựa vào mà viết code vba đóng cửa sổ chương trình đó.chứ nếu là file excel thì mặc định mở là excel rồi chỉ cần biết tên đường dẫn cũng đóng lại được
Mình dùng phần mềm Foxit phantom đó bạn
Bài đã được tự động gộp:

Bạn nên đưa code mở file lên trước. Khi file pdf đang mở sẽ không xóa hay đổi tên được. Bạn vào đường dẫn đó thử đổi tên, nếu không được thì đóng cửa sổ, tùy theo bạn mở bằng chương trình gì thì cách đóng có thể khác nhau.
Mình mở file từ đường dẫn để xem nội dung file PDF, sau đó dùng code để đổi tên file. Vấn đề mình gặp là cần tự động đóng các file đã mở từ đường dẫn trước thì mới đổi tên file bằng code đươc
 
Lần chỉnh sửa cuối:
Mở:

-------------
PHP:
Dim Foxit As String, PDF as String
Foxit = "C:\path\FoxitPhantomPDF.exe"
PDF ="D:\file.pdf"
Shell "Cmd.exe /S /K START """" """ & Foxit & """ """ & PDF & """", vbNormalFocus
-------------

Đóng:
PHP:
Dim AppName As String
AppName = "FoxitPhantomPDF.exe"
Shell "Cmd.exe /S /K TASKKILL /f /fi ""Imagename eq " & AppName, vbHide
 
Lần chỉnh sửa cuối:
Ý mình là mở một số file pdf dựa vào đường dẫn được lưu trên excel. Sau đó sẽ thực hiện đóng file bằng chính những đường dẫn đã mở.
Tức bạn muốn nói tới điểm 1 trong bài của tôi? Nếu thế thì đính kèm cái code mà bạn đã có và bạn dùng để "mở file pdf từ excel bằng đường dẫn".

Không phải vô cớ mà tôi muốn biết, bạn muốn đóng tập tin nào, đã được mở như thế nào. Tùy cách mở mà lựa chọn cách đóng thôi. Tôi không biết bạn mở thế nào thì hơi khó để lựa cách đóng. Đóng tập tin mà chính code vừa mở có thể khác với đóng tập tin mà người dùng tự mở hằng hà sa số.
-------------
Ví dụ tôi mở Nitro PDF như trong runPDF, và đóng như trong closePDF (Module1 ở dưới)

Cũng có thể tham khảo bài trong chủ đề.


Module1
Mã:
Option Explicit

Private Const WM_CLOSE As Long = &H10

#If VBA7 Then
    Private Declare PtrSafe Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hWnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As Long
    Private Declare PtrSafe Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As LongPtr, lpdwProcessId As Long) As Long
    Private Declare PtrSafe Function EnumWindows Lib "user32" (ByVal lpEnumFunc As LongPtr, ByVal lParam As LongPtr) As Long
    Private Declare PtrSafe Function IsWindowVisible Lib "user32" (ByVal hWnd As LongPtr) As Long
#Else
    Private Declare Function PostMessage Lib "user32.dll" Alias "PostMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Declare Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
    Private Declare Function EnumWindows Lib "user32.dll" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
    Private Declare Function IsWindowVisible Lib "user32.dll" (ByVal hWnd As Long) As Long
#End If

Private ProcID As Long

#If VBA7 Then
Function EnumWindowsProc(ByVal hWnd As LongPtr, ByVal lParam As LongPtr) As Long
#Else
Function EnumWindowsProc(ByVal hWnd As Long, ByVal lParam As Long) As Long
#End If
Dim ProcessId As Long
    EnumWindowsProc = 1
    If IsWindowVisible(hWnd) Then
        GetWindowThreadProcessId hWnd, ProcessId
        If ProcessId = lParam Then
            PostMessage hWnd, WM_CLOSE, 0, 0
            EnumWindowsProc = 0
        End If
    End If
End Function

'    code de chay thu

Sub runPDF()
Dim filename As String
    filename = "c:\bi mat.pdf"
    filename = """" & filename & """"
    ProcID = Shell("C:\Program Files\Nitro PDF\Professional\nitroPDF.exe " & filename, vbMaximizedFocus)
End Sub

Sub closePDF()
    If ProcID = 0 Then Exit Sub
    EnumWindows AddressOf EnumWindowsProc, ProcID
End Sub
 
Tức bạn muốn nói tới điểm 1 trong bài của tôi? Nếu thế thì đính kèm cái code mà bạn đã có và bạn dùng để "mở file pdf từ excel bằng đường dẫn".

Không phải vô cớ mà tôi muốn biết, bạn muốn đóng tập tin nào, đã được mở như thế nào. Tùy cách mở mà lựa chọn cách đóng thôi. Tôi không biết bạn mở thế nào thì hơi khó để lựa cách đóng. Đóng tập tin mà chính code vừa mở có thể khác với đóng tập tin mà người dùng tự mở hằng hà sa số.
-------------
Ví dụ tôi mở Nitro PDF như trong runPDF, và đóng như trong closePDF (Module1 ở dưới)

Cũng có thể tham khảo bài trong chủ đề.


Module1
Mã:
Option Explicit

Private Const WM_CLOSE As Long = &H10

#If VBA7 Then
    Private Declare PtrSafe Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hWnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As Long
    Private Declare PtrSafe Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As LongPtr, lpdwProcessId As Long) As Long
    Private Declare PtrSafe Function EnumWindows Lib "user32" (ByVal lpEnumFunc As LongPtr, ByVal lParam As LongPtr) As Long
    Private Declare PtrSafe Function IsWindowVisible Lib "user32" (ByVal hWnd As LongPtr) As Long
#Else
    Private Declare Function PostMessage Lib "user32.dll" Alias "PostMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Declare Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
    Private Declare Function EnumWindows Lib "user32.dll" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
    Private Declare Function IsWindowVisible Lib "user32.dll" (ByVal hWnd As Long) As Long
#End If

Private ProcID As Long

#If VBA7 Then
Function EnumWindowsProc(ByVal hWnd As LongPtr, ByVal lParam As LongPtr) As Long
#Else
Function EnumWindowsProc(ByVal hWnd As Long, ByVal lParam As Long) As Long
#End If
Dim ProcessId As Long
    EnumWindowsProc = 1
    If IsWindowVisible(hWnd) Then
        GetWindowThreadProcessId hWnd, ProcessId
        If ProcessId = lParam Then
            PostMessage hWnd, WM_CLOSE, 0, 0
            EnumWindowsProc = 0
        End If
    End If
End Function

'    code de chay thu

Sub runPDF()
Dim filename As String
    filename = "c:\bi mat.pdf"
    filename = """" & filename & """"
    ProcID = Shell("C:\Program Files\Nitro PDF\Professional\nitroPDF.exe " & filename, vbMaximizedFocus)
End Sub

Sub closePDF()
    If ProcID = 0 Then Exit Sub
    EnumWindows AddressOf EnumWindowsProc, ProcID
End Sub
Mình cảm ơn bạn rất nhiều. Code VBA thật tuyệt!
 
Tức bạn muốn nói tới điểm 1 trong bài của tôi? Nếu thế thì đính kèm cái code mà bạn đã có và bạn dùng để "mở file pdf từ excel bằng đường dẫn".

Không phải vô cớ mà tôi muốn biết, bạn muốn đóng tập tin nào, đã được mở như thế nào. Tùy cách mở mà lựa chọn cách đóng thôi. Tôi không biết bạn mở thế nào thì hơi khó để lựa cách đóng. Đóng tập tin mà chính code vừa mở có thể khác với đóng tập tin mà người dùng tự mở hằng hà sa số.
-------------
Ví dụ tôi mở Nitro PDF như trong runPDF, và đóng như trong closePDF (Module1 ở dưới)

Cũng có thể tham khảo bài trong chủ đề.


Module1
Mã:
Option Explicit

Private Const WM_CLOSE As Long = &H10

#If VBA7 Then
    Private Declare PtrSafe Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hWnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As Long
    Private Declare PtrSafe Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As LongPtr, lpdwProcessId As Long) As Long
    Private Declare PtrSafe Function EnumWindows Lib "user32" (ByVal lpEnumFunc As LongPtr, ByVal lParam As LongPtr) As Long
    Private Declare PtrSafe Function IsWindowVisible Lib "user32" (ByVal hWnd As LongPtr) As Long
#Else
    Private Declare Function PostMessage Lib "user32.dll" Alias "PostMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Declare Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
    Private Declare Function EnumWindows Lib "user32.dll" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
    Private Declare Function IsWindowVisible Lib "user32.dll" (ByVal hWnd As Long) As Long
#End If

Private ProcID As Long

#If VBA7 Then
Function EnumWindowsProc(ByVal hWnd As LongPtr, ByVal lParam As LongPtr) As Long
#Else
Function EnumWindowsProc(ByVal hWnd As Long, ByVal lParam As Long) As Long
#End If
Dim ProcessId As Long
    EnumWindowsProc = 1
    If IsWindowVisible(hWnd) Then
        GetWindowThreadProcessId hWnd, ProcessId
        If ProcessId = lParam Then
            PostMessage hWnd, WM_CLOSE, 0, 0
            EnumWindowsProc = 0
        End If
    End If
End Function

'    code de chay thu

Sub runPDF()
Dim filename As String
    filename = "c:\bi mat.pdf"
    filename = """" & filename & """"
    ProcID = Shell("C:\Program Files\Nitro PDF\Professional\nitroPDF.exe " & filename, vbMaximizedFocus)
End Sub

Sub closePDF()
    If ProcID = 0 Then Exit Sub
    EnumWindows AddressOf EnumWindowsProc, ProcID
End Sub

Code của bạn rất hay. Tuy nhiên, phải chọn chương trình cụ thể, nếu qua máy khác dùng phần mềm khác phải chỉnh code. Code của mình đang dùng để mở file pdf không phụ thuộc vào chương trình Pdf, nên mình nghĩ không biết có cách nào vận dụng để không phải khai báo phần mềm sử dụng không, nếu được thì thật thuận tiện.
Sub MOPDF()
Dim pdfPath As String
pdfPath = "C:\bi mat.pdf"
Call OpenAnyFile(pdfPath)
End Sub

Function OpenAnyFile(strPath As String)
Set objShell = CreateObject("Shell.Application")
objShell.Open (strPath)
End Function
 
Đóng bất kì loại file nào đang được mở ở một ứng dụng bất kì nhờ ứng dụng của bên thứ 3 (Ứng dụng Microsoft đề xuất) .

Cách này có chứa rủi ro, quyết định sử dụng hay không tùy vào bạn.

-----------------------------
Tải ứng dụng Handle nếu không có Internet (link dưới code) Vào cùng đường dẫn với File có VBA, và giải nén vào thư mục handle
Nếu có Internet thì code tự động tải.

*Tôi không viết Code cho trường hợp file được mở cùng lúc trong nhiều ứng dụng.
-----------------------------
JavaScript:
Option Explicit
#If VBA7 Then
  Private Declare PtrSafe Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" (ByVal pCaller As LongPtr, ByVal szURL As String, ByVal szFileName As String, ByVal dwReserved As Long, ByVal lpfnCB As LongPtr) As LongPtr
#Else
  Private Declare Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" (ByVal pCaller As Long, ByVal szURL As String, ByVal szFileName As String, ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long
#End If
' TaÒi ýìng duòng nêìu không có Internet
' Vào cùng ðýõÌng dâÞn võìi File có VBA và giaÒi nén vào thý muòc handle
' Nêìu có Internet thiÌ týò ðôòng
Private Const URL$ = "https://download.sysinternals.com/files/Handle.zip"
Public Sub CloseAppOpenFile()
  On Error Resume Next
  Dim a, FilePath As String
  FilePath = "D:\file.pdf"
  a = CheckFileInApp(FilePath)
  a = VBA.Split(a(0), " pid: ", , 1)
  Select Case VBA.UCase(VBA.Trim(a(0)))
  Case "EXCEL.EXE", "WORD.EXE", "POWERPOINT.EXE":
    VBA.GetObject(FilePath).Close True
  Case "ACCESS.EXE"
    VBA.GetObject(FilePath).CloseCurrentDatabase
  Case Else
    Shell "Cmd.exe /S /K TASKKILL /f /fi ""Imagename eq " & VBA.Trim(a(0)), vbHide
  End Select
End Sub
Private Function CheckFileInApp(FilePath As String) As Variant
  On Error Resume Next
  DoEvents
  If Not DownloadHandle Then Exit Function
  Dim temp$, i As Integer, k As Integer
  temp = PathHandle
  If VBA.Dir(temp & "log.txt", vbSystem) <> "" Then
    Kill temp & "log.txt"
  End If
  Dim aHandle As String
  #If Win64 Then
    aHandle = "handle64.exe"
  #Else
    aHandle = "handle.exe"
  #End If
  With VBA.CreateObject("WScript.Shell")
    .Run "cmd.exe /s /k cd """ & temp & """ && " & aHandle & " """ & FilePath & """ >" & temp & "log.txt && exit", 0, True
  End With
  Application.Wait VBA.Now + VBA.TimeSerial(0, 0, 1)
  With VBA.CreateObject("ADODB.Stream")
      .Open
      .Charset = "utf-8"
      .LoadFromFile temp & "log.txt"
      CheckFileInApp = VBA.Split(.ReadText, " type: ", , 1)
      .Close
  End With
End Function
Private Function DownloadHandle() As Boolean
  On Error Resume Next
  Dim Tmp$, temp$, zip$, File
  zip = "handle.zip"
 
  temp = PathHandle
  VBA.MkDir temp
  VBA.err.Clear
  If VBA.Dir(temp & "handle.exe", vbDirectory) <> "" Then GoTo Ends
  If URLDownloadToFile(0, URL, temp & zip, 0, 0) = 0 Then
    Application.Wait VBA.Now + VBA.TimeSerial(0, 0, 2)
    With VBA.CreateObject("Shell.Application")
      .Namespace(CVar(temp)).CopyHere .Namespace(CVar(temp & zip)).Items, &H10&
    End With
  End If
  Kill temp & zip
Ends:
  DownloadHandle = VBA.err.Number = 0
End Function

Private Function PathHandle() As String
  PathHandle = ThisWorkbook.Path & "\handle\"
End Function
 
Lần chỉnh sửa cuối:
Code của bạn rất hay. Tuy nhiên, phải chọn chương trình cụ thể, nếu qua máy khác dùng phần mềm khác phải chỉnh code. Code của mình đang dùng để mở file pdf không phụ thuộc vào chương trình Pdf, nên mình nghĩ không biết có cách nào vận dụng để không phải khai báo phần mềm sử dụng không, nếu được thì thật thuận tiện.
Sub MOPDF()
Dim pdfPath As String
pdfPath = "C:\bi mat.pdf"
Call OpenAnyFile(pdfPath)
End Sub

Function OpenAnyFile(strPath As String)
Set objShell = CreateObject("Shell.Application")
objShell.Open (strPath)
End Function
Chính vì vấn đề rất phụ thuộc vào cách mở PDF mà tôi đã khó tính. Với tôi không chỉ 1 câu cụt lủn "mở bằng đường dẫn", "đóng bằng đường dẫn" là được.

Nếu dùng cách mở như bạn thì system sẽ phải xác định, ứng dụng nào mặc định sẽ được dùng để mở tập tin PDF. Thông tin được ghi trong Registry. Với tập tin BMP, AVI, XLSX ... tương tự.

Nhìn hình 1 thấy (trên Windows 10 của tôi)

anh123.PNG

trong registry ở khóa HKEY_CLASSES_ROOT có khóa .pdf. Nhìn sang phải thì giá trị mặc định là AcroExch.Document.11. Cuộn xuống một tí, vẫn ở khóa HKEY_CLASSES_ROOT cho tới khóa AcroExch.Document.11 như ở hình 2.

anh456.PNG

Nhìn sang phải thấy giá trị mặc định là "C:\Program Files ... \ AcroRd32.exe". Cần phải đọc ra ứng dụng mặc định dùng để mở PDF. Tức: truy cập tới khóa HKEY_CLASSES_ROOT\.pdf rồi đọc giá trị của tên mặc định, giả sử là XYZ. Truy cập tới khóa HKEY_CLASSES_ROOT\XYZ\shell\Open\command rồi đọc ra giá trị của tên mặc định, rồi lọc ra đường dẫn tới tập tin EXE.

Một cách khác là: dùng Windows API hook WH_CBT (SetWindowsHookEx). Trong hook procedure CBTProc khi code = HCBT_CREATEWND hoặc HCBT_ACTIVATE thì wParam là handle của cửa sổ được tạo. Cần ghi lại handle này để sau đó đóng nó bằng WM_CLOSE. Tóm lại là: SetWindowsHookEx -> chạy code của bạn để mở PDF. Khi đó sẽ có cửa sổ ứng dụng NitroPDF hoặc Foxit hoặc ... được tạo, và trong CBTProc handle của cửa sổ đó được lưu lại. Vậy khi cần đóng cửa sổ thì gửi thông điệp WM_CLOSE tới cửa sổ đó thôi.

Code lấy giá trị từ Registry, code hook WH_CBT có thể tìm trên mạng, trên GPE. Bạn tự tìm hiểu.
 
Chính vì vấn đề rất phụ thuộc vào cách mở PDF mà tôi đã khó tính. Với tôi không chỉ 1 câu cụt lủn "mở bằng đường dẫn", "đóng bằng đường dẫn" là được.

Nếu dùng cách mở như bạn thì system sẽ phải xác định, ứng dụng nào mặc định sẽ được dùng để mở tập tin PDF. Thông tin được ghi trong Registry. Với tập tin BMP, AVI, XLSX ... tương tự.

Nhìn hình 1 thấy (trên Windows 10 của tôi)

View attachment 235987

trong registry ở khóa HKEY_CLASSES_ROOT có khóa .pdf. Nhìn sang phải thì giá trị mặc định là AcroExch.Document.11. Cuộn xuống một tí, vẫn ở khóa HKEY_CLASSES_ROOT ch

View attachment 235988

Nhìn sang phải thấy giá trị mặc định là "C:\Program Files ... \ AcroRd32.exe". Cần phải đọc ra ứng dụng mặc định dùng để mở PDF. Tức: truy cập tới khóa HKEY_CLASSES_ROOT\.pdf rồi đọc giá trị của tên mặc định, giả sử là XYZ. Truy cập tới khóa HKEY_CLASSES_ROOT\XYZ\shell\Open\command rồi đọc ra giá trị của tên mặc định, rồi lọc ra đường dẫn tới tập tin EXE.

Một cách khác là: dùng Windows API hook WH_CBT (SetWindowsHookEx). Trong hook procedure CBTProc khi code = HCBT_CREATEWND hoặc HCBT_ACTIVATE thì wParam là handle của cửa sổ được tạo. Cần ghi lại handle này để sau đó đóng nó bằng WM_CLOSE. Tóm lại là: SetWindowsHookEx -> chạy code của bạn để mở PDF. Khi đó sẽ có cửa sổ ứng dụng NitroPDF hoặc Foxit hoặc ... được tạo, và trong CBTProc handle của cửa sổ đó được lưu lại. Vậy khi cần đóng cửa sổ thì gửi thông điệp WM_CLOSE tới cửa sổ đó thôi.

Code lấy giá trị từ Registry, code hook WH_CBT có thể tìm trên mạng, trên GPE. Bạn tự tìm hiểu.
Mình cảm ơn bạn rất nhiều
 
Mình cảm ơn bạn rất nhiều
Bạn thử test trên các máy của bạn xem sao.
Mã:
Function defaultExe(ByVal ext As String) As String
Dim k As Long, key As String, filePath As String, shell As Object
    Set shell = CreateObject("WScript.Shell")
    key = shell.RegRead("HKCR\." & ext & "\")
    filePath = shell.RegRead("HKCR\" & key & "\Shell\open\command\")
    k = InStrRev(filePath, " ")
    filePath = Left(filePath, k - 1)
    Set shell = Nothing
    defaultExe = filePath
End Function

Sub test()
Dim exePath As String
'    ung dung mac dinh mo tap tin PDF
    exePath = defaultExe("pdf")
    MsgBox exePath
End Sub
 
Web KT

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

Back
Top Bottom