rksoftware

Visual Studio とか C# とかが好きです

.NET Core デスクトップアプリケーションで PDF 帳票を画面表示する

.NET Core 3.0 で Windows デスクトップアプリ(WPF/WinForms)が .NET Core で作れるようになりました。
しかし、実際にデスクトップアプリを作る際には様々なライブラリを導入することが多いものです。その中でもいわゆる帳票出力コンポーネントは日本では非常に人気の高い要件でしょう。これがなければどんなに WPF の .NET Core 対応が完璧でも採用できないケースも多いはずです。

そこで DioDocs です、という記事を以前に書きました。

※DioDocs について

詳しくは次の素晴らしい記事を読んでください。

■ 前回のあらすじ

テンプレートとなる Excel ファイルを読み込んでセルに値を設定したシートを PDF ファイルとして出力し、Edge で表示しました。

■ 今回のあらすじ

PDF ファイルを出力せず、WPF 上の Image コントロールに画像として表示します。

■ 試してみる

試してみましょう。

  • プロジェクトの作成
  • NuGet パッケージのインストール
  • テンプレートの Excel

というところまでは前回と同様です。

□ コード

<Window x:Class="dotnetcorediodocs.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:dotnetcorediodocs"
        mc:Ignorable="d"
        Title="MainWindow" Height="500" Width="500">
    <StackPanel HorizontalAlignment="Center" Margin="20">
        
        <Label Content="メニュー" FontSize="20"/>
        <TextBox HorizontalAlignment="Stretch" x:Name="menuText"/>
        
        <Label Content="価格"  FontSize="20"/>
        <TextBox HorizontalAlignment="Stretch" x:Name="priceText"/>
        
        <Button Content="印刷" Grid.Row="1" FontSize="20" Click="Button_Click"/>
        <Image HorizontalAlignment="Center" Width="800" Height="800" x:Name="imgPdf"/>
    </StackPanel>
</Window>
using System.Linq;
using System.Windows;
using System.Windows.Media.Imaging;
using System;
using System.IO;

namespace dotnetcorediodocs
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            // 入力文字列を数値にパース
            if (!int.TryParse(priceText.Text, out var price)) return;

            var image = new BitmapImage();

            // テンプレート Excel を読み込む
            var workbook = new GrapeCity.Documents.Excel.Workbook();
            workbook.Open("template.xlsx");
            var activesheet = workbook.ActiveSheet;

            // データを書き込む
            foreach (var row in Enumerable.Range(4, 7))
            {
                activesheet.Range[row, 2].Value = menuText.Text;
                activesheet.Range[row, 3].Value = price;
            }

            // PDF に変換して表示
            using (var memoryStream = new MemoryStream())
            using (var randomAccesStream = memoryStream.AsRandomAccessStream())
            using (var inMemoryRandomAccessStream = new Windows.Storage.Streams.InMemoryRandomAccessStream())
            using (var stream = inMemoryRandomAccessStream.AsStream())
            {
                // PDF ファイルをストリームに保存
                workbook.Save(memoryStream, GrapeCity.Documents.Excel.SaveFileFormat.Pdf);

                // PDF を画像に変換
                var pdfDocument = await Windows.Data.Pdf.PdfDocument.LoadFromStreamAsync(randomAccesStream);
                using (var page = pdfDocument.GetPage(0))
                {
                    await page.RenderToStreamAsync(inMemoryRandomAccessStream);
                }

                image.BeginInit();
                image.CacheOption = BitmapCacheOption.OnLoad;
                image.StreamSource = stream;
                image.EndInit();
            }

            // 画像を表示
            imgPdf.Source = image;
        }
    }
}

□ PDF をストリームに保存

DioDocs では PDF をファイルを保存するだけでなく、ストリームに Save することもできます。このストリームから頑張ればファイル保存なしに画面へ表示することができます。

// PDF ファイルをストリームに保存
workbook.Save(memoryStream, GrapeCity.Documents.Excel.SaveFileFormat.Pdf);

□ PDF を画像に 変換

Windows 10 の機能の PdfDocument クラスを使うと PDF を画像にできるそうです。

// PDF を画像に変換
var pdfDocument = await Windows.Data.Pdf.PdfDocument.LoadFromStreamAsync(randomAccesStream);
using (var page = pdfDocument.GetPage(0))
{
    await page.RenderToStreamAsync(inMemoryRandomAccessStream);
}

※次の記事を参考にさせていただきました。

参考記事では、System.Runtime.WindowsRuntime.dll を .NETCore フォルダのものを参照していますが、今回は

C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.6\System.Runtime.WindowsRuntime.dll

を参照しました。こちらでないと AsRandomAccessStream() メソッドがありませんでした。

今回参照へ追加したもの

ファイル パス
System.Runtime.WindowsRuntime.dll C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.6\System.Runtime.WindowsRuntime.dll
Windows.winmd C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.17763.0\Windows.winmd

■ 実行

PDF が画面の Image コントロールに表示できました。
f:id:rksoftware:20190131032801j:plain