MS-Access: Replace "bracket" - sql

In one of the ms-access table I work with we have a text field with a set size.
At the end of this field there is some extra code that varies depending on the situation.
I'm looking for a way to remove one of these code but even when the last part is truncated by the field maximum size.
Let's call the field "field" and the code I'm looking to remove "abc-longcode".
If I use the replace SQL function with the string abc-longcode the query will only work when the code is complete.
If I also want my update query (that does nothing but remove this specific code at the end of my field) to work on incomplete codes how would that translate into ms-SQL?
It would have to remove (or replace with "" to be precise) all of the following (example of course, not the real codes):
abc-longcode
abc-longcod
abc-longco
abc-longc
abc-long
abc-lon
abc-lo
abc-l
Obviously I could do that with several queries. Each one replacing one of the expected truncated codes... but it doesn't sound optimal.
Also, when the field is big enough to get all of the code, there can sometime be extra details at the end that I'll also want to keep so I cannot either just look for "abc-l" and delete everything that follows :\
This query (or queries if I can't find a better way) will be held directly into the .mdb database.
So while I can think of several ways to do this outside of a ms-sql query, it doesn't help me.
Any help?
Thanks.

You can write a custom VBA replace method that will replace any of the given cases {"abc-longcode", ... "abc-l"}. This is essentially the same tack as your "several queries" idea, except it would only be one query. My VBA is rusty, but something like:
public function ReplaceCodes(str as string) as string
dim returnString as string
returnString = str
returnString = replace(returnString,"abc-longcode","")
// ... etc...
ReplaceCodes = returnString
end function
I may have gotten the parameter order wrong on replace :)

I would use my own custom function to do this using the split function to get the first part of the string. You can then use that value in the update query.
Public Function FirstPart(thetext As String) As String
Dim ret As String
Dim arrSplitText As Variant
arrSplitText = Split(thetext, "-")
ret = arrSplitText(0)
FirstPart = ret
End Function

Can you use:
Left(FieldX,InStr(FieldX,"abc-")-1)
EDIT re Comment
If there is a space or other standard delimiter:
IIf(InStr(InStr(FieldX, "abc-"), FieldX, " ") = 0, Left(FieldX, InStr(FieldX, "abc-") - 1), Replace(FieldX, Mid(FieldX, InStr(FieldX, "abc-"), InStr(InStr(FieldX, "abc-"), FieldX, " ") - InStr(FieldX, "abc-")), ""))

Related

"Query too Complex": MS Access Function to Replace text in Query (Nested Replace())

Purpose: Use a SQL Query in MS Access to locate all records matching specific keywords in a long text field
I am attempting to query for all records in a MS Access DB that have a match on a list of specific keywords within a field. The keywords are as follows:
AIN, ATIN, CKD, AKI, ARF
Issue I'm running into is that the field is a free text entry field, so the formatting of the data is all over the place, and the keywords I'm searching on will often appear in the middle of other full length words (i.e. AIN matches on "pAIN","agAIN", etc), while I only want to include matches on words that are strictly the keywords (i.e. " AIN ", " AKI ").
The idea I'm working with is to simply include matches that will hit on the following format: field_name like '* AIN *'.So basically only include matches that have a space before and after the keyword to limit the number of false positives appearing in the result set.
I have tried writing a SQL query that will normalize the data so that all other characters that appear (".","!","?","#", etc...) will be replaced with a space character (i.e. " AIN!" would be replace(field_name,"!"," ") = " AIN ") with the idea that this should only include words containing only the keyword. In attempting to run my very long nested replace statement in the query, I am receiving the "Query Too Complex" message. Nested replace is as follows:
UCASE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(a.REF_CONTENT_NM,chr(13)," "),chr(10)," "),"`"," "),"~"," "),"!"," "),"#"," "),"#"," "),"$"," "),"%"," "),"^"," "),"&"," "),"*"," "),"("," "),")"," "),"-"," "),"_"," "),"="," "),"+"," "),"["," "),"{"," "),"]"," "),"}"," "),";"," "),":"," "),","," "),"<"," "),"."," "),">"," "),"/"," "),"?"," "),"\"," "),"|"," "),""""," ")) like "* AIN *"
I believe that a workaround would be to create a custom function that could be referenced in the SQL statement, but I am not entirely sure of how to accomplish this. So essentially, I am looking for guidance on how to evaluate a solution of how to normalize the text like the above nested replace statement in Access without running into the "Query Too Complex message". I feel like there is a simple solution that I am just not seeing here, so guidance would be tremendously appreciated!
The main trick to writing a custom function to do this is properly using the ParamArray
This is a small function that executes multiple replaces:
Public Function ReplaceMultiple(strInput As String, strReplace As String, ParamArray Find() As Variant) As String
Dim i As Long
ReplaceMultiple = strInput
For i = LBound(Find) To UBound(Find)
ReplaceMultiple = Replace(ReplaceMultiple, Find(i), strReplace)
Next
End Function
Implement it:
ReplaceMultiple(a.REF_CONTENT_NM, " ", chr(13), chr(10), "`", "etc....")
You might need to think about altering the logic altogether, though, for example keeping a table of characters that should be replaced. I remember something about the max number of arguments being around 20-30, so you might need to use ReplaceMultiple twice.
If you just want to replace everything that isn't a string with a space, you can try the following small function:
Public Function ReplaceNonAlphanumeric(str As String) As String
If str = "" Then Exit Function
Dim i As Long
For i = 1 To Len(str)
If Mid(str, i, 1) Like "[0-9A-z]" Then
ReplaceNonAlphanumeric = ReplaceNonAlphanumeric & Mid(str, i, 1)
Else
ReplaceNonAlphanumeric = ReplaceNonAlphanumeric & " "
End If
Next
End Function

MS Access VBA - Pulling a partial string from semi-consistent data in a field

I've looked around but wasn't able to find an exact solution...
I have an identifier-type field that generally follows the format of XXX-YY-ZZZZZZZZ. Sometimes the number of X's and Z's will vary, but the YY's are always enclosed between the two hyphens. If I wanted to create another field using just the "YY", what would be the best function to use? There's also another reference table with the YYs listed that I intend to relate it to.
Thanks in advance.
Sounds like you want to split the string into an array. Try this out
Public Sub Example()
Dim ExampleStr As String: ExampleStr = "XXX-YY-ZZZZZZZZ"
Dim StrArray() As String
StrArray = Split(ExampleStr, "-")
Debug.Print StrArray(1) ' Return the second element
End Sub

VBA error: A value used in the formula is the wrong data type?

I'm trying to create a function which generates a secret encoded message. It takes in three things: a string, for example, "testingtestingonetwothree", as well as the desired number of characters, for example 5, and the desired number of words, for example 5. It generates the message by starting at the first character, and extracting every fifth character through the string, putting these characters into a codeword, then starting at the second character and extracting every fifth character through the string, putting these into a second codeword, and so on. It just outputs a string, with the codewords separated by a space. So for this example it would produce: "tntnt egieh stntr tegwe isooe".
I'm okay at coding but new to VBA. I've made what I think is a valid function, but when it's used in the spreadsheet I get a #VALUE! error: "A value used in the formula is the wrong data type". This is the user defined function I made:
Function encode(strng, numchars, numwords)
Dim word As Integer
Dim step As Integer
Dim temp As String
Dim output As String
For word = 1 To numchars
step = word
temp = ""
Do While step <= Len(strng)
temp = temp & Mid(strng, 1, step)
step = step + numchars
Loop
If word = 1 Then output = temp Else output = output & " " & temp
Next word
encode = output
End Function
And when it's used in the spreadsheet I just call it, as in
=encode(A16,A7,A10)
Where A16 contains testingtestingonetwothree, A7 contains 5 and A10 contains 5.
Does my function seem okay? And is there anything you guys can see which could be giving the value error? Any help would be greatly appreciated, thanks a lot for reading.
EDIT: This now outputs a value, but the wrong value. It outputs: "ttestintestingtesttestingtestingontestingtestingonetwot tetestingtestingtestitestingtestingonetestingtestingonetwoth ", when it should output: "tntnt egieh stntr tegwe isooe". Is there anything you guys can see that my function is doing wrong?
EDIT2: After fixing the Mid function, to
temp = temp & Mid(strng, step, 1)
as per vacip's answer, the function now produces the correct answer.
Ok, everyone says it works, but for me, it doesn't produce the desired output. What the...???
Anyway, I think your Mid function is in the wrong order, try it like this:
temp = temp & Mid(strng, step, 1)
Also, make sure to properly declare your variables, like this:
Function encode(strng As String, numchars As Integer, numwords As Integer) As String
I have also rewritten your IF statement, that one-line thing is strange for me...
If word = 1 Then
output = temp
Else
output = output & " " & temp
End If
This way it worked for me.
Other people have addressed the type problem. Here is a different suggestion. The cipher that you are describing is a simple transposition cipher, specifically a columnar transposition ( https://en.wikipedia.org/wiki/Transposition_cipher#Columnar_transposition )
The way people did this pre-computer was to write the characters into a grid row by row then read them off column by column. In fact -- this is probably still the easiest way to implement it even with computers. Declare a variant which can be redimensioned to be an array with e.g. 5 columns (where 5 is the skip between letters) and the number of rows is chosen to be large enough so that the grid can hold the string. After you load up the characters row by row, read them off column by column using nested for loops.
Once you get a basic example working, you can try to implement a version which uses a key to determine the order that you read off the columns for added security.
Coding classical cryptography/cryptanalysis as an excellent way to learn a programming language. Almost the first thing I do when I try to learn a new language is to implement a Vigenere cipher in it. Even though it is long out of print and can be somewhat tricky to translate to modern dialects of Basic the book "Cryptanalysis for Microcomputers" by Caxton Foster is great fun and can be purchased for just a few dollars from online used bookstores.
You need to define your Function's type. So in this case I believe you would want
Function encode(strng, numchars, numwords) As String
I tested your code exactly as it is, and it worked fine.
So, your problem may be:
A certain argument of your function is not the right type. (I bet the len method is the problem in there).
Check if A16 is really a string. If not, consider converting it to a string before if you want to pass numbers too:
Function encode(strng as variant, numchars as integer, numwords as integer) as string
strng = str(strng)
Check also if A7 and A10 are really integers.

MS Access Remove Words from Text

I'm trying to remove various words from a text field in MS Access. The data might look like:
Hi there #foo, what's new #bar
#goodfriend and I just watched Star Wars
#this and #that and #theother
I want to remove all the words that start with '#'.
Replace() won't work since the words are different in each record.
Any ideas?
If you're using VBA, you should be able to replace text based on regular expressions. See the answer to replace a column using regex in ms access 2010 as an example.
I actualy upvoted CheeseInPosition's answer but just thought I would provide another way if you can't/don't want to do it with regex. Just wrote a quick function to parse out the words:
Public Function RemoveAtWords(strOriginal As String) As String
Dim strParts() As String
Dim i As Integer
strParts() = Split(strOriginal, " ")
For i = LBound(strParts) To UBound(strParts)
If Left(strParts(i), 1) <> "#" Then
RemoveAtWords = RemoveAtWords & " " & strParts(i)
End If
Next
RemoveAtWords = Trim(RemoveAtWords)
End Function
You can call that from a query and pass through your string. Not as efficient because you have to loop through the whole string, but just another option.

Inserting a String inside a String

I want to insert a word inside an existing word? Both are Strings.
For example:
Given String word:
HELLO SAMPLE SENTENCE
i want to insert the word I AM A so my output would be:
HELLO I AM A SAMPLE SENTENCE
i am inserting here basing on the word SAMPLE. So the insertion starts before the word SAMPLE. is this possible?
Based on the description of your logic (which isn't much to go on), I would use:
Dim input As String = "HELLO SAMPLE SENTENCE"
Dim iSample As Integer = input.IndexOf("SAMPLE")
Dim output As String = input.Insert(iSample, "I AM A ")
This uses the BCL function String.Insert, which simply inserts a string into another string at a particular position.
Create a function like this:
Function InsertBefore(sentence As String, find As String, textToInsert As String
Return sentence.Replace(find, textToInsert+Find)
End Function
And call it like this:
sentence = InsertBefore("HELLO SAMPLE SENTENCE", " SAMPLE ", "I AM A")
If I remember correctly, you can use the String.split() function on your string.
See DotNetPerls' page on Split here.
You can split the string into an array, then insert the line you want into the array, then join them back together using String.Join() (thanks Monty, I don't use Visual Basic that frequently anymore, I forgot that :)).
Hope this help :)