Extracting data from QR to a form

So this may be a simple one and I am just not seeing it. My scripting isn’t the best.

I have a QR that when using a scanner brings back what looks like a string to me:
(GS1-241)782485-14(GS1-10)RX42563(GS1-37)100

I understand what the GS1’s stand for and know what data is what. I need to make a script that will separate the data after each GS1 to a text field. I have a field for each type. Basically I am trying to make this more automated. My script initially was this when I was scanning particular bar codes but using the QR would be much faster I believe.

results = event.getResults()

if results.containsKey(‘GS1-241’):
event.source.parent.getComponent(‘txtLotNumber’).text = results.get(‘GS1-241’).get(1)
if results.containsKey(‘GS1-10’):
event.source.parent.getComponent(‘txtPartNumber’).text = results.get(‘GS1-10’).get(1)
if results.containsKey(‘GS1-37’):
event.source.parent.getComponent(‘QuantityNumber’).int = event.results.get(‘GS1-37’).get(1)

Any assistance would be great. Thanks.

1 Like

It looks like you are using the Sepasoft Barcode Scanning Module, is that correct? If so, you should try something like this (untested). Make sure all of the GS1 keys you are using are enabled in the pattern configuration. Also, when posting code, encapsulate the code with triple back quotes to format it. the back quote is above the tab key.

result = event.toDict()
print result
partNo = result['GS1-241'][0]
batch = result['GS1-10'][0]
count = result['GS1-37'][0]

EDIT: I’m not sure what you mean by “more automated.” Easier to read? Get rid of the if statements? More info = better advice. Thanks.

What I mean is I have 3 fields as in the pic.
pic

When I scan the QR once, I want to auto populate those fields. The code I have basically how you have it laid out and I have the GS1 items that I need selected… I am missing something I know, but can’t remember.

print result
txtPartNumber = result['GS1-241'][0]
txtLotNumber = result['GS1-10'][0]
numQty = result['GS1-37'][0]

if 'GS1-241' in results:
 event.source.parent.getComponent('txtPartNumber').text = txtPartNumber
if 'GS1-10' in results:
 event.source.parent.getComponent('txtLotNumber').text = txtLotNumber
if 'GS1-37' in results:
 event.source.parent.getComponent('numQty').int = numQty```

Is result a dictionary, or is it a string? If it’s a string, then you need to parse it according to your ‘GS1’ delimiters.

print type(result)

will let you know for certain. I suspect it is a string. If so, something like this may be more appropriate to your application:

def parseString(stringIn, delimiters):
	########################################################
	##                                                    ##
	##  parse a delimited string and return a dictionary  ##
	##                                                    ##
	##  NOTE: Be sure the delimiter list is in the same   ##
	##        order as they appear in the string. Save    ##
	##        yourself some pain. :)                      ##
	##                                                    ##
	########################################################
	
	
	# Create a list of lists that contains the indexes of where each delimiter appears,
	# and the length of the delimiter, so we can use them to say where each field data lies.
	indexList = [[stringIn.index(delimiter), len(delimiter)] for delimiter in delimiters]

	# This is just a pointer that we'll use later to flag when the last iteration of the 
	# following loop is in play.
	last = len(indexList) - 1

	# Initialize the output dictionary.
	dictOut = {}

	# populate the output dictionary with the field data
	for index, delimiter in zip(range(len(indexList)), delimiters):
		# set the start of each field data
		start = indexList[index][0] + indexList[index][1]
		# set the end of the field data. This is treated differently if it 
		# is the last iteration.
		if index != last:
			end = indexList[index + 1][0]
		else:
			end = len(stringIn)
		# Add to the output dictionary
		dictOut[delimiter] = stringIn[start:end]
		
	return dictOut
	

fieldDelimiterList = ['(GS1-241)','(GS1-10)','(GS1-37)']

parsedData = parseString(result, fieldDelimiterList)

event.source.parent.getComponent('txtPartNumber').text = parsedData['(GS1-241)']
event.source.parent.getComponent('txtLotNumber').text = parsedData['(GS1-10)']
event.source.parent.getComponent('numQty').int = parsedData['(GS1-37)']

Sepasoft documentation isn’t great, and I have just started to use their barcode scanner component. From the little I know, it seems that it buffers the keystrokes which are then put into a dictionary. From there the result['GS1-241'][0] takes the dictionary and parses it according to the key, which is the [‘GS1-241’] part. The component has a dataset of keys and regex patterns to parse by. For GS1-241 it is

(241)(.{1,30}<<separator>>|.{1,30}$)

So is it necessary for the use your parsing function?

So tried both methods and nothing populates. However, if I click on one of the text fields and scan, then the whole string (GS1-241)782485-14(GS1-10)RC42563(GS1-37)100 shows in that one text field.

I have a feeling that my script is not running. So I tried the example that is on the SepaSoft knowledgebase(Configuring the BarcodeScanner) and it does not work either. I have to physically select the text field. I am using it on a client, not on the designer. The BarcodeScanner is enabled.

Since the scanner I am using (Symbol DS6878), has been used somewhere else, I restored it back to default just in case some custom configuration was loaded. No luck. I know the scanner works as far as input since it will fill a text field. I am going to try to find another scanner type and see what happens. But I truly feel my script is never running for the component.

No idea. :grin:

What we are not seeing yet is what leads up to the result variable. What is the event that is supposed to trigger it?

EDIT: NVM, I see what it’s doing for the event. I do want to see what comes back as a result as it’s currently set up.

I bet your preamble character is wrong. I used a Honeywell 3800 scanner, and I had to program the a different preamble (prefix) character that the default \u0002. Your scanner should have programming barcodes where you can setup the prefix character. The preamble allows for the Sepasoft barcode listener to know when to buffer the input as a barcode and not keyboard typing. Use a preamble that won’t be used on any keyboard input. The \u002 code is Unicode hexadecimal. Next configure your separator, I have a return key set for mine, which is \u000A. Also note that the scanner component does not work in designer preview, only a client Open a client, click the help menu then diagnostics. Select logging levels tab, then on PMIBarcodeController, select the level as debugging. Then go to the console tab, and scan a barcode. This should show you what it happening upon scan. Also make sure if you are using it in trial mode, that you are have trial time running.

The preamble character triggers the listener to buffer the input. The event handler is onBarcodeReceived
Below is a successful barcode buffer in the ignition debug console

13:44:35.339 [AWT-EventQueue-0] DEBUG PMIBarcodeController - ------- Resetting elapsed time: 13334. Looking for preamble of: \\u003f
13:44:35.355 [AWT-EventQueue-0] DEBUG PMIBarcodeController - ------- Preamble found: \u003f. Start buffering...
13:44:35.386 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Keyevent ID: 402, Slash, char: \u003f (?)
13:44:35.401 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Handled: true  Buffering: true  Elapsed Time: 16  buffer: 3  echo 0
13:44:35.417 [AWT-EventQueue-0] DEBUG PMIBarcodeController - -
13:44:35.417 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Keyevent ID: 402, Shift, char: \uffff (?)
13:44:35.417 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Handled: true  Buffering: true  Elapsed Time: 52  buffer: 6  echo 0
13:44:35.417 [AWT-EventQueue-0] DEBUG PMIBarcodeController - -
13:44:35.433 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Keyevent ID: 402, Q, char: \u0051 (Q)
13:44:35.433 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Handled: true  Buffering: true  Elapsed Time: 67  buffer: 7  echo 0
13:44:35.433 [AWT-EventQueue-0] DEBUG PMIBarcodeController - -
13:44:35.464 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Keyevent ID: 402, 3, char: \u0033 (3)
13:44:35.464 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Handled: true  Buffering: true  Elapsed Time: 100  buffer: 10  echo 0
13:44:35.464 [AWT-EventQueue-0] DEBUG PMIBarcodeController - -
13:44:35.480 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Keyevent ID: 402, 4, char: \u0034 (4)
13:44:35.480 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Handled: true  Buffering: true  Elapsed Time: 119  buffer: 13  echo 0
13:44:35.495 [AWT-EventQueue-0] DEBUG PMIBarcodeController - -
13:44:35.511 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Keyevent ID: 402, 7, char: \u0037 (7)
13:44:35.511 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Handled: true  Buffering: true  Elapsed Time: 140  buffer: 16  echo 0
13:44:35.511 [AWT-EventQueue-0] DEBUG PMIBarcodeController - -
13:44:35.526 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Keyevent ID: 402, 8, char: \u0038 (8)
13:44:35.526 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Handled: true  Buffering: true  Elapsed Time: 156  buffer: 19  echo 0
13:44:35.526 [AWT-EventQueue-0] DEBUG PMIBarcodeController - -
13:44:35.542 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Keyevent ID: 402, 2, char: \u0032 (2)
13:44:35.542 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Handled: true  Buffering: true  Elapsed Time: 172  buffer: 22  echo 0
13:44:35.542 [AWT-EventQueue-0] DEBUG PMIBarcodeController - -
13:44:35.558 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Keyevent ID: 402, 1, char: \u0031 (1)
13:44:35.558 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Handled: true  Buffering: true  Elapsed Time: 188  buffer: 25  echo 0
13:44:35.558 [AWT-EventQueue-0] DEBUG PMIBarcodeController - -
13:44:35.573 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Keyevent ID: 402, 0, char: \u0030 (0)
13:44:35.573 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Handled: true  Buffering: true  Elapsed Time: 207  buffer: 28  echo 0
13:44:35.573 [AWT-EventQueue-0] DEBUG PMIBarcodeController - -
13:44:35.589 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Keyevent ID: 402, Enter, char: \u000a (
)
13:44:35.589 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Handled: true  Buffering: true  Elapsed Time: 220  buffer: 31  echo 0
13:44:35.589 [AWT-EventQueue-0] DEBUG PMIBarcodeController - -
13:44:35.589 [AWT-EventQueue-0] DEBUG PMIBarcodeController - ########## Possible preamble = Keyevent ID: 402, Enter, char: \u000a (
)
13:44:35.792 [AWT-EventQueue-0] DEBUG PMIBarcodeController -  *** Input Timeout KeyEventHandler SI (readtime 200) ***
13:44:35.792 [AWT-EventQueue-0] DEBUG PMIBarcodeController -  si.buffer: [Key Pressed, Slash, ?]
 [Key Released, Slash, ?]
 [Key Pressed, Q, Q]
 [Key Released, Shift, \uFFFF]
 [Key Released, Q, Q]
 [Key Pressed, 3, 3]
 [Key Released, 3, 3]
 [Key Pressed, 4, 4]
 [Key Released, 4, 4]
 [Key Pressed, 7, 7]
 [Key Released, 7, 7]
 [Key Pressed, 8, 8]
 [Key Released, 8, 8]
 [Key Pressed, 2, 2]
 [Key Released, 2, 2]
 [Key Pressed, 1, 1]
 [Key Released, 1, 1]
 [Key Pressed, 0, 0]
 [Key Released, 0, 0]
 [Key Pressed, Enter, \n]
 [Key Released, Enter, \n]

13:44:35.792 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Barcode Scanner 1 si.Regex target ?Q3478210
  pattern: \u003f.* = found: true
13:44:35.792 [AWT-EventQueue-0] DEBUG PMIBarcodeController - Barcode Scanner 1 Decode Results: Default
13:44:35.808 [AWT-EventQueue-0] DEBUG PMIBarcodeController - value[0] = Q3478210
{u'Default': [Q3478210]}
13:44:35.823 [AWT-EventQueue-0] DEBUG PMIBarcodeController - si.buffer: 
13:44:35.823 [AWT-EventQueue-0] DEBUG PMIBarcodeController - si.echo  : 
13:44:35.823 [AWT-EventQueue-0] DEBUG PMIBarcodeController - *** End of Input Timeout, Elapsed Time: 458 
13:44:46.526 [AWT-EventQueue-0] DEBUG PMIBarcodeController - ------- Resetting elapsed time: 10699. Looking for preamble of: \\u003f

1 Like

I appreciate the info. I installed the module to play with, but my spare scanner came up AWOL. I’m going to have to bow out on the configuration side, while I’m waiting for my spare for the spare. :face_with_raised_eyebrow:

1 Like

dkhayes117, you were right. It was the preamble. I used the debug tool to figure out what the scanner was using. I tried to change it in the scanner but it would not take so now my preamble for the component is \u000a. Now the scanner triggers the script.

Now, I have an error. I’ve tried it as a dictionary and I have tried it as a string.
With a string, I tried the parsing script that JordanCClark gave me and I get back an error that says line 42 ‘result’ is not defined:

def parseString(stringIn, delimiters):
	########################################################
	##                                                    ##
	##  parse a delimited string and return a dictionary  ##
	##                                                    ##
	##  NOTE: Be sure the delimiter list is in the same   ##
	##        order as they appear in the string. Save    ##
	##        yourself some pain. :)                      ##
	##                                                    ##
	########################################################
	
	
	# Create a list of lists that contains the indexes of where each delimiter appears,
	# and the length of the delimiter, so we can use them to say where each field data lies.
	indexList = [[stringIn.index(delimiter), len(delimiter)] for delimiter in delimiters]

	# This is just a pointer that we'll use later to flag when the last iteration of the 
	# following loop is in play.
	last = len(indexList) - 1

	# Initialize the output dictionary.
	dictOut = {}

	# populate the output dictionary with the field data
	for index, delimiter in zip(range(len(indexList)), delimiters):
		# set the start of each field data
		start = indexList[index][0] + indexList[index][1]
		# set the end of the field data. This is treated differently if it 
		# is the last iteration.
		if index != last:
			end = indexList[index + 1][0]
		else:
			end = len(stringIn)
		# Add to the output dictionary
		dictOut[delimiter] = stringIn[start:end]
		
	return dictOut
	

fieldDelimiterList = ['(GS1-241)','(GS1-10)','(GS1-37)']

parsedData = parseString(result, fieldDelimiterList)

event.source.parent.getComponent('txtPartNumber').text = parsedData['(GS1-241)']
event.source.parent.getComponent('txtLotNumber').text = parsedData['(GS1-10)']
event.source.parent.getComponent('numQty').int = parsedData['(GS1-37)']

When I use dictionary with this scriptI get Line 3 KeyError: GS1-241:

print result
txtPartNumber = result['GS1-241'][0]
txtLotNumber = result['GS1-10'][0]
numQty = result['GS1-37'][0]

if 'GS1-241' in results:
 event.source.parent.getComponent('txtPartNumber').text = txtPartNumber
if 'GS1-10' in results:
 event.source.parent.getComponent('txtLotNumber').text = txtLotNumber
if 'GS1-37' in results:
 event.source.parent.getComponent('numQty').int = numQty

On the barcode component properties, beside the barcode pattern configuration, click on the dataset icon with the magnifying glass. make sure that the GS1-241, GS1-10, and GS1-37 keys are all enabled.
image
Also, you don’t need the if statements in your code if the key parses using the Regex pattern correctly.

print result
txtPartNumber = result['GS1-241'][0]
txtLotNumber = result['GS1-10'][0]
numQty = result['GS1-37'][0]

 event.source.parent.getComponent('txtPartNumber').text = txtPartNumber
 event.source.parent.getComponent('txtLotNumber').text = txtLotNumber
 event.source.parent.getComponent('numQty').int = numQty

Be sure that your variable names match up, if you’re presenting it as a string.

parsedData = parseString(whatever_variable_your_string_is, fieldDelimiterList)

Whichever method you use, this would be true. :slight_smile:

I tried that as well and no luck. Still gives me a key error.
With the string, I realized my result isn’t defined just as stated, but I am not sure how to define it.
result = ?

Do have the result = event.toDict() on the first line?

Actually, I realized that after I sent that. But now getting this error.
Traceback (most recent call last):
File “event:onBarcodeReceived”, line 43, in
File “event:onBarcodeReceived”, line 16, in parseString
AttributeError: ‘dict’ object has no attribute ‘index’

try removing the [0] from result['GS1-241'][0]

if I use that script, I still get a keyerror for gs1-241

I would get in touch with sepasoft support at this point. I’m sure there is something missing in the code somewhere. They should be able to tell you exactly how it should be.