on 12-04-2023 7:10 PM - last edited on 02-01-2024 12:52 PM by DonWilliams
I am working on a routine in C# for programmatically adding new formulas to existing Crystal Reports (RPT files). While I've successfully added formulas to the main report, I'm encountering challenges with integrating them into subreports.
Our company develops a commercial C# .NET Framework 4.7 desktop application, and these reports are integral to it, running locally on Windows 10/11 PCs. The reports utilize the CR redistributable and reports are always run locally on the user's desktop. No reporting server is used. The purpose of this C# routine is to streamline the update process of RPT files for our internal staff before distribution.
I'm reaching out for guidance or examples on how to:
Any insights, C# code snippets, or best practices would be greatly appreciated. Thank you in advance for your help!
Steve,
rcd is the main report's client document.
Use my code to instantiate the subreport's client document. Don't try to cast it.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Steve,
I wrote a few samples on a lot of these questions:
how-to-parameters-in-crystal-reports-for-visual-studio-net
Printing Crystal Reports in .NET
The Parameter test app has log on routines for subreports. single step through the app and you'll see how I do it.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Steve,
try something like
SubreportClientDocument crSubreportDocument;
crSubreportDocument = rcd.SubreportController.GetSubreport(subreportname);
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Ido-
Thank you for taking time to post. I've been carrying on a conversation with Dell Stinnett-Christy who responded first. I'm not sure if you have seen those comments I'll paste the following routine that I am currently working with that I have shown Dell. Would you mind taking a look at it if you have a minute and tell me where I should use the code you suggested I try? For example would this go after the line in my code - ReportDocument subReportDocument = subreportObject.OpenSubreport(subreportObject.SubreportName);? Also what type is rcd in the piece "rcd.SubreportController.GetSubreport..."? Does this code replace my OpenSubreport line? Here is my code:
- Steve
No code snippet, but the logic you use would be similar to the logic you need for setting the database logons for subreports. Basically, you'll do this:
For each section in the report
For each object in the section
If the object is a subreport then
Cast the subreport as a ReportDocument or ReportClientDocument (whichever you're using for the main report)
Update the formulas in the same way as in the main report
Go to the next object or section
else
Go to the next object or section
end if
-Dell
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Dell-
Thank you for taking the time to post, but I am needing this routine to add a
completely new formula to a subreport, not update existing formulas.
Here is the routine that I've used to handle adding a new formula to the
Main report, that works well. I just have not been able to adapt it to
subreports. If you have any other thoughts, I would appreciate it.
// This creates / adds a new formula to the main report within an RPT file. It does not handle subreports.
public void AddNewFormulaToReport(string reportPath, string formulaName, string formulaText)
{
// based on: https://userapps.support.sap.com/sap/support/knowledge/en/1284635
using (ReportDocument reportDocument = new ReportDocument())
{
reportDocument.Load(reportPath);
// Access the underlying ReportClientDocument object
ISCDReportClientDocument reportClientDocument = reportDocument.ReportClientDocument;
// Create dummy values for any parameter fields that might have been set up
foreach (ParameterFieldDefinition parameterField in reportDocument.DataDefinition.ParameterFields)
{
ParameterDiscreteValue discreteVal = new ParameterDiscreteValue();
discreteVal.Value = "DummyValue"; // Replace with an appropriate value for the parameter
parameterField.CurrentValues.Add(discreteVal);
parameterField.ApplyCurrentValues(parameterField.CurrentValues);
}
// Create a FormulaFieldDefinition through the ClientDoc API
FormulaField formulaField = new FormulaField();
// Assign the name and formula text
formulaField.Name = formulaName;
formulaField.Text = formulaText;
// Add the formula field to the report's DataDefinition
reportClientDocument.DataDefController.FormulaFieldController.Add(formulaField);
// Save the changes back to the disk
reportDocument.ExportToDisk(CrystalDecisions.Shared.ExportFormatType.CrystalReport, reportPath);
}
}
-Steve
Thank you again Dell for responding. Taking your logic, this is the routine that I currently have created.
I'm passing the following items:
pathFileName: 1) path and rpt name, 2) subReportName - the name of the subreport I want to add the new formula to, 3) formulaName - the name of the formula I want to add, and 4) formulaText - the formula itself
Here is the code:
public void UpdateSubreportFormulasWednesday(string pathFileName, string subReportName, string formulaName, string formulaText)
{
ReportDocument mainReport = new ReportDocument();
mainReport.Load(pathFileName);
bool shouldBreak = false;
// Iterate through each section in the report
foreach (Section section in mainReport.ReportDefinition.Sections)
{
// Iterate through each report object in the section
foreach (ReportObject reportObject in section.ReportObjects)
{
// Check if the object is a subreport
if (reportObject.Kind == ReportObjectKind.SubreportObject)
{
SubreportObject subreportObject = (SubreportObject)reportObject; // create SubreportObject so I can see its Name
if (subreportObject.SubreportName == subReportName) // verify that the Subreport is the one we want
{
// Access the underlying ReportClientDocument object
ISCDReportClientDocument reportClientDocument = (ReportClientDocument)subreportObject; //<<<< here I get the following error:
Unable to cast object of type 'CrystalDecisions.CrystalReports.Engine.SubreportObject' to type 'CrystalDecisions.ReportAppServer.ClientDoc.ReportClientDocument'
// Create a FormulaField
FormulaField formulaField = new FormulaField();
// Assign the name and formula text
formulaField.Name = formulaName;
formulaField.Text = formulaText;
// Add the formula field to the report's DataDefinition
reportClientDocument.DataDefController.FormulaFieldController.Add(formulaField);
// Save the changes back to the disk
mainReport.ExportToDisk(CrystalDecisions.Shared.ExportFormatType.CrystalReport, pathFileName);
shouldBreak = true;
break;
}
}
}
if (shouldBreak)
break;
}
}
I've tried to note it above but on this line:
ISCDReportClientDocument reportClientDocument = (ReportClientDocument)subreportObject;
I get the following error:
Unable to cast object of type 'CrystalDecisions.CrystalReports.Engine.SubreportObject' to type 'CrystalDecisions.ReportAppServer.ClientDoc.ReportClientDocument'I've also tried casting on this line instead but get the same error:
//ISCDReportClientDocument reportClientDocument = (ReportClientDocument)reportObject;
Am I missing something in your instructions?
Also I am casting to ReportClientDocument per your initial comment because that is what I am doing in the Main report,
Cast the subreport as a ReportDocument or ReportClientDocument (whichever you're using for the main report)
Update the formulas in the same way as in the main report
Thank you again for your help.
-Steve
Dell-
Thank you for your continued patience. I think I was actually down this path last week but I've made the change per your comment and this is what I get now:
When I try and cast the subReportDocument ReportDocument, I get the above error. Note:I have to cast the ReportDocument to the ISCDReportClientDocument type in order to have access to the Add method of its DataDefController.FormulaFieldController. The ReportDocument doesn't appear to allow adding of new formulas but the ISCDReportClientDocument type does. I've tried this with just the main report which works. But trying to do this with SubReports is where I get stuck. Thank you for your continued help.
-Steve
User | Count |
---|---|
83 | |
10 | |
10 | |
9 | |
7 | |
6 | |
6 | |
6 | |
5 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.