Removing certain strings in an Access 2010 query - ms-access

I currently have an Access query that returns data in two forms
One form is 5 numbers, e.g., 12345
The other form is 2 letters, followed by 5 numbers, e.g., ab12345
This is coming in the same field, and I need to get only the numbers. I can't strip off the first two characters, because then for the IDs that have only the numbers, I'm cutting it short.

Use Val(string) to strip letters after numbers.
Use pVal(string) to strip letters before numbers.
string1 = "123456abcd1234"
val1 = val(string1) => val1 = 123456
string2 = "aqweqweasd123456abcd1234"
val2 = pval(string2) => val2 = 123456
if in case you have "asdasd123asasd456" and you want to have 123456 as result you can modify the pval to replace all non numeric values from output
here is the pVal function. Place this in a module and use it from anywhere
Public Function pVal(s As String)
Dim i As Long
For i = 1 To Len(s)
If IsNumeric(Mid(s, i, 1)) Then
pVal = Val(Mid(s, i, Len(s)))
Exit Function
End If
Next i
End Function

Use a select query as source for your form like this with an expression that strips the two leading characters:
Select *, Mid([XX0000NumberField], 3) As NumberOnlyID
From YourTable
Or for mixed numbers:
Select *, Right([XX0000NumberField], 5) As NumberOnlyID
From YourTable

Related

Take substring and use it in multiple where condition in sql

I have a string which has some values concatenated. Like 'Val1val2val3val4'.
I have a query like
Select * from table where var1 = Val1 and var2 = val2 and var3 = var3;
Val1 and val2 are length only 4 but val3 may differ in length. Val4 is of length 8 and no use.
I can form query with functions like var1 = substring (text, 1, 4), var2 = substring (text, 5, 8) and for var3 = substring (text, 9, Len(text) - 8).
But the problem is, i have to manually edit replace the value in 3 places in query each time in workbench. Which is a painful task in my case. Is it possible to just put the string in one place and make the SQL automatically take substrings and use in where clause conditions? I have only read access, cannot modify tables. Local variables like #var = Text, throws error code 1046. Hands tied for me. Need ideas if feasible.
You could put the input string into a derived table of one row, and cross-join that to your table:
SELECT ...
FROM (SELECT 'Val1val2val3val4' AS text) AS v
CROSS JOIN MyTable
WHERE var1 = substring(v.text, 1, 4) AND ...
Or you could use a user-defined variable and use it in a subsequent query:
SET #var = 'Val1val2val3val4';
SELECT ...
FROM MyTable
WHERE var1 = substring(#var, 1, 4) AND ...
You mentioned you got a 1046 error, but it's not clear how you were trying to assign it, so I can't guess what happened.
If you are sure that both #var1 and #var2 have length of 4 chars, then all you need is:
WHERE text LIKE CONCAT(#var1, #var2, #var3, REPEAT('_', 8))
If not then:
WHERE text LIKE CONCAT(#var1, #var2, #var3, REPEAT('_', 8))
AND CHAR_LENGTH(#var1) = 4
AND CHAR_LENGTH(#var2) = 4;
If the comparison should be case sensitive, change to:
WHERE text LIKE BINARY CONCAT(#var1, #var2, #var3, REPEAT('_', 8))

Is there any way to get alphabetical numbering of rows in ssrs instead of numerical numbering?

What I need (alphabetical numbering of rows-highlighted in bold(serial column)):
I have tried converting the output of rownumber function into string, But nothing seems to work as I don't have any idea.
Please help!
You can do this with a bit of custom code.
Go to the Report Properties, click the "Code" tab and paste the following code into the custom code window.
Public Function GetRowLetter(RowNum As Integer) As String
' stick the RowNum in a variable that we can reduce until it's zero
Dim r As Integer
Dim i As Integer
Dim s As String ' holds result
s = ""
r = RowNum
' we start at the right side so if the rownum is 28 we want to be back AB
' need to get 'B' first
Do While RowNum > 0
r = Int((RowNum - 1) / 26)
i = (RowNum - 1) Mod 26
s = Chr(i + 65) & s
RowNum = r
Loop
GetRowLetter = s
End Function
This will give "A" for 1, "B" for 2 etc, then it will give "AA" for 27, "AB" or 28 etc...
If you want to return lower case letters instead, swap the 65 for 98
In your report set the textbox value expression to
=Code.GetRowLetter(RowNumber("myDataSetName"))
swap out myDataSetName with the name of your dataset or scope you want to apply it to. Remember the dataset and scope names are case sensitive and must be surrounded by quotes ( " )

How to sort values in a Join function with LookUpSet in SSRS?

How can I sort the values returned from a LookUpSet function inside a Join function?
Example data:
TransNo MasterTran Item Category ModifierLevel
1001000 1001000 ItemA CategoryB 0
1002000 1001000 ItemB CategoryC 1
1003000 1001000 ItemC CategoryC 1
End result I'd like to get is "CategoryB ItemB ItemC". When I use the following combination of Join and LookUpSet, I end up getting "ItemB CategoryB ItemC".
=Join(LookUpSet(Fields!MasterTransNo.Value, Fields!MasterTransNo.Value, Iif(Fields!ModifierLevel.Value > 0, Trim(Fields!ItemDescription.Value), Trim(Fields!CategoryDescription.Value)), "LineItemDetails"), " ")
This is an expression on a cell in a table. The Row Group is set to Group on TransNo, sort by TransNo. I've tried a variety of different approach to sorting for the group, but always get the same result.
Any ideas on how I can force the order of data from LookUpSet so that it's joined in the order I want?
I ended up figuring this out by seeing other questions looking to pull distinct values only from the Join(LookUpSet()) functions and modifying it. This code is based off the useful answers from this other SO question.
Go to Report Properties
Enter the Code editor and past the following function into the Custom Code box:
Public Function JoinSortAlpha(arr As Object(), delimiter As String) As String
System.Array.Sort(arr)
Dim result As String = String.Empty
For i As Integer = 0 To arr.Length - 1
If Not arr(i) Is Nothing And arr(i) <> String.Empty Then
If result = String.Empty Then
result = arr(i)
Else
result = result + delimiter + arr(i)
End If
End If
Next
Return result End Function
Go to your expression and replace the Join() function with your new function by calling JoinSortAlpha(). My new expression looks like this:
=JoinSortAlpha(LookUpSet(Fields!MasterTransNo.Value, Fields!MasterTransNo.Value, Iif(Fields!ModifierLevel.Value > 0, Trim(Fields!ItemDescription.Value), Trim(Fields!CategoryDescription.Value)), "LineItemDetails"), " ")
Here's a breakdown of what the function is doing:
Create a new function called JoinSortAlpha which will have values passed into it from the expression. In this case, the values from the LookUpSet() function.
Sort the array passed from the function's argument. It's this sort that will make it alphabetical by default.
Create a String object called result to pass the final values to.
Evaluate the array arr and write a value to the result string for each value contained in the arr array. Values in an array are given a numeric value starting at 0 and increasing by 1. Here, we're telling the array to continue populating the result string from the first value in the array (at 0) until the last value in the array which is determined by the length of the array minus 1 (because the array starts at 0 rather than 1).
If your LookUpSet() function doesn't return any values, SSRS will show an error if we don't account for that in this JoinSortAlpha function. To deal with any potential blanks being returned, we're using an If statement to determine if the string is empty in which case it just returns nothing. Otherwise, it will return the value plus the delimiter from the end of the function (a space " " in my case).

parsing the first 2 parts of a string

I have a field called 'Specimen' that has entries formatted like 'CM-Z-01', 'TOR-XY-03', etc. I want to populate 2 additional fields in the same table, called 'TestType' and 'Axis', with the first two sections of the 'Specimen' entry, respectively. So 'TestType' would have 'CM' and 'TOR'; Axis would have 'Z' and 'XY'
I can do the first one just fine, with
UPDATE MechanicalData
SET MechanicalData.TestType = Left(Specimen,InStr(Specimen,"-")-1);
Is there an easy way to grab the middle portion?
You can use the Split function which returns an array with the string parts:
firstPart = Split("TOR-XY-03", "-")(0)
secondPart = Split("TOR-XY-03", "-")(1)
Make a function that you can call in your query based on this function. You cannot use Split directly as it is not supported in SQL.
Public Function SpecimenPart(ByVal s As Variant, ByVal partNo As Long) As Variant
If Nz(s) <> "" Then
Dim parts As Variant
parts = Split(s, "-")
If partNo - 1 <= UBound(parts) Then
SpecimenPart = parts(partNo - 1)
End If
End If
End Function
The parameter partNo is one-based (1 for first part).
UPDATE MechanicalData SET
TestType = SpecimenPart(Specimen, 1),
Axis = SpecimenPart(Specimen, 2);

Aggregate multiplicate function

I have a table of the following:
1 X 10
2 X 30
3 Y 5
4 Y 2
...etc
I need to turn it into:
X 300 //(10 * 30)
Y 10 //(5 * 2)
so I'm in fact looking for a kind of a multiplication function that I could use like sum, avg and stuff... does this exist guys?
for instance:
select field2, **multiply**(field3)
from t
group by field2
Thanks
Ideally, Access SQL would have a PRODUCT aggregate function available, but it doesn't. We can however simulate it by remembering what we learned about logarithms at school (or not...), and remembering that the anti-log of the sum of logs is equal to the product:
SELECT field2, EXP(Sum(LOG(Field3))) AS ProductOfField3
FROM t
GROUP BY Field2
Note that whereas a true PRODUCT function would simply return 0 for a group if there are any zero values, this solution will fail if there are any zero values, so watch out for that. Also, this approach won't work if there are any negative values.
To deal with zeroes we could do this:
SELECT
field2,
EXP(Sum(LOG(IIf(Field3 = 0, 1, Field3)))) AS ProductOfField3,
MIN(ABS(Field3)) AS MinOfAbsField3
FROM t
GROUP BY Field2
and then disregard the ProductOfField3 value for any row where MinOfAbsField3 is zero (as this indicates a group containing a zero, thus the 'true' product should be 0)
To deal with negative values we could further do this:
SELECT
field2,
EXP(Sum(LOG(IIf(Field3 = 0, 1, ABS(Field3))))) AS ProductOfField3,
MIN(ABS(Field3)) AS MinOfAbsField3,
SUM(IIf(Field3 < 0, 1, 0)) AS SumOfNegativeIndicator
FROM t
GROUP BY Field2
and interpret the results with these rules:
If MinOfAbsField3 is zero, disregard ProductOfField3 for that row - the product is zero
Otherwise, the required answer for a given row is ProductOfField3, negated if SumOfNegativeIndicator is odd in that row
You can define following two functions:
Public Function ResetProd() As Boolean
Call Prod(Null)
ResetProd = True
End Function
Public Function Prod(nNumber As Variant) As Double
Static nPrevNumber As Double
If IsNull(nNumber) Then
nPrevNumber = 1
Else
nPrevNumber = nPrevNumber * nNumber
End If
Prod = nPrevNumber
End Function
...and use them as follows:
SELECT PROD(_column_for_wich_you_want_product_) FROM _your_table_
WHERE RESETPROD()