Email-HTML String, Create DataitemList
Generates HTML code (for HTML mail) that lists stored data. Assembles the specified Data Items in the workflow in the specified order. You can share your data with any party by using the [Throwing Message Intermediate Event].
Configs
- A: Set Field Names in each line (eg “q_corp_name”) *#{EL}
- B: Set Note (Line breaks are automatically converted to br)#{EL}
- C: If to display footer link, Set ${var[applicationRoot]}#{EL}
- D: Select STRING DATA that stores Email-HTML (update) *
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
2021-06-24 (C) Questetra, Inc. (MIT License)
https://support.questetra.com/addons/email-html-string-create-dataitemlist-2021/
The Add-on import feature is available with Professional edition.
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.
- HTML mail notifications 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 a [Throwing Message 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.
- Special characters are escaped as appropriate. For example,
Capture



Appendix
- The generated HTML code is not guaranteed to be displayed properly in all mailers.
- Some Data Items 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 Item.
- To check Discussion-type data, assign it to the multiline String-type in advance and set the String-type as a reference.