Get rid of any parenthesis or values enclosed in parenthesis SSRS - reporting-services

I'm trying to remove any parenthesis or value enclosed in parenthesis in a string field in SSRS, which will be the best way to do it? I read about replace function but not sure how to use it with several values.
Here are some examples about what I'm trying to do:
Original string Expected string
ERP(123) ERP
TE(PO)ST TEST
(123)string string

Assuming you only have a single set of parentheses then this will work.
=LEFT(Fields!test.Value, InStr(Fields!test.Value, "(") -1)
&
MID(Fields!test.Value, InStr(Fields!test.Value, ")") +1)
Basically we take the left part of the string up to the first "(" position minus 1
and then concatenate the remainder of the string starting at the first ") +1

For this I would use a function that would be usable everywhere and not always copy paste:
In here we do a Substring of the part we want to delete, and then we do a Replace to changed with no spaces and that way the string will be together (in the case if the original was separated by the parenthesis)
Public Function removeParenthesis (input As Object) As Object
Try
Dim FirstIndex As Integer = input.IndexOf("(")
Dim SecondIndex As Integer = input.IndexOf(")") - FirstIndex + 1
Dim Result As String = input.ToString().Replace(input.Substring(FirstIndex, SecondIndex), "")
Return Result
Catch ex As Exception
Return ex
End Try
End Function
This is pasted in the Code sections and will be called like this:
Code.removeParenthesis(Fields!Textbox1.Value)
The function is implemented on Report > Report Properties > Code > paste the function above
EDIT
Taking in mind what #Alan Schofield said in his answer
Assuming you only have a single set of parentheses [...].
I have made a little change and have validate too if there's actually some parenthesis, the idea is to loop till everything is clean.
If there's no parenthesis then It'll return original value
Public Function removeParenthesis(input As Object) As Object
Try
Dim Result As String = input.ToString()
Dim FirstIndex As Integer = Result.IndexOf("(")
Dim SecondIndex As Integer = Result.IndexOf(")")
While FirstIndex <> -1 And SecondIndex <> -1
SecondIndex = SecondIndex - FirstIndex + 1
Result = Result.Replace(Result.Substring(FirstIndex, SecondIndex), "")
FirstIndex = Result.IndexOf("(")
SecondIndex = Result.IndexOf(")")
End While
Return Result
Catch ex As Exception
Return ex
End Try
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

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.

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

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

Query to parse a field and display it

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*';