{"id":10302,"date":"2022-08-01T05:19:55","date_gmt":"2022-08-01T03:19:55","guid":{"rendered":"https:\/\/www.auditsi.eu\/?p=10302"},"modified":"2022-07-31T16:09:41","modified_gmt":"2022-07-31T14:09:41","slug":"excel-automatiser-lextraction-des-tableaux-de-donnees-dun-fichier-pdf","status":"publish","type":"post","link":"https:\/\/www.auditsi.eu\/?p=10302","title":{"rendered":"Excel : automatiser l&#8217;extraction des tableaux de donn\u00e9es d&#8217;un fichier PDF"},"content":{"rendered":"<p style=\"text-align: justify;\">L&#8217;<strong>automatisation<\/strong> des t\u00e2ches est dans l&#8217;air du temps ; surtout lorsqu&#8217;il s&#8217;agit de <strong>t\u00e2ches r\u00e9p\u00e9titives<\/strong> d\u00e9pourvues de valeur ajout\u00e9e. Il en est ainsi de t\u00e2ches d&#8217;extraction \/ importation de donn\u00e9es effectu\u00e9es de mani\u00e8re r\u00e9currente.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10314\" src=\"https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Power-Query-Table003-Page-2.png\" alt=\"PQ Power Query Table003 (Page 2)\" width=\"1011\" height=\"544\" srcset=\"https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Power-Query-Table003-Page-2.png 1011w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Power-Query-Table003-Page-2-300x161.png 300w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Power-Query-Table003-Page-2-768x413.png 768w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Power-Query-Table003-Page-2-730x393.png 730w\" sizes=\"auto, (max-width: 1011px) 100vw, 1011px\" \/><\/p>\n<p style=\"text-align: justify;\">L&#8217;expos\u00e9 ci-apr\u00e8s sera illustr\u00e9 par un exemple tr\u00e8s concret : l&#8217;extraction de statistiques mensuelles des immatriculations de v\u00e9hicules publi\u00e9 par la <a href=\"https:\/\/pfa-auto.fr\/\" target=\"_blank\" rel=\"noopener\">PFA<\/a>. Dans un pr\u00e9c\u00e9dent article, <a href=\"https:\/\/www.auditsi.eu\/?p=10284\">l&#8217;extraction des statistiques \u00e9tait effectu\u00e9e manuellement<\/a>. Dans cet article, <strong>cette extraction sera automatis\u00e9e \u00e0 l&#8217;aide d&#8217;un programme original<\/strong>.<\/p>\n<p style=\"text-align: justify;\">Si le <strong>langage VBA est le langage de pr\u00e9dilection pour automatiser l&#8217;ex\u00e9cution de t\u00e2ches<\/strong>, le <strong>langage M<\/strong> est, lui, le <strong>langage d&#8217;extraction et de manipulation de donn\u00e9es<\/strong> par excellence. L&#8217;association de ces deux langages permet de b\u00e9n\u00e9ficier de leurs <strong>capacit\u00e9s respectives<\/strong>.<\/p>\n<p style=\"text-align: justify;\"><em>Fonctionnement du programme (code-source d\u00e9taill\u00e9 plus loin) :<\/em><\/p>\n<p style=\"text-align: justify;\">Pour <strong>lancer le programme<\/strong>, ouvrir le classeur intitul\u00e9 &#8220;Automatisation import tableaux PDF.xlsm&#8221; t\u00e9l\u00e9chargeable au bas de cet article et <strong>cliquer sur le bouton &#8220;Importer tableaux PFA&#8221;<\/strong>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10317\" src=\"https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/Bouton-PFA.png\" alt=\"Bouton PFA\" width=\"295\" height=\"66\"><\/p>\n<p style=\"text-align: justify;\">Le programme demande \u00e0 l&#8217;utilisateur de <strong>s\u00e9lectionner le fichier PDF<\/strong> (\u00e0 obtenir sur <a href=\"https:\/\/pfa-auto.fr\/\" target=\"_blank\" rel=\"noopener\">le site du PFA<\/a> ou \u00e0 t\u00e9l\u00e9charger en bas de page) \u00e0 traiter (instruction <em>.GetOpenFileName<\/em>). Ensuite, cliquer sur le bouton Ouvrir. Le nom du fichier (et son chemin d&#8217;acc\u00e8s) est stock\u00e9 dans la variable <em>FichierPDF<\/em>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10318\" src=\"https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Selection-fichier-PDF.png\" alt=\"PQ S\u00e9lection fichier PDF\" width=\"946\" height=\"533\" srcset=\"https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Selection-fichier-PDF.png 946w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Selection-fichier-PDF-300x169.png 300w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Selection-fichier-PDF-768x433.png 768w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Selection-fichier-PDF-730x411.png 730w\" sizes=\"auto, (max-width: 946px) 100vw, 946px\" \/><\/p>\n<p style=\"text-align: justify;\">Ceci fait, la <a href=\"https:\/\/www.auditsi.eu\/?p=1696\"><strong>boucle compteur<\/strong> (<em>For.. To&#8230; Next&#8230;<\/em>)<\/a> traite chacun des trois tableaux de donn\u00e9es d\u00e9sign\u00e9s successivement (\u00e0 l&#8217;aide de la <strong>structure conditionnelle<\/strong> <a href=\"https:\/\/www.auditsi.eu\/?p=8040\"><em>Select Case&#8230; End Select<\/em><\/a>) par la variable <em>TableEnCours<\/em>.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"visualbasic\">Select Case i\r\n    Case 1:\r\n        TableEnCours = \"Table003 (Page 2)\"\r\n        SourceEnCours = \"Table003\"\r\n    Case 2:\r\n        TableEnCours = \"Table005 (Page 3)\"\r\n        SourceEnCours = \"Table005\"\r\n    Case 3:\r\n        TableEnCours = \"Table007 (Page 4)\"\r\n        SourceEnCours = \"Table007\"\r\nEnd Select<\/pre>\n<p style=\"text-align: justify;\">Ensuite, le programme <strong>cr\u00e9e la requ\u00eate<\/strong> (<em>.Queries.Add Name:=&#8221;&#8221; &amp; TableEnCours<\/em>) interrogeant le fichier PDF. La formule de la requ\u00eate est introduite par la commande &#8220;<em>Formula:=<\/em>&#8220;. La formule est <strong>r\u00e9dig\u00e9e en <a href=\"https:\/\/docs.microsoft.com\/fr-fr\/powerquery-m\/\" target=\"_blank\" rel=\"noopener\">langage M<\/a><\/strong>.<\/p>\n<p style=\"text-align: justify;\">Le <strong>langage M est le langage de manipulation de donn\u00e9es impl\u00e9ment\u00e9 par Microsoft sur le module ETL<\/strong> (<em>Extract-Transform-Load<\/em>) <strong>Power Query d&#8217;Excel<\/strong>. Power Query permet \u00e0 Excel de se connecter \u00e0 des sources de donn\u00e9es vari\u00e9es (bases de donn\u00e9es, classeurs Excel, fichiers ASCII \/ CSV, fichiers PDF&#8230;) et de mettre en forme les donn\u00e9es pour r\u00e9pondre aux besoins de l&#8217;utilisateur. Un exemple de connexion \u00e0 un fichier ASCII (en l&#8217;occurrence un FEC) est fourni dans l&#8217;article <a href=\"https:\/\/www.auditsi.eu\/?p=8590\">Analyser un FEC de plus d\u2019un million de lignes dans Excel<\/a>.<\/p>\n<p style=\"text-align: justify;\">Un programme \u00e9crit en VBA est en mesure de <strong>prendre le contr\u00f4le de Power Query<\/strong> en vue d&#8217;<strong>automatiser des requ\u00eates r\u00e9dig\u00e9es en langage M<\/strong>. C&#8217;est pr\u00e9cis\u00e9ment ce que r\u00e9alise le programme objet de cet article.<\/p>\n<p style=\"text-align: justify;\"><em>Requ\u00eate en langage M :<\/em><\/p>\n<p style=\"text-align: justify;\">La requ\u00eate r\u00e9dig\u00e9e en Langage M est appel\u00e9e par le programme \u00e9crit, lui, en langage VBA, ce qui appelle quelques commentaires.<\/p>\n<p style=\"text-align: justify;\">Le texte de la requ\u00eate est le suivant :<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">let\r\n    Source = Pdf.Tables(File.Contents(\"C:\\Users\\COLDIR01\\Downloads\\Flash-Marche-publication-mensuelle-PFA-0522.pdf\"), [Implementation=\"1.3\"]),\r\n    TableDonn\u00e9es = Source{[Id=\"Table003\"]}[Data],\r\n    #\"En-t\u00eates promus\" = Table.PromoteHeaders(TableDonn\u00e9es, [PromoteAllScalars=true]),\r\n    #\"Type modifi\u00e9\" = Table.TransformColumnTypes(#\"En-t\u00eates promus\",{{\"Marque\", type text}, {\"Volume\", Int64.Type}, {\"%\", type number}, {\"Volume_1\", Int64.Type}, {\"%_2\", type number}, {\"%Var\", type number}, {\"Volume_3\", Int64.Type}, {\"%_4\", type number}, {\"Volume_5\", Int64.Type}, {\"%_6\", type number}, {\"%Var_7\", type number}}),\r\n    #\"Erreurs supprim\u00e9es\" = Table.RemoveRowsWithErrors(#\"Type modifi\u00e9\", {\"Volume\"})\r\nin\r\n    #\"Erreurs supprim\u00e9es\"<\/pre>\n<p style=\"text-align: justify;\">La requ\u00eate est introduite par l&#8217;<strong>instruction &#8220;<em>Let<\/em>&#8220;<\/strong> ; elle est suivie de la <strong>d\u00e9finition de la source de donn\u00e9es<\/strong> puis de la <strong>liste des champs de donn\u00e9es<\/strong> \u00e0 reprendre et, le cas \u00e9ch\u00e9ant, des <strong>transformations de donn\u00e9es<\/strong> (cr\u00e9ation de champs calcul\u00e9s, d\u00e9finition des formats&#8230;).<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">let  \r\n   Variablename = expression,  \r\n   #\"Variable name\" = expression2  \r\nin   \r\n   Variablename<\/pre>\n<p style=\"text-align: justify;\">La source de donn\u00e9es est d\u00e9sign\u00e9e ici par &#8220;Source =&#8221; suivi du type de source (ici PDF : <em>Pdf.Tables<\/em>) puis de la localisation de la source. <a href=\"https:\/\/docs.microsoft.com\/fr-fr\/powerquery-m\/table-promoteheaders\" target=\"_blank\" rel=\"noopener\"><em>Table.PromoteHeaders<\/em><\/a> indique que la premi\u00e8re ligne du tableau correspond \u00e0 l&#8217;ent\u00eate de colonne (nom du champ de donn\u00e9es).<\/p>\n<p style=\"text-align: justify;\">Le commande <a href=\"https:\/\/docs.microsoft.com\/fr-fr\/powerquery-m\/table-transformcolumntypes\" target=\"_blank\" rel=\"noopener\"><em>.TransformColumnTypes<\/em><\/a> pr\u00e9cise le <strong>type de donn\u00e9es<\/strong> de chaque champ de donn\u00e9es. <em>Type text<\/em> pr\u00e9cise que le champ de donn\u00e9es est de type <strong>alphanum\u00e9rique<\/strong>, c&#8217;est-\u00e0-dire qu&#8217;il contiendra indiff\u00e9remment du texte, des chiffres, des symboles&#8230; <em>Type number<\/em> sp\u00e9cifie un <strong>nombre r\u00e9el (avec des d\u00e9cimales)<\/strong> alors que <em>Int64.type<\/em> sp\u00e9cifie un <strong>nombre entier (donc sans d\u00e9cimales)<\/strong>. Si le type de donn\u00e9es sp\u00e9cifi\u00e9 est num\u00e9rique (entier ou r\u00e9el) et que le contenu du champ est alphanum\u00e9rique, un message d&#8217;erreur appara\u00eetra (&#8220;Error&#8221;) :<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10329\" src=\"https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Power-Query-ERROR.png\" alt=\"PQ Power Query ERROR\" width=\"873\" height=\"168\" srcset=\"https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Power-Query-ERROR.png 873w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Power-Query-ERROR-300x58.png 300w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Power-Query-ERROR-768x148.png 768w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Power-Query-ERROR-730x140.png 730w\" sizes=\"auto, (max-width: 873px) 100vw, 873px\" \/><\/p>\n<p style=\"text-align: justify;\">La commande <em>.RemoveRowsWithErrors<\/em> supprime les enregistrements (lignes) pour lesquelles le champ de donn\u00e9es &#8220;Volume&#8221; g\u00e9n\u00e8re une erreur (car non num\u00e9rique). Dans le cas pr\u00e9sent, le tableau de donn\u00e9es int\u00e8gre inutilement la derni\u00e8re ligne citant la source AAA DATA :<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10315\" src=\"https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/Source-AAA-DATA.png\" alt=\"Source AAA DATA\" width=\"492\" height=\"88\" srcset=\"https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/Source-AAA-DATA.png 492w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/Source-AAA-DATA-300x54.png 300w\" sizes=\"auto, (max-width: 492px) 100vw, 492px\" \/><\/p>\n<p style=\"text-align: justify;\">Cette m\u00eame requ\u00eate est repr\u00e9sent\u00e9e sous cette forme dans l&#8217;\u00e9diteur avanc\u00e9 de Power Query (accessible \u00e0 partir du classeur Excel g\u00e9n\u00e9r\u00e9 par le code VBA) :<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10304\" src=\"https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Table003-Page-2.png\" alt=\"PQ Table003 (Page 2)\" width=\"1048\" height=\"393\" srcset=\"https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Table003-Page-2.png 1048w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Table003-Page-2-300x113.png 300w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Table003-Page-2-1024x384.png 1024w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Table003-Page-2-768x288.png 768w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Table003-Page-2-730x274.png 730w\" sizes=\"auto, (max-width: 1048px) 100vw, 1048px\" \/><\/p>\n<p><em>Requ\u00eate en langage M int\u00e9gr\u00e9e au code VBA :<\/em><\/p>\n<p style=\"text-align: justify;\">Le <strong>programme VBA automatise la g\u00e9n\u00e9ration des requ\u00eates en langage M<\/strong> avec la commande <em>.Queries.Add<\/em>.&nbsp; La r\u00e9daction de la requ\u00eate fait l&#8217;objet de quelques am\u00e9nagements afin d&#8217;\u00eatre intelligible par le code VBA.<\/p>\n<p style=\"text-align: justify;\">Tout d&#8217;abord, pour le code VBA la requ\u00eate en langage M n&#8217;a pas de signification particuli\u00e8re. Aussi cette requ\u00eate, identifi\u00e9e par la commande &#8220;<em>Formula =<\/em>&#8220;, est-elle stock\u00e9e sous la forme d&#8217;une simple cha\u00eene de caract\u00e8res. Les <strong>guillemets servent \u00e0 d\u00e9limiter des cha\u00eenes de caract\u00e8res<\/strong> tant en Langage M qu&#8217;en VBA, il est n\u00e9cessaire d&#8217;ajouter un guillemet pour chaque s\u00e9rie de guillemets pr\u00e9sente dans la requ\u00eate M.<\/p>\n<p style=\"text-align: justify;\">Ensuite, pour que le programme VBA cr\u00e9\u00e9 des requ\u00eates personnalis\u00e9es \u00e0 la vol\u00e9e, il est n\u00e9cessaire de remplacer le nom des sources de donn\u00e9es et des tables de donn\u00e9es initialement d\u00e9finies en dur (Table003, Table005&#8230;) par des variables. Une <strong>variable correspond \u00e0 un emplacement m\u00e9moire qui stocke des donn\u00e9es<\/strong>, des r\u00e9sultats de calculs\u2026 La valeur prise par une variable peut \u00eatre chang\u00e9e \u00e0 loisir durant l&#8217;ex\u00e9cution du programme. C&#8217;est cette possibilit\u00e9 qui est mise \u00e0 profit ici pour cr\u00e9er trois requ\u00eates semblables \u00e0 l&#8217;aide d&#8217;une seule ligne de code.<\/p>\n<p style=\"text-align: justify;\">Requ\u00eate en langage M int\u00e9gr\u00e9e dans le programme VBA :<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"visualbasic\">ActiveWorkbook.Queries.Add Name:=\"\" &amp; TableEnCours &amp; \"\", Formula:= _\r\n    \"let\" &amp; Chr(13) &amp; \"\" &amp; Chr(10) &amp; _\r\n    \"    Source = Pdf.Tables(File.Contents(\"\"\" &amp; FichierPDF &amp; \"\"\"), [Implementation=\"\"1.3\"\"]),\" &amp; Chr(13) &amp; \"\" &amp; Chr(10) &amp; _\r\n    \"    TableDonn\u00e9es = Source{[Id=\"\"Table003\"\"]}[Data],\" &amp; Chr(13) &amp; \"\" &amp; Chr(10) &amp; _\r\n    \"    #\"\"En-t\u00eates promus\"\" = Table.PromoteHeaders(TableDonn\u00e9es, [PromoteAllScalars=true]),\" &amp; Chr(13) &amp; \"\" &amp; Chr(10) &amp; _\r\n    \"    #\"\"Type modifi\u00e9\"\" = Table.TransformColumnTypes(#\"\"En-t\u00eates promus\"\",{{\"\"Marque\"\", type text}, {\"\"Volume\"\", Int64.Type}, {\"\"%\"\", type number}, {\"\"Volume_1\"\", Int64.Type}, {\"\"%_2\"\", type number}, {\"\"%Var\"\", type number}, {\"\"Volume_3\"\", Int64.Type}, {\"\"%_4\"\", type number}, {\"\"Volume_5\"\", Int64.Type}, {\"\"%_6\"\", type number}, {\"\"%Var_7\"\", type number}}),\" &amp; Chr(13) &amp; \"\" &amp; Chr(10) &amp; _\r\n    \"    #\"\"Erreurs supprim\u00e9es\"\" = Table.RemoveRowsWithErrors(#\"\"Type modifi\u00e9\"\", {\"\"Volume\"\"})\" &amp; Chr(13) &amp; \"\" &amp; Chr(10) &amp; _\r\n    \"in\" &amp; Chr(13) &amp; \"\" &amp; Chr(10) &amp; _\r\n    \"    #\"\"Erreurs supprim\u00e9es\"\"\"\r\n<\/pre>\n<p style=\"text-align: justify;\">Cette requ\u00eate est cr\u00e9\u00e9e \u00e0 trois reprises (du fait de la boucle compteur <em>For&#8230; To&#8230; Next<\/em>) pour r\u00e9cup\u00e9rer chacune des trois tables d\u00e9sign\u00e9es tour \u00e0 tour.<\/p>\n<p style=\"text-align: justify;\">Une fois ces trois tables int\u00e9gr\u00e9es, une derni\u00e8re requ\u00eate est r\u00e9dig\u00e9e (toujours en langage M) afin de fusionner les trois premi\u00e8res. Cette <strong>fusion est op\u00e9r\u00e9e \u00e0 l&#8217;aide de la commande <em>.Combine<\/em><\/strong> suivie du nom des tables \u00e0 fusionner :<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">let\r\n    \/\/Fusion des trois tables pr\u00e9c\u00e9demment import\u00e9es\r\n    Source = Table.Combine({#\"Table003 (Page 2)\", #\"Table005 (Page 3)\", #\"Table007 (Page 4)\"})\r\nin\r\n    Source<\/pre>\n<p style=\"text-align: justify;\">Le classeur Excel nouvellement cr\u00e9\u00e9 par le programme est maintenant \u00e0 disposition de l&#8217;utilisateur. Ses donn\u00e9es peuvent servir de base pour cr\u00e9er, par exemple, un tableau de bord (cf \u00e0 ce sujet les deux s\u00e9ries d&#8217;articles d\u00e9di\u00e9es \u00e0 ce sujet : <a href=\"https:\/\/www.auditsi.eu\/?cat=2265\">tableaux de bord dynamiques<\/a> et <a href=\"https:\/\/www.auditsi.eu\/?cat=2251\">tableaux de bord visuels<\/a>).<\/p>\n<p style=\"text-align: justify;\">Les requ\u00eates cr\u00e9\u00e9es par la macro VBA peuvent \u00eatre ouvertes par le lecteur pour analyse. Pour ce faire, dans le classeur cr\u00e9\u00e9 par le programme VBA, se rendre dans le <strong>menu Donn\u00e9es puis Requ\u00eates et connexions<\/strong> :<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10321\" src=\"https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/Excel-menu-Donnees-Requetes.png\" alt=\"Excel menu Donn\u00e9es Requ\u00eates\" width=\"602\" height=\"312\" srcset=\"https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/Excel-menu-Donnees-Requetes.png 602w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/Excel-menu-Donnees-Requetes-300x155.png 300w\" sizes=\"auto, (max-width: 602px) 100vw, 602px\" \/><\/p>\n<p style=\"text-align: justify;\">Les requ\u00eates disponibles s&#8217;affichent \u00e0 droite de l&#8217;\u00e9cran :<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10322\" src=\"https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/Excel-Liste-Requetes-et-connexions.png\" alt=\"Excel Liste Requ\u00eates et connexions\" width=\"302\" height=\"307\" srcset=\"https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/Excel-Liste-Requetes-et-connexions.png 302w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/Excel-Liste-Requetes-et-connexions-295x300.png 295w\" sizes=\"auto, (max-width: 302px) 100vw, 302px\" \/><\/p>\n<p style=\"text-align: justify;\">Pour <strong>visualiser le contenu de la requ\u00eate<\/strong> : faire un clic droit sur une des requ\u00eates puis s\u00e9lectionner Modifier dans le menu contextuel. Power Query, le module ETL d&#8217;Excel s&#8217;ouvre alors et affiche le r\u00e9sultat de la requ\u00eate (ici avec la requ\u00eate ToutesTables) :<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10303\" src=\"https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-ToutesTables.png\" alt=\"PQ ToutesTables\" width=\"1318\" height=\"532\" srcset=\"https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-ToutesTables.png 1318w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-ToutesTables-300x121.png 300w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-ToutesTables-1024x413.png 1024w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-ToutesTables-768x310.png 768w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-ToutesTables-730x295.png 730w\" sizes=\"auto, (max-width: 1318px) 100vw, 1318px\" \/><\/p>\n<p style=\"text-align: justify;\">Pour <strong>visualiser le texte de la requ\u00eate<\/strong> (et \u00e9ventuellement l&#8217;amender), cliquer sur <strong>Editeur avanc\u00e9<\/strong> (menu Accueil) :<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-10323\" src=\"https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Power-Query-ToutesTables-editeur-avance.png\" alt=\"PQ Power Query ToutesTables \u00e9diteur avanc\u00e9\" width=\"845\" height=\"404\" srcset=\"https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Power-Query-ToutesTables-editeur-avance.png 845w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Power-Query-ToutesTables-editeur-avance-300x143.png 300w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Power-Query-ToutesTables-editeur-avance-768x367.png 768w, https:\/\/www.auditsi.eu\/wp-content\/uploads\/2022\/07\/PQ-Power-Query-ToutesTables-editeur-avance-730x349.png 730w\" sizes=\"auto, (max-width: 845px) 100vw, 845px\" \/><\/p>\n<p style=\"text-align: justify;\"><em>Le code source de la macro VBA est retranscrit in extenso ci-apr\u00e8s :<\/em><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"visualbasic\">'---------------------------------------------------------------------------------------\r\n'Automatisation de la r\u00e9cup\u00e9ration des tables chiffr\u00e9es des \u00e9tats d'immatriculations PFA\r\n'Ecrit par Beno\u00eet RIVIERE 07\/2022\r\n'---------------------------------------------------------------------------------------\r\n\r\n\r\nOption Explicit\r\n\r\n\r\nSub ImportTablesDonn\u00e9esPFA()\r\n    'D\u00e9finition des variables\r\n    '---Nom du fichier PDF \u00e0 traiter (comprend le chemin d'acc\u00e8s)\r\n    Dim FichierPDF As Variant\r\n    '---Variable boucle compteur\r\n    Dim i As Integer\r\n    '---Nom de la table de donn\u00e9es en cours de traitement\r\n    Dim TableEnCours As String\r\n    '---Source en cours de traitement\r\n    Dim SourceEnCours As String\r\n    '---Variable tableau contenant le nom des tables de donn\u00e9es\r\n    Dim Tables(3) As String\r\n        \r\n    'Collecte du nom du fichier PDF \u00e0 traiter\r\n    FichierPDF = Application.GetOpenFilename(\"Fichiers PDF (*.pdf),*.pdf,Tous les fichiers (*.*),*.* \", 1, \"S\u00e9lectionnez le fichier PDF \u00e0 traiter\", , False)\r\n    '---Si le traitement est annul\u00e9 par l'utilisateur (bouton annul\u00e9, touche Echap...) -&gt; arr\u00eat du programme\r\n    If FichierPDF = False Then Exit Sub\r\n    \r\n    'Cr\u00e9ation d'un nouveau classeur Excel\r\n    Workbooks.Add\r\n    \r\n    'Boucle de traitement des tables de dnn\u00e9es PDF\r\n    '---3 tabes de donn\u00e9es \u00e0 traiter\r\n    For i = 1 To 3\r\n        'En fonction de la position du compteur (1, 2 ou 3), d\u00e9finition du tableau de donn\u00e9es \u00e0 importer\r\n        Select Case i\r\n            Case 1:\r\n                TableEnCours = \"Table003 (Page 2)\"\r\n                SourceEnCours = \"Table003\"\r\n            Case 2:\r\n                TableEnCours = \"Table005 (Page 3)\"\r\n                SourceEnCours = \"Table005\"\r\n            Case 3:\r\n                TableEnCours = \"Table007 (Page 4)\"\r\n                SourceEnCours = \"Table007\"\r\n        End Select\r\n        Tables(i) = TableEnCours\r\n        \r\n        'Cr\u00e9ation de la requ\u00eate interrogeant le fichier PDF (formule r\u00e9dig\u00e9e en langage M)\r\n        ActiveWorkbook.Queries.Add Name:=\"\" &amp; TableEnCours &amp; \"\", Formula:= _\r\n            \"let\" &amp; Chr(13) &amp; \"\" &amp; Chr(10) &amp; _\r\n            \"    Source = Pdf.Tables(File.Contents(\"\"\" &amp; FichierPDF &amp; \"\"\"), [Implementation=\"\"1.3\"\"]),\" &amp; Chr(13) &amp; \"\" &amp; Chr(10) &amp; _\r\n            \"    TableDonn\u00e9es = Source{[Id=\"\"\" &amp; SourceEnCours &amp; \"\"\"]}[Data],\" &amp; Chr(13) &amp; \"\" &amp; Chr(10) &amp; _\r\n            \"    #\"\"En-t\u00eates promus\"\" = Table.PromoteHeaders(TableDonn\u00e9es, [PromoteAllScalars=true]),\" &amp; Chr(13) &amp; \"\" &amp; Chr(10) &amp; _\r\n            \"    #\"\"Type modifi\u00e9\"\" = Table.TransformColumnTypes(#\"\"En-t\u00eates promus\"\",{{\"\"Marque\"\", type text}, {\"\"Volume\"\", Int64.Type}, {\"\"%\"\", type number}, {\"\"Volume_1\"\", Int64.Type}, {\"\"%_2\"\", type number}, {\"\"%Var\"\", type number}, {\"\"Volume_3\"\", Int64.Type}, {\"\"%_4\"\", type number}, {\"\"Volume_5\"\", Int64.Type}, {\"\"%_6\"\", type number}, {\"\"%Var_7\"\", type number}}),\" &amp; Chr(13) &amp; \"\" &amp; Chr(10) &amp; _\r\n            \"    #\"\"Erreurs supprim\u00e9es\"\" = Table.RemoveRowsWithErrors(#\"\"Type modifi\u00e9\"\", {\"\"Volume\"\"})\" &amp; Chr(13) &amp; \"\" &amp; Chr(10) &amp; _\r\n            \"in\" &amp; Chr(13) &amp; \"\" &amp; Chr(10) &amp; _\r\n            \"    #\"\"Erreurs supprim\u00e9es\"\"\"\r\n    Next i\r\n    \r\n    'Cr\u00e9ation d'une requ\u00eate (intutul\u00e9e \"ToutesTables\") fusionnant le r\u00e9sultat des trois requ\u00eates pr\u00e9c\u00e9dentes (toujours en langeg M)\r\n    ActiveWorkbook.Queries.Add Name:=\"ToutesTables\", Formula:= _\r\n        \"let\" &amp; Chr(13) &amp; \"\" &amp; Chr(10) &amp; _\r\n        \"    Source = Table.Combine({#\"\"\" &amp; Tables(1) &amp; \"\"\", #\"\"\" &amp; Tables(2) &amp; \"\"\", #\"\"\" &amp; Tables(3) &amp; \"\"\"})\" &amp; Chr(13) &amp; \"\" &amp; Chr(10) &amp; _\r\n        \"in\" &amp; Chr(13) &amp; \"\" &amp; Chr(10) &amp; _\r\n        \"    Source\"\r\n    \r\n    'Cr\u00e9ation d'une nouvelle feuille de travail dans le classeur en curs\r\n    ActiveWorkbook.Worksheets.Add\r\n    \r\n    'Le r\u00e9sultat de la requ\u00eate \"ToutesTables\" est affich\u00e9 dans l'onglet nouvellement cr\u00e9\u00e9 sous la forme d'un tableau de donn\u00e9es\r\n    With ActiveSheet.ListObjects.Add(SourceType:=0, Source:= _\r\n        \"OLEDB;Provider=Microsoft.Mashup.OleDb.1;Data Source=$Workbook$;Location=ToutesTables;Extended Properties=\"\"\"\"\" _\r\n        , Destination:=Range(\"$A$1\")).QueryTable\r\n        .CommandType = xlCmdSql\r\n        .CommandText = Array(\"SELECT * FROM [ToutesTables]\")\r\n        .RowNumbers = False\r\n        .FillAdjacentFormulas = False\r\n        .PreserveFormatting = True\r\n        .RefreshOnFileOpen = False\r\n        .BackgroundQuery = True\r\n        .RefreshStyle = xlInsertDeleteCells\r\n        .SavePassword = False\r\n        .SaveData = True\r\n        .AdjustColumnWidth = True\r\n        .RefreshPeriod = 0\r\n        .PreserveColumnInfo = True\r\n        .ListObject.DisplayName = \"ToutesTables\"\r\n        .Refresh BackgroundQuery:=False\r\n    End With\r\nEnd Sub\r\n<\/pre>\n<p style=\"text-align: justify;\">Afin de s&#8217;exercer, le lecteur trouvera ci-apr\u00e8s en <strong>libre t\u00e9l\u00e9chargement<\/strong> le classeur Excel comprenant la macro VBA, les statistiques d&#8217;immatriculations de mai et juin 2022 (fichiers PDF) ainsi qu&#8217;un classeur Excel g\u00e9n\u00e9r\u00e9 par la macro VBA.<\/p>\n<p style=\"text-align: justify;\">Le lecteur souhaitant approfondir ses connaissances sur le langage M pourra consulter l&#8217;abondante <a href=\"https:\/\/docs.microsoft.com\/fr-fr\/powerquery-m\/\" target=\"_blank\" rel=\"noopener\">documentation sur le site de Microsoft<\/a>.<\/p>\n<p style=\"text-align: justify;\">___<\/p>\n<p style=\"text-align: justify;\">En savoir plus sur l\u2019<a href=\"https:\/\/www.auditsi.eu\/?tag=analyse-de-donnees\">analyse de donn\u00e9es<\/a>&nbsp;\/ <a href=\"https:\/\/www.auditsi.eu\/?cat=1569\">Programmer en VBA<\/a> \/ <a href=\"https:\/\/www.auditsi.eu\/?p=7504\">Ex\u00e9cuter des requ\u00eates SQL dans du code VBA<\/a><\/p>\n<div id=\"sconnect-is-installed\" style=\"display: none; text-align: justify;\">2.13.0.0<\/div>\n<div id=\"sconnect-is-installed\" style=\"display: none;\">2.13.0.0<\/div>\n<div id=\"sconnect-is-installed\" style=\"display: none;\">2.13.0.0<\/div>\n<div id=\"sconnect-is-installed\" style=\"display: none;\">2.13.0.0<\/div>\n<div id=\"sconnect-is-installed\" style=\"display: none;\">2.13.0.0<\/div>\n<div id=\"sconnect-is-installed\" style=\"display: none;\">2.13.0.0<\/div>\n<div id=\"sconnect-is-installed\" style=\"display: none;\">2.13.0.0<\/div>\n<div id=\"sconnect-is-installed\" style=\"display: none;\">2.13.0.0<\/div>\n<div id=\"sconnect-is-installed\" style=\"display: none;\">2.13.0.0<\/div>\n<div id=\"sconnect-is-installed\" style=\"display: none;\">2.13.0.0<\/div>\n<div id=\"sconnect-is-installed\" style=\"display: none;\">2.13.0.0<\/div>\n<div id=\"sconnect-is-installed\" style=\"display: none;\">2.13.0.0<\/div>\n<div id=\"sconnect-is-installed\" style=\"display: none;\">2.13.0.0<\/div>\n<div id=\"sconnect-is-installed\" style=\"display: none;\">2.13.0.0<\/div>\n<div id=\"sconnect-is-installed\" style=\"display: none;\">2.13.0.0<\/div>\n<div id=\"sconnect-is-installed\" style=\"display: none;\">2.13.0.0<\/div>\n<div id=\"sconnect-is-installed\" style=\"display: none;\">2.13.0.0<\/div>\n<div id=\"sconnect-is-installed\" style=\"display: none;\">2.13.0.0<\/div>\n<div id=\"sconnect-is-installed\" style=\"display: none;\">2.13.0.0<\/div>\n<div id=\"sconnect-is-installed\" style=\"display: none;\">2.13.0.0<\/div>\n<div style=\"padding-bottom:20px; padding-top:10px;\" class=\"hupso-share-buttons\"><!-- Hupso Share Buttons - https:\/\/www.hupso.com\/share\/ --><a class=\"hupso_counters\" href=\"https:\/\/www.hupso.com\/share\/\"><img decoding=\"async\" src=\"https:\/\/static.hupso.com\/share\/buttons\/lang\/fr\/share-small.png\" style=\"border:0px; padding-top:2px; float:left;\" alt=\"Share Button\"\/><\/a><script type=\"text\/javascript\">var hupso_services_c=new Array(\"twitter\",\"facebook_like\",\"facebook_send\",\"email\",\"print\",\"linkedin\");var hupso_counters_lang = \"fr_FR\";var hupso_image_folder_url = \"\";var hupso_twitter_via=\"BenoitRiviere14\";var hupso_url_c=\"\";var hupso_title_c=\"Excel%20%3A%20automatiser%20l%27extraction%20des%20tableaux%20de%20donn%C3%A9es%20d%27un%20fichier%20PDF\";<\/script><script type=\"text\/javascript\" src=\"https:\/\/static.hupso.com\/share\/js\/counters.js\"><\/script><!-- Hupso Share Buttons --><\/div>","protected":false},"excerpt":{"rendered":"<p>L&#8217;automatisation des t\u00e2ches est dans l&#8217;air du temps ; surtout lorsqu&#8217;il s&#8217;agit de t\u00e2ches r\u00e9p\u00e9titives d\u00e9pourvues de valeur ajout\u00e9e. Il en est ainsi de t\u00e2ches d&#8217;extraction \/ importation de donn\u00e9es effectu\u00e9es de mani\u00e8re r\u00e9currente. L&#8217;expos\u00e9 ci-apr\u00e8s sera illustr\u00e9 par un exemple tr\u00e8s concret : l&#8217;extraction de statistiques mensuelles des immatriculations de v\u00e9hicules publi\u00e9 par la &#8230;<\/p>\n<p><a href=\"https:\/\/www.auditsi.eu\/?p=10302\" class=\"more-link\">Continue reading &lsquo;Excel : automatiser l&#8217;extraction des tableaux de donn\u00e9es d&#8217;un fichier PDF&rsquo; &raquo;<\/a><\/p>\n<div style=\"padding-bottom:20px; padding-top:10px;\" class=\"hupso-share-buttons\"><!-- Hupso Share Buttons - https:\/\/www.hupso.com\/share\/ --><a class=\"hupso_counters\" href=\"https:\/\/www.hupso.com\/share\/\"><img src=\"https:\/\/static.hupso.com\/share\/buttons\/lang\/fr\/share-small.png\" style=\"border:0px; padding-top:2px; float:left;\" alt=\"Share Button\"\/><\/a><script type=\"text\/javascript\">var hupso_services_c=new Array(\"twitter\",\"facebook_like\",\"facebook_send\",\"email\",\"print\",\"linkedin\");var hupso_counters_lang = \"fr_FR\";var hupso_image_folder_url = \"\";var hupso_twitter_via=\"BenoitRiviere14\";var hupso_url_c=\"\";var hupso_title_c=\"Excel%20%3A%20automatiser%20l%27extraction%20des%20tableaux%20de%20donn%C3%A9es%20d%27un%20fichier%20PDF\";<\/script><script type=\"text\/javascript\" src=\"https:\/\/static.hupso.com\/share\/js\/counters.js\"><\/script><!-- Hupso Share Buttons --><\/div>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"ngg_post_thumbnail":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","_links_to":"","_links_to_target":""},"categories":[48,8,2680,215],"tags":[2709,2710,2713,2714,815,2707,1633,307,985,2718,2706,2712,2711,2704,2705,2708,2719,2715,2703,2717,2716],"class_list":["post-10302","post","type-post","status-publish","format-standard","hentry","category-excel","category-extractions-de-donnees","category-m","category-vba","tag-combine","tag-queries-add","tag-removerowswitherrors","tag-transformcolumntypes","tag-automatisation","tag-etl","tag-excel","tag-fichier-pdf","tag-importation-de-donnees","tag-int64-type","tag-langage-m","tag-let-in","tag-pdf-tables","tag-pfa","tag-pfa-auto-fr","tag-power-query","tag-requete","tag-table-promoteheaders","tag-tableau-de-donnees","tag-type-number","tag-type-text"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":false,"_links":{"self":[{"href":"https:\/\/www.auditsi.eu\/index.php?rest_route=\/wp\/v2\/posts\/10302","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.auditsi.eu\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.auditsi.eu\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.auditsi.eu\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.auditsi.eu\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10302"}],"version-history":[{"count":19,"href":"https:\/\/www.auditsi.eu\/index.php?rest_route=\/wp\/v2\/posts\/10302\/revisions"}],"predecessor-version":[{"id":10336,"href":"https:\/\/www.auditsi.eu\/index.php?rest_route=\/wp\/v2\/posts\/10302\/revisions\/10336"}],"wp:attachment":[{"href":"https:\/\/www.auditsi.eu\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10302"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.auditsi.eu\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10302"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.auditsi.eu\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10302"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}