Click here to Skip to main content
15,888,816 members
Please Sign up or sign in to vote.
1.00/5 (2 votes)
See more:
I have created a back - end application in C# with embedded microsft sql server. I am pretty new to crystal reports and I had created one but in a wrong way and I am trying to correct it. I almost don't remember how I created and I feel bad for that.

So, I have a form represent orders management. So when the user runs the application, he enters an OrderID in the Search Text Box and the corresponding Order appears in the form controls. More detailed, the displayed Order comes with the appropriate Invoice Record, the appropriate Customer that made this order, all these appear in RichTextBoxes, and a DataGridView that displays the products that Customer ordered. Everything runs perfectly.

I also have button for my crystal report of the searched order, the btnPrint.
I would like also to mention that report values are place to details section.

The problem comes when I try to give values to the report from the DataGridView with GiveValuesToRpt function, all the other values appears correctly. I get to the Report only the last record of product details of the DataGridView and not all the records it's need. Any suggestions, help and explanation will be much appreciated.

Thank you so much in advanced.

What I have tried:

C#
<pre> 
private void btnPrint_Click(object sender, EventArgs e)
{
   Reports.OrderRpt orderRprt = new Reports.OrderRpt(); ;
            
   OrdersPrintReport printFrm = new OrdersPrintReport(ref orderRprt);

   IEnumerable<String> paramNames = (from CrystalDecisions.Shared.ParameterField p in orderRprt.ParameterFields

                                              where string.IsNullOrEmpty(p.ReportName)

                                              select p.Name);


   foreach (Control Container in this.Controls)
     if (Container.GetType() == typeof(GroupBox) || Container.GetType() == typeof(Panel))
   {
      GiveValuesToRpt(Container, paramNames,ref orderRprt);
   }

   printFrm.Text = this.Text;
   fromForm.OpenChildForm(printFrm, this.fromForm.menuBtn);
}

private void GiveValuesToRpt(Control Container, IEnumerable<String> paramNames, ref Reports.OrderRpt OrderReport)
{
    IEnumerable<RichTextBox> RtBoxes;
    IEnumerable<CustomCombo> Cbos;
    IEnumerable<CheckBox> checkBoxes;

    IEnumerable<DateTimePicker> dtPickers;
    dtPickers  = Enumerable.Empty<DateTimePicker>();
    IEnumerable<DataGridView> dtGridViews;


    string name, ColumnName;//, strValue;
            
    RtBoxes = SaveSQLquery.GetControls<RichTextBox>(Container.Controls);
    Cbos = SaveSQLquery.GetControls<CustomCombo>(Container.Controls);
    dtPickers = SaveSQLquery.GetControls<DateTimePicker>(Container.Controls);
    checkBoxes = SaveSQLquery.GetControls<CheckBox>(Container.Controls);
    dtGridViews = SaveSQLquery.GetControls<DataGridView>(Container.Controls);

    foreach (Control cntrl in Container.Controls)
    {
        if (RtBoxes.Any())
          foreach (var RTxtbox in RtBoxes)
          {
             if (paramNames.Contains(RTxtbox.Name))
             {
                name = RTxtbox.Name.ToString();
                OrderReport.SetParameterValue(name, RTxtbox.Text);
             }
          }
          if (Cbos.Any())
             foreach (var Cbo in Cbos)
             {
                 if (paramNames.Contains(Cbo.Name))
                     OrderReport.SetParameterValue(Cbo.Name, Cbo.Text);
             }
          if (dtPickers.Any())
             foreach (var dtP in dtPickers)
             {
                if (paramNames.Contains(dtP.Name))
                {
                   OrderReport.SetParameterValue(dtP.Name, DateTime.Parse(dtP.Text.ToString()));
                }
             }
          if (checkBoxes.Any())
          {
             foreach (var checkBox in checkBoxes)
             {
                if (paramNames.Contains(checkBox.Name))
                {
                   bool value = checkBox.Checked;
                   string yes = "Ναι";

                   if (!value) yes = "Όχι";

                   OrderReport.SetParameterValue(checkBox.Name, yes);
                }
             }
          }

                
          if (dtGridViews.Any())
          {
             foreach (var dtGridV in dtGridViews)
             {
                for (int iR = 0; iR <= dtGridV.Rows.Count - 1; iR++)
                  for (int iC = 0; iC <= dtGridV.Columns.Count - 1; iC++)
                  {
                     ColumnName = dtGridV.Columns[iC].Name;
                     if (paramNames.Contains(ColumnName))
                     {
                        if (dtGridV.Rows[iR].Cells[ColumnName].Value.GetType() == typeof(string))
                                        OrderReport.SetParameterValue(ColumnName, dtGridV.Rows[iR].Cells[ColumnName].Value.ToString());

                                   
                     }
                  }
             }
          }
    }
          
}
Posted
Updated 9-Apr-24 23:13pm
v3

1 solution

Each iteration of your for (int iR = 0; iR <= dtGridV.Rows.Count - 1; iR++) loop overwrites the values from the previous row with the values from the current row. As a result, you end up only passing in the values of the last row.

If you really want to pass this data to the report in parameters, then you need to set your parameters up to accept multiple values, and build an array of values to pass to the parameter:
C#
for (int iC = 0; iC < dtGridV.Columns.Count; iC++)
{
    string columnName = dtGridV.Columns[iC].Name;
    List<string> values = new List<string>(dtGridV.Rows.Count);
    for (int iR = 0; iR < dtGridV.Rows.Count; iR++)
    {
        if (dtGridV.Rows[iR].Cells[columnName].Value is string value)
        {
            values.Add(value);
        }
    }
    
    OrderReport.SetParameterValue(columnName, values.ToArray());
}
 
Share this answer
 
Comments
Aggeliki Asimakopoulou 10-Apr-24 6:11am    
So, I tried the following:
 
private void btnPrint_Click(object sender, EventArgs e)
{
      Reports.OrderRpt orderRprt = new Reports.OrderRpt(); 

       OrdersPrintReport printFrm = new OrdersPrintReport(ref orderRprt);
            
       IEnumerable< CrystalDecisions.Shared.ParameterField> params_ =
       (from CrystalDecisions.Shared.ParameterField p in orderRprt.ParameterFields
        where string.IsNullOrEmpty(p.ReportName)
        select p);
            
        foreach (ParameterField pf in params_)
           pf.EnableAllowMultipleValue = true;

        IEnumerable<string> paramNames = 
        (from CrystalDecisions.Shared.ParameterField p in orderRprt.ParameterFields
         where string.IsNullOrEmpty(p.ReportName)
         select p.Name);
          
            
        foreach (Control Container in this.Controls)
           if (Container.GetType() == typeof(GroupBox) || Container.GetType() == typeof(Panel))
            {
                 GiveValuesToRpt(Container, paramNames,ref orderRprt);
            }

            printFrm.Text = this.Text;
            fromForm.OpenChildForm(printFrm, this.fromForm.menuBtn);
        }

In order to allow multiple value to params.
But with your code, I get only the first record of the dtGridV now. What goes wrong?
Richard Deeming 10-Apr-24 6:14am    
Did you update your report the process the multi-value parameters?
Aggeliki Asimakopoulou 10-Apr-24 6:17am    
No, how can I do that?
Aggeliki Asimakopoulou 10-Apr-24 6:30am    
No effect even I refresh the Report.
 private void btnPrint_Click(object sender, EventArgs e)
        {
            Reports.OrderRpt orderRprt = new Reports.OrderRpt(); ;

            //orderRprt.EnableDrillDown = False;

            //OrdersPrintReport printFrm=new OrdersPrintReport(fromForm,ref orderRprt);
            OrdersPrintReport printFrm = new OrdersPrintReport(ref orderRprt);
            
            IEnumerable< CrystalDecisions.Shared.ParameterField> params_ =
                (from CrystalDecisions.Shared.ParameterField p in orderRprt.ParameterFields
                 where string.IsNullOrEmpty(p.ReportName)
                 select p);
            
            foreach (ParameterField pf in params_)
                pf.EnableAllowMultipleValue = true;

            IEnumerable<String> paramNames = 
                (from CrystalDecisions.Shared.ParameterField p in orderRprt.ParameterFields
                 where string.IsNullOrEmpty(p.ReportName)
                 select p.Name);


            orderRprt.Refresh();

            foreach (Control Container in this.Controls)
                if (Container.GetType() == typeof(GroupBox) || Container.GetType() == typeof(Panel))
                {
                    GiveValuesToRpt(Container, paramNames,ref orderRprt);
                }

            printFrm.Text = this.Text;
            fromForm.OpenChildForm(printFrm, this.fromForm.menuBtn);
        }


With orderRprt.Refresh(); the prompt enter parameter values window always displays and we don't want this. So your code doesn't work... If I don't use orderRprt.Refresh(); I get only the first record of datagridview and I want them all... With my code I get only the last record? What's going on?
I don't understand at all the link you shared.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900