Reputation: 727
Hia,
I have a string ( a URL) where I want to get first string in between two characters in an access query.
http://websiteurl.com/sometext-STUFFIWANT-foo-bar
All the text is variable, and there are a varying number of "-" in the URL.
I can get the position of the first occurrence:
Instr([column],"-")+1
and I think I want something like:
Mid(
[column],
Instr([column],"-")+1,
InStr(InStr(1,[column],"-")-1,[column],"-")
)
This is giving me however the first chunk of the string, followed by some of the text after what I want.
I ideally would like: "get position of first -, the position of the second -, and then return all the text between those 2 positions"
I'm going round in circles a bit, and though I think I'm close, I'm no longer making progress.
Upvotes: 2
Views: 16843
Reputation: 21
I has the same problem, here is a function you can use, which allows for strings as startbit and endbit delimiters, and finds the middlebit from within the teststring even if the second delimiter isn't found.
Public Function middlebit(startbit, endbit, teststring)
Dim first As Integer
Dim second As Integer
middlebit = ""
If teststring <> "" Then
first = InStr(1, teststring, startbit)
second = InStr(first + Len(startbit), teststring, endbit)
If second = 0 Then second = Len(teststring)
If first > 0 And second > first Then
second = second - first
middlebit = Mid(teststring, first + Len(startbit), second - Len(startbit))
End If
End If
End Function
Upvotes: 0
Reputation: 97101
You didn't mention the context where you're doing this ... a VBA procedure, a query in Access, a query from outside an Access session. But this could be very easy if you can use the Split()
function. Consider this example from the Immediate window.
strUrl = "http://websiteurl.com/sometext-STUFFIWANT-foo-bar"
varPieces = Split(strUrl, "-")
? varPieces(1)
STUFFIWANT
Now that you've said you want to do this in a query, I think you're looking for something like this ...
SELECT
Mid(
[column],
InStr([column], "-") +1,
(InStr(InStr([column], "-") +1, [column], "-") - InStr([column], "-")) -1
) AS stuff_i_want
FROM YourTable;
That might even be sufficient. However, it will throw "invalid use of Null" errors whenever [column]
is Null. And it will also choke on [column]
values which include less than 2 dashes. If you can deal with those limitations, you may be good to go. But if you need to modify that complex field expression ... good luck!
If this is a query you will be running from within an Access application session, you could create a user-defined function based on the Split()
example I showed you earlier. Then your query would be simple to write.
SELECT
GetStuffYouWant([column]) AS stuff_i_want
FROM YourTable;
You may have heard warnings that UDFs can be slow in queries. However, in this case, the alternative is Mid()
plus a bunch of InStr()
functions, and that's not really an easier workload for the db engine. I compared both approaches with a table which contains over 10 million rows. The time it took to fully populate a DAO recordset ranged between 37 and 45 seconds, with neither approach as the consistent winner.
If you want to try the UDF approach yourself, I included the function below. And here is an Immediate window session testing the function with various input values.
? GetStuffYouWant(Null)
Null
? GetStuffYouWant("")
Null
? GetStuffYouWant("abc")
Null
? GetStuffYouWant("abc-")
Null
? GetStuffYouWant("abc-def")
Null
? GetStuffYouWant("abc-def-")
def
? GetStuffYouWant("http://websiteurl.com/sometext-STUFFIWANT-foo-bar")
STUFFIWANT
And the function ...
Public Function GetStuffYouWant(ByVal pInput As Variant, _
Optional pSplitChar As String = "-") As Variant
Dim varResult As Variant
Dim varPieces As Variant
If IsNull(pInput) Then
varResult = Null
Else
varPieces = Split(pInput, pSplitChar)
If UBound(varPieces) > 1 Then
varResult = varPieces(1)
Else
varResult = Null
End If
End If
GetStuffYouWant = varResult
End Function
Upvotes: 5
Reputation: 3226
Your code is really close. Is this what you want to do?
dim first as integer
dim second as integer
dim result as string
first = instr(1,"yourtext","-")
second = instr(first+1,"yourtext","-")
if first > 0 and second > first then
second = second - first
result = mid("yourtext",first+1, second-1)
end if
for "xx-bbb-cc" , result will be "bbb"
for "xx-bbb-cc-zz-cc, result will be "bbb"
for xxxx-bbb, there will be no result
Upvotes: 0