XL 2016 VBA - Récupérer le texte d'un fichier PDF

Dudu2

XLDnaute Barbatruc
Bonjour,

Y a-t-il un moyen de chercher et récupérer du texte directement dans un PDF sans avoir à l'ouvrir / tout sélectionner / copier dans le clipboard texte ?

Merci pour toute information.

Edit: Titre modifié pour mieux refléter la solution de cette longue discussion.
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
bon allez je me permet d'insister sur le fait que l'on est en train de se perdre avec la gestion de fenêtres
donc tu a trouvé une belle astuce qui consiste à cliquer sur la fenêtre
et ben je vais m'en servir pour chrome et firefox

VB:
'******************************************************************************************************************************************************
'    ___      _     _______  __      _    ____  _   _  _______  ___      _   _    _    ___      _     _.
'   //  \\   /\\      //    // \\   //   //    //  //    //    //  \\   //  //   //   //  \\   //|   //
'  //___//  //__\    //    //__//  //   //    //__||    //    //   //  //  //   //   //   //  // |  //
' //       //   \\  //    //  \\  //   //    //  \\    //    //   //  //  //   //   //   //  //  | //
'//       //    // //    //   // //   //___ //    \\  //     \\__//  //__//   //___ \\__//  //   |//
'******************************************************************************************************************************************************
'-----------------------------------------
'pdf grabber
'[@patricktoulon] on exceldownloads
'adding Chrome firefox control in an select case
'reduction of (window ready wait times) for  (chrome or firefox)
'added clipboard management
'non-empty clipboard wait loop
'loading time lasts the time the clipboard takes to load the data
'updated V 2
'replacing wscript.shell.sendkeys
'by simulating keys with Api keybd_event
'the numeric keypad is no longer disabled
'-----------------------------------------
Option Explicit
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare PtrSafe Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)
Private Declare PtrSafe Sub mouse_event Lib "user32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As LongPtr)
'mouse_event() dwFlags
Private Const MOUSEEVENTF_LEFTDOWN = &H2
Private Const MOUSEEVENTF_LEFTUP = &H4

Function GrabbTextInPdF(FichierPDF As String) As String
    Dim nav$, T$, clip As Object, wshshell As Object, essai

    Cells(1, 1).CurrentRegion.ClearContents
    'browser path constantes
    Const nav1 = "C:\Program Files\Google\Chrome\Application\chrome.exe"
    Const nav2 = "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
    Const nav3 = "C:\Program Files\Mozilla Firefox\firefox.exe"
    Const nav4 = "C:\Program Files (x86)\Mozilla Firefox\firefox.exe"

    'select case true to find the browser installed on your system
    Select Case True
    Case Dir(nav1) <> "": nav = nav1
    Case Dir(nav2) <> "": nav = nav2
    Case Dir(nav3) <> "": nav = nav3    'je met le nav3 en premier je préfère firefox64
    Case Dir(nav4) <> "": nav = nav4
    Case Else
    End Select


    'run the browser chosen in the select case
    Call Shell(nav & " --new-window -url " & """" & FichierPDF & """", vbMaximizedFocus)
    Sleep 1000    'increase if necessary

re:

    'we create the clipboard object (late binding)no reference required
    ' we empty the clipboard
    Set clip = Nothing
    If essai = 4 Then MsgBox " 2 essais ont été effectués sans succès arrêt de la procédure": Exit Function
    Set clip = CreateObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
    clip.SetText "": clip.PutInClipboard


    'we still leave a minimum of 1 second for the window to be ready
    'even if the document is not completely loaded


    'loop and  simulating (CTRL+A and C keys) as long as the clipboard is not full
    Call mouse_event(MOUSEEVENTF_LEFTDOWN, 100, 100, 0, 0)
    Call mouse_event(MOUSEEVENTF_LEFTUP, 100, 100, 0, 0)
    Do While Len(T) = 0
        keybd_event &H11, 1, 0, 0    'appuie sur la touche CTRL
        keybd_event &H41, 1, 0, 0    'appuie sur la touche A
        keybd_event &H41, 0, &H2, 0    'Lacher la touche A
        keybd_event &H43, 1, 0, 0    'appuie sur la touche C
        keybd_event &H43, 0, &H2, 0    'Lacher la touche C
        keybd_event &H11, 0, &H2, 0    'Lacher la touche CTRL
        On Error Resume Next
        clip.GetFromClipboard
        T = clip.GetText(1)
        If Err Then Err.Clear: essai = essai + 1: GoTo re
        DoEvents
    Loop
    Call mouse_event(MOUSEEVENTF_LEFTDOWN, 100, 100, 0, 0)
    Call mouse_event(MOUSEEVENTF_LEFTUP, 100, 100, 0, 0)

    'simulate CTRL+F4 keys to close browser window
    keybd_event &H11, 1, 0, 0    'appuie sur la touche CTRL
    keybd_event &H73, 0, 0, 0    'appuie sur la touche F4
    keybd_event &H73, 0, &H2, 0    'Lacher la touche F4
    keybd_event &H11, 0, &H2, 0    'Lacher la touche CTRL

    'Temporisation 10
    ' MsgBox "il y a eu " & essai & " tentative(s)"
    'return on worksheet
    With ThisWorkbook.Worksheets(1)
        .[A1].Select
        .[A1].ClearContents
        .Paste
        GrabbTextInPdF = .[A1].Value
    End With
    Set clip = Nothing
End Function



Sub test2()
    GrabbTextInPdF "C:\Users\patricktoulon\Desktop\trier un tableau avec la fonction sort d'excel 2023.pdf"
End Sub
 

Dudu2

XLDnaute Barbatruc
Il fait 62.8 Mo. Alors c'est long MAIS ça fonctionne.

Je vois que tu fais une double boucle sur l'envoi de Ctrl A + Ctrl C (sur Len(T) sans temporisation et sur Re: ) en attendant d'avoir quelque chose dans le Clipboard. C'est ton idée de départ.
Je me demande pourquoi tu n'as pas temporisé entre 2 séquences d'envoi de ces touches.
D'autre part, la boucle sur le Re: (quand Err) je l'ai supprimée et ça marche quand même.

Je me rends compte que j'ai fait une bourde dans mon code en bouclant sur l'envoi des touches (j'avais inclus le Alt F4 !). Je vais recoder ta boucle dans mon code en étant plus attentif.
 

patricktoulon

XLDnaute Barbatruc
e vois que tu fais une double boucle sur l'envoi de Ctrl A + Ctrl C (sur Len(T) sans temporisation et sur Re: ) en attendant d'avoir quelque chose dans le Clipboard. C'est ton idée de départ.
oui c'est mon idée de depart et comme tu vois j'avais raison
alors c'est pas vraiment une double boucle
la boucle do/loop tant que T est vide
mais dans le cas ou j'ai une erreur d'accès au dataobject
je repars sur e et refait le clip
le re est proposé 4 fois
la récursivité "re:" est primordiale car l'erreur d'accès se produit quand tu cherche à lire par gettext(1) et qu'il est en train de charger par le CTRL+C

voilà
il aura fallu 8 pages pour te convaincre mais on y arrive ;)
tu te radouci hein 🤣🤣🤣
la vitesse sur chrome est fulgurante sur des pdfs de tailles raisonnables
 

Dudu2

XLDnaute Barbatruc
En effet, ton idée de départ était la bonne.
Je l'ai introduite dans mon code (cette fois correctement !) et ça fonctionne.

Alors le Sleep de départ, il n'est pas vraiment nécessaire dans la mesure où je fais un FindWindow, je l'ai gardé pour minimiser les boucles sur les envois de touches que j'ai quand même temporisés.

Voilà un fichier avec les 2 codes... Voir plus loin .
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
ok on est bon pour les deux versions
pour tester j'ai rajouter les sleep 10 au send key dans ma version et non pas un sleep 100 mais 50 dans le do/loop
et en effet j'ai 3 essais moi aussi
mais on ne peut pas considérer des sleep de 10 et 50 comme harbitraire mais plutot comme aide à la réactivité mémoire
là je suis d'accords

bon voilà
que dire
What else ;)
 

patricktoulon

XLDnaute Barbatruc
allez juste pour le fun et puisque tu insiste avec ton findwindow regarde comme je le fait moi le find window
si on faisait simple ;)
réfléchi à la logique
et réfléchi a quoi ca te dispenserait ;)

VB:
'******************************************************************************************************************************************************
'    ___      _     _______  __      _    ____  _   _  _______  ___      _   _    _    ___      _     _.
'   //  \\   /\\      //    // \\   //   //    //  //    //    //  \\   //  //   //   //  \\   //|   //
'  //___//  //__\    //    //__//  //   //    //__||    //    //   //  //  //   //   //   //  // |  //
' //       //   \\  //    //  \\  //   //    //  \\    //    //   //  //  //   //   //   //  //  | //
'//       //    // //    //   // //   //___ //    \\  //     \\__//  //__//   //___ \\__//  //   |//
'******************************************************************************************************************************************************
'-----------------------------------------
'pdf grabber
'[@patricktoulon] on exceldownloads
'adding Chrome firefox control in an select case
'reduction of (window ready wait times) for  (chrome or firefox)
'added clipboard management
'non-empty clipboard wait loop
'loading time lasts the time the clipboard takes to load the data
'updated V 2
'replacing wscript.shell.sendkeys
'by simulating keys with Api keybd_event
'the numeric keypad is no longer disabled
'-----------------------------------------
'Option Explicit
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare PtrSafe Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)
Private Declare PtrSafe Sub mouse_event Lib "user32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As LongPtr)
Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr
'mouse_event() dwFlags
Private Const MOUSEEVENTF_LEFTDOWN = &H2
Private Const MOUSEEVENTF_LEFTUP = &H4

Function GrabbTextInPdF(FichierPDF As String) As String
    Dim nav$, T$, clip As Object, wshshell As Object, essai,hwnD as longptr

    Cells(1, 1).CurrentRegion.ClearContents
    'browser path constantes
    Const nav1 = "C:\Program Files\Google\Chrome\Application\chrome.exe"
    Const nav2 = "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
    Const nav3 = "C:\Program Files\Mozilla Firefox\firefox.exe"
    Const nav4 = "C:\Program Files (x86)\Mozilla Firefox\firefox.exe"

    'select case true to find the browser installed on your system
    Select Case True
    Case Dir(nav1) <> "": nav = nav1
    Case Dir(nav2) <> "": nav = nav2
    Case Dir(nav3) <> "": nav = nav3    'je met le nav3 en premier je préfère firefox64
    Case Dir(nav4) <> "": nav = nav4
    Case Else
    End Select

    HWND = GetActiveWindow''le handle est le handle de l'application
    'run the browser chosen in the select case
    Call Shell(nav & " --new-window -url " & """" & FichierPDF & """", vbMaximizedFocus)

    Do While hwnD= GetActiveWindow'boucle tant que l'on est sur le handle de l'application
        Sleep 500    'increase if necessary
        DoEvents
    Loop
re:

    'we create the clipboard object (late binding)no reference required
    ' we empty the clipboard
    Set clip = Nothing
    If essai = 4 Then MsgBox " 2 essais ont été effectués sans succès arrêt de la procédure": Exit Function
    Set clip = CreateObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
    clip.SetText "": clip.PutInClipboard


    'we still leave a minimum of 1 second for the window to be ready
    'even if the document is not completely loaded


    'loop and  simulating (CTRL+A and C keys) as long as the clipboard is not full
    Call mouse_event(MOUSEEVENTF_LEFTDOWN, 100, 100, 0, 0)
    Call mouse_event(MOUSEEVENTF_LEFTUP, 100, 100, 0, 0)
    Do While Len(T) = 0
        keybd_event &H11, 1, 0, 0    'appuie sur la touche CTRL
        keybd_event &H41, 1, 0, 0    'appuie sur la touche A
        keybd_event &H41, 0, &H2, 0    'Lacher la touche A
        keybd_event &H43, 1, 0, 0    'appuie sur la touche C
        keybd_event &H43, 0, &H2, 0    'Lacher la touche C
        keybd_event &H11, 0, &H2, 0    'Lacher la touche CTRL
        On Error Resume Next
        clip.GetFromClipboard
        T = clip.GetText(1)
        If Err Then Err.Clear: essai = essai + 1: GoTo re
        DoEvents
    Loop
    Call mouse_event(MOUSEEVENTF_LEFTDOWN, 100, 100, 0, 0)
    Call mouse_event(MOUSEEVENTF_LEFTUP, 100, 100, 0, 0)

    'simulate CTRL+F4 keys to close browser window
    keybd_event &H11, 1, 0, 0    'appuie sur la touche CTRL
    keybd_event &H73, 0, 0, 0    'appuie sur la touche F4
    keybd_event &H73, 0, &H2, 0    'Lacher la touche F4
    keybd_event &H11, 0, &H2, 0    'Lacher la touche CTRL

    'Temporisation 10
    ' MsgBox "il y a eu " & essai & " tentative(s)"
    'return on worksheet
    With ThisWorkbook.Worksheets(1)
        .[A1].Select
        .[A1].ClearContents
        .Paste
        GrabbTextInPdF = .[A1].Value
    End With
    Set clip = Nothing
End Function

Sub test2()
    GrabbTextInPdF "C:\Users\patricktoulon\Desktop\trier un tableau avec la fonction sort d'excel 2023.pdf"
End Sub
 

Discussions similaires

Statistiques des forums

Discussions
312 698
Messages
2 091 100
Membres
104 760
dernier inscrit
emilielechelard