We have been using Crystal Reports for our Travel CRM with good results for a few years now. We use a completely custom ExtJs based experience for Report viewing which includes a custom user interface for entering report parameters (see screenshot below for an example) and a custom toolbar for managing report navigation and exporting etc (I had blogged about the toolbar earlier here).

A custom User Interface for entering report parameters for Crystal Reports

 

Everything worked good. However the client recently came back to us mentioning that our interface does not populate the default value for a report parameter automatically. Well we never supported it earlier, so we began looking for a way to extract the default value for a parameter using the Crystal Reports developer version for Visual Studio SDK to be able to populate the same in our interface. It took us sometime to figure out the way to accomplish this using the SDK, so I thought I would share it for everyone’s benefit.

To start with, let’s clear out some Crystal Report SDK’s nomenclature which is a bit misleading in my opinion. Crystal Report parameters have something known as default values in the SDK. This is not exactly the default value for a parameter, rather a list of options from which you can choose a value (i.e. pre-defined values for a parameter available for selection). For example, in the screenshot below, you are defining available values for the “Detail or Summary” parameter. When executing the report, these values be available in the drop-down as you can see in the screenshot.

Parameter Default values in Crystal Reports are actually pre-defined values available for selection

 

Not exactly intuitive you would agree.

Next we come to another option on the parameter which is labeled as “Default value” for the parameter in the Report Designer’s user interface (again reference the screenshot below).

Default value for a Crystal Report Parameter

 

This is what most people would take as the default value for a parameter in my understanding. The Crystal Reports SDK calls this as “Initial Value” of the parameter; pretty interesting, ain’t it…

With the background out of our way, let’s now come to the code to extract these values from a CR report template using the SDK. I will demonstrate extracting both default as well as initial values of a parameter.

Both these types of values can be extracted from a CrystalDecisions.CrystalReports.Engine.ReportDocument object. Given a path to CR report’s template (.rpt) file, here’s how you load it into a ReportDocument object:

 

ReportDocument doc = new ReportDocument();
doc.Load(reportFilePath);

 

Next we use the ReportDocument object to extract the default values for each parameter (remember default values are the list of pre-defined values as discussed above).

 

{syntaxhighlighter brush: csharp;fontsize: 100; first-line: 1; }foreach (ParameterFieldDefinition p in doc.DataDefinition.ParameterFields)
{
if (p.ParameterFieldUsage != ParameterFieldUsage.NotInUse)
{
reportParams.Add(p.Name, new
{
type = p.ParameterValueKind,
label = p.PromptText,
required = (!p.EnableNullValue) || (!p.IsOptionalPrompt),
allowCustom = p.EnableAllowEditingDefaultValue,
allowMultiple = p.EnableAllowMultipleValue,
rangeType = p.DiscreteOrRangeKind,
defaultValues = p.DefaultValues,
initialValues = new
{
discreetValues = new List<object>()
}
});
}
}{/syntaxhighlighter}

 

We iterate over ReportDocument.DataDefinition.ParameterFields collection. For each parameter, we check if its in use on the report and if yes, extract various configuration options for the parameter including its default values (p.DefaultValues). The above code extract is from our Travel CRM, you can off-course adapt it anyway you need to.

Finally, we extract the InitialValues for each parameter (which you would recall is labeled as default value of the parameter in the Report Designer UI). Again, for some reason, the SDK developers chose to expose the InitialValues using a completely different set of objects (rather than the ParameterFieldDefinition).

 

{syntaxhighlighter brush: csharp;fontsize: 100; first-line: 1; }foreach (CrystalDecisions.ReportAppServer.DataDefModel.ISCRParameterField clientParameterFieldDefinition in doc.ReportClientDocument.DataDefController.DataDefinition.ParameterFields)
{
foreach (var initialValue in clientParameterFieldDefinition.InitialValues)
{
var discreetInitialValue = initialValue as CrystalDecisions.ReportAppServer.DataDefModel.ParameterFieldDiscreteValue;
if (discreetInitialValue != null)
{
var initialValue = discreetInitialValue.Value;
//Use initial value anyway you would like to. In our case, we stored it and passed to our ExtJs UI to populate in the interface.
}
}
}{/syntaxhighlighter}

 

You need to goto ReportDocument.ReportClientDocument.DataDefController.DataDefinition.ParameterFields and check the InitialValues collection for each field. Then you ensure each item of the InitialValues collection is of type ParameterFieldDiscreteValue, and if it is, that’s your default value for that parameter. It appears the SDK developers chose to keep InitialValues multi-valued so report designers can input multiple default values (aka initial values) for mulit-valued report parameters.

Please note the last part (extracting InitialValues for a parameter) is written using 13.0.10.1385 version of the SDK. I believe there’s a minor variation to it if you use an earlier version (I don’t have the earlier version, so can’t tell the difference exactly but you can use intelli-sense or Reflector to find the exact property hierarchy).

If its different for your SDK version and you aren’t able to figure it out, feel free to use the comment form below for seeking help (clearly mention your full SDK version in this case) and I would try to solve the puzzle for you.