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. Ошибка 1 В качестве оператора могут использоваться только выражения присваивания, вызова, приращения, уменьшения, ожидания и новых объектов.
  2. 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;
}

Опять же, я мог бы предложить больше, но этого было бы слишком много для одного вопроса, так как у вас, вероятно, будут / вы захотите задать больше вопросов.

Другие вопросы по тегам