Cloud Run functionsとActiveReports for .NETでつくる帳票生成API

.NET帳票コンポーネント「ActiveReports for .NET(アクティブレポート)」の最新バージョン「18.0J」では、クラウド環境のサポートが拡充され、新たに大手クラウドベンダー4社の「FaaS(Function as a Service)」が利用可能となりました。今回は、その中からGoogle Cloudの「Cloud Run functions」とActiveReportsを利用して、帳票機能をWeb APIとして作成する方法をご紹介します。

開発環境

ActiveReports for .NETの開発環境にはOSに「Windows」、統合開発環境(IDE)に「Visual Studio」が必要となります。事前に、ActiveReportsの必要システムに記載されている、開発環境をご準備ください。さらに、今回はCloud Run functionsのデプロイ先としてGoogle Cloud環境もご用意ください。

今回の開発環境では、以下を使用します。

  • Google Cloud環境
    ※ 事前にCloud Run Functionsのデプロイ先となるGoogle Cloudプロジェクト作成しておく必要があります。今回の記事では「ActiveReports」という名前で作成しています。詳しい作成方法については、こちらを参考に作成してください。
  • Google Cloud SDKGoogle Cloud CLI
    ※ 事前に、Google Cloud CLIを使用して用意したGoogle Cloud環境アカウントへの接続を完了させる必要があります。接続方法については、こちらを参考に設定してください
  • Visual Studio「Google Cloud Functions」プロジェクトテンプレート
    こちらを参考に、事前にプロジェクトテンプレートをインストールしてください。
  • OS:Windows 11(23H2)
  • IDE:Visual Studio 2022(Version 17.13.2)
  • ActiveReports:18.0J SP1(v18.1.1.0)
  • Postman
    POST動作の確認で利用します。デスクトップ版もしくはVisualStudio Code拡張機能を準備してください。

製品版の最新バージョンは以下より入手可能です。

トライアル版は無料で以下より入手可能です。

プロジェクトの作成

それでは、プロジェクトの作成を行っていきます。今回は次のように事前にインストールしたVisual Studio「Google Cloud Functions」プロジェクトテンプレートを利用します。

検索ボックスに「Google Cloud Functions HttpFunction」と入力すると、「Google Cloud Functions HttpFunction(Google LLC)」がフィルタリングされますので、この中から「C#」のテンプレートを選択して[次へ]ボタンを押します。
※ 同名のテンプレートで、「C#」、「F#」、「Visual Basic」があるため、ご注意ください。

プロジェクトの作成1

続いて表示されるダイアログでは、プロジェクト名を「GoogleFunctionsReportsApp」とします。保存場所は任意の場所を設定してください。

プロジェクトの作成2

NuGetからActiveReportsパッケージをインストール

プロジェクトが作成されると次のような画面が表示されます。まずはActiveReportの関連パッケージをNuGetからインストールしていきます。

図のように、ソリューションエクスプローラー上からプロジェクトを右クリックし「NuGetパッケージの管理」を選択します。

NuGetからのインストール1

続いて、NuGetパッケージマネージャーの表示後、「参照」タブを選択、検索テキストボックスに「MESCIUS.ActiveReports.ja」を入力します。検索結果には次のように「MESCIUS.ActiveReports.ja」が表示されるので、選択し、インストールを行います。

NuGetからのインストール2

さらに、今回作成するAPIで利用するPDF出力に関するパッケージ「MESCIUS.ActiveReports.Export.Pdf.ja」もインストールします。

NuGetからのPDFパッケージインストール

帳票レイアウト

パッケージのインストール後、帳票レイアウトの準備を行います。今回は以下のGitHubに公開されているレポートファイル「Invoice_bluegray.rdlx」を利用します。

今回のプログラムは、Cloud Run functionsのWebAPIとして実装します。APIのリクエストのタイミングでJSONデータを渡し、そのデータを帳票のデータソースとして利用して帳票を生成する構成として実装を行っていきます。

最初に、ダウンロードしたレポートファイルを次のようにソリューションエクスプローラーから追加します。追加の際、ファイルのビルドアクションを「埋め込みリソース」に変更します。

レポートファイルの追加

続けて、APIのリクエスト時に渡されるJSONデータを帳票のデータソースとして利用するために、データを格納する「レポートパラメータ」を追加していきます。

追加したファイルを選択し、Visual StudioのIDEデザイナで開きます。次に、レポートエクスプローラからパラメータを選択し、「パラメータの追加」を使用してレポートパラメータを追加します。

レポートファイルの編集1

レポートパラメータダイアログが表示後、パラメータ名称など変更可能です。今回は初期値のままにしておきます。

レポートファイルの編集2

続いて、レポートパラメータダイアログの「既定値」タブを選択します。「値を直接入力」を選び、「+アイコン」をクリックして既定値のリストを追加します。追加されたリスト内に、レポート表示データの初期値となるJSONデータを設定します。

レポートファイルの編集3
レポート表示初期値用JSONデータ
[
  {
    "ID": 1,
    "BillNo": "WS-DF502",
    "SlipNo": "GB465",
    "CustomerID": 1,
    "CustomerName": "長崎カントリーフーズ",
    "Products": "コーヒー 250 ml",
    "Number": 100,
    "UnitPrice": 100,
    "Date": "2020-01-05T00:00:00"
  },
  {
    "ID": 2,
    "BillNo": "WS-DF502",
    "SlipNo": "GB465",
    "CustomerID": 1,
    "CustomerName": "長崎カントリーフーズ",
    "Products": "紅茶 350 ml",
    "Number": 300,
    "UnitPrice": 120,
    "Date": "2020-01-05T00:00:00"
  },
  {
    "ID": 3,
    "BillNo": "WS-DF502",
    "SlipNo": "DK055",
    "CustomerID": 1,
    "CustomerName": "長崎カントリーフーズ",
    "Products": "炭酸飲料 (オレンジ) 350 ml",
    "Number": 200,
    "UnitPrice": 120,
    "Date": "2020-01-09T00:00:00"
  }
]

つづけて、追加したレポートパラメータを帳票のデータソースとして利用する為、以下のようにレポートエクスプローラの「データソース」から現在設定されている「DataSource1」を編集で開きます。

レポートファイルの編集4

レポートデータソースダイアログの表示後、次の画像のように「コンテンツ」タブ内の「JSONデータの形式の選択」を「式」に変更し、つづけて「式の入力」に="jsondata=" &[@ReportParameter1]を入力します。

レポートファイルの編集5

以上で、帳票レイアウトの設定は終了です。

コード実装

つづいて、コードの実装を行います。プロジェクトの作成時に、次の「Function.cs」というファイルが追加されています。このファイルに対して、次のコードで強調表示している箇所を実装していきます。

using Google.Cloud.Functions.Framework;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;
using System;
using System.IO;
using System.Reflection;
using System.Text.Json;
using GrapeCity.ActiveReports;

namespace GoogleFunctionsReportsApp;

public class Function : IHttpFunction
{
    /// <summary>
    /// JSONを取得し、テンプレートに設定してPDF化。結果のPDFを'report.pdf'として保存しHTTPレスポンスで返却。エラー時は500を返す。
    /// </summary>
    /// <param name="context">リクエストとレスポンスを含むHTTPコンテキスト。</param>
    /// <returns>PDF生成および送信処理の完了を示す非同期タスク。</returns>
    public async Task HandleAsync(HttpContext context)
    {
    // HTTPリクエストオブジェクトを取得
    HttpRequest request = context.Request;

        string Datajson = request.Query["DataJson"].ToString();
        // リクエストボディを取得
        string requestBody = await new StreamReader(request.Body).ReadToEndAsync();

        JsonDocument dataDocument = null;
        if (!string.IsNullOrEmpty(requestBody))
        {
            dataDocument = JsonDocument.Parse(requestBody);
        }
        // クエリパラメータが空の場合、リクエストボディのDataJsonを使用
        if (string.IsNullOrEmpty(Datajson) && dataDocument != null)
        {
            Datajson = JsonSerializer.Serialize(dataDocument.RootElement);
        }

        try
        {
            // アセンブリ取得
            var assembly = Assembly.GetExecutingAssembly();
            var assemblyName = assembly.GetName().Name;

            // レポートファイルのストリームを取得
            var stream = assembly.GetManifestResourceStream(assemblyName + ".Invoice_bluegray.rdlx");
            var streamReader = new StreamReader(stream);

            // レポートファイルを読み込み
            GrapeCity.ActiveReports.PageReport pageReport = new PageReport(streamReader);

            // レポートにパラメータを設定
            pageReport.Document.Parameters[0].Values[0].Value = Datajson;

            // PDF出力設定
            GrapeCity.ActiveReports.Export.Pdf.Page.Settings pdfSetting = new GrapeCity.ActiveReports.Export.Pdf.Page.Settings();
            GrapeCity.ActiveReports.Export.Pdf.Page.PdfRenderingExtension pdfRenderingExtension = new GrapeCity.ActiveReports.Export.Pdf.Page.PdfRenderingExtension();
            GrapeCity.ActiveReports.Rendering.IO.MemoryStreamProvider outputProvider = new GrapeCity.ActiveReports.Rendering.IO.MemoryStreamProvider();

            // PDFレンダリング
            pageReport.Document.Render(pdfRenderingExtension, outputProvider, pdfSetting);

            // PDFファイルをMemoryStreamに変換
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            outputProvider.GetPrimaryStream().OpenStream().CopyTo(ms);

            System.IO.File.WriteAllBytes("report.pdf", ms.ToArray());

            context.Response.ContentType = "application/pdf";
            context.Response.StatusCode = 200;
            context.Response.ContentLength = ms.Length;
            ms.Position = 0;
            await ms.CopyToAsync(context.Response.Body);
            await context.Response.SendFileAsync("report.pdf");
        }
        catch (Exception ex)    // エラー処理
        {
            context.Response.StatusCode = 500;
            await context.Response.WriteAsync(ex.Message);
        }
    }
}

このコードでは、GETメソッドのリクエスト時にクエリパラメータ「DataJson」を渡すか、POSTメソッドの場合はリクエストボディで設定されたJSONデータを渡します。これを帳票レイアウトで定義したレポートパラメーターを通じて帳票データソースとして利用し、最終的にPDFファイルとして帳票を作成しています。

動作確認

ここまでで、帳票レイアウトの編集、コード実装が一通り終了しましたので、ローカルのデバック実行にて動作の確認を行います。ブラウザで「127.0.0.1:8080/?DataJson=以下のJSON文字列」を設定します。

[{"ID":1,"BillNo":"WS-DF502","SlipNo":"GB465","CustomerID":1,"CustomerName":"ローカルテスト","Products":"コーヒー 250 ml","Number":100,"UnitPrice":100,"Date":"2020-01-05T00:00:00"},{"ID":2,"BillNo":"WS-DF502","SlipNo":"GB465","CustomerID":1,"CustomerName":"ローカルテスト","Products":"紅茶 350 ml","Number":300,"UnitPrice":120,"Date":"2020-01-05T00:00:00"},{"ID":3,"BillNo":"WS-DF502","SlipNo":"DK055","CustomerID":1,"CustomerName":"ローカルテスト","Products":"炭酸飲料 (オレンジ) 350 ml","Number":200,"UnitPrice":120,"Date":"2020-01-09T00:00:00"}]

リクエスト時に送信したJSONデータが帳票のデータソースとして設定され、PDF形式で帳票が生成されました。

Google Cloud環境へデプロイ

ここまでで、帳票レイアウト作成、コード実装、ローカル環境での動作確認までの、一連の作業が完了しましたので、Google Cloud環境へのデプロイを行っていきます。

ライセンス設定

Google Cloud環境へデプロイする為に、まずアプリケーションへのライセンス設定を行っていきます。

「Cloud Run functions」を含む、FaaS(Function as a Service)環境での実行には、通常の「.NETアプリケーション」と異なり、「gclm.exe」を利用したライセンスを付与する必要があります。
※ Cloud Run functionsを利用する際は通常のコアサーバーライセンスでは利用できません。配布ライセンスの詳細については営業部へお問い合わせください。

まず、以下のように、Windowsのコマンドラインツールで「gclm.exe」が配置されているパスへ移動します。

cd C:\ProgramData\GrapeCity\gclm

続いて、次の形式のコマンドを実行し、任意のフォルダにライセンスファイルを生成します。

gclm.exe "[ActiveReports GUID]" -lc "[output dir]/[filename].gclicx" [assemblyName].dll
項目設定内容
[ActiveReports GUID]ActiveReports for .NET 18.0J 製品IDを設定します。
8145dedc-e6e6-4af3-917b-c3fb57853f6b
[output dir]ライセンスファイルの出力先フォルダを設定します。
[filename]任意のファイル名を設定します。
[assemblyName]アプリケーションのアセンブリ名を指定します。今回は次のアセンブリ名を設定します。
GoogleFunctionsReportsApp

上述のコマンドを利用して、以下のように、ライセンスの付与ファイル「.gclicx」を生成します

ライセンス付与

続いて、コマンドにより生成されたライセンスファイル「.gclicx」をプロジェクト内に含め、ビルドアクションを「埋め込みリソース」に設定します。

ライセンスファイルの追加

上記に加えて、プロジェクトファイルをエディタで開き、以下のように<PropertyGroup>内に<disablegclm>true</disablegclm>の記述を追加します。この設定は、通常の.NETアプリケーションをビルドする際に自動的に付与されているライセンスを無効化するものです。プロジェクトファイルを編集した後、再度プロジェクトを開き直してください。

自動付与ライセンスを無効化

フォント設定

つづいて、フォントの設定を行っていきます。今回使用している帳票レイアウトでは、フォントを「IPAゴシック」に設定しています。ローカル環境では該当フォントがインストールされているため、問題なく表示されていましたが、Google Cloud環境上にはこのフォントがインストールされていないため、フォントファイルを含めてデプロイする必要があります

まず、プロジェクト内に「Fonts」フォルダを作成し、そのフォルダ内にフォントファイルを格納し、ビルドアクションを「埋め込みリソース」に設定します。※ IPAゴシックファイルはこちらからダウンロード可能です。

フォントファイルの追加

格納したフォントファイルを作成した帳票で利用するため、「EmbeddedFontResolver」クラスを追加します。

using GrapeCity.ActiveReports;
using GrapeCity.Documents.Text;
using System.Reflection;

internal sealed class EmbeddedFontResolver : IFontResolver
{
    internal static readonly IFontResolver Instance = new EmbeddedFontResolver();
    internal static readonly Font Ipag;
    static EmbeddedFontResolver()
    {
        var assembly = Assembly.GetExecutingAssembly();
        var assemblyName = assembly.GetName().Name;

        Ipag = Font.FromStream(assembly.GetManifestResourceStream(assemblyName + ".Fonts.ipag.ttf"));
    }
    internal EmbeddedFontResolver() { }
    public FontCollection GetFonts(string familyName, bool isBold, bool isItalic)
    {
        var fonts = new FontCollection();
        fonts.AppendFonts(new Font[] { Ipag }, true);
        return fonts;
    }
}

さらに、実装済みの「Function」内で、次のコードの強調表示されている箇所において、レポートオブジェクトに追加したクラスを利用してフォントの設定を行います。

・・・(中略)・・・

        try
        {
            // アセンブリ取得
            var assembly = Assembly.GetExecutingAssembly();
            var assemblyName = assembly.GetName().Name;

            // レポートファイルのストリームを取得
            var stream = assembly.GetManifestResourceStream(assemblyName + ".Invoice_bluegray.rdlx");
            var streamReader = new StreamReader(stream);

            // レポートファイルを読み込み
            GrapeCity.ActiveReports.PageReport pageReport = new PageReport(streamReader);

            // フォントの設定
            pageReport.FontResolver = new EmbeddedFontResolver();

            // レポートにパラメータを設定
            pageReport.Document.Parameters[0].Values[0].Value = Datajson;

            // PDF出力設定
            GrapeCity.ActiveReports.Export.Pdf.Page.Settings pdfSetting = new GrapeCity.ActiveReports.Export.Pdf.Page.Settings();
            GrapeCity.ActiveReports.Export.Pdf.Page.PdfRenderingExtension pdfRenderingExtension = new GrapeCity.ActiveReports.Export.Pdf.Page.PdfRenderingExtension();
            GrapeCity.ActiveReports.Rendering.IO.MemoryStreamProvider outputProvider = new GrapeCity.ActiveReports.Rendering.IO.MemoryStreamProvider();

            // PDFレンダリング
            pageReport.Document.Render(pdfRenderingExtension, outputProvider, pdfSetting);

・・・(中略)・・・

デプロイ

ライセンス設定とフォント設定が完了し、Google Cloudへのデプロイの準備が整いましたので、アプリケーションをGoogle Cloud上にデプロイします。

Google Cloudのデプロイには、開発環境として準備していた「Google Cloud CLI」を利用していきます。デフォルトでインストールした場合「Google Cloud SDK Shell」のショートカットがデスクトップに作成されていますので、そちらから開いてください。

Google Cloud CLIの起動

続いて、CLIがGoogle Cloud環境アカウントへの接続されているかを次のコマンドで確認します。

gcloud config get-value core/account

次のように、アカウントが表示されれば接続済みです。

アカウントの確認

続いて、デプロイ先のGoogle Cloudプロジェクトを設定します。次のコマンドを実行してください。

gcloud config set project [プロジェクトID]

プロジェクトIDには、今回デプロイ先のIDを設定します。

gcloud config set project activereports

設定後、正しく設定されているかを以下のコマンドで確認します。

gcloud config get-value core/project

正しく、設定されている場合は、次のようにプロジェクトIDが表示されます。

GoogleCloudプロジェクトの設定

ここまでで、準備が整いましたので、デプロイしていきます。まず、作成したプロジェクトファイルが含まれる、ディレクトリに移動します。

プロジェクトフォルダへ移動

続いて、次のコマンドでデプロイを実行していきます。

gcloud functions deploy GoogleFunctionsReportsApp ^
  --entry-point=GoogleFunctionsReportsApp.Function ^
  --runtime=dotnet8 ^
  --region=asia-northeast1 ^
  --source=. ^
  --trigger-http ^
  --allow-unauthenticated

コマンドのパラメータオプションは次の表のとおりです。

オプション名内容
gcloud functions deployCloud Functions に関数をデプロイするコマンドgcloud functions deploy [ファンクション名]
--entry-pointエントリーポイントとなる関数名(クラス.メソッド名など)を指定--entry-point=[クラス.メソッド名など]
--runtime使用するランタイム環境を指定(例: Python, Node.js, Go, .NET など)--runtime=dotnet8
--regionデプロイ先のリージョンを指定--region=asia-northeast1
--sourceソースコードのパス(. はカレントディレクトリを意味する)--source=.
--trigger-httpHTTP リクエストで関数を実行するトリガーを指定(API化)--trigger-http
--allow-unauthenticated認証なしでも関数にアクセスできるようにする(誰でもアクセス可能になる)--allow-unauthenticated

コマンドの実行後、次のようにビルド・デプロイが実行されます。

GoogleCloudへデプロイ1

デプロイが完了すると、次のようにデプロイ結果が表示され、デプロイ先のURLが表示されます。

GoogleCloudへデプロイ2

動作確認

最後に動作確認を行っていきます。ブラウザで「デプロイ先のホストアドレス/GoogleFunctionsReportsApp?DataJson=以下のJSON文字列」を設定します。

[{"ID":1,"BillNo":"WS-DF502","SlipNo":"GB465","CustomerID":1,"CustomerName":"GoogleCloudテスト","Products":"コーヒー 250 ml","Number":100,"UnitPrice":100,"Date":"2020-01-05T00:00:00"},{"ID":2,"BillNo":"WS-DF502","SlipNo":"GB465","CustomerID":1,"CustomerName":"GoogleCloudテスト","Products":"紅茶 350 ml","Number":300,"UnitPrice":120,"Date":"2020-01-05T00:00:00"},{"ID":3,"BillNo":"WS-DF502","SlipNo":"DK055","CustomerID":1,"CustomerName":"GoogleCloudテスト","Products":"炭酸飲料 (オレンジ) 350 ml","Number":200,"UnitPrice":120,"Date":"2020-01-09T00:00:00"}]

次のように、クエリパラメータとして渡されたJSON文字列がPDF帳票として生成されました。

つづいて、POST動作も確認します。今回は、Postmanを利用してPOSTリクエストを実行します。

Google Cloud上にデプロイしたアプリにおいても、GETおよびPOSTの各メソッドで、請求書PDF帳票生成が確認できました。

さいごに

今回の記事では、ActiveReports for .NET 18.0JがサポートするGoogle Cloudの「Cloud Run functions」を利用し、帳票機能をWeb APIとして構築する方法をご紹介しました。

Cloud Run functionsを活用することで、インフラ運用の負担を軽減しつつ、帳票処理の負荷変動に柔軟に対応できます。さらに、マイクロサービス化により他システムとの連携性や拡張性が高まり、迅速なサービス改善が可能になります。

クラウド、サーバーレス、そしてマイクロサービスを組み合わせた帳票サービス構築のヒントとして、今回ご紹介した方法をぜひ参考にしていただければ幸いです。

今回の内容について動作を確認されたい方は、是非トライアル版ダウンロードの上、GitHub上のコードをお試しください。

また、今回の記事でご紹介したGoogle Cloudの「Cloud Run functions」と同様のFaaS運用環境である「Microsoft Azure Functions」、「AWS Lambda」での帳票生成APIの作成方法も以下の記事でご紹介していますので、こちらもあわせてご確認ください。

製品の機能を手軽に体験できるデモアプリケーションも公開しておりますので、こちらもご確認ください。

また、ご導入前の製品に関するご相談、ご導入後の各種サービスに関するご質問など、お気軽にお問合せください。

\  この記事をシェアする  /