Converter: #TSV String to #MdChart String

Converter: #TSV String to #MdChart String

translate コンバータ: #TSV文字列 to #MdChart文字列

Converts a numeric TSV string into a Markdown-embeddable stacked bar chart (MdChart). The first TSV column is used as the aggregation unit, such as “YYYYMM”, and the first row as data series, such as “Sales Representative” or “Client”.

Auto Step icon
Configs for this Auto Step
StrConfA
A: Set TSV String *#{EL}
StrConfB1
B1: Set Pixel Widths (Unit Bar Total) as CSV (default:60,360,60)#{EL}
StrConfB2
B2: Set Series Color in CSV (default: “#e66,#39f,#f90,#a3c,…”)#{EL}
StrConfB3
B3: Set Max Scale Value (default: 100)#{EL}
StrConfB4
B4: Set Scale Labels in CSV (eg. “0,50,100%”)#{EL}
StrConfB5
B5: Set Value Prefix/Suffix in CSV (eg. “$,”, “,usd”)#{EL}
BoolConfB6
B6: Legend (Color Marker + Series Name), Hide or Show
BoolConfB7
B7: Scale Labels, Hide or Show
SelectConfC
C: Select DATA to store Converted Markdown String (update) *
StrConfB8
B8: Set Max Num of MdChart String (default: 8000)#{EL}
SelectConfD1
D1: Select NUMERIC for Number of TSV Lines (update)
SelectConfD2
D2: Select NUMERIC for TSV Rows (ignore blanks) (update)
Script (click to open)
// Script Example of Business Process Automation
// for 'engine type: 3' ("GraalJS standard mode")


//////// START "main()" /////////////////////////////////////////////////////////////////
main();
function main(){ 

//// == Config Retrieving / 工程コンフィグの参照 ==
const strTsv        = configs.get       ( "StrConfA" );     // REQUIRED
  const arr2dTsv    = parseAsRectangular( strTsv );
  if( arr2dTsv.length === 0 ){
    throw new Error( "\n AutomatedTask ConfigError:" +
                     " Config {A: TSV} is empty \n" );
  }
  if( arr2dTsv.length === 1 ){
    throw new Error( "\n AutomatedTask ConfigError:" +
                     " Config {A: TSV} requires at least 2 lines (header and data) \n" );
  }
const strWidths     = configs.get       ( "StrConfB1" ) || "60,360,60"; // default
const arrWidths     = strWidths.split(",");
const numWidthUnit  = parseInt (arrWidths[0], 10) || 60;
const numWidthBar   = parseInt (arrWidths[1], 10) || 360;
const numWidthTotal = parseInt (arrWidths[2], 10) || 60;
const strColors     = configs.get       ( "StrConfB2" ) || "#e66,#39f,#f90,#a3c,#6a5,#678,#cc3,#999";     // default
const arrColors     = strColors.split(",")
const strMaxScale   = configs.get       ( "StrConfB3" );
const numMaxScale   = strMaxScale !== "" ? parseFloat(strMaxScale) : 100; // default 100
const strLabels     = configs.get       ( "StrConfB4" ) || "0,50,100%";
const arrLabels     = strLabels.split(",");
const strPrefSuf    = configs.get("StrConfB5") || ","; // デフォルトはカンマのみ(前後になにも付けない)
const arrPrefSuf    = strPrefSuf.split(",");
const strPrefix     = arrPrefSuf[0] || ""; // カンマの左側
const strSuffix     = arrPrefSuf.length > 1 ? arrPrefSuf[1] : ""; // カンマの右側
const isShowLegend  = configs.getObject ( "BoolConfB6" );
const isShowLabels  = configs.getObject ( "BoolConfB7" );
const numMaxLength  = parseInt(configs.get("StrConfB8" ), 10) || 8000;
const strPocketC    = configs.getObject ( "SelectConfC" );
const numPocketD1   = configs.getObject ( "SelectConfD1" );
const numPocketD2   = configs.getObject ( "SelectConfD2" );



//// == Data Retrieving / ワークフローデータの参照 ==
// (Nothing. Retrieved via Expression Language in Config Retrieving)



//// == Calculating / 演算 ==
let strMarkdown = "";

// 凡例の表示
if (isShowLegend) {
  for (let i = 1; i < arr2dTsv[0].length; i++) {
    const color = arrColors[(i - 1) % arrColors.length];  // 色の数が足りない場合はループさせる
    strMarkdown += `<span style="color:${color}">■${arr2dTsv[0][i]}</span> `;
  }
  strMarkdown += "\n";
}

// 目盛りの表示
if (isShowLabels) {
  strMarkdown += `<div style="display:flex;color:#777"><span style="display:inline-block;width:${numWidthUnit}px"></span>`;
  strMarkdown += `<span style="display:flex;width:${numWidthBar}px;justify-content:space-between">`;
  for (let i = 0; i < arrLabels.length; i++) {
    strMarkdown += `<span>${arrLabels[i]}</span>`;
  }
  strMarkdown += `</span><span style="display:inline-block;width:${numWidthTotal}px"></span></div>`;
  strMarkdown += "\n";
}


// 棒グラフの表示
for (let i = 1; i < arr2dTsv.length; i++) {
  let strRow = ""; // 1行分の文字列を一時保存する変数

  // ユニット名
  strRow += `<div style="display:flex;align-items:center"><span style="display:inline-block;width:${numWidthUnit}px">`;
  strRow += arr2dTsv[i][0];
  strRow += `</span>`;
  // 一本の棒グラフ(背景)
  strRow += `<span style="display:inline-block;width:${numWidthBar}px;background:#eee">`;
  strRow += `<span style="display:flex;width:100%;height:10px">`;
  let totalValue = 0;
  // 一本の棒グラフ: 系列の積み上げ
  for (let j = 1; j < arr2dTsv[i].length; j++) {
    const cellValue = parseFloat(arr2dTsv[i][j].replace(/[^0-9.-]/g, "")) || 0;
    totalValue += cellValue;
    const barRatio = Math.max(0, cellValue / numMaxScale);
    const color = arrColors[(j - 1) % arrColors.length];
    strRow += `<span style="flex:${barRatio};background:${color}"></span>`;
  }
  // 一本の棒グラフ: グラフ部分を閉じる
  strRow += `<span style="flex:${Math.max(0, 1 - (totalValue / numMaxScale))}"></span>`;
  strRow += `</span></span>`;
  // 一本の棒グラフの横に積み上げ合計値
  strRow += `<span style="display:inline-block;width:${numWidthTotal}px;text-align:right">${strPrefix}${totalValue.toLocaleString()}${strSuffix}</span></div>`;
  strRow += "\n";

  // 文字数制限チェック (B8)
  // 現在の文字列と追加予定の行の文字数を足して、上限を超えるなら追加せずにループを終了
  if (strMarkdown.length + strRow.length > numMaxLength) {
    engine.log(`Warning: Reached Max Length (${numMaxLength}) at row ${i}. Stopping chart generation to prevent unclosed HTML tags.`);
    break; 
  }
  // 制限内に収まる場合のみ全体文字列に追加
  strMarkdown += strRow;
}




//// == Data Updating / ワークフローデータへの代入 ==

if ( strPocketC !== null) { 
  engine.setData( strPocketC, strMarkdown );
}

// オリジナルのTSV文字列の行数 (D1)
if ( numPocketD1 !== null) { 
  const totalLines = strTsv.split("\n").length;
  engine.setData( numPocketD1, new java.math.BigDecimal(totalLines) );
}

// 空行を除いたTSV行数 (D2)
if ( numPocketD2 !== null) { 
  engine.setData( numPocketD2, new java.math.BigDecimal(arr2dTsv.length) );
}

} //////// END "main()" /////////////////////////////////////////////////////////////////



/**
 * Parses TSV string as a two-dimensional rectangular data matrix and creates a 2D array.
 * @param {string} strTsv - The input TSV string
 * @returns {Array<Array<string>>} Rectangular 2D array
 */
function parseAsRectangular( strTsv ){
  const arrTsv = strTsv.split("\n");
  let numMinWidth   = Infinity;
  let numMaxWidth   = 0;
  let numBlanklines = 0;
  
// Step 1: パースと最大最小幅算出を1度のループで / Parse and Calc max-min widths in single loop
  const parsedRows = [];
  for( let i = 0; i < arrTsv.length; i++ ){
    const line = arrTsv[i];
    if( line === "" ){
      numBlanklines++;
      continue;
    }
    const arrCells = line.split("\t");
    const len = arrCells.length;
    if( len < numMinWidth ){ numMinWidth = len; }
    if( len > numMaxWidth ){ numMaxWidth = len; }
    parsedRows.push( arrCells );
  }
  // 全て空行だった場合のフェイルセーフ / Fail-safe in case all lines are blank
  if( numMinWidth === Infinity ){
    numMinWidth = 0;
  }
  engine.log( " AutomatedTask TsvDataCheck:" + 
              " MinWidth:" + numMinWidth +
              " MaxWidth:" + numMaxWidth +
              " Lines:" + arrTsv.length +
              " (BlankLines:" + numBlanklines + ")" );

// Step 2: 矩形へ整形 (不足列に "") / Format into rectangle (fill in missing columns with "")
  for( let i = 0; i < parsedRows.length; i++ ){
    const row = parsedRows[i];
    // 最大幅に満たない分だけ空文字列を追加
    while( row.length < numMaxWidth ){
      row.push( "" );
    }
  }
  return parsedRows;
}


/*
### NOTES-en
- A bar chart (MdChart string) is automatically generated each time a Case reaches this Automated Step.
    - From the second row of the input TSV string onward, all fields are parsed as "numeric strings", except for the first column (Column A).
        - Only the first column (Column A) is considered as the aggregation unit name, such as "YYYY-MM" or "Quarter".
        - If characters other than a "period (.)", a "minus sign (-)", and "0-9" exist, the "stripped string" is parsed.
        - Even if commas exist, they are considered thousands separators, and the "stripped string" is parsed.
        - The "stripped string" is parsed using `parseFloat()`.
        - If parsing fails, the value is evaluated as `0`.
    - The "MdChart string" is an HTML string where `div` and `span` elements are arranged using flexbox.
        - For an N-row, 2-column TSV string, a simple bar chart is displayed (e.g., "Monthly Sales").
        - For an N-row, M-column TSV string, a stacked bar chart with (M-1) "series" is displayed.
        - If the stacked total value exceeds the "Max Scale Value (B3)", the chart will be automatically scaled down to fit exactly within the chart width (100%) while maintaining the ratio of each series (no blank space will be displayed on the right).
- The input TSV is parsed as the "simplest tab-separated string".
    - Double quotes and other characters within the TSV string are retained as is.
- The number of lines in the input TSV string can also be saved as Case Data.

### NOTES-ja
- このアドオン自動工程にケース(案件)が到達する度に、自動的に棒グラフ(MdChart文字列)が生成されます。
    - 入力TSV文字列の2行目以降は、全フィールドが「数値文字列」として解析されます。※1列目(A列)を除く
        - 1列目(A列)だけは、「年月」や「四半期」などの集計単位名とみなされます。
        - 「ピリオド(.)」と「マイナス記号」と「0~9」以外の文字が存在する場合、「除去された文字列」が解析されます。
        - カンマが存在する場合も、(桁区切り文字とみなされ)、「除去された文字列」が解析されます。
        - 「除去された文字列」が `parseFloat()` によって解析されます。
        - 解析に失敗した場合 `0` とみなされます。
    - "MdChart文字列" は `div` と `span` が flex 配置されたHTML文字列です。
        - N行2列TSV文字列の場合、シンプル棒グラフが表示されます。 ※「月ごとの売上」など
        - N行M列TSV文字列の場合、"系列" が (M-1) 個の積み上げ棒グラフが表示されます。
        - 積み上げ合計値が「グラフ目盛りの最大値(B3)」を超えた場合、縮小して表示されます。
            - グラフの表示幅(100%)にぴったり収まるよう、各系列の比率を維持したまま、縮小されます。
            - 右側の余白は生成されません。
- 入力TSVは「もっともシンプルなタブ区切り文字列」としてパースされます。
    - TSV文字列内のダブルクオート文字等も、そのまま保持されます。
- 入力TSV文字列の行数もケースデータとして格納可能です。


#### TSV example
```
YYYY-MM	Tanaka	Sato	Suzuki	Yamada
2026-01	610,000	520,000	380,000	450,000
2026-02	580,000	490,000	410,000	480,000
2026-03	700,000	600,000	450,000	550,000
2026-04	550,000	480,000	390,000	420,000
2026-05	590,000	510,000	420,000	460,000
2026-06	630,000	550,000	460,000	510,000
2026-07	680,000	620,000	250,000	280,000
2026-08	570,000	530,000	230,000	290,000
2026-09	650,000	310,000	220,000	250,000
2026-10	560,000	290,000	240,000	270,000
2026-11	600,000	300,000	250,000	260,000
2026-12	800,000	720,000	600,000	680,000
```


### APPENDIX-en
- Blank lines within the input TSV string are ignored.
- Please set series colors corresponding to the number of series in the TSV (TSV column count - 1).
    - (It is fine to set more colors than required)
    - Example of high-contrast series colors: "#e66,#39f,#f90,#a3c,#6a5,#678,#cc3,#999".
    - Example of warm/cool color gradation: "#c42,#e84,#fb6,#cc3,#6ad,#9cf,#cde,#eef".
- Blank lines within the input TSV string are ignored regarding the character limit for the MdChart string.
- You can specify a prefix and suffix for the total value.
    - To add only a prefix: Set `$,` → `$1,200,000`
    - To add only a suffix: Set `, items` → `150 items`
    - To add both: Set `Approx. , hours` → `Approx. 40 hours`
    - To include a space: Set `$ ,` → `$ 1,200`

### APPENDIX-ja
- 入力TSV文字列内の空行は無視されます。
- 系列の色は、TSV内の系列の数(TSV列数 - 1)だけセットしてください。(多く設定する分には構いません)
    - 系列のメリハリを効かせる例: "#e66,#39f,#f90,#a3c,#6a5,#678,#cc3,#999"
    - 寒色暖色でグラデーション例: "#c42,#e84,#fb6,#cc3,#6ad,#9cf,#cde,#eef"
- MdChart文字列の文字数制限は、入力TSV文字列内の空行は無視されます。
- 合計値には接頭辞・接尾辞を指定できます。
    - 前だけにつけたい場合: `¥,` と設定 → `¥1,200,000`
    - 後ろだけにつけたい場合: `,件` と設定 → `150件`
    - 前後両方につけたい場合: `約,時間` と設定 → `約40時間`
    - 間にスペースを入れたい場合: `$ ,` と設定 → `$ 1,200`
*/

Download

warning Freely modifiable JavaScript (ECMAScript) code. No warranty of any kind.
(Installing Addon Auto-Steps are available only on the Professional edition.)

Notes

  • A bar chart (MdChart string) is automatically generated each time a Case reaches this Automated Step.
    • From the second row of the input TSV string onward, all fields are parsed as “numeric strings”, except for the first column (Column A).
      • Only the first column (Column A) is considered as the aggregation unit name, such as “YYYY-MM” or “Quarter”.
      • If characters other than a “period (.)”, a “minus sign (-)”, and “0-9” exist, the “stripped string” is parsed.
      • Even if commas exist, they are considered thousands separators, and the “stripped string” is parsed.
      • The “stripped string” is parsed using parseFloat().
      • If parsing fails, the value is evaluated as 0.
    • The “MdChart string” is an HTML string where div and span elements are arranged using flexbox.
      • For an N-row, 2-column TSV string, a simple bar chart is displayed (e.g., “Monthly Sales”).
      • For an N-row, M-column TSV string, a stacked bar chart with (M-1) “series” is displayed.
      • If the stacked total value exceeds the “Max Scale Value (B3)”, the chart will be automatically scaled down to fit exactly within the chart width (100%) while maintaining the ratio of each series (no blank space will be displayed on the right).
  • The input TSV is parsed as the “simplest tab-separated string”.
    • Double quotes and other characters within the TSV string are retained as is.
  • The number of lines in the input TSV string can also be saved as Case Data.

Capture

Appendix

  • Blank lines within the input TSV string are ignored.
  • Please set series colors corresponding to the number of series in the TSV (TSV column count – 1).
    • (It is fine to set more colors than required)
    • Example of high-contrast series colors: “#e66,#39f,#f90,#a3c,#6a5,#678,#cc3,#999”.
    • Example of warm/cool color gradation: “#c42,#e84,#fb6,#cc3,#6ad,#9cf,#cde,#eef”.
  • Blank lines within the input TSV string are ignored regarding the character limit for the MdChart string.
  • You can specify a prefix and suffix for the total value.
    • To add only a prefix: Set $,$1,200,000
    • To add only a suffix: Set , items150 items
    • To add both: Set Approx. , hoursApprox. 40 hours
    • To include a space: Set $ ,$ 1,200

See Also

Discover more from Questetra Support

Subscribe now to keep reading and get access to the full archive.

Continue reading