C# ReportViewer Локальный отчет с параметром
Всем доброго дня,
Большую часть последних двух недель я потратил на поиск помощи по проблеме, которая возникла в моем приложении C# WinForm.
У меня есть форма, в которой есть DataGridView, отображающий детали, извлеченные из базы данных. Когда пользователь дважды щелкает строку в этой сетке, код извлекает значение из столбца CustomerID, помещает его в статическую открытую строку, а затем открывает другую форму, в которой есть средство просмотра отчетов.
Затем я пытаюсь заставить программу просмотра отчетов запустить отчет, используя CustomerID в качестве параметра.
Пока все, что мне удалось сделать, это заставить его заявить, что определение отчета не было указано.
Мой SQL-сервер - это старый сервер, на котором нет SSRS, и я не могу установить его из-за проблем с запросами на изменение, поэтому мне приходится использовать локальный отчет, а не отчет сервера.
Я создал отчет таким образом, чтобы перейти к своему обозревателю решений в Visual Studio и перейти к пункту "Добавить - новый элемент - отчет", в котором я затем дал набор данных и параметр. Я помещаю отчет в подпапку "Отчеты", которая находится внутри решения рядом со всеми моими формами.
Код для моей формы просмотра отчетов приведен ниже. Не смейся слишком много, я на все 100% самоучка.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Reporting.WinForms;
using System.Data.SqlClient;
namespace FormsApp
{
public partial class ReportGenerator : Form
{
public ReportGenerator()
{
InitializeComponent();
this.reportViewer1.RefreshReport();
}
private void ReportGenerator_Load(object sender, EventArgs e)
{
if (CustomerList.CustomerID!= "")
{
this.reportViewer1.ProcessingMode = ProcessingMode.Local;
this.reportViewer1.LocalReport.ReportPath = "\\Reports\\CustomerDetails.rdlc";
this.reportViewer1.ShowParameterPrompts = true;
ReportParameter CustID = new ReportParameter("CustomerID",CustomerList.CustomerID);
this.reportViewer1.LocalReport.SetParameters(CustID);
}
else
{}
}
}
}
Я неправильно использую Local Report? Я действительно в замешательстве, и это последнее, что мне нужно, чтобы начать работать, тогда мое заявление будет завершено.
Любая помощь будет принята с благодарностью.
Большое спасибо
ОБНОВИТЬ
Мой код теперь показывает следующие предложения из разных источников.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Reporting.WinForms;
using System.Data.SqlClient;
namespace FormsApp
{
public partial class ReportGenerator : Form
{
public ReportGenerator()
{
InitializeComponent();
this.reportViewer1.RefreshReport();
}
private DataTable getCustomerData()
{
SqlConnection con = new SqlConnection(Home.ConString);
DataSet ds = new DataSet();
ds.DataSetName = "CustomerListRetrieve";
string sql = "SELECT * FROM Customers";
SqlDataAdapter da = new SqlDataAdapter(sql, con);
da.Fill(ds);
DataTable dt = ds.Tables[0];
return dt;
}
private void ReportGenerator_Load(object sender, EventArgs e)
{
if (CustomerList.CustomerID != "")
{
this.reportViewer1.Reset();
this.reportViewer1.LocalReport.ReportEmbeddedResource = "FormsApp.Reports.CustomerDetails.rdlc";
ReportDataSource rds = new ReportDataSource("CustomerListRetrieve", getCustomerData());
this.reportViewer1.LocalReport.DataSources.Clear();
this.reportViewer1.LocalReport.DataSources.Add(rds);
ReportParameter CustID= new ReportParameter("CustomerID", CustomerList.CustomerID);
this.reportViewer1.LocalReport.SetParameters(CustID);
this.reportViewer1.LocalReport.Refresh();
ViewButtonClicked();
}
else
{
}
}
private void ViewButtonClicked(object sender, ReportParametersEventArgs e)
{
var SubmittedParameters = e.Parameters.Clone();
e.Parameters.Clear();
SubmittedParameters.Where(x => x.Name == "Parametername").FirstOrDefault().Values[0] = "YourValue";
SubmittedParameters.ToList().ForEach(x => e.Parameters.Add(x));
}
private void OnReportChosenFromList()
{
reportViewer1.SubmittingParameterValues -= ViewButtonClicked;
reportViewer1.SubmittingParameterValues += ViewButtonClicked;
}
}
}
Код источника данных, который я добавил после ответа от codingbiz. После добавления этого я больше не получил ошибку определения отчета, просто пустое окно, когда загрузчик отчетов загрузился.
Два нижних метода - ViewButtonClicked и OnReportChosenFromList были добавлены по предложению Бернарда Уолтерса. После добавления этого я получаю 2 ошибки, утверждающие:
- Ошибка 1 В качестве оператора могут использоваться только выражения присваивания, вызова, приращения, уменьшения, ожидания и новых объектов.
- Microsoft.Reporting.WinForms.ReportParameterCollection не содержит определения "Клон" и метода расширения "Клон"...
Действительно в тупик сейчас. Вероятно, неправильно реализованные предложения.
2 ответа
ReportViewer не будет действовать, пока у вас не будет reportViewer1.RefreshReport(); это команда для запуска отчета локально или удаленно. Каждый раз, когда вы хотите обновить или загрузить отчет, вам нужна эта команда.
У меня была такая же проблема, вот исправление:
private void ViewButtonClicked(object sender, ReportParametersEventArgs e)
{
var SubmittedParameters = e.Parameters.Clone();
e.Parameters.Clear();
SubmittedParameters.Where(x => x.Name == "Parametername").FirstOrDefault().Values[0] = "YourValue";
SubmittedParameters.ToList().ForEach(x => e.Parameters.Add(x));
}
private void OnReportChosenFromList()
{
reportViewer.SubmittingParameterValues -= ViewButtonClicked;
reportViewer.SubmittingParameterValues += ViewButtonClicked;
}
Эта строка:
reportViewer.SubmittingParameterValues += ViewButtonClicked;
устанавливает прослушиватель на средство просмотра отчетов, которое выполняет ViewButtonClicked
когда событие срабатывает.
ViewButtonClicked
затем перехватывает сообщение, содержащее все данные параметров, которые отправляются в SSRS, что позволяет копировать их данные, редактировать их, а затем снова добавлять данные непосредственно перед отправкой сообщения в SSRS.
ПРИМЕЧАНИЕ: это немного отредактировано, но большая часть его скопирована прямо из моего кода
Я написал целый класс-оболочку для отчетов и могу помочь / предложить его части, но могу сделать это позже / в чате / по электронной почте.
Что касается проблемы, у вас нет источника данных отчета, предоставленного нигде, с которым отчет фактически работает. У вас есть запрос к вашей базе данных, который возвращает хороший набор данных, но он явно не привязан к отчету. Итак, позвольте мне начать с этого.
При выполнении запроса и вызове FILL() вы можете заполнить один DataTable вместо DataSet. Преимущество DataSet заключается в том, что вы можете передать несколько таблиц в отчет и получить больше отчетов о родительских / дочерних... или даже иметь дополнительную таблицу только для одной записи, чтобы иметь такие вещи, как подписи, заголовки, сообщения, хотите, чтобы в другом месте вашего отчета всегда было одно и то же по сравнению с копированием в каждой строке каждой таблицы. А пока давайте остановимся только на одном DataTable
private void generateReport()
{
var rptDT = getCustomerData();
// dont know how you are preparing the load of your report...
var yourRpt = YourReportViewer.LocalReport.LoadReportDefinition( whateverYourReport );
// Now, add the data source to it. THIS is what populates the report with the data
// as a result of your query, pull down, assign table name for context in the report.
// You are telling the local report, here is the datasource, and by the way, the named
// reference of the table is whatever you set for the table name... and finally, this
// datatable object IS the content for the report.
YourReportViewer.LocalReport.DataSources.Add(
new ReportDataSource( rptDT.TableName, rptDT ) );
}
private DataTable getCustomerData()
{
SqlConnection con = new SqlConnection(Home.ConString);
// slightly altered using just a datatable
DataTable dt = new DataTable();
string sql = "SELECT * FROM Customers";
SqlDataAdapter da = new SqlDataAdapter(sql, con);
da.Fill(dt);
dt.TableName = "CustomerList";
return dt;
}
Опять же, я мог бы предложить больше, но этого было бы слишком много для одного вопроса, так как у вас, вероятно, будут / вы захотите задать больше вопросов.