VBA et développement Web

Image non disponible


précédentsommairesuivant

VIII. API WinInet

Les API sont des fonctions que l'on trouve dans des librairies (fichiers .dll).
Ces fonctions ne sont pas directement utilisables par VBA, il n'y a pas de référence que l'on pourrait ajouter à l'éditeur VBA.

Il faut donc déclarer chacune de ces fonctions, en ciblant le bon fichier dll, et avec les paramètres requis.
Il faut également trouver les valeurs des constantes et déclarer les types.

C'est souvent un travail pénible, et on peut s'aider de sites tels que AllAPI.net

À partir d'Access 2010, une version 64 bits d'Office est disponible et demande une adaptation du code : Développer avec Office 64 bits


Avant de chercher la déclaration pour VB, la bible est MSDN : Windows Internet
MSDN est en anglais mais c'est ici que nous trouverons toute la documentation nécessaire.
Par contre, on n'y trouve rien pour VB...

En plus de fonctions communes, on trouve notamment dans WinInet un découpage en deux parties :
- les sessions HTTP.
- les sessions FTP.

Avant d'aller plus loin, voici quelques liens qui pourraient vous être utiles :
- Article Access : Repousser les limites d'Access - récupérer un fil RSS ;
- FAQ Excel : Comment récupérer le contenu d'un fichier txt placé sur internet ? ;
- Sources Access : Récupérer le code HTML d'une page Web à l'aide de l'APIWindows ;
- Sources Access : Récupérer le code HTML d'une page Web à l'aide de l'API Windows (2e méthode) ;
- Sources Access : Envoi/réception de fichier sur un serveur FTP.

Les codes trouvés dans ces pages sont exploitables quel que soit le produit Office utilisé.

VIII-A. Gestion d'erreurs WinInet

Lors de l'appel aux fonctions de l'API, les erreurs ne sont pas des erreurs VBA "classiques" que l'on peut gérer avec On Error.

Il faut vérifier le retour de chaque fonction (voir sur MSDN le retour en cas d'erreur), et en cas d'erreur utiliser Err.LastDllError pour connaître le numéro de l'erreur.
Les erreurs internet sont répertoriées ici : Error Messages.
Ou ici en français : INFO : Codes d'erreur WinInet (12001 à 12156).

VIII-B. Sessions HTTP

Cette partie est reprise dans la librairie Microsoft WinHTTP Services.
Si possible, il est beaucoup plus simple d'utiliser cette librairie que les API.

Pour une utilisation de l'API, nous allons avoir besoin de déclarer les fonctions, types, et constantes utilisés.
Ces déclarations doivent être écrites en en-tête de module.

Il faut d'abord trois fonctions pour se connecter à internet :

 
Sélectionnez

Private Declare Function InternetOpen Lib "wininet" Alias "InternetOpenA" (ByVal sAgent As String, _
            ByVal lAccessType As Long, ByVal sProxyName As String, ByVal sProxyBypass As String, _
            ByVal lFlags As Long) As Long
Private Declare Function InternetConnect Lib "wininet" Alias "InternetConnectA" (ByVal hInternetSession As Long, _
            ByVal sServerName As String, ByVal nServerPort As Integer, ByVal sUserName As String, _
            ByVal sPassword As String, ByVal lService As Long, ByVal lFlags As Long, _
            ByVal lContext As Long) As Long
Private Declare Function InternetCloseHandle Lib "wininet" (ByRef hInet As Long) As Long


Et voici les constantes dont nous avons besoin :

 
Sélectionnez

Private Const INTERNET_OPEN_TYPE_PRECONFIG = 0
Private Const INTERNET_SERVICE_HTTP = 3
Private Const INTERNET_INVALID_PORT_NUMBER = 0

Pour trouver la valeur d'une constante, recherchez dans Google le nom de la constante suivi de Declare.
On trouve alors la plupart du temps la valeur recherchée.


Dans une nouvelle procédure ConnectHTTP, nous allons nous connecter au site www.developpez.com.

Première étape, on se connecte à internet grâce à InternetOpen :

 
Sélectionnez

Dim hOpen As Long
hOpen = InternetOpen("SiteHTTP", INTERNET_OPEN_TYPE_PRECONFIG, vbNullString, vbNullString, 0)


- Le premier paramètre est un nom libre.
- Le deuxième paramètre définit l'utilisation d'un proxy : INTERNET_OPEN_TYPE_PRECONFIG demande de rechercher le proxy configuré par défaut dans Windows.
- Les troisième et quatrième paramètres définissent des paramètres de proxy que nous n'utilisons pas ici.
- vbNullString est une chaîne de caractères spéciale qui indique qu'aucune valeur n'est passée en paramètre.
- Le cinquième et dernier paramètre est un flag (booléen) qui pourrait définir une exécution asynchrone ou la gestion du cache ; on ne l'utilise pas ici.

La fonction renvoie un identifiant (appelée handle) que nous devons conserver pour la suite.
Si la connexion est effectuée sans erreur, ce handle est différent de zéro.

Deuxième étape : la connexion au site web grâce à la fonction InternetConnect :

 
Sélectionnez

Sub ConnectHTTP()
Dim hOpen As Long, hConnect As Long
hOpen = InternetOpen("SiteHTTP", INTERNET_OPEN_TYPE_PRECONFIG, vbNullString, vbNullString, 0)
If hOpen <> 0 Then
   hConnect = InternetConnect(hOpen, "www.developpez.com", _
               INTERNET_INVALID_PORT_NUMBER, vbNullString, vbNullString, INTERNET_SERVICE_HTTP, 0, 0)
End If
End Sub


- On réutilise en premier paramètre l'identifiant retourné par InternetOpen.
- Ensuite on indique l'adresse du site auquel on souhaite se connecter.
- En troisième paramètre on définit le port de connexion : utilisez INTERNET_INVALID_PORT_NUMBER pour le port par défaut en fonction du service défini ensuite.
- Un utilisateur et un mot de passe peuvent être définis si besoin dans les deux paramètres suivants.
- le sixième paramètre spécifie le service utilisé pour la connexion : HTTP ici, on pourrait indiquer FTP par exemple.
- les deux derniers paramètres sont inutilisés pour notre besoin.

La fonction renvoie également un identifiant (handle) que nous devons conserver pour la suite.
Si la connexion au site est effectuée sans erreur, ce handle est différent de zéro.

Il faut, à la fin, penser à fermer les connexions ouvertes avec InternetCloseHandle :

 
Sélectionnez

Sub ConnectHTTP()
Dim hOpen As Long, hConnect As Long
hOpen = InternetOpen("SiteHTTP", INTERNET_OPEN_TYPE_PRECONFIG, vbNullString, vbNullString, 0)
If hOpen <> 0 Then
   hConnect = InternetConnect(hOpen, "www.developpez.com", _
               INTERNET_INVALID_PORT_NUMBER, vbNullString, vbNullString, INTERNET_SERVICE_HTTP, 0, 0)
   If hConnect <> 0 Then
       InternetCloseHandle hConnect
   End If
   InternetCloseHandle hOpen
End If
End Sub


Une fois la connexion établie, nous pouvons envoyer des requêtes à la page comme nous l'avions fait avec la librairie WinHTTP.
C'est toutefois bien plus complexe à coder avec les API.

Je vous invite, pour cette partie, à consulter cette source : Récupérer le code HTML d'une page Web à l'aide de l'API Windows (2e méthode).

Une autre source également intéressante, qui utilise InternetOpenUrl au lieu de InternetConnect :
Récupérer le code HTML d'une page Web à l'aide de l'APIWindows.

VIII-C. Sessions FTP

Pour cette partie, il n'y a pas de librairie disponible.
Seules les API nous permettent d'utiliser la partie FTP de WinInet.

VIII-C-1. Sessions FTP sans proxy

Un exemple est disponible dans les sources :
- Sources Access : Envoi/réception de fichier sur un serveur FTP.

L'utilisation est similaire à une session HTTP, à l'aide des fonctions : InternetOpen, InternetConnect et InternetCloseHandle.
La différence est la spécification du service FTP à l'appel de InternetConnect.
Il faut, à la place de INTERNET_SERVICE_HTTP, utiliser INTERNET_SERVICE_FTP qui se déclare ainsi :

 
Sélectionnez

Private Const INTERNET_SERVICE_FTP = 1


Dans l'exemple, la valeur 1 est utilisée directement.

Une fois la connexion établie, on peut utiliser les fonctions WinInet dont le nom commence par FTP.

VIII-C-2. Sessions FTP avec proxy

Vous rencontrez des problèmes de connexion si vous êtes derrière un proxy HTTP (de type CERN).

Ces deux articles de MSDN expliquent le principe d'un tel proxy et comment contourner le problème :
- Comment faire du FTP un proxy CERN en utilisant l'API WinInet ;
- Exemple : FTP proxy CERN protégé par mot de passe en utilisant l'API WinInet.

La solution est d'utiliser la fonction InternetOpenUrl.
Le mot de passe pour le FTP sera précisé dans l'adresse.

Voici un exemple :

 
Sélectionnez

Option Explicit
            
Private Const INTERNET_OPEN_TYPE_PRECONFIG = 0
            
Private Declare Function InternetOpen Lib "wininet" Alias "InternetOpenA" _
        (ByVal sAgent As String, ByVal lAccessType As Long, ByVal sProxyName As String, _
         ByVal sProxyBypass As String, ByVal lFlags As Long) As Long
Private Declare Function InternetConnect Lib "wininet" Alias "InternetConnectA" _
        (ByVal hInternetSession As Long, ByVal sServerName As String, ByVal nServerPort As Integer, _
         ByVal sUserName As String, ByVal sPassword As String, ByVal lService As Long, _
         ByVal lFlags As Long, ByVal lContext As Long) As Long
Private Declare Function InternetCloseHandle Lib "wininet" (ByRef hInet As Long) As Long
Private Declare Function InternetOpenUrl Lib "wininet" Alias "InternetOpenUrlA" _
        (ByVal hInternetSession As Long, ByVal lpszUrl As String, ByVal lpszHeaders As String, _
         ByVal dwHeadersLength As Long, ByVal dwFlags As Long, ByVal dwContext As Long) As Long
Private Declare Function InternetReadFile Lib "wininet" (ByVal hFile As Long, sBuffer As Any, _
         ByVal lNumBytesToRead As Long, lNumberOfBytesRead As Long) As Integer
            
Function DownloadFTP()
Dim hOpen As Long
Dim hInternetFile As Long
Dim buffer() As Byte
Dim lRead As Long
Dim f As Integer
' Connexion internet
hOpen = InternetOpen("SiteWeb", INTERNET_OPEN_TYPE_PRECONFIG, vbNullString, vbNullString, 0)
' Ouverture du fichier par son URL complète
hInternetFile = InternetOpenUrl(hOpen, "ftp://login:pass@monftp.com/monfichier.gif", vbNullString, 0, 0, 0)
' Création du fichier cible sur le PC
f = FreeFile
Open ThisWorkbook.Path & "\monfichier.gif" For Binary As #f
' Lecture du fichier par paquet de 1024 bytes
Do
   ' Dimensionne le buffer pour accueillir 1024 bytes
   ReDim buffer(1 To 1024)
   ' Lecture de 1024 bytes du fichier
   If InternetReadFile(hInternetFile, buffer(1), 1024, lRead) Then
       If lRead > 0 Then
           ' Redimensionne le buffer à la taille réellement lue
           ' Utilise Preserve pour ne pas effacer le contenu
           ReDim Preserve buffer(1 To lRead)
           ' Ecrit le buffer dans le fichier
           Put #f, , buffer()
       Else
           ' Plus de données à lire => on sort de la boucle
           Exit Do
       End If
   Else
       ' Erreur de lecture => on sort de la boucle
       ' Gestion d'erreurs à compléter ici
       Exit Do
   End If
Loop
' Fermeture du fichier
Close #f
' Fermeture de tous les handles
InternetCloseHandle hInternetFile
InternetCloseHandle hOpen
End Function


On passe donc par HTTP pour télécharger un fichier sur un FTP.

Par contre on ne peut pas faire l'inverse, c'est-à-dire envoyer un fichier sur le serveur.
On verra dans le chapitre Winsock suivant comment envoyer un fichier par FTP en passant par un proxy.

IX. API URL Monikers (URLDownloadToFile)

Comme WinInet et Winsock, URL Monikers est une librairie dont nous devons déclarer les fonctions, types et constantes utilisées.

La liste des fonctions de cette API est sur MSDN en anglais : URL Monikers Functions.

Nous allons utiliser une seule fonction de cette API : URLDownloadToFile.
Elle est disponible à partir d'Internet Explorer 3.0 et Windows NT4.0, donc sur pratiquement tous les PC.

Très pratique, cette API va nous permettre de télécharger un fichier en une instruction.

Il faut d'abord déclarer la fonction en en-tête de module :

 
Sélectionnez

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


Ensuite l'appel de cette fonction est très simple :

 
Sélectionnez

Function DownloadUrlMon()
' Téléchargement depuis FTP avec mot de passe
URLDownloadToFile 0, "ftp://login:pass@monftp.com/monfichier.gif", ThisWorkbook.Path & "\monfichier.gif", 0, 0
' Téléchargement depuis HTTP
URLDownloadToFile 0, "http://monsite.com/monfichier.gif", ThisWorkbook.Path & "\monfichier.gif", 0, 0
End Function


Je ne l'ai pas vu dans la documentation, mais la fonction utilise apparemment la configuration Windows par défaut du proxy.

Vous avez peut-être vu le dernier paramètre lpfnCB qui devrait permettre de récupérer des événements, notamment de progression du téléchargement.
Sa mise en œuvre est très complexe en VB.
Si vous souhaitez connaître la progression du téléchargement, je vous invite à utiliser WinInet comme vu dans le chapitre précédent.


précédentsommairesuivant

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2011 Thierry GASPERMENT. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts. Droits de diffusion permanents accordés à Developpez LLC.