sum two values from different datasets using lookups in report builder - ssrs-2008

I have a report that should read values from 2 dataset by Currency:
Dataset1: Production Total
Dataset2: Net Total
Ive tried to use:
Lookup(Fields!Currency_Type.Value,
Fields!Currency_Type1.Value,
Fields!Gross_Premium_Amount.Value,
"DataSet2")
This returns only the first amount from dataset 2.
I've tried Lookupset function as well but it didn't SUM the retrieved values.
Any help would be appreciated.

Thanks Jamie for the reply.
THis is what i have done and it worked perfect:
From Report Properties--> Code , write the below function:
Function SumLookup(ByVal items As Object()) As Decimal
If items Is Nothing Then
Return Nothing
End If
Dim suma As Decimal = New Decimal()
Dim ct as Integer = New Integer()
suma = 0
ct = 0
For Each item As Object In items
suma += Convert.ToDecimal(item)
Next
If (ct = 0) Then return 0 else return suma
End Function
Then you can call the function:
code.SumLookup(LookupSet(Fields!Currency_Type.Value, Fields!Currency_Type1.Value,Fields!Gross_Premium_Amount.Value, "DataSet2"))

Yes, Lookup will only return the first matching value. Three options come to mind:
Change your query, so that you only need to get one value: use a GROUP BY and SUM(...) to combine your two rows in the query. If you are using this query other places, then make a copy and change that.
Is there some difference in the rows? Such as one is for last year and one is for this year? If so, create an artificial lookup key and lookup the two values separately:
=Lookup(Fields!Currency_Type.Value & ","
& YEAR(DATEADD(DateInterval.Year,-1,today())),
Fields!Currency_Type1.Value & ","
& Fields!Year.Value,
Fields!Gross_Premium_Amount.Value,
"DataSet2")
+
Lookup(Fields!Currency_Type.Value & ","
& YEAR(today()),
Fields!Currency_Type1.Value & ","
& Fields!Year.Value,
Fields!Gross_Premium_Amount.Value,
"DataSet2")
Use the LookupSet function as mentioned. With this you'll get a collection of the values back, and then need to add those together. The easiest way to do this is with embedded code in the report. Add this function to the report's code:
Function AddList(ByVal items As Object()) As Double
If items Is Nothing Then
Return 0
End If
Dim Total as Double
Total = 0
For Each item As Object In items
Total = Total + CDbl(item)
Next
Return Total
End Function
Now call that with:
=Code.AddList(LookupSet(Fields!Currency_Type.Value,
Fields!Currency_Type1.Value,
Fields!Gross_Premium_Amount.Value,
"DataSet2"))
(Note: this code was not tested. I just composed it in the Stack Overflow edit window & I'm no fan of VB. But it should give you a good idea of what to do.)

Related

Libreoffice calc - how to write a same value into a range

I know how to 'select' a range in LO (7.2.4.1) Calc BASIC ....
ThisComponent.CurrentController.ActiveSheet.getCellRangeByName("D1:H6")
But how to write a value, e.g. "1", into that range using BASIC?
myRange = ThisComponent.CurrentController.ActiveSheet.getCellRangeByName("D1:H6")
myRange.Value = 1
Gives an "property or method not found" error. But I can't find any properties or values to go after Range to allow me to do what I want. Flailing around and trying
myRange.setValue = 1
myRange.writeValue = 1
myRange.setString = "1"
and numerous other variants don't work either.
Would really appreciate the solution. Thanks.
You can edit the value of an individual cell, but not the entire range. You will have to iterate over all the cells in the range one at a time, changing the value of each of them.
Sub Set1ToD1H6
myRange = ThisComponent.CurrentController.ActiveSheet.getCellRangeByName("D1:H6")
For i = 0 To myRange.getRows().getCount()-1
For j = 0 To myRange.getColumns().getCount()-1
myRange.getCellByPosition(j, i).setValue(1)
Next j
Next i
End Sub
But since the read-write operation to a cell is comparable in time to the read-write operation to a whole range, it is preferable to use another method - to prepare data in an array and write from it to a range in one operation:
Sub Set1ToRange
myRange = ThisComponent.CurrentController.ActiveSheet.getCellRangeByName("D1:H6")
dataOfRange = myRange.getData()
For i = LBound(dataOfRange) To UBound(dataOfRange)
For j = LBound(dataOfRange(i)) To UBound(dataOfRange(i))
dataOfRange(i)(j) = 1
Next j
Next i
myRange.setData(dataOfRange)
End Sub
(For your example, this will be approximately 30 times faster, for a larger range the time winnings will be even more significant)
The .getData() and .setData() methods work on numeric range values. To work with text strings (and numbers), use .getDataArray() and .setDataArray(), for working with cell formulas use .getFormulaArray() and .setFormulaArray()

VBA Autofilter subset contains extra row up top

The macro attempts to filter Sheet "Temp" for one Criteria at a time (PE, AR, DC,FI), and copy column 5 that contains non-duplicate data into another sheet "Detail". Please help me understand two issues. (1) The macro does correct filtering for each of the 4 criteria. However, the filtered list for each of the criteria always contains the first item from the filtered list of the very first criteria "PE". I.e. the filtered list for criteria 2, "AR", contains all items in AR, but starts with the first item in "PE". There's a header row, but it doesn't seem to make a difference. How can I get rid of that first item in all cases except when filtering for "PE" (where it belongs)? (2) I would like to be able to count and store the number of visible rows for each filtered list. I would like to be able to paste each filtered list into another spreadsheet ("Detail"), starting in cell A4. Each consecutive list should start two rows below the list that was just pasted. For example, if the first list contains 16 items, then the next list should start in cell A22 (A4+16+2). For some reason, copiedrows (used to remember number of rows in a filtered list) is correct the first time around (=16), but not the second time (=1?). It looks like q's 1 & 2 are related. Perhaps, if I figure out #1, I can do something about #2. I reviewed exiting posts on Autofiltering, but still feel a bit stuck here. Really appreciate your help!
Sub FilterCategories()
Dim LastRow As Long
Dim startpos As Integer
Dim k As Integer
Dim copiedrows(1 To 4) As Long
Dim AG(1 To 4) As String
Dim rng As Range
AG(1) = "PE"
AG(2) = "AR"
AG(3) = "DC"
AG(4) = "FI"
'Autofilter based on each AG and copy over to 'Detail'. Create temporary
sheet for filtering.
startpos = 4
For k = LBound(AG) To UBound(AG)
Application.DisplayAlerts = False
On Error Resume Next
Sheets("Temp").Delete
Sheets("Lookup").AutoFilterMode = False
Sheets("Lookup").Copy After:=Sheets("Lookup")
ActiveSheet.Name = "Temp"
With Sheets("Temp")
AutoFilterMode = False
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
With .Range("A2:E" & LastRow)
.AutoFilter Field:=4, Criteria1:=AG(k)
.RemoveDuplicates Columns:=5
.Columns(5).SpecialCells(xlCellTypeVisible).Copy
Destination:=Sheets("Detail").Range("A" & startpos)
copiedrows(k) = .SpecialCells(xlCellTypeVisible).Rows.Count
Debug.Print copiedrows(k)
startpos = copiedrows(k) + 6
Debug.Print startpos
End With
End With
Next
End Sub

SSRS Max date from Lookupset

I've spent a long time looking around for a solution for this and not found quite what I want. Efforts to adapt existing solutions for different problems have also not worked!
I am using LookupSet to return a list of dates, then joining them to return a list:
=Join(LookupSet(Fields!cPatSer.Value,Fields!cPatSer.Value,Fields!DDate.Value,"PatD"))
I want to only show the most recent date from that list. Here is what I have tried so far:
The above function wrapped in a Max function (doesn't work because Join returns a string)
Using a split function to split the resultant string looking for the commas then using the max function
Doing both of the above but converting the output to Date objects using CDate and DateTime.Parse first as follows...
=Join(LookupSet(Fields!cPatSer.Value,Fields!cPatSer.Value,CDate(Fields!DDate.Value),"PatD"))
=Join(LookupSet(Fields!cPatSer.Value,Fields!cPatSer.Value,DateTime.Parse(Fields!DDate.Value),"PatD"))
Can anybody provide any pointers please?
I've found a solution using Custom Code. Oz Locke made a function that does various aggregates for integer data (links below), and I've amended this to work for dates instead.
In the Code property of the report, paste in this:
'Amended from Oz Locke's code:
'https://github.com/OzLocke/SSRSAggLookup/blob/master/AggLookup.vb
'Allows users to adjust the aggregation type of lookupsets in a cell
Function AggLookup(ByVal choice As String, ByVal items As Object)
'Ensure passed array is not empty
'Return a zero so you don't have to allow for Nothing
If items Is Nothing Then
Return 0
End If
'Define names and data types for all variables
Dim current As Date
Dim count As Integer
Dim min As Date
Dim max As Date
Dim err As String
'Define values for variables where required
current = CDate("01/01/1900")
count = 0
err = ""
'Calculate and set variable values
For Each item As Object In items
'Calculate Count
count += 1
'Check value is a number
If IsDate(item) Then
'Set current
current = CDate(item)
'Calculate Min
If min = Nothing Then
min = current
End If
If min > current Then
min = current
End If
'Calculate the Max
If max = Nothing Then
max = current
End If
If max < current Then
max = current
End If
'If value is not a number return "NaN"
Else
err = "NaN"
End If
Next
'Select and set output based on user choice or parameter one
If err = "NaN" Then
If choice = "count" Then
Return count
Else
Return 0
End If
Else
Select Case choice
Case "count"
Return count
Case "min"
Return min
Case "max"
Return max
End Select
End If
End Function
Then in the cell of your report, use this expression:
=code.AggLookup("max", LookupSet(Fields!cPatSer.Value,Fields!cPatSer.Value,Fields!DDate.Value,"PatD"))
https://itsalocke.com/aggregate-on-a-lookup-in-ssrs/
https://github.com/OzLocke/SSRSAggLookup/blob/master/AggLookup.vb

Getting the total number of records in PagedList

The datagrid that I use on the client is based on SQL row number; it also requires a total number of pages for its paging. I also use the PagedList on the server.
SQL Profiler shows that the PagedList makes 2 db calls - the first to get the total number of records and the second to get the current page. The thing is that I can't find a way to extract that total number of records from the PagedList. Therefore, currently I have to make an extra call to get that total which creates 3 calls in total for each request, 2 of which are absolutely identical. I understand that I probably won't be able to rid of the call to get the totals but I hate to call it twice. Here is an extract from my code, I'd really appreciate any help in this:
var t = from c in myDb.MyTypes.Filter<MyType>(filterXml) select c;
response.Total = t.Count(); // my first call to get the total
double d = uiRowNumber / uiRecordsPerPage;
int page = (int)Math.Ceiling(d) + 1;
var q = from c in myDb.MyTypes.Filter<MyType>(filterXml).OrderBy(someOrderString)
select new ReturnType
{
Something = c.Something
};
response.Items = q.ToPagedList(page, uiRecordsPerPage);
PagedList has a .TotalItemCount property which reflects the total number of records in the set (not the number in a particular page). Thus response.Items.TotalItemCount should do the trick.

MS Access 2010 Form Box Control Source IIF Statement

I am running into the Max Character Issue when trying to put my IIF statement into a box I have created for the calculation of a score on my form. The box code is:
=IIf([cbov1]="na" And [cbov2]="na" And [cbov3]="na" And [cbov4]="na" And [cbov5]="na" And [cboV6]="na" And [cboV7]="na" And [cboV8]="na" And [cboV9]="na" And [cboV10]="na" And [cboV11]="na" And [cboV12]="na" And [cboV13]="na" And [cboi1]="na" And [cboi2]="na" And [cboi3]="na" And [cboi4]="na" And [cbop1]="na" And [cbop2]="na" And [cbop3]="na" And [cbop4]="na" And [cbop5]="na" And [cbop6]="na" And [cbop7]="na" And [cbop8]="na" And [cbop9]="na" And [cbop10]="na" And [cbop11]="na" And [cbof1]="na" And [cbof2]="na" And [cbof3]="na" And [cbof4]="na" And [cbof5]="na" And [cbof6]="na" And [cbof7]="na" And [cbof8]="na" And [cbof9]="na" And [cbof10]="na" And [cbom1]="na" And [cbom2]="na" And [cbom3]="na" And [cbom4]="na" And [cbom5]="na" And [cbom7]="na" And [cbom8]="na" And [cbom9]="na" And [cbom10]="na" And [cbom6]="na",0,(IIf([cboV1]="yes",0,0)+IIf([cbov2]="yes",0,0)+IIf([cbov3]="yes",0,0)+IIf([cbov4]="yes",0,0)+IIf([cbov5]="yes",0,0)+IIf([cboV6]="yes",0,0)+ IIf([cboV7]="yes",0,0)+ IIf([cboV8]="yes",0,0)+ IIf([cboV9]="yes",0,0)+ IIf([cboV10]="yes",0,0)+ IIf([cboV11]="yes",0,0)+ IIf([cboV12]="yes",0,0)+ IIf([cboV13]="yes",0,0)+IIf([cboi1]="yes",5,0)+IIf([cboi2]="yes",3,0)+IIf([cboi3]="yes",3,0)+ IIf([cboi4]="yes",4,0)+IIf([cbop1]="yes",5,0)+IIf([cbop2]="yes",5,0)+IIf([cbop3]="yes",5,0)+IIf([cbop4]="yes",5,0)+ IIf([cbop5]="yes",5,0)+ IIf([cbop6]="yes",4,0)+ IIf([cbop7]="yes",4,0)+ IIf([cbop8]="yes",4,0)+ IIf([cbop9]="yes",4,0)+ IIf([cbop10]="yes",2,0)+IIf([cbop11]="yes",2,0)+IIf([cbof1]="yes",1,0)+IIf([cbof2]="yes",1,0)+IIf([cbof3]="yes",1,0)+IIf([cbof4]="yes",1,0)+ IIf([cbof5]="yes",1,0)+ IIf([cbof6]="yes",1,0)+ IIf([cbof10]="yes",0,0)+ IIf([cbof7]="yes",3,0)+ IIf([cbof8]="yes",3,0)+ IIf([cbof9]="yes",3,0)+IIf([cbom1]="yes",5,0)+IIf([cbom2]="yes",1,0)+IIf([cbom3]="yes",1,0)+IIf([cbom4]="yes",1,0)+IIf([cbom5]="yes",1,0)+IIf([cbom6]="yes",1,0) +IIf([cbom7]="yes",3,0) +IIf([cbom8]="yes",2,0) +IIf([cbom9]="yes",5,0) +IIf([cbom10]="yes",5,0))/(IIf([cboV1]="na",0,0)+IIf([cbov2]="na",0,0)+IIf([cbov3]="na",0,0)+IIf([cbov4]="na",0,0)+IIf([cbov5]="na",0,0)+IIf([cboV6]="na",0,0)+ IIf([cboV7]="na",0,0)+ IIf([cboV8]="na",0,0)+ IIf([cboV9]="na",0,0)+ IIf([cboV10]="na",0,0)+ IIf([cboV11]="na",0,0)+ IIf([cboV12]="na",0,0)+ IIf([cboV13]="na",0,0)+IIf([cboi1]="na",0,5)+IIf([cboi2]="na",0,3)+IIf([cboi3]="na",0,3)+ IIf([cboi4]="na",0,4)+IIf([cbop1]="na",0,5)+IIf([cbop2]="na",0,5)+IIf([cbop3]="na",0,5)+IIf([cbop4]="na",0,5)+ IIf([cbop5]="na",0,5)+ IIf([cbop6]="na",0,4)+ IIf([cbop7]="na",0,4)+ IIf([cbop8]="na",0,4)+ IIf([cbop9]="na",0,4)+ IIf([cbop10]="na",0,2)+ IIf([cbop11]="na",0,2)+IIf([cbof1]="na",0,1)+IIf([cbof2]="na",0,1)+IIf([cbof3]="na",0,1)+IIf([cbof4]="na",0,1)+ +IIf([cbof5]="na",0,1)+ +IIf([cbof6]="na",0,1)+ +IIf([cbof7]="na",0,3)+ +IIf([cbof8]="na",0,3)+ +IIf([cbof9]="na",0,3)+ +IIf([cbof10]="na",0,0)+IIf([cbom1]="na",0,5)+IIf([cbom2]="na",0,1)+IIf([cbom3]="na",0,1)+IIf([cbom4]="na",0,1)+IIf([cbom5]="na",0,1)+IIf([cbom6]="na",0,1) +IIf([cbom7]="na",0,3) +IIf([cbom8]="na",0,2) +IIf([cbom9]="na",0,5) +IIf([cbom10]="na",0,5)))*(IIf([cbov1]="no" Or [cbov2]="no" Or [cbov3]="no" Or [cbov4]="no" Or [cbov5]="no" Or [cboV6]="no" Or [cboV7]="no" Or [cboV8]="no" Or [cboV9]="no" Or [cboV10]="no" Or [cboV11]="no" Or [cboV12]="no" Or [cboV13]="no",0,1))
The purpose of the score is to score "Yes" with points, Score "No" as no points, and then have "NA" remove from the overall score. So if a person has 67 out of 67 points, they get a 100. The maximum points is 100 if all questions are answered "Yes" or "No". I need to have all portions of the calculation because CBOV1-13 have a stipulation of if they are "No" the score is automatically 0%.
I don't know of a work around for the MAX CHARACTER you get within the expression builder on the Control Source box via the properties sheet.
Any help on a work around for this issue or ways to make the code shorten and fit with the same end result would be a huge help.
First, I would be tempted to have my field as a numeric (0,1,2 instead of "na,Yes,No"
Then you could use addition...IIF{cvb01 + Cvb02 +cvb03 = 0, 0 ,...else
Using Strings
I can think of two ways. One in the formula using concatenation (ugly)
IIF[cvb01] & [cvb02] & [cvb03] = "NANANA", 0 , ...Else)
I would be more tempted to write a function to take care of it.
dim NAcount as integer
Dim YesCount as integer
Dim NoCount as integer
dim ctr as integer
dim StrAns as string
for ctr = 1 to 10
StrAns = Fields ("cvb" & Ctr)
Select case StrAns
Case "NA"
NaCount = NACount + 1
'...add values here
Case "Yes"
'...more values go here
Case "No"
'... more values
End Select
Next Ctr
...