Email-HTML 文字列, 案件データリスト 生成 (Email-HTML String, Create DataitemList)
格納データが一覧できるHTMLコード(HTMLメール用)を生成します。ワークフロー内の指定データ項目を指定の順序で組み立てます。生成コードをメール送信イベントに渡せば、任意の関係者とデータを共有できます。
Configs
- A: 各行にフィールド名をセットしてください (例 “q_corp_name” ) *#{EL}
- B: ノート文をセットしてください (改行はbrに自動変換)#{EL}
- C: 案件リンクをフッタ表示させたい場合、基盤URLをセットしてください (${var[applicationRoot]})#{EL}
- D: Email-HTML が格納される文字列型データ項目を選択してください (更新) *
Script (click to open)
// GraalJS Script (engine type: 2)
//////// START "main()" /////////////////////////////////////////////////////////////////
main();
function main(){
//// == Config Retrieving / 工程コンフィグの参照 ==
const strFieldNames = configs.get( "StrConfA" ); /// REQUIRED
if( strFieldNames === "" ){
throw new Error( "\n AutomatedTask ConfigError:" +
" Config {A: FieldNames} is empty \n" );
}
let strAbstract = configs.get( "StrConfB" ); // NotRequired
strAbstract = encodeHTML( strAbstract ).replace(/\n/g, '<br>\n');
if( strAbstract === "" ){
engine.log( " AutomatedTask ConfigWarning: " +
" {B: Note} is empty" );
}
let strApplicationRoot = configs.get( "StrConfC" ); // NotRequired
const strPocketHtml = configs.getObject( "SelectConfD" ); /// REQUIRED
//// == Data Retrieving / ワークフローデータの参照 ==
// (Nothing. Retrieved via Expression Language in Config Retrieving)
//// == Calculating / 演算 ==
/// Build HTML String
let strBlockHeader = `<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dataitem List</title>
</head>
<body bgcolor="#ffffff" style="background-color:#ffffff; margin:0 auto; padding:0; width:100%">
`;
// for Note
let strBlockAbstract = '<div style="margin:0 auto 30px 0px; padding:10px;';
strBlockAbstract += ' display:inline-block; border:medium solid #009900; background-color:#ffffff">\n';
strBlockAbstract += ' ' + strAbstract + '\n';
strBlockAbstract += '</div>\n';
// for Dataitems
let strBlockDataitems = '<div style="margin:0; padding:5px; background-color:#eeeeee">\n'; // start BlockDataitems
const arrFieldNames = strFieldNames.split("\n");
for( let i = 0; i < arrFieldNames.length; i++ ){
let qPocket = engine.findDataDefinitionByVarName( arrFieldNames[i] );
if( qPocket.matchDataType( "STRING_TEXTFIELD" ) ){
strBlockDataitems += ' <span style="font-weight:bolder; color:#009900">' + qPocket.getName();
strBlockDataitems += '</span> <span style="color:#aaaaaa; font-size: x-small; padding:2px 5px">Singleline String</span>\n';
strBlockDataitems += ' <div style="padding-left:30px">\n'; // 30px indent
let qString = engine.findData( qPocket );
if( qString === null ){
strBlockDataitems += ' <span style="font-style:italic; color:#aaaaaa">null</span>';
}else{
qString = encodeHTML( qString );
qString = qString.replace(/\t/g, ' ');
qString = convertMultiSpaces( qString );
strBlockDataitems += ' <p style="display:inline-block; margin:0; padding:2px 10px; background:#ffffff">' + qString + '</p>\n';
}
strBlockDataitems += ' </div>\n'; // Indent end
}else if( qPocket.matchDataType( "STRING_TEXTAREA" ) ){
strBlockDataitems += ' <span style="font-weight:bolder; color:#009900">' + qPocket.getName();
strBlockDataitems += '</span> <span style="color:#aaaaaa; font-size: x-small; padding:2px 5px">Multiline String</span>\n';
strBlockDataitems += ' <div style="padding-left:30px">\n'; // 30px indent
let qString = engine.findData( qPocket );
if( qString === null ){
strBlockDataitems += ' <span style="font-style:italic; color:#aaaaaa">null</span>';
}else{
qString = encodeHTML( qString );
qString = qString.replace(/\t/g, ' ');
qString = qString.replace(/\n/g, '<br>\n');
qString = convertMultiSpaces( qString );
strBlockDataitems += ' <p style="display:inline-block; margin:0; padding:2px 10px; background:#ffffff">' + qString + '</p>\n';
}
strBlockDataitems += ' </div>\n'; // Indent end
}else if( qPocket.matchDataType( "DECIMAL" ) ){
strBlockDataitems += ' <span style="font-weight:bolder; color:#009900">' + qPocket.getName();
strBlockDataitems += '</span> <span style="color:#aaaaaa; font-size: x-small; padding:2px 5px">Numeric</span>\n';
strBlockDataitems += ' <div style="padding-left:30px">\n'; // 30px indent
let qNumber = engine.findData( qPocket );
if( qNumber === null ){
strBlockDataitems += ' <span style="font-style:italic; color:#aaaaaa">null</span>';
}else{
strBlockDataitems += ' <p style="display:inline-block; margin:0; padding:2px 10px; background:#ffffff">' + qNumber + '</p>\n';
}
strBlockDataitems += ' </div>\n'; // Indent end
}else if( qPocket.matchDataType( "SELECT" ) ){
strBlockDataitems += ' <span style="font-weight:bolder; color:#009900">' + qPocket.getName();
strBlockDataitems += '</span> <span style="color:#aaaaaa; font-size: x-small; padding:2px 5px">Select</span>\n';
strBlockDataitems += ' <div style="padding-left:30px">\n'; // 30px indent
let qSelected = engine.findData( qPocket );
if( qSelected === null ){
strBlockDataitems += ' <span style="font-style:italic; color:#aaaaaa">null</span>';
}else{
let numOfSelected = qSelected.size() - 0;
strBlockDataitems += ' <table cellpadding="2" cellspacing="2" bgcolor="#eeeeee">\n';
for( let j = 0; j < numOfSelected; j++ ){
strBlockDataitems += ' <tr><td style="padding:2px 10px; background:#ffffff">';
strBlockDataitems += qSelected.get(j).getDisplay();
strBlockDataitems += '</td><td style="padding:2px 5px; color:#aaaaaa">';
strBlockDataitems += qSelected.get(j).getValue();
strBlockDataitems += '</td></tr>\n';
}
strBlockDataitems += ' </table>\n';
}
strBlockDataitems += ' </div>\n'; // Indent end
}else if( qPocket.matchDataType( "DATE" ) ){
strBlockDataitems += ' <span style="font-weight:bolder; color:#009900">' + qPocket.getName();
strBlockDataitems += '</span> <span style="color:#aaaaaa; font-size: x-small; padding:2px 5px">Date</span>\n';
strBlockDataitems += ' <div style="padding-left:30px">\n'; // 30px indent
let qDate = engine.findData( qPocket );
if( qDate === null ){
strBlockDataitems += ' <span style="font-style:italic; color:#aaaaaa">null</span>';
}else{
strBlockDataitems += ' <p style="display:inline-block; margin:0; padding:2px 10px; background:#ffffff">' + qDate.toString() + '</p>\n';
}
strBlockDataitems += ' </div>\n'; // Indent end
}else if( qPocket.matchDataType( "DATETIME" ) ){
strBlockDataitems += ' <span style="font-weight:bolder; color:#009900">' + qPocket.getName();
strBlockDataitems += '</span> <span style="color:#aaaaaa; font-size: x-small; padding:2px 5px">Datetime</span>\n';
strBlockDataitems += ' <div style="padding-left:30px">\n'; // 30px indent
let qDatetime = engine.findData( qPocket );
if( qDatetime === null ){
strBlockDataitems += ' <span style="font-style:italic; color:#aaaaaa">null</span>';
}else{
strBlockDataitems += ' <p style="display:inline-block; margin:0; padding:2px 10px; background:#ffffff">' + qDatetime.toString() + '</p>\n';
}
strBlockDataitems += ' </div>\n'; // Indent end
}else if( qPocket.matchDataType( "FILE" ) ){
strBlockDataitems += ' <span style="font-weight:bolder; color:#009900">' + qPocket.getName();
strBlockDataitems += '</span> <span style="color:#aaaaaa; font-size: x-small; padding:2px 5px">Files</span>\n';
strBlockDataitems += ' <div style="padding-left:30px">\n'; // 30px Indent
let qFiles = engine.findData( qPocket );
if( qFiles === null ){
strBlockDataitems += ' <span style="font-style:italic; color:#aaaaaa">null</span>';
}else{
strBlockDataitems += ' <table cellpadding="2" cellspacing="2" bgcolor="#eeeeee">\n';
let numOfFiles = qFiles.size() - 0;
for( let j = 0; j < numOfFiles; j++ ){
strBlockDataitems += ' <tr><td style="padding:2px 10px; background:#ffffff">';
strBlockDataitems += qFiles.get(j).getName();
strBlockDataitems += '</td><td style="padding:2px 10px; color:#aaaaaa">';
strBlockDataitems += qFiles.get(j).getContentType();
strBlockDataitems += '</td><td style="padding:2px 5px; color:#aaaaaa">';
strBlockDataitems += convertFileSizeString( qFiles.get(j).getLength() - 0 ) + '</td></tr>\n';
}
strBlockDataitems += ' </table>\n';
}
strBlockDataitems += ' </div>\n'; // Indent end
}else if( qPocket.matchDataType( "QUSER" ) ){
strBlockDataitems += ' <span style="font-weight:bolder; color:#009900">' + qPocket.getName();
strBlockDataitems += '</span> <span style="color:#aaaaaa; font-size: x-small; padding:2px 5px">User</span>\n';
strBlockDataitems += ' <div style="padding-left:30px">\n'; // 30px indent
let qUser = engine.findData( qPocket );
if( qUser === null ){
strBlockDataitems += ' <span style="font-style:italic; color:#aaaaaa">null</span>';
}else{
strBlockDataitems += ' <table cellpadding="2" cellspacing="2" bgcolor="#eeeeee">\n';
strBlockDataitems += ' <tr><td style="padding:2px 10px; background:#ffffff">';
strBlockDataitems += qUser.getName();
strBlockDataitems += '</td><td style="padding:2px 10px; color:#aaaaaa">';
strBlockDataitems += qUser.getId();
strBlockDataitems += '</td><td style="padding:2px 5px; color:#aaaaaa">';
strBlockDataitems += qUser.getEmail();
strBlockDataitems += '</td></tr>\n';
strBlockDataitems += ' </table>\n';
}
strBlockDataitems += ' </div>\n'; // Indent end
}else if( qPocket.matchDataType( "QGROUP" ) ){
strBlockDataitems += ' <span style="font-weight:bolder; color:#009900">' + qPocket.getName();
strBlockDataitems += '</span> <span style="color:#aaaaaa; font-size: x-small; padding:2px 5px">Organization</span>\n';
strBlockDataitems += ' <div style="padding-left:30px">\n'; // 30px indent
let qGroup = engine.findData( qPocket );
if( qGroup === null ){
strBlockDataitems += ' <span style="font-style:italic; color:#aaaaaa">null</span>';
}else{
strBlockDataitems += ' <table cellpadding="2" cellspacing="2" bgcolor="#eeeeee">\n';
strBlockDataitems += ' <tr><td style="padding:2px 10px; background:#ffffff">';
strBlockDataitems += qGroup.getName();
strBlockDataitems += '</td><td style="padding:2px 10px; color:#aaaaaa">';
strBlockDataitems += qGroup.getId();
strBlockDataitems += '</td><td style="padding:2px 5px; color:#aaaaaa">';
strBlockDataitems += qGroup.getEmail();
strBlockDataitems += '</td></tr>\n';
strBlockDataitems += ' </table>\n';
}
strBlockDataitems += ' </div>\n'; // Indent end
}else if( qPocket.matchDataType( "LIST" ) ){
strBlockDataitems += ' <span style="font-weight:bolder; color:#009900">' + qPocket.getName();
strBlockDataitems += '</span> <span style="color:#aaaaaa; font-size: x-small; padding:2px 5px">Table</span>\n';
strBlockDataitems += ' <div style="padding-left:30px">\n'; // 30px indent
let qTable = engine.findData( qPocket );
if( qTable === null ){
strBlockDataitems += ' <span style="font-style:italic; color:#aaaaaa">null</span>';
}else{
strBlockDataitems += ' <table cellpadding="2" cellspacing="2" bgcolor="#eeeeee">\n';
let numOfRows = qTable.size() - 0;
let numOfCells = qPocket.getSubDataDefinitions().size() - 0;
for( let j = 0; j < numOfRows; j++ ){
strBlockDataitems += ' <tr>\n';
for( let k = 0; k < numOfCells; k++ ){
strBlockDataitems += ' <td style="padding:2px 10px; background:#ffffff">';
let strCell = qTable.get(j,k);
strCell = encodeHTML( strCell );
strCell = strCell.replace(/\t/g, ' ');
strCell = convertMultiSpaces( strCell );
if( qPocket.getSubDataDefinitions().get(k).matchDataType( "SELECT" ) ){
let strVarName = qPocket.getSubDataDefinitions().get(k).getVarName();
if( strVarName !== null ){
let strCell2 = qTable.getRow(j).getObject( strVarName ).getDisplay();
strCell2 = encodeHTML( strCell2 );
strCell2 = strCell2.replace(/\t/g, ' ');
strCell2 = convertMultiSpaces( strCell2 );
strCell = strCell2 + '<br><span style="color:#aaaaaa; font-size: x-small">' +
strCell + '</span>';
}
}
strBlockDataitems += strCell;
strBlockDataitems += '</td>\n';
}
strBlockDataitems += ' </tr>\n';
}
strBlockDataitems += ' </table>\n';
}
strBlockDataitems += ' </div>\n'; // Indent end
}
}
strBlockDataitems += '</div>\n'; // end BlockDataitems
// for FooterLink
const strProcessInstanceId = processInstance.getProcessInstanceId() + "";
const strProcessInstanceTitle = processInstance.getProcessInstanceTitle() + "";
let strBlockFooter = `<div style="margin:30px auto 0px 20px">
<span style="color:#009900">p${strProcessInstanceId}</span><br>
<span style="padding-left:20px; font-weight:bold">${strProcessInstanceTitle}</span>
</div>
<div style="margin:10px auto 10px 20px">
<a href="${strApplicationRoot}PE/Workitem/list?processInstanceId=${strProcessInstanceId}"
style="display:inline-block; font-weight:bold; border-radius:8px; padding:8px 16px;
color:#ffffff; background:#009900; border:solid 4px #009900">Desktop View</a>
<a href="${strApplicationRoot}SP/PE/ProcessInstance/view?processInstanceId=${strProcessInstanceId}"
style="display:inline-block; font-weight:bold; border-radius:8px; padding:8px 16px;
color:#ffffff; background:#009900; border:solid 4px #009900">Mobile View</a>
</div>
`;
/// Assembles
let strHtml = strBlockHeader;
if( strAbstract !== "" ){
strHtml += strBlockAbstract;
}
strHtml += strBlockDataitems;
if( strApplicationRoot !== "" ){
strHtml += strBlockFooter;
}
strHtml += "</body></html>";
//// == Data Updating / ワークフローデータへの代入 ==
engine.setData( strPocketHtml, strHtml );
} //////// END "main()" /////////////////////////////////////////////////////////////////
function encodeHTML( str ){
return str.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
// convert multiple consecutive spaces to " .."
function convertMultiSpaces( strArg ){
let re = /\ {2,}/g;
let strReturn = strArg.replace( re, function( strMatch ){
let strNbspSpRepeat = "";
for( let i = 0; i < strMatch.length; i++ ){
if( (i % 2) === 0 ){ // Even number
strNbspSpRepeat += " ";
}else{ // Odd number
strNbspSpRepeat += " ";
}
}
return strNbspSpRepeat;
});
return strReturn;
}
function convertFileSizeString( numArg ){
let strReturn = "";
if ( numArg >= (Math.pow(1024,4)) ){ strReturn = (numArg / Math.pow(1024,4)).toFixed(0) + " TB"; }
else if( numArg >= (Math.pow(1024,3)) ){ strReturn = (numArg / Math.pow(1024,3)).toFixed(0) + " GB"; }
else if( numArg >= (Math.pow(1024,2)) ){ strReturn = (numArg / Math.pow(1024,2)).toFixed(0) + " MB"; }
else if( numArg >= 1024 ){ strReturn = (numArg / 1024 ).toFixed(0) + " KB"; }
else { strReturn = numArg + " bytes"; }
return strReturn;
}
/*
Notes:
- Email notification is an effective way to share business data with non-users.
- You can share any data in your workflow with anyone, regardless of the data viewing permissions.
- If you notify by HTML mail, you can improve the visibility of business data.
- When a token reaches the automated step, the code for HTML mail is automatically generated.
- The generated code can be set in "Message Sending Intermediate Event (Email)" (v13.1) as it is.
- https://support.questetra.com/bpmn-icons/throwing-message-intermediate-event-email/
- Some data will be converted automatically.
- Special characters are escaped as appropriate. For example, `<` is automatically converted to `<`.
- The tab code is replaced with 4 spaces.
- Continuous spaces (two or more) are replaced with ` ` every other character.
APPENDIX
- The generated HTML code is not guaranteed to be displayed properly in all mailers.
- Some dataitems cannot be incorporated.
- The Guide Panel cannot be set.
- The Discussion is ignored.
- "Label" may not be output for the choice type data in the table type data.
Notes-ja:
- ワークフローシステムの非ユーザと業務データを共有する手段としては、メール通知が有効です。
- データ閲覧権限に関わらず、ワークフロー内の任意データを任意の人と共有できます。
- "HTMLメール" で通知すれば、業務データの視認性を高められます。
- 案件が自動処理工程に到達した際、HTMLメール用のコードが自動的に生成されます。
- 生成されたコードは、そのまま『メッセージ送信中間イベント(メール)』(v13.1)にセットできます。
- https://support.questetra.com/ja/bpmn-icons/throwing-message-intermediate-event-email/
- 一部のデータは自動的に変換されます。
- 特殊文字は、適宜エスケープ処理されます。たとえば `<` は `<` に自動的に変換されます。
- タブコードはスペース4つに変換されます。
- 連続スペース(2文字以上)は、一文字おきに ` ` に置換されます。
APPENDIX-ja
- 生成されるHTMLコードは、全てのメーラで正常に表示されることが保証されている訳ではありません。
- 一部のデータ項目は組み込めません。
- ガイドパネル型(Guide Panel)は設定できません。
- 掲示板型(Discussion)は無視されます。
- テーブル型データ内の選択肢型データは「表示ラベル」が出力されない場合があります。
*/
Download
- Email-Html-String-Create-DataitemList-2021.xml
- Email-Html-String-Create-DataitemList-2023.xml
- 2023-08-08 (C) Questetra, Inc. (MIT License)
- for “GraalJS standard (engine-type 3)” on v15.0 or above
2021-06-24 (C) Questetra, Inc. (MIT License)
https://support.questetra.com/ja/addons/email-html-string-create-dataitemlist-2021/
Addonファイルのインポートは Professional でのみご利用いただけます
Notes
- ワークフローシステムの非ユーザと業務データを共有する手段としては、メール通知が有効です。
- データ閲覧権限に関わらず、ワークフロー内の任意データを任意の人と共有できます。
- “HTMLメール” で通知すれば、業務データの視認性を高められます。
- 案件が自動処理工程に到達した際、HTMLメール用のコードが自動的に生成されます。
- 生成されたコードは、そのまま『メッセージ送信中間イベント(メール)』(v13.1)にセットできます。
- https://support.questetra.com/ja/bpmn-icons/throwing-message-intermediate-event-email/
- 一部のデータは自動的に変換されます。
- 特殊文字は、適宜エスケープ処理されます。たとえば
<
は<
に自動的に変換されます。 - タブコードはスペース4つに変換されます。
- 連続スペース(2文字以上)は、一文字おきに
に置換されます。
- 特殊文字は、適宜エスケープ処理されます。たとえば
Capture



Appendix
- 生成されるHTMLコードは、全てのメーラで正常に表示されることが保証されている訳ではありません。
- 一部のデータ項目は組み込めません。
- ガイドパネル型(Guide Panel)は設定できません。
- 掲示板型(Discussion)は無視されます。
- テーブル型データ内の選択肢型データは「表示ラベル」が出力されない場合があります。
- 掲示板型データを確認したい場合は、あらかじめ複数行文字列型に代入し、その文字列型を参照設定してください。