extract numbers from string in access - ms-access

I need help creating a VB code or expression in Access 2010 that will group numbers from a string where each set starts with number 6 and is always 9 characters long.
Example of strings:
Order Confirmation # 638917872-001 Partial Order/$23.74 RECEIVED
Order Confirmation - Multiple Orders - Order Confirmation#639069135-001/$297.45 - Order Confirmation#639069611-001/$32.08.
I'm using a VB code to remove all the alpha characters but that just leaves me with:
6389178720012374 from string 1 and
639069135001297456390696110013208 from string 2.
All I care about is the order number that starts with 6 and is 9 characters long. Any help would be greatly appreciated, I know there's an easier way.

VB.NET Solution:
If you just need the first 9 numbers from your resulting strings you could use String.Substring, ie:
Dim numberString as String = "6389178720012374"
Dim newString As String = numberString.Substring(0, 9)
MessageBox.Show(newString)
shows 638917872
MSDN Link
EDIT:
Maybe you would want to use a RegEx - something like this perhaps can get you started:
Private Sub Input()
Dim numberString As String = "Order Confirmation # 638917872-001 Partial Order/$23.74 RECEIVED"
Dim numberString2 As String = "Order Confirmation - Multiple Orders - Order Confirmation#639069135-001/$297.45 - Order Confirmation#639069611-001/$32.08"
GiveMeTheNumbers(numberString)
GiveMeTheNumbers(numberString2)
End Sub
Function GiveMeTheNumbers(ByVal s As String) As String
Dim m As Match = Regex.Match(s, "6\d{8}") 'get 9 digit #s begin w/6
Do While m.Success
MessageBox.Show(m.Value.ToString)
m = m.NextMatch()
Loop
Return False
End Function
Results -
MessageBox1: 638917872
MessageBox2: 639069135
MessageBox3: 639069611

You can use this function ... tested in VB.NET
Function NumOnly(ByVal s As String) As String
sRes = ""
For x As Integer = 0 To s.Length - 1
If IsNumeric(s.Substring(x, 1)) Then sRes = sRes & s.Substring(x, 1)
Next
return sRes
End Function
Little modif for ms-access

OK, here's a VBA solution. You'll need to add Microsoft VBScript Regular Expressions to your references.
This will match every 9 digit number it finds and return an array of strings with the order #s.
Function GetOrderNum(S As String) As String()
Dim oMatches As Object
Dim aMatches() As String
Dim I As Integer
Dim RE As Object
Set RE = CreateObject("vbscript.regexp")
ReDim aMatches(0)
RE.Pattern = "\d{9}"
RE.Global = True
RE.IgnoreCase = True
Set oMatches = RE.Execute(S)
If oMatches.Count <> 0 Then
ReDim aMatches(oMatches.Count)
For I = 0 To oMatches.Count - 1
aMatches(I) = oMatches(I)
Next I
End If
GetOrderNum = aMatches
End Function

Related

Extract char/numbers using Mid and Pos function

I have a string with a value of "String_test|123456"
How can I extract the numbers and characters and put them to another variable
string2 = "String_test" and int = 123456 using Mid / Pos functions.
Thanks!
Assuming you want a PowerBuilder answer rather than the ones given...
You seem to have a string with a 'string' portion and a 'number' portion delimited by a pipe character '|'. Assuming this is the normal format of the data you find the position of the pipe by:
li_pipepos = Pos(ls_string, '|')
Then the string portion is found thusly:
ls_string_portion = Mid(ls_string, 1, li_pipepos - 1)
The number portion is found:
ls_number_portion = Mid(ls_string, li_pipepos + 1 )
Then you convert the number portion into an integer (watch out since in PB an integer is not very large - i'd use a long instead) by:
ll_number = Long(ls_number_portion)
Now if your data isn't in a standardized format you will need to loop through all the characters to determine if they are a number or not and then append them to a string variable (one for numbers and another for characters) then finally convert the number string into a number.
Assuming | is the delimiter, it's easier to use Split function to do this.
Sub Test()
Const sampleStr As String = "String_test|123456"
Dim splitArr() As String
splitArr = Split(sampleStr, "|")
Dim string2 As String
string2 = splitArr(0)
Debug.Print string2 'String_test
Dim int2 As Long
int2 = splitArr(1)
Debug.Print int2 '123456
End Sub
You can modify this user defined function to suit your needs.
Public Function ReturnIntegers(cell As Range) As String
Dim stringholder As String
stringholder = cell.value
Dim pos As Integer
pos = InStr(1, stringholder, "|", vbTextCompare)
ReturnIntegers = Right(stringholder, (Len(stringholder) - pos))
End Function

MS access Query pull 9 digit number from string

I've been looking on google but cant quite find exactly what i need & using these sorts of functions is my weak spot.
Basically, from an alphanumeric string in a table, I need to pull out any 9 digit numbers. they will always start with 0. The numbers won't have any breaks within them.
I would also prefer to retrieve the 9 digits using a query. ie have the pulled number sit alone in a separate column. there will only be 1 9 digit number
I have the below, which pulls out the number, i just dont know how to limit the length with it as the string with have other things, like parts of addresses and whatnot.
PHONE: Mid([DESCRIPTION],InStrRev([DESCRIPTION]," ",InStr([DESCRIPTION],"0"))+1,InStr(InStr([DESCRIPTION],"0"),[DESCRIPTION]," ")-InStrRev([DESCRIPTION]," ",InStr([DESCRIPTION],"0")))
You can use Split for this:
Public Function StripNine(ByVal Text As String) As String
Dim Words As Variant
Dim Index As Integer
Dim Result As String
Words = Split(Text, " ")
For Index = LBound(Words) To UBound(Words)
If Len(Words(Index)) = 9 Then
If IsNumeric(Words(Index)) Then
Result = Words(Index)
Exit For
End If
End If
Next
StripNine = Result
End Function
This will run and return for an example like this:
s = "This is 1 message 00 with a 09-digit number 087654321 somewhere in the body"
? StripNine(s)
087654321
You can use the Mid() function. Like this:
Mid("Test1String", 1, 4) 'Result = "Test"
Mid("Test2String", 5, 3) 'Result = "2St"
Mid("Test3String", 7, 2) 'Result = "tr"
And if you want to eliminate the blanks you can use:
Trim(" Test4 String ") 'Result = "Test4 String"
Replace(" Test5 String ", " ", "") 'Result = "Test5String"
UPDATE:
Try this:
Dim intPostion As Integer
Dim strResult As String
intPosition = InStr(YourString, 0) 'Search for the 0
strResult = Mid(YourString, intPosition, 9) 'Extract 9 digits
If you put this in a loop (so that intPosition checks the whole string) and check if strResult has only numeric numbers you should get your result.

Convert Column To Field Order

I am importing an excel spreadsheet into access, and requesting the user to input wchich column holds a userid and phone. Now on the access form, they will be string values, like A & R
I am trying to then convert the alpha value to a number value, but when I use this syntax it is not giving appropriate results. Such as the below produces # when I would want it to produce 3 - what is the appropriate way in Access to convert Letters to Column Numbers
Sub Test()
Dim colletter As String
colletter = "C"
Debug.Print Chr(Val(colletter) + 64)
End Sub
You are really close. You are going to want to use the ASC() function which returns the ASCII value of a character. When you subtract 64, it will get you the correct column index.
Sub Test()
Dim colletter As String
colletter = "C"
Debug.Print Asc(colletter) - 64
End Sub
*EDIT: I've added some controls for multiple letters and to make sure that the letters are upper case. This does, however, limit it to only having two letters, meaning column "ZZ" is your last column, but hopefully your user doesn't have more than 702 columns. :)
Sub Test()
Dim colLetter As String
Dim colNumber As Integer
Dim multiplier As Integer
colLetter = "AB"
multiplier = 0
'If there is more than one letter, that means it's gone through the whole alphabet
If Len(colLetter) > 1 Then
multiplier = Asc(Left(UCase(colLetter), 1)) - 64
End If
colNumber = (multiplier * 26) + Asc(Right(UCase(colLetter), 1)) - 64
Debug.Print colNumber
End Sub
Here's another solution that allows any number of letters, such as "ZZZZ". As you can tell, it is quite similar to the post by #BobtimusPrime.
Public Function RowLetterToNumber(ByVal RowLetter As String) As Integer
If Len(RowLetter) > 1 Then
RowLetterToNumber = RowLetterToNumber(Mid(RowLetter, 2))
RowLetterToNumber = RowLetterToNumber + 26
Else
RowLetterToNumber = Asc(RowLetter) - 64
End If
End Function
Sorry, but can't you simply use: =COLUMN()

getting linked table path with tabledef.connect

I have been trying to get the path to a linked table. I am looping thru the tables. it works one the first loop but not on the 2nd loop. it returns "".
Ive tried several different ways, calling the table by name or by number. the code originally comes from Neville Turbit. Neville's code calls the table by name, but I could not get that to work.
Public Function GetLinkedDBName(TableName As String)
Dim tblTable As TableDef
Dim strReturn As String
Dim i As Integer
On Error GoTo Error_NoTable ' Handles table not found
'---------------------------------------------------------------
'
i = 0
On Error GoTo Error_GetLinkedDBName ' Normal error handling
For Each tblTable In db.TableDefs
If tblTable.Name = TableName Then
strReturn = tblTable.Connect
strReturn = db.TableDefs(i).Connect
Exit For
End If
i = i + 1
Next tblTable
You don't need a loop:
Public Function GetLinkedDBName(TableName As String) As String
Dim strReturn As String
On Error Resume Next ' Handles table not found
strReturn = CurrentDb.TableDefs(TableName).Connect
GetLinkedDBName = strReturn
End Function
This is my modification from Gustav's.
CurrentDb.TableDefs(TableName).Connect command will returns a string like this:
"MS Access;PWD=p455w0rd;DATABASE=D:\Database\MyDatabase.accdb"
The string above contains 3 information and parted by ";" char.
You need to split this information and iterate through it to get specific one which contain database path.
I am not sure if different version of ms access will return exact elements and with exact order of information in return string. So i compare the first 9 character with "DATABASE=" to get the index of array returns by Split command and get path name from it.
Public Function getLinkedDBName(TableName As String) As String
Dim infos, info, i As Integer 'infos and info declared as Variant
i = -1
On Error Resume Next ' Handles table not found
'split into infos array
infos = Split(CurrentDb.TableDefs(TableName).Connect, ";")
'iterate through infos to get index of array (i)
For Each info In infos
i = i + 1
If StrComp(Left(info, 9), "DATABASE=") = 0 Then Exit For
Next info
'get path name from array value and return the path name
getLinkedDBName = Right(infos(i), Len(infos(i)) - 9)
End Function

Return multiple values from a function, sub or type?

So I was wondering, how can I return multiple values from a function, sub or type in VBA?
I've got this main sub which is supposed to collect data from several functions, but a function can only return one value it seems. So how can I return multiple ones to a sub?
You might want want to rethink the structure of you application, if you really, really want one method to return multiple values.
Either break things apart, so distinct methods return distinct values, or figure out a logical grouping and build an object to hold that data that can in turn be returned.
' this is the VB6/VBA equivalent of a struct
' data, no methods
Private Type settings
root As String
path As String
name_first As String
name_last As String
overwrite_prompt As Boolean
End Type
Public Sub Main()
Dim mySettings As settings
mySettings = getSettings()
End Sub
' if you want this to be public, you're better off with a class instead of a User-Defined-Type (UDT)
Private Function getSettings() As settings
Dim sets As settings
With sets ' retrieve values here
.root = "foo"
.path = "bar"
.name_first = "Don"
.name_last = "Knuth"
.overwrite_prompt = False
End With
' return a single struct, vb6/vba-style
getSettings = sets
End Function
You could try returning a VBA Collection.
As long as you dealing with pair values, like "Version=1.31", you could store the identifier as a key ("Version") and the actual value (1.31) as the item itself.
Dim c As New Collection
Dim item as Variant
Dim key as String
key = "Version"
item = 1.31
c.Add item, key
'Then return c
Accessing the values after that it's a breeze:
c.Item("Version") 'Returns 1.31
or
c("Version") '.Item is the default member
Does it make sense?
Ideas :
Use pass by reference (ByRef)
Build a User Defined Type to hold the stuff you want to return, and return that.
Similar to 2 - build a class to represent the information returned, and return objects of that class...
You can also use a variant array as the return result to return a sequence of arbitrary values:
Function f(i As Integer, s As String) As Variant()
f = Array(i + 1, "ate my " + s, Array(1#, 2#, 3#))
End Function
Sub test()
result = f(2, "hat")
i1 = result(0)
s1 = result(1)
a1 = result(2)
End Sub
Ugly and bug prone because your caller needs to know what's being returned to use the result, but occasionally useful nonetheless.
A function returns one value, but it can "output" any number of values. A sample code:
Function Test (ByVal Input1 As Integer, ByVal Input2 As Integer, _
ByRef Output1 As Integer, ByRef Output2 As Integer) As Integer
Output1 = Input1 + Input2
Output2 = Input1 - Input2
Test = Output1 + Output2
End Function
Sub Test2()
Dim Ret As Integer, Input1 As Integer, Input2 As Integer, _
Output1 As integer, Output2 As Integer
Input1 = 1
Input2 = 2
Ret = Test(Input1, Input2, Output1, Output2)
Sheet1.Range("A1") = Ret ' 2
Sheet1.Range("A2") = Output1 ' 3
Sheet1.Range("A3") = Output2 '-1
End Sub
you can return 2 or more values to a function in VBA or any other visual basic stuff but you need to use the pointer method called Byref. See my example below. I will make a function to add and subtract 2 values say 5,6
sub Macro1
' now you call the function this way
dim o1 as integer, o2 as integer
AddSubtract 5, 6, o1, o2
msgbox o2
msgbox o1
end sub
function AddSubtract(a as integer, b as integer, ByRef sum as integer, ByRef dif as integer)
sum = a + b
dif = b - 1
end function
Not elegant, but if you don't use your method overlappingly you can also use global variables, defined by the Public statement at the beginning of your code, before the Subs.
You have to be cautious though, once you change a public value, it will be held throughout your code in all Subs and Functions.
I always approach returning more than one result from a function by always returning an ArrayList. By using an ArrayList I can return only one item, consisting of many multiple values, mixing between Strings and Integers.
Once I have the ArrayList returned in my main sub, I simply use ArrayList.Item(i).ToString where i is the index of the value I want to return from the ArrayList
An example:
Public Function Set_Database_Path()
Dim Result As ArrayList = New ArrayList
Dim fd As OpenFileDialog = New OpenFileDialog()
fd.Title = "Open File Dialog"
fd.InitialDirectory = "C:\"
fd.RestoreDirectory = True
fd.Filter = "All files (*.*)|*.*|All files (*.*)|*.*"
fd.FilterIndex = 2
fd.Multiselect = False
If fd.ShowDialog() = DialogResult.OK Then
Dim Database_Location = Path.GetFullPath(fd.FileName)
Dim Database_Connection_Var = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=""" & Database_Location & """"
Result.Add(Database_Connection_Var)
Result.Add(Database_Location)
Return (Result)
Else
Return (Nothing)
End If
End Function
And then call the Function like this:
Private Sub Main_Load()
Dim PathArray As ArrayList
PathArray = Set_Database_Path()
My.Settings.Database_Connection_String = PathArray.Item(0).ToString
My.Settings.FilePath = PathArray.Item(1).ToString
My.Settings.Save()
End Sub
you could connect all the data you need from the file to a single string, and in the excel sheet seperate it with text to column.
here is an example i did for same issue, enjoy:
Sub CP()
Dim ToolFile As String
Cells(3, 2).Select
For i = 0 To 5
r = ActiveCell.Row
ToolFile = Cells(r, 7).Value
On Error Resume Next
ActiveCell.Value = CP_getdatta(ToolFile)
'seperate data by "-"
Selection.TextToColumns Destination:=Range("C3"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, _
Semicolon:=False, Comma:=False, Space:=False, Other:=True, OtherChar _
:="-", FieldInfo:=Array(Array(1, 1), Array(2, 1)), TrailingMinusNumbers:=True
Cells(r + 1, 2).Select
Next
End Sub
Function CP_getdatta(ToolFile As String) As String
Workbooks.Open Filename:=ToolFile, UpdateLinks:=False, ReadOnly:=True
Range("A56000").Select
Selection.End(xlUp).Select
x = CStr(ActiveCell.Value)
ActiveCell.Offset(0, 20).Select
Selection.End(xlToLeft).Select
While IsNumeric(ActiveCell.Value) = False
ActiveCell.Offset(0, -1).Select
Wend
' combine data to 1 string
CP_getdatta = CStr(x & "-" & ActiveCell.Value)
ActiveWindow.Close False
End Function