Extracting barcode data using VBA - excel

I need help. I developed an Excel sheet that as I scan an employee barcode it will extract the base-32 code information so I can get the employee ID number, first name and last name using different formulas. Excel Sheet
The only problem is the formulas to extract this data is different based on how the code starts out as seen in the Excel Sheet. I can use the IFS formula in Excel on O365 but all of our agencies use the standard desktop version of Excel.
My question; is there a way to code out in VBA that when an ID is scanned, regardless of what the scanned code starts with, that it will perform the needed formula to extract the three items I need which is ID, first name and last name? Below are the formulas I use:
Scan starting with "M"
Base-32 =MID(A2,2,7)
First Name =PROPER(MID(A2,17,20))
Last Name =PROPER(MID(A2,38,20))
Scan Starting with "N"
Base-32 =MID(A3,9,7)
First Name =PROPER(MID(A3,16,20))
Last Name =PROPER(MID(A3,36,26))
Scan Starting with "C"
Base -32 =MID(A4,8,7)
First Name =PROPER(MID(A4,15,20))
Last Name =PROPER(MID(A4,35,20))
ID NUMBER
The ID number for each of them is calculated the same (based on the cell the scan goes in to) using:
=IF(C2="","0",SUMPRODUCT(POWER(32,LEN(C2)-ROW(INDIRECT("1:"&LEN(C2)))),(CODE(UPPER(MID(C2,ROW(INDIRECT("1:"&LEN(C2))),1)))-48*(CODE(MID(C2,ROW(INDIRECT("1:"&LEN(C2))),1))<58)-55*(CODE(MID(C2,ROW(INDIRECT("1:"&LEN(C2))),1))>64))))
Thank you in advance to anyone that can help.

Not sure if this is exactly in line with your requirements, but the following UDF could be used to retrieve your data:
Function GetData(inp As String, grp As Long) As String
With CreateObject("VBScript.RegExp")
.Pattern = "^(?:M|N.{7}|C.{6})(.{7})\S*([A-Z][a-z]+)\s*(\S+)"
If .Test(inp) Then
GetData = .Execute(inp)(0).Submatches(grp - 1)
Else
GetData = "No Data Found"
End If
End With
End Function
Here is an online demo how the pattern works. It would match:
^ - Start line anchor.
(?:M|N.{7}|C.{6}) - A non-capture group to either capture a literal 'M', or a literal 'N' followed by 7 characters other than newline, or a literal 'C' followed by 6 of those characters.
(.{7} - Then a 1st capture group of 7 characters to mimic the MID() functionality, capturing the Base-32 code.
\S* - 0+ (Greedy) non-whitespace characters, upto:
([A-Z][a-z]+) - A 2nd capture group to capture the lastname through a single uppercase alphachar and 1+ (Greedy) lowercase ones.
\s* - 0+ (Greedy) whitespace characters upto:
(\S+) - A 3rd capture group to catch the first name through 1+ (Greedy) non-whitespace characters.
You'd call this function in your sheet through =GetData(A1,1) to get the 'Base-32' code and use integer 2 to get the last name and a 3 to get the first name. I hope that helped a bit.

Related

Excel VBA RegEx expressions not always working correctly

I used the feedback from this post to construct the following regex expression in Excel VBA:
With myRegEx
'allow numbers, alphabetic characters, ".,?&?|"
.Pattern = "[^\x30-\x39\x61-\x7A\\x2E\x21\x26]+"
'from Space to to Tilde in the assci tablet
.Pattern = "[^\x20-\x7E]+"
'match all cases not first occurances
'.Global = True
End With
take the value from the cell, everything which is not between hex32 and hex 7E is removed.
wsData.Range("A1") = myRegEx.Replace(wsData.Range("A1").Value, " ")
of course I iterate through my collection but for the sake of the example I removed the rest of the code.
The code as such works fine it will remove all non printable ASCII characters BUT if you have a large string in a cell, let's say 1500 characters, the algorithm will not remove it. It will also not throw an error. So it just does not do anything and you are not aware of it. I have no idea how to force the RegEx on the entire cell contents and what the maximum number of characters is which the RegEx supports?
I know it is a bit odd of a question but I would like to find out how I can force the regex to do a check on the entire cell contents.
many thanks in advance

Splitting very large string separated with comma and i need to split 50 items only per row

im having very big string on 1st row.so 1st row contains lots of items with comma like below
12345,54322,44444,222222222,444444,121,333,44444,........
I just need to split this till 50 items in every row. lets assume there are 700 items separated with comma and I want to keep till 50 items only in 1st row and then next 50 in 2nd row and so on.
I tried with the below code which splits till 50 for sure but im not sure if this will works going forward. so need help on this
OutData = Split(InpData, ",")(50)
MsgBox OutData
You can do this in many more ways, but one would be to replace every nth comma. For example through Regular Expressions:
Sub Test()
Dim s As String: s = "1,2,3,4,5,6,7,8,9,10,11"
Dim n As Long: n = 2
Dim arr() As String
With CreateObject("vbscript.regexp")
.Global = True
.Pattern = "([^,]*(?:,[^,]*){" & n - 1 & "}),"
arr = Split(.Replace(s, "$1|"), "|")
End With
End Sub
The pattern used means:
( - Open 1st capture group;
[^,]* - Match 0+ (Greedy) characters other than comma;
(?: - Open a nested non-capture group;
,[^,]* - Match a comma and again 0+ characters other than comma;
){1} - Close the non-capture group and match n-1 times (1 time in the given example);
), - Close the capture group and match a literal comma.
Replace every match with the content of the 1st capture group and a character you know is not in the full string so we can split on that character. See an online demo
I suppose you can do whatever you like with the resulting array. You probably want to transpose it into the worksheet.

MS Excel Forumla assistance

I have a cell I need to split into 2 cells.
Data Sample: Note: All Cells are formatted as TEXT
"3851v61_18.005_ Have the anchors for all suspended scaffolding system suspension lines and separate vertical lifelines been verified? "
Data Sample 2: Parent_ID
Steps:
Need to check to see if the cell value starts with number.
Also, If it contains a special character ("_") if may have more than 1.
Display cell #1 = just the ID number containing the underscore(s).
Display cell #2 - Just the text right of the underscore. However, if the original cell only starts with Alpha characters then display the actual value. ie. Parent_Id
Strip off any erroneous underscores left hanging.
Expected results:
Cell #:
"3851v61_18.005" (ID Number portion of the Text)
"Have the anchors for all suspended scaffolding system suspension lines and separate vertical lifelines been verified?
This is what I have so far: (If it does not start with a number, then return the value of the cell, else continue with the equation)
`=`IF(NUMBERVALUE(LEFT(C321,1))>=1,IFERROR(LEFT(C321, FIND("_",C321)-1), C321),FALSE)`
=IFERROR(RIGHT(C321,LEN(C321)-FIND("_",C321)), C321)`
If the Underscore count is more than one need to include it in the entire number and strip off the text after the last underscore in Cell 1. At the same for the right of the Underscore to display the text after underscore in Cell 2.
Thank you for any assistances offered.
I think I understand but am not 100% sure.
Try something like the below to get the full string (if it starts with something that isn't a number) or the string up to the last underscore (if it does start with a number):
=IF(NOT(ISNUMBER(NUMBERVALUE(LEFT($D1,1)))), $D1,
LEFT($D1, FIND("!!!", SUBSTITUTE($D1, "_", "!!!",
LEN($D1)-LEN(SUBSTITUTE($D1, "_", ""))))-1))
Then in a similar fashion try something like the below to get the full string (if it starts with something that isn't a number) or the string to right of the last underscore (if it does start with a number):
=IF(NOT(ISNUMBER(NUMBERVALUE(LEFT($D1,1)))), $D1,
RIGHT($D1, LEN($D1)-FIND("!!!", SUBSTITUTE($D1, "_", "!!!",
LEN($D1)-LEN(SUBSTITUTE($D1, "_", ""))))))
For example:

Remove next substring from charter on last position in Excel

I have Excel sheet which contains data similar to
Addresses
xyz,abc,olk
opn,opk,prt
we-ylj,tyf,uyfas
oiui,ytfy,tydry - We also work in bla,bla,bla
ytfyt,tyfyt,ghfyt
i-hgsd,gsdf-hgd,sdgh,- We also work in xxx,yy,zzz
ytsfgh,gfasdg,tydsfyt
I want to remove all substring which is next to the character "-" only if it's in the last position.
Result should be like
xyz,abc,olk
opn,opk,prt
we-ylj,tyf,uyfas
oiui,ytfy,tydry
ytfyt,tyfyt,ghfyt i-hgsd,gsdf-hgd,sdgh
ytsfgh,gfasdg,tydsfyt
I tried with =Substitute function but unable to replace data because of the last substring separated from "-" is not similar.
Going by your specifications, I would use two columns just so it's not a very long formula:
In B1:
=IFERROR(FIND(CHAR(1),SUBSTITUTE(A1,"-",CHAR(1),LEN(A1)-LEN(SUBSTITUTE(A1,"-",""))))-1,LEN(A1))
This gets the position of the last - or the full text length.
Then in C1:
=LEFT(A1,IF(FIND(",",A1)<B1,B1,LEN(A1)))
This checks if there's a , before the last -. If there is no ,, then the full text is taken.
EDIT: I only now noticed your edited comment. If it's just everything after - We, then I would use this:
=TRIM(LEFT(A1,IFERROR(FIND("- We",A1)-2,LEN(A1))))

Excel replace characters in string before and after 'x'

Hello I have a column with strings (names of products) in it.
Now these are formatted as Name LenghtxWidth, example Green box 20x30. Now I need to change the 20 with the 30 in this example so I get Green box 30x20, any ideas how I can achieve this?
Thanks
Here is both a formula solution, as well as a VBA solution using Regular Expressions:
Formula
=LEFT(A1,FIND(TRIM(RIGHT(SUBSTITUTE(A1," ",REPT(" ",99)),99)),A1)-1)&
MID(TRIM(RIGHT(SUBSTITUTE(A1," ",REPT(" ",99)),99)),SEARCH("x",TRIM(RIGHT(SUBSTITUTE(A1," ",REPT(" ",99)),99)))+1,99)&
"x"&
LEFT(TRIM(RIGHT(SUBSTITUTE(A1," ",REPT(" ",99)),99)),SEARCH("x",TRIM(RIGHT(SUBSTITUTE(A1," ",REPT(" ",99)),99)))-1)
UDF
Option Explicit
Function RevWL(S As String)
Dim RE As Object
Const sPat As String = "(\d+.?\d*)x(\d+.?\d*)"
'If L or W might start with a decimal point, and not a digit,
'Then change sPat to: (\d*.?\d+)x(\d*.?\d+)
Set RE = CreateObject("vbscript.regexp")
With RE
.Global = True
.ignorecase = True
.Pattern = sPat
RevWL = .Replace(S, "$2x$1")
End With
End Function
Here is an example of the kinds of data I tested with:
The Formula works by looking at the last space-separated substring which would be LxW, then reversing the portion after and before the x, then concatenating everything back together.
The regex pattern captures the two numbers (could be integers or decimals, so long as the start with an integer -- although that could be changed if needed), and reversing them.
Here is a more detailed explanation of the regex (and the replacement string) with links to a tutorial:
(\d+.?\d*)x(\d+.?\d*)
(\d+.?\d*)x(\d+.?\d*)
Options: Case insensitive; ^$ don’t match at line breaks
Match the regex below and capture its match into backreference number 1 (\d+.?\d*)
Match a single character that is a “digit” \d+
Between one and unlimited times, as many times as possible, giving back as needed (greedy) +
Match any single character that is NOT a line break character .?
Between zero and one times, as many times as possible, giving back as needed (greedy) ?
Match a single character that is a “digit” \d*
Between zero and unlimited times, as many times as possible, giving back as needed (greedy) *
Match the character “x” literally x
Match the regex below and capture its match into backreference number 2 (\d+.?\d*)
Match a single character that is a “digit” \d+
Between one and unlimited times, as many times as possible, giving back as needed (greedy) +
Match any single character that is NOT a line break character .?
Between zero and one times, as many times as possible, giving back as needed (greedy) ?
Match a single character that is a “digit” \d*
Between zero and unlimited times, as many times as possible, giving back as needed (greedy) *
$2x$1
Insert the text that was last matched by capturing group number 2 $2
Insert the character “x” literally x
Insert the text that was last matched by capturing group number 1 $1
Created with RegexBuddy
Here is a VBA solution that will work for you:
Option Explicit
Function Switch(r As Range) As String
Dim measurement As String
Dim firstPart As String
Dim secondPart As String
measurement = Right(r, Len(r) - InStrRev(r, " "))
secondPart = Right(measurement, Len(measurement) - InStr(1, measurement, "x"))
firstPart = Left(measurement, InStr(1, measurement, "x") - 1)
Switch = Left(r, InStrRev(r, " ") - 1) & " " & secondPart & "x" & firstPart
End Function
You can paste this in a regular module in the VBE (Visual Basic Editor) and use it as a regular function/formula. If your value is in cell A1 then type =Switch(A1) in cell B1. Hope it helps!
Ok, so it is really easier to use VBA, but if you want only some formulas you can use some columns to split your text and then concatenate your cells.
Here is a little example:
Of course B1-4 are optional. It is here only to have something more readable, but you can do use only one formula
=CONCATENATE(LEFT(A1, SEARCH(" ",A1,1)-1)," ",RIGHT(RIGHT(A1,LEN(A1)-SEARCH(" ",A1,1)),LEN(RIGHT(A1,LEN(A1)-SEARCH(" ",A1,1)))-SEARCH("x",RIGHT(A1,LEN(A1)-SEARCH(" ",A1,1)),1)),"x",LEFT(RIGHT(A1,LEN(A1)-SEARCH(" ",A1,1)), SEARCH("x",RIGHT(A1,LEN(A1)-SEARCH(" ",A1,1)),1)-1))
If you have several spaces in your names, you can use this formula that will search the last space in the text
=CONCATENATE(LEFT(A1, SEARCH("^^",SUBSTITUTE(A1," ","^^",LEN(A1)-LEN(SUBSTITUTE(A1," ",""))))-1)," ",RIGHT(RIGHT(A1,LEN(A1)-SEARCH("^^",SUBSTITUTE(A1," ","^^",LEN(A1)-LEN(SUBSTITUTE(A1," ",""))))),LEN(RIGHT(A1,LEN(A1)-SEARCH("^^",SUBSTITUTE(A1," ","^^",LEN(A1)-LEN(SUBSTITUTE(A1," ",""))))))-SEARCH("x",RIGHT(A1,LEN(A1)-SEARCH("^^",SUBSTITUTE(A1," ","^^",LEN(A1)-LEN(SUBSTITUTE(A1," ",""))))),1)),"x",LEFT(RIGHT(A1,LEN(A1)-SEARCH("^^",SUBSTITUTE(A1," ","^^",LEN(A1)-LEN(SUBSTITUTE(A1," ",""))))), SEARCH("x",RIGHT(A1,LEN(A1)-SEARCH("^^",SUBSTITUTE(A1," ","^^",LEN(A1)-LEN(SUBSTITUTE(A1," ",""))))),1)-1))

Resources