GS1 barcode parsing
Asked Answered
D

3

11

We need to parse the GS1 datamatrix barcode which will be provided by other party. We know they are going to use GTIN(01), lot number(10), Expiration date(17), serial number (21). The problems is that barcode reader output a string, the format is like this 01076123456789001710050310AC3453G321455777. Since there is not separator and both serial number and lot number are variable length according to GS1 standard, we have trouble to identify segments. My understanding is that it seems like the best way to parse is to embed the parser in the scanning device, not from the application. But we didn't plan an embed software yet. How can I implement the parser? Any suggestions?

Derzon answered 21/8, 2014 at 15:58 Comment(0)
T
8

There should be a FNC1 character at the end of a variable-length field; so that FNC1 will appear between the G3 and the 21.

FNC1 is invisible to humans but can be detected by scanners and should be reproduced in the string reported by the scanner as the GS character (ASCII value 29). Simply send the string directly to a text file and examine the text with a hex reader. The GS character representing the barcode's FNC1 separator should be obvious.

If you can, it might be an idea to swap the sequence of the 21 field and the 10 field since you appear to be using a pure-numeric for 21. This would make the barcode produced a little shorter.

Traweek answered 21/8, 2014 at 16:13 Comment(6)
I tested 02034531200000111709112510ABCD12343710, there supposed to be a separator between 10ABCD1234 and 3710. I used ASCII encoding, and get the bytes of the string, ASCIIEncoding.GetBytes(barcodeString), it only read 38 bytes, the FNC1 is still missing in the byte stream.Derzon
The absence of the FNC1 indicates one of many things. It could be that it's missing from the label, or the scanner isn't sending it or that the software you are using isn't processing it correctly. What I would do is to take a known-good FNC1-containing barcode from the EAN manuals (I don't care what their name is this week, it's not relevant.) Try reading that code into something like notepad which should show the extra character (can't test, equipment not to hand). You could also try a routine which accepts raw bytes and displays hex - even read into cmd and create a file which will haveTraweek
a length. If you can detect that FNC1 from EAN source by one of these methods, then that indicates the reader is OK, if not, suspect the reader. If you can find the FNC1 in EAN's code but not in yours, then suspect the label-production software or equipment. If one of these simple methods can find FNC1s and you are convinced the label is correct, then suspect your (presumably) C# routine.Traweek
Thanks, Magoo. That was good suggestion. I will keep you updated.Derzon
The code I tested was from the GS1 manual, the FNC1 is visible from my iphone scanner. So I have very good reason to suspect the device. We decided to discuss investment on a more sophisticated device.Derzon
"There should be a FNC1 character at the end of a variable-length field that is not filled to maximum." The requirement for FNC1 is irrespective of whether a field is filled. The FNC1 should be applied to any "variable-length", non-terminal field. (Variable-length is a bit of a misnomer: Strictly speaking the GS1 General Specifications implicitly define a list of AIs not requiring FNC1 by listing all field that do require them and stating that all future definitions will also require them.)Abey
F
2

One way to deal with this is to program the scanner to replace FNC1 with space or another plain text character before sending it to your application. The scanner manufacturer usually provides a tool to produce programming bar codes that can do simple substitutions in the scanner. Then you can parse the data without having to handle special characters.

Frigging answered 17/8, 2016 at 18:3 Comment(1)
The transmission protocol strictly defines that FNC1 (other than in first or second character position) must be transmitted as a GS character (ASCII value 29). So a typical substitution would be to translate GS characters to something that isn't valid in GS1 AI values such as ~.Abey
A
0

the bestway is you do your code. put in your form an editbox, and adoquery, do the select to your table.

with this code it will parse the gtin, serial, expdate and batch.

for example:

01001917780231522116080557521871457989211726083110Y008179 01036647980113261726043010X3D285V21136R4EG4NMKCDN7144261780 010019177800529521137374405177714565882817260630103037011 01036647980113261726043010X3D285V21136R4EG4NM38DA7144261780 01036647980113261726043010X3D285V21136R4EG4MVV4G67144261780 01036647980113261726043010X3D285V21136R4EG4MW26VM7144261780 01036647980113261726043010X3D285V21136R4EG5CC5EV07144261780 01036647980113261726043010X3D285V21136R4EG55T1GC87144261780 01001917780231522112897347314271457989211726083110Y008179 01036647980540711725073110W3H254V21136C4CVRTEDPDM7145458484 01001917780231522118590092518371457989211726083110Y008179

use this code:

    Edit1.Text:=ADOQuery1.FieldByName('QRCode').AsString;

    GTIN:='';
    EXPDATE:='';
    BATCH:='';
    Serial:='';

    while (GTIN='') or (BATCH='') or (EXPDATE='') or (Serial='') do
      begin
        if GTIN='' then
          begin
           GTIN := copy(Edit1.Text,3,14);
           Edit1.Text:=StringReplace(Edit1.text,'01'+GTIN,'',[rfReplaceAll]);
          end;

        if copy(Edit1.Text,0,3)='714' then
          Edit1.Text:=copy(Edit1.Text,12,100);

        if (BATCH='') and (copy(Edit1.Text,0,2)='10') then
         begin
          if Pos(Delimiter, Edit1.Text)>0 then
            BATCH:=copy(Edit1.Text,3,Pos(Delimiter, Edit1.Text)-3)
          else
            BATCH:=copy(Edit1.Text,3,30);

          Edit1.Text:=StringReplace(Edit1.text,'10'+BATCH+Delimiter,'',[rfReplaceAll]);
          Edit1.Text:=StringReplace(Edit1.text,'10'+BATCH,'',[rfReplaceAll]);

         end;

         if (copy(Edit1.Text,0,2)='17') and (EXPDATE='') then
         begin
           EXPDATE := copy(Edit1.Text,3,6);
           Edit1.Text:=StringReplace(Edit1.text,'17'+EXPDATE+Delimiter,'',[rfReplaceAll]);
           Edit1.Text:=StringReplace(Edit1.text,'17'+EXPDATE,'',[rfReplaceAll]);
         end;

         if (copy(Edit1.Text,0,2)='21') and (Serial='') then
         BEGIN
           if Pos(Delimiter, Edit1.Text)>0 then
             Serial := copy(Edit1.Text,3,Pos(Delimiter, Edit1.Text)-3)
           else
             Serial := copy(Edit1.Text,3,100);

           Edit1.Text:=StringReplace(Edit1.text,'21'+Serial+Delimiter,'',[rfReplaceAll]);
           Edit1.Text:=StringReplace(Edit1.text,'21'+Serial,'',[rfReplaceAll]);
         END;
      end;
Angkor answered 20/7, 2024 at 15:48 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.