How can External Assemblies deal with SSRS variables? - reporting-services

I want to create an External Assembly and reference it inside my SSRS reports, so that I avoid repeating functions like this on every report I create:
Public Function UserName()
Try
Return Report.User!UserID
Catch
Return "System"
End Try
End Function
However, "Report.User!ID" won't be available inside my external assembly.
I'm trying to implement item 7 from: http://www.ssw.com.au/Ssw/Standards/Rules/RulesToBetterSQLReportingServices.aspx#userExperience

Related

Access Ribbon callback function cannot be inside report

Below is my ribbon code for report
<button id="EmailPDF" label = "Email Customer"
size="large"
imageMso="FileEmailAsPdfEmailAttachment"
onAction="=Rpt_Email()"
supertip= "Email to customer."/>
And this is my callback function
Public Function Rpt_Email() As Boolean
MsgBox "OK"
End Function
Call back function works, if it is in module. But, it does not work, if I move it to Report. I need it to be on the report. Because, I need to access each report information and setup email accordingly.
You can't do that. Callbacks need to be in public modules, and can't be in class modules, form modules or report modules.
Instead, use Screen.ActiveReport to determine which report is active from that global module. Or, create separate functions and ribbons per report, and show them as the report ribbon (this has the additional advantage of not showing the ribbon if none of the reports are open).

CustomReportItem Report Parameters

I am trying to design a custom report item for SSRS. Is there a way to access report parameters within the EvaluateReportItemInstance function when implementing the ICustomReportItem?
Please note that I am not trying to access custom properties for the custom report item being designed. I wish to access all of the parameters declared in a report.
My mistake.
This needs to be done when implementing the CustomReportItemDesigner, not the ICustomReportItem. For example:
public class MyCustomReportItemDesigner : Microsoft.ReportDesigner.CustomReportItemDesigner
{
public override void InitializeNewComponent()
{
//this.Report.ReportParameters;

SSIS Script Component Can't Write to ReadWriteVariable

I have a script component in SSIS on SQLServer 2008 R2, that needs to be able to write to a Read-Write variable to produce a file name for a flat file export. I created a package level variable to hold the file name, and set the flat file connection to use an expression containing the variable..
I have a script component that, among other things, builds the file name dynamically in the post execute method. I've set the variable in the ReadWriteVariables setting of the script component.
The package will immediately fail if I don't have a default value in the variable, because the flat file connection manager tries to evaluate the expression to set up the destination file. So, I just put in a placeholder file name.
The problem is that now it always uses the placeholder filename instead of the one that the script specifies. What's the best way to make sure that I can write to those variables? I tried Variables.VariableName = "value", I've also tried using VariableDispenser and this.ReadWriteVariables["VariableName"].value, and none of them are persisting the value I set in the script.
Here is one way you can assign value to a package variable from within Script Component available inside Data Flow Task.
I try to lock the variables inside the Script Task or Script Component instead of specifying them on Properties dialog. I feel this is easier to maintain.
In the following example, I have a package variable named FileName and the variable is being assigned with the value C:\Temp\PathChanged inside the Script Component.
I believe that Script Component may not be the right place to manipulate the package variable value such as file name but again that depends on what you are trying to do.
Hope that helps.
/* Microsoft SQL Server Integration Services Script Component
* Write scripts using Microsoft Visual C# 2008.
* ScriptMain is the entry point class of the script.*/
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
public override void PreExecute()
{
base.PreExecute();
}
public override void PostExecute()
{
base.PostExecute();
IDTSVariables100 varCollection = null;
this.VariableDispenser.LockForWrite("User::FileName");
this.VariableDispenser.GetVariables(out varCollection);
varCollection["User::FileName"].Value = #"C:\Temp\PathChanged";
}
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
}
}

How can I save a global variable value after dynamically loading a reference?

I have a Access 2003 database that will dynamically load MDB databases as a library reference. The reason for this is this database is a menu front-end for 60+ application databases. Rather than deal with permanently referencing all these databases, the menu front-end will dynamically reference what is needed when the user makes a selection. I was working on moving this database to Access 2010 and creating a custom ribbon. I started using the technique from here to capture the ribbon object in a global variable when the ribbon loads. I then ran into the problem where I could verify the code was running and the global variable was correctly being assigned the ribbon reference but after the database would run through it's startup routine, that global variable would get reset to Nothing.
To verify what was going on, I created a simple database for testing. In this database, I had a module with a global variable:
Public obj as Object
I then had a function like this:
Public Function SetObj()
Set obj = Application
Debug.Print "IsNothing=" & (obj Is Nothing)
References.AddFromFile "Test.mdb"
Debug.Print "IsNothing=" & (obj Is Nothing)
End Function
Obviously, in my code, "Test.mdb" refers to an actual file. If I run this code, Debug.Print gives me "IsNothing=False" for both instances, but after the function finishes and if I wait a couple seconds, Debug.Print will give me "IsNothing=True". If I comment out References.AddFromFile, Debug.Print gives me "IsNothing=False" no matter how long I wait.
It makes sense to me that since Access has to re-compile the VBA code after loading the library that all global variables are reset. I've experimented with moving the global variable into a class, but since I then need a global variable for the class, the class variable then gets reset instead. I tried using a local variable in the function to save the value of the global variable, but it looks like Access waits a couple seconds after the code is finished running to do the re-compile, so that doesn't work either. Does anyone have any other ideas to accomplish this?
I don't really know if this will solve the problem for this kind of reference, but in general, I don't use public variables for this kind of thing, but instead use a STATIC variable inside your function. It would be something like this:
Public Function SetObj() As Object
Static obj As Object
If (obj Is Nothing) Then
Set obj = Application
End If
Set SetObj = obj
End Function
Then you'd just use SetObj as an object for using your application. In a production app, you'd need tear-down code, too, but I've omitted that here.
I doubt this helps, but your code struck me as rather inefficient and incomplete.
I figured out a solution to my problem, and thanks #David-W-Fenton, as your answer gave me the idea. I use your approach in a library database for caching frequently-accessed values that are stored in a table but don't change after the initial startup. Those values aren't lost every time the references change, and that's when the light bulb lit up.
The solution is to put the global variable in a library database. Access looks to be only resetting global variables in the database that the reference is being loaded into - which makes sense after thinking about it. So since the library database isn't the one being re-compiled, it doesn't get it's global (or private or static) variables reset.
What I ended up doing was creating a new module in an existing library database. It has a private variable and two methods - one to set the variable, one to retrieve the variable value. In my menu front-end database, when the ribbon loads and calls my callback function, rather than saving the ribbon object in the front-end database, I pass it to this module for saving. I now no longer lose that ribbon reference whenever new databases are added to the library references on the fly.

Reporting Services custom assembly: accessing report parameters

I'm writting a custom assembly to be referenced in a report. I'd like to be able to access the Report object from that assembly, so that I could then access the report parameters and other stuff that I can access in custom RDL code by using Report.stuff.
I obviously need to reference some reporting services assembly to do this, yet I can't figure out which. I tried Microsoft.ReportingServices.ProcessingCore, since it has a class Report with various properties like Parameters etc., but when I tried to pass the Report object from the RDL custom code section to my class, I got this error:
Unable to cast object of type 'ReportExprHostImpl' to type 'Microsoft.ReportingServices.ReportRendering.Report'.
There's also an assembly which exposes various interfaces and an abstract class Report, but it doesn't seem to have the parameters as a property.
So the question is, how could I achieve this, what assembly do I have to reference ? And if possible, can I access the Report object without passing it from the RDL, i.e. so that I could just register an instance of my class and later write expressions like:
=Utils.DoStuffWhileReferencingReportParameters(Fields!field.Value)
Reference these two dlls in your library:
Microsoft.ReportingServices.ProcessingCore
Microsoft.ReportingServices.ProcessingObjectModel
Put the following code in your library (as an example)
using Microsoft.ReportingServices.ReportProcessing.ReportObjectModel;
public static string Test(Parameters item)
{
return item ["my_parameter_name"].Value.ToString();
}
Here’s an example expression to use in your RDL file:
=MyNameSpace.MyStaticClass.Test(Parameters)