スクリプト工程をフロー図の途中に配置すれば、データ編集の自動化を実現できます。例えば "出勤時刻" と "帰宅時刻" から勤務時間を算出するといった演算処理や、 "作業実施日" の曜日情報を自動的に付加するといった文字列編集処理を自動化する事ができます。([データ更新] より更に複雑な処理が可能です)
1. スクリプトタスクの活用シーンについて、概要を理解する
- 1. データ代入
- ECMA スクリプトで生成した日付や数値などを自動的に代入させる
- 2. データ加工
- 入力済みの数値や文字列を加工し、新たなデータとして代入する
- "ECMA スクリプト"とは、JavaScript と JScript の共通部分をベースに標準化されたスクリプト言語です
2. スクリプトタスクで利用できる関数について、概要を理解する
- a. 利用可能な JavaScript
- "ECMAScript 2022" に規定された多くの関数
- b. 利用可能な Java クラス
- 業務データの参照更新を行う Java クラス関数、他
- JavaScript と Java の基礎的な知識が必要になります
R2300: スクリプトタスクで利用できる Java クラス
3. スクリプトタスクを設定する
- 1. ECMA コードを登録する
- データ参照、データ加工、データ代入などの処理コードを記入します
- 2. スクリプトエンジンを選択する
- 特段の理由がない限り「GraalJS」を選択します
- 業務データの代入や更新は、スクリプト処理完了後に一括して行われます
- エラー発生時には代入更新は行われません(次の処理に進みます)
- エラー発生時に処理が進む先を正常終了時と分けることもできます(エラー境界イベント)
- スクリプトの処理時間は最長で30秒に制限されます (負荷状況により若干変動します)
- HTTPリクエストは1自動処理工程につき10回に制限されます
- スクリプトエンジン GraalJS (Nashorn Compatible Mode) 廃止のお知らせ(2024年4月)
//// == Data Retrieving == var dataA = engine.findDataByNumber("0") + ""; // 業務データ0を参照 var dataB = engine.findDataByName("Data B") + ""; // 「Data B」という項目名の業務データを参照 // convert java.lang.String → javascript string //// == Calculating == var newData = dataA + dataB; //// == Data Updating == engine.setDataByNumber("3", newData ); //業務データ代入
R2301: Scriptデータ取得/代入
R2252: OAuth トークン取得手順
BPMNアイコン:スクリプトタスク
X. 業務アプリ
- PayPal請求プロセス
- 顧客マスタ同期プロセス
- 回答作成プロセス
- 資料請求対応フロー
- 翻訳プロセス
- 外部 API を利用したデータ取得
- 問合対応プロセス
- 請求書発行フロー
- 社員個人情報の申請受付
- 上司評価の投票
- 共有パスワード問合
Z. 追加情報: スクリプト実行エンジン
- a. GraalJS エンジン
- [スクリプト工程]は、スクリプト実行エンジン "GraalJS" によって処理されます。(サーバーサイド)
- b. GraalJS の特徴
- ワークフローアプリ設計者は "ECMAScript" (JavaScript) による自動処理スクリプトだけでなく "Java メソッド" による自動処理スクリプトも設定できます(Scripting Java)。たとえば
new java.lang.String("kyoto")
のような書式でオブジェクトを生成すれば、replaceFirst()
といった Java String クラスのメソッドが使用できるようになります。 - c. ワークフローに流れるデータの参照
- "請求日" や "見積額" といった業務データを参照するには、特別なメソッド
engine.findDataByNumber("♦項目ID♦")
を利用します。Java インスタンスとして呼び出されるため JavaScript string として扱いたい場合はvar text = engine.findDataByNumber("♦項目ID♦") + "";
などの明示的な型変換が推奨されます。 - d. ワークフローに流れるデータの更新
- スクリプト工程にて演算された値を、ワークフローに流れる業務データとして代入するには、特殊なメソッド
engine.setDataByNumber("♦項目ID♦","♦新しい値♦")
を利用します。(ECMA/JavaScript には数値に関する型が "number型" しか存在しないため、スクリプト内で演算された結果をワークフロー側に戻す際に "java.math.BigDecimal" を明示的に記述する必要があります) - e. 業務に役立つ関数およびサンプルコード
- number Math.random(); // 乱数 (0.00 to 0.99)
//////// == 演算 / Calculating == var myrand = Math.floor( Math.random() * 5 ) ; // 0 or 1 or 2 or 3 or 4 //// == ワークフローデータへの代入 / Updating == engine.setDataByNumber("♦DataDefID♦", new java.math.BigDecimal(myrand) );
number dateObj.getTime(); // 経過ミリ秒 (1970年1月1日 UTC 0時から)//// == ワークフローデータの参照 / Retrieving == var timestart = engine.findDataByNumber("♦DataDefID♦"); // 日時型:プロセス開始時刻 var timesent = engine.findDataByNumber("♦DataDefID♦"); // 日時型:回答メール送信時刻 //// == 演算 / Calculating == var conciergesec = timesent.getTime() - timestart.getTime(); var conciergehour = new java.math.BigDecimal( Math.floor( conciergesec / (1000 * 60 * 60) )); // Math.floor 切り捨て //// == ワークフローデータへの代入 / Updating == engine.setDataByNumber("♦DataDefID♦",conciergehour); var daystart = timestart.getDay(); // 問い合わせ発生曜日のメモ if (daystart == 0) engine.setDataByNumber("♦DataDefID♦","日曜日"); if (daystart == 1) engine.setDataByNumber("♦DataDefID♦","月曜日"); if (daystart == 2) engine.setDataByNumber("♦DataDefID♦","火曜日"); if (daystart == 3) engine.setDataByNumber("♦DataDefID♦","水曜日"); if (daystart == 4) engine.setDataByNumber("♦DataDefID♦","木曜日"); if (daystart == 5) engine.setDataByNumber("♦DataDefID♦","金曜日"); if (daystart == 6) engine.setDataByNumber("♦DataDefID♦","土曜日");
//// == ワークフローデータの参照 / Retrieving == var ym = engine.findDataByNumber("♦DataDefID♦"); //日付型(年月) //// == 演算 / Calculating == var date = new com.questetra.bpms.util.AddableDate(ym.getTime()); //年月 -> 年月日 date = date.getFirstDateInMonth().addDays(24); //指定年月の25日 //// == ワークフローデータへの代入 / Updating == engine.setDataByNumber("♦DataDefID♦", date);
string stringObj.charAt(number intindex); // N文字目(一番左が0文字目)//// == ワークフローデータの参照 / Retrieving == var mynumber = engine.findDataByNumber("♦DataDefID♦") + ""; //// == 演算 / Calculating == if( mynumber.length == 13 ){ var mysum = 0; for( i=1; i<13; i++){ mysum += parseInt( mynumber.charAt(i) ) * (i % 2 + 1); } var checkdigitnum = 9 - mysum % 9; var typedcd = parseInt( mynumber.charAt(0) ); //// == ワークフローデータへの代入 / Updating == if( typedcd == checkdigitnum ){ engine.setDataByNumber("♦DataDefID♦", "OK" ); } else { engine.setDataByNumber("♦DataDefID♦", "ERROR" ); } }
string JSON.parse(String text); // JSON からのデータ抽出//// == ワークフローデータの参照 / Retrieving == var weatherjson = JSON.parse(engine.findDataByNumber("♦DataDefID♦")); // 中間イベント等で取得済の想定 //// == 演算 / Calculating == var mydesc = weatherjson.list[0].weather[0].description; var mytemp = new java.math.BigDecimal(weatherjson.list[0].temp.max - 273.15); //// == ワークフローデータへの代入 / Updating == engine.setDataByNumber("♦DataDefID♦", mydesc ); engine.setDataByNumber("♦DataDefID♦", mytemp );
string stringObj.replace(string regexp_or_patternstr, string newsubstr); // 文字列の置換(正規表現)//// == ワークフローデータの参照 / Retrieving == var fromaddr = engine.findDataByNumber("♦DataDefID♦") + ""; var inq = engine.findDataByNumber("♦DataDefID♦") + ""; //// == 演算 / Calculating == var inquirywithmark = inq.replace(/(^.*$)/gm, "> "+"$1"); // 行頭リダイレクトマーク //// == ワークフローデータへの代入 / Updating == engine.setDataByNumber("♦DataDefID♦", fromaddr + '\n' + inquirywithmark );
string[] StringObj.split(String regex_or_separator) // 文字列の分割//////// == ワークフローデータの参照 / Retrieving == var csv_text = engine.findDataByNumber("♦DataDefID♦"); // 文字列型複数行のCSVデータ(4列)を前提 // ex) // Nakagyo-ku, Kyoto-shi, Kyoto-pref, Japan // Malibu, Los Angeles County, California, USA //// == 演算 / Calculating == var csvObj = new String( csv_text ); // String オブジェクト (JavaScript) var tmpTable = new com.questetra.bpms.core.model.formdata.ListArray(); // テーブル型データ var lineArray = csvObj.split("\n"); // 改行毎に分割し String[] 配列に格納 for (var i=0; i < lineArray.length; i++){ var tmpRow = new com.questetra.bpms.core.model.formdata.ListArray.ListRow(); // 追加行(横列) var cellstrArray = lineArray[i].split(","); // カンマ毎に分割し格納 tmpRow.addCol( cellstrArray[0] ); tmpRow.addCol( cellstrArray[1] ); tmpRow.addCol( cellstrArray[2] ); tmpRow.addCol( cellstrArray[3] ); tmpTable.addRow( tmpRow ); // 行追加 } //// == ワークフローデータへの代入 / Updating == engine.setDataByNumber("♦DataDefID♦", tmpTable );
String ListArrayObj.get(int row, int col); // テーブル型データ内の文字列//// == ワークフローデータの参照 / Retrieving == // mytable: com.questetra.bpms.core.model.formdata.ListArray var mytable = engine.findDataByNumber("♦DataDefID♦"); // テーブル型データを取得 //// == 演算 / Calculating == var i=0; var n = mytable.size(); var texttsv = ""; for (i=0; i < n; i++){ texttsv += mytable.get(i, 0) + "\t"; texttsv += mytable.get(i, 1) + "\t"; texttsv += mytable.get(i, 3) + "\t"; texttsv += mytable.get(i, 4) + "\n"; } //// == ワークフローデータへの代入 / Updating == engine.setDataByNumber("♦DataDefID♦", texttsv );
QuserView quserDao.findByEmail(string email); // BPMS ユーザの検索//// == ワークフローデータの参照 / Retrieving == var quserEmail = engine.findDataByNumber("♦DataDefID♦") + ""; // 文字列データに "example@example.net" が格納されている前提 //// == 演算 / Calculating == // com.questetra.bpms.core.event.scripttask.QuserDaoWrapper var quser = quserDao.findByEmail(quserEmail); //// == ワークフローデータへの代入 / Updating == engine.setDataByNumber("♦DataDefID♦", quser);
List<ItemView> itemDao.findAll(String fileName, boolean isSharedFile); // 選択肢Options内の文字列//// == ワークフローデータの参照 / Retrieving == optionsList = itemDao.findAll("value-display-list.xml", true); // M319 Options-XML //// == 演算 / Calculating == optionsNum = optionsList.size(); var value_id_list = ""; var display_label_list = ""; for (i=0; i < optionsNum; i++){ value_id_list += optionsList.get(i).getValue() + "\n"; display_label_list += optionsList.get(i).getDisplay() + "\n"; } //// == ワークフローデータへの代入 / Updating == engine.setDataByNumber("♦DataDefID♦", value_id_list); engine.setDataByNumber("♦DataDefID♦", display_label_list);
List<ItemView> itemDao.findAll(String fileName, boolean isSharedFile); // 選択肢Optionsをテーブル型データに代入//// == ワークフローデータの参照 / Retrieving == optionsList = itemDao.findAll("value-display-list.xml", true); // M319 Options-XML //// == 演算 / Calculating == var tmpTable = new com.questetra.bpms.core.model.formdata.ListArray(); // テーブル型データ optionsNum = optionsList.size(); for (i=0; i < optionsNum; i++){ var tmpRow = new com.questetra.bpms.core.model.formdata.ListArray.ListRow(); // 追加行(横列) tmpRow.addCol( optionsList.get(i).getValue() ); tmpRow.addCol( optionsList.get(i).getDisplay() ); tmpTable.addRow( tmpRow ); // 行追加 } //// == ワークフローデータへの代入 / Updating == engine.setDataByNumber("♦DataDefID♦", tmpTable );
コメント
0件のコメント
サインインしてコメントを残してください。