My answer does not pretend to solve your question, but I will show how the output of the reports is implemented in me. It may be useful or suggest an idea.
Suppose we have a form (Form1) on which the DataGridView is located to display data from the database, two datetimepickers for filtering by time and the Report button. When the button is pressed, the second form (Form2) opens, on which the reportviewer component rests.
In Form1, we create the following method and throw the Report button into the handler:
void Nakladnaya() { if (dataGridView1.SelectedCells.Count > 0) { var aktIds = new List<int>(); // получаем список id записей в таблице foreach (DataGridViewRow row in dataGridView1.Rows) { aktIds.Add((int)row.Cells["pit_id"].Value); } //открываем форму с отчетом var reportForm = new PriemIzTZAReport("Прием из ТЗА", aktIds); reportForm.Show(); } else { MessageBox.Show("Нет данных для экспорта"); }
Method to filter data in DataGridView using two datetimepicker:
if (dateTimePicker1.Checked) { filterStr += " and pit_date_ins >= '" + dateTimePicker1.Value.ToString() + "'"; } if (dateTimePicker2.Checked) { string dt_do = dateTimePicker2.Value.ToString(); filterStr += " and pit_date_ins <= '" + dt_do + "'"; } if (dataGridView1.DataSource != null) { (dataGridView1.DataSource as DataTable).DefaultView.RowFilter = filterStr; }
In the second form, the code looks like this:
private readonly string headerText; private List<int> aktIds; public PriemIzTZAReport() { InitializeComponent(); } public PriemIzTZAReport(string headerText, List<int> aktIds) { InitializeComponent(); this.headerText = headerText; this.aktIds = aktIds; } private void PriemIzTZAReport_Load(object sender, EventArgs e) { try { Text = headerText; var dt = BaseWorker.GetPriemIzTZAReport(aktIds); if (dt == null) { throw new Exception("Не удалось получить данные из БД"); } var rds = new ReportDataSource("DataSet1", dt); reportViewer1.LocalReport.DataSources.Add(rds); reportViewer1.RefreshReport(); } catch (Exception exc) { MessageBox.Show(exc.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); } this.reportViewer1.RefreshReport(); }
In my case, the BaseWorker class contains queries and procedures for accessing the database.
var dt = BaseWorker.GetPriemIzTZAReport(aktIds);
Code in class Baseworker:
//формирование отчета прием из тза internal static DataTable GetPriemIzTZAReport(List<int> aktIds) { SqlConnection conn = BaseWorker.GetConnection(); try { var stringIds = new StringBuilder(); aktIds.ForEach(id => stringIds.Append($"{id},")); var sqlQueryString = $"SELECT * FROM dbo.Table WHERE pit_id IN({stringIds.ToString().TrimEnd(',')})"; SqlCommand cmd = new SqlCommand(sqlQueryString, conn); DataTable data = null; SqlDataAdapter dataAdapter = null; //формируем и устанавливаем источник данных для таблицы data = new DataTable(); dataAdapter = new SqlDataAdapter(cmd); dataAdapter.Fill(data); if (data.Rows.Count == 0) { return null; } return data; } catch (Exception exc) { conn.Close(); MessageBox.Show(exc.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); return null; } }
Next, add the reportviewer component to the second form, create a new report, specify the DataSet1, select or create a data source, select the desired table, draw a template, and specify which columns we want to display.