JSON Encode string literal "asdf\\nsedfgs" - json

I am working with an old classic asp/vbscript app that has a json class.
I have a string literal: asdf\\nsedfgs e.g. thats not escaped json or anything. its literally those characters.
So, to use that value in a JSON string, it should be something like this, right?
{"somedesc":"asdf\\\\nsedfgs"}
...with the two backslash characters escaped.
However, on the way out of JSON and back to string literal, we'd do something like this (in this order)
val = Replace(val, "\""", """")
val = Replace(val, "\\", "\")
val = Replace(val, "\/", "/")
val = Replace(val, "\b", Chr(8))
val = Replace(val, "\f", Chr(12))
val = Replace(val, "\n", Chr(10))
val = Replace(val, "\r", Chr(13))
val = Replace(val, "\t", Chr(9))
...but for the string above, this sequence of replace() gives us the incorrect decoded value:
result (note the newline, as the 4 \ got replaced to two, then the \n got replaced to a newline)
asdf\
sedfgs
So questions:
how does one encode and decode a literal asdf\\nsedfgs to and from json correctly?
is that decode logic correct? in the correct order? It seems not, because how could it distinguish between a literal \n vs an escaped chr(13)?
is there something else I am missing here?

The important part is isolating the escaped backslashes from the rest of the string so that they don't interfere with escape sequences- You can split the string, reattach the missing parts later:
Const ENCODE = FALSE
Const DECODE = TRUE
val = "asdf\\\\nsedfgs"
val = JSON(val, DECODE)
MsgBox val
'Swap replacement values & dividers + concatenation characters
val = JSON(val, ENCODE)
MsgBox val
Function JSON(ByVal str, ByVal mode)
Dim key, val
Set d = CreateObject("Scripting.Dictionary")
d.Add "\/", "/"
d.Add "\b", Chr(8)
d.Add "\f", Chr(12)
d.Add "\n", Chr(10)
d.Add "\r", Chr(13)
d.Add "\t", Chr(9)
If mode Then
d.Add "\""", """"
d.Add "\\", "\"
div = "\\"
cat = "\"
key = d.Keys
val = d.Items
Else
d.Add "\\", "\"
d.Add "\""", """"
div = "\"
cat = "\\"
key = d.Items
val = d.Keys
End If
arr = Split(str, div)
For i = 0 To UBound(arr)
For j = 0 To UBound(key)
arr(i) = Replace(arr(i), key(j), val(j))
Next
output = output & arr(i)
If i <> UBound(arr) Then output = output & cat
Next
d.RemoveAll
JSON = output
End Function

Related

Accessing JSON array data in VBA

I have this json array and the data I need is in the array that starts data_id which I cannot extract. I am able to extract keys,value before the array but not in the array. I believe I need to request data in a specific way with a number in () after the fieldname nest but I cannot find a beginners explanation to see what number goes in the brackets and why you chose that number.
{"api":{"results":37,"data":[{"data_id":643951,"location_id":3005,"person":{"name":"Bob","country":"Turkey",
Any tips appreciated here is some code
'Print a few object variables before parse
Dim WrkSht As Worksheet
Set WrkSht = ThisWorkbook.Worksheets("jsonoutput")
WrkSht.Cells(1, 1).Value = xml_obj.responseText
' Displays data fine in one string as shown above
'Parse the response
Set jp = JsonConverter.ParseJson(xml_obj.responseText)
For Each dict In jp
Debug.Print dict
If Not IsObject(jp(dict)) Then
Debug.Print jp(dict)
Else
For Each subDict In jp(dict)
Debug.Print subDict
'Debug.Print jp(dict)(subDict)
Next subDict
End If
Next dict
' I need to drill down into further levels but ?
End Sub
Here's a simple example
JSON used:
{"api":{"results":37,
"data":[{"data_id":643951,
"location_id":3005,
"person":{"name":"Bob","country":"Turkey"}
} ]
}}
Code:
Sub Test36()
Dim jso As Object, arr, data, obj
'loading from a cell for testing...
Set jso = JsonConverter.ParseJson(Sheet2.Range("A17").Value)
'jso is a Dictionary
Debug.Print jso("api")("results") '>> 37
Set data = jso("api")("data") 'data is a Collection
Debug.Print data.Count ' >> 1
For Each obj In data
Debug.Print obj("data_id") '>> 643951
Debug.Print obj("person")("country") '>> Turkey
Next obj
End Sub
I thought I would just share the code I ended up with. It can be improved on and some is over coded simply to make it easier to see where amendments can be made. Currently this will:
Access an API - just put as many header lines in as you need
Collect the JSON data and flatten it to one level - this code will only work with Json where
blank values are recorded as "null" rather than just "". You may
have to manually correct the columns (or update the code) for
blank values
Ask you which key you want to start with - it will
then mark that keys values to start a new row each time it comes
across this
Make replacements in the data to create delimiters
to mark which data is keys and which is values
Pastes your keys
in row 1 that have values - dictionary keys are ignored but
you can change that if needed
Remove all keys from the string to
just leave values and paste those in the rows below.
You need to have the RunScriptime XMl HTTP 6.0 and Object library ticked in Tools reference in VBA as well
Sub FlattenJsonGetDataFromKeysWithValues()
ActiveWorkbook.Worksheets("yourworksheet").Range("a1:ZZ10000").ClearContents
Dim i As Long
'Declare variables
Dim xml_obj As MSXML2.XMLHTTP60
Dim base_url As String
Dim Json1 As String, Json2, Json3, Json4, Json5, Json6, json7, Json8, Json9, Json10, Json11, Json12, Json13, Json14, Json15, Json16, Json17, Json18
Dim Json0 As String
Dim keys As String, keys2
'Create a new Request Object make sure in Tools-> reference the xml6.0, scripting runtime and object library are ticked
Set xml_obj = New MSXML2.XMLHTTP60
'Define URL Components two headers are shown but you cana dd as many as required
base_url = "https://yoururl.com"
xml_obj.Open "GET", base_url
xml_obj.SetRequestHeader "key", "55555"
xml_obj.SetRequestHeader "host", "valuefor2ndheaderkeyifneeded"
xml_obj.Send
'Print the status code in case something went wrong
MsgBox("The Request was " + CStr(xml_obj.Status))
strJson0 = xml_obj.responseText
MsgBox (Len(strJson0)) ' tells how long string is
'Look for Json current delimiters and change all to a comma
Json1 = strJson0
Const SpecialCharacters As String = "!,#,#,$,%,^,&,*,(,),{,[,],},?,:"
Dim char As Variant
For Each char In Split(SpecialCharacters, ",")
Json1 = Replace(Json1, char, " ")
Next
' Place # before all field names, I have shown in this way so if needed you can vary to suit your needs
Json2 = Replace(Json1, "," & Chr(34), "#") ' Replaces ," - Chr(34) is a "
Json3 = Replace(Json2, ", " & Chr(34), "#") ' replaces , "
Json4 = Replace(Json3, Chr(34) & " " & Chr(34), Chr(34) & "#") ' Replaces " "
Json5 = Replace(Json4, Chr(34) & " " & Chr(34), Chr(34) & "#") ' Replaces " "
'Place : after fieldname and before value
Json6 = Replace(Json5, Chr(34) & " " & Chr(34), ":") 'Replaces " "
json7 = Replace(Json6, Chr(34) & " ", ":") 'Replaces "(blankspace)
Json8 = Replace(json7, Chr(34), ":") 'Replaces "
Json9 = Replace(Json8, ":#", "#") 'Replaces :# with #
Json10 = Replace(Json9, "/", "") 'Removes /
Json11 = Replace(Json10, " ", "") 'Removes blankspace
If Left(Json11, 1) = ":" Then Json11 = "#" & Right(Json11, (Len(Json11) - 1)) ' Replace : with # if first character
' Now you just have field names (keys) marked by # and values marked by :
' Find Field Names - which field should we start with? How many times is that key in the data
Dim firstkey As String
MsgBox (Json11) 'View this to see your key/header row options
firstkey = InputBox("Enter First Field/Key to locate") 'This will mark where all new rows start
keys = Json11
' Now take text between #*# as dictionary keys and ignore and text between #*: as headers for field names until repeat text is found in string by finding the firstkey you input above and putting a # marker in all heading that = firstkey
Dim openPos As Long
Dim closePos As Long
Dim k As Integer
Dim jsonFields As Collection
Set jsonFields = New Collection
Dim jsonValues As Collection
Set jsonValues = New Collection
' Find wanted starting key, skip over keys without value
k = 1
openPos = InStr(keys, firstkey)
closePos = InStr(openPos, keys, ":")
If InStr(1, Mid(keys, openPos, closePos - openPos), "#") > 0 Then openPos = openPos + InStr(1, Mid(keys, openPos, closePos - openPos), "#")
jsonFields.Add Mid(keys, openPos, closePos - openPos)
keys = Replace(keys, firstkey & ":", ":#")
k = k + 1
' Find other keys with values, find dict keys
Do Until Mid(keys, openPos, closePos - openPos) = ""
openPos = InStr(closePos, keys, "#") + 1
If k = 2 Then openPos = InStr(1, keys, "#")
closePos = InStr(openPos, keys, ":")
If InStr(1, Mid(keys, openPos, closePos - openPos), "#") > 0 Then openPos = openPos + InStr(1, Mid(keys, openPos, closePos - openPos), "#")
jsonFields.Add Mid(keys, openPos, closePos - openPos)
k = k + 1
Loop
' Find values and remove delimiters, keys and replace : in https values that are removed with other delimiters
y = 2 ' use to start populate rows
currentcolumn = 1
Dim r&
p = Split(keys, "#")
For r = 0 To UBound(p)
If InStr(1, p(r), ":") Then p(r) = Right(p(r), Len(p(r)) - InStr(1, p(r), ":") + 1) ' remove keys
If InStr(1, p(r), ":") = 0 Then p(r) = "" ' remove :
If InStr(1, p(r), ":") Then p(r) = Right(p(r), Len(p(r)) - InStr(1, p(r), ":")) ' set value for collection to print later
If InStr(1, p(r), "https") Then p(r) = Replace(p(r), "https", "https:") ' fix https value by readding :
jsonValues.Add p(r) ' add to collection
Next r
' Print Values to worksheet
currentcolumn = 1
'Now Output your parsed key data, turn screen updating off
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
For Each Item In jsonFields
ActiveWorkbook.Worksheets("yourworksheet").Cells(1, currentcolumn).Value = Item
currentcolumn = currentcolumn + 1
Next Item
y = 2
currentcolumn = 1
Dim ws As Worksheet
Set ws = Worksheets("yourworksheet")
For Each Item In jsonValues
If Len(Item) > 0 Then
If InStr(1, Item, "#") = 1 Then
y = y + 1
currentcolumn = 1
End If
ws.Cells(y, currentcolumn).Value = Item
currentcolumn = currentcolumn + 1
End If
Next Item
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub

Access Vba - Reverse a string's contents

I have a string called str = "12345-5, 12345-4, 12345-3, 12345-2, 12345-1 I need to reverse the string so it looks like this str = "12345-1, 12345-2, 12345-3, 12345-4, 12345-5"
I have tried the strReverse method, and it almost did what I wanted...
Sub rev()
Dim str As String
str = "12345-5, 12345-4, 12345-3, 12345-2, 12345-1"
str = StrReverse(Trim(str))
'turns out to be str = "1-54321 ,2-54321 ,3-54321 ,4-54321 ,5-54321"
End Sub
but it ended up reversing the whole string, should have guessed that. So I'm wondering should I use a regex expression to parse the string and remove the "12345-" and then reverse it and add it back in? I'm not too sure if that would be the best method for my problem. Does anyone know a solution to my problem or could point me in the right direction? Thanks
Use Split then loop backwards through the array:
Sub rev()
Dim str As String
str = "12345-5, 12345-4, 12345-3, 12345-2, 12345-1"
Dim strArr() As String
strArr = Split(str, ",")
str = ""
Dim i As Long
For i = UBound(strArr) To LBound(strArr) Step -1
str = str & ", " & Trim(strArr(i))
Next i
str = Mid(str, 3)
Debug.Print str
End Sub
I would do it like this:
Sub TestMe()
Dim str As String
str = "12345-5, 12345-4, 12345-3, 12345-2, 12345-1"
str = StrReverse(str)
Dim myArr As Variant
myArr = Split(str, ",")
Dim newString As String
Dim myA As Variant
For Each myA In myArr
newString = newString & StrReverse(myA) & ","
Next myA
newString = Trim(Left(newString, Len(newString) - 1))
Debug.Print newString
End Sub
Getting this:
12345-1, 12345-2, 12345-3, 12345-4,12345-5
In general, this is quite popular Algorithmic problem, which used to be asked by Google for Junior Developers. Sounding like this - Efficiently reverse the order of the words (not characters) in an array of characters

html encode doesnt encode space

i have the following function on vbscript:
Function HTMLEncode(sText)
Dim regEx
Dim matches
Dim match
sText = Replace(sText, Chr(34), """)
sText = Replace(sText, Chr(60) , "<")
sText = Replace(sText, Chr(62) , ">")
sText = Replace(sText, Chr(38), "&")
sText = Replace(sText, Chr(32), " ")
Set regEx= New RegExp
With regEx
.Pattern = "&#(\d+);" 'Match html unicode escapes
.Global = True
End With
Set matches = regEx.Execute(sText)
'Iterate over matches
For Each match in matches
'For each unicode match, replace the whole match, with the ChrW of the digits.
sText = Replace(sText, ChrW(match.SubMatches(0)), match.Value)
Next
HTMLEncode = sText
End Function
However, this doesn't encode space. when i type >, <, ", & they get encoded. but when i type space it doesnt get encoded. It does, but its encoded when I enter multiple spaces, for example:
"thishas4spaces word"
the first three get encoded except the last space. so it goes like this:
"thishas4spaces word"
Any idea why? help please. language is vbscript

Search and replace whole words which can be separated not only by a space

I'm looking for a way to search and replace whole words. The whole words can be separated not only by a space but .,;:/? etc.
I'm looking to do something like this
replace([address], ***--list of separators, like .,;:/?--*** & [replacewhat] & ***--list of separators, like .,;:/?--*** ," " & [replacewith] & " ")
I don't know how to pass a list of separators instead of running a replace function once for each combination of separators (which combined with 300 words I'm replacing would amount to an insane number of queries).
You can do a replacement with a regular expression using a pattern with the \b marker (for the word boundary) before and after the word you want to replace.
Public Function RegExpReplaceWord(ByVal strSource As String, _
ByVal strFind As String, _
ByVal strReplace As String) As String
' Purpose : replace [strFind] with [strReplace] in [strSource]
' Comment : [strFind] can be plain text or a regexp pattern;
' all occurences of [strFind] are replaced
' early binding requires reference to Microsoft VBScript
' Regular Expressions:
'Dim re As RegExp
'Set re = New RegExp
' with late binding, no reference needed:
Dim re As Object
Set re = CreateObject("VBScript.RegExp")
re.Global = True
're.IgnoreCase = True ' <-- case insensitve
re.pattern = "\b" & strFind & "\b"
RegExpReplaceWord = re.Replace(strSource, strReplace)
Set re = Nothing
End Function
As written, the search is case sensitive. If you want case insensitive, enable this line:
re.IgnoreCase = True
In the Immediate window ...
? RegExpReplaceWord("one too three", "too", "two")
one two three
? RegExpReplaceWord("one tool three", "too", "two")
one tool three
? RegExpReplaceWord("one too() three", "too", "two")
one two() three
? RegExpReplaceWord("one too three", "to", "two")
one too three
? RegExpReplaceWord("one too three", "t..", "two")
one two three
... and for your range of delimiters ...
? RegExpReplaceWord("one.too.three", "too", "two")
one.two.three
? RegExpReplaceWord("one,too,three", "too", "two")
one,two,three
? RegExpReplaceWord("one;too;three", "too", "two")
one;two;three
? RegExpReplaceWord("one:too:three", "too", "two")
one:two:three
? RegExpReplaceWord("one/too/three", "too", "two")
one/two/three
? RegExpReplaceWord("one?too?three", "too", "two")
one?two?three
? RegExpReplaceWord("one--too--three", "too", "two")
one--two--three
? RegExpReplaceWord("one***too***three", "too", "two")
one***two***three
Thank you for your answer. It was of great help to me.
However, as the number of iterations of this code increased due to increase in my data size, I realized that this piece of code is slowing down my application. For instance, 10,000 iterations of this code take about 20 seconds.
I was using below code based on your answer:
Function CleanString(ByVal InputString As String, Optional SplWords = "USP|BP|EP|IP|JP", _
Optional Delim As String = "|") As String
Dim i As Integer
Dim ArrIsEmpty As Boolean
Dim ArrSplWords() As String
Dim Wrd As Variant
Dim RE As Object
CleanString = InputString
ArrSplWords = Split(SplWords, Delim)
Set RE = CreateObject("VBScript.RegExp")
RE.Global = True
RE.ignorecase = True
For Each Wrd In ArrSplWords
RE.Pattern = "\b" & Wrd & "\b"
If RE.test(CleanString) Then
CleanString = RE.Replace(CleanString, "")
End If
Next Wrd
CleanString = Application.WorksheetFunction.Trim(CleanString)
End Function
To tackle the issue of slowness, I decided to ditch the RegExp approach and came up with below code. Based on my evaluation, the below function is about 25 times faster (I timed it using timer function over 1000 iterations of each code).
Function CleanString(ByVal InputString As String, Optional SplWords As String = "USP|BP|EP|IP|JP", _
Optional Delim As String = "|", Optional WordSeparator As String = " ", _
Optional SplChar As String = "~|`|!|#|#|$|%|^|&|*|-|+|=|'|<|>|,|.|/|\|?|:|;") As String
Dim TestStr As String
Dim ArrSplChar() As String
Dim Char As Variant
Dim TestWords() As String
Dim Wrd As Variant
Dim Counter As Integer
TestStr = InputString
ArrSplChar = Split(SplChar, Delim, -1, vbTextCompare)
For Each Char In ArrSplChar
TestStr = Replace(TestStr, Char, WordSeparator & Char & WordSeparator, 1, -1, vbTextCompare)
Next Char
TestWords = Split(TestStr, WordSeparator, -1, vbTextCompare)
For Each Wrd In TestWords
Counter = IIf(Wrd = "", Counter + 1, Counter)
If InStr(1, LCase(SplWords), LCase(Wrd), vbTextCompare) = 0 Then
CleanString = CleanString & " " & Wrd
Counter = Counter + 1
End If
Next Wrd
CleanString = IIf(Counter - 1 = UBound(TestWords) - LBound(TestWords), _
Application.WorksheetFunction.Trim(InputString), _
Application.WorksheetFunction.Trim(CleanString))
End Function
This function looks a little messier than the regExp based function, but it is faster than the regExp based function.
Both the above functions generate the same output and can be called as follows:
Sub TestSub()
Debug.Print CleanString("Paracetamol USP")
End Sub
This will print "Paracetamol" in the immediate window.

Access VBA remove CR & LF only from the beginning of a text string by searching for them

I need to remove line breaks from the beginning of a memo type records. I dont want to use the replace function as it would remove all line breaks from the record which is not desired. Its only the line breaks at the beginning of the field that I am interested in removing.
Furthermore, the my records do not always begin with a line break so I cant really use text positioning, the solution would be to look for line break at the beginning instead of always expecting it at the beginning.
If Len(string) > 0 Then
Do While Left(string,1)= chr(13) Or Left(string,1)= chr(10) or Left(string,1) = " "
string = Right(string, len(string)-1)
Loop
End If
This will check to make sure the string isn't empty, then runs a simple loop to remove the left-most character as long as it is either a CR (chr(13)), LF (chr(10)), or a space (" ").
Once the loop hits the first character that doesn't match the criteria, it stops and you have the desired result of trimming all extra CR, LF, and space characters only from the beginning of the string.
Since it's relatively short, I just put it in the event procedure where needed, you could also modify it to be a public function in a module if you see fit.
Replace does not replace all occurences when you use the count argument: http://office.microsoft.com/en-us/access/HA012288981033.aspx
You can test it like so:
s1 = vbCrLf & "abc"
s2 = "ab" & vbCrLf & "c"
MsgBox "---" & IIf(Left(s1, 2) = vbCrLf, Replace(s1, vbCrLf, "", , 1), s1)
MsgBox "---" & IIf(Left(s2, 2) = vbCrLf, Replace(s2, vbCrLf, "", , 1), s2)
Improving upon what SBinVA wrote
The following code does not need the if statement and it is easy to expand to more character (space, tabs, etc.).
(It also assumes line breaks can originate from a file that can comes from other systems, so vbCr and vbLf are used separately, which takes care of all scenarios.)
Public Function trimCrOrLf(ByVal s As String) As String
Dim firstChar As String
firstChar = Left(s, 1)
Do While InStr(vbCr & vbLf, firstChar) > 0
s = Mid(s, 2)
firstChar = Left(s, 1)
Loop
trimCrOrLf = s
End Function
Consider a SQL UPDATE statement to discard only those CRLF at the beginning of each memo field.
UPDATE MyTable SET MyTable.memo_field = Mid([memo_field],3)
WHERE (((MyTable.memo_field) Like Chr(13) & Chr(10) & "*"));
Private Sub TestLineFeed()
Dim strString$, strTestChar, booStartsWith_CR As Boolean
strString = Chr$(13) & "some text"
strTestChar = "2"
'strTestChar = Chr$(13) ''This is a CR.
booStartsWith_CR = (Left(strString, 1) = strTestChar)
Debug.Print "-----"
Debug.Print "Raw: " & strString
Debug.Print booStartsWith_CR
If booStartsWith_CR Then
strString = Mid(strString, 2, 100)
End If
Debug.Print "-----"
Debug.Print "New: " & strString
End Sub
Note alternatives for strTestChar so you can see the action. You should notice "-----" in your Immediate Window is followed by a CR, thus a blank line; and this can be removed. Mid(strString, 2, 100) will need some tweaking, but the idea is to copy over your memo string without the first character.
I would use a function like this. It's fairly straight-forward and easily adapted to other circumstances. For example, to remove leading spaces too, add another test to the if (c = vbCr) line.
Function LTrimCRLF(s As String) As String
Dim index As Integer, start As Integer, strLen As Integer
Dim c As String
strLen = Len(s)
index = 1
start = -1
Do While (index <= strLen) And (start = -1)
c = Mid(s, index, 1)
If (c = vbCr) Or (c = vbLf) Then
index = index + 1
Else
start = index
End If
Loop
If start = -1 Then
LTrimCRLF = ""
Else
LTrimCRLF = Mid(s, start)
End If
End Function
Here's a test routine:
Sub TestLTrimCRLF()
Dim withWS As String, noWS As String, blank As String, onlyWS As String
withWS = vbCrLf & " this string has leading white space"
noWS = "this string has no leading white space"
onlyWS = vbCrLf & " " & vbCrLf & " "
blank = ""
Say "with WS: {" & LTrimCRLF(withWS) & "}"
Say "no WS: {" & LTrimCRLF(noWS) & "}"
Say "only WS: {" & LTrimCRLF(onlyWS) & "}"
Say "blank: {" & LTrimCRLF(blank) & "}"
End Sub
BTW, I tried looking at your sample data, but it says the document is not available. Maybe you need to make it public or something?
My contribution to VBA trimwhitespace() function, loop finds for first non-whitespace index, splits a string, then same thing for trailing whitespaces. Left+Right functions are run only once. If you need just leftTrim or rightTrim it's easy to introduce new arguments or separate functions.
Function trimWhitespace(str As String) As String
Dim idx As Long
Dim ch As String
' LeftTrim
If Len(str) > 0 Then
idx = 1
ch = Mid(str, idx, 1)
Do While ch = Chr(13) Or ch = Chr(10) Or ch = " "
idx = idx + 1
ch = Mid(str, idx, 1)
Loop
If (idx > 1) Then str = Right(str, Len(str) - idx)
End If
' RightTrim
idx = Len(str)
If idx > 0 Then
ch = Mid(str, idx, 1)
Do While ch = Chr(13) Or ch = Chr(10) Or ch = " "
idx = idx - 1
ch = Mid(str, idx, 1)
Loop
If (idx < Len(str)) Then str = Left(str, idx)
End If
trimWhitespace = str
End Function
This will trim all leading and trailing spaces, carriage returns, tabs, and other non-printable characters.
Public Function TrimSpecial(InputString As Variant) As String
' This will trim leading/trailing spaces and non-printable characters from the passed string.
Dim i As Integer
Dim str As String
On Error GoTo ErrorHandler
str = InputString
For i = 1 To Len(str)
If Asc(Mid(str, i, 1)) > 32 And Asc(Mid(str, i, 1)) < 127 Then
' Valid character found. Truncate leading characters before this.
str = Mid(str, i)
Exit For
End If
Next i
For i = Len(str) To 1 Step -1
If Asc(Mid(str, i, 1)) > 32 And Asc(Mid(str, i, 1)) < 127 Then
' Valid character found. Truncate trailing characters after this.
str = Mid(str, 1, i)
Exit For
End If
Next i
TrimSpecial = str
Exit_Function:
Exit Function
ErrorHandler:
MsgBox "Error #" & Err.Number & " - " & Err.Description & vbCrLf & "in procedure TrimSpecial"
GoTo Exit_Function
Resume Next
Resume
End Function
You can use this routine to test it:
Public Sub Test_TrimSpecial()
' Run this to test the TrimSpecial function.
Dim x As String
x = vbCrLf & " " & vbTab & " ab cd" & vbCrLf & vbTab & " xyz " & vbCr & vbCrLf
Debug.Print "-----"
Debug.Print ">" & x & "<"
Debug.Print "-----"
Debug.Print ">" & TrimSpecial(x) & "<"
Debug.Print "-----"
End Sub
Like "*" & Chr(13) & Chr(10)
(Access used carriage return + line feed, characters 13 and 10, for a new line).
To remove the carriage return/line feed, change the query to an update query and enter the following in the Update to line:
Replace([FieldName], Chr(13) & Chr(10), "")
or
Replace([FieldName], Chr(10),"")
Replace([FieldName], Chr(13),"")