# Get Numbers from G-code

Z

#### ZigZagZak

Hello-
I created a access form/VB that changes a "G-Code" from absolute to
incrimental. This pretty much means that I have a text & numeric string that
I need to pull the numbers out of and do math with, then put them back in
there correct spots in the string.

a sample line of g-code would be like.... : G1X25.625Y-4.12I-25.432J2.658

I have a working code to do this, however depending on who/what wrote the
code, it comes in different formats. Like sometimes it doesn't have the X
value, or the Y. So on and so forth. I have handled some of this, but its
not that easy with instr() & mid() & left() formulas. I would like to have a
code that looks for the numbers directly following the constant...."X" or "Y"
and so on. Hopefully that makes sense.
The line of code I am using to find the "X" value is:
AbosX=IIf([Text0] Like "*" & "X" & "*", IIf([Text0] Like "*" & "Y" & "*",
Left(Mid([Text0], InStr([Text0], "X") + 1), InStr(Mid([Text0], InStr([Text0],
"X") + 1), "Y") - 1), Mid([Text0], InStr([Text0], "x") + 1)), "")

but a problem I just ran into is when my G-code is:
X.833I.417J-1.266
AbosX is supposed to equal ".833"
but AbosX ends up equaling "X.833I.417J-1.266"
which is obviously a problem for doing math against.

Help?
Thanks!
Zach

D

#### Damon Heron

I would use an array to place the numbers and then do your manipulations
from there.
This could be a sub ( I assumed that all of your characters are numbers or
letters, with -, ., and / added):

Dim textstring As String ' this is your GCode
Dim C As Integer
Dim ct As Integer
ct = 0
Dim ltr As Variant
Dim myNum(10) As Single
Dim num As String

For C = 1 To Len(textstring)
ltr = Asc((Mid(textstring, C, 1)))
If (ltr > 44) And (ltr < 58) Then
num = num & Chr(ltr)
Else
If num <> "" Then
myNum(ct) = CSng(num)
ct = ct + 1
num = ""
ltr = ""
End If
End If
Next C

myNum(ct) = CSng(num)' we need to pick up the last number...
'all numbers are now in an numeric array
Debug.Print myNum(0), myNum(1), myNum(2), myNum(3) ' etc

Damon

E

#### EMonk

ZigZagZak said:
Hello-
I created a access form/VB that changes a "G-Code" from absolute to
incrimental. This pretty much means that I have a text & numeric string that
I need to pull the numbers out of and do math with, then put them back in
there correct spots in the string.

a sample line of g-code would be like.... : G1X25.625Y-4.12I-25.432J2.658

This would be for a CNC application? Reference: http://en.wikipedia.org/wiki/G-code
I have a working code to do this, however depending on who/what wrote the
code, it comes in different formats. Like sometimes it doesn't have the X
value, or the Y. So on and so forth. I have handled some of this, but its
not that easy with instr() & mid() & left() formulas. I would like to have a
code that looks for the numbers directly following the constant...."X" or "Y"
and so on. Hopefully that makes sense.
The line of code I am using to find the "X" value is:
AbosX=IIf([Text0] Like "*" & "X" & "*", IIf([Text0] Like "*" & "Y" & "*",
Left(Mid([Text0], InStr([Text0], "X") + 1), InStr(Mid([Text0], InStr([Text0],
"X") + 1), "Y") - 1), Mid([Text0], InStr([Text0], "x") + 1)), "")

Ouch... that looks like a nasty thing to debug.
but a problem I just ran into is when my G-code is:
X.833I.417J-1.266
AbosX is supposed to equal ".833"
but AbosX ends up equaling "X.833I.417J-1.266"
which is obviously a problem for doing math against.

This looks like a good time to apply a regular expression.
Fortunately that's not too hard to do with Access.

First you'll need to add a reference to the RegExp functions. In the
VBA window (code view for your project) go to the Tools menu and
select References. Search down the list until you find an entry that
reads "Microsoft VBScript Regular Expressions 5.5" and tick it.

Now try something like this:

--[Start Code]--

' Initialize regular expression object
Dim re As New RegExp
re.IgnoreCase = True
re.Global = True ' returns all matching items
' General pattern for NC codes, with support for exponential notation
in values
re.Pattern = "(([A-Z])([0-9\.+-]*(E([+-]|)[0-9]*|)))"

Dim mc As MatchCollection
Set mc = re.Execute("G1X25.625Y-4.12I-25.432J2.658")

Dim m As Match, nCode As String, nValue As Double
For Each m In mc
nCode = m.SubMatches(1)
nValue = Val(m.SubMatches(2))

Select Case nCode
Case "X"
AbosX = nValue

' insert cases for other things you need to handle

End Select
Next
--[End Code]--

The above handles the sample you've given, plus variants with white-
space included. Each term in the provided G-Code string will be
extracted to a Match entry in the MatchCollection object 'mc', and
SubMatches will hold the code letter (G, X, Y, etc) in position 1,
value in position 2. Step through the code and watch the values to
get an idea of what's going on.

Hope this helps Z

#### ZigZagZak

Thanks for the Great reply EMonk!
Problem though....Your piece of the puzzle seems to work perfect. And it
does when I step through the code. However when I apply a (do/until/loop) to
it. It uses a old value in place of a null. I don't understand why it would
do that when it doesn't if I don't have it loop....below is my VB.

Do Until Me.PositionNum = Me.TotalLines
If Text0 Like "m" & "*" Or Text0 Like "(" & "*" Or Text0 = "G91" Or Text0 =
"G40" Or Text0 = "%" Or Text0 = "G70" Or Text0 = "G41" Then
If Me.Text0 Like "(" & "*" Then
Me.Text2 = Me.Text2 & vbCrLf & Me.Text0
End If

If Me.Text0 Like "M04" & "*" Then
Me.Text2 = Me.Text2 & vbCrLf & "M70"
End If
If Me.Text0 = "M03" Then
Me.Text2 = Me.Text2 & vbCrLf & "M73"
End If
If Me.Text0 = "G91" Then
Me.Text2 = Me.Text2 & vbCrLf & "G90"
End If
Else

If Me.Text0 Like "G" & "*" Or Text0 Like "X" & "*" Or Text0 Like "y" & "*"
Or Text0 Like "I" & "*" Or Text0 Like "J" & "*" Then
If Me.AbsoI <> "" Then
IncI = Nz(Me.AbsoI, 0) + Nz(IncX, 0)
End If
If Me.AbsoJ <> "" Then
IncJ = Nz(Me.AbsoJ, 0) + Nz(IncY, 0)
End If
If Me.AbsoX <> "" Then
IncX = Nz(IncX, 0) + Me.AbsoX
End If
If Me.AbsoY <> "" Then
IncY = Nz(IncY, 0) + Me.AbsoY
End If

'*******Important!!!
If Me.Text0 Like "G0" & "*" Then
Me.MoveCONST = "G0"
End If
If Me.Text0 Like "G1" & "*" Then
Me.MoveCONST = "G1"
End If
If Me.Text0 Like "G2" & "*" Then
Me.MoveCONST = "G2"
End If
If Me.Text0 Like "G3" & "*" Then
Me.MoveCONST = "G3"
End If
If Me.Text0 Like "G00" & "*" Then
Me.MoveCONST = "G0"
End If
If Me.Text0 Like "G01" & "*" Then
Me.MoveCONST = "G1"
End If
If Me.Text0 Like "G02" & "*" Then
Me.MoveCONST = "G2"
End If
If Me.Text0 Like "G03" & "*" Then
Me.MoveCONST = "G3"
End If
'******

End If

Select Case Me.MoveCONST
Case Is = "G0"
Me.Text2 = Me.Text2 & vbCrLf & Me.MoveCONST & "X" & Round(IncX, 4) & "Y" &
Round(IncY, 4)
Case Is = "G1"
Me.Text2 = Me.Text2 & vbCrLf & Me.MoveCONST & "X" & Round(IncX, 4) & "Y" &
Round(IncY, 4)
Case Is = "G2"
Me.Text2 = Me.Text2 & vbCrLf & Me.MoveCONST & "X" & Round(IncX, 4) & "Y" &
Round(IncY, 4) & "I" & Round(IncI, 4) & "J" & Round(IncJ, 4)
Case Is = "G3"
Me.Text2 = Me.Text2 & vbCrLf & Me.MoveCONST & "X" & Round(IncX, 4) & "Y" &
Round(IncY, 4) & "I" & Round(IncI, 4) & "J" & Round(IncJ, 4)
End Select
End If

DoCmd.GoToRecord , , acNext
'--[Start Code]--

' Initialize regular expression object
Dim re As New RegExp
re.IgnoreCase = True
re.Global = True ' returns all matching items
' General pattern for NC codes, with support for exponential notation in
values
re.Pattern = "(([A-Z])([0-9\.+-]*(E([+-]|)[0-9]*|)))"

Dim mc As MatchCollection
If IsNull(Text0) = True Then
'do nothing
Else

Set mc = re.Execute(Text0)
'Set mc = re.Execute("G1X25.625Y-4.12I-25.432J2.658")

Dim m As Match, nCode As String, nValue As Double
For Each m In mc
nCode = m.SubMatches(1)
nValue = Val(m.SubMatches(2))

Select Case nCode
Case "X"
AbosX = nValue
Case "Y"
AbosY = nValue
Case "I"
AbosI = nValue
Case "J"
AbosJ = nValue

' insert cases for other things you need to handle

End Select
Next
End If
'--[End Code]--
Me.AbsoX = AbosX
Me.AbsoY = AbosY
Me.AbsoI = AbosI
Me.AbsoJ = AbosJ
Me.PositionNum = Me.PositionNum + 1
'Loop
Next
'DoCmd.OpenQuery "table1 query"
Me.MoveCONST = ""
Me.FirstG = "LOST"
End Sub

EMonk said:
ZigZagZak said:
Hello-
I created a access form/VB that changes a "G-Code" from absolute to
incrimental. This pretty much means that I have a text & numeric string that
I need to pull the numbers out of and do math with, then put them back in
there correct spots in the string.

a sample line of g-code would be like.... : G1X25.625Y-4.12I-25.432J2.658

This would be for a CNC application? Reference: http://en.wikipedia.org/wiki/G-code
I have a working code to do this, however depending on who/what wrote the
code, it comes in different formats. Like sometimes it doesn't have the X
value, or the Y. So on and so forth. I have handled some of this, but its
not that easy with instr() & mid() & left() formulas. I would like to have a
code that looks for the numbers directly following the constant...."X" or "Y"
and so on. Hopefully that makes sense.
The line of code I am using to find the "X" value is:
AbosX=IIf([Text0] Like "*" & "X" & "*", IIf([Text0] Like "*" & "Y" & "*",
Left(Mid([Text0], InStr([Text0], "X") + 1), InStr(Mid([Text0], InStr([Text0],
"X") + 1), "Y") - 1), Mid([Text0], InStr([Text0], "x") + 1)), "")

Ouch... that looks like a nasty thing to debug.
but a problem I just ran into is when my G-code is:
X.833I.417J-1.266
AbosX is supposed to equal ".833"
but AbosX ends up equaling "X.833I.417J-1.266"
which is obviously a problem for doing math against.

This looks like a good time to apply a regular expression.
Fortunately that's not too hard to do with Access.

First you'll need to add a reference to the RegExp functions. In the
VBA window (code view for your project) go to the Tools menu and
select References. Search down the list until you find an entry that
reads "Microsoft VBScript Regular Expressions 5.5" and tick it.

Now try something like this:

--[Start Code]--

' Initialize regular expression object
Dim re As New RegExp
re.IgnoreCase = True
re.Global = True ' returns all matching items
' General pattern for NC codes, with support for exponential notation
in values
re.Pattern = "(([A-Z])([0-9\.+-]*(E([+-]|)[0-9]*|)))"

Dim mc As MatchCollection
Set mc = re.Execute("G1X25.625Y-4.12I-25.432J2.658")

Dim m As Match, nCode As String, nValue As Double
For Each m In mc
nCode = m.SubMatches(1)
nValue = Val(m.SubMatches(2))

Select Case nCode
Case "X"
AbosX = nValue

' insert cases for other things you need to handle

End Select
Next
--[End Code]--

The above handles the sample you've given, plus variants with white-
space included. Each term in the provided G-Code string will be
extracted to a Match entry in the MatchCollection object 'mc', and
SubMatches will hold the code letter (G, X, Y, etc) in position 1,
value in position 2. Step through the code and watch the values to
get an idea of what's going on.

Hope this helps Z

#### ZigZagZak

sorry!!! I forgot to take out something I was trying.....the "next" at the
bottom wasn't supposed to be there

The real code below:

Do Until Me.PositionNum = Me.TotalLines
If Text0 Like "m" & "*" Or Text0 Like "(" & "*" Or Text0 = "G91" Or Text0 =
"G40" Or Text0 = "%" Or Text0 = "G70" Or Text0 = "G41" Then
If Me.Text0 Like "(" & "*" Then
Me.Text2 = Me.Text2 & vbCrLf & Me.Text0
End If

If Me.Text0 Like "M04" & "*" Then
Me.Text2 = Me.Text2 & vbCrLf & "M70"
End If
If Me.Text0 = "M03" Then
Me.Text2 = Me.Text2 & vbCrLf & "M73"
End If
If Me.Text0 = "G91" Then
Me.Text2 = Me.Text2 & vbCrLf & "G90"
End If
Else

If Me.Text0 Like "G" & "*" Or Text0 Like "X" & "*" Or Text0 Like "y" & "*"
Or Text0 Like "I" & "*" Or Text0 Like "J" & "*" Then
If Me.AbsoI <> "" Then
IncI = Nz(Me.AbsoI, 0) + Nz(IncX, 0)
End If
If Me.AbsoJ <> "" Then
IncJ = Nz(Me.AbsoJ, 0) + Nz(IncY, 0)
End If
If Me.AbsoX <> "" Then
IncX = Nz(IncX, 0) + Me.AbsoX
End If
If Me.AbsoY <> "" Then
IncY = Nz(IncY, 0) + Me.AbsoY
End If

'*******Important!!!
If Me.Text0 Like "G0" & "*" Then
Me.MoveCONST = "G0"
End If
If Me.Text0 Like "G1" & "*" Then
Me.MoveCONST = "G1"
End If
If Me.Text0 Like "G2" & "*" Then
Me.MoveCONST = "G2"
End If
If Me.Text0 Like "G3" & "*" Then
Me.MoveCONST = "G3"
End If
If Me.Text0 Like "G00" & "*" Then
Me.MoveCONST = "G0"
End If
If Me.Text0 Like "G01" & "*" Then
Me.MoveCONST = "G1"
End If
If Me.Text0 Like "G02" & "*" Then
Me.MoveCONST = "G2"
End If
If Me.Text0 Like "G03" & "*" Then
Me.MoveCONST = "G3"
End If
'******

End If

Select Case Me.MoveCONST
Case Is = "G0"
Me.Text2 = Me.Text2 & vbCrLf & Me.MoveCONST & "X" & Round(IncX, 4) & "Y" &
Round(IncY, 4)
Case Is = "G1"
Me.Text2 = Me.Text2 & vbCrLf & Me.MoveCONST & "X" & Round(IncX, 4) & "Y" &
Round(IncY, 4)
Case Is = "G2"
Me.Text2 = Me.Text2 & vbCrLf & Me.MoveCONST & "X" & Round(IncX, 4) & "Y" &
Round(IncY, 4) & "I" & Round(IncI, 4) & "J" & Round(IncJ, 4)
Case Is = "G3"
Me.Text2 = Me.Text2 & vbCrLf & Me.MoveCONST & "X" & Round(IncX, 4) & "Y" &
Round(IncY, 4) & "I" & Round(IncI, 4) & "J" & Round(IncJ, 4)
End Select
End If

DoCmd.GoToRecord , , acNext
'--[Start Code]--

' Initialize regular expression object
Dim re As New RegExp
re.IgnoreCase = True
re.Global = True ' returns all matching items
' General pattern for NC codes, with support for exponential notation in
values
re.Pattern = "(([A-Z])([0-9\.+-]*(E([+-]|)[0-9]*|)))"

Dim mc As MatchCollection
If IsNull(Text0) = True Then
'do nothing
Else

Set mc = re.Execute(Text0)
'Set mc = re.Execute("G1X25.625Y-4.12I-25.432J2.658")

Dim m As Match, nCode As String, nValue As Double
For Each m In mc
nCode = m.SubMatches(1)
nValue = Val(m.SubMatches(2))

Select Case nCode
Case "X"
AbosX = nValue
Case "Y"
AbosY = nValue
Case "I"
AbosI = nValue
Case "J"
AbosJ = nValue

' insert cases for other things you need to handle

End Select
Next
End If
'--[End Code]--
Me.AbsoX = AbosX
Me.AbsoY = AbosY
Me.AbsoI = AbosI
Me.AbsoJ = AbosJ
Me.PositionNum = Me.PositionNum + 1
Loop
'DoCmd.OpenQuery "table1 query"
Me.MoveCONST = ""
Me.FirstG = "LOST"
End Sub

Z

#### ZigZagZak

Ok, I figured it out......when the code loops it doesn't reset the value of
"AbosX" to zero or null, and therefor uses the value it had before in the
case of null. So after I have it finish the calculation with it, I just ask
it to zero back out.......done!

Thanks again Emonk!!!!!
Zach