Category: VBA Code

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 »

Tips & Tricks zu Gespeicherte Prozeduren in Access

By , 9. April 2011

Im zweiten Artikel in dieser Serien ging es darum wie man Gespeicherte Prozeduren in Access aufrufen kann, welche Parameter wie übergeben werden, und wie man gleichartige Gespeicherte Prozeduren mit einem universellen VBA-Prozedur aufruft. In diesem dritten und vorerst letzten Teil geht es nur noch um Feinheiten und Vereinfachungen.

Beispielsweise kann man für Gespeicherte Prozeduren die genau einen Rückgabewert liefern, eine universelle Prozedur schreiben.
Eine solche Prozedur in Access benötigt auf jedenfall ID-Feld und ID-Wert, welche beide zusammen das Abfragekriterium bilden.
Ist die Gespeicherte Prozedur universell gehalten (siehe 4. Codelisting im zweiten Teil der Serie), wird zusätzlich der Tabellennamen benötigt.
Bzw. bei einer speziell gehaltenen Gespeicherten Prozedur wird der Name der Gespeicherten Prozedur benötigt.

Ich verwende für letztere Zwecke die nachfolgende VBA-Prozedur:

Public Function singleProc(idWert As Double, idFeld As String, outputFeld As String, strProcname As String) As Variant
    ConnectionString = "Driver={SQL Server};Server=?;Database=?;Uid=?;Pwd=?;"
    Set cnn = OpenConnection(ConnectionString)
    Set cmdObj = New ADODB.Command
    With cmdObj
        .ActiveConnection = cnn
        .CommandText = strProcname
        .CommandType = adCmdStoredProc
        .CommandTimeout = 60
        .Parameters.Refresh
        .Parameters("@" & idFeld) = idWert
        .Execute
        singleProc = .Parameters("@" & outputFeld).Value
    End With
    Set cmdObj = Nothing
    Set cnn = Nothing
End Function

Damit kann jede gespeicherte Prozedur aufgerufen werden die genau 1 Inputvariable und genau 1 Outputvariable verlangt.
Der Namen beider Variablen können Variieren, sie werden ja als idFeld und outputFeld übergeben.
Read more »

Gespeicherte Prozeduren in Access aufrufen

By , 8. April 2011

Im ersten Teil der Serie “Gespeicherte Prozeduren” ging es darum wie im SQL Management Studio von Microsoft gespeicherte Prozeduren angelegt werden können. Es wurden zwei verschiedene Möglichkeiten einen SQL-String auszuführen erörtert, sowie zwischen “Getter” und “Setter” Prozeduren unterschieden. In diesem zweiten Teil geht es nun darum wie man diese Gespeicherten Prozeduren (SP für Stored Procedures) in Access nutzen kann um ausgewählte Daten zu erhalten bzw. um Daten in der SQL Server Datenbank zu speichern.

Ich erstelle zu diesem Zweck immer ein separates Modul mdlStoredProcedures worin ich verschiedene Prozeduren erstelle, je nach Anwendungszweck.
Ich unterscheide dabei zwischen Universellen Prozeduren und Speziellen Prozeduren.

Universelle Prozeduren bedienen immer mehrere gleichartige Gespeicherte Prozeduren im SQL Server. Beispiel dazu sind z.B. Prozeduren wo ein Status geändert wird. Nachfolgend als Generelles Beispiel für eine Setter-Prozedur in Access:

Deklarationsteil:

Dim cmdObj As ADODB.Command
Dim cnn As ADODB.Connection
Dim ConnectionString As String

Prozedur:

Public Function setStatus1(idWert As String, Prozedurname As String, Status As Long) As Boolean
    ConnectionString = "Driver={SQL Server};Server=?;Database=?;Uid=?????;Pwd=?;"
    Set cnn = OpenConnection(ConnectionString)
    Set cmdObj = New ADODB.Command
    With cmdObj
        .ActiveConnection = cnn
        .CommandType = adCmdStoredProc
        .Parameters.Append .CreateParameter("@indent", adVarChar, adParamInput, 10, idWert)
        .Parameters.Append .CreateParameter("@status", adVarChar, adParamInput, 2, CStr(Status))
        .CommandText = Prozedurname
        .Execute
    End With
    Set cmdObj = Nothing
    Set cnn = Nothing
End Function

Der Prozedurname wird als Parameter übergeben und der Eigenschaft CommandText des ADODB Objektes zugewiesen.
An dieser Stelle sei erwähnt, dass wir mit ADO arbeiten, und daher den Verweis “Microsoft ActiveX Data Objects 2.1 Library” benötigen.
Die Übergabeparameter müssen in der richtigen Reihenfolge stehen wie in der SP definiert. Die Parameter der Funktion CreateParameter() sind folgende:
Parametername, Datentyp, Input/Output-Typ, Zeichenlänge, Wert
Read more »

Benutzerdefinierte Datentypen

By , 8. November 2010

Man unterscheidet zwei verschiedene Typen von benutzerdefinierte Datentypen:
a) den Aufzählungstyp
b) den Verbundtyp

Der Grundlegende Gedanke hinter den benutzerdefinierten Datentypen ist, zusammengehörige Informationen nicht in vielen verschiedenen Variablen zu speichern sondern in nur 1 Datentyp. Dies führt zur Vereinfachung und zur Übersichtlichkeit im VBA-Code.

a) Aufzählungstyp:
Der Aufzählungstyp beinhaltet eine Variable mit einem begrenzten abzählbaren Wertebereich. Er wird durch die Enum-Anweisung gebildet. Wir machen gleich mal ein Beispiel damit Sie sehen was ich damit meine. Z.B. möchten Sie in Ihrer Anwendung verschiedene Sicherheitsstufen realisieren um Mitarbeiter z.B. vor verschiedene Gefahrensituationen zu warnen.
Hier ein frei erfundenes Szenario:

Public Enum Securitylevel
    normal = 0
    leicht erhoeht = 1
    erhoeht = 2
    Gefahr = 3
    akute Gefahr = 4
    Evakuierung  = 5
End Enum

Nun können Sie im Code auf den Datentyp zugreifen und den Wert verändern:

Dim security As Securitylevel
security = 1
Alternativ: security = Gefahr

Read more »

Datenimport aus Textdatei

By , 3. November 2010

Analog zum Artikel Regelmäßiger Datenimport realisieren wo es um den Import von Daten aus Excel ging, zeige ich in diesem Artikel auf wie man aus einer Textdatei importiert. Langweilig, kennen wir schon … mögen Sie jetzt denken. Aber lesen Sie weiter, es wird spannender als Sie denken.

Die Situation ist die gleiche wie im ersten Artikel. Sie haben ein Produktiv-Backend das 7×24 Stunden im Einsatz ist. Das bedeutet dass Sie nur bereinigte Daten in das Arbeitsbackend übertragen können. Der Lösungsweg ist der gleiche wie zuvor, der Import geschieht über eine temporäre Datenbank die zum Zwecke des Imports und der Bearbeitung der Daten per Code erstellt danach gelöscht wird.

Details zum Erstellen der temporären Datenbank und Tabelle lesen Sie bitte im ersten Artikel. Der Vereinfachung halber füge ich hier nur die Prozedur ein die Datenbank und Tabelle erstellt.

Function CreateNewDB(dbNam As String, TabName As String) As Database
    Dim wrkDefault As DAO.Workspace
    Dim dbNeu As DAO.Database

    ' Standardarbeitsbereich bestimmen.
    Set wrkDefault = DBEngine.Workspaces(0)

    'wenn Datenbank bereits vorhanden, dann löschen
    If Dir(CurrentProject.Path & "\" & dbNam & ".mdb") <> "" Then
        Kill CurrentProject.Path & "\" & dbNam & ".mdb"
    End If

    'neue Datenbank erstellen
    Set dbNew = wrkDefault.CreateDatabase(CurrentProject.Path & "\" & _
                                          dbNam & ".mdb", dbLangGeneral, dbEncrypt Or dbVersion40)

    'Tabelle erstellen
    dbNew.Execute "CREATE TABLE " & TabNam & " (" & Fields & ")"

    'Rückgabewert zuweisen
    Set CreateNewDB = dbNeu
End Function

Der nächste Schritt ist der Import aus der Textdatei. In meinem Beispiel verwendete ich eine Spaltenorientierte Textdatei mit gleich langen Spalten. Es geht aber auch mit anderen Typen wie z.B. mit einem Separator etc. Der einfachste Weg ist eine Importspezifikation zu erstellen. Wer das nicht kennt hier eine Schnellanleitung dazu:

  • Über Datei/Externe Daten/Importieren Dateityp Textfiles auswählen und die entsprechende Textdatei auswählen.
  • Ein Klick auf Importieren öffnet einen Assistenten zur Zuordnung der Spalten und der Spalteneigenschaften.
  • Man wählt einen der beiden Modis aus, also Trennzeichen oder feste Breite und klickt auf “Weiter”.
  • Danach dem Assistenten folgen. Die Eingaben sollten selbsterklärend sein.
  • Zum Schluss bevor man “Fertig stellen” klickt die Schaltfläche “Weitere” anklicken.
  • Ein weiteres Fenster öffnet sich wo man entsprechende Auswahlen treffen sollte.
  • Zum Schluss auf “Speichern unter” klicken, einen Spezifikationsnamen angeben und 2x OK klicken.
  • Jetzt sind Sie wieder im ersten Fenster wo Sie den Assistenten mit “Fertig stellen” beenden.

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

Arbeiten mit ISO Passmaßen

By , 6. Januar 2010

Wenn Sie in Ihrer Anwendung ISO Passmaße nach ISO 286 benötigen, so findet man im Internet zahlreiche Excel-Tabellen die sämtliche Abmaße für Bohrung und Welle enthalten.
Ich bin für mein Projekt auf der Seite www.siritec.com fündig geworden. Siritec stellt das Programm “PMTabelle V4.0.1″ für Solid Edge kostenlos zur verfügung, dieser Download enthält u.a. die Excel-Datei PassMassTabelle.xls, auf deren Struktur der folgende Programmcode aufbaut. Die Excel Arbeitsmappe enthält über 60 Arbeitsblätter, für jede Toleranzlage und Bohrung/Welle je eine Seite bei einem Nennmaß bis 500mm.

Der Aufbau im Einzelnen ist folgender:

  • Spalte 1: Nennmassbereich untere Grenze (ausschließend)
  • Spalte 2: Nennmassbereich obere Grenze (einschließend)
  • Spalte 3 bis 38: Toleranzgrade 1 bis 18, wobei jedes Toleranzfeld 2 Spalten umfasst, für die untere und für die obere Abmaße.
  • Zeile 2: Toleranzgrade
  • Zeile 3: Kennung untere Grenze/obere Grenze
  • Zeile 4-28 Toleranzen in µm

Was jetzt folgt ist die Excel Automation als late Binding, die ich nur in Ausschnitten zeigen und erleutern möchte.

Public UTG AS Double
Public OTG AS Double
...
Sub getPassMasse(istmass, Toleranzlage, Toleranzgrad)
    Dim ExcelApp AS Object
    Dim ws AS Long 'Worksheet - Zähler
    Dim tol AS long  'Toleranzen - Zähler
    Set ExcelApp = CreateObject("Excel.Application")
    ExcelApp.Workbooks.Open FileName:="c:\PassMassTabelle.xls", ReadOnly:=True
    With ExcelApp
        For ws = 1 To .Sheets.Count    'alle Arbeitsblätter durchsuchen
            If ExcelApp.Sheets(ws).Name = Toleranzlage Then
                For tol = 4 To 28
                    If istmass <= CDbl(ExcelApp.Sheets(ws).Cells(tol, 2)) And istmass > CDbl(ExcelApp.Sheets(ws).Cells(tol, 1)) Then
                        UTG = ExcelApp.Sheets(ws).Cells(tol, 2 * Val(Toleranzgrad) + 1)
                        OTG = ExcelApp.Sheets(ws).Cells(tol, 2 * Val(Toleranzgrad) + 2)
                        GoTo Ausstieg
                    End If
                Next tol
            End If
        Next ws
    End With

Ausstieg:
    Excel_Terminate
End Sub

Zuerst wird das Excel Objekt instanziert und die Arbeitsmappe PassMassTabelle.xls geöffnet.
In der äußeren Schleife werden alle 69 Arbeitsblätter durchsucht nach dem, welches der entsprechenden Toleranzlage entspricht. Ist das Abeitsblatt gefunden werden in einer inneren Schleife die Zeilen 4 bis 28 durchlaufen, und nach dem Nennmassbereich gesucht, in diesen das Istmass gehört. Ist der richtige Bereich gefunden werden die Toleranzen ausgelesen. die richtigen Zellen findet man über den Toleranzgrad. Beispielsweise ergibt Toleranzgrad 7 die Zellen 15 und 16 der entsprechenden Zeile. So wird auf eine zusätzliche Schleife verzichtet. Sind die Toleranzen gefunden erfolgt der Ausstieg über eine Sprungmarke.
Was man bei der Excel Automation immer machen sollte ist eine Prüfung ob Excel schon geöffnet ist oder nicht, damit die Instanzierung des Excel Objektes auch funktioniert.
Die Funktion Excel_Terminate dient dazu, Excel zu schließen oder nur die Arbeitsmappe zu schließen, je nach dem ob beim Start Excel schon geöffent war.
Zu beidem gibts in den Newsgroups bzw. einschlägige Foren genug Beispiele.

UTG und OTG sind unteres und oberes Abmass in µm. das bedeutet, dass das Istmass du beiden hinzuzuaddieren ist, um die Toleranzgrenzen zu erhalten.

Zur Auswahl einer Passung kann man sich z.B. ein kleines Popup-Formular erstellen, das beim schließen die gefundenen Toleranzgrenzen in das Eingabeformular eintragen. Nachfolgend noch ein paar Screenshots wie das aussehen könnte.

AV 2010

Plausibilitätsprüfung von Messwerten

By , 6. Oktober 2009

Bei der manuellen Messwerterfassung hat man immer die Unsicherheit des Faktors “Mensch” zu berücksichtigen. Zahlendreher oder zuviele Nullen sind da schnell mal eingegeben, und im Nachhinein schwer zu finden. Da ist es besser man macht eine Plausibilitätsprüfung indem man das Formular ungebunden macht und bei klick auf den Speicherbutton die Eingabewerte überprüft.

Z.B. auf die Anzahl der Stellen, ob positiv oder negativ, ob größer oder kleiner von einem bestimmten Wert, oder ob in einem bestimmten Zahlenbereich liegend.

Das Problem daran ist, dass sich diese Begrenzungen ständig ändern können. Dann muss man den VBA-Code durchsuchen wo man diese Plausibilitätsprüfung gemacht hat. Besser wäre das doch wenn man in einer Tabelle alle Plausibilitäten einfach ablegen könnte von wo aus sie einfach zu administrieren sind. Und genau das wollen wir jetzt machen.

Zuerst die Tabelle.
Jeder Messwert hat eine bestimmte Nummer oder Namen. Außerdem benötigen wird ein Vergleichsmuster, und eine Werteliste mit den einzelnen Werten gegen den der Messwert abgeprüft wird.

Ein Datensatz in dieser Tabelle sieht z.B. so aus:

ID Bezeichner Muster Werteliste
1 MP1 > {1} AND < = {2} AND <> {3} 2;5;4

Im Muster sieht man Platzhalter in geschweiften Klammern stehen, diese werden dann mit den Werten aus der Werteliste ergänzt.
Read more »

OfficeFolders theme by Themocracy