I have report in .rdlc format. I have inserted table in my report which is filled in programatically(in runtime) from datatable(which is also filled by dataadapter programatically). Also I want in table to use conditional formatting - background color of cell based on value. To do that in BackGroundColor property of needed column expression was inserted:
=iif(cdbl(Fields!MyField.Value),"Green","Yellow")
I haven't mentioned that all fields in my datatable are string. Therefore i use cdbl function to convert string to double. And when I render report, i don't have the desired result.
Therefore questions:
How to make sure there is no parsing error?
Is it possible to see step by step computation (as in excel)?
And what else error could be?
I suspect problem might be in culture.
The quickest way to test is to call
=iif(cdbl("3.14"),"Green","Yellow")
=iif(cdbl("3,14"),"Green","Yellow")
And see if it's working.
I don't have a reporting services right now and can't test it. I think you can do a tryParse in Reporting services.
Related
I have searched and searched and have not been able to find the answer to this. I'm no stranger to SSRS, .Net (c# and vb.net), SQL, etc...been in it for years. I currently have a multi-select report parameter that is populated by a dataset in my report. There are hundreds of entries, so I built it to be driven by a wildcard character in a preceding parameter. Everything works fine right now. My question is this: is it possible to enter a wildcard value, select one (or more) of the filtered values and then store that/those value(s) on selection so that a user can go back and enter another wildcard value and select from a newly filtered list? (Basically, remember what has been selected in the overall dataset before report execution and create some sort of comma-separated list as the final parameter value to be passed to the report) I realize this may be better served in a web app w/a reportviewer control, but I'm trying to avoid deviating from the native SSRS server if possible. Thanks in advance!
The way I might approach this (not actually done it but the theory sounds ok)
Have 2 parameters for user input, your current one and a hidden one called say #filter (visible) and #filterHistory (this is the hidden one)
Have a textbox (formatted like button) with something like "Refine" as the text. Set the action to call your report again but set the #filterHistory to be something like #filterHistory & ", " & #filter. Basically we keep appending the last user input to the history.
Then your report would filter based on both parameters. You'll have to do some parsing of the delimited parameter now to split it out into the constituent parts but you get the idea.
I've no time to build a test report but hopefully that will point you in the right direction. If it doesn't help or work then comment and I'll see if I can knock up a quick example.
TL;DR In a SSRS 2008 report which uses a custom assembly to do some extra calculations can I pass an entire report dataset as a method parameter?
Full story
I have an SSRS report with 3 datasets, each returned from an SQL query.
(In case it makes a difference to my question they're currently shared datasets although I'm sure local would work too)
The largest and primary dataset is a list of tasks which may or may not have been completed. I have information in here such as the ID, status, create date/time, target resolution hours etc of each task.
This dataset is displayed in a tablix and is the focus of the report.
The remaining two datasets are not displayed and are for reference. One is a simple one column query which returns a list of holiday dates for the UK. The other is a small table which contains our exact business hours.
At the moment I'm able to loop through the rows in the tablix of tasks and pass multiple values from the current row to a method. This is useful if I want to do some calculations based on data found only in the current row. For example I could take the create date/time and the response target hours and the assembly would return a target date/time for the current task. Cool so far.
I want to do a more complicated version of this where I not only pass in the row data but the 2 other datasets to get my return value. This is because in reality the due date calculation is much more complex and must take into account changing business hours and holidays from the other 2 datasets.
Can I pass a dataset as a method parameter to an assembly? Something like:
=Code.MyClass.MyMethod(val1, val2, dataset1, dataset2);.
I've been unable to find much definitive information on this. Nearly all tutorials demonstrate what I'm already doing by processing single rows. I'm sure I had an MSDN article that hinted this was not possible but I've lost it (helpful I know). There's a post on the Microsoft forums where a moderator says it's not possible. The general lack of information and tutorials suggests it's not possible or I'm doing this in the wrong way.
Any suggestions?
(I have alternate solutions such as having the assembly fetch the other datasets or just writing something outside SSRS but I'm not pursuing those until I knnow whether it can be done this way).
An older topic on the MSDN forums Iterate through rows of dataset in report's custom code offers a more definitive answer as well as a potential solution to this problem.
Passing the DataSet as an object or collection is not a possibility because:
A dataset in Reporting Services is not the same type of object as an ADO.Net dataset. A report dataset is an internal object managed by the SSRS runtime (it's actually derived from a DataReader object) and not an XML structure containing datatables, etc. and cannot be passed into the report's custom code.
The only way to effectively loop through the rows of a report dataset is to call a custom function or referenced method in a report data region expression. Using this technique, it may be possible to pass all of the the row and field information into a code structure, array or collection.
The hint given in the above statement suggests passing row and field information into a code structure. A contributor to the linked MSDN topic, Migeul Catalao developed a workaround using such an approach.
A real-world scenario of it's usage with example code demonstrating Migeul Catalao's solution can be found here.
Granted, it is still more of a row-by-row approach, so I would strongly suggest moving outside of SSRS and pursue alternative solutions.
Although I've accepted the other answer due to it being clear and helpful I didn't use that solution in the end (I was too stupid to understand it) and went for something else that works.
Disclaimer: This is a horrible hack. It works absolutely great in my scenario so I though I'd share in case it was useful to somebody else. There are many pitfalls here which could most likely be worked around given time.
I ended up following the advice in the comment given by Steven White and looking into LookupSet. This function allows you to query a dataset to return matching rows and a single column of data.
It looks like this:
LookupSet(Fields!ComparisonField.Value, // The value to search for, e.g '001'.
Fields!MatchField.Value, // The column to match on in the target dataset.
Fields!MyColumn.Value, // The column that will be returned.
"MyDataSet") // The dataset to search.
This returns a string array representing the returned values.
So far so good, but I needed ALL columns and rows. This is where the dirty hack appears in the form of string concatenation:
LookupSet(0, // Dummy ID 0.
0, // Matches the dummy ID 0 so all rows are returned.
Fields!Column1.Value + "[^]" // I concatenate all of the values into
+ Fields!Column2.Value + "[^]" // one string with the separator [^]
+ Fields!.Column3.Value, // so I can split them later.
"MyDataSet") // The dataset to query
I can now pass this to my custom assembly:
=MyAssemblyNamespace.Class.Method(LookupSet(0,0,Fields!Column1.Value..., "MyDataSet"), other, parameters, here)
Now in my C# method I have a generic object which after some reflection is actually an array of strings.
Cast to something useful:
var stringList = ((IEnumerable)MyDataSetObject).Cast<string>().ToList();
Split it:
foreach (var item in stringList)
{
var columns = item.Split(new[] { "[^]" }, StringSplitOptions.None);
// columns is a string[] which holds each column value for the current row
// So columns[0] is the value for column 1 in this row
// In my case I pushed the values to a DataTable row each time and built a datatable
// which when finished represented my dataset in full with all rows and columns.
}
I hope this makes sense to anyone trying to achieve a similar result.
I've got a report with a table looking like this:
UserCode|RecordID|OriginatingBranch|OriginatingAccount|HomingBranch|HomingAccount|Amount|ActionDate|SeqNo|Onus|Homedback
The last two columns are booleans, they contain either Y or N. In fact, the Onus column will only contain Ys. I need to have a subtotal at the end of each page showing how many Onus transactions there are and their value, and the same for Onus transactions.
I've tried several things including everything described here but when I try that I'm left with a nondescript #Error in my report. I have no errors or logs or anything, just an #Error where I should have a number.
Now I'm trying the answer from here, which says:
Add additional column and enter this expression: =Runningvalue(Fields!YourValue.Value,Sum,"yourtable1"), and set its hidden property to true.
In the page header or footer, use the expression: =Last(ReportItems!textbox12.Value) to get the subtotal of all previous pages.( assume that the above column’s detail row is textbox12)
I've put this in my table, this is my expression:
=RunningValue(IIF(Fields!HomedBack.Value="Y", Fields!Amount2.Value, 0),Sum,"Items")
//my tablix is called "Items" and my "Amount" field is a formatted string,
//the actual value is kept in "Amount2"
And lo and behold, I am getting the famous #Error again. My first row contains 0, and every row after that contains #Error.
I should note that I'm not viewing the report in a browser or interactively or anything like that, I'm using my company's old reporting library that is terrible and needs to be rewritten (I wish), and pretty much it takes a dataset and an RDLC and spits it out into a PDF.
Is there anything glaringly obvious that is wrong with my expression? I'm pretty new to RDLC so I feel like I'm missing something silly. Also is there any way to show exactly what these #Errors actually mean or correspond to?
Another note, I designed my RDLC in VS2013 if that makes any difference.
SSRS can give #Error because of data type mismatch. It might be evaluating Amount2 as string field instead of numeric. To avoid such conditions do the explicit conversion.
Try this:
=RunningValue(IIF(Fields!HomedBack.Value="Y", Fields!Amount2.Value*1.0, 0.0),Sum,"Items")
OR
=RunningValue(IIF(Fields!HomedBack.Value="Y", CDBL(Fields!Amount2.Value), 0.0),Sum,"Items")
OR
=RunningValue(IIF(Fields!HomedBack.Value="Y", CDEC(Fields!Amount2.Value), 0),Sum,"Items")
I have a table that contain column with VARBINARY(MAX) data type. That column represents different values for different types in my c# DB layer class. It can be: int, string and datetime. Now I need to convert that one column into three by it's type. So values with int type go to new column ObjectIntValue and so on for every new column.
But I have a problems with transmitting data to datetime column, because the old column contains datetime value as a long received from C# DateTime.ToBinary method while data saving.
I should make that in TSQL and can't using .NET for convert that value in new column. Have you any ideas?
Thanks for any advice!
Using CLR in T_SQl
Basically you use Create Assembly to register the dll with your function(s) in it,
Then create a user defined function to call it, then you can use it.
There's several rules depending on what you want to do, but as basically you only want DateTime.FromBinary(), shouldn't be too hard to figure out.
Never done it myself, but these guys seem to know what they are talking about
CLR in TSQL tutorial
This is a one off convert right? Your response to #schglurps is a bit of a concern.
If I get you there would have to be break in your update script, ie the one you have woukld work up to when you implement this chnage, then you's have a one off procedure for this manouevre, then you would be updating from a new version.
If you want to validate it, just check for the existnec or non-existance of the new columns.
Other option would be to write a wee application that filled in the new columns from the old one and invoke it. Ugh...
If this isn't one off and you want to keep and maintain the old column, then you have problems.
I have an SQL Server 2005 Express Reporting Server and I'm trying update a report to show a coloured label based on a value stored in the database.
I currently store the colour as an aRGB value, but I can change this if required.
I've seen posts on how to use expression in the color property, but I can't embed c# there.
Thanks!
SSRS uses VB.NET, not C#, and most places will accept code, it is prefixed with a '=' to let the parser know that it is code. I don't know exactly where you are trying to set the label (in a table, in a floating textbox, etc), but it is very likely that it is doable.
After some digging I found out that u have to use VB code.
Here's the steps.
Add a reference to System.Drawing in the report properties -> reference tab
Add this custom code to the report properties -> code tab
Public Function GetMyColour(myColour as integer) as string
Dim colorObj As System.Drawing.Color = System.Drawing.Color.FromArgb(myColour)
return String.Format("#{0:X2}{1:X2}{2:X2}", colorObj.R, colorObj.G, colorObj.B)
End Function
Set the color property expression on the report object you want set the color of to this
=Code.GetMyColour(First(Fields!RecipeColour.Value, "StockControl"))