none
ReportViewerのデータを動的に作成して表示するにはどうしたらいいですか RRS feed

  • 質問

  • お世話になります。

    ReportViewerを使ってデータを表示支度下記のようにしました。やりたいことは、ReportViewer上のReportNyukin.rdlcにビハインドコードで作成したテーブルを表示させたいのです。

    下記のコードで作成されているtableをデバッグで見るとテーブルは作成されています。

    単にそれをReportViewerに放り込んでも表示しないのですね。

    どのようにしたらいいでしょうか?教えてください。

    ReportNyukin.rdlc には特に何もしていませんが、データセット名を入れろと言ってくるので「DataSet1」としてあります。

    テーブルも選択されているようで(強制的?)、カラムのDBアイコン左クリックでテーブルの項目が表示されます。

    今回、この項目は表示しません。ビハインドコードで作成したテーブルを表示させたいのです。

    string[] lists = { "顧  客  名", "01", "", "02", "", "03", "", ・・ "12", "" };		// 途中略1月ー12月のつもり
    string[] header = { "user", "nyukin1", "tsuki1", "nyukin2", "tsuki2", "nyukin3", "tsuki3", ・・ "nyukin12", "tsuki12" };
    
    DataTable table = new DataTable();
    for (int i = 0; i < lists.Length; i++)
    {
           DataColumn col = new DataColumn();
    
           col.ColumnName = header[i];
           col.DataType = Type.GetType("System.String");
           if (i == 0)
                col.Caption = lists[i];
           else
                if (lists[i].Length != 0)
                   col.Caption = lists[i] + " 月";
                else
                   col.Caption = "";
    
           table.Columns.Add(col);
    }
    
    for (int i = 0; i < _user.Count; ++i)
    {
          DbAccessClass sql = new DbAccessClass();
          DataTable master = sql.SelectDateGroupTable(key);
          if (master != null)
          {
              if (master.Rows.Count > 0)
              {
                    string UserID = master.Rows[0][1].ToString();
                    row[header[0]] = GetUser(UserID);
    
                    switch (k)
                    {
                     case 0: row[header[1]] = GetNumber(master.Rows[0][6].ToString());
                             row[header[2]] = GetNumber(master.Rows[0][12].ToString());
                             break;
                     case 1: row[header[3]] = GetNumber(master.Rows[0][6].ToString());
                             row[header[4]] = GetNumber(master.Rows[0][12].ToString());
                             break;
                     case 2: row[header[5]] = GetNumber(master.Rows[0][6].ToString());
                             row[header[6]] = GetNumber(master.Rows[0][12].ToString()); 
                             break;
    
                         :
    
                    }
                table.Rows.Add(row);
              }
          }
    
          Microsoft.Reporting.WebForms.ReportDataSource rs = new Microsoft.Reporting.WebForms.ReportDataSource();
          rs.Name = "DataSet1";
          rs.Value = table;
    
          ReportViewer1.LocalReport.ReportPath = Server.MapPath(@"ReportNyukin.rdlc");
          ReportViewer1.LocalReport.DataSources.Add(rs);
          ReportViewer1.LocalReport.Refresh();
    

    .aspx

    <rsweb:ReportViewer ID="ReportViewer1" runat="server" Font-Names="Verdana" Font-Size="8pt" WaitMessageFont-Names="Verdana" WaitMessageFont-Size="14pt" Width="1574px">
          <LocalReport ReportPath="ReportNyukin.rdlc">
                <DataSources>
                     <rsweb:ReportDataSource  Name="DataSet1" />
                </DataSources>
          </LocalReport>
    </rsweb:ReportViewer>
    Visual studio 2015 C# ASP.NET

    2017年3月28日 1:57

回答

  • > 設定しなおすという意味が分かりません。

    上のレスで紹介したスレッドを上から下まで読んでもらえば分かると思ったのですが・・・

    同じことの繰り返しですが、要点のみ以下に転記します。

    チュートリアル : ローカル処理モードでの ReportViewer Web サーバー コントロールとデータベースのデータ ソースの使用法
    https://msdn.microsoft.com/ja-jp/library/ms252123.aspx

    上のチュートリアル通りに作ると以下のようになるはずです。先のスレッドのレスに書いた(注1)、(注2)も読んでください。

    <%@ Page Language="C#" %>
    
    <%@ Register 
        Assembly="Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
        Namespace="Microsoft.Reporting.WebForms" TagPrefix="rsweb" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <script runat="server">
    
    </script>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <asp:ScriptManager ID="ScriptManager1" runat="server">
        </asp:ScriptManager>
    
        <rsweb:ReportViewer ID="ReportViewer1" runat="server" Font-Names="Verdana" 
            Font-Size="8pt" InteractiveDeviceInfos="(コレクション)" 
            WaitMessageFont-Names="Verdana" WaitMessageFont-Size="14pt">
            <LocalReport ReportPath="C:\WebSites\WebSiteNET4\0097-Report.rdlc">
                <DataSources>
                    <rsweb:ReportDataSource DataSourceId="ObjectDataSource1" Name="DataSet1" />
                </DataSources>
            </LocalReport>
        </rsweb:ReportViewer>
        <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" 
            OldValuesParameterFormatString="original_{0}" SelectMethod="GetData" 
            TypeName="DataSet1TableAdapters.DataTable1TableAdapter">
        </asp:ObjectDataSource>
        </form>
    </body>
    </html>

    チュートリアルのデータソース構成ウィザードで作った型付 DataSet + TableAdapter で取得できる DataTable と同等なものは、例えば、以下のようなクラスファイル/メソッドを作れば作成できます。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Data;
    using System.Data.SqlClient;
    
    /// <summary>
    /// ReportViewerDataSource の概要の説明です
    /// </summary>
    public class ReportViewerDataSet
    {
    	public ReportViewerDataSet()
    	{
    		//
    		// TODO: コンストラクター ロジックをここに追加します
    		//
    	}
    
        public DataTable CreateDataTable()
        {
            string connectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\AdventureWorks_Data.mdf;Integrated Security=True;User Instance=True";
            string query = 
                "SELECT d.Name as Dept, s.Name as Shift, e.EmployeeID " + 
                "FROM (HumanResources.Department d " + 
                "INNER JOIN HumanResources.EmployeeDepartmentHistory e " + 
                "ON d.DepartmentID = e.DepartmentID) " + "INNER JOIN HumanResources.Shift s " + 
                "ON e.ShiftID = s.ShiftID";
    
            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                SqlDataAdapter adapter = new SqlDataAdapter();
                adapter.SelectCommand = new SqlCommand(query, connection);
                DataTable table = new DataTable();
                adapter.Fill(table);
                return table;
            }
        }
    }

    上のコードの ObjectDataSource1 で、SelectMethod="CreateDataTable" TypeName="ReportViewerDataSet" に変更すると同じ内容のレポートが表示されます。


    2017年3月28日 5:18
  • > ReportViewer上のReportNyukin.rdlcにビハインドコードで作成したテーブルを表示させたいのです。

    以下のスレッドでの回答そのままですが・・・

    Microsoft ReportViewerコントロール(WEB)について
    https://social.msdn.microsoft.com/Forums/ja-JP/1dab4155-8073-46a8-a9c0-da40a8e0bf67/microsoft-reportviewerweb?forum=aspnetja


    まずは以下のチュートリアルのようにウィザードで型付 DataSet + TableAdapter を作って、それをベースに .rdlc ファイルと .aspx ファイルを作った後で、質問者さんが言われる「ビハインドコードで作成したテーブル」を渡すためのクラスファイル/メソッドのコードを書いて、それらを型付 DataSet + TableAdapter に代えて ObjectDataSource の TypeName, SelectMethod プロパティに設定しなおすという手段ではいかがでしょう?

    チュートリアル : ローカル処理モードでの ReportViewer Web サーバー コントロールとデータベースのデータ ソースの使用法
    https://msdn.microsoft.com/ja-jp/library/ms252123.aspx

    具体例については上のスレッドを見てください。

    2017年3月28日 2:53

すべての返信

  • > ReportViewer上のReportNyukin.rdlcにビハインドコードで作成したテーブルを表示させたいのです。

    以下のスレッドでの回答そのままですが・・・

    Microsoft ReportViewerコントロール(WEB)について
    https://social.msdn.microsoft.com/Forums/ja-JP/1dab4155-8073-46a8-a9c0-da40a8e0bf67/microsoft-reportviewerweb?forum=aspnetja


    まずは以下のチュートリアルのようにウィザードで型付 DataSet + TableAdapter を作って、それをベースに .rdlc ファイルと .aspx ファイルを作った後で、質問者さんが言われる「ビハインドコードで作成したテーブル」を渡すためのクラスファイル/メソッドのコードを書いて、それらを型付 DataSet + TableAdapter に代えて ObjectDataSource の TypeName, SelectMethod プロパティに設定しなおすという手段ではいかがでしょう?

    チュートリアル : ローカル処理モードでの ReportViewer Web サーバー コントロールとデータベースのデータ ソースの使用法
    https://msdn.microsoft.com/ja-jp/library/ms252123.aspx

    具体例については上のスレッドを見てください。

    2017年3月28日 2:53
  • お世話になります。

    > それらを型付 DataSet + TableAdapter に代えて ObjectDataSource の TypeName, SelectMethod プロパティに設定しなおすという手段ではいかがでしょう?

    設定しなおすという意味が分かりません。ObjectDataSource2を作成しようとするとTableAdapterやテーブルをセットするよう求められます。これをxsdにあるものに仮設定し表示のタイミングで作成したものに変更する?と言うことですか?

    どうやって?

    ビハインドコードで下記を作成するという意味ですか?データーテーブルを加工してDB上にないものを表示させたいのですが、それを存在しているかのように作成するのでしょうか?

    ObjectDataSource2.TypeName = ここに作ったもの;

    教えてください。

    2017年3月28日 3:55
  • > 設定しなおすという意味が分かりません。

    上のレスで紹介したスレッドを上から下まで読んでもらえば分かると思ったのですが・・・

    同じことの繰り返しですが、要点のみ以下に転記します。

    チュートリアル : ローカル処理モードでの ReportViewer Web サーバー コントロールとデータベースのデータ ソースの使用法
    https://msdn.microsoft.com/ja-jp/library/ms252123.aspx

    上のチュートリアル通りに作ると以下のようになるはずです。先のスレッドのレスに書いた(注1)、(注2)も読んでください。

    <%@ Page Language="C#" %>
    
    <%@ Register 
        Assembly="Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
        Namespace="Microsoft.Reporting.WebForms" TagPrefix="rsweb" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <script runat="server">
    
    </script>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <asp:ScriptManager ID="ScriptManager1" runat="server">
        </asp:ScriptManager>
    
        <rsweb:ReportViewer ID="ReportViewer1" runat="server" Font-Names="Verdana" 
            Font-Size="8pt" InteractiveDeviceInfos="(コレクション)" 
            WaitMessageFont-Names="Verdana" WaitMessageFont-Size="14pt">
            <LocalReport ReportPath="C:\WebSites\WebSiteNET4\0097-Report.rdlc">
                <DataSources>
                    <rsweb:ReportDataSource DataSourceId="ObjectDataSource1" Name="DataSet1" />
                </DataSources>
            </LocalReport>
        </rsweb:ReportViewer>
        <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" 
            OldValuesParameterFormatString="original_{0}" SelectMethod="GetData" 
            TypeName="DataSet1TableAdapters.DataTable1TableAdapter">
        </asp:ObjectDataSource>
        </form>
    </body>
    </html>

    チュートリアルのデータソース構成ウィザードで作った型付 DataSet + TableAdapter で取得できる DataTable と同等なものは、例えば、以下のようなクラスファイル/メソッドを作れば作成できます。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Data;
    using System.Data.SqlClient;
    
    /// <summary>
    /// ReportViewerDataSource の概要の説明です
    /// </summary>
    public class ReportViewerDataSet
    {
    	public ReportViewerDataSet()
    	{
    		//
    		// TODO: コンストラクター ロジックをここに追加します
    		//
    	}
    
        public DataTable CreateDataTable()
        {
            string connectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\AdventureWorks_Data.mdf;Integrated Security=True;User Instance=True";
            string query = 
                "SELECT d.Name as Dept, s.Name as Shift, e.EmployeeID " + 
                "FROM (HumanResources.Department d " + 
                "INNER JOIN HumanResources.EmployeeDepartmentHistory e " + 
                "ON d.DepartmentID = e.DepartmentID) " + "INNER JOIN HumanResources.Shift s " + 
                "ON e.ShiftID = s.ShiftID";
    
            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                SqlDataAdapter adapter = new SqlDataAdapter();
                adapter.SelectCommand = new SqlCommand(query, connection);
                DataTable table = new DataTable();
                adapter.Fill(table);
                return table;
            }
        }
    }

    上のコードの ObjectDataSource1 で、SelectMethod="CreateDataTable" TypeName="ReportViewerDataSet" に変更すると同じ内容のレポートが表示されます。


    2017年3月28日 5:18
  • お世話になります。

    Report.rdlcを作成するタイミングに気づかず(前のままだったのでDBの項目が当初のまま)

    > ObjectDataSource の TypeName, SelectMethod プロパティに設定しなおすという手段ではいかがでしょう?

    を更新した後でReport.rdlcにテーブルを追加することに気が付くのに時間がかかってしまいました。

    遅くなりましたが、表示できるようになりました。

    本来なら終了ですが、もう一つ教えてください。このアプリ、コンボボックスで年(2017, 2016, 2015・・)を切り替えて表示するのですが、SelectMethod="CreateDataTable"で返すテーブルは更新されているのですが、表示に反映されません。

    ReportViewer1.LocalReport.Refresh();や

    ReportViewer1.LocalReport.DataSources.Clear();では、うまくいかないようです。

    ポストバックしているので更新して表示してもよさそうでが、表の中身が変わりません。

    お願いします。

    2017年3月29日 3:17
  • 表題や最初の質問内容と異なることは新たに別のスレッドを立てて質問していただくようお願いします。(このスレッドの次のステップとしての質問と理解しています)

    その際、新しいスレッドには、このスレッドの URL を書いて、このスレッドの次のステップとしての質問であることを明記してください。

    さらに、新しいスレッドに、

    > コンボボックスで年(2017, 2016, 2015・・)を切り替えて表示するのですが、SelectMethod="CreateDataTable"
    > で返すテーブルは更新されているのですが、表示に反映されません。

    のあたりの情報をもっと詳しく書いてください。上記では何をしたのかが分かりませんので答えようがないです。

    たとえば、

    コンボボックスとは何ですか? DropDownList のこと? AutoPostBack を true にしている?

    初期画面はどうなっていて、それの選択を変えると具体的に何がどうなるようにプログラムを組んだんですか?

    ・・・などです。

    2017年3月29日 4:26
  • お世話になります。

    分かりにくくてすみません。

    > コンボボックスとは何ですか? DropDownList

    その通りです。WebよりWinFormが圧倒的に多いのでつい使ってしまいます。

    テストしてみると

    <asp:ObjectDataSource ID="ObjectDataSource2" runat="server" SelectMethod="GetData"・・・

    は、初回表示時に呼び出されてSelectMethod="GetData"がデータを返すタイミングでポストバックしているようです。

    これで表示するなら問題ないのですが、条件を変えてデータを読み出(表示)したいため(ここで、DropDownListが登場します。)

    DropDownListで選択した年のデータを読み出し表示させようとしました。

    が、このタイミングでSelectMethod="GetDataを実行しテーブルを返しても今度はポストバックしていません。

    こういう仕様でしょうか?初回以降の呼び出しがまずいでしょうか?

    呼び出し方は、

    protected void button1_Click(object sender, EventArgs e)
    {
          var user = (DataTable)((DataView)this.ObjectDataSource2.Select()).Table;

    }

    としているだけです。

    別スレがふさわしいとご指摘を頂ければそうします。

    2017年3月29日 5:58
  • 別スレッドでお願いします。

    2017年3月29日 6:11