Neuigkeiten:

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

Mobiles Hauptmenü

String zwischen bestimmten Zeichen auslesen

Begonnen von ChickenWing, September 09, 2016, 08:11:48

⏪ vorheriges - nächstes ⏩

ChickenWing

Servus Leute,

ich versuche einen Wert aus einem String auszulesen. Kleines Beispiel:

KD-NR-NR=12345^KONTO-NR=6789^PRIMANOTA=24^Buchung=123^
LF-NR=67890^KONTO-NR=4010^PRIMANOTA=24^Buchung=456^
KONTO-NR=9876^PRIMANOTA=24^Buchung=789^
PERS-NR=1234^LOHNART=123^

Das steht (wunderschön...) alles in einer Spalte. Ich brauche für eine Abfrage die KD-NR bzw. die LF-NR oder wenn die nicht vorhanden sind entsprechend Konto-NR bzw. die PERS-NR.
Ich möchte im Endeffekt weitere Tabellen darüber verknüpfen. Also Händlernamen bzw. Kundennamen anhängen.
Ich bin bis an den Punkt gekommen:

MID([Haupttabelle].[Zusatzinfo],7,5)
FROM Haupttabelle;


Das ganze klappt zwar für die KD-Nr und LF-NR aber bei den anderen scheitert es natürlich aufgrund der anderen Länge und Position im String.

Gibt es eine Möglichkeit zu sagen, dass er mir zwischen dem ersten = und dem ersten ^ die Nummern ausgibt oder ähnliches? Bin noch neu im Thema und arbeite mich aktuell in Access ein. Von den Sprachen habe ich noch keinen Schimmer, verstehe aber im Groben die Syntax.

Ich sitze an Access 2016.

Falls jemand eine Idee hat würde ich mich freuen  :)

Liebe Grüße
Max
----------------------
Mit freundlichen Grüßen

Max

Lachtaube

In VBA kann man die Split-Funktion zum Trennen der Daten verwenden. Hier etwas VBA-Code zum Testen in einem aöögemeinen VBA-Modul.Sub Test()
   Const Data$ = _
         "KD-NR-NR=12345^KONTO-NR=6789^PRIMANOTA=24^Buchung=123^" & vbCrLf & _
         "LF-NR=67890^KONTO-NR=4010^PRIMANOTA=24^Buchung=456^" & vbCrLf & _
         "KONTO-NR=9876^PRIMANOTA=24^Buchung=789^" & vbCrLf & _
         "PERS-NR=1234^LOHNART=123^"

   Dim Attributes$(), Attrib$(), i&

   '// ggf. Zeilenumbrüche vorher entfernen
   Replace(Data, vbCrLf, vbNullString)
   Attributes = Split(Data, "^")
   For i = 0 To UBound(Attributes)
      If InStr(Attributes(i), "=") Then
         Attrib = Split(Attributes(i), "=")
         MsgBox Attrib(0) & ": " & Attrib(1)
         
         '// in einem zum Editieren vorbereitetem Recordset könnte man hier
         '// auch Feldwerte eintragen, wenn die Spaltennamen vor dem "="
         '// mit den Zielfeldern der Tabelle übereinstimmen. Idealerweise ersetzt
         '// man noch Minus-Zeichen durch einen Unterstrich (hier nicht
         '// berücksichtigt)
         '//
         '// DeinRecordset(Attrib(0)) = Attrib(1))
      End If
   Next
End Sub
Grüße von der (⌒▽⌒)

ebs17

Dim vArr As Variant
vArr = Split(EinString, "^")
For i = 0 To UBound(vArr)
   Debug.Print Split(vArr(i), "=")(1)
Next


ZitatDas steht (wunderschön...) alles in einer Spalte.
Fallen solche Inhalte vom Himmel in Deine Tabellen, oder hast Du einfach ungeschickt importiert, z.B. den nächstbesten Knopf gedrückt?

Besser würde man einen Importvorgang als eine Schnittstelle betrachten, wo man
a) die Ausgangsdatei in Struktur und Inhalt analysiert,
b) in der Datenbank ein vorhandenes durchdachtes Datenmodell  hat und nicht eine sich ergebende Tabelle,
c) ausgehend vom Vorgenannten einen Weg beschreitet, Daten aus der Ausgangsdatei in die Tabelle(n) des Datenmodells zu überführen.
Mit freundlichem Glück Auf!

Eberhard

ChickenWing

Hey Taube,
Ok, soweit ich es verstehe klingt das erstmal super. Aber wie/bzw. wo binde ich das ein? Ich hab bis jetzt immer nur mit SQL um mich geworfen...

Außerdem: Verstehe ich das richtig das er nur die 4 Zeilen durchsucht die ich als Beispiel gegeben habe? Oder verstehe ich das falsch. Gut möglich  ;D
Es geht ja drum eine komplette Tabelle damit in Access durchzuarbeiten. Die ist mehrere Millionen Zeilen groß. Ist anstrengend alles abzutippen  :D

Funktionsweise aufgrund der Größe stelle ich mir so vor(weiß nicht hab das hilft):
Der Endnutzer soll in einem Formular eine Kostenstellennummer eingeben, nach der wird gesucht, daraufhin die Spalte um die es hier geht durchgenommen und entsprechend werden Händler/Kundennamen angehangen.

Mit dem Formular etc. ist aber alles schon gemacht. Mir geht's nur um die Nummern.
Hoffe ich blamiere mich hier nicht direkt  ::)

ZitatFallen solche Inhalte vom Himmel in Deine Tabellen, oder hast Du einfach ungeschickt importiert, z.B. den nächstbesten Knopf gedrückt?

Besser würde man einen Importvorgang als eine Schnittstelle betrachten, wo man
a) die Ausgangsdatei in Struktur und Inhalt analysiert,
b) in der Datenbank ein vorhandenes durchdachtes Datenmodell  hat und nicht eine sich ergebende Tabelle,
c) ausgehend vom Vorgenannten einen Weg beschreitet, Daten aus der Ausgangsdatei in die Tabelle(n) des Datenmodells zu überführen

Die Tabelle selbst ist nur verknüpft nicht importiert. Ich ziehe sie über ODBC-Treiber. Importiert würde sie Access sprengen da sie alle Buchungen seid fast 20 Jahren enthält.
Ich habe leider keinen Einfluss auf die Tabelle. Das ganze hat mir schon öfter die Arbeit verkompliziert  :-\
----------------------
Mit freundlichen Grüßen

Max

Lachtaube

Das Beispiel sollte nur demonstrieren, wie man den Zeichenwust zerpflücken kann. In der Praxis wird man dann ehere eine Methode verwenden, die den Sermon oder auch ein Schlüsselfeld als Parameter durchreicht. Es hängt wohl davon ab, was unter angehangen zu verstehen ist.
Grüße von der (⌒▽⌒)

ChickenWing

Mit angehangen meinte ich:
Mein Ziel ist es an die Daten der Haupttabelle die Namen der Lieferanten und Kunden anzuhängen, da nur die entsprechende Nummer in der Tabelle vorhanden ist. Die Lieferanten und Kundendaten stehen jeweils in eigenen(verknüpften) Tabellen im Stil von

LF-NR          Name                   Kontonummer
15221          Beispiel GmbH      123456789

entsprechend brauche ich eine Abfrage die mir bei meiner Grundtabelle
Grundtabelle:

Kostenstelle/Träger    Menge     Betrag          Zusatzinfo
123456                       5             250€          KD-NR-NR=12345^KONTO-NR=6789^PRIMANOTA=24^Buchung=123^

die KD-NR/LF_NR isoliert und in einem eigenen Feld wiedergibt. Also etwa so:

Kostenstelle/Träger    Menge     Betrag          LF/KD-NR
123456                       5             250€          12345


Ich möchte also die LF/KD-NR dann als Fremdschlüssel um eine n:1 Beziehung zwischen der Haupttabelle und der Kunden Tabelle(bzw. Lieferanten Tabelle herzustellen. Im Endeffekt soll dann ein Formular dabei rauskommen mit einem Eingabefeld um die Kostenstelle einzugeben und er sucht alles dazu raus inkl. den Namen des Händlers.

Kostenstelle/Träger   Menge        Betrag           LF/KD-NR         Name
123456                      5               250€              15221            Beispiel GmbH


Natürlich ist das ganze etwas größer(es stehen noch Verwendung der Güter, was es überhaupt ist usw. dabei) aber das hat ja mit dem Grundproblem nicht viel zu tun.

Zitat von: Lachtaube am September 09, 2016, 10:26:12
Das Beispiel sollte nur demonstrieren, wie man den Zeichenwust zerpflücken kann. In der Praxis wird man dann ehere eine Methode verwenden, die den Sermon oder auch ein Schlüsselfeld als Parameter durchreicht. Es hängt wohl davon ab, was unter angehangen zu verstehen ist.

Was ist ein Sermon?  :o
----------------------
Mit freundlichen Grüßen

Max

Lachtaube

Zuerst zum Wichtigen: Ein Sermon ist eine Kirchenpredigt oder ein langes (, gähnend langweilendes) Gebet. :)

Zum Problem: Erstelle ein allgemeines VBA-Modul und verwende den nchfolgenden Code. In einer Abfrage kannst Du dann in einem Feld zum Beispiel folgendes festlegen (möglichst, ohne Sonderzeichen im Feldnamen zu verwnden).LF_KD_NR: HoleInfoDetaíl(Tabname.ZusatzInfo; "LF/KD-NR")Hier nun der Code:Option Compare Database
Option Explicit

Public Function HoleInfoDetail(ByVal ZusatzInfo, ByVal InfoName$)
   Dim Pos1&, Pos2&, Length&

   '// ohne Info gibt es kein Detail
   If IsNull(ZusatzInfo) Then Exit Function
   '// ohne InfoName ebenso nicht
   If Len(InfoName) = 0 Then Exit Function

   '// Sicherstellen, dass der InfoName mit "=" endet.
   If Right$(InfoName, 1) <> "=" Then InfoName = InfoName & "="
   '// Länge des Names merken
   Length = Len(InfoName)

   '// Position von InfoName in ZusatzInfo ermitteln
   Pos1 = InStr(1, CStr(ZusatzInfo), InfoName, vbDatabaseCompare)
   If Pos1 Then
      '// Bei Erfolg die Position des nächsten "^" Feststellen
      Pos2 = InStr(Pos1 + Length, CStr(ZusatzInfo), "^")
      If Pos2 Then
         '// Bei Erfolg gefundene Info ausgeben
         HoleInfoDetail = Mid$(CStr(ZusatzInfo), Pos1 + Length, _
                               Pos2 - (Pos1 + Length))
      End If
   End If
End Function
Grüße von der (⌒▽⌒)

ChickenWing

Wow, danke  :)

Ich kämpfe grade noch damit es so einzubauen, dass es funktioniert(ich habe mir eine kleine Test DB gebastelt da ich mit VBA noch nie(außer heute) was gemacht habe), aber das bekomme ich bestimmt noch hin. Da sorgt mein Stolz für  ;D

In Bezug auf das Ganze. Die Abfrage über die jetzt alles laufen soll(hat sich erst vor einer Stunde so ergeben) ist jetzt eine Pass-Through. Funktioniert das dann noch genauso? Und wie baue ich das in den SQL ein? Wenn ich es richtig verstehe ist das
LF_KD_NR: HoleInfoDetaíl(Tabname.ZusatzInfo; "LF/KD-NR")
ja so aufgebaut, dass man es in einen normalen Abfrageentwurf einbauen kann. Den habe ich leider durch die Pass-Through ja nicht mehr.

Momentan sieht meine Abfrage so aus:
SELECT nr_kst_ktr_aper_folge, bez_kst_ktr_aper_kost1, ka_folge, bez_ka, menge_folge, betrag_folge, beleg_datum_folge, beleg_nr_folge, text_folge, zusatzinfo_folge
from be_buchungfolge
where nr_kst_ktr_aper_folge =4112999


Zur Erklärung: Das Kriterium =4112999 ist einfach nur eine Art Platzhalter damit nicht alles gezogen wird.

Das wird später durch diesen Code im Formular alles angepasst

Private Sub Befehl2_Click()
    Dim dbsCurrent As Object
    Dim qryTest As QueryDef
           
           
    Set dbsCurrent = CurrentDb
    Set qryTest = dbsCurrent.QueryDefs("Abfrage1")
           
    qryTest.Connect = "%%%%%%%%%%%%%%%%;TABLE=lnx.be_buchungfolge"
    qryTest.SQL = "SELECT nr_kst_ktr_aper_folge, bez_kst_ktr_aper_kost1, ka_folge, bez_ka, menge_folge, betrag_folge, beleg_datum_folge, beleg_nr_folge, text_folge, zusatzinfo_folge from be_buchungfolge where nr_kst_ktr_aper_folge =" & Me.Text0
    qryTest.Close
    Me.Abfrage1.Requery
   
End Sub


Klappt dein Code(wenn ich ihn eingebaut bekomme :D ) noch mit der Pass-Through? Also über ein VBA Modul?
Ich bin jetzt erstmal eine Woche weg, ich werde zwar hier reinschauen, hab aber kein Access zur Verfügung zum testen/probieren/lernen.


Nochmal vielen vielen Dank, sowohl für Code als auch Allgemeinbildung  ;)
----------------------
Mit freundlichen Grüßen

Max

Lachtaube

Bei 'ner PT-Abfrage wird die Funktion IMHO nicht greifen, weil der Abfragetext 1:1 an das DMS weitergeleitet wird. Wenn der Server (Produkt nebst Version) bekant wäre, ließe sich vielleicht ein PT-gerechter Ausdruck formulieren..
Grüße von der (⌒▽⌒)

ChickenWing

So, ich bin wieder da.

ZitatBei 'ner PT-Abfrage wird die Funktion IMHO nicht greifen, weil der Abfragetext 1:1 an das DMS weitergeleitet wird. Wenn der Server (Produkt nebst Version) bekannt wäre, ließe sich vielleicht ein PT-gerechter Ausdruck formulieren..

Ich kann mal versuchen an was dranzukommen. Lässt sich das nicht evtl. einfacher über eine 2. Abfrage lösen? Dass erst die PT ausgeführt wird und die ausgehenden Daten dann mit dem VBA von dir durchgepflügt werden? Oder übersehe ich da ein Problem?
----------------------
Mit freundlichen Grüßen

Max

ChickenWing

Habs hinbekommen, aber ziemlich unorthodox soweit ich das beurteilen kann.

Das ganze läuft jetzt über die PT Abfrage, dann eine die mir den String teilt und eine letzte die alles zusammenbaut. Aber es funktioniert und arbeitet durchaus zügig. Werde über Zeit wohl noch etwas dran arbeiten, hab aber auf jeden Fall alles erstmal so, dass es zu 99% funktioniert. Mit den Feinheiten quäle ich mich alleine rum.  :D

Nochmal vielen Dank für die Hilfestellungen  :)
----------------------
Mit freundlichen Grüßen

Max