SSRS Group Variables SUM & VB.NET Custom Code - vb.net

I have an SSRS report built using group variables with expressions that do field calculations. The group varaibles are providing correct results between 3 datsets using lookups, arithmatic, and logic operations.
I need to SUM total the results of the variable textbox expressions in the tablix footer. But variables will not work in this way and when I try different expressions in the tablix footer I get errors.
So I did online search of summing group variables and I came to custom code solution using VB.NET variables with functions to aggregate then display the values. But the custom code is not quite working. Please see the custom code at the bottom of the page. And here are some issues I've observed
Custom Code issues
If I use variable as Public Dim the total values changes to 0 when exported to excel (e.g.- "1,214,284" on the screen; "0" when exported to excel.)
If I change declare the variables as Public Dim to Public Shared Dim then the values on screen are the same and they will export to excel.
The problem is Public Shared Dim seems to work great in Visual Studio. But when executed on the Report Server, the variable accumulates every time the report is executed (i.e., ExecEvent #1: "150 value" on the screen & excel; ExecEvent #2: "300 value‬" on the screen & excel; ExecEvent #3: "450 value‬" on the screen & excel).
Any help? How can I make these values aggregate and export? How to get the custom code VB variables to behave correctly. Particularly the variable initialization on the server getting correctly set and reset.
Custom Code correction notes
In the "add" function I added return thisValue to fix an issue where the details variable values with blank (not printing)
References
SSRS Summing Group Variables outside of the group
SSRS code variable resetting on new page
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/d4a3969a-f3fc-457b-8430-733d7b590ff6/use-reportitems-to-sum-all-textboxes-in-a-tablix?forum=sqlreportingservices&prof=required
TablixDesign-WithGroupVaraibles
Group row, Group footer row
Tablix Footer: group variable expression errors outside of group
NOTE: These expressions are not allowed
Variables!varExpenditureLifetime.Value --ERROR: Expressions can only refer to a Variable declared within the same grouping scope, a containing grouping scope, or those declared on the report. Letters in the names of variabels must use the correct cast.
Sum(Variables!varExpenditureLifetime.Value) --ERROR: Variables cannot be used in aggregate functions
REPORT CODE:
Group Variable ("varLWSBegin_LifetimeExpense")
= Code.addLWSBeginLifetimeExpense(CDbl(
IIF(Parameters!boolUseLwsBalance.Value = false, 0,
Lookup(Fields!ProjectId.Value, Fields!ProjectId.Value, Fields!LWSBegin_LifetimeExpense.Value, "dsCAPEXAmountsCustomDataUpload"))
))
Tablix group row
Variables!varLWSBegin_LifetimeExpense.Value
Tablix footer row
Code.getTotalLWSBeginLifetimeExpense()
VB.NET Custom Code
'
' Add group variable values to an external variable declared on the VB Code.
' In Tablix Group Properties variable the value will be the call to the addValue function
' Then on your textbox you call the getValue function:
' Group Var: Code.addValue(Fields!my_field).
' Textbox: Code.getValue()
'
' variable1, addTotalBudget, getTotalBudget
' variable2, addLWSBeginLifetimeExpense, getLWSBeginLifetimeExpense
' variable3, addExpenditureLifetime, getExpenditureLifetime
'
'TEMPLATE
Public totalMyField2 as Integer
Public totalMyFieldName as Integer
Public Function addMyFieldName(ByVal thisMyFieldName AS integer)
totalMyFieldName = totalMyFieldName + thisMyFieldName
End Function
Public Function getMyFieldName()
return totalMyFieldName
End Function
'MyVariables
Public Shared Dim totalTotalBudget as Integer
Public Shared Dim totalLWSBeginLifetimeExpense as Integer
Public Shared Dim totalExpenditureLifetime as Integer
Public Shared Function Initialize()
totalTotalBudget = 0
totalLWSBeginLifetimeExpense = 0
totalExpenditureLifetime = 0
End Function
'Functions
Public Function addTotalBudget(ByVal thisValue AS Integer )
totalTotalBudget = totalTotalBudget + thisValue
return thisValue
End Function
Public Function addLWSBeginLifetimeExpense(ByVal thisValue AS Integer )
totalLWSBeginLifetimeExpense = totalLWSBeginLifetimeExpense + thisValue
return thisValue
End Function
Public Function addExpenditureLifetime(ByVal thisValue AS Integer )
totalExpenditureLifetime = totalExpenditureLifetime + thisValue
return thisValue
End Function
Public Function getTotalBudget()
return totalTotalBudget
' Dim myval as Integer = totalTotalBudget
' totalTotalBudget = 0
' return myval
End Function
Public Function getTotalLWSBeginLifetimeExpense()
return totalLWSBeginLifetimeExpense
' Dim myval as Integer = totalLWSBeginLifetimeExpense
' totalLWSBeginLifetimeExpense = 0
' return myval
End Function
Public Function getTotalExpenditureLifetime()
return totalExpenditureLifetime
' Dim myval as Integer = totalExpenditureLifetime
' totalExpenditureLifetime = 0
' return myval
End Function
'<END>

Easiest approach to be able to use variables like you are trying to is to use Report Variables instead of Group Variables. If you use Report Variables, it can be accessed from any scope.
You might have to change your dataset a little bit so that the aggregation is unmistakably grouped when calculated at the report level. I could not really guide you with that because I don't know your data like you do. But as an easier route to the scope of your aggregation, check this SO question. You can use your table group as the scope of your aggregate functions.
I've had to do something along the lines of what you are trying to accomplish and Report Variables came to the rescue for me. Let me know if this would work in your scenario.

Related

How to set 2 arguments on Let function in a class in vba (for excel)?

I am creating a Class in vba (for excel) to process blocks of data. After some manipulation of a text file I end up with blocks of data (variable asdatablock() ) which I want to process in a For Loop
I created my own Class called ClDataBlock from which I can get key data by a simple call of the property required. 1st pass seems to work and I am now trying to expand my Let function to 2 argument but it’s not working. How do I specify the 2nd argument?
Dim TheDataBlock As New ClDataBlock
For i = 0 to UBound(asdatablock)
asDataBlockLine = Split(asdatablock(i), vbLf) ‘ split block into line
TheDataBlock.LineToProcess = asDataBlockLine(5) ‘allocate line to process by the class
Dvariable1 = TheDataBlock.TheVariable1
‘and so on for the key variables needed base don the class properties defined
Next i
In the Class Module the Let function takes 2 arguments
Public Property Let LineToProcess(stheline As String, sdataneeded As String)
code extract of what I am looking at -
'in the class module
Dim pdMass As Double
Private pthelineprocessed As String
Public Property Let LineToProcess(stheline As String, sdataneeded As String)
pthelineprocessed = DeleteSpaces(Replace(stheline, vbLf, ""))
Dim aslinedatafield() As String
Select Case sdataneeded
'THIS IS AN EXTRACT FROM THE FUNCTION
'THERE ARE AS NUMBER OF CASES WHICH ARE DEALT WITH
Case Is = "MA"
aslinedatafield() = Split(pthelineprocessed, " ")
pdbMass = CDbl(aslinedatafield(2))
End select
End function
Public Property Get TheMass() As Double
TheMass = pdMass
End Property
'in the "main" module
Dim TheDataBlock As New ClDataBlock
For i = 0 to UBound(asdatablock)
TheDataBlock.LineToProcess = asDataBlockLines(5) 'Need to pass argument "MA" as well
dmass = TheDataBlock.TheMass
'and so on for all the data to be extracted
Next i
When a Property has 2 or more arguments, the last argument is what is getting assigned. In other words, the syntax is like this:
TheDataBlock.LineToProcess("MA") = asDataBlockLine(5)
This means you need to change the signature of your property:
Public Property Let LineToProcess(sdataneeded As String, stheline As String)

Error In Function Name

I get an error when trying to use the below function. The strange part is that the error occurs in the name
Code:
Function DATECHECK(rng As Range, date_time As Date) As Boolean
For Row = 1 To rng.Rows.Count
'Stuff'
Next Row
End Function
Syntax:
DateCheck(Sheet2!A2:B561, Sheet1!A2)
Error:
#NAME
#NAME(Sheet2!A2:B561, Sheet1!A2)
Make sure the function is in a public module; not a private worksheet code sheet.
DateCheck should return something. Add DateCheck = 1 before End Function.
You cannot manipulate values of other cells with a worksheet UDF. You decided that showing the relevant code wasn't important; it was important.
In your function's context, Row is a variable. You need to declare it as a long (e.g. dim row as long) if you are using Option Explicit.

ByRef argument type mismatch in Excel VBA

I'm working with VBA. I wrote a user define function that takes a string, process it and return a cleaned string. I am not sure what is wrong with it. I am not able to call it and ask it to process my string and return it. I am thinking there are a mistake in the way I am defining or returning it.
Public Function ProcessString(input_string As String) As String
' The temp string used throughout the function
Dim temp_string As String
For i = 1 To Len(input_string)
temp_string = Mid(input_string, i, 1)
If temp_string Like "[A-Z, a-z, 0-9, :, -]" Then
return_string = return_string & temp_string
End If
Next i
return_string = Mid(return_string, 1, (Len(return_string) - 1))
ProcessString = return_string & ", "
End Function
And I use this function like this
Worksheets(data_sheet).Range("C2").Value = ProcessString(last_name)
Last name is a string variable, usually looks like this Lastname*****, and I am trying to remove all the stars behind it. Have it return Lastname without the stars.
I received Compile error: ByRef arugment type mismatch when I tried to run this. I am using Windows XP with Office 2003.
EDIT: I added the basic struction of the code I have, I have about 20 lines of the similar code. Doing the same thing for each field I need.
Private Sub CommandButton2_Click()
' In my original production code I have a chain of these
' Like this Dim last_name, first_name, street, apt, city, state, zip As String
Dim last_name As String
' I get the last name from a fixed position of my file. Because I am
' processing it from another source which I copied and pasted into excel
last_name = Mid(Range("A4").Value, 20, 13)
' Insert the data into the corresponding fields in the database worksheet
Worksheets(data_sheet).Range("C2").Value = ProcessString(last_name)
I suspect you haven't set up last_name properly in the caller.
With the statement Worksheets(data_sheet).Range("C2").Value = ProcessString(last_name)
this will only work if last_name is a string, i.e.
Dim last_name as String
appears in the caller somewhere.
The reason for this is that VBA passes in variables by reference by default which means that the data types have to match exactly between caller and callee.
Two fixes:
1) Force ByVal -- Change your function to pass variable ByVal: Public Function ProcessString(ByVal input_string As String) As String, or
2) Dim varname -- put Dim last_name As String in the caller before you use it.
(1) works because for ByVal, a copy of input_string is taken when passing to the function which will coerce it into the correct data type. It also leads to better program stability since the function cannot modify the variable in the caller.
I don't know why, but it is very important to declare the variables separately if you want to pass variables (as variables) into other procedure or function.
For example there is a procedure which make some manipulation with data: based on ID returns Part Number and Quantity information. ID as constant value, other two arguments are variables.
Public Sub GetPNQty(ByVal ID As String, PartNumber As String, Quantity As Long)
the next main code gives me a "ByRef argument mismatch":
Sub KittingScan()
Dim BoxPN As String
Dim BoxQty, BoxKitQty As Long
Call GetPNQty(InputBox("Enter ID:"), BoxPN, BoxQty)
End sub
and the next one is working as well:
Sub KittingScan()
Dim BoxPN As String
Dim BoxQty As Long
Dim BoxKitQty As Long
Call GetPNQty(InputBox("Enter ID:"), BoxPN, BoxQty)
End sub
I changed a few things to work with Option Explicit, and the code ran fine against a cell containing "abc.123", which returned "abc.12,". There were no compile errors.
Option Explicit ' This is new
Public Function ProcessString(input_string As String) As String
' The temp string used throughout the function
Dim temp_string As String
Dim i As Integer ' This is new
Dim return_string As String ' This is new
For i = 1 To Len(input_string)
temp_string = Mid(input_string, i, 1)
If temp_string Like "[A-Z, a-z, 0-9, :, -]" Then
return_string = return_string & temp_string
End If
Next i
return_string = Mid(return_string, 1, (Len(return_string) - 1))
ProcessString = return_string & ", "
End Function
I'll suggest you post more of your relevant code (that calls this function). You've stated that last_name is a String, but it appears that may not be the case. Step through your code line by line and ensure that this is actually the case.
While looping through your string one character at a time is a viable method, there's no need. VBA has built-in functions for this kind of thing:
Public Function ProcessString(input_string As String) As String
ProcessString=Replace(input_string,"*","")
End Function
Something is wrong with that string try like this:
Worksheets(data_sheet).Range("C2").Value = ProcessString(CStr(last_name))
It looks like ByRef needs to know the size of the parameter. A declaration of
Dim last_name as string
doesn't specify the size of the string so it takes it as an error. Before using
Worksheets(data_sheet).Range("C2").Value = ProcessString(last_name)
The last_name has to be declared as
Dim last_name as string *10 ' size of string is up to you but must be a fix length
No need to change the function. Function doesn't take a fix length declaration.
For me the problem here was that I was declaring multiple variables in a row instead of separate rows.
For example, I was trying to pass i as an integer to my function.
Dim i,j as integer - gets me the error
Dim i as integer - doesn't get the error

parse several field using file helper

Good day to all,
i have a problem regarding CSV parse using File Helper. My CSV is look like this
,,,026642,0,00336,05,19,"WATERMELON *",19,"1 ",,,,,,,,0,,001.99.,0,,,,,0,,0,0,,,,,,,,,,,,,,,,,,51,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,026645,0,00338,05,19,"ONION ",19,"*1 ",,,,,,,,0,,002.99.,0,,,,,0,,0,0,,,,,,,,,,,,,,,,,,51,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,026687,0,00380,05,19,"MUSHROOM ",19," (BLACK FUNGUS) ",,,,,,,,0,,021.90.,0,,,,,0,,0,0,,,,,,,,,,,,,,,,,,51,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
which this CSV have 116 column / field.
The problem was i just need only 4 field from whole line which
Field 4 = 026687, Field 9 = "WATERMELON *", Field 11 = "(BLACK FUNGUS)", Field 21 = 002.99.
When i using wizard which a very good solution to make instance class, and i put FieldValueDiscarded _ on top of every other fields i don't need it, it just print a same as CSV input.
Please give me some advise how do i extract only needed field to write into output.
Thank you
UPDATED : After research some more, i finally getting clear about this error. This error happen because class non-inherited so i cannot get specific field into another class. By declare mapping class as inherited class, i can get specific field.
However, i stuck at how to retrieve functions inside the class who inherited from mapping class. This is my code
`Imports System.Text
Imports System.IO
Imports FileHelpers
Public Class ProcessField : Inherits InputCSV
Public Function MyPLUc(ByVal value As Integer)
Dim PLUc As String
MyBase.PLU = value
PLUc = (0 + 0 + value)
Return (0 + 0 + value)
End Function
Public Function MyStatusc(ByVal value As Integer)
MyBase.Status = value
Dim Status As Integer
If value > 0 Then
Status = 800
Else
Status = 900
End If
Return (0 + Status)
End Function
Public Function MyUnitPricec(ByVal value As Integer)
MyBase.UnitPrice = value
Dim UP As Integer
UP = value
Dim bytes As Byte() = System.Text.Encoding.Unicode.GetBytes(UP)
Return (0 + 0 + 0 + UP)
End Function
Public Function MyLabelFormat(ByVal value As Integer)
Return (1 + 1)
End Function
Public Function MyEAN(ByVal value As Integer)
Return (0 + 6)
End Function
Public Function MyCName(ByVal value As String)
MyBase.CName1 = value
Dim hexString As String = Hex(value)
Return (hexString)
End Function
Public Function MyBCC(ByVal value As String)
value = (0 + 0)
Return (0 + 0)
End Function
End Class`
and the problem is how i retrieve all return value in these function
I'm not sure I understand your question, but I think you are making things more complicated than you need.
You can just create your FileHelpers class with 116 string fields. They should be (public) fields, NOT properties. You should NOT subclass the FileHelpers class. Do not try to use the FileHelpers class as a normal class (i.e., with properties, functions, etc, subclasses). Think of the FileHelpers class as a 'specification' of your CSV format only.
To import, you write something like:
Dim engine As New FileHelperEngine(GetType(RecordSpec))
' To Read Use:
Dim results As RecordSpec() = DirectCast(engine.ReadFile("FileIn.txt"), RecordSpec())
Then you have an array of RecordSpec. Each RecordSpec will have all 116 fields populated, but just ignore the fields you don't need. Then loop through the results and do whatever you want with the values. For instance, perhaps you need to map the imported fields to another (more normal) MyProduct class with properties instead of fields and perhaps with additional logic.
For Each recordSpec As RecordSpec In results
Dim myProduct = New MyProduct()
myProduct.Id = recordSpec.Field4
myProduct.Name = recordSpec.Field9
myProduct.Category = recordSpec.Field23
' etc.
Next
In summary: the RecordSpec class should only be used to define the structure of the CSV file. You use it to populate a simple array with all the values from the file. You then map the values to a more useful class MyProduct.

Problem with Write Custom Function in reportViewer repot

I want to use of a custom function in reportviewer's expression report .
I wrote this function in code tab section in report's property.
I want to use of this function in my feild's expression but when i write "Code" and put after that "." , intellisense in report's expression does not show me my function.
Public Function FarsiNumber(ByVal str As String) As String
Dim s As String = ""
Dim ch() As Char = str.ToCharArray
For Each c In ch
If IsNumeric(c) Then
s += CChar(ChrW(1728 + CInt(AscW(c))))
Else
s += c.ToString
End If
Next
Return s
End Function
any body can show me an example.
thanks
The Intellisense doesn't catch my custom functions either. But you can still use them.
In your case, you can use Code.FarsiNumber() in your expressions in your report