4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Visual BasicAdvent Calendar 2021

Day 18

Visual Basic で簡単レポート作成

Last updated at Posted at 2021-12-18

<おことわり>

帳票は無くならない

請求書、依頼書、出荷明細書など、企業で使う帳票は、ペーパーレスが徐々に浸透しつつある今でも無くなる気配がない。ペーパーレスになったところで、見たいものを簡潔にまとめ上げるレイアウト情報としての帳票は、まだまだ存在し続けるだろう。
そんな帳票を作るのに、AccessのレポートやRDLCなどを使っている人も多いと思うが、

WPF + Visual Basic でやってみたら意外に楽しかった:laughing:
FixedDocumentを使う

WPFでレポート作成するのなら、FixedDocumentクラスがお勧めだ。
レポートの大枠が、以下のようにでき上がっている。
大枠.png
この枠の中に、Xamlで帳票を組み立てていく。

Xamlで帳票を組み立てる

せっかくなので、最新のVisual Studio 2022を使い、.NET6で作ってみよう。
まずはWPFプロジェクトを作成する。
WPFプロジェクト作成.png
次にUserControlを追加。
UserControl追加.png
追加したUserControlにXamlをゴリゴリ書いていく。Xamlデザイナーに慣れていない人は、デザインビューでの編集はしないことだ。思い通りにコントロールを配置できず、イライラが増して嫌になる。デザインビューは仕上がりを視覚的に確認するものと割り切った方がいい。
XamlビューでXamlのテキストを直接書き込んでいく。書くと言っても大部分はコピぺで済む。
まずはGridCanvasに変える。Canvasは、レポート内の文字や罫線が固定されるので帳票作成に向いている。Canvas内はセンチメートルでサイズを書ける。
以下、単純な帳票を書いてみた。

ShukkaUserControl.xaml
<UserControl x:Class="ShukkaUserControl"
    -- 省略 --
    DataContext="{StaticResource ShukkaVM}"
    Height="1122.51" Width="793.7">
    <UserControl.Resources>
        <Style x:Key="Line1" TargetType="Line">
            <Setter Property="StrokeThickness" Value="1"/>
            <Setter Property="Stroke" Value="Black"/>
        </Style>
    </UserControl.Resources>
    <Canvas Background="White">
        <!--横線-->
        <Line X1="6cm" X2="15cm" Y1="3.5cm" Y2="3.5cm" Style="{StaticResource Line1}"/>
        <Line X1="1cm" X2="20cm" Y1="5cm" Y2="5cm" Style="{StaticResource Line1}"/>
        <Line X1="1cm" X2="20cm" Y1="7cm" Y2="7cm" Style="{StaticResource Line1}"/>
        <Line X1="1cm" X2="20cm" Y1="15cm" Y2="15cm" Style="{StaticResource Line1}"/>
        <Line X1="1cm" X2="20cm" Y1="17cm" Y2="17cm" Style="{StaticResource Line1}"/>
        <Line X1="1cm" X2="20cm" Y1="19cm" Y2="19cm" Style="{StaticResource Line1}"/>
        <!--縦線-->
        <Line X1="1cm" X2="1cm" Y1="5cm" Y2="19cm" Style="{StaticResource Line1}"/>
        <Line X1="10.5cm" X2="10.5cm" Y1="7cm" Y2="19cm" Style="{StaticResource Line1}"/>
        <Line X1="20cm" X2="20cm" Y1="5cm" Y2="19cm" Style="{StaticResource Line1}"/>
        <!--文字列-->
        <TextBlock Text="出 荷 指 図 書" Margin="6.65cm,2cm" Width="8cm" Height="1.5cm" FontSize="46"/>
        <TextBlock Text="出荷指図№" Margin="1.25cm,5.25cm" Height="1.5cm" FontSize="36" FontWeight="Bold"/>
        <TextBlock Text="納品先" Margin="1.25cm,7.25cm" Height="1cm" FontSize="26"/>
        <TextBlock Text="住所" Margin="10.75cm,7.25cm" Height="1cm" FontSize="26"/>
        <TextBlock Text="出荷日" Margin="1.25cm,15.25cm" Height="1cm" FontSize="26"/>
        <TextBlock Text="納品日" Margin="1.25cm,17.25cm" Height="1cm" FontSize="26"/>
        <TextBlock Text="個数" Margin="10.75cm,15.25cm" Height="1cm" FontSize="26"/>
        <TextBlock Text="運送便" Margin="10.75cm,17.25cm" Height="1cm" FontSize="26"/>
        <!--設定値-->
        <TextBlock Text="{Binding 出荷指図NO}" Margin="7cm,5.25cm" Height="1.5cm" Width="10cm" FontSize="36"/>
        <TextBlock Text="{Binding 納品先}" Margin="1.25cm,9cm" Height="5cm" FontSize="20"/>
        <TextBlock Text="{Binding 住所}" Margin="10.75cm,9cm" Height="5cm" FontSize="20"/>
        <TextBlock Text="{Binding 出荷日}" Margin="4cm,15.5cm" Height="1cm" FontSize="20"/>
        <TextBlock Text="{Binding 納品日}" Margin="4cm,17.5cm" Height="1cm" FontSize="20"/>
        <TextBlock Text="{Binding 個数}" Margin="13cm,15.5cm" Height="1cm" FontSize="20"/>
        <TextBlock Text="{Binding 運送便}" Margin="14cm,17.5cm" Height="1cm" FontSize="20"/>
    </Canvas>
</UserControl>

でき上りは以下のとおり。
出荷指図書.png
このレベルならAccessのレポートで十分作れるのだが、Xamlなら更に複雑なことができるのは想像がつくだろう。
コントロールをマウスでドラッグして線が斜めになったとか、部分的に表示位置をずらしたくなったとか、Accessレポートなどではうんざりする修正作業も、Xamlならストレス無く、各コントロールの座標数字を書き換えるだけで済む。

ここで、3行目の、

DataContext="{StaticResource ShukkaVM}

は、本来ならViewModelを作成してから書く。(:warning:これを書かない方法を後述しています)

ViewModelの作成

以下は追加したユーザーコントロールのViewModelである。コードビハインドは一切汚さない。ふざけたコードだが、わかりやすさ重視だ:grin:

ShukkaViewModel.vb
Public Class ShukkaViewModel
    ' 以下バインドするプロパティたち
    ' バインドするならプロパティでなければならない
    Public Property 出荷指図NO As String
    Public Property 納品先 As String
    Public Property 住所 As String
    Public Property 出荷日 As String
    Public Property 納品日 As String
    Public Property 個数 As String
    Public Property 運送便 As String
    ' コンストラクタ
    Public Sub New()
        ' 実際はEntityFrameworkCoreなどでデータをはめ込むが、
        ' テーマから反れるので、ここでは省略
        出荷指図NO = "SK20211224-001"
        納品先 = "株式会社ほげ商事"
        住所 = "東京都中央区〇〇町〇丁目-〇-〇" & vbCr & "レポートビル1階"
        出荷日 = "12月24日"
        納品日 = "12月25日"
        個数 = "10個"
        運送便 = "佐山運輸"
    End Sub
End Class

以下はウインドのViewModelである。こちらもコードビハインドは一切汚さない。

MainWindowViewModel.vb
Public Class MainWindowViewModel 
    Public Property ReportViewer As FixedDocument
    Public Sub New()
        Dim report = New ShukkaUserControl
        Dim page = New FixedPage With {.Width = 793.7, .Height = 1122.51}
        Dim pageContent = New PageContent
        Dim doc = New FixedDocument
        page.Children.Add(report)
        pageContent.Child = page
        doc.Pages.Add(pageContent)
        ReportViewer = doc
    End Sub
End Class

ここでFixedDocumentをこしらえてReportViewerプロパティにセットしている。
今回は単一ページだが、複数ページも実装可能。これを見れば自力で作れると思う。
2ページ目以降は書式が変わってアタッチシート、なんてこともできるだろう。
FixedDocumentの構造は、

親)FixedDocument
子)PageContent
孫)FixedPage

で、孫のFixedPageの子供としてUserControlをChildren.Addする。

Application.xamlの編集(:warning:これを書かない方法を後述)

アプリで二つのViewModelを利用できるようにリソースとして登録する。

Application.xaml
<Application x:Class="Application"
    -- 省略 --
    StartupUri="MainWindow.xaml">
    <Application.Resources>
        <local:MainWindowViewModel x:Key="MainVM"/>
        <local:ShukkaViewModel x:Key="ShukkaVM"/>
    </Application.Resources>
</Application>

ここのx:Keyは自分の好みで名付ける。ウインドウとユーザーコントロールのDataContextに、これらの名前を各々設定する。

MainWindow.xamlの編集

MainWindow.xaml
<Window x:Class="MainWindow"
    -- 省略 --
    DataContext="{StaticResource MainVM}"
    Title="MainWindow" Height="600" Width="600">
    <Grid>
        <DocumentViewer Document="{Binding ReportViewer}"/>
    </Grid>
</Window>

3行目でDataContextにApplication.xamlで設定した MainWindowViewModel のリソースをセットしている。(:warning:これを書かない方法を次節に示しています)
また、Grid内でDocumentViewerDocumentReportViewerをバインドしている。
:warning:Application.xaml に書かない方法

@FKbelm さんの書かれた『XAML内でDataContextのプロパティにIntelliSenseが効くようにする』の前半部分を適用すると、Application.xaml には何も書かずに済みます。これは見習いたい。@FKbelm さん、ありがとうございます。

MainWindow.xaml
<Window x:Class="MainWindow"
    -- 省略 -- >
    <Window.DataContext>
        <local:MainWindowViewModel/>
    </Window.DataContext>
ShukkaUserControl.xaml
<UserControl x:Class="ShukkaUserControl"
    -- 省略 -- >
    <UserControl.DataContext>
        <local:ShukkaViewModel/>
    </UserControl.DataContext>

そして、

DataContext="{StaticResource MainVM}"

DataContext="{StaticResource ShukkaVM}"

は消します。

実行結果

実行結果.png
印刷や拡大縮小などの機能が既に組み込まれていて、それらを実装する必要はない。あー何て楽なんだろう。UXの時代に古臭い見た目だが、そんなことは気にしない:laughing:

WPF + Visual Basic は、まだまだ事務処理系の現場で使い倒せるのだ:bangbang:

4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?