【VB.NET】フリーの帳票出力(Microsoft レポート)

# 前提条件
Visual Studio 2017

# はじめに
.NETで帳票出力といえば昔はCrystalReportsだったが、いつからか無くなった。
それ以降、帳票出力したいなら商用ツールを購入するのが定石かと思っていたが、Microsoft公式の帳票出力ツールがあったらしい。それがMicrosoftレポート。

# インストール
公式とはいえ、最初からVisual Studioに含まれてはいないので、インストールが必要。

インストール手順の動画(英語)
https://youtu.be/70uUsC5GFgk

1. Visual Studioのメニュー → ツール → 拡張機能と更新プログラム を選ぶ。<br>
![01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/ec8da1c5-3335-0607-b480-349c94cd5a50.png)
2. 左側で「オンライン」を選び、検索エリアに「rdlc」と入力する。すると「Microsoft RDLC Report Designer」が出てくるので、ダウンロードボタンを押す。<br>
![02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/99d994e9-5790-3de3-b75f-b6cd24433471.png)
3. 下部にVisual Studioを終了させるように促すメッセージが出るので、ウィンドウを閉じてVisual Studioを終了させる。<br>
![03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/75f9f550-3630-b217-03d6-a7cdfc7b16f1.png)
4. 終了させた後しばらく待っていると(待ち時間はPCスペックによるかも)、インストーラの画面が起動するので、「変更」を押す。<br>
![04.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/f63791de-e8ba-9a4b-db41-ec7a33a7e820.png)
5. しばらく待っているとインストールが完了するので、インストーラを閉じて、Visual Studioを起動する。<br>
![05.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/03c0848b-96d6-8c82-fb66-8009c6331485.png)

# ReportViewerコントロールの追加
拡張機能をインストールしただけでは、WindowsフォームコントロールにReportViewerが追加されない。

1. プロジェクトで右クリック→「NuGetパッケージの管理」を選ぶ。
2. `Microsoft.ReportingServices.ReportViewerControl.WebForms`または`Microsoft.ReportingServices.ReportViewerControl.WinForms`を探してインストール。  
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/f6a2da38-fa05-05e3-5b41-6a42a101ccc4.png)
3. インストールが完了すると、ツールボックスにReportViewerが追加されている。  
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/b5b3c591-b9e1-a66c-6b11-22ee6cd62ad1.png)

ちなみに、ReportViewerコントロールは、SQLServer上に作ったレポートファイルも表示できる。

※ ツールボックスにReportViewerが無い場合

1. ツールボックスで右クリック→「アイテムの選択」を選ぶ。(もしくは、メニュー→「ツール」→「ツールボックスアイテムの選択」)
2. 「参照」を押す。  
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/398bcb54-7473-e4ca-e613-b3ba4577472e.png)
3. `ソリューションフォルダ\packages\Microsoft.ReportingServices.ReportViewerControl.Winforms.150.900.148\lib\net40`にある`Microsoft.ReportViewer.WebForms.dll`または`Microsoft.ReportViewer.WinForms.dll`を選択して開く。

# レポート作成方法

新しいレポートを作成するときは、「共通項目」のカテゴリを探す。よそのサンプルでは「Reporting」のカテゴリにレポートがあるが、VS2017では違うらしい。
![06.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/f1405f71-8272-ce5b-ec1d-2383326f637c.png)

また、レポート作成時に警告が表示されるので、「信頼する」を押す。
![07.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/4c9219ff-a698-aad9-5697-404f2f1ac6b3.png)

↓デザイナの画面
![01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/14835589-0439-6349-8a94-03606af3a342.png)

↓ツールボックスからアイテムを選択して追加する。
![02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/de253040-9d06-eafd-b44a-00c1ed1fbcc8.png)

## 日本語表示時の注意
フォントが英字用フォントだと、日本語が表示されない。既定値は「Arial」になっているので、日本語を表示できるフォントへ変更する。

## 一覧形式のレポートを作成する
ツールボックスで「一覧」を選び、レポートの本文へドラッグ＆ドロップする。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/7269918e-fccc-b6d5-d066-d0d714620780.png)

初めて一覧を追加する場合、データセットの作成ウィザードが始まるので、適宜データソースを作成する。

一覧の列を追加するには、一覧上で右クリック→「列を挿入」→「左揃え」または「右揃え」を選ぶ。「左揃え」を選ぶと、クリックした列の左側に列が挿入される。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/5f1363a3-fd62-15fb-3750-30bc45142f05.png)

列に表示するデータを指定するには、列の右上に表示するアイコンをクリックして、列の一覧から表示したい列を選ぶ。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/a98bcf93-ca69-5083-cbc4-cf0c1418e8e7.png)

一覧に表示するデータを指定した様子。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/25eb73ea-d73f-7e77-72d9-2777310228ad.png)

デフォルトのままでは、一覧が複数ページに渡ったときに2ページ目以降でヘッダーが表示されない。
[表示する方法](https://qiita.com/mima_ita/items/dd95ba1f25ba176fccb3#%E5%90%84%E3%83%9A%E3%83%BC%E3%82%B8%E3%81%AB%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%81%AE%E3%83%98%E3%83%83%E3%83%80%E3%83%BC%E3%82%92%E8%A1%A8%E7%A4%BA%E3%81%99%E3%82%8B)

## 独自クラスで一覧を作成する

一覧の行データになるクラスを作っておく。

```vb
Public Class DataRow1

    Private _column1 As String
    Public Property Column1() As String
        Get
            Return _column1
        End Get
        Set(ByVal value As String)
            _column1 = value
        End Set
    End Property

    Private _column2 As String
    Public Property Column2() As String
        Get
            Return _column2
        End Get
        Set(ByVal value As String)
            _column2 = value
        End Set
    End Property

    Private _column3 As String
    Public Property Column3() As String
        Get
            Return _column3
        End Get
        Set(ByVal value As String)
            _column3 = value
        End Set
    End Property
End Class
```

「レポートデータ」で「新規」→「データセット」を選ぶ。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/35353fb6-19da-9cd0-917e-cf3fef0e7901.png)

「データソース」の「新規」を押す。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/639bec7d-eece-03db-60cc-0eaf2d9119f0.png)

「オブジェクト」を選択して次へ。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/1760455b-623e-c7c9-adac-b09c66727d1e.png)

追加したいクラスを選択して「完了」を押す。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/bf10d8e5-eeef-f022-fcf2-ba30cd388140.png)

選択したクラスのフィールドなどが追加されるので、OKを押す。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/c310d325-ef05-42b1-c663-d216e5ace251.png)

レポートファイルのデザイナで、「一覧」を追加する。

一覧(Tablix)のプロパティ「DataSetName」に、追加したDataSetの名前を指定する。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/e43e1fca-1398-18d0-96db-18ec512441f9.png)

## 単票項目を作成してデータを表示する

ツールボックスから「テキストボックス」等を追加する。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/0133c103-8659-e429-76cb-45de8fa2a74a.png)

テキストボックスの内部で右クリック→「プレースホルダの作成」を選ぶ。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/d697a2b4-f6f5-8e84-3db3-26be53d0b54e.png)

「ラベル」にデザイナ上で表示する名前を入力する。
「値」は右側のボタンを押す。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/71d75927-18d9-f159-0f52-4025f8681715.png)

カテゴリ「データセット」→表示したいデータのフィールドをダブルクリック。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/b3eb57ab-615d-ac1e-491d-9905bc19bae9.png)

設定後の様子。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/5fbf6491-56a9-0d7b-128c-49e6858b2f1f.png)

## 用紙のサイズや向きを指定する

レポートファイルの外側の余白で右クリック→「レポートのプロパティ」を選択。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/c7b94a8a-ea7f-3937-1fcd-8dfeb77ddd8c.png)

ページ設定画面が出るので、ここでサイズや向きを指定する。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/89fce5bc-02fe-94d4-a5f4-d59735dde9a8.png)

プログラムから指定する場合は、`PaperSize`クラスを使ってReportViewerの設定値を変更する。

```vb
ReportViewer1.PrinterSettings.DefaultPageSettings.PaperSize = new PaperSize("Custom", 100, 200)
```

[PaperSize Class (System.Drawing.Printing) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.drawing.printing.papersize)

## 1ページ目のみ表示する
テキストや四角形を特定のページのみ表示させたいときの設定方法。

設定したいオブジェクトを選択し、プロパティウィンドウの「Hidden」で「<式...>」を選択する。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/88be9ebb-a0d6-c063-f87b-d32542151328.png)

式の欄に、条件式を入力する。画面は1ページのみ項目を表示したいときの例。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/28ee2e02-8a55-7876-73f3-d4e7146e065e.png)

```vb
=IIf(Globals!OverallPageNumber = 1, False, True)
```
# レポートを表示する

フォームにReportViewerコントロールを追加する。

コントロールの右上の三角を押し、表示するレポートを選ぶ。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/a66bd92a-abfc-7c91-aedf-4ea978d35f00.png)

レポートのDataSetがオブジェクトの場合(に限るか不明)、BindingSourceが追加される。
行データの追加はそのBindingSourceに対して行う。

```vb
Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        For i = 0 To 4
            Dim row As New DataRow1
            row.Column1 = "列1"
            row.Column2 = "列2"
            row.Column3 = "列3"

            Me.DataRow1BindingSource.Add(row)
        Next

        Me.ReportViewer1.RefreshReport()
    End Sub
End Class
```

レポートを表示した様子。(列1と列2は英字フォントのままにしているので、日本語が表示されない)
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/dcdcb4ea-5074-dcce-549d-a839255b7397.png)

## 表示するレポートをコードで指定する

```vb
Me.ReportViewer1.LocalReport.ReportEmbeddedResource = "WindowsApp1.Report1.rdlc"
```
レポートファイルが「埋め込みリソース」になっていることを確認すること。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/e901692d-6926-a33d-06d7-4d1e2c87082e.png)

## 印刷レイアウトで表示する

```vb
Me.ReportViewer1.SetDisplayMode(Microsoft.Reporting.WinForms.DisplayMode.PrintLayout)
```

`DisplayMode`というプロパティもあるが、読み取り専用。

## レポートの名前を指定する
ReportViewerのプロパティ → `LocalReport` → `DisplayName`
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/e7d9cb86-d134-8854-d2d0-7517d769c901.png)

レポートを印刷したときのドキュメント名などがこれになる。
指定しない場合、レポートのファイル名が出てきてしまう。

# トラブルシューティング

## 1ページごとに空白ページが挿入されるとき
現象：
Viewerでレポートを印刷レイアウトで表示すると、1ページごとに空白ページが挿入されることがある。

解決策：
レポートの横幅がページからはみ出している可能性がある。
Body部の幅が、ページ設定のページサイズ＋余白の中に収まっているか確認すること。

参考：[reportviewer - Empty pages in RDLC-Report - Stack Overflow](https://stackoverflow.com/questions/4830944/empty-pages-in-rdlc-report)

## ReportViewerコントロール追加時にエラーになるとき
現象：
あるソリューションでReportViewerを使用した後、別ソリューションで同じくReportViewerを参照に追加し、Formにコントロールを追加すると下記エラーになる。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/39499f37-4694-caee-729f-188a37a625dd.png)

原因予想：
ツールボックスへReportViewerを追加する手順が上手くいかなかったかもしれない。

解決策：
`%localappdata%\Microsoft\VisualStudio\[バージョン番号?]\ProjectAssemblies`フォルダの内容を、念のためバックアップを取りつつ削除する。

# 参考
Getting started with the ReportViewer 2016 control - SQL Server Reporting Services (SSRS) | Microsoft Docs
https://docs.microsoft.com/en-us/sql/reporting-services/application-integration/integrating-reporting-services-using-reportviewer-controls-get-started?view=sql-server-2017

Microsoft レポートによる帳票の作成 - Qiita
https://qiita.com/mima_ita/items/dd95ba1f25ba176fccb3

Microsoft Report の基礎の基礎 - Qiita
https://qiita.com/sebon77@github/items/a7ead91de9ab8a9860b2