Hallo Forum,
derzeit scanne ich einen Barcode [Format: (01)AB012345(02)1234567890(0123)000025]
in ein Textfeld [Textfeld1] über das Ereignis: BeforeUpdate zerlege ich den Barcode
und übergebe diesen an zwei weitere Textfelder [Textfeld2] und [Textfeld3] mit folgendem CODE
Me.Textfeld2 = Format(Mid([Textfeld1], 3, 8), ,,@@@@-@@@@")
Me.Textfeld3 = Mid([Textfeld1], 13, Instr([Textfeld1], "0123") -12)
Ist es Möglich den Barcode statt in das Textfeld1 in eine Variable zu speichern und dann zu zerlegen und an die Textfelder1 und 2 zu übergeben?
Hier der CODE von Textfeld1:
Private Sub Barcode_BeforeUpdate(Cancel As Integer)
If Not Me!Textfeld1 Like "01AB01*" Then
MsgBox "Die MaterialNr ist ungültig!" & vbCrLf & "prüfen ob die Umschalt Taste an der Tastatur aktiviert ist!" & vbCrLf & "ansonsten falsches Material gescannt...", vbInformation, "ACHTUNG"
Me.Undo
Else
Me. Textfeld2 = Format(Mid([Textfeld1], 3, 8), "@@@@-@@@@")
Me. Textfeld3 = Mid([Textfeld1], 13, InStr([Textfeld1], "0123") - 12)
End If
Me.UF1.Visible = True
End Sub[code][/code]
Gruß
Omron2003
Hallo,
textfeld1 wird nur dann gespeichert, wenn es an die Tabelle gebunden ist. Hebst du diese Bindung auf (Steuerelemeninhalt löschen), erhälst du ein ungebundenes Textfeld, mit dem du arbeiten kannst, ohne dass es gespeichert wird.
Statt im Event beforeUpdate sollte das auch "bei Änderung = change" klappen.
lg
crystal
PS: Wusste nicht, dass es in VBA auch einen LIKE-Operator gibt. Wieder was gelernt.
PPS: In deinem Code geht's etwas durcheinander mit "Barcode" und Textfeld1, oder?
PPPs: ... es wäre die Umschalt-Taste, nicht die Schaltfläche...
In irgendein Textfeld musst Du scannen, denn der Scanner wird vermutlich Tastatureingaben emulieren. Das Textfeld kann aber eine Breite und Höhe von 0 cm haben - wichtig ist nur, dass es den Fokus empfangen kann. Das Vor Aktualisierung Ereignis kannst abbrechen, in dem Cancel auf einen Wert <> 0 gesetzt wird. Ausserdem wird ein Undo benötigt, damit das Textfeld leer bleibt. Vor dem Undo solltest Du den Wert des Textfelds an eine im Formularmodul deklarierte Variable oder IMHO besser noch an eine eigene Methode zur Aufarbeitung des gescannten Codes übergeben, die dann die Restaufgabe übernimmt.
ich habe es jetzt soweit zum laufen gebracht mit einen ungebundenem Textfeld1,
leider bekomme ich bei folgendem CODE,
Me.Textfeld3 = Mid([Textfeld1], 13, InStr([Textfeld1], "0123") - 12)
einen Laufzeitfehler 5: Ungültiger Prozeduraufruf oder ungültiges Argument
Woran könnte das liegen?
Vielleicht eine blöde Idee:
Hier "Me. Textfeld3 " ist ein Leerzeichen dazwischen ....
Sorry,
das war ein Fehler von mir hier im Code,
im Orginal Code ist kein Leerzeichen vorhanden.
Gruß
Omron2003
Hallo,
Liegt wohl daran, dass
InStr([Textfeld1], "0123") - 12
einen Wert < 0 zurück gibt.
I.Ü. würde ich auch das Textfeld1 mit Me. referenzieren.
gruss ekkehard
Zeige doch einmal das Ergebnis einiger Scan-Vorgänge und passend dazu, wie die Aufteilung erfolgen soll. Ggf. Regel mit angeben.
Hallo,
Mit seinem Beispiel aus dem OP erhalte ich im Direktfenster
s="(01)AB012345(02)1234567890(0123)000025"
?Format(Mid(s, 3, 8), "@@@@-@@@@")
1)AB-0123
?Mid(s, 13, InStr(s, "0123") - 12)
Laufzeitfehler 5, wie beim TS, was IMO daran liegt
?InStr(s, "0123")-12
-5
gruss ekkehard
...
Ob da vielleicht
InStr([Textfeld1], "(0123)") - 12
helfen würde?
...
Hallo crystal,
In der Tat.
Wollte ihn nur selber drauf kommen lassen, dass die Zeichenfolge "0123" da zweimal
drinsteckt ;)
gruss ekkehard
Und wenn ich mir grad nochmal das Ergebnis angeschaut habe
Zitat(02)1234567890(
vermute ich sogar, dass
ZitatInStr([Textfeld1], "(0123)") - 13
den gewünschten Teilstring liefert.
gruss ekkehard
Hallo,
Sorry das Problem scheint am Barcode zu liegen,
denn wenn die erste Ziffer nach (02) eine 0 ist bekommen ich diesen Laufzeitfehler 5?
(01)AB012345(02)0123456789(0123)000025]
Da der hier im Forum gepostete String nicht der original(wieder etwas dazugelernt) ist war mir das mit der 0 nicht aufgefallen.
Gibt es hierfür eine Lösung?
Besten Dank im Voraus
Omron2003
Dann zeige doch mal ein Original!
der Original Code lautet:
Me.VD_Charge = Mid([Barcode_VD], 13, InStr([Barcode_VD], "3100") - 13
scanne ich diesen Barcode:
(91) RX089123 (10) 0131234567 (3100) 000180
wird der Laufzeitfehler 5 erzeugt
beim Scannen von diesem funktioniert die Übergabe.
Also nehme ich an das der Laufzeitfehler durch die vorstehenden 0 zwischen (10) und (3100) liegt
(91) RX089123 (10) 1131234567 (3100) 000180
die in Klammer stehenden Ziffern in Barcode bedeuten,
(91) = Material
(10) = Charge
(3100) = Menge
werden für meinem Zweck aber nicht Gebrauch.
Gruß
Omron2003
Hallo,
Zitatwird der Laufzeitfehler 5 erzeugt
Bei mir nicht
Zitats="(91) RX089123 (10) 0131234567 (3100) 000180"
?Format(Mid(s, 3, 8), "@@@@-@@@@")
1) R-X089
?Mid(s, 13, InStr(s, "3100") - 13)
3 (10) 0131234567 (
Allerdings halte ich die Ergebnisstrings nicht für richtig im Sinne von "wie gewünscht".
gruss ekkehard
Korrektur:
Zitat?Mid(s, 13, InStr(s, "(3100)") - 13)
3 (10) 0131234567
könnte schon eher sinnvoll sein
Man könnte auch mit einem Regulären Ausdruck den Scan zerpflücken.Sub Test()
Const CLSID_RegExp = "{3F4DACA4-160D-11D2-A8E9-00104B365C9F}"
Const Scan1$ = "(91)RX089123(10)0131234567(3100)000180"
' die Leerzeichen sind vermutlich eher Artefakte aus dem Forum
Const SCAN2$ = "(91) RX089123 (10) 0131234567(3100) 000180"
Const MUSTER$ = "\(\w*\) *(\w*) *\(\w*\) *(\w*) *\(\w*\) *(\w*)"
Dim sm
With CreateObject("new:" & CLSID_RegExp)
Scan1:
Debug.Print "SCAN1:"
.Pattern = MUSTER
If .Test(Scan1) Then
For Each sm In .Execute(Scan1)(0).SubMatches
Debug.Print sm
Next
End If
Debug.Print
Test2:
Debug.Print "SCAN2:"
If .Test(SCAN2) Then
For Each sm In .Execute(SCAN2)(0).SubMatches
Debug.Print sm
Next
End If
End With
End SubWas dann zu dieser Ausgabe im Direktbereich führt:SCAN1:
RX089123
0131234567
000180
SCAN2:
RX089123
0131234567
000180
Hallo,
leider komme ich hier nicht weiter.
Deshalb habe ich mal eine Demo .accdb im Anhang
Die mein Problem mit dem Barcode veranschaulichen sollte?
Besten Dank im Voraus
Gruß
Omron2003
Hallo,
Warum prüfst du die Werte nicht mal selber im Einzelschrittmodus?
91RX0891231001315638793100000180 enthält den Suchstring (3100)
zweimal. Da ergibt InStr den Wert 10 (1. Vorkommen), und somit -13
wieder einen negativen Wert.
Hier: 91RX0891231011315638793100000180 taucht der Begriff das
1. Mal an Stelle 23 auf (-13 = 10).
gruss ekkehard
Hallo!
Zerlege deinen Code etwas, dann kannst du besser prüfen.
Ausgangscode:
Private Sub Barcode_BeforeUpdate(Cancel As Integer)
If Not Me!Barcode Like "91RX0*" Then
MsgBox "Die MaterialNr ist ungültig!" & vbCrLf & "prüfen ob die Umschalt Schaltfläche an der Tastatur aktiviert ist!" & vbCrLf & "ansonsten falsches Material gescannt...", vbInformation, "ACHTUNG"
Me.Undo
Else
Me.Charge = Mid([Barcode], 13, InStr([Barcode], "3100") - 13)
End If
End Sub
Etwas aufgeteilt:
Private Sub Barcode_BeforeUpdate(Cancel As Integer)
If Not Me!Barcode Like "91RX0*" Then
MsgBox "Die MaterialNr ist ungültig!" & vbCrLf & "prüfen ob die Umschalt Schaltfläche an der Tastatur aktiviert ist!" & vbCrLf & "ansonsten falsches Material gescannt...", vbInformation, "ACHTUNG"
Me.Undo
Exit Sub
End If
Dim Pos3100 As Long
Pos3100 = InStr([Barcode], "3100")
If Pos3100 < 13 Then
MsgBox "3100 steht an Posistion " & Pos3100 & " das ist kleiner als 13 ... und was nun?"
Exit Sub
End If
Me.Charge = Mid([Barcode], 13, Pos3100 - 13)
'Was sagt die magische 13 eigentlich aus?
End Sub
BTW: Das sieht für mich nach einem GS1-Code aus. Wäre es dann nicht besser, den Code nach den Regeln der Application Identifier zu zerlegen?
mfg
Josef
Ja korregt, es ist ein EAN 128 Code der aus SAP stammt und sich auf Etiketen befindet die ich in Access einscanne um das Material und die Charge zu speichern.
Gruß
Omron2003
So könnte man das mit dem Regulären Ausdruck gestalten.
Hallo Josef,
ZitatBTW: Das sieht für mich nach einem GS1-Code aus. Wäre es dann nicht besser, den Code nach den Regeln der Application Identifier zu zerlegen?
Kannst du mir hierzu mehr Infos geben?
Da der Code auf dem Etikett so dargestellt wird (91)RX089123(10)1131563879(3100)000180
und nach dem scannen im Textfeld Barcode so aussieht 91RX0891231011315638793100000180
kann ich mir nicht vorstellen wie da eine Regel zum zerlegen aussehen könnte.
Besten Dank im Voraus
Omron2003
Hallo Lachtaube,
sorry da hat sich der Post wohl überschnitten,
ich schaue mir die Demo an..
So wie das aussieht handelt es sich hierbei um
den Code nach Regeln der Application Identifier zu zerlegen
was Josef meinte...
Besten Dank
Omron2003
Hallo!
ZitatDa der Code auf dem Etikett so dargestellt wird (91)RX089123(10)1131563879(3100)000180
und nach dem scannen im Textfeld Barcode so aussieht 91RX0891231011315638793100000180
Das ist durchaus üblich. ;)
Liste der Application Identifier: https://www.activebarcode.de/codes/ean128_ucc128_ai.html
oder von gs1.org: http://www.gs1.org/docs/barcodes/GS1_General_Specifications.pdf
Damit:
91 => Für firmeninterne Nutzung, alphanumerisch bis zu 30-stellig, inkl. FNC1
(91)RX089123 + CHR-Code von FNC1
=> du weißt, wann (91) endet und kannst dann den nächsten Ziffernblock auslesen.
Anm. zu FNC1 zw. 3 und der 1 müsste noch ein Zeichen sein (das wird als Text aber nicht sichtbar sein, sollte aber mit Asc(xxx) auswertbar sein.)
10 => Losnummer bzw. Chargennummer, alphanumerisch bis zu 20-stellig, inkl FNC1
(10)1131563870
bleibt noch
3100 => Nettogewicht in Kilogramm, numerisch 6-stellig
Wenn der Barcode bei dir immer in der Reihenfolge (91)..(10)...(3100) vorkommt, kannst du den relativ einfach zerlegen.
Wenn du den Text mit dem FNC1-Zeichen splittest, hast du bereits nach den AI unterteilt, da 91 und 10 einen FNC1 erfordern (falls es ein GS1-Code128 ist).
Hättest du noch AI mit fixen Längen (also ohne FNC1) müsstest du diese noch extra behandeln.
/edit: unter http://www.aidecoder.com/ oder https://online-barcode-reader.inliteresearch.com/ kannst du ein Bild des Barcodes auswerten lassen.
mfg
Josef
Hallo zusammen,
ich möchte mich nochmals recht Herzlichst für die Unterstützung bedanken.
Ich werde mich nochmals näher mit der Thematik Barcode und Access befassen,
da warscheinlich im laufer der Zeit noch weitere Fragen auftreten werden.
@Lachtaube
Ich hätte da noch eine Frage zu dem Beitrag "mit regulären Ausdruck gestallten"
Den Code habe ich nun in meine Anwendung übernommen und er funktioniert einwandfrei wenn die Charge 10 Stellen hat.
Allerdings habe ich ein Material bei dem die Charge nur 8 Stellen hat, wenn ich hier den Code anwende bekomme ich die Meldung "Keine Übereinstimmung". Ich dacht nun wenn ich den Wert in der folgender Codezeile von 10 auf 8 ändere müsste es gehen. Tut es aber nicht.
ZitatCinst MUSTER$ = "91" (\w{8})10[\w{10})3100(\w{6})"
habe ich hier etwas übersehen? Oder liegt es an der Charge (LL6-08VB) weil diese nicht nur aus Zahlen besteht?
Besten Dank im Voraus
Omron2003
Wenn 8 bis 10 Stellen möglich sind, sollte das Muster 91(\w{8})10(\w{8,10})3100(\w{6}) lauten.
Übersetz: der Scan muss mit 91 beginnen. Das erste Klammerpaar fängt den ersten Submatch ein, welcher aus exakt 8 Zeichen (alphanumerisch nebst Unterstrich) bestehen muss. Danach muss zwingend die 10 vorhanden sein. Jetzt kommt der zweite Submatch innerhalb der Klammern, der in der modifizierten Form 8 bis 10 alphanumerische Zeichen erwartet. Es folgt die 3100, der den letzte Submatch mit zwingend 6 alphanumerischen Zeichen folgt.
Reguläre Ausdrücke (https://de.wikipedia.org/wiki/Regul%C3%A4rer_Ausdruck) können recht praktisch beim Parsen und Testen von Gültigkeiten sein, wenn exakte(n) Regel(n) bekannt sind.
Ich will aber nicht verschweigen, dass sie je nach Textumfang und Komplexität des Musters auch viel Rechenkapazität beanspruchen.
Hallo!
Falls das ein GS1-Code ist, müsste der AI 10 mit einem FNC1 abgeschlossen sein. Damit fällt dann jede annähernde Ermittlung weg, da die Text-Blöcke exakt definiert sind.
Ob ein FNC1 enthalten ist, kann man prüfen, wenn man den echten Barcode über einen Scanner erhält. In diesem Text würde ich nachsehen, welche Zeichen (Byte-weise) vom Scanner geliefert werden. Es könnten nämlich mehr sein, als man im Textfeld sieht.
mfg
Josef
dann hab ich schon das erste Problem,
die Chargen enthalten nicht nur alphanumerische Zeichen.
Es können sich auch - und _ in der Charge befinden..
Gruß
Omron2003
Hallo Josef P.
ich habe das Bild des Barcodes mal auswerten lassen,
dabei kam folgendes Ergebnis heraus (siehe Bild im Anhang)
mfg
Omron 2003
Das lässt sich Alles gestalten, wenn nur die exakten Regeln bekannt sind. Der Unterstrich wird ja bereits abgedeckt. Zusätzlich mit Bindestrich käme dieses Muster zur Anwendung:
91(\w{8})10([\w-]{8,10})3100(\w{6})
Hallo!
Ich nehme an, das {GS} das FNC1-Zeichen symbolisiert.
Gib bitte einmal alle Zeichen des Barcodes als ASC-Wert aus.
Prinzip:
dim BC as String
dim i as long
BC = me.DeinTextfeldInDasDerBarcodeEingelesenWurde.Value
debug.print "Länge:", Len(BC)
Debug.Print "ASC-Werte:",
for i = 1 to len(BC)
Debug.print Asc(mid(BC, i, 1)),
next
debug.print
Vielleicht siehst du dann den zu suchenden ASC-Wert des FNC1-Zeichens.
mfg
Josef
Hallo Josef P.,
anbei das Debug-Ergebnis deines Codes:
Länge: 30
ASC-Wert: 57 49 82 88 48 52 50 49 53 49 49 48 76 76 54 45 48 56 86 66 51 49 48 48 48 48 48 48 50 53
mfg
Omron2003
hallo
wie es ausschaut steht in deinem Textfeld der Barcode ohne FNC1/GS-Zeichen, wurde wahrscheinlich von deiner scannersoftware automatisch entfernt.
@Lachtaube
es funktioniert bestens mit dem regulären Ausdruck,
ist es hier auch Möglich bei einem Ereignis (Textfeld Vor Aktualisieren) mehrere Regeln einzubinden?
91(\w{8})10([\w-]{8,10})3100(\w{6})
91(\w{8})10([\w-]{10})
Besten Dank im Voraus
Omron2003
Das geht auch - es gibt dann natürlich nur 2 SubMatches. If .Test(DerText) Then
'...
Else
.Pattern = ZweitesMuster
If .Test(DerText) Then
'zweites Muster passt
'weiter wie zuvor
irgendwie mache ich was falsch!
Bekomme die Meldung Fehler beim Kompilieren:
Else ohne If
ZitatConst CLSID_RegExp = "{3F4DACA4-160D-11D2-A8E9-00104B365C9F}"
Const MUSTER$ = "91(\w{8})10(\w{10})3100(\w{6})"
Const MUSTER1$ = "91(\w{8})10(\w{7})"
With CreateObject("new:" & CLSID_RegExp)
.Pattern = MUSTER
If .Test(Me.Barcode) Then
With .Execute(Me.Barcode)(0)
If .Submatches.Count = 3 Then
Me.Material = .Submatches(0)
Me.Charge = .Submatches(1)
Me.Menge = .Submatches(2)
End If
Else
.Pattern = MUSTER1
If .Test(Me.Barcode) Then
With .Execute(Me.Barcode)(0)
If .Submatches.Count = 3 Then
Me.Material = .Submatches(0)
Me.Charge = .Submatches(1)
End If
End With
Else
MsgBox "Keineübereinstimmung"
End If
End With
End Sub
gelöscht
Ungetestet: Const CLSID_RegExp = "{3F4DACA4-160D-11D2-A8E9-00104B365C9F}"
Const MUSTER$ = "91(\w{8})10(\w{10})3100(\w{6})"
Const MUSTER1$ = "91(\w{8})10(\w{7})"
With CreateObject("new:" & CLSID_RegExp)
.Pattern = MUSTER
If .Test(Me.Barcode) Then
With .Execute(Me.Barcode)(0)
If .Submatches.Count = 3 Then
Me.Material = .Submatches(0)
Me.Charge = .Submatches(1)
Me.Menge = .Submatches(2)
End If
End With
Else
.Pattern = MUSTER1
If .Test(Me.Barcode) Then
With .Execute(Me.Barcode)(0)
If .Submatches.Count = 2 Then
Me.Material = .Submatches(0)
Me.Charge = .Submatches(1)
End If
End With
Else
MsgBox "Keineübereinstimmung"
End If
End If
End With
da habe ich im oberen Codeanschnitt ein
ZitatEnd With
vergessen.
Jetzt funktioniert es!
Nochmals besten Dank für die kompetente Hilfe
PS.
Eine Frage hätte ich noch,
wie müsste ich in einen Muster das Leerzeichen deklarieren?
Ein beliebiges Wortzeichen ist ja " \w " und bei einmel Leerzeichen?
Gruß
Omron2003
so das mit dem Leerzeichen habe ich nun mit dem Ausdruck \2 hinbekommen,
ZitatConst MUSTER$ =AB.([\w.]{2})([\s\w]{4})]
nur habe ich aber im Ausgabe Textfeld ein Leerzeichen!
Gibt es eine Möglichkeit das diese Leerzeichen nicht mitübernommen wird?
Gruß
Omron2003
mit Trim habe ich das unnötige Leerzeichen entfernt bekommen,
ob das die optimale Lösung ist weis ich nicht.
Aber es scheint zu funktionieren.
ZitatConst CLSID_RegExp = "{3F4DACA4-160D-11D2-A8E9-00104B365C9F}"
Const MUSTER$ = "AB.([\w.]{2})([\s\w]{4})([\s\w]{4})"
With CreateObject("new:" & CLSID_RegExp)
.Pattern = MUSTER
If .Test(Me.ZerlegWert) Then
With .Execute(Me.ZerlegWert)(0)
If .Submatches.Count = 3 Then
Me.Wert1 = .Submatches(0)
Me.Wert1 = Trim(Me.Wert1)
Me.Wert2 = .Submatches(1)
Me.Wert2 = Trim(Me.Wert2)
Me.Wert3 = .Submatches(2)
Me.Wert3 = Trim(Me.Wert3)
End If
End With
Else
MsgBox "Keineübereinstimmung"
End If
Ein einzelnes Leerzeichen kann ganz einfach als Literal " " (ohne die Anführungszeichen) verwendet werden. Dahinter kannst Du dann auch einen Quantor setzen. * für keinen bis unendlich viele, + für einen bis unendlich viele, ? kein- bis einmal, {x} exakt x-mal, {x,} mindestens x-mal, {x,y} zwischen x- und y-mal, {0,x} kein- bis x-mal. Du kannst natürlich auch mehr als ein Leerzeichen angeben ohne einen Quantor zu verwenden - dann muss der Text aber exakt für einen Treffer passen. Das Gesagte trifft eigentlich auf alle Zeichen zu. Zeichen, die z. Bsp. für die Deklaration als Quantor verwendet werden, das Escape-Zeichen /, Zeichen für Satz-Anfang ^ oder Ende $, jegliche Klammern, der Punkt müssen durch ein Escape-Zeichen als Literal gekennzeichnet werden. Wenn man die Sache dann in etwa verstanden hat, können die Regexen richtig Spaß machen. Im Internet finden sich auch viele OL-Tools, um seine Ausdrücke testen zu können.