The default is NearestNeighbor, use High and/or test to see what looks best for your images.
public frmMain()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
// added GDIPlus interpolation mode function
LstInterpolationMode.Enabled = true;
Array CRinterpolationMode = Enum.GetValues(typeof(System.Drawing.Drawing2D.InterpolationMode));
foreach (object obj in CRinterpolationMode)
{
//CRInterpolMode.GetTypeCode(CRinterpolationMode);
LstInterpolationMode.Items.Add(obj);
}
LstInterpolationMode.SelectedItem = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
if (System.Globalization.RegionInfo.CurrentRegion.IsMetric)
isMetric = 567;
else
isMetric = 1440;
foreach (Assembly MyVerison in AppDomain.CurrentDomain.GetAssemblies())
{
if (MyVerison.FullName.Substring(0, 38) == "CrystalDecisions.CrystalReports.Engine")
{
//File: C:\Windows\assembly\GAC_MSIL\CrystalDecisions.CrystalReports.Engine\13.0.2000.0__692fbea5521e1304\CrystalDecisions.CrystalReports.Engine.dll
//InternalName: Crystal Reports
//OriginalFilename:
//FileVersion: 13.0.9.1312
//FileDescription: Crystal Reports
//Product: SBOP Crystal Reports
//ProductVersion: 13.0.9.1312
//Debug: False
//Patched: False
//PreRelease: False
//PrivateBuild: False
//SpecialBuild: False
//Language: English (United States)
System.Diagnostics.FileVersionInfo fileVersionInfo = System.Diagnostics.FileVersionInfo.GetVersionInfo(MyVerison.Location);
txtRuntimeVersion.Text += fileVersionInfo.FileVersion.ToString();
CRVer = fileVersionInfo.FileVersion.Substring(0, 2);
return;
}
}
//End Class
//
// TODO: Add any constructor code after InitializeComponent call
//
}
Now onto the main routines….
The test applications main form looks like this:
Some important info below:
Above shows the Report location, report version ( 14.1 ) Revision number (1) Type of report
Runtime version and database driver used
And then the history of the report when saved ( read Only property and only updated via the Report Designer in VS or standalone CR Designer.
Lots of report object info on the right using the drop down box:
NOTE: most parts are complete but some are still incomplete, no call for info on them so I did not complete them.
The best place to start once the report is loaded is to get the list of parameters which shows their type and values if applicable also note some times you use the Engine to get the info and other times you need to use RAS to get the object info:
This is the routine that gets the values:
private void getParameterFields(CrystalDecisions.CrystalReports.Engine.ReportDocument rpt)
{
string textBox1 = "";
string textBox2 = "";
string MyObjectType = ReportObjectComboBox1.SelectedItem.ToString();
btnReportObjects.Text = "";
iCnt = -1;
// NOTE: WHEN GETTING THE PARAMETER LISTS IT DOES NOT MATTER THE TYPE OF PARAMETER. ONLY WHEN SETTING THE VALUES DOES IT MATTER.
// SEE SetParam_Click, ReportDocumentSetParameters AND SetCrystalParam FOR MORE DETAILS ON HOW TO
if (rptClientDoc.DataDefController.DataDefinition.ParameterFields.Count > 0) //there are parameters
{
btnCount.Text = rptClientDoc.DataDefController.DataDefinition.ParameterFields.Count.ToString();
foreach (CrystalDecisions.ReportAppServer.DataDefModel.ParameterField paramfield in rptClientDoc.DataDefController.DataDefinition.ParameterFields)
{
iCnt++;
// this line gets the parameter name by index
//rptClientDoc.DataDefController.DataDefinition.ParameterFields[1].LongName.ToString();
switch (paramfield.ValueRangeKind)
{
case CrParameterValueRangeKindEnum.crParameterValueRangeKindDiscrete:
{
try
{
if (paramfield.ReportName.ToString() != null)
btnReportObjects.Text += "Subreport Name: " + paramfield.ReportName.ToString() + "\n";
}
catch (Exception ex)
{
{ } // main report does not have a name so ignore the exception
}
btnReportObjects.Text += "Discrete Param Name: \"";
btnReportObjects.AppendText(paramfield.Name.ToString() + "\"");
textBox1 = "";
getDiscreteValues(paramfield);
break;
}
case CrParameterValueRangeKindEnum.crParameterValueRangeKindDiscreteAndRange:
{
try
{
if (paramfield.ReportName.ToString() != null)
btnReportObjects.Text += "Subreport Name: " + paramfield.ReportName.ToString() + "\n";
}
catch (Exception ex)
{
{ } // main report does not have a name so ignore the exception
}
//getRangeAndDiscreteValues(paramfield);
btnReportObjects.Text += "Discrete and Range Param Name: ";
btnReportObjects.AppendText(paramfield.Name.ToString() + "\"");
textBox1 = "";
getDiscreteValues(paramfield);
IsParamRange = true;
break;
}
case CrParameterValueRangeKindEnum.crParameterValueRangeKindRange:
{
try
{
if (paramfield.ReportName.ToString() != null)
btnReportObjects.Text += "Subreport Name: " + paramfield.ReportName.ToString() + "\n";
}
catch (Exception ex)
{
{ } // main report does not have a name so ignore the exception
}
btnReportObjects.Text += "Range Parameter Name: ";
btnReportObjects.AppendText(paramfield.Name.ToString() + "\"");
textBox1 = "";
//getRangeValues(paramfield);
getDiscreteValues(paramfield);
IsParamRange = true;
break;
}
}
}
}
}
At this point you can now determine what type of Parameter they are which also dictates which ENUM to use when setting/updating/adding values.
Lets try a basic report now using CR Static Parameter. (Report attached - ParameterOrderField.rpt)
Run the application and load the above report and you will see the following:
General info about the report in the top left area explained earlier.
- Record Selection Formula text box shows you the formula with comments.
- SQL Statement: text box gives you info on the connection properties
- Under the Report Objects text there is another text box for general object info and messages
Now look at the parameter using the drop down Report Objects drop down feature and select Parameters ( 3rd listed 😞
- As you can see it is a Discrete Static parameter
- It has a Current Initial value and default values.
Now to set the CR parameter you can set the logon info first or set the parameter value first. In this case it does not matter.
NOTE: When using a Stored Procedure the Parameter MUST be set first before sett the log on info because the connection requires it.
So now fill in the connection info, I imported our legacy xtreme.mdb (attached) into my SQL 2008 Server
Now that you are connected you can now see the SQL has been updated:
Click the Parameter Set button and the SQL statement area now is updated with:
Parameters Set
You can now preview the report, not the selection formula does not use the parameter value but easy to do so in CR Designer or in code but that's for a different Document...
The code to set the value to 1003 is below:
private void SetParam_Click(object sender, EventArgs e)
{
try
{
foreach (CrystalDecisions.CrystalReports.Engine.ParameterFieldDefinition pField in (ParameterFieldDefinitions)rpt.DataDefinition.ParameterFields)
{
if (pField.ParameterType == ParameterType.StoreProcedureParameter)
{
rpt.SetParameterValue("@test", "1003");
}
if (pField.ParameterType == ParameterType.ReportParameter)
{
if (pField.ParameterFieldName == "test")
SetCrystalParam(rpt, "@test", "1003");
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
btnSQLStatement.Text += "\nParameters Set";
}
And example of using a Dynamic parameter in a report and getting that info:
Update to the application to get the SQL from the subreport is below.
In the logon routine I've added some code to preset the values, If the subreport is linked to the main report in the record selection formula the value will need to be set for that parameter the same way as above.
The tricky part now is the subreport is based on a field, possibly, screen shot below shows the parameter in the subreport view:
Now what you need to do is get the Parameter Links from that collection and set the values specifically:
Search the app for"// Get subreport SQl " and you'll find the update I did below to set the value when logging on.
First add a global variable to hold the value:
int subreportLinkValue = 0;
Then search for this in the log on routine and update it:
//pass the necessary parameters to the connectionInfo object
//crConnectioninfo.ServerName = btrDataFile.Text.ToString();
crConnectioninfo.ServerName = btrDataFile.Text.ToString();
if (!mainSecureDB)
{
crConnectioninfo.ServerName = btrDataFile.Text.ToString();
crConnectioninfo.UserID = btrFileLocation.Text.ToString(); // "sa";
crConnectioninfo.Password = btrPassword.Text.ToString(); // Password
crConnectioninfo.DatabaseName = btrSearchPath.Text.ToString(); // XTREME.CUSTOMER
}
else
{
crConnectioninfo.IntegratedSecurity = true;
}
// this is where you set the main report parameter values
// if the subreport is not linked by the record selection formula it returns the first value, or last value depending on the subreport link
// so in this case where the subreport is linked via the record selection formula the value needs to be passed to the subreport Link.
subreportLinkValue = 1005;
SetCrystalParam(rpt, "@My Parameter", subreportLinkValue.ToString());
crTableLogOnInfo = crTable.LogOnInfo;
crTableLogOnInfo.ConnectionInfo = crConnectioninfo;
try
{
crTable.ApplyLogOnInfo(crTableLogOnInfo);
}
catch (Exception ex)
{
btnSQLStatement.Text += "ApplyLogOnInfo failed: " + ex.ToString();
}
// Get subreport SQl
foreach (String resultField in rptClientDoc.SubreportController.GetSubreportNames())
{
SubreportController subreportController = rptClientDoc.SubreportController;
SubreportClientDocument subreportClientDocument = subreportController.GetSubreport(resultField);
// this gets the subreport linked fields so if more than one you will need to handle the values individually
// since the main report parameter and record selection formula are only linked in the record selection formula you need to get the actual field the subreport is linked on to be able to get the SQL statement
try
{
SubreportLinks SubLinks = rptClientDoc.SubreportController.GetSubreportLinks(resultField.ToString());
for (int I = 0; I < SubLinks.Count; I++)
{
SubreportLink subLink = SubLinks[I];
string trimCurlies = subLink.LinkedParameterName.ToString();
char[] charsToTrim = { '{', '}', '?' }; // remove the {? ... } from the Parameter field name
trimCurlies = trimCurlies.Trim(charsToTrim);
subreportClientDocument.DataDefController.ParameterFieldController.SetCurrentValue(subreportClientDocument.Name.ToString(), trimCurlies.ToString(), subreportLinkValue);
}
subreportClientDocument.DatabaseController.LogonEx(crConnectioninfo.ServerName, crConnectioninfo.DatabaseName, crConnectioninfo.UserID, crConnectioninfo.Password);
GroupPath gp1 = new GroupPath();
gp1.FromString("");
string sql = String.Empty;
subreportClientDocument.RowsetController.GetSQLStatement(gp1, out sql);
btnSQLStatement.Text += "Subreport: " + resultField.ToString() + "\n:" + sql;
btnSQLStatement.AppendText("\n");
break;
}
catch (Exception ex)
{
{
if (nvp2Sub.Name.ToString() == crConnectioninfo.DatabaseName.ToString())
Now you can get the SQL from the subreprort but be aware if there are multiple links you will need to provide those values and handle them accordingly.
This is the basics and should get you going on creating your own routines to manage your parameters
More info on this product:
CR for VS no longer allows connecting to Business Objects Enterprise also known as Managed Reports. There is a separate .NET SDK for BOE 4.1 that eventually will have the above API’s but for now this is limited to CR for VS only.
Conclusion
When using various Parameters in Crystal Reports be aware of the various types used, if they are range types, static, dynamic etc. Using this application should get you going.
If you need any more details or examples please search our SCN Forums at:
If you have specific requests and didnot find an example or how to on the forum please post a new question.
Also, when Designing reports you are able to save errors, after all the Designer is a design tool and assume it will be fixed later.
The SDK loads all objects so if there are errors it can cause problems so validate all object before releasing them and using the report in your application.
A common issue is in Formulae being saved with invalid field names being used. This application will valid all formula and report any that have issues. Good this to do in your application....
Extreme example of a bad report with multiple formula errors:
The error reported is typically like this:
Error in formula :
Error in formula ~:
'DatetimeVar Field_Name;'
This field name is not known.
Details: errorKind
Update: 2016-02-09 added the default values to the get Parameter info routine
Update: 2016-02-24 fixed IsDCP objAttributes["FieldID"] try/catch
Update: 2016-06-10 added ability to get subreport SQL by setting the value in the Logon routine.
Update: 2016-12-01 updated Subreport log info again and get query
Update: 2017-04-26 Fixed some Subreport SQL issues and other parts as well as added Interpolation mode functionality - GDIPlus image handler.
Update: 2021-04-01 Added getting subreport Command SQL