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
les codes je les ai tous
je viens de tester ta méthode findwindow
impossible chez chez moi c'est 0 réussite
j'ai bien essayé d'adater mon case sur firfox mais la encore le findwindows negatif il tourne en boucle et me bloque obligé de fermer le fichier
j'ai rallongé les sleep mais rien n'y fait
je sais que tu a du mal à m'écouter mais
comme je te l'ai dis il n'y a qu'un seul point commun a nos version c'est le clipboard

d'autre part pourquoi la touche tab j'en ai pas besoins chez moi ?

d'autre part aussi impossible de mettre la librairie pour le data object je l'ai donc mis en late binding
comme ca on est sur ,et puis il est plus pratique si l'on veut distribuer son fichier
voici le code tel que je l'ai modifié chez moi
VB:
Option Explicit
'
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassname As String, ByVal lpWindowName As String) As LongPtr
Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As LongPtr, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) 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 Const WM_CLOSE As Integer = &H10
Sub test_dudu()
GetPDFText "C:\Users\patricktoulon\Desktop\trier un tableau avec la fonction sort d'excel 2023.pdf"
End Sub
'-----------------------
'Returns a PDF file text
'-----------------------
Function GetPDFText(FichierPDF As String) As String
    Dim Clipboard As Object
    Dim ChromeExe As String
    Dim NomPDF As String
    Dim hWnd As LongPtr
    Dim nav As String
    Dim PartTitle As String '
     Const SleepTime = 500
   Set Clipboard = CreateObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
  
    'Check file
    If Len(Dir(FichierPDF)) = 0 Then
        MsgBox "Fichier <" & FichierPDF & "> non trouvé !"
        Exit Function
    End If
 
    '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: PartTitle = " - Google Chrome"
    Case Dir(nav2) <> "": nav = nav2: PartTitle = " - Google Chrome"
    Case Dir(nav4) <> "": nav = nav4: PartTitle = " - Mozilla Firefox"
    Case Dir(nav3) <> "": nav = nav3: PartTitle = " - Mozilla Firefox"
    'possible other browsers
    Case Else
    End Select

    'PDF file name
    NomPDF = Mid(FichierPDF, InStrRev(FichierPDF, "\") + 1)
 
    'Empty the Clipboard
    With Clipboard
        .SetText ""
        .PutInClipboard
    End With

    'Kill possible existing Windows
    Do While 1
        hWnd = FindWindow(vbNullString, NomPDF & PartTitle)
        If Not hWnd = 0 Then
            Call SendMessage(hWnd, WM_CLOSE, 0, 0)
            DoEvents
        Else
            Exit Do
        End If
    Loop

    'Run Chrome and wait for the Window to be ready
    Call Shell(nav & " --new-window -url " & """" & FichierPDF & """", vbNormalFocus)
  Sleep 1000
    Do While hWnd = 0
        hWnd = FindWindow(vbNullString, NomPDF & " - Google Chrome")
        Temporisation 1000
    Loop
  Debug.Print "handle trouvé :" & hWnd
    Sleep SleepTime

    'Send keys to Select All / Copy / Kill the application
    Call SendKeysSelectCopyClose
 
    'Get Clipboard data
    With Clipboard
        .GetFromClipboard
        On Error Resume Next
        GetPDFText = .GetText
        On Error GoTo 0
    End With
End Function

'----------------------------
'Envoi des touches sur Chrome
'----------------------------
Private Sub SendKeysSelectCopyClose()
    Const Tempo = 1000

    SendKeybd "a", "ctrl"   'Touche Ctrl A
    Temporisation Tempo
 
    SendKeybd &H9           'Touche TAB
    Temporisation Tempo

    SendKeybd "c", "ctrl"   'Touche CTRL C
    Temporisation Tempo
 
    SendKeybd &H73, "alt"   'Touche ALT F4
End Sub

'--------------------------------------------
'Wrap keybd_event
'Alter = "down", "up", "shift", "ctrl", "alt"
'E.g. SendKeybd &H43, "ctrl" 'Send Ctrl C
'https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
'--------------------------------------------
Sub SendKeybd(ByVal Key As Variant, Optional ByVal Alter As String = "")
    Dim AlterValue As Byte
 
    If VarType(Key) = vbString Then Key = Asc(Key)
 
    Select Case UCase(Alter)
        Case "DOWN"
            keybd_event Key, 1, 0, 0
        Case "UP"
            keybd_event Key, 0, 2, 0
        Case "SHIFT"
            AlterValue = &H10
            GoSub AlterKey
        Case "CTRL"
            AlterValue = &H11
            GoSub AlterKey
        Case "ALT"
            AlterValue = &H12
            GoSub AlterKey
        Case Else
            GoSub DownUp
    End Select
    Exit Sub
 
AlterKey:
    keybd_event AlterValue, 1, 0, 0
    GoSub DownUp
    keybd_event AlterValue, 0, 2, 0
    Return
 
DownUp:
    keybd_event Key, 1, 0, 0
    keybd_event Key, 0, 2, 0
    Return
End Sub

'-------------
'Temporisation
'-------------
Private Sub Temporisation(NbDoEvents As Integer)
    Dim k As Integer
 
    For k = 1 To NbDoEvents
        DoEvents
    Next k
End Sub
 

Dudu2

XLDnaute Barbatruc
Alors tu as raison, ton implémentation de mon code ne fonctionne pas non plus chez moi et je ne sais pas du tout pourquoi. C'est un mystère.

Je t'envoie le fichier avec les 2 codes, le tien qui ne fonctionne pas et le mien qui fonctionne (à vérifier quand même chez toi).
Le challenge, si vous l'acceptez ? Trouver ce qui fait que le tien ne fonctionne pas !

d'autre part aussi impossible de mettre la librairie
C'est indiqué dessus comme sur le "Port-Salut":
Code:
Dim Clipboard As New MSForms.DataObject 'Reference Microsoft Forms 2.0 Object Library (or add and delete a USerForm)

je viens de voir aussi que tu envoie les code de touche sous leur forme string
En plus tu sais pas lire non plus ;) :
VB:
If VarType(Key) = vbString Then Key = Asc(Key)
 

Pièces jointes

  • Classeur2.xlsm
    37.6 KB · Affichages: 2
Dernière édition:

Dudu2

XLDnaute Barbatruc
Aahhh ! Mais je sais pourquoi !
Parce que tu as MODIFIÉ mon code:
Code:
'----------------------------
'Envoi des touches sur Chrome
'----------------------------
Private Sub SendKeysSelectCopyClose()
    Const Tempo = 1000

    SendKeybd "a", "ctrl"   'Touche Ctrl A
    Temporisation Tempo
 
    SendKeybd &H9           'Touche TAB
    Temporisation Tempo

    SendKeybd "c", "ctrl"   'Touche CTRL C
    Temporisation Tempo
 
    SendKeybd &H73, "alt"   'Touche ALT F4
End Sub

Je t'ai dis que keybd_event envoie ce qu'il veut.
Mais tu ne veux pas m'écouter ! 🤣
 

patricktoulon

XLDnaute Barbatruc
re
non ton code original ne fonctionne pas même avant les modifs
je te l'ai dit ca tourne en boucle au findwindow
chez moi le titre de la fenêtre c'est le titre du document et non le nom du fichier
que se soit sur chrome ou firefox

c'est pas que je veux pas t'ecouter
et pour info mon code clipboard fonctionne très bien sur 2007 32 et 2013 32 et 2016 64
et pourtant mon excel 2016 est lent comme un balourd tout les lancements reussisent
je teste toute à l'heure sur le 365 de mon pot voisin

ps: devant une telle lenteur j'ai viré chrome énormement gourmand
donc je ne peut tester que sur firefox

tu ne peut raisonnablement pas proposer un truc qui ne fonctionne que sur chrome
demain ton ami change tu fait quoi ? tu change tout le code ?

mon code au moins fonctionne avec tout les navigateurs sans distinction
 

patricktoulon

XLDnaute Barbatruc
alors j'ai testé ton dernier fichier mais avec mon select case pour firefox
et c'est toujoujours pareil ca tourne en boucle au findwindow
j'ai testé en paralelle ma findwindowbyPartTitle
je trouve bien ma fenêtre firefox avec le titre du fichier +" - Mozilla Firfox"
on a donc un réel problème avec findwindow
 

patricktoulon

XLDnaute Barbatruc
re je viens de voir que ce que tu dis etre mon code ne l'est pas tu l'a modifié avec tes sub keybd
qui font absolument pas le job chez moi de toute facons
quand tu dis qu'un code ne fonctionne pas test l'original
l'original c'est celui là
change juste le nom du fichier dans le test2
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)

Sub Temporisation(NbDoEvents As Integer)
'@dudu2 sur exceldownloads
    Dim k As Integer
    For k = 1 To NbDoEvents
        DoEvents
    Next k
End Sub
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(nav4) <> "": nav = nav4
    Case Dir(nav3) <> "": nav = nav3    'je met le nav3 en premier je préfère firefox64
    Case Else
    End Select


    'run the browser chosen in the select case
    Call Shell(nav & " --new-window -url " & """" & FichierPDF & """", vbNormalFocus)

re:

    'we create the clipboard object (late binding)no reference required
    ' we empty the clipboard
    Set clip = Nothing
    If essai = 2 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
    Sleep 1000    'increase if necessary

  
    'loop and  simulating (CTRL+A and C keys) as long as the clipboard is not full
    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
        Temporisation 10
        keybd_event &H43, 1, 0, 0    'appuie sur la touche C
        keybd_event &H43, 0, &H2, 0    'Lacher la touche C
        Temporisation 10
        keybd_event &H11, 0, &H2, 0    'Lacher la touche CTRL
        Temporisation 30
        On Error Resume Next
        clip.GetFromClipboard
        T = clip.GetText(1)
        If Err Then Err.Clear: essai = essai + 1: GoTo re
        DoEvents
    Loop

    '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

    '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
 

patricktoulon

XLDnaute Barbatruc
et pour conclure
et tu le sais tres bien
faire des attentes à durée arbitraire n'a jamais été une solution pérenne
on doit avoir un signal d'entrée et un signal de sortie
tu utilise une fonction api keybd_event et tu trouve moyen de passer par une passerelle keybd ;)

pour info j'ai testé juste cette partie la
et ca ne fait pas ce qu'il faut faire
a savoir
apuie sur CTRL (reste appuyé)
appuie sur "a" et non "A"
relache la touche "a"
appuie sur "c" et non sur "C"
relache la touche "c"
relache la touche ctrl

appuie sur ctrl(reste appuyé) et non "Alt"
appuie sur touche"F4"
relache la touche "F4"
relache la touche CTRL et non "Alt"
 

Dudu2

XLDnaute Barbatruc
Je ne réponds pas à tes 4 derniers posts. Je ne peux pas non plus savoir si mon code fonctionne chez toi parce que tu utilises TON implémentation de MON code qui est fausse (voir post #66). Mais ce n'est pas grave.

Mais parlons de ton code. Je l'ai testé chez moi, et... ça ne fonctionne absolument pas.
Ça reste sur Chrome, texte sélectionné. Et plus rien ne se passe.
 

Pièces jointes

  • Classeur2.xlsm
    28.8 KB · Affichages: 0
Dernière édition:

Dudu2

XLDnaute Barbatruc
Comme ça, ça fonctionne.
Code:
    'loop and  simulating (CTRL+A and C keys) as long as the clipboard is not full
    Do While Len(T) = 0
        keybd_event &H11, 0, 0, 0    'appuie sur la touche CTRL
        keybd_event &H41, 0, 0, 0    'appuie sur la touche A
        keybd_event &H41, 0, 2, 0    'Lacher la touche A
        keybd_event &H11, 0, 2, 0    'Lacher la touche CTRL
        Temporisation 10
       
        keybd_event &H9, 0, 0, 0
        keybd_event &H9, 0, 2, 0
        Temporisation 10
       
        keybd_event &H11, 0, 0, 0    'appuie sur la touche CTRL
        keybd_event &H43, 0, 0, 0    'appuie sur la touche C
        keybd_event &H43, 0, 2, 0    'Lacher la touche C
        keybd_event &H11, 0, 2, 0    'Lacher la touche CTRL
        Temporisation 3000
       
        On Error Resume Next
        clip.GetFromClipboard
        T = clip.GetText(1)
        If Err Then Err.Clear: essai = essai + 1: GoTo re
        DoEvents
    Loop
 

patricktoulon

XLDnaute Barbatruc
ben oui moi j'ai mis tout en dur pour les touche je me susi même pas ennuyé avec le hex du nombre

bon j'ai trafiqué la tienne pour qu'elle fonctionne chez moi
1° case chrome et firefox
2°j'ai viré findwindow pour ma fonction findwindowByPartTitle( comme ça je n'ai pas a me souvier de l'exactutude de la barre de titre de la fenêtre ent out cas le nom du fichier doit s'y trouver
3°j'ai viré ta keybd
j'ai codé les touche en dur
4°au fait pour le clip c'est pas .GetText mais .GetText(1)
c'est un poil plus lent avec le findwindw+

pour le mien peut etre que je vais un peu vite rallonge les temps chez toi pour chrome
peut être aussi que la touche Tab est necessaire chez toi chez moi non ( et ca c'est dejà un problème)

voila
j'ai rallongé les temps dans la mienne pour que tu teste
j'oublie tout le temps qu'en 64 vous êtes plus lent sur le clipboard
debloque au cas ou la touche tab
en l'etat ca fonctionne chez moi les deux (la tienne légèrement plus longue)
dans le module 3 tu a la fonction findwindow+
je te fait une vidéo si tu veux
 

Pièces jointes

  • pdf to text by chrome or firefox V2 .xlsm
    33.6 KB · Affichages: 1

Dudu2

XLDnaute Barbatruc
faire des attentes à durée arbitraire n'a jamais été une solution pérenne
Pourtant c'est bien ce que tu fais après ton Shell.
Code:
Sleep 1000    'increase if necessary
Et si cette durée n'est pas suffisante, tu envoies de Ctrl A & Ctrl C sur la fenêtre Excel et comme tu récupères quelque chose tu conclues que c'est bon.

Le fait de faire un FindWindow assure au moins que Chrome ou Firefox ont été lancés et leur fenêtre présente. Selon la charge du PC ça prend "un certain temps" comme le fût du canon.
Une Sleep 500 derrière est une sécurité (parfois ça marche sans, parfois c'est nécessaire) assure que le PDF est prêt.

Alors si le FindWindow ne fonctionne pas chez toi, je demande bien pourquoi !
 

Dudu2

XLDnaute Barbatruc
bon j'ai trafiqué la tienne pour qu'elle fonctionne chez moi
Non, tu l'as trafiqué sur la base de mon code que tu avais déjà trafiqué comme indiqué au post #66
car tu as remplacé les "A" et "C" par des minuscules, et ça, ça ne fonctionne pas avec keybd_event.
Code:
'----------------------------
'Envoi des touches sur Chrome
'----------------------------
Private Sub SendKeysSelectCopyClose()
    Const Tempo = 1000

    SendKeybd "a", "ctrl"   'Touche Ctrl A <<<<<<<<<< tu as remplacé "A" par "a"
    Temporisation Tempo
 
    SendKeybd &H9           'Touche TAB
    Temporisation Tempo

    SendKeybd "c", "ctrl"   'Touche CTRL C <<<<<<<<<< tu as remplacé "C" par "c"
    Temporisation Tempo
 
    SendKeybd &H73, "alt"   'Touche ALT F4
End Sub

Par contre l'envoi du TAB qui fout le bazar chez toi et qui est nécessaire chez moi c'est un problème car on ne sait pas ce qui le conditionne. Chrome 32 bits ? 64 bits ?
 

Discussions similaires

Statistiques des forums

Discussions
312 505
Messages
2 089 096
Membres
104 030
dernier inscrit
Angy