Zippen und Unzippen aus Access heraus Teil 1

By , 6. März 2014

Erstellt man z.B. aus Access heraus PDF-Dateien – so wie im vorigen Artikel gezeigt – dann möchte man diese unter Umständen auch per Email verschicken, z.B. einen regelmäßigen Umsatzbericht an die Geschäftsleitung. Da würde es Sinn machen, vorher die PDF-Dateien in einem Zip-Archiv zusammenzufügen.
Ein anderes Szenario wäre, Sie erhalten regelmäßig Textdateien in gezippter Form, und möchten diese in eine Access-Tabelle importieren.
Die Möglichkeiten die man dazu hat sind überschaubar. Man könnte z.B. Winzip oder Winrar automatisieren. Was aber wenn es nicht gestattet ist 3th Party Software auf dem Rechner zu installieren, und weder Winzip noch Winrar sind verfügbar.

Für so einen Fall gibt es verschiedene DLL-Bibliotheken von externen Anbietern, die die Zip/Unzip Funktionaliät bieten. Und so eine möchte ich heute vorstellen, nämlich “SawZipNG”. Leider ist dieses geniale Projekt eingestellt worden, und der Entwickler auch nicht mehr erreichbar. Zum Glück hat sich noch eine Kopie der DLL und der Dokumentation auftreiben lassen, die ich im Downloadbereich zur Verfügung stellen werde.

Laden Sie sich die DLL aus dem Downloadbereich herunter, und führen Sie die Anwendung aus. Die DLL-Datei wird automatisch registriert.

Danach steht Ihnen die die Zip/Unzip Funktionalität zur Verfügung. Öffnen Sie Ihre Access Anwendung und den VBA-Editor, und wählen Sie unter Extra/Verweise den Eintrag SAWZIPNG aus. Im Folgenden Beispiel zeige ich Ihnen wie Sie z.B. eine zuvor erstellte PDF-Datei zippen bzw. ein Archiv unzippen können. Sehen Sie sich dazu auch die Dokumentation an (Downloadbereich).
Beispiel 1: Eine einzelne Datei Zippen

Public Sub CreateZIPSingle(ByVal cSourceFileName AS String, _
                           ByVal cZipFileName AS String, _
                           Optional ByVal bFullpath As Boolean = False, _
                           Optional ByVal cComment As String = "", _
                           Optional ByVal cPassword AS String = "")

    Dim objZipArchive As SAWZipNG.Archive
    Set objZipArchive = New SAWZipNG.Archive

    With objZipArchive 
        .Create cZipFileName
        .Password = cPassword
        .AddFile cSourceFileName, bFullpath
        .Comment = cComment 
        .Close
    End With
    
    Set objZipArchive = Nothing
End Sub

Read more »

Bericht mit Filterkriterien nach PDF

By , 5. März 2014

Bis einschließlich der Version Access 2003 gab es keine eingebaute Funktion um einen Bericht nach PDF zu speichern. Zum Glück für diejenigen, die noch mit Access 2003 oder älter arbeiten, hat Stephen Lebans dafür eine DLL erstellt, mit der ab Access 2000 bis 2003 Berichte nach PDF gespeicherte werden können.
Hier gehts zum Link: http://www.lebans.com/reporttopdf.htm

Unter Access 2007 und neuer gibt es jetzt eine Möglichkeit, direkt einen Bericht nach PDF zu speichern: Docmd.OutputTo… mit dem AusgabeFilter acFormatPDF.
Will man aber dem Bericht Filterkriterien mitgeben, um z.B. nach einem bestimmten Kunden zu filtern, dann muss man schon ein bisschen mehr coden. Ich hab dazu mal ein Beispiel gemacht:

Private Sub ReportToPDF(ByVal cReportName As String, _
                        ByVal cReportFilter As String, _
                        ByVal cPDFName As String, _
                        Optional ByVal cHeadline As String = "Umsatzbericht")
    
    DoCmd.OpenReport cReportName, acPreview, , cReportFilter, acHidden
    Reports(cReportName).Titelzeile.Caption = cHeadline
    DoCmd.OutputTo acOutputReport, cReportName, acFormatPDF, cPDFName, False
    DoCmd.Close acReport, cReportName, acSaveNo
End Sub

Read more »

Daten Auswerten mit Kreuztabelle & Co

By , 4. März 2014

Will man z.B. Umsätze verschiedener Standorte auswerten um die Standorte miteinander zu vergleichen, dann ist das Übliche Mittel eine Kreuztabellenabfrage zuerstellen.
Unter Access 2010 klickt man in der Registerkarte “erstellen” auf “Abfrageassistent” und wählt dann “Kreuztabellenabfragen-Assistent” aus.

Der restliche Dialog sollte selbsterklärend sein. Man wählt die Tabelle oder Abfrage aus, welche die Grundlage für die Kreuztabellen-Abfrage ist, und klickt auf weiter. Danach wird nach den Zeilenüberschriften gefragt, wir wählen hier das Feld “Monat” aus. Nach klick auf Weiter wählt man die Spaltenüberschrift, wir nehmen hier das Feld “Standort”. Zum Schluss wird nach den Kreuzungspunkten gefragt, also nach den darzustellenden Werten. Bei mir heißt das Feld treffend “Umsatz”. Also das Feld Umsatz auswählen und rechts daneben die Funktion “Summe” anklicken, da wir ja die Summen pro Monat und Standort möchten. Bei Access 2010 ergibt sich jetzt folgendes Bild:

Kreuztabellenabfrage-Assistent

Kreuztabellenabfrage-Assistent


Read more »

Arbeiten mit ini-Dateien

By , 3. März 2014

ini-Dateien eignen sich hervorragend um z.B. Einstellungen und Optionen der Access-Anwendung zu speichern. Sei es Farben, Schriftarten, Schriftgröße oder auch Pfade. ini-Dateien sind nichts anderes als einfache Text-Dateien, die z.B. mit Notepad erstellt werden können. Das Besondere ist der Aufbau des Inhaltes. Hier mal ein Beispiel:

[Colors]
backcolor=255
forecolor = 0
[Fonts]
fontname=Arial
fontsize = 14

Erstellen Sie mit Notepad eine leere Textdatei und benennen Sie diese z.B. meinTest.ini. Im Explorer sehen sie sofort, dass der Text-Datei ein anderes Datei-Icon als das für Textdateien zugeordnet wurde. An diesem Icon können Sie ini-Dateien erkennen. Kopieren Sie nun obigen Code in die ini-Datei und speichern Sie diese.

Um nun lesend oder schreibend darauf zugreifen zu können, benötigen wir 2 API-Funktionen, die wir in ein Standardmodul hinein kopieren:

Public Declare Function GetPrivateProfileString Lib _
                                                "kernel32" Alias "GetPrivateProfileStringA" _
                                                (ByVal lpApplicationname As String, _
                                                 ByVal lpKeyName As Any, _
                                                 ByVal lpDefault As String, _
                                                 ByVal lpReturnedString As String, _
                                                 ByVal nSize As Long, _
                                                 ByVal lpFileName As String) As Long

Public Declare Function WritePrivateProfileString Lib "kernel32" _
                                                  Alias "WritePrivateProfileStringA" _
                                                  (ByVal lpApplicationname As String, _
                                                   ByVal lpKeyName As Any, _
                                                   ByVal lpString As Any, _
                                                   ByVal lpFileName As String) As Long

Read more »

Factory Module verwenden

By , 2. März 2014

Man stelle sich vor man hat eine Klasse namens “Fahrzeug”, abgeleitet von dem Interface im Artikel zuvor, und Sie möchten neue Objekt erstellen. Üblicherweise geschieht das in folgender Weise:

    Dim car1 As Fahrzeug
    Set car1 = New Fahrzeug
    With car1
        .iFahrzeug_Farbe = 255
        .iFahrzeug_Geschwindigkeit = 100
        .iFahrzeug_Richtung = "Gerade aus"
        .iFahrzeug_Fahren
    End With

Mit der Anweisung Set car1 = New Fahrzeug wird das Objekt “car1″ zwar erstellt, das Objekt ist aber komplett ‘leer’. Erst in den nachfolgenden Zeilen wird das Objekt mit Daten belegt. D.H. zum Erstellungszeitpunkt des Objektes stehen alle Eigenschaften auf 0 bzw. auf vbNullString.

Wäre es nicht Cool wenn man, um beim obigen Beispiel zu bleiben, das Objekt so erstellen könnte:

    Dim car1 As Fahrzeug
    Set car1 = New Fahrzeug(255,100,"Gerade aus")

Diese Möglichkeit gibt es in VBA leider nicht, aber wir können uns behelfen mit einer sogenannten Factory.

Zuerst benötigen wir in der Klasse “Fahrzeug” einen Ersatz für den Standard-Konstruktor. Dazu erstellen wir eine öffentliche Prozedur, welche alle beim Start benötigten Werte als Parameter verlangt. Diese Parameter-Werte werden in dieser Prozedur einfach den Privaten Variablen zugewiesen. Und so sieht diese Prozedur für obiges Beispiel aus:
Read more »

Service Pack für Office 2013 verfügbar

By , 2. März 2014

Vor wenigen Tagen hat Microsoft das Service Pack 1 für Office 2013 und SharePoint 2013 veröffentlicht. Das Service Pack soll vorallem die Stabilität und Sicherheit von Office 2013 und SharePoint 2013 erhöhen.

Die wichtigsten Änderungen:
Kompatibilität zu Windows 8.1 und Internetexplorer 11 wurde verbessert
Neue Apps für Office und APIs für Entwickler
Neues 3D Virtualisierungs Tool für Excel: Power Map
etc.

Wer viel Neues vom ServicePack erwartet, wird wahrscheinlich enttäuscht werden, das Hauptaugenmerk liegt hauptsächlich auf Stabilität und Sicherheit.
Beide Updates sind verfügbar im Microsoft Download Center:
Office 2013 SP1 32 Bit Version: http://www.microsoft.com/en-us/download/details.aspx?id=42017
Office 2013 SP1 64 Bit Version: http://www.microsoft.com/en-us/download/details.aspx?id=42006

Bis dahin
© 2014 Andreas Vogt

Benutzerdefinierte Collections

By , 1. März 2014

Collections, auf Deutsch Auflistungen, begegnen uns beim Entwickeln in VBA eigentlich ständig, sei es die Auflistung aller Formulare (Forms), oder aller Steuerelemente in einem Formular (Controls). Neben diesen bereits vorhandenen Collections, ist es möglich auch eigene Collections zu erstellen. Dies geschieht mit der simplen Anweisung:
Dim CollectionName As New Collection.

Im Unterschied zu einem Array kann eine benutzerdefinierte Collection Werte und Objekte jeglichen Typs aufnehmen, eine Collection ist also nicht Typ gebunden. Ein weiterer, nicht zu unterschätzender Vorteil ist dieser, dass im Gegensatz zu einem Array – wo die Items nur durch ihre Ordnungszahl definiert sind – bei einer Collection als optionalen Parameter einen eindeutigen Bezeichner angegeben werden kann, über den auf das entsprechende Item zugegriffen werden kann.

Eine Benutzerdefinierte Collection verfügt über die Methoden “ADD”, “REMOVE”, “COUNT” und “ITEM”, d.h. es gibt keine Edit-Methode. Will man ein Item ändern muss man es aus der Collection entfernen und geändert neu einfügen. Eine weitere Besonderheit benutzerdefinierter Collections ist, dass sie immer 1-Basiert sind, also das erste Element in einer Collection hat die Ordnungszahl 1, und nicht 0 wie bei einem Array.

Ein Beispiel:

Sub CollectionTest()
    Dim cBuch As New Collection
    Dim Ausgabe As String
    
    With cBuch
        .Add "Ken Getz", "Autor"
        .Add "VBA Developers Handbook", "Titel"
        .Add 922, "Seiten"
    End With
    
    Ausgabe = cBuch("Autor") & vbCrLf
    Ausgabe = Ausgabe & cBuch(2) & vbCrLf
    Ausgabe = Ausgabe & cBuch("Seiten") & " Seiten"
    MsgBox Ausgabe
End Sub

Wie man an diesem kleinen Beispiel sieht ist es egal ob ich cBuch(2) oder cBuch(“Titel”) schreibe. Der große Vorteil des Bezeichners ist, dass ich mir keine Gedanken machen muss an welcher Stelle ein Item steht, mit dem Bezeichner wird immer der richtige Wert verwendet.

Bis dahin
© 2014 Andreas Vogt

Arbeiten mit Interface-Klassen

By , 28. Februar 2014

Dass man mit Access auch objektorientiert entwickeln kann – wenn auch nicht völlig – dürfte hinlänglich bekannt sein. Klassenmodul erstellen, Methoden und Eigenschaften in als Prozeduren und Properties definieren, alles längst bekannt. Weniger bekannt aber ist die Verwendung von Interfaces bzw. Interface-Klassen.

Man stelle sich vor, man hat eine Klasse Auto, eine Klasse Motorrad und eine Klasse Fahrrad. 3 verschiedene Klassen, und doch werden die Methoden und Eigenschaften dieser Klassen in vielen Punkten identisch sein. Die Objekte aller 3 Klassen haben sicherlich die gemeinsamen Methoden “Fahren”, “Bremsen” und “Lenken”. Außerdem die gemeinsamen Eigenschaften “Geschwindigkeit”, “Richtung” und “Farbe”, um ein paar Beispiele zu nennen.

Diese Zusammenhänge lassen sich durch ein Interface abbilden, und das geschieht einfacher als man denkt. Ein Interface ist zuerst einmal nichts anderes als ein Klassenmodul, das man speziell benennt. Eingebürgert hat sich, dass man vor den Interface-Namen ein “i” setzt. Wir erstellen also ein Klassenmodul, und benennen es “iFahrzeug”. Um jetzt die Struktur für Fahrzeuge in diesem Interface abzubilden erstellen wir darin alle Properties und Prozeduren wie oben benannt, aber ohne weiteren Code. Unser Interface sieht jetzt wie folgt aus:

Option Explicit

Property Get Geschwindigkeit() As Long
End Property
Property Let Geschwindigkeit(ByVal lSpeed As Long)
End Property

Property Get Richtung() As String
End Property
Property Let Richtung(ByVal cRichtung As String)
End Property

Property Get Farbe() As Long
End Property
Property Let Farbe(ByVal lColor As Long)
End Property

Sub Fahren()
End Sub

Sub Bremsen()
End Sub

Sub Lenken()
End Sub

Read more »

Array definieren mal anderst

By , 27. Februar 2014

Arrays werden entweder per Array() Anweisung definiert, oder auch durch den Split() Befehl.
Auf eine andere bzw. erweiterte Möglichkeit bin ich kürzlich gestoßen beim Entwickeln eines Benutzersteuerelementes mit VB6.
Dort ging es u.a. darum, Steuerelemente beim Klick auf einen Button zu plazieren und sichtbar zu machen.

Die Größe und Position der Steuerelemente habe ich dabei wie folgt definiert:

Private Sub Form_Open(Cancel As Integer)
    Dim sizeArr(8) As Variant
    Dim i As Long
    sizeArr(0) = Array("cmdClose", 2350, 23, 306, 975)
    sizeArr(1) = Array("Linie1", 47, 2412, 2066, 2066)
    sizeArr(2) = Array("Linie2", 47, 2412, 697, 697)
    sizeArr(3) = Array("lblMonat", 23, 47, 454, 2381)
    sizeArr(4) = Array("zurueck", 142, 120, 227, 227)
    sizeArr(5) = Array("vor", 142, 2160, 227, 227)
    sizeArr(6) = Array("MonatJahr", 120, 480, 255, 1575)
    sizeArr(7) = Array("Heute", 2066, 47, 255, 2381)
    sizeArr(8) = Array("Rechteck1", 23, 47, 2280, 2381)

Das bedeutet also, jedem einzelnen Array-Element wurde ein weiteres Array zugewiesen.
Der Zugriff auf einen bestimmten Wert, z.B. auf “lblMonat” lautet dann: sizeArr(3)(0)

Und um wieder zum Beispiel aus der Praxis zurückzukommen, hier der restliche Code, der die Steuerelemente dimensioniert, positioniert und sichtbar schaltet:

    For i = LBound(sizeArr) To UBound(sizeArr)
        With Controls(sizeArr(i)(0))
            .Top = sizeArr(i)(1)
            .Left = sizeArr(i)(2)
            .Height = sizeArr(i)(3)
            .Width = sizeArr(i)(4)
            .Visible = True
        End With
    Next i
End Sub

Bis dahin
© 2014 Andreas Vogt

Clouden Sie noch oder wie wichtig sind Ihnen Ihre Daten?

By , 15. Februar 2014

Die Zeit der Goldgräberstimmung in der Cloud Server Branche außerhalb der EU ist längst vorbei, zu tief sind doch die emotionalen Gräben die uns die NSA beschert hat. Für mich war es immer schon klar dass in die Cloud keine betriebswichtigen Daten gehören. Meine Denkweise war aber eher die dass in einem Rechtsstreit ServerHardware und entsprechende auch die Daten beschlagnamt werden könnten – dass aber die NSA die Cloud direkt anzapfte, Hersteller von Internetdiensten dazu verpflichten Hintertürchen einzubauen etc. etc. – diese Dimension haben sich wohl die wenigsten ausgemalt, ich auch nicht.

Die ganze Spionagetätigkeit läuft unter dem Aspekt der Terrorabwehr, und verschleiert vollkommen, dass es auch um handfeste Wirtschaftsspionage geht.

Hintertuerchen Gut, dann eben wieder lokale Lösungen mit eigenem und teuren Rechenzentrum. Das wäre auch bislang eine sichere Bank gewesen, bis zu dem entsprechenden Spiegel-Beitrag vor etwa 6 Wochen.
Die NSA hat ganze Lieferungen von PC Hardware abgefangen, aufgeschraubt und Spionage-Tools verbaut als Hintertürchen, um so an Daten und Kontrolle über den PC zu kommen. Das ganze klingt nach einem übertriebenen Science-Fiction Roman – doch die Wirklichkeit hat diese Lektüre bereits überholt.

Viele “flüchten” jetzt zu Cloud-Anbietern innerhalb Europa vorallem auch innerhalb Deutschland. Was bleibt ist die Frage ob auch hier es so weit kommt bzw. ob es nicht längst auch so weit ist.
Das digitale Wettrüsten hat längst begonnen und ist im vollen Gange.

Also schauen Sie ruhig mal nach Ihrem PC unter dem Schreibtisch, nicht dass dort ein Hintertürchen aufsteht.

Meint der Autor.

Quelle: http://www.spiegel.de/netzwelt/netzpolitik/…
© 2014 Andreas Vogt

OfficeFolders theme by Themocracy