IM-PDFAutoConverter を利用したワークフロー画面のPDFをSharePointへアップロードする方法

このCookBookでは、IM-PDFAutoConverterを利用してワークフロー画面のPDFをSharePointへアップロードする方法について説明します。

注意
このCookBookの内容は、2025 Spring以降の環境で利用可能です。

注意
このサンプルでは最終承認をしたユーザのセッション情報を元に画面を表示してPDFを作成します。
そのため、PDF化処理が完了する前にログアウトなどを行ったことにより、セッションが切れてしまうとPDF化に失敗する可能性があります。

完成イメージ

このCookBookでは、以下の処理を行うことでワークフローの画面をPDF化し、SharePointへアップロードします。
1. 最終承認のタイミングのアクション処理でセッション情報を案件プロパティに格納します。
2. 格納したセッション情報などをパラメーターとして案件終了処理でジョブネットを実行します。
3. 実行されたジョブネットでは、まずIM-PDFAutoConverterを利用してワークフロー画面をPDFファイルにしてパブリックストレージに出力します。
4. 次に、IM-LogicDesignerを利用してパブリックストレージのPDFファイルをSharePointへアップロードします。

cookbook260401_01

完成サンプル

このCookBookの完成サンプルを含めたユーザモジュールを以下のリンクからダウンロードできます。
zipファイルを解凍いただくと、中に im_cookbook_260401-1.0.0.imm というユーザモジュールがございます。

サンプルユーザモジュール: cookbook260401.zip

注意
このサンプルを利用する場合、2025 Spring以降の環境が必要です。

サンプルの使い方

  1. 上記のzipファイルをダウンロードして解凍します。
  2. IM-Jugglingから上記ユーザモジュールを含めたプロジェクトを作成し、warファイルを作成します。
  3. 作成したwarファイルをデプロイして、システム管理画面からテナント環境セットアップを実施します。
  4. テナント管理者でログインし、「サイトマップ - テナント管理 - ジョブ管理 - ジョブ設定」でジョブ管理画面にアクセスします。
    1. 「im_cookbook_260401」カテゴリ内の「HTML→PDF変換 非同期 スクリプト開発モデル」の「編集」をクリックして「実行パラメータ」を編集します。
    2. baseUrl にベースURLを設定します(例: http://localhost:8080/imart
    3. 分散環境で利用している場合は isHtmlToPdfRemotetrue に設定します。
    4. 「更新」をクリックして、ジョブ設定を保存します。
  5. 「サイトマップ - LogicDesigner - フロー定義一覧」でロジックフロー定義一覧にアクセスします。
    1. 「im_cookbook_260401」カテゴリ内の「uploadSharePoint」の「編集」をクリックしてロジックフロー定義編集に遷移します。
    2. 「定数設定」からOffice365連携に必要な情報を設定します。
    3. providerIdsitePathを設定します。
      • providerId: Office365のプロバイダーIDを指定します。
      • sitePath: Office 365 SharePoint Online 上のサイトパスを指定します。トップサイトを指定する場合は入力の必要はありません。
        例えば、チームサイトが「https://yourcompany.sharepoint.com/sites/foo」の場合、サイトパスには “foo” でなく “sites/foo” を指定します。
    4. userCd には「Office 365 Files API」 の利用が許可されているユーザのユーザコードをしてください
    5. 「保存」をクリックして、ロジックフロー定義を保存します。
  6. PDFを出力したいワークフローの設定を行います。
    1. 「サイトマップ - ワークフロー - ワークフロー管理者 - マスタ定義 - コンテンツ定義」から、PDFを出力したいワークフローのコンテンツ定義を選択し、編集画面を開きます。
    2. 「ユーザプログラム」タブから「新規作成」をクリックして、アクション処理を登録します。
      • プログラム名: 任意
      • プラグイン種別: アクション処理
      • 対象ノード: 承認ノード
      • プラグイン種類: 【アクション処理】 スクリプト開発モデル
      • プラグイン設定値: im_cookbook_260401/pdfa/htmltopdf/async/SessionSaveActionProcess
      • 実行順番: 任意
    3. 「ユーザプログラム」タブから「新規作成」をクリックして、案件終了処理を登録します。
      • プログラム名: 任意
      • プラグイン種別: 案件終了処理
      • プラグイン種類: 【案件終了処理】 スクリプト開発モデル
      • プラグイン設定値: im_cookbook_260401/pdfa/htmltopdf/async/JobExecuteMatterEndProcess
      • 実行順番: 任意
  7. ワークフローを実行して案件終了時にSharePointにPDFがアップロードされるようになりました。

実装

ここからは詳細な実装について以下の順番で説明をします。
1. セッション情報を案件プロパティに格納するアクション処理の実装
2. IM-PDFAutoConverterを利用してワークフロー画面をPDFファイルにしてパブリックストレージに出力するジョブの実装
3. パブリックストレージのPDFファイルをSharePointへアップロードするロジックフローの実装
4. ジョブ・ジョブネットの実装
5. アクション処理で格納したセッション情報などをパラメーターとしてジョブネットを実行する案件終了処理の実装

アクション処理

セッション情報を案件プロパティに格納するアクション処理を実装します
IM-PDFAutoConverter for Accel Platform プログラミングガイド - チュートリアル - HTML→PDF変換 - 非同期処理 - スクリプト開発モデル」に記載されているチュートリアルのSessionSaveProcess.jsを元に作成します。

  1. このアクション処理ではセッションIDを案件プロパティに格納するため、格納先の案件プロパティを作成します。
    「サイトマップ - ワークフロー - ワークフロー管理者 - マスタ定義 - 案件プロパティ定義」から案件プロパティ一覧画面に遷移します。
    「新規作成」から対象となる案件プロパティ定義を登録します。

    • キー: 任意(以降ではim_260401_session_idで設定したものとして進めます)
    • キー名: 任意
    • : 文字列
  2. アクション処理プログラムを作成します。
    作成するファイルのパスは任意ですが、このCookBookではim_cookbook_260401/pdfa/htmltopdf/async/JobExecuteMatterEndProcess.jsに実装を行ったものとして説明をします。
function approve(parameter,userParameter) {
    var result = null;

    // セッションIDを取得
    var httpContextManager = new Packages.jp.co.intra_mart.common.aid.jsdk.javax.servlet.http.HTTPContextManager.getInstance();
    var httpContext = httpContextManager.getCurrentContext();
    var session = httpContext.getCurrentSession();
    var sessionId = session.getId();

    // 取得したセッションIDを基に、案件プロパティの配列を用意
    var matterProperty = [
        {
            "matterPropertyKey" : "im_260401_session_id",   // 登録する案件プロパティのキー
            "matterPropertyValue" : sessionId,
            "userDataId" : parameter.userDataId
        }
    ];

    // 案件プロパティの配列(セッションID)を、案件プロパティのDBに登録
    var actvMatterProperty = new UserActvMatterPropertyValue();
    result = actvMatterProperty.getMatterProperty(matterProperty[0].userDataId, matterProperty[0].matterPropertyKey);
    if (result.error) {
        return {
            "resultFlag" : false,
            "message" : result.errorMessage
        };
    }

    if(result.data === null) {
        // まだ登録されていない場合は新規登録
        result = actvMatterProperty.createMatterProperty(matterProperty);
        if (result.error) {
            return {
                "resultFlag" : false,
                "message" : result.errorMessage
            };
        }
    } else {
        // まだ登録されていない場合は更新
        result = actvMatterProperty.updateMatterProperty(matterProperty);
        if (result.error) {
            return {
                "resultFlag" : false,
                "message" : result.errorMessage
            };
        }
    }


    return {
        "resultFlag" : true
    };
}

PDF化ジョブ

「ベースURL」「システム案件ID」「ユーザデータID」「セッションID」「分散構成か否か」をパラメーターとして受け取り、パブリックストレージにPDFファイルを出力するジョブを実装します。
作成するファイルのパスは任意ですが、このCookBookではim_cookbook_260401/pdfa/htmltopdf/async/HtmlToPdfJob.jsに実装を行ったものとして説明をします。
IM-PDFAutoConverter for Accel Platform プログラミングガイド - チュートリアル - HTML→PDF変換 - 非同期処理 - スクリプト開発モデル」に記載されているチュートリアルのHtmlToPdfJob.jsを元に作成します。
チュートリアルの内容から変更を加えた点は以下です。

  • ジョブにパラメーターisHtmlToPdfRemoteを追加して、使用するAPIを切り替えるように対応
  • パブリックストレージに該当のディレクトリが存在しない場合は作成するように対応
/**
 * HTML→PDF変換処理を実行するジョブ
 */
function execute() {

    // 実行パラメータの取得
    var contexts = Contexts.getJobSchedulerContext();
    // ベースURL(http://<HOST>:<PORT>/<CONTEXT_PATH>)
    var baseUrl = contexts.getParameter("baseUrl");
    // システム案件ID
    var systemMatterId = contexts.getParameter("imwSystemMatterId");
    // ユーザデータID
    var userDataId = contexts.getParameter("imwUserDataId");
    // セッションID
    var sessionId = contexts.getParameter("sessionId");
    // 分散構成か(値が存在しない場合や不正な場合はスタンドアロンと判断)
    var isHtmlToPdfRemoteParam = contexts.getParameter("isHtmlToPdfRemote");
    var isHtmlToPdfRemote = isHtmlToPdfRemoteParam !== null ? isHtmlToPdfRemoteParam.toLowerCase() === "true" : false;

    // 一時ファイルを作成
    var prefix = "htmltopdf_";
    var suffix = ".pdf";
    var tempFile = File.createTempFile(prefix, suffix);

    try {
        // 出力先を設定
        var dirPath = "im_cookbook_260401/pdfa/htmltopdf/async";
        mkPublicStorageDir(dirPath);

        var outFileName = prefix + systemMatterId + suffix;
        var outFilePath = dirPath + "/" + outFileName;

        // PDF変換を実行
        var htmlToPdf = getHtmlToPdfInstance(isHtmlToPdfRemote);
        htmlToPdf.setWaitMillisecond(3000);
        htmlToPdf.convertWorkflowScreenWithSessionInfo(systemMatterId, userDataId, baseUrl, "JSESSIONID", sessionId, tempFile.path());

        // 変換したPDFファイルをパブリックストレージへコピー
        copyPublicStorage(tempFile, outFilePath);
    } catch (error) {
        return {
            status: 'error',
            message: error.message
        };
    } finally {
        if (tempFile.exist()) {
            tempFile.remove();
        }
    }

    return {
        status: 'success',
        message: 'ジョブが正常に実行されました。'
    };
}

/**
 * パブリックストレージへファイルをコピー
 * @param {File} tempFile コピー元ファイル
 * @param {String} outFilePath コピー先ファイルのパブリックストレージパス
 */
function copyPublicStorage(tempFile, outFilePath) {
    tempFile.openAsBinary(function (reader, error1) {
        if (error1 != null) {
            throw error1;
        }
        new PublicStorage(outFilePath).createAsBinary(function (writer, error2) {
            if (error2 != null) {
                throw error2;
            }
            if (!reader.transferTo(writer)) {
                throw new Error("ファイルのコピーに失敗しました。");
            }
        });
    });
}

/**
 * パブリックストレージにディレクトリが存在しない場合は作成する
 * @param {String} path 対象となるパス
 */
function mkPublicStorageDir(path) {
    var storage = new PublicStorage(path);
    if (storage.exists()) {
        return;
    }
    storage.makeDirectories();
}

/**
 * 対象となるHtmlToPdfのインスタンスを返却します
 * @param {boolean} isHtmlToPdfRemote 分散環境であるか
 */
function getHtmlToPdfInstance(isHtmlToPdfRemote) {
    return isHtmlToPdfRemote ? new HtmlToPdfRemote() : new HtmlToPdf();
}

SharePointアップロードロジックフロー

パブリックストレージに出力したPDFファイルをSharePointへアップロードするロジックフローを実装します。
フローの全体像は、以下のとおりです。
cookbook260401_02

入力値の設定

このロジックフローは入力値でシステム案件IDを受け取るため、「入出力設定」から、図のように入力値の設定をします。

  • 入力 - imwSystemMatterId(文字列)
    cookbook260401_03
定数の設定

フロー内で使用する定数を「定数設定」から設定します。

定数ID 定数値 説明
/ / パスの区切り文字に使用する文字列です
dirPath im_cookbook_260401/pdfa/htmltopdf/async PDFファイルを出力したパブリックストレージのパスです。HtmlToPdfJob.jsで指定したものと同じ値を指定します。
prefix htmltopdf_ PDFファイルのプレフィックスです。HtmlToPdfJob.jsで指定したものと同じ値を指定します。
providerId [Office365のプロバイダーID] Office365のプロバイダーIDを指定します。
sitePath [サイトパス] Office 365 SharePoint Online 上のサイトパスを指定します。トップサイトを指定する場合は入力の必要はありません。
例えば、チームサイトが「https://yourcompany.sharepoint.com/sites/foo」の場合、サイトパスには “foo” でなく “sites/foo” を指定します。
suffix .pdf PDFファイルの拡張子です
userCd [「Office 365 Files API」 の利用が許可されているユーザのユーザコード] IM-BIS for Accel Platform Office365 for IM-BIS 連携ガイド - BISシステムユーザと Office 365 ユーザ を連携する」を対応済みである場合は、BISシステムユーザのユーザコード(BIS)と入力してください。

cookbook260401_04

パブリックストレージに配置したPDFファイルの取得

HtmlToPdfJob.jsでパブリックストレージに出力したPDFファイルを取得する処理を実装します。

  • パレットの「ストレージ操作」から「パブリックストレージ取得」を配置します
  • 図のようにマッピングします。この時タスクに渡している値はパブリックストレージ内のPDFファイルのパスです。
    cookbook260401_05
  • 次にパレットの「ストレージ操作」から「ストレージファイル読み込み(バイナリ)」を配置します。
  • 図のようにマッピングします。
  • cookbook260401_06
SharePointへのPDFファイルのアップロード

PDFファイルの情報をSharePointへのPDFファイルのアップロードする処理を実装します。

  • パレットの「Office365」から「SharePointストレージ取得」を配置します。
  • 図のようにマッピングします。pathにマッピングしている値は、SharePointに配置する際のパスです。
    このCookBookでは{システム案件ID}/{システム案件ID}.pdfに格納するようになっています。
    cookbook260401_07
  • 次にパレットの「ストレージ操作」から「ストレージ出力(バイナリ)」を配置します。
  • 図のようにマッピングします。
    cookbook260401_08
タスクのマッピング・保存
  1. フローの全体像の通りにタスクをマッピングします。
    cookbook260401_02
  2. 「新規保存」をクリックして「フロー定義ID」「フロー定義名」「フローカテゴリ」に任意の値を入力してフローを保存します。
    • ここでは「フロー定義ID」にimCookbook260401_uploadSharePointにしたものとして説明をします。

ジョブ・ジョブネット

ここまでに作成したHtmlToPdfJob.jsとロジックフローをジョブネットで実行できるように登録していきます。

HtmlToPdfJob.jsを実行するジョブの作成
  1. 「サイトマップ - テナント管理 - ジョブ管理 - ジョブ設定」でジョブ管理画面にアクセスします。
  2. 必要であれば「カテゴリ新規作成」から任意のカテゴリを作成します。
  3. 「ジョブ新規作成」をクリックします。
  4. 「基本情報」の「ジョブカテゴリ」「ジョブID」「ジョブ名」に任意の値を入力します。
    • このCookBookではジョブIDをim_cookbook_260401-jobにしたものとして説明をします。
  5. 「実行時の情報」の項目を以下のように設定します。
    • 実行言語: JavaScript
    • 実行プログラム: im_cookbook_260401/pdfa/htmltopdf/async/HtmlToPdfJob
      • 「PDF化ジョブ」のパスを指定します。
    • 実行パラメータ: 以下のように入力します。
      キー
      baseUrl ベースURLを記載します(例: http://localhost:8080/imart
      imwSystemMatterId 空欄
      imwUserDataId 空欄
      isHtmlToPdfRemote PDFAutoConverterを分散環境で利用している場合はtrue、スタンドアロン環境で使用している場合はfalseを指定します。
      sessionId 空欄
  6. 「新規作成」ボタンをクリックしてジョブを登録します。
ジョブネットの作成
  1. 「サイトマップ - テナント管理 - ジョブ管理 - ジョブネット設定」でジョブ管理画面にアクセスします。
  2. 必要であれば「カテゴリ新規作成」から任意のカテゴリを作成します。
  3. 「ジョブネット新規作成」をクリックします。
  4. 「基本情報」の「ジョブネットカテゴリ」「ジョブネットID」「ジョブネット名」に任意の値を入力します。
    • このCookBookではジョブネットIDをim_cookbook_260401-jobnetにしたものとして説明をします。
  5. 「実行時の情報」の項目を以下のように設定します。
    • 実行ジョブ: 「ジョブを追加」から以下の2つのジョブをこの順序で選択します。
      • 先ほど作成したジョブ(im_cookbook_260401-job)
      • カテゴリIM-LogicDesigner内のフロー実行ジョブ
    • 実行パラメータ: 以下のように入力します。
      キー
      flow_id imCookbook260401_uploadSharePoint
      (先ほど作成したロジックフローのフローID)
      imwSystemMatterId 空欄
      imwUserDataId 空欄
      sessionId 空欄
  6. 「新規作成」ボタンをクリックしてジョブネットを登録します。

案件終了処理

上記のジョブネットを実行する案件終了処理を実装します。
案件プロパティからセッション情報を取得、案件終了処理のパラメータからシステム案件IDとユーザデータIDを取得して、それをジョブネットのパラメータとして実行します。
作成するファイルのパスは任意ですが、このCookBookではim_cookbook_260401/pdfa/htmltopdf/async/JobExecuteMatterEndProcess.jsに実装を行ったものとして説明をします。
IM-PDFAutoConverter for Accel Platform プログラミングガイド - チュートリアル - HTML→PDF変換 - 非同期処理 - スクリプト開発モデル」に記載されているチュートリアルのJobExecuteProcess.jsを元に作成します。

/**
 * HTML→PDF変換処理のジョブを実行する
 * 「終了ノードの到達処理」、または、「案件終了処理」で当該処理を実行する
 * @param {Object} parameter パラメータ
 */
function execute(parameter) {
    var result = null;
    // ジョブネットID
    var jobnetId = "im_cookbook_260401-jobnet";

    // 案件プロパティにて保持していたセッションIDを取得
    let sessionId = "";
    var actvMatterProperty = new UserActvMatterPropertyValue();
    if (actvMatterProperty != null) {
        result = actvMatterProperty.getMatterProperty(parameter.userDataId, "im_260401_session_id");
        if (result.data != null) {
            sessionId = result.data.matterPropertyValue;
        }
    }

    // ジョブネット情報を取得
    var jobManager = new JobSchedulerManager();
    result = jobManager.findJobnet(jobnetId);
    if (result.error) {
        return {
            "resultFlag" : false,
            "message" : result.errorMessage
        }
    }

    // ジョブネットの実行パラメータをセット
    var jobnetDetail = result.data;
    // セッションID
    jobnetDetail.parameters.sessionId = sessionId;
    // システム案件ID
    jobnetDetail.parameters.imwSystemMatterId = parameter.systemMatterId;
    // ユーザデータID
    jobnetDetail.parameters.imwUserDataId = parameter.userDataId;

    // ジョブネット情報を更新
    result = jobManager.updateJobnet(jobnetDetail);
    if (result.error) {
        return {
            "resultFlag" : false,
            "message": result.errorMessage,
            "data" : false
        }
    }

    // ジョブネットの即時実行
    result = jobManager.execute(jobnetId);
    if (result.error) {
        return {
            "resultFlag" : false,
            "message": result.errorMessage,
            "data" : false
        }
    }

    return {
        "resultFlag": true,
        "data" : false
    }
}

ワークフロー

作成したアクション処理と案件終了処理を対象のワークフローのコンテンツ定義に登録します。

  1. 「サイトマップ - ワークフロー - ワークフロー管理者 - マスタ定義 - コンテンツ定義」から、PDFを出力したいワークフローのコンテンツ定義を選択し、編集画面を開きます。
  2. 「ユーザプログラム」タブから「新規作成」をクリックして、アクション処理を登録します。
    • プログラム名: 任意
    • プラグイン種別: アクション処理
    • 対象ノード: 承認ノード
    • プラグイン種類: 【アクション処理】 スクリプト開発モデル
    • プラグイン設定値: im_cookbook_260401/pdfa/htmltopdf/async/SessionSaveActionProcess
    • 実行順番: 任意
  3. 「ユーザプログラム」タブから「新規作成」をクリックして、案件終了処理を登録します。
    • プログラム名: 任意
    • プラグイン種別: 案件終了処理
    • プラグイン種類: 【案件終了処理】 スクリプト開発モデル
    • プラグイン設定値: im_cookbook_260401/pdfa/htmltopdf/async/JobExecuteMatterEndProcess
    • 実行順番: 任意