#Email-HTML-文字列: 案件データリスト 生成

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

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メール用のコードが自動的に生成されます。
  • 一部のデータは自動的に変換されます。
    • 特殊文字は、適宜エスケープ処理されます。たとえば <&lt; に自動的に変換されます。
    • タブコードはスペース4つに変換されます。
    • 連続スペース(2文字以上)は、一文字おきに &nbsp; に置換されます。

Capture

格納データが一覧できるHTMLコード(HTMLメール用)を生成します。ワークフロー内の指定データ項目を指定の順序で組み立てます。生成コードをメール送信イベントに渡せば、任意の関係者とデータを共有できます。
格納データが一覧できるHTMLコード(HTMLメール用)を生成します。ワークフロー内の指定データ項目を指定の順序で組み立てます。生成コードをメール送信イベントに渡せば、任意の関係者とデータを共有できます。
格納データが一覧できるHTMLコード(HTMLメール用)を生成します。ワークフロー内の指定データ項目を指定の順序で組み立てます。生成コードをメール送信イベントに渡せば、任意の関係者とデータを共有できます。

Appendix

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

See also

Questetra Supportをもっと見る

今すぐ購読し、続きを読んで、すべてのアーカイブにアクセスしましょう。

続きを読む