ActiveReportsで実現する!Power Appsの帳票開発(2)

前回の記事では、Power Apps上でActiveReportsを利用する為、ActiveReportsのJSビューワをPower Appsのコードコンポーネントとして実装する方法と、ビューワに帳票機能を提供するASP.NET Core Webアプリの実装について解説いたしました。

今回の記事では、作成したコードコンポーネントをキャンバスアプリ上に配置して、実際にPower Apps上で帳票を開発する方法についてもご紹介していきます。

Power Apps上でActiveReports for .NETを利用する2

事前準備

今回は前回使用した開発環境に加え、新たに次の環境を用意します。

前回までに使用した環境は以下の通りです。

  • Visual Studio Code
  • Npm or Node.JS ※ LTS (長期サポート) バージョンのご利用をお勧め
  • Power Platform CLI(Power Apps Component Frameworkを利用する為のツール)
  • OS:Windows 11(23H2)
  • IDE:Visual Studio 2022(Version 17.9.5)
  • ActiveReports:18.0J (v18.0.0.0)

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

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

ActiveReportsビューワコンポーネントをPower Apps環境で利用する

ビューワコンポーネントのパッケージ化

それでは、前回までに作成した「コードコンポーネント」をPower Apps環境へアップする為にコンポーネントをパッケージ化していきます。

コードコンポネントのパッケージ化に詳細は以下で詳しく解説しています。

パッケージ化を行うためには、ソリューションプロジェクトを作成する必要があります。そのため、まずプロジェクトフォルダを作成する必要があります。また、ソリューションプロジェクトの作成時に「publisher-name」と「publisher-prefix」の指定が必要となります。今回は以下のように設定します。

  • フォルダ名:ARdotNetViewerSolution(ARdotNetViewerPCFの配下に作成します)
  • publisher-name(ソリューション発行者):ardotnet
  • publisher-prefix(ソリューション発行者を表すカスタマイズの接頭辞の値):ard

「コンポーネントのパッケージ化を行う方法」にしたがって、ビルドを行うと、次のようにコードコンポーネントがパッケージ化され「ARdotNetViewerSolution.zip」が作成されます。

Power Apps環境の設定

続いて、作成したパッケージをPower Apps環境で利用できるように以下の設定を行います。

  • コードコンポーネントの利用設定
  • コンポーネントのアップロードサイズ設定

詳しい環境設定の方法については、次の記事をご覧ください。

Power Apps 環境へアップロード

環境設定終了後、Power Apps 画面を開き、サイドバー「ソリューション」から次の動画のように作成したコンポーネントパッケージをアップロード(ソリューションをインポート)します。

パッケージのアップロードが完了すると、以下の図のようにパッケージが「ソリューション」としてアップロードされます。

ソリューションのインポート

Power Appsキャンバスアプリ上に帳票を作成

ここまでで、作成したコンポーネントを利用する準備が整いましたので、続いてはキャンバスアプリ上で、コンポーネントの利用した帳票機能を作成していきます。

キャンバスアプリ上にコードコンポーネントを追加

それでは、さっそく空のキャンバスアプリを作成していきます。初期状態では、コンポーネントの「挿入」メニューには追加したコンポーネントは表示されていませんので、以下のように追加してきます。

キャンバスアプリを作成

メニュー上からコンポーネントの追加も可能となりましたので、実際にキャンバスアプリを作成していきます。

まず、以下の図の青枠内のようにコンポーネントを配置し、アプリケーションのデザインを行います。

アプリレイアウトトデザイン

続いて追加したコンポーネントに、以下のプロパティを設定していきます。

「垂直コンテナ」コンポーネントのプロパティ設定
プロパティ設定値
コンポーネント名Container1
HeightParent.Height
WidthParent.Width
X0
Y0
「コンテナ」コンポーネントのプロパティ設定
プロパティ設定値
コンポーネント名Container2
FillRGBA(12, 161, 117, 1)
Height110
WidthParent.Width
X0
Y0
「ラベル」コンポーネントのプロパティ設定
プロパティ設定値
コンポーネント名Label1
HeightParent.Height
Width1000
X0
Y0
Text“ActiveReports for .NET on Power Apps”
※ プロパティペインから入力する際は「”」は不要です。
FontWeightSemibold
Size36
ColorRGBA(255, 255, 255, 1)
PaddingLeft50
「切替」コンポーネントのプロパティ設定
プロパティ設定値
コンポーネント名Toggle1
Height56
Width160
X1150
Y27
「水平コンテナ」コンポーネントのプロパティ設定
プロパティ設定値
コンポーネント名Container3
HeightParent.Height-110
WidthParent.Width
X0
Y0
LayoutMinHeightParent.Height-110
「ギャラリー」配下のコンポーネントのプロパティ設定
コンポーネントプロパティ設定値
ギャラリーコンポーネント名Gallery1
Items[
{reportsid:”AcmeStore.rdlx”},
{reportsid:”AnnualReport.rdlx”},
{reportsid:”Invoice.rdlx”},
{reportsid:”Invoice.rpx”},
{reportsid:”Invoice_Colored.rpx”},
{reportsid:”InvoiceList.rdlx”},
{reportsid:”Project & Resource Analysis – Staff Performance Analysis.rdlx”},
{reportsid:”Statistical analysis scatter plot.rdlx”},
{reportsid:”User defined report columns.rdlx”}
]
HeightParent.Height-110
WidthParent.Width
X0
Y0
LayoutMinHeight200
レイアウトタイトル
四角形
※デフォルト設定のまま
コンポーネント名Rectangle1
四角形
※デフォルト設定のまま
コンポーネント名Separator1
アイコン
※デフォルト設定のまま
コンポーネント名NextArrow1
ラベルコンポーネント名Title1
TextThisItem.reportsid
「ActiveReportsビューワコードコンポネント」のプロパティ設定
プロパティ設定値
コンポーネント名ARdotNetViewer1
FillPortions1
HeightParent.Height
WidthParent.Width-Gallery1.Width
X0
Y0
LayoutMinHeight1000

「ActiveReportsビューワコードコンポネント」には、上記の設定に加えて、独自に実装したプロパティ設定の追加も行います。

プロパティ設定値
Server_Url「AcitveReports ASP.NET Core Webアプリ」のホスト名を指定します。

今回は、前回Azure上にデプロイしたWebアプリのホストを指定します。
「https://任意のアプリケーション名.azurewebsites.net/”」
Reports_ID表示するレポートを指定します。

今回は次のように、ギャラリー上列挙されたレポートを、選択した内容が表示できるように以下に用に設定します。
Gallery1.Selected.reportsid」
Reports_Loadingレポートの読み込みを行うかどうかの設定です。
レポート設定が行われていない場合に読込を行うとエラーとなる動作の抑制を行います。

今回はアプリケーション上から、制御できるように切替コンポネントにて操作可能なように以下を設定します。
Toggle1.Value」
Style_Widthビューワコンポーネントのスタイル設定(幅)です。
今回は、他のコンポーネントのサイズに連動して動作するよう以下を設定しています。
(Parent.Width-Gallery1.Width) &”px”
Style_Heightビューワコンポーネントのスタイル設定(高さ)です。
今回は、他のコンポーネントのサイズに連動して動作するよう以下を設定しています。
Parent.Height & “px”

ここまで実施した、レイアウト作成とプロパティ設定により、帳票アプリの作成が完了となります。動作を確認すると、次の動画のように帳票アプリの基本的な動作である、「印刷プレビュー」、「印刷」、「PDFエクスポート」などが可能なことがわかります。また、「Power Apps」のギャラリーコンポーネント上から、出力する帳票を選択することで、複数の帳票を簡単に表示することも可能です。

Power Appsからのデータを帳票に利用

ここまでご紹介した内容では、あらかじめデータの設定までが行われた帳票を表示してきましたが、ここからは、Power Apps上に用意されたデータを利用した帳票を作成してみます。

レポートパラメータをデータソースとする帳票レイアウトの作成

新たな帳票レイアウトとして、以下のようなレイアウトをActiveReportsの帳票デザイナを利用し作成します。

帳票レイアウトの作成

この帳票レイアウトには、以下のように帳票出力の際にパラメータを渡すための「レポートパラメータ」を追加しています。

レポートパラメータ

また、この「レポートパラメータ」を帳票のデータソースとして利用するため、データソースには以下のように追加済みの「ReportParameter1」を参照するように設定を行っています。

レポートパラメータをデータソースの参照に指定

帳票レイアウトの作成は以上となります。細かなレポートの内容については、こちらをダウンロードの上ご確認ください。

ASP.NET Core Webアプリにレポートを追加し再デプロイ

作成した帳票レイアウトを、ASP.NET Core Webアプリに追加し、再度Azure上へデプロイします。

帳票レイアウトをWebアプリに追加

Azureへのデプロイについては以下をご覧ください。

ActiveReportsビューワコンポーネントにレポートパラメータプロパティを追加

帳票レイアウト、バックエンドWebアプリに続いて、作成済みのコードコンポーネントにレポートパラメータを渡すためのプロパティを追加します。今回変更する必要があるソースコードは以下となります。

マニフェストファイルの更新

<?xml version="1.0" encoding="utf-8" ?>
<manifest>
  <control namespace="ARdotNet" constructor="ARdotNetViewer" version="0.0.1" display-name-key="ARdotNetViewer" description-key="ARdotNetViewer description" control-type="virtual" >
    <!--external-service-usageノードは、このサードパーティPCFコントロールが外部サービスを使用しているかどうかを宣言します。もし使用している場合、このコントロールはプレミアムと見なされ、使用している外部ドメインも追加してください。  
    外部サービスを使用していない場合、enabled="false"に設定し、以下にドメインを追加しないでください。"enabled"はデフォルトでfalseになります。  
    例1:  
      <external-service-usage enabled="true">  
        <domain>www.Microsoft.com</domain>  
      </external-service-usage>  
    例2:  
      <external-service-usage enabled="false">  
      </external-service-usage>  
    -->  
    <external-service-usage enabled="true">  
    <domain>http://example.com/</domain>  
      <!--外部ドメインを追加するにはコメントを解除してください  
      <domain></domain>
      <domain></domain>
      -->
    </external-service-usage>
    <!-- propertyノードは、コントロールがCDSから期待する特定の設定可能なデータを識別します -->  
    <!-- <property name="sampleProperty" display-name-key="Property_Display_Key" description-key="Property_Desc_Key" of-type="SingleLine.Text" usage="bound" required="true" /> -->
    <property name="Server_Url" display-name-key="Server_Url" description-key="ActiveReport.Netのバックエンドサーバーを指定します。" of-type="SingleLine.Text" pfx-default-value ='"http://example.com/"' usage="input" required="true"  />  
    <property name="Reports_ID" display-name-key="Reports_ID" description-key="表示するレポートを指定します。" of-type="SingleLine.Text" pfx-default-value ='"Invoice.rdlx"' usage="input" required="true"/>  
    <property name="Reports_Loading" display-name-key="Reports_Loading" description-key="レポートの読み込みを行うかを指定します。" of-type="TwoOptions" pfx-default-value ='false' usage="input" required="true"/>  
    <property name="Reports_Parameter" display-name-key="Reports_Parameter" description-key="レポートへパラメータを渡します。" of-type="Multiple"  usage="input" required="false"/>  
    <property name="Style_Width" display-name-key="Style_Width" description-key="ビューワの横幅を指定します。" of-type="SingleLine.Text" pfx-default-value ='"100%"' usage="input" required="true"/>  
    <property name="Style_Height" display-name-key="Style_Height" description-key="ビューワの高さを指定します。" of-type="SingleLine.Text" pfx-default-value ='"100vh"' usage="input" required="true"/>
    <!--
      プロパティノードの of-type 属性は of-type-group 属性にすることができます。
      例:
      <type-group name="numbers">
        <type>Whole.None</type>
        <type>Currency</type>
        <type>FP</type>
        <type>Decimal</type>
      </type-group>
      <property name="sampleProperty" display-name-key="Property_Display_Key" description-key="Property_Desc_Key" of-type-group="numbers" usage="bound" required="true" />
    -->
    <resources>
      <code path="index.ts" order="1"/>
      <platform-library name="React" version="16.8.6" />
      <!-- <platform-library name="Fluent" version="8.29.0" />      -->
      <css path="css/App.css" order="1" />  
      <css path="css/jsViewer.min.css" order="2" />  
      <css path="css/jsViewer.chart.min.css" order="3" />  
      <!-- 追加のリソースを追加するにはコメントを解除してください  
      <css path="css/ARdotNetViewer.css" order="1" />
      <resx path="strings/ARdotNetViewer.1033.resx" version="1.0.0" />
      -->
    </resources>
    <!-- 指定されたAPIを有効にするにはコメントを解除してください  
    <feature-usage>
      <uses-feature name="Device.captureAudio" required="true" />
      <uses-feature name="Device.captureImage" required="true" />
      <uses-feature name="Device.captureVideo" required="true" />
      <uses-feature name="Device.getBarcodeValue" required="true" />
      <uses-feature name="Device.getCurrentPosition" required="true" />
      <uses-feature name="Device.pickFile" required="true" />
      <uses-feature name="Utility" required="true" />
      <uses-feature name="WebAPI" required="true" />
    </feature-usage>
    -->
  </control>
</manifest>

tsxファイルの更新

import * as React from 'react';  

// 型定義
interface GrapeCity {  
  ActiveReports: {  
    JSViewer: {  
      create: (config: { element: string;  reportService: { url: string } }) => ViewerInstance;  
    };  
  };  
}  
  
// ViewerInstance の型定義
interface ViewerInstance {  
  openReport: (
    report: string | null,
    reportParameters: Array<{ name: string; values: string[]}> 
  ) => void;  
}  
  
interface Window {  
  GrapeCity: GrapeCity;  
}  
  
declare let window: Window;  
  
// 追加するプロパティ  
export interface IViewerProps {  
  Server_Url?: string | null;  
  Reports_ID?: string | null;  
  Reports_Loading?: boolean | false;  
  Reports_Parameter?: string | null;  
  Style_Width?: string;  
  Style_Height?: string;  
}  
  
export class Viewer extends React.Component<IViewerProps> {  
  viewer: ViewerInstance | null = null;  
  
  constructor(props: IViewerProps) {  
    super(props);  
  }  
  
  componentDidMount() {  
    let _reportParameters: Array<{ name: string; values: string[] }> = [];  
    if (window.GrapeCity && window.GrapeCity.ActiveReports) {  

      if (this.props.Reports_Parameter) {  
        try {  
          _reportParameters = [JSON.parse(this.props.Reports_Parameter)];  
        } catch (error) {  
          console.error("Failed to parse Reports_Parameter:", error);  
        }  
      }  

      this.viewer = window.GrapeCity.ActiveReports.JSViewer.create({  
        element: '#viewer-host',  
        reportService: {  
          url: (this.props.Server_Url ?? '') + 'api/reporting',  
        },  
      });  

      if (this.props.Reports_Loading) { 
        this.viewer.openReport(this.props.Reports_ID ?? null, _reportParameters );  
      }
    }  
  }  
  
  componentDidUpdate() {  
    let _reportParameters: Array<{ name: string; values: string[] }> = [];  
    if (this.props.Reports_Parameter) {  
      try {  
        _reportParameters = [JSON.parse(this.props.Reports_Parameter)];  
      } catch (error) {  
        console.error("Failed to parse Reports_Parameter:", error);  
      }  
    }  

    if (this.viewer && this.props.Reports_Loading) {  
      this.viewer.openReport(this.props.Reports_ID ?? null, _reportParameters);  
    }  
  }  
  
  render() {  
    const viewerStyle = {  
      width: this.props.Style_Width || '100%',  
      height: this.props.Style_Height || '100vh'  
    };  
  
        
  
    return (  
      <div>  
        <div id="viewer-host" style={viewerStyle} />  
      </div>  
    );  
  }  
}  

index.tsファイルの更新

import { IInputs, IOutputs } from "./generated/ManifestTypes";
import { Viewer, IViewerProps } from "./App";  
import * as React from "react";
import "@mescius/activereportsnet-viewer-ja/dist/jsViewer.min.js";

export class ARdotNetViewer implements ComponentFramework.ReactControl<IInputs, IOutputs> {
    private theComponent: ComponentFramework.ReactControl<IInputs, IOutputs>;
    private notifyOutputChanged: () => void;
    private props: IViewerProps = { Server_Url: 'http://example.com/', Reports_ID: 'Invoice.rdlx', Reports_Loading:false, Reports_Parameter:null, Style_Width: '100%', Style_Height: '100vh' };  

    /**
     * 空のコンストラクタ。
     */
    constructor() { }

    /**
     * コントロールのインスタンスを初期化するために使用されます。ここでリモートサーバー呼び出しや他の初期化アクションを開始できます。
     * データセットの値はここでは初期化されません。updateViewを使用してください。
     * @param context コンテキストオブジェクトを介して制御できるプロパティバッグ全体。これは、マニフェストで定義されたプロパティ名にマッピングされたカスタマイザによって設定された値やユーティリティ関数を含みます。
     * @param notifyOutputChanged コントロールに新しい出力が非同期で取得可能であることをフレームワークに通知するコールバックメソッド。
     * @param state 単一ユーザーの1つのセッション内で持続するデータ。Modeインターフェイスで 'setControlState' を呼び出すことにより、コントロールのライフサイクルの任意の時点で設定できます。
     */
    public init(
        context: ComponentFramework.Context<IInputs>,
        notifyOutputChanged: () => void,
        state: ComponentFramework.Dictionary
    ): void {
        this.notifyOutputChanged = notifyOutputChanged;
        this.props.Server_Url = context.parameters.Server_Url.raw || 'http://example.com/';  
        this.props.Reports_ID = context.parameters.Reports_ID.raw || 'Invoice.rdlx';  
        this.props.Reports_Loading = context.parameters.Reports_Loading.raw.valueOf() || false;  
        this.props.Reports_Parameter = context.parameters.Reports_Parameter.raw || null;  
        this.props.Style_Width = context.parameters.Style_Width?.raw || '100%';  
        this.props.Style_Height = context.parameters.Style_Height?.raw || '100vh';  
    }

    /**
     * プロパティバッグ内の任意の値が変更されたときに呼び出されます。これには、フィールド値、データセット、コンテナの高さや幅などのグローバル値、オフラインステータス、ラベル、可視性などのコントロールメタデータ値が含まれます。
     * @param context コンテキストオブジェクトを介して制御できるプロパティバッグ全体。これは、マニフェストで定義された名前にマッピングされたカスタマイザによって設定された値やユーティリティ関数を含みます。
     * @returns ReactElement コントロールのルートReact要素を返します。
     */
    public updateView(context: ComponentFramework.Context<IInputs>): React.ReactElement {
        this.props.Server_Url = context.parameters.Server_Url.raw || 'http://example.com/';  
        this.props.Reports_ID = context.parameters.Reports_ID.raw || 'Invoice.rdlx';  
        this.props.Reports_Loading = context.parameters.Reports_Loading.raw.valueOf() || false;  
        this.props.Reports_Parameter = context.parameters.Reports_Parameter.raw || null;  
        this.props.Style_Width = context.parameters.Style_Width?.raw || '100%';  
        this.props.Style_Height = context.parameters.Style_Height?.raw || '100vh';  
    
        return React.createElement(
            Viewer, this.props
        );
    }

    /**
     * コントロールが新しいデータを受け取る前に、フレームワークによって呼び出されます。
     * @returns マニフェストで定義された命名法に基づくオブジェクトを返します。「bound」または「output」とマークされたプロパティに対するオブジェクトを期待します。
     */
    public getOutputs(): IOutputs {
        return { };
    }

    /**
     * コントロールがDOMツリーから削除されるときに呼び出されます。コントロールはこの呼び出しを使用してクリーンアップを行うべきです。
     * 例: 保留中のリモート呼び出しのキャンセル、リスナーの削除など。
     */
    public destroy(): void {
        // 必要に応じてコントロールをクリーンアップするコードを追加
    }
}

ソースコードの修正が終わったら、ビルド後、パッケージ化しPower Apps環境へアップロードしてください。
※ コードコンポーネントが同一の場合、コードコンポーネントのバージョンを上げてもキャンバスアプリに追加できないことがあります。その場合は、別名のコードコンポーネントを作成のうえ再度アップロードしてご利用ください。

キャンバスアプリ上に画面を追加

Power Appsからのデータを帳票に利用する準備が整いましたので、作成中のキャンバスアプリの画面を追加して、Power Appsからのデータを渡した帳票アプリを作成します。

この画面では次のような機能を実装することで、Power Appsのデータをビューワコンポーネントを介し、サーバーへ渡し、サーバーで作成された帳票をビューワへ表示します。

  1. 画面表示時にデータを読みこむ
  2. データを、表形式に配置したテキスト入力コンポーネントへ設定
  3. 印刷アイコンを押し、テキスト入力の値をコンテキスト変数「setValue」へレポートパラメータへ渡せる形式として保存
  4. テキスト入力「Screen2JSonTextInput」の初期値を「setValue」とする
  5. 「ActiveReportsビューワコードコンポネント」の「Reports_Parameter」プロパティの設定値を「Screen2JSonTextInput.Text」として、パラメータ値を設定
  6. Screen2Toggle1.Valueの状態によって、ビューワのロードが始まる

ビューワ上に帳票表示後、印刷やPDFが可能となります。

それでは、実際に以下のように画面レイアウトを構成しアプリケーションを作成していきます。

画面追加

まず画面「Screen2」を追加します。画面の表示時に請求書のデータが利用できるように、OnVisibleプロパティに「invoice」というJSON形式の埋込データを設定します。

データ設定
OnVisibleプロパティの設定
プロパティ設定値
OnVisibleClearCollect(invoice,{companyname:”テスト企業1”,no:”DB-00001″,sku:”7948352″,name:”モッツァレッラチーズとトマトのサラダ”,unit:”120″,price:”1200″,remark:”前菜”},{companyname:”テスト企業1”,no:”DB-00001″,sku:”1797382″,name:”ナポリ風スパゲティー”,unit:”60″,price:”2500″,remark:”パスタ”},{companyname:”テスト企業1”,no:”DB-00001″,sku:”9963274″,name:”小羊背肉のリンゴソースかけ”,unit:”130″,price:”5000″,remark:”メイン”},{companyname:”テスト企業2”,no:”DB-00002″,sku:”8398400″,name:”超極厚牛タン”,unit:”130″,price:”4800″,remark:”肉”},{companyname:”テスト企業2”,no:”DB-00002″,sku:”7079356″,name:”濃厚ずんだロール”,unit:”20″,price:”780″,remark:”デザート”},{companyname:”テスト企業2”,no:”DB-00002″,sku:”6407829″,name:”ハチミツパンケーキ”,unit:”120″,price:”1300″,remark:”お持ち帰り”},{companyname:”テスト企業3”,no:”DB-00003″,sku:”7627259″,name:”マスクメロン”,unit:”90″,price:”1100″,remark:”フルーツ”},{companyname:”テスト企業3”,no:”DB-00003″,sku:”8238079″,name:”ラ・フランス”,unit:”150″,price:”700″,remark:”フルーツ”});

その他の項目のプロパティ設定は以下を参考に設定してください。

「ラベル:Screen2Titlelabel」コンポーネントのプロパティ設定
プロパティ設定値
コンポーネント名Screen2Titlelabel
Height82
Width1027
X0
Y0
ColorRGBA(255, 255, 255, 1)
PaddingLeft50
FontWeightSemibold
Size36
Text“Power Apps data for Reports DataSource”
「切替:Screen2Toggle1」コンポーネントのプロパティ設定
プロパティ設定値
コンポーネント名Screen2Toggle1
Height56
Width160
X1083
Y17
「四角形:Screen2TitleRectangle1」コンポーネントのプロパティ設定
プロパティ設定値
コンポーネント名Screen2TitleRectangle1
Height82
WidthParent.Width
X0
Y0
FillRGBA(100, 118, 132, 1)
「アイコン:Screen2PrintIcon」コンポーネントのプロパティ設定
プロパティ設定値
コンポーネント名Screen2PrintIcon
Height64
Width64
X1275
Y9
アイコンIcon.Print
OnSelectUpdateContext({setvalue:””});UpdateContext({setvalue:
“{” & “””” & “name” & “””” & “:” & “””” & “ReportParameter1” & “””” & “,” & “””” & “values” & “””” & “:[” & “””” & “[” & “{” & “¥” & “””” & “companyname” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec1_Col1.Text & “¥” & “””” & “,” & “¥” &”””” & “no” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec1_Col2.Text & “¥” & “””” & “,” & “¥” &”””” & “sku” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec1_Col3.Text & “¥” & “””” & “,” & “¥” &”””” & “name” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec1_Col4.Text & “¥” & “””” & “,” & “¥” & “””” & “unit” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec1_Col5.Text & “¥” & “””” & “,” & “¥” & “””” & “price” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec1_Col6.Text & “¥” & “””” & “,” & “¥” & “””” & “remark” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec1_Col7.Text & “¥” & “””” & “}” &
“,{” & “¥” & “””” & “companyname” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec2_Col1.Text & “¥” & “””” & “,” & “¥” &”””” & “no” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec2_Col2.Text & “¥” & “””” & “,” & “¥” &”””” & “sku” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec2_Col3.Text & “¥” & “””” & “,” & “¥” &”””” & “name” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec2_Col4.Text & “¥” & “””” & “,” & “¥” & “””” & “unit” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec2_Col5.Text & “¥” & “””” & “,” & “¥” & “””” & “price” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec2_Col6.Text & “¥” & “””” & “,” & “¥” & “””” & “remark” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec2_Col7.Text & “¥” & “””” & “}” &
“,{” & “¥” & “””” & “companyname” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec3_Col1.Text & “¥” & “””” & “,” & “¥” &”””” & “no” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec3_Col2.Text & “¥” & “””” & “,” & “¥” &”””” & “sku” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec3_Col3.Text & “¥” & “””” & “,” & “¥” &”””” & “name” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec3_Col4.Text & “¥” & “””” & “,” & “¥” & “””” & “unit” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec3_Col5.Text & “¥” & “””” & “,” & “¥” & “””” & “price” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec3_Col6.Text & “¥” & “””” & “,” & “¥” & “””” & “remark” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec3_Col7.Text & “¥” & “””” & “}” &
“,{” & “¥” & “””” & “companyname” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec4_Col1.Text & “¥” & “””” & “,” & “¥” &”””” & “no” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec4_Col2.Text & “¥” & “””” & “,” & “¥” &”””” & “sku” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec4_Col3.Text & “¥” & “””” & “,” & “¥” &”””” & “name” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec4_Col4.Text & “¥” & “””” & “,” & “¥” & “””” & “unit” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec4_Col5.Text & “¥” & “””” & “,” & “¥” & “””” & “price” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec4_Col6.Text & “¥” & “””” & “,” & “¥” & “””” & “remark” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec4_Col7.Text & “¥” & “””” & “}” &
“,{” & “¥” & “””” & “companyname” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec5_Col1.Text & “¥” & “””” & “,” & “¥” &”””” & “no” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec5_Col2.Text & “¥” & “””” & “,” & “¥” &”””” & “sku” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec5_Col3.Text & “¥” & “””” & “,” & “¥” &”””” & “name” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec5_Col4.Text & “¥” & “””” & “,” & “¥” & “””” & “unit” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec5_Col5.Text & “¥” & “””” & “,” & “¥” & “””” & “price” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec5_Col6.Text & “¥” & “””” & “,” & “¥” & “””” & “remark” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec5_Col7.Text & “¥” & “””” & “}” &
“,{” & “¥” & “””” & “companyname” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec6_Col1.Text & “¥” & “””” & “,” & “¥” &”””” & “no” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec6_Col2.Text & “¥” & “””” & “,” & “¥” &”””” & “sku” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec6_Col3.Text & “¥” & “””” & “,” & “¥” &”””” & “name” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec6_Col4.Text & “¥” & “””” & “,” & “¥” & “””” & “unit” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec6_Col5.Text & “¥” & “””” & “,” & “¥” & “””” & “price” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec6_Col6.Text & “¥” & “””” & “,” & “¥” & “””” & “remark” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec6_Col7.Text & “¥” & “””” & “}” &
“,{” & “¥” & “””” & “companyname” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec7_Col1.Text & “¥” & “””” & “,” & “¥” &”””” & “no” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec7_Col2.Text & “¥” & “””” & “,” & “¥” &”””” & “sku” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec7_Col3.Text & “¥” & “””” & “,” & “¥” &”””” & “name” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec7_Col4.Text & “¥” & “””” & “,” & “¥” & “””” & “unit” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec7_Col5.Text & “¥” & “””” & “,” & “¥” & “””” & “price” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec7_Col6.Text & “¥” & “””” & “,” & “¥” & “””” & “remark” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec7_Col6.Text & “¥” & “””” & “}” &
“,{” & “¥” & “””” & “companyname” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec8_Col7.Text & “¥” & “””” & “,” & “¥” &”””” & “no” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec8_Col6.Text & “¥” & “””” & “,” & “¥” &”””” & “sku” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec8_Col5.Text & “¥” & “””” & “,” & “¥” &”””” & “name” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec8_Col4.Text & “¥” & “””” & “,” & “¥” & “””” & “unit” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec8_Col3.Text & “¥” & “””” & “,” & “¥” & “””” & “price” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec8_Col2.Text & “¥” & “””” & “,” & “¥” & “””” & “remark” & “¥” & “””” & “:” & “¥” & “””” & Screen2TableRec8_Col1.Text & “¥” & “””” & “}”&”]” & “””” & “]” &”}”
});
「テキスト入力:Screen2JSonTextInput」コンポーネントのプロパティ設定
プロパティ設定値
コンポーネント名Screen2JSonTextInput
Height244
Width587
X14
Y500
Defaultsetvalue
「表形式のラベル、テキスト入力」コンポーネントのプロパティ設定
コンポーネントプロパティ設定値
ラベルコンポーネント名Screen2TableLabelCol(1~7)
Height40
WidthCol1:137,Col2:67,Col3:61,Col4:140,Col5:37,Col6:50,Col7:96
XCol1:14,Col2:151,Col3:218,Col4:279,Col5:419,Col6:455,Col7:505
Y106
FillRGBA(100, 118, 132, 1)
TextCol1:”会社名”,Col2:”伝票番号”,Col3:”商品番号”,Col4:”商品名”,Col5:”数量”,Col6:”単価”,Col7:”備考”
Size9
ColorRGBA(255, 255, 255, 1)
AlignCenter
VerticalAlignMiddle
BorderThickness1
BorderColorRGBA(32, 54, 71, 1)
テキスト入力コンポーネント名Screen2TableRec(1~8)_Col(1~7)
Height43
WidthScreen2TableLabelCol(1~7).Width
XScreen2TableLabelCol(1~7).X
YRec1_Col(1~7):145,Rec2_Col(1~7):188,Rec3_Col(1~7):231,Rec4_Col(1~7):274,Rec5_Col(1~7):317,Rec6_Col(1~7):360,Rec7_Col(1~7):403,Rec8_Col(1~7):445
DefaultRec(1~8)_Col1:Index(invoice,1~8).companyname
Rec(1~8)_Col2:Index(invoice,1~8).no
Rec(1~8)_Col3:Index(invoice,1~8).sku
Rec(1~8)_Col4:Index(invoice,1~8).name
Rec(1~8)_Col5:Index(invoice,1~8).unit
Rec(1~8)_Col6:Index(invoice,1~8).price
Rec(1~8)_Col7:Index(invoice,1~8).remark
Size9
ColorRGBA(255, 255, 255, 1)
AlignRec(1~8)_Col1:Left,Rec(1~8)_Col2:Left,Rec(1~8)_Col3:Right,Rec(1~8)_Col4:Left,Rec(1~8)_Col5:Right,Rec(1~8)_Col6:Right,Rec(1~8)_Col7:Left
BorderThickness1
BorderColorRGBA(32, 54, 71, 1)

画面上のコンポーネント配置、プロパティ設定が終わりましたら、最後に「ActiveReportsビューワコードコンポネント」の設定も行っていきます。以前の設定とほぼ同じですが、先ほど追加したプロパティ「Reports_Parameter」への設定と、「Reports_ID」にも新たに追加した帳票レイアウトを設定してきます。

プロパティ設定値
コンポーネント名ARdotNetParamViewer1
Height662
Width733
X623
Y82
Server_UrlARdotNetViewer1と同様
Reports_IDinvoiceparam.rdlx
Reports_LoadingScreen2Toggle1.Value
Reports_ParameterScreen2JSonTextInput.Text
Style_Height662px
Style_Width733px

動作確認

最後に動作確認を行います。次の動画のように、Power Apps上のデータが帳票のデータソースとして利用され、テキスト入力コンポーネントで編集した内容も即座に反映されていることが確認できます。

帳票機能機能

画面上で編集されたデータを即時に帳票へ反映

Power Appsでは、Microsoft Lists(SharePointリスト)やExcelデータをはじめ、様々なデータソースを利用することができます。そのため、これらのデータを用いてアプリケーションを作成している方も多いでしょう。こうした方々にとって、Power Apps上のデータを活用して簡単に帳票を作成できることは、大きなメリットとなるのではないでしょうか?

さいごに

今回の記事では、作成したコードコンポーネントをキャンバスアプリ上に配置して、実際にPower Apps上で帳票を開発する方法についてご紹介しました。

ご紹介してきた機能を活用することで、既存の帳票アプリケーションを簡単にローコードプラットフォームに移行することが可能になるほか、Power Appsのデータを活用した、新規の帳票の作成も可能です。

また、ActiveReports for .NETには、Web上で帳票の新規作成や変更などの帳票デザインが行えるJavaScriptコンポーネント「Webデザイナ」を提供しています。JSビューワ同様にコードコンポーネントとして作成することで、以下の動画のようにPower Apps上で、帳票レイアウトの新規作成や、既存のレイアウトの変更することも可能です。

これまでActiveReportsをお使いで、既存の帳票資産を活かしてシステム移行を検討中の方や、Power Apps上に高度な帳票機能を追加したいとお考えの方は、ぜひ今回ご紹介したPower AppsとActiveReports for .NETを組み合わせた帳票アプリケーションの開発方法を参考にしていただけると幸いです。

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

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

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