Query to parse a field and display it - ms-access

I have a table with values
Errors:
X_11;SR_4;D_11;SR_2
SR_4;T_22
E_18; E_28; SR_3;
E_28; SR_3;
SR_2;SR_4
I need to put in a query to parse the values so that anything with SR comes up so I do like "*SR*" but in the output I need to display only this:
Errors:
SR_4;SR_2
SR_4
SR_3
SR_3
SR_2;SR_4
I would like this in query with many fields other than this one ... instead of VBA. I am using MS Access 2010, I am guessing some type of parsing with each field being separated with ";" that will only capture SR ones?

I think regular expressions might be a way to go.
In VBA, you need to enable the reference to "Microsoft VBScript Regular Expressions 5.5". This question and its accepted answer has a detailed descrpition on what are Regular Expressions and how to enable them in your project (it's for Excel, but for Access is the same route).
Once you have the reference enabled, this little function will give you a "clean" string:
Public Function filterString(str As String)
Dim re As RegExp, obj As Object, x As Variant, first As Boolean
Set re = New RegExp
With re
.Global = True
.IgnoreCase = True
.MultiLine = False
.Pattern = "SR_[0-9]" ' This will match the string "SR_"
' followed by a digit
End With
filterString = ""
first = True
If re.Test(str) Then
Set obj = re.Execute(str)
For Each x In obj
If first Then
first = False
Else
filterString = filterString & ";"
End If
filterString = filterString & x
Next x
End If
End Function
If you test it you'll see that the result is:
filterString("X_11;SR_4;D_11;SR_2")
SR_4;SR_2
which is the result you want.
Now, a simple select query will give you what you need:
select filterString([Errors]) as err
from [yourTable]
where [yourTable].[Errors] like '*sr*'
Hope this helps

I think you can get what you need by splitting your input string into an array and then using the Filter function to create a second array which includes only the SR_ matches from the first array. Finally Join the second array to produce your output string which contains the matches.
Public Function filterString(ByVal pInput As String) As String
Dim array1() As String
Dim array2() As String
array1 = Split(Replace(pInput, " ", vbNullString), ";")
array2 = Filter(array1, "SR_")
filterString = Join(array2, ";")
End Function
Compared to a regular expression approach, this function is more concise. I find the logic simpler. And it does not require setting a reference.
Notice also it will accommodate SR codes which include more than a single digit (in case that eventually becomes a requirement). For example:
? filterString("X_11;SR_4;D_11;SR_234")
SR_4;SR_234
You could use that function in a query in the same way #Barranka suggested:
SELECT filterString(y.Errors) AS sr_codes
FROM [yourTable] AS y
WHERE y.Errors Like '*sr*';

Related

Function to extract a string between the 2nd and 3rd comma

I am looking for a function that will extract all the information between the 2nd and 3rd comma.
[DropOffAddress] = "Hotel, 1234 Johnson St, Minneapolis, MN 55449"
I am looking to extract just "Minneapolis" from the string above.
If it is less complicated, just extracting "Minneapolis, MN 55449" is workable.
I am using a query to display the information and I know the info I will always be between the second and third comma in the field [DropOffAddress]
Thanks
You can in VBA code use this:
dim strResult as string
strResult = split(strSourceString,",")(2)
So split is zero based, and hence "2" will get us the 3rd token out of the string delimited by ",".
You can't however use VBA split() function in sql query, but you can use it in code as per above.
If you need this in a query?
Then in a standard code module, then place this function.
Public Function MySplit2(v As Variant, ix As Integer) As String
MySplit = ""
If IsNull(v) Then Exit Function
If v = "" Then Exit Function
Dim vBuf As Variant
vBuf = Split(v, "|")
If ix > UBound(vBuf) Then Exit Function
MySplit = vBuf(ix)
End Function
Now, in a sql query, say one column was UserName (first name,LastName)
SELECT id, MySplit([UserName],0) as FirstName,
MySplit([UserName],1) as LastName, City, State from tblCustomers

Extracting results from an API call with a VBA function

I'm just starting to work with JSON in one of my macros. I'm able to send a call to an API service and it returns results. The service has been set up to return something like 25 fields (?). I don't need all of the fields, just some of them. The macro uses VBA.
I'm able to write the results to a specific worksheet with the following code:
For Each result In jsonObject
With Sheets("Sheet1")
.Cells(r, 5).Value = result("firstName")
.Cells(r, 6).Value = result("lastName")
.Cells(r, 9).Value = result("userCodeInfo")("userCode")
.Cells(r, 10).Value = result("userCodeInfo")("previousUserCode")
.Cells(r, 28).Value = result("saleType")
.Cells(r, 29).Value = result("cost")
End With
Next
Later, in the code, a decision point needs to use to one of the fields in the results. I'm trying to use a function to return that field value:
Public Function APIUnitData_Read(MyField As String)
Dim JSONConverter As New clsJSONParser
Set jsonObject = JSONConverter.ParseJson(UnitResp)
For Each result In jsonObject
APIUnitData_Read = result(MyField)
Next
End Function
The function works well when the field is a "non-grouped" field, e.g., "firstName, "lastName", etc.
vDecPt = API.APIUnitData_Read("firstName")
It doesn't work (or at least I haven't gotten it to work with the "grouped" fields; e.g., ("userCodeInfo")("userCode") and ("userCodeInfo")("previousUserCode").
vDecPt = API.APIUnitData_Read("userCodeInfo")("PreviousUseCode")
I'm guessing I don't have the right combination of parentheses, double quotes, single quotes, etc. I've tried a number of different combinations without success. I'm sure my lack of experience is also in play here.
Any suggestions or advice how to resolve this issue would be greatly appreciated. Thanks for taking the time to review this question and for any help you can provide......
If you're asking about accessing nested values with a single call then maybe you can try something like this:
Sub tester()
Dim json As Object
Set json = JsonConverter.ParseJson(JsonContent)
Debug.Print JSONValue(json, "name") ' fred
Debug.Print JSONValue(json, "addresses/1/city") ' NYC
Debug.Print JSONValue(json, "addresses/2/street") ' Rue blah
Debug.Print JSONValue(json, "values/4") ' 40
End Sub
'return a "leaf" value from a `json` object
Public Function JSONValue(json As Object, MyField As String)
Dim res, arr, i, v
Set res = json
arr = Split(MyField, "/") 'array of keys/indexes
For i = LBound(arr) To UBound(arr)
v = arr(i)
If TypeName(res) = "Collection" Then v = CLng(v) 'numeric index for collection
If i <> UBound(arr) Then
'not at the end yet so have either a dictionary or a collection
Set res = res(v)
Else
'accessing a single non-object value
JSONValue = res(v)
End If
Next i
End Function
'dummy JSON content
Function JsonContent()
JsonContent = Replace("{'name':'fred','addresses':" & _
"[{'city':'NYC','street':'Easy St'}," & _
"{'city':'Paris','street':'Rue blah'}]," & _
"'values':[10,20,30,40]}", "'", """")
End Function
Very basic but should work if you just want a single non-object return value which might be nested several fields deep.

VBA: Why isn't my FOR loop returning anything?

The overall goal is to return the characters in between the commas and use each of them in another piece of code. If anyone knows a more optimal way of doing this, please let me know.
The problem:
I am trying to find the positions of the commas in the string.
The string:
Dim st As String
st = "1642377,001642381,010301642379"
My attempt:
For pos = 1 To Len(st)
If Mid(st, pos, 1) = "," Then
MsgBox ("Position of comma:" & pos)
End If
Next
Currently returning:
The code doesn't return anything. The If condition isn't returning true.
Expected result:
A MsgBox should pop up twice, showing the position of the comma each time.
Use the split function. It returns a string array
Dim parts() As String, p As Variant
parts = Split("1642377,001642381,010301642379", ",")
For Each p In parts
Debug.Print p
Next
prints
1642377
001642381
010301642379
You are using 2 different values: st and Me.Text585.Value. Did you mean to use st in the two places? If I do so, the code works and it returns the positions 8 and 18.

Remove letter from a string access VBA

I have a string sStr that contains letters and numbers.I'm trying to remove letters from a string.
For eg: sStr= "P441" or sometimes sStr="BK471" .
I tried using
Right(sStr,3) and split
which gives me 441. since the string sStr may contain 2 letters ("BK471") sometimes, how do i remove letters in vba .
You can loop through each character in the string checking if it IsNumeric
Dim x as integer
Dim sCleanedStr As String
For x = 1 to Len(sStr)
If IsNumeric(Mid(sStr, x, 1)) then sCleanedStr = sCleanedStr & Mid(sStr, x, 1)
Next
You can use Regular Expressions to remove any letters. For this, you need to include the Regex library in your macro (Go to Tools -> References, then search and select the regular expressions library)
Sub test()
sStr = "abc123"
Dim regEx As New RegExp
With regEx
.Pattern = "[a-z]+"
.Global = True
.IgnoreCase = True
End With
sStr = regEx.Replace(sStr, "")
MsgBox (sStr)
End Sub
The above code will replace any letter from anywhere in the word.

Create query in QueryEditor with VBA function call for specifying the WHERE IN clause

I have written a couple of VBA functions which in the end return a Collection of Integers:
Public Function ValidIDs() As Collection
Now I want to run create a query in the QueryEditor with the following condition: WHERE TableID IN ValidIDs(). That does not work since access for some reason does not even find my function as long as it returns a Collection. Therefore I wrote a wrapper around it, which joins the Collection:
Public Function joinCollectionForIn(Coll As Collection) As String
Now a third function which calls ValidIDs(), passes the result to joinCollectionForIn and returns that result. Lets call it GetIDCollectionAsString().
As a result I can now change my query to WHERE TableID IN (GetIDCollectionAsString()). Note the added parenthesis since the IN needs them in any case, they can not just be at the end and the beginning of the String returned by GetID....
Running that query however results in
Data type mismatch in criteria expression.
I guess that results from the fact that I return a String, therefore access automatically wraps that string in ' for the SQL and the IN-clause no longer works because I would check if a number is IN a collection of 1 string.
Therefore my question is:
Is there a way to prevent access from wrapping the returned string for the SQL
or (would be a whole lot better):
Is there an already existing way to pass a collection or array to the WHERE IN-clause?
P.S.: I am currently using a workaround by writing a placeholder in the parenthesis following the IN (e.g. IN (1,2,3,4,5)) and replacing that placeholder in Form_Load with the result of GetIDCollectionAsString() - that works but it is not pretty...
Edit: The final query should look like SELECT * FROM TestTable t WHERE t.ID IN (1,2,3,4,5,6,7). That actually works using above method, but not in a nice way.
Well this required more work than it seems.... i couldn't find a straight solution so here is a workaround
Public Function ListforIn(inputString As String) As String
Dim qdf As QueryDef
Dim valCriteria As String
Dim strsql As String
Dim splitcounter As Byte
Dim valcounter As Byte
Set qdf = CurrentDb.QueryDefs(**TheNameOfQueryYouWantToModify**)
strsql = qdf.sql
strsql = Replace(strsql, ";", "") 'To get rid of ";"
splitcounter = Len(inputString) - Len(Replace(inputString, ",", ""))
For valcounter = 0 To splitcounter
valCriteria = valCriteria & ValParseText(inputString, valcounter, ",")
Next
strsql = strsql & " WHERE TableId IN (" & Left(valCriteria, Len(valCriteria) - 1) & ")"
qdf.sql = strsql
End Function
Public Function ValParseText(TextIn As String, X As Byte, Optional MyDelim As String) As Variant
On Error Resume Next
If Len(MyDelim) > 0 Then
ValParseText = "Val(" & (Split(TextIn, MyDelim)(X)) & "),"
Else
ValParseText = Split(TextIn, " ")(X)
End If
End Function