cancel
Showing results for 
Search instead for 
Did you mean: 

Need Assistance with Programmatically Adding Formulas to Subreports in Crystal Reports Using C#

aabbdfg852
Explorer
0 Kudos

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:

  • Programmatically add formulas to subreports within RPT files using C#.
  • Ensure compatibility with our existing .NET Framework and operating systems.

Any insights, C# code snippets, or best practices would be greatly appreciated. Thank you in advance for your help!

Accepted Solutions (1)

Accepted Solutions (1)

ido_millet
Active Contributor
0 Kudos

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.

aabbdfg852
Explorer
0 Kudos

Ido-

Thank you very much. That was the answer. In your opinion, what is some of the best sources of C# related SDK documentation for this type of question? I've obviously overlooked it because this seems like such a fundamental topic.

Thanks again,

Steve

ido_millet
Active Contributor
0 Kudos

Hi Steve,
Glad it helped.
In terms of documentation, I'm afraid I can't recommend anything. I've benefited mostly from advice on tech support forums, such as this one.

aabbdfg852
Explorer
0 Kudos

no problem..thanks again

Answers (3)

Answers (3)

DonWilliams
Active Contributor
0 Kudos

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.

ido_millet
Active Contributor
0 Kudos

Hi Steve,

try something like

SubreportClientDocument crSubreportDocument;
crSubreportDocument = rcd.SubreportController.GetSubreport(subreportname);
aabbdfg852
Explorer
0 Kudos

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

DellSC
Active Contributor
0 Kudos

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

aabbdfg852
Explorer
0 Kudos

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

DellSC
Active Contributor
0 Kudos

The logic that I posted should still work - the point is that you need to find the subreport, cast it as a ReportDocument, and then add/update formulas in that new ReportDocument object. Don't dispose of this extra ReportDocument until after you've saved the report file (main report).

-Dell

aabbdfg852
Explorer
0 Kudos

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

DellSC
Active Contributor
0 Kudos

Can you work with it as a ReportDocument? If not, I know that subreports will cast to ReportDocument, so you could do that and then try casting that result to a ReportClientDocument.

-Dell

aabbdfg852
Explorer
0 Kudos

The ReportDocument does not provide access to the Add method in order to add new formulas so I have to work with it as a ReportClientDocument. How do you cast a subreport to a ReportDocument?

Like this:

Because I get an error as shown here.

DellSC
Active Contributor
0 Kudos

From the Help file:

ReportDocument subReportDocument = subreportObject.OpenSubreport(subreportObject.SubreportName);

-Dell

aabbdfg852
Explorer
0 Kudos

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

DellSC
Active Contributor
0 Kudos

Try this:

ISCDReportClientDocument reportClientDocument = subReportDocument.ReportClientDocument

-Dell

aabbdfg852
Explorer
0 Kudos

Dell-

Now I get this error message:

- Steve