Dateien aus dem Web herunterladen per VBA

Es gibt eine Menge Gründe, warum man per VBA komplette Dateien aus dem Internet herunterladen sollte. Beispielsweise könnte man von dort Listen im Excel- oder .csv-Format herunterladen, um anschließend die enthaltenen Daten in die aktuelle Datenbank einzulesen. Oder man hat eine Anwendung, die beim Kunden läuft, und diese soll in regelmäßigen Abständen prüfen, ob es ein Update für diese Anwendung gibt und die neue Datei bei Bedarf aus dem Internet herunterladen. In diesem Beitrag zeigen wir die Technik, mit der solche Anforderungen umgesetzt werden. Dabei nutzen wir verschiedene Techniken, zum Beispiel per API oder mit dem XMLHTTP-Objekt der Bibliothek Microsoft XML, v6.0.

Download per API

Ein Download via API ist die am schnellsten programmierte und einfachste Methode, um eine Datei aus dem Internet herunterzuladen, die auch frei verfügbar ist (also auch über die Eingabe der URL in einen Webbrowser heruntergeladen werden könnte). Die Lösung zu diesem Ansatz sieht wie in Listing 1 aus. Hier deklarieren wir zunächst eine API-Funktion namens URLDownloadToFile in der 32-Bit-Version und in der 64-Bit-Version sowie eine Konstante.

#If VBA7 Then
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
#Else
Private Declare PtrSafe Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" _
     (ByVal pCaller As LongPtr, ByVal szURL As String, ByVal szFileName As String, _
     ByVal dwReserved As LongPtr, ByVal lpfnCB As LongPtr) As LongPtr
#End If
Const ERROR_SUCCESS = 0
Sub DownloadAPI()
     Dim strUrl As String
     Dim strDatei As String
     strUrl = "http://www.access-im-unternehmen.de/pic001.png"
     strDatei = CurrentProject.Path & "\pic001.png"
     Debug.Print URLDownloadToFile(0&, strUrl, strDatei, BINDF_GETNEWESTVERSION, 0&) = ERROR_SUCCESS
End Sub

Listing 1: Einfacher Code zum Herunterladen einer Datei

Danach rufen wir die Prozedur DownloadAPI auf, in der wir die URL der herunterzuladenden Datei sowie den Zielpfad angeben. Damit ausgestattet rufen wir die API-Funktion auf und übergeben dieser mit dem zweiten und dritten Parameter die URL und den Zielpfad. Die übrigen Parameter bleiben leer. Wenn wir die Prozedur nun aufrufen und die angegebene Datei vorhanden ist, wird sie unter dem angegebenen Pfad auf dem lokalen Rechner gespeichert.

Funktion auf Basis dieser Prozedur

In vielen Fällen wollen wir die Parameter einer solchen Prozedur wie die URL der herunterzuladenden Datei und den Zielpfad dynamisch angeben und diese nicht fest im Code vorgeben.

Dann erstellen wir eine Funktion auf Basis der Prozedur, die wie folgt aussieht:

Public Function DownloadAPI(strURL As String, _
         strDatei As String) As Boolean
     If URLDownloadToFile(0&, strURL, strDatei, 0&, 0&) _
             = ERROR_SUCCESS Then
         DownloadAPI = True
     End If
End Function 

Der Aufruf erfolgt beispielsweise über die folgende Prozedur:

Public Sub Test_DownloadAPI()
     Dim strURL As String
     Dim strDatei As String
     strURL = "http://www.access-im-unternehmen.de/pic001.png"
     strDatei = CurrentProject.Path & "\pic001.png"
     Debug.Print DownloadAPI(strURL, strDatei)
End Sub

Mehr Komfort per Formular

Wenn wir dem Benutzer die Steuerung des gesamten Vorgangs überlassen wollen, können wir ihm ein Formular wie in Bild 1 hinzufügen. Dieses enthält zwei Textfelder – eines zum Eingeben der URL der Quelldatei und eines für die Zieldatei – und eine Schaltfläche namens cmdDownload.

Entwurf des Formulars zum Herunterladen von Dokumenten aus dem Internet

Bild 1: Entwurf des Formulars zum Herunterladen von Dokumenten aus dem Internet

Außerdem hinterlegen wir noch eine Schaltfläche, mit welcher der Benutzer den Namen der Datei angeben kann, unter welcher die herunter geladende Datei gespeichert werden soll. Diese Schaltfläche heißt cmdDateiauswahl und ruft die folgende Prozedur auf:

Private Sub cmdDateiauswahl_Click()
     Dim objFileDialog As FileDialog
     Set objFileDialog = FileDialog(msoFileDialogSaveAs)
     objFileDialog.Title = "Zieldatei festlegen"
     objFileDialog.InitialFileName = _
         CurrentProject.Path & "\"
     If objFileDialog.Show = True Then
         Me!txtZieldatei = objFileDialog.SelectedItems(1)
     End If
End Sub

Für die Verwendung der FileDialog-Klasse benötigen wir einen Verweis auf die Bibliothek Microsoft Office 16.0 Object Library (wie wir diesen hinzufügen, zeigen wir weiter unten).

Wenn der Benutzer auch noch die URL wie in Bild 2 ausfüllt, können wir die Schaltfläche cmdDownload nutzen, für die wir die folgende Prozedur hinterlegen:

Formular zur Eingabe von Quelle und Ziel beim Download

Bild 2: Formular zur Eingabe von Quelle und Ziel beim Download

Private Sub cmdDownload_Click()
     If DownloadAPI(Me!txtURL, Me!txtZieldatei) Then
         MsgBox "Download erfolgreich!"
     End If
End Sub

Für etwas mehr Komfort haben wir die Eigenschaft Horizontaler Anker der beiden Textfelder auf Beide eingestellt. So können wir die Felder verbreitern, indem wir die Breite des Formulars vergrößern. Die gleiche Eigenschaft stellen wir für die beiden Bezeichnungsfelder dann wieder auf Links ein, da diese automatisch auf Rechts eingestellt wurden.

Außerdem legen wir diese Eigenschaft für die Schaltfläche cmdDateiauswahl auf Rechts ein, damit sie beim Vergrößern nach rechts verschoben wird (siehe Bild 3).

Neue Schaltfläche für eine Download-Alternative

[

Bild 3: Neue Schaltfläche für eine Download-Alternative

Download per ServerXMLHTTP-Objekt

Die zweite Methode, die wir in diesem Beitrag vorstellen, erfolgt mit einem Objekt aus der Bibliothek Microsoft XML, v6.0. Um dieses zu verwenden und dabei die Vorteile von IntelliSense zu benutzen, benötigen wir einen Verweis auf diese Bibliothek. Dazu wählen wir im VBA-Editor den Menübefehl Extras|Verweise aus und fügen im Dialog Verweise den entsprechenden Eintrag durch Anklicken des Kontrollkästchens hinzu (siehe Bild 4).

Verweise für die ServerXMLHTTP-Variante

Bild 4: Verweise für die ServerXMLHTTP-Variante

Das Gleiche erledigen wir, wenn noch nicht geschehen, für die Bibliothek Microsoft Office 16.0 Object Library. Schließlich benötigen wir noch einen dritten Verweis, nämlich den auf die Bibliothek Microsoft ActiveX Data Objects 6.1 Library. Diese enthält die Elemente, die wir für das Speichern der heruntergeladenen Datei benötigen, denn im Gegensatz zur API-Funktion URLDownloadToFile hat das Objekt ServerXMLHTTP keine Methode zum direkten Speichern des heruntergeladenen Objekts im Dateisystem.

Für die neue Variante des Downloads erstellen wir eine weitere Funktion namens DownloadXML. Diese sieht wie in Listing 2 aus und enthält die gleichen beiden Parameter wie die Funktion DownloadAPI.

Public Function DownloadXML(strURL As String, strDatei As String)
     Dim objServerXMLHTTP As MSXML2.ServerXMLHTTP60
     Dim objStream As ADODB.Stream
     Set objXMLServerHTTP = New MSXML2.ServerXMLHTTP60
     objXMLServerHTTP.Open "GET", strURL, False
     objXMLServerHTTP.send
     Set objStream = CreateObject("ADODB.Stream")
     objStream.Open
     objStream.Type = 1
     objStream.Write objServerXMLHTTP.responseBody
     objStream.SaveToFile strDatei, 2
     objStream.Close
     If Not Len(Dir(strDatei)) = 0 Then
         DownloadXML = True
     End If
End Function

Listing 2: VBA-Code zum Herunterladen einer Datei per ServerXMLHTTP-Objekt

Um nun die Klasse ServerXMLHTTP zu nutzen, deklarieren wir zunächst eine Objektvariable des Typs MSXML2.ServerXMLHTTP60. Außerdem deklarieren wir ein Objekt des Typs ADODB.Stream.

Danach erstellt die Funktion ein Objekt des Typs ServerXMLHTTP und referenziert dieses mit der Variablen objServerXMLHTTP. Dieses wird gleich verwendet werden, um eine Verbindung zu der mit strURL angegebenen URL herzustellen und die enthaltenen Daten abzurufen.

Die Prozedur ruft als Erstes die Methode Open des Objekts auf und übergibt neben dem Wert GET für den ersten Parameter die URL mit dem zweiten Parameter. Der dritte Parameter erhält den Wert False, damit die Operation nicht asynchron verläuft, das heißt, dass dieser Aufruf zuerst vollständig ausgeführt wird, bevor die nächste Anweisung der Prozedur an der Reihe ist. Die send-Methode sorgt schließlich für die Ausführung des Abrufs der Daten.

Anschließend erstellt die Prozedur ein Objekt des Typs ADODB.Stream und öffnet dieses. Die Variable objStream ist ein Objekt der Klasse ADODB.Stream, die zur Manipulation von Binär- und Textdatenströmen in VBA verwendet wird. Die Type-Eigenschaft legt den Typ des ADODB-Streams fest. In diesem Fall wird der Wert 1 zugewiesen, was bedeutet, dass der Stream als Binärstrom erstellt wird und Binärdaten wie zum Beispiel die Daten in einem Bild oder in einer Datei enthält.

Wenn Type auf 2 gesetzt ist, wird ein Textstream erstellt, welcher Textdaten wie zum Beispiel eine Zeichenfolge enthält. Da in diesem Fall eine normale Datei heruntergeladen wird, wird ein binärer Datenstrom benötigt, um die binären Daten der Datei zu speichern.

Die folgende Zeile mit der Methode Write erwartet die Antwort des Aufrufs des ServerXMLHTTP-Objekts als Parameter und schreibt diesen in den Stream. Das Stream-Objekt dient also praktisch als Zwischenspeicher, bevor die heruntergeladene Datei mit der SaveToFile-Methode in die mit strDatei angegebene Datei geschrieben wird.

Danach schließt die Funktion das Stream-Objekt mit der Close-Methode, prüft, ob die angegebene Datei vorhanden ist und gibt in diesem Fall den Wert True als Funktionswert zurück.

Diese Funktion rufen wir über eine weitere Schaltfläche auf, die wir ebenfalls im Formular frmDownload unterbringen (siehe Bild 5).

Weiteres Downloadverfahren per Formular

Bild 5: Weiteres Downloadverfahren per Formular

Die durch diese Schaltfläche aufgerufene Prozedur sieht schließlich wie folgt aus:

Private Sub cmdDownloadXMLHTTP_Click()
     If DownloadXML(Me!txtURL, Me!txtZieldatei) Then
         MsgBox "Download erfolgreich!"
     End If
End Sub

Download von geschützten Dateien

Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...

den kompletten Artikel im PDF-Format mit Beispieldatenbank

diesen und alle anderen Artikel mit dem Jahresabo

Schreibe einen Kommentar