Neuigkeiten:

Wenn ihr euch für eine gute Antwort bedanken möchtet, im entsprechenden Posting einfach den Knopf "sag Danke" drücken!

Mobiles Hauptmenü

Änderungsabfrage mit Variablen Suchkriterien aus externer Tabelle

Begonnen von carrotman, Januar 16, 2014, 21:41:30

⏪ vorheriges - nächstes ⏩

carrotman

Hallo zusammen,

ich möchte gerne in Access Kontoauszüge auswerten.
Die Tabelle_Kontoauszuege hat u.a die Spalten Buchung_Datum, Buchung_Betrag, Buchung_Text, Sachkonto.
Die ersten 3 kommen von der Bank, das Sachkonto möchte ich möglichst automatisch mit einer Änderungsabfrage hinzufügen, anhand verschiedenster Kriterien, die in Buchung_Text zu finden sind (in der WENN-Funktion hab ich zusätzlich auch über Buchung_Betrag und Buchung_Datum gesucht, wenn das aber in meinem Vorhaben unten zu kompliziert ist, komme ich auch ohne aus). Derzeit habe ich das über verschachtelte WENN-Funktionen gelöst, was so ausssieht:
WENN([Buchung_Text] wie ,,*Suchtext1*" AND [Buchung_Text] wie ,,*Suchtext2*" OR [Buchung_Text] wie *Suchtext3* AND NOT [Buchung_Text] wie *Suchtext4*;[Sachkonto]17;WENN([Buchung_Text] wie *Suchtext5* AND NOT [Buchung_Text] wie *Suchtext2*;[Sachkonto]2;""))

Das klappt soweit auch, aber man kommt schnell an ein Ende. Zum einen kann ich damit max. 13 WENN-Funktionen ineinander verschachteln, zum anderen muss man jedes Mal die Formel ändern, wenn ein neues Kriterium hinzukommt, für mich wäre das umständlich, für andere User, die Access nicht kennen, unmöglich. Die Funktion also 1 zu 1 in VBA umzuwandeln wäre daher auch keine Option, denn dann muss das Modul jedes Mal geändert werden.
Daher bin ich auf den Ansatz gekommen, zwei weitere Tabellen zu erstellen, wovon die eine Tabelle_Kontoauszuege_Regeln die Regeln enthält (Regel_ID und Sachkonto) und die zweite Tabelle_Kontoauszuege_Regel_Items die Regel Items mit den Spalten Regel_Item_ID, Operator, Suchtext, Regel_ID Position.
Die Funktion oben würde dann jetzt so aussehen:



Regel_Item_IDOperatorSuchtextRegel_IDPosition
1*Suchtext1*171
2AND*Suchtext2*172
3AND NOT*Suchtext4*174
4OR*Suchetxt3*173
5*Suchtext5*21
6AND NOT*Suchtext2*   22

Meine Frage ist jetzt, wie muss ich den zugehörigen Code schreiben (ich vermute, das wird über VBA-Module gehen, mit denen habe ich bislang noch nicht gearbeitet), damit die Operatoren berücksichtigt werden, sowie alle Suchtexte, die eine Regel betreffen und deren Position und dass zudem die Regel_ID in Tabelle_Kontoauszuege.Sachkonto eingetragen wird.
Außerdem sollen manuelle Eingaben bei Sachkonto später nicht mehr geändert werden (es geht auch, wenn alle vorhandenen Einträge später nicht mehr überschrieben werden - was einmal zugewiesen wurde, bleibt dann so - ist mit der WENN-Funktion auch ziemlich simpel zu lösen, wenn Sachkonto ungleich NULL, dann Sachkonto, sonst...).

Zu Übungszwecken möchte ich das gerne in Access und nicht mit einer anderen Software lösen und würde auch gerne den Ansatz, dass die Suchkriterien in einer eigenen Tabelle aufgelistet werden, beibehalten.
Für jede Unterstützung bin ich sehr dankbar.

Hondo

Hallo,
ich würde das per VBA-Code lösen. Wenn du nach Muster in dem Buchungstext suchst, macht man das am besten per RegExp, also reguläre Ausdrücke. Ich hab das mal in meinem Blog beschrieben: http://www.accessblog.de/?p=432

Ansonsten kann man sich auch mit if-Konstrukten behelfen und mit instr() den Suchbegriff suchen. Da instr aber groß von kleinschreibung unterscheidet, sollte man z.B. mit lcase() den Buchungstext kleingeschrieben vergleichen.
Hier mal eine Prozedur die das macht:

Sub Sachkonto_Speichern()
    Dim strText As String
    Dim Suchtext1 As String, Suchtext2 As String, Suchtext3 As String, Suchtext4 As String
    Dim db As DAO.Database
    Dim rs As DAO.Recordset

    Set db = CurrentDb
    Set rs = db.OpenRecordset("tblKontoauszug")

    Suchtext1 = "ebay"
    Suchtext2 = "volksbank"
    Suchtext3 = "forex"
    Suchtext4 = "paypal"

    Do While Not rs.EOF
        If InStr(LCase(rs!Buchung_Text), Suchtext1) > 0 And InStr(1, LCase(rs!Buchung_Text), Suchtext2) > 0 Or InStr(1, LCase(rs!Buchung_Text), Suchtext3) > 0 And InStr(1, LCase(rs!Buchung_Text), Suchtext4) = 0 Then
            strText = "17"
        ElseIf InStr(LCase(rs!Buchung_Text), Suchtext4) > 0 And InStr(1, LCase(rs!Buchung_Text), Suchtext2) = 0 Then
            strText = "2"
        End If
        If strText <> "" Then
            rs.Edit
            rs!Sachkonto = strText
            rs.Update
            strText = ""
        End If
        rs.MoveNext
    Loop

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


Gruß Andreas

Hondo

Bezüglich noch zu deinen Regeln, du musst das so schreiben dass in 1 Zeile 1 Regel steht. D.h. wenn das und das und das und das nicht dann ... und nicht in mehere Zeilen aufgesplittet. Am einfachsten wird das wohl mit den regulären ausdrücken gehen. Dann brauchst du als Regel nämlich nur das Patchmuster abspeichern.
Andreas

carrotman

Tausend Dank Andreas für Deine Hilfe!
Ich hab es mal ausprobiert, aber es klappt nicht wirklich, dazu muss ich mich wohl erst in VBA richtig einarbeiten. Da mir das aber derzeit zu zeitaufwändig ist, werde ich schauen, dass ich Buchungskennzeichen vergebe, wenn ich etwas überweise, bzw. etwas bekomme, damit geht die Zuordnung dann ja ziemlich einfach.
Vielen Dank noch mal,
Tobias

Hondo

Ist das Thema noch aktuell?
Falls nicht bitte setzte es auf Status gelöst.

Andreas

carrotman

Hab angefangen, jetzt meine Buchungskennzeichen mit regulären Ausdrücken aus den Kontoauszügen auszulesen, allerdings suche ich noch nach einer Lösung für folgendes Problem:
Meine Buchungskennzeichen bestehen immer aus einem "Z", gefolgt von 8 Zahlen und evtl. einem Buchstaben am Ende - diese 9-10 Zeichen können allerdings an beliebiger Stelle (der Bank sei Dank) durch insgesamt ein Leerzeichen unterbrochen sein. Also z.B. "Z12345678b"; "Z123 45678b" oder "Z 12345678".
Wie muss der Ausdruck lauten?
Gibt es eine Möglichkeit, das eleganter und kürzer als so zu lösen (Leerzeichen beachten, sind nicht in Klammern gesetzt)?
"(z|Z)( ?\d{8}|\d \d{7}|\d{2} \d{6}|\d{3} \d{5}|\d{4} \d{4}|\d{5} \d{3}|\d{6} \d{2}|\d{7} \d{1}|\d{8} ?)[a-zA-Z]?"

Ich habe es hiermit versucht, das liefert aber keine Ergebnisse. Was stimmt daran nicht? Sucht er mit {9,10} mind. 9, max. 10 mal nach dem ganzen Ausdruck oder nach der Anzahl der Stellen insgesamt, also 9 bis 10 Zeichen?
"((z|Z)(\d{1,8})?( )?(\d{1,8})?){9,10}([a-zA-Z])?"

Danke schon mal für eure Hilfe,
Tobias