Часто, при создании отчетов, нам приходится иметь дело с базами данных, далекими от идеала. Различные «особеннсти», порой, вводят в ступор. Как, например, построить отчет на основе нескольких наборов данных, которые возникает хранимая процедура MS SQL? При создании источника данных внутри отчета, мы можем использовать хранимую процедуру в sql запросе, но только для конкретной таблицы. А это означает, что будет взят только первый набор данных, возвращаемый хранимой процедурой. Чтобы сгенерировать несколько таблиц из результатов работы хранимой процедуры, нам нужно создавать источник данных программно, в коде пользовательского приложения.
Необходимо создать подключение к базе данных, выполнить хранимую процедуру, а результаты ее работы поместить в DataSet. Затем, DataSet передаем в отчет и регистрируем в нем источник данных. Таким образом, в дизайнере, при создании отчета мы получим подготовленный источник данных. Можно пойти дальше, и программно подключить этот источник к отчету так, что он уже будет в дереве данных. Но сначала рассмотрим первый вариант с простым добавлением источника данных в отчет.
Допустим у вас есть некоторое WinForms приложение, из которого вы формируете отчеты. Добавим кнопку для вызова редактора отчетов:
1 2 3 4 5 6 7 8 |
private void button1_Click(object sender, EventArgs e) { Report FReport = new Report(); SqlConnection conn = new SqlConnection("Data Source=localhost;AttachDbFilename=;Initial Catalog=salesdb;Integrated Security=True;Persist Security Info=False;User ID=;Password="); DataSet data = GetDataSet(conn, "Test"); FReport.RegisterData(data, "NorthWind"); FReport.Design(); } |
Здесь, мы создали объект отчета, объявили строку подключения к базе данных MS SQL, создали источник данных для отчета и зарегистрировали его в отчете. Метод получения источника данных GetDataSet реализуем ниже:
1 2 3 4 5 6 7 8 9 10 11 |
public DataSet GetDataSet(SqlConnection connection, string storedProcName, params SqlParameter[] params) { var command = new SqlCommand(storedProcName, connection) { CommandType = CommandType.StoredProcedure }; command.Parameters.AddRange(params); var result = new DataSet(); var dataAdapter = new SqlDataAdapter(command); dataAdapter.Fill(result); return result; } |
Этот метод принимает на вход строку подключения, имя хранимой процедуры и возможные параметры для хранимой процедуры. В нашем случае мы не передали ничего. После создания подключения к базе данных выполняется хранимая процедура. Результаты ее работы помещаются в dataAdapter.
На этом можно было бы закончить статью. Приведенного кода достаточно, чтобы создать и зарегистрировать источник данных в отчете, который будет доступен вам в дизайнере, при редактировании созданного в начале объекта отчета.
Когда дизайнер отчетов будет открыт, вы увидите пустой шаблон отчета. Источники данных нужно будет выбрать в настройках:
Однако, мы можем усовершенствовать код и избежать дополнительных действий по выбору источников данных в дизайнере. То есть отчет будет создан с сразу добавленными данными. Для этого доработаем обработчик нажатия кнопки:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
private void button1_Click(object sender, EventArgs e) { Report FReport = new Report(); Config.DesignerSettings.DesignerLoaded += DesignerSettings_DesignerLoaded; SqlConnection conn = new SqlConnection("Data Source=localhost;AttachDbFilename=;Initial Catalog=salesdb;Integrated Security=True;Persist Security Info=False;User ID=;Password="); DataSet data = GetDataSet(conn, "Test"); FReport.RegisterData(data, "NorthWind"); // activate all data sources by default foreach (DataSourceBase source in FReport.Dictionary.DataSources) { source.Enabled = true; } FReport.Design(); } |
Как вы заметили, мы подписали обработчик на событие загрузки дизайнера. Далее, мы в цикле включаем все источники данных в отчете. Реализуем обработчик для события загрузки дизайнера:
1 2 3 4 |
private void DesignerSettings_DesignerLoaded(object sender, EventArgs e) { (sender as Designer).cmdNew.CustomAction += new EventHandler(cmdNew_CustomAction); } |
Пробрасываем событие с указателем на дизайнер отчетов. Обработчик события:
1 2 3 4 5 6 7 8 9 10 |
void cmdNew_CustomAction(object sender, EventArgs e) { Designer designer = sender as Designer; //StandardReportWizard wizard = new StandardReportWizard(); // you can use any wizard form package BlankReportWizard wizard = new BlankReportWizard(); wizard.Run(designer); designer.SetModified(this, "EditData"); } |
Создаем мастер создания пустого отчета. В итоге, при редактировании пустого отчета, мы получаем добавленные данные: