Category: Formulardesign

Selektive Datensätze – oder wie zeige ich Datensätze seitenweise an

By , 10. Mai 2011

Eine bekannte Problematik ist, wie man viele Datensätze so anzeigt, dass immer nur eine bestimmte Anzahl sichtbar wird, gleichzeitig aber Seitenartig geblättert werden kann.
Aus der PHP/MySQL Welt ist die Möglichkeit bekannt in einer Abfrage die Datensätze mittels dem Limit Operator die Anzahl und die Startposition der Datensätze einzustellen. Diese Möglichkeit gibt es in Access leider nicht – man kann sich aber behelfen.

Möchte man z.B. die sortierten Datensätze 31 bis 40 darstellen, lässt sich das dadurch bewerkstelligen, indem man die Top 40 Datensätze nimmt, und von diesen in umgekehrter Reihenfolge die Top 10 Datensätze nimmt. Jetzt hat man die Datensätze 40……bis 31 in umgekehrter Reihenfolge. Auf diese Menge wendet man eine äußere Abfrage an die absteigend aufsteigend sortiert und schon hat man die richtige Ergebnismenge in der korrekten Reihenfolge.

In meinem Beispiel verwende ich ein Unterformular in Datenblattansicht, 4 Buttons zur Navigation und 1 Bezeichnungsfeld als Datensatzanzeiger. Es werden immer 10 Einträge pro Seite angezeigt.

Zuerst werden in einem Modul Globale Variablen deklariert:

Global sumDS As Long
Global start As Long

Dann benötigt man eine Prozedur die die Datenherkunft des Unterformulars einstellt:

Private Sub setQuery(start As Long, Optional perpage As Long = 10)
    Me!ufo1.Form.RecordSource = "SELECT tblKfzKennzeichen.ID, tblKfzKennzeichen.Kennzeichen, tblKfzKennzeichen.Bezirk " & _
                                "FROM tblKfzKennzeichen " & _
                                "WHERE (((tblKfzKennzeichen.ID) In (Select Top " & perpage & " ID From (Select top " & start & " ID From tblKfzKennzeichen) Order By ID Desc))) " & _
                                "ORDER BY tblKfzKennzeichen.ID;"

    Me.DSAnzeiger.Caption = "Eintrag " & start - (perpage - 1) & " bis " & start
    Me!ufo1.Form.Requery
End Sub

Read more »

Formatierte Hilfeseiten erstellen

By , 16. April 2011

Es mag oft eine lästige Arbeit sein am Ende eines Projektes oder mitten drin ein Hilfesystem zu implementieren.
Für einfache Anwendungen genügt auch meist 1 Hilfeseite pro Formular. Ich bin dabei auf eine verblüffend einfache Methode gestoßen:
Man erstelle ein neues Formular, und plaziere darauf genau 1 Steuerelement, nämlich das ActiveX Webbrowser Control. Vor dem Speichern des Formulares das Steuerelement in die Ausgangsgröße positionieren, weil spätere Änderungen nicht möglich sind. Am besten man wähle ein möglichst großes Format, das aber noch auf allen Bildschirmen im ganzen sichtbar sind.
Der Name des Controls sei jetzt „Webbrowser1″.

Die weitere Vorgehensweise ist die folgende:
1. Man erstellt man die gewünschte Hilfeseite mit einem HTML-Editor seiner Wahl.
2. Kopiert den Quelltext und überträgt diesen in das Formularmodul in eine neue Prozedur.
3. Der eingefügte HTML-Quelltext wird bearbeitet, alle Anführungszeichen müssen ersetzt werden (Copy/Paste) durch die folgende Zeichenfolge: “ & chr(34) & “
4. Jede einzelne Zeile wird wie folgt eingeschlossen: Print #1, „Hier kommt die Quelltextzeile“

Ich verwende für die einzelne Hilfeseiten Prozeduren die fortlaufend nummeriert sind, also z.B. Public Sub help1():

Public Sub help1()
Open CurrentProject.Path & "/index.html" For Output As #1
Print #1, "<!DOCTYPE html PUBLIC " & Chr(34) & "-//W3C//DTD XHTML 1.0 Transitional//EN" & Chr(34) & " " & Chr(34) & "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" & Chr(34) & ">"
Print #1, "<html xmlns=" & Chr(34) & "http://www.w3.org/1999/xhtml" & Chr(34) & ">"
Print #1, "<head>"
Print #1, "<style type=" & Chr(34) & "text/css" & Chr(34) & ">"
Print #1, "    body{background:#fff;color:#000;font-family:Verdana,Arial,Helvetica,sans-serif;font-size:11px;font-style:normal;font-weight:400;margin:5;width:95%}"
Print #1, "    dl{margin-top:0;padding-left:1px}"
Print #1, "    dd p{margin-left:0;margin-top:0;padding-right:20px}"
Print #1, "</style>"
Print #1, "Verbindung mit Server herstellen (Datenbankmodul)"
Print #1, "<title>Verbindung mit Server herstellen (Datenbankmodul)"
Print #1, "</head>"
Print #1, "<body>"
Print #1, "<div style=" & Chr(34) & "margin:5px;width:100%" & Chr(34) & ">"
Print #1, "<div style=" & Chr(34) & "margin-bottom: 20px" & Chr(34) & "><b><font size=" & Chr(34) & "+1" & Chr(34) & ">Verbindung mit Server herstellen (Datenbankmodul)</font></b></div>"Print #1, "<div><p>Verwenden Sie dieses Dialogfeld, um Optionen für Verbindungen zu Computern mit MicrosoftSQL Server Database Engine (Datenbankmodul) anzuzeigen oder anzugeben. In den meisten Fällen können Sie eine Verbindung herstellen, indem Sie im Feld <b>Servername</b> den Computernamen des Datenbankservers eingeben, und dann auf <b>Verbinden</b> klicken. Verwenden Sie beim Herstellen der Verbindung mit SQL Server Express den Computernamen gefolgt von <b>\sqlexpress</b>.</p><p>Viele Faktoren können Auswirkungen auf die Möglichkeit zum Herstellen der Verbindung mit SQL Server haben. Ein kurzes Lernprogramm zum Herstellen der Verbindung mit SQL Server finden Sie unter <span><a id=" & Chr(34) & "ctl00_MainContent_ctl01" & Chr(34) & " href=" & Chr(34) & "http://....." & Chr(34) & " onclick=" & Chr(34) & "javascript:Track('ctl00_MainContent_ctl00|ctl00_MainContent_ctl01',this);" & Chr(34) & ">Lernprogramm: Erste Schritte mit dem Datenbankmodul</a></span>.</p></div>"
Print #1, "<span>"
Print #1, "<div><b><font size=" & Chr(34) & "2" & Chr(34) & ">Optionen:</font></b></div>"
Print #1, "<div style=" & Chr(34) & "display:block;" & Chr(34) & " >"
...... usw.
Print #1, "</body>"
Print #1, "</html>"
Close #1
Me!WebBrowser1.Navigate CurrentProject.Path & "/index.html"
End Sub

Read more »

Schnellerfassung 1:n verbundener Daten

By , 15. März 2010

Stellt euch vor, ihr habt eine ausgedrukte Liste von Daten vor euch liegen, und sollt diese erfassen. Das ist schon Arbeit genug, aber richtig heftig wird es erst, wenn die Daten in verschiedene Tabellen gehören. Das bedeutet, zuerst die Daten in die Stammdatentabelle eintragen, erstellter AutoWert-ID aufschreiben, und danach in die Detaildatentabelle gehen und die restlichen Daten mit der aufgeschriebenen Nummer eintragen. Eigentlich eine Arbeit für Praktikanten?! Aber wie hoch ist die Gefahr von Falscheingabe? Stimmt der übertragene ID nicht überein, sind die Detaildaten nicht mehr auffindbar. Die Lösung ist, wir lassen das von einem Programm erledigen.

Also nur noch 1 Formular mit allen Daten, und per VBA-Code werden die Inhalte in die richtigen Tabellen geschrieben. Das will ich euch mal an einem einfachen Beispiel zeigen. Gegeben ist eine Bücherliste mit Buchtitel, Vor- und Nachname des Autors.

Wer haben also 3 Textfelder im Formular die Vorname, Nachname und Buchtitel heißen. Außerdem brauchen wir eine Logik die es verhindert dass ein Autor mit selben Namen doppelt angelegt wird, und eine Logik die verhindert dass ein Buch mehrmals angelegt wird. Kommen wir mal zum Code. Dieser ist zweckmäßiger Weise in eine Prozedur eingebunden, welche mit einer Befehlsschaltfläche im Formular aufgerufen wird. Wir haben 2 Tabellen, TabelelBuch und TabelleAutor. Die Feldbezeichner sind aus dem Code zu entnehmen, die Schlüsselfelder beider Tabellen heißen jeweils „id“.

Eine kleine Besonderheit ist die Art wir der zu übertragene ID ausgelesen wird, dies geschieht mit folgender Abfrage: SELECT @@IDENTITY AS ID;
@@IDENTITY ist ene Systemfunktion, die den zuletzt eingefügten Identitätswert zurückgibt. Wenn der Einfügevorgang keinen Datensatz eingefügt hat, gibt die Funktion den Wert Null zurück.

Sub Speichern()
    Dim autorid As Long
    Dim db As Database
    Dim rs As Recordset

    Set db = CurrentDb
    Set rs = db.OpenRecordset("Select id From TabelleAutor Where Vorname = '" & Me!Vorname & "' And Nachname = '" & Me!Nachname & "'", dbOpenDynaset)
    If rs.EOF Then
        db.Execute "Insert into TabelleAutor (Vorname, Nachname) Values ('" & Me!Vorname & "', '" & Me!Nachname & "')"
        Set rs = db.OpenRecordset("SELECT @@IDENTITY AS ID;", dbOpenDynaset)
        autorid = rs!ID
    Else
        Set rs = db.OpenRecordset("Select id From TabelleAutor Where Vorname = '" & Me!Vorname & "' And Nachname = '" & Me!Nachname & "'", dbOpenDynaset)
        autorid = rs!ID
    End If

    Set rs = db.OpenRecordset("Select id From TabelleBuch Where Titel= '" & Me!Titel & "'", dbOpenDynaset)
    If rs.EOF Then
        db.Execute "Insert into TabelleBuch (Titel, Autorid) Values ('" & Me!Titel & "', " & autorid & ")"
        MsgBox "Daten gespeichert"
    Else
        MsgBox "Buch schon vorhanden!"
    End If

    rs.Close
    Set rs = Nothing
    Set db = Nothing
End Sub

Zuerst wird geprüft ob der Autor schon existiert. Falls nicht werden die Autor-Daten in die Tabelle eingefügt und den automatisch erzeugten ID-Wert ausgelesen. Falls bereits vorhanden wird lediglich der ID-Wert des Autors geholt. Der ID-Wert wird in beiden Fällen in der Variable autorid zwischengespeichert.

Danach wird geprüft ob das Buch schon vorhanden ist, falls nicht, wird das Buch gespeichert und eine Erfolgsmeldung ausgegeben, bzw. im anderen Falle die Meldung ausgegeben, dass das Buch schon vorhanden ist. Am Schluss noch wie üblich Aufräumen, Recordset schließen und Objekte zurücksetzen.

Wie immer fehlt eine zusätzliche Fehlerbehandlung, die ihr im Betrieb unbedingt einbauen solltet. Das Beispiel kann man auch auf mehrere 1:n verbundener Tabellen anwenden, man muss dann sorgfältig die Daten trennen was wohin gehört und dann mehrmals mit @@IDENTITY den gespeicherten ID-Wert holen.

AV 2010

Verzeichnis in ein Listenfeld auslesen

By , 14. Februar 2010

Kürzlich hatte ich ein Projekt bei dem XML-Dateien importiert wurden. Zur Auswahl der Dateien mussten diese zuvor aus einem Verzeichnis in ein Listenfeld ausgelesen werden.
Um das zu bewerkstelligen bedienen wir uns wieder einmal der „Microsoft Scripting Runtime“ Bibliothek. Diese wird seit Office 2000 mit dem Office-Paket ausgeliefert und beinhaltet verschiedene Objekte die Dateizugriff möglich machen, u.a. auch das aus einem anderen Artikel bekannte FileSystemObject, kurz FSO genannt. Des weiteren werden die Objekte Files() und Folder() im Beispiel verwendet.

Das FileSystemObject hat verschiedene Methoden zum Datei- und Verzeichniszugriff. Wir verwenden im unteren Beispiel die Methoden GetFolder() und FolderExists(). Die Methode Files des Folder-Objektes liefert eine Collection von Dateiobjekten zurück. Diese Objekte kann man über die „Name“ Eigenschaft überprüfen, ob es sich auch um den gewünschten Dateityp handelt, also z.B. „XML“.

Soweit erst mal die graue Theorie, kommen wir zum VBA-Code.
Zuerst die Deklaration der benötigten Objektvariablen. Benötigt wird dazu der Verweis auf Microsoft Scripting Runtime.

    Dim oFSO As Scripting.FileSystemObject
    Dim oFolder As Scripting.Folder
    Dim oFile As Scripting.FILE
    Dim cFile As String

Dann die Zuweisung von oFSO und oFolder:

Set oFSO = New Scripting.FileSystemObject
    If oFSO.FolderExists(Me!Folder) Then
        Set oFolder = oFSO.GetFolder(Me!Folder)

In einer Schleife über oFolder.Files, welches eine Collection aller Dateiobjekte ist, erfolgt das Auslesen der Dateinamen im Verzeichnis:

        For Each oFile In oFolder.Files
            DoEvents
            cFile = oFile.NAME
            If Right(cFile, 3) = "xml" Then
                ReDim Preserve aFiles(i)
                aFiles(i) = cFile
                i = i + 1
            End If
        Next

Zuletzt noch die Zuweisung der Dateinamen an das Listenfeld:

Me!Listenfeld1.RowSource = Join(aFiles, ";")

Read more »

Müssen Formulare immer rechteckig sein?

By , 13. Februar 2010

Hallo,
ich hab mich in letzter Zeit ein wenig mit den Möglichkeiten der GDI32.dll API Bibliothek befasst. Die GDI (Graphik Device Interface) beinhaltet Funktionen um z.B. das Aussehen eines Formulares zu verändern. Ob dreieckig, rund, abgerundet etc ist alles möglich. Auch Kombinationen von Formen sind zulässig.
OK, zugegeben, braucht eigentlich niemand. Aber man darf auch schon mal beim Design der Formulare etwas mehr an Kreativität zeigen als sonst.

Ich möchte euch jetzt zeigen wie ihr Coole runde Formulare erstellt.
Zuerst braucht ihr einen Hintergrund. Benützt dazu euer Grafikprogramm wie z.B. Photoshop etc. und erstellt eine Grafik. macht diese gleich etwas größer als das spätere Formular. Eine Verlaufsebene einfügen, darauf mit einem coolen Stil ein Kreis malen, in den Kreis ein weiterer Kreis mit weissem Hintergrund malen. Dies gibt der Rand eures Formulars.

Dann erstellt ein leeres Formular.
Plaziert darauf eure Steuerelemente wie gewohnt, denkt aber an die spätere Formular form.

Dann kommt der Code-Teil dran. Wir benötigen 3 API Funktionen, SetWindowRgn(), DeleteObject() und CreateEllipticRgn().

Hier der Deklarationsteil:

Private Declare Function SetWindowRgn _
                          Lib "user32" (ByVal hWnd As Long, _
                                        ByVal hRgn As Long, _
                                        ByVal bRedraw As Boolean) As Long

Private Declare Function DeleteObject Lib "gdi32" ( _
                                      ByVal hObject As Long) As Long

Private Declare Function CreateEllipticRgn Lib "gdi32.dll" ( _
                                           ByVal X1 As Long, _
                                           ByVal Y1 As Long, _
                                           ByVal X2 As Long, _
                                           ByVal Y2 As Long) As Long

Dim Region1 As Long

Dann im Ereignis „Beim Laden“ wird die Form geändert. Die Koordinaten müsst ihr entsprechend anpassen, damit es bei euch passt.

Private Sub Form_Load()
    X1 = 29
    Y1 = 50
    X2 = 533
    Y2 = 552
    Me.Picture = CurrentProject.Path & "\hintergrund.gif"
    Region1 = CreateEllipticRgn(X1, Y1, X2, Y2)
    SetWindowRgn Me.hWnd, Region1, True
End Sub

Wenn das Formular entladen wird sollte auch die Form zurückgesetzt werden:

Private Sub Form_Unload(Cancel As Integer)
    DeleteObject Region1
End Sub

Hier noch ein Beispiel wie das ganze aussehen könnte:

Auf www.vbAchiv.net findet ihr zu den API-Funktinonen und zu weiteren Funktionen der GDI Erklärungen.
Ein komplexeres Beispiel als Download findet ihr auf access-o-mania

AV 2010

Startformular mit „Countdown“ Schaltfläche

By , 18. März 2009

Ein Startbildschirm kann verschiedenste Aufgaben erfüllen. Z.B. den Anwender begrüßen oder über Neuigkeiten informieren. Ein weiterer Aspekt ist den Start der eigentlichen Anwendung bewusst zu verzögern um eine Art Barriere aufzubauen. Dies könnte man z.B. dafür Nutzen eine eingeschränkte Anwendung zu erstellen, um die Anwender zu drängen eine entsprechende Lizenz zu kaufen.

Dies zu realisieren ist sogar ziemlich einfach. Man erstelle ein Formular mit einer deaktivierten Befehlsschaltfläche die im Klick-Ereignis das Anwendungs-Formular öffnet. Im Formularmodul dann dieser Code:

Option Compare Database
Option Explicit

Dim Startintervall As Integer

Private Sub cmdApp_Click()
    DoCmd.Close acForm, Me.Name
    DoCmd.OpenForm "Anwendungsform"
End Sub

Private Sub Form_Timer()
    If Startintervall <= 10 Then
        Me.TimerInterval = 1000
        Me!cmdApp.Caption = 10 - Startintervall
        Startintervall = Startintervall + 1
    Else
        Me.TimerInterval = 0
        Me!cmdApp.Caption = "Anwendung starten"
        Me!cmdApp.Enabled = True
    End If
End Sub

Read more »

Quick Tipp: Popup-Formulare positionieren

By , 22. Februar 2009

Popup-Formular, d.h. Formulare mit der Eigenschaft Popup = ja, lassen sich mittig ausrichten indem man die Eigenschaft „Automatisch zentrieren“ auf ja stellt. Will man aber z.B. mehrere Popup-Formular an definierter Stelle positionieren, dann muss man dafür schon ein Stückchen VBA-Code einsetzen.

Die entsprechende Anweisung dazu lautet:
Forms("Formularname").Move Links, Oben, Breite, Höhe
Die Angaben Links, Oben, Breite und Höhe sind in Twips anzugeben. Die Angabe des Wertes Links ist erforderlich, die restlichen Angaben sind Optional.

Die Maßeinheit Twip bedeutet 1/20 eines Inch-Punktes, was 1/1440 Inch (Zoll) entspricht.
Demnach ist 1mm gerundete 56,7 Twips.

Probiert es einfach mal aus. Wenn ihr aber zu große Werte eingebt, wird euer Formular nicht mehr zu sehen sein da es außerhalb dem sichtbaren Bereich „liegt“.

Ein anderer Anwendungsfall ist, dass ein Popup-Formular relativ zu einem anderen Formular oder einem Steuerelement auf einem anderen Fomular plaziert sein soll. Dies ist z.B. bei dem DatePicker der Fall, den ich in einem anderen Beitrag beschrieben habe.

Nachfolgend eine Prozedur die ein Popup-Formular öffnet und direkt unter einer Befehlsschaltfläche plaziert:
Read more »

Zeichnen in Formularen mit Lebans Picturebox-Klasse

By , 12. Februar 2009

Bekannter Weise gibt es für Formular-Objekte keine Zeichen-Befehler wie line() oder Circle(), dies ist den Berichts-Objekten vorbehalten. Das kann man ärgerlich finden oder nicht, ändern kann man das eh nicht. „Man“ sucht also nach Alternativen – der Kunde will das schließlich.

Fündig wird man wie so oft bei Stephen Lebans, einem Access Enthusiast der sein Wissen bereitwillig teilt. Auf http://www.lebans.com/imageclass.htm findet man für Access 97 und 2000+ 2 Downloads namens PictureBoxA97.zip und PictureBoxA2K.zip.

Der Download besteht aus einer Beispieldatenbank die die Funktionsweise demonstriert. Für eigene Projekte sind die beiden Klassenmodele clsPictureBox und clsVertices relevant, die man am besten gleich in eine leere Access-Datei kopiert.

Meine Aufgabenstellung war, anhand von Konstruktionsangaben offene und geschlossene Grundrisszeichnungen darzustellen. Die Angaben waren Kundenspezifisch und bestehen aus Innenwinkel und Länge von Linien, also eine relative Polarkoordinaten. Ein Quadratischer Grundriss der Länge 1000 hat daher die folgenden Angaben:
(90/1000), (90/1000), (90/1000), (90/1000)
Gibt man noch eine Tiefe von 200mm vor, dann sieht die generierte Zeichnung so aus:

Read more »

Ausklappbare Formularbereiche

By , 1. Oktober 2008

Bei Formulareingaben gibt es Felder, die häufig benutzt werden, und solche Felder, die nur in bestimmten Fällen benötigt werden. Um nun das Formulardesign trotzdem schlank und übersichtlich zu halten kann man sich eines Tricks bedienen: Man versteckt die selten benötigten Felder und zeigt diese nur bei Bedarf an.

Na so einfach ist es dann doch nicht. Schauen wir uns zuerst mal das mögliche Ergebnis in Bildern an.
Formular in Normalgröße
Read more »

Mehrsprachigkeit die 3.

By , 16. September 2008

Im letzten Teil der Serie geht es nun darum wie man in der Praxis die Mehrsprachigkeit realisiert. In der Regel ist es so, dass man zuerst die Formulare und Berichte ganz normal in Deutscher Sprache erstellt.
Um nun die Sprachcodes zu handhaben kann man mit einem Blatt Papier anfangen und Code mit Sprache als Liste aufschreiben. Oder man macht das z.B. in Excel. Wichtig bei dieser Sache ist, dass der Sprachcode fortlaufend ist und dass keine doppelten Codes vorhanden sind.
Hat man alle Deutschen Texte und Sprachcodes erfasst, ändert man nun im Formular/Bericht die Beschriftungen bzw. ControlTipText ab.
OK, das ist mir persönlich zu mühselig, und ich habe daher kurzerhand eine Funktion erstellt, die das automatisch für mich macht.
Read more »

OfficeFolders theme by Themocracy