#TSV文字列: 数値列の四則演算
#TSV-String: Basic Math on Numeric Column
数値演算の結果を新しい列として追加します。「A列とB列の加算」や「C列と “1.1” の乗算」といった2値の演算結果がTSV各行の行末に追加されます。加算、減算、乗算、除算、剰余、べき乗に対応しています。
Configs for this Auto Step
- StrConfA
- A: 入力TSV文字列をセットしてください *#{EL}
- BoolConfAx
- Ax: 1行目をヘッダ行とみなさない ⇔ 1行目をヘッダ行とみなす
- OptionConfB
- B: 演算子を選択してください *
- StrConfX
- X: 第1オペランド(変数X)となる列IDをセットしてください(A列:”0″, C列:”2″)#{EL}
- StrConfXv
- Xv: 第1オペランド(X)のデフォルト値をセットしてください(例: “1.1”)#{EL}
- StrConfY
- Y: 第2オペランド(変数Y)となる列IDをセットしてください(B列:”1″, D列:”3″)#{EL}
- StrConfYv
- Yv: 第2オペランド(Y)のデフォルト値をセットしてください(例: “1.1”)#{EL}
- SelectConfC
- C: アウトプットTSVが格納される複数行文字列型データを選択してください (更新) *
- BoolConfCx
- Cx: 桁区切り文字: Off ⇔ On
- SelectConfDy
- Dy: インプットTSVの行数(高さ)を格納する数値型データを選択してください (更新)
- SelectConfDx
- Dx: インプットTSVの列数(幅)を格納する数値型データを選択してください (更新)
- SelectConfEy
- Ey: アウトプットTSVの行数(高さ)が格納される数値型データを選択してください (更新)
- SelectConfEx
- Ex: アウトプットTSVの列数(幅)が格納される数値型データを選択してください (更新)
- StrConfF
- F: 桁区切りOnの時、小数部に使用する最小桁数をセットしてください(default: “0”)#{EL}
- StrConfG
- G: 桁区切りOnの時、小数部に使用する最大桁数をセットしてください(default: “3”)#{EL}
Script (click to open)
// Script Example of Business Process Automation
// for 'engine type: 3' ("GraalJS standard mode")
// cf. 'engine type: 2' ("GraalJS Nashorn compatible mode") (renamed from "GraalJS" at 20230526)
//////// START "main()" /////////////////////////////////////////////////////////////////
main();
function main(){
//// == Config Retrieving / 工程コンフィグの参照 ==
const strTsv = configs.get ( "StrConfA" ); // REQUIRED
if( strTsv === "" ){
throw new Error( "\n AutomatedTask ConfigError:" +
" Config {A: TSV} is empty \n" );
}
// get TSV as Array-Array (2d Array)
const arr2dTsv = parseAsRectangular ( strTsv ); // [rowY,colX]
let numInputTsvLines = arr2dTsv.length;
let numInputTsvCols = arr2dTsv[0].length;
const boolHeaderOn = configs.getObject ( "BoolConfAx" ); // TOGGLE
// https://questetra.zendesk.com/hc/ja/articles/360024574471-R2300 "Boolean object"
const strOperator = configs.get ( "OptionConfB" ); /// REQUIRED (SELECT_ITEM)
// "add", "subtract", "multiply", "divide", "remainder", "power"
const strOperandXid = configs.get ( "StrConfX" ); // not required
let numOperandXid = parseInt( strOperandXid, 10 ); // Int or NaN
const strOperandXv = configs.get ( "StrConfXv" ); // not required
let numOperandXv = parseFloat( strOperandXv ); // Float or NaN
const strOperandYid = configs.get ( "StrConfY" ); // not required
let numOperandYid = parseInt( strOperandYid, 10 ); // Int or NaN
const strOperandYv = configs.get ( "StrConfYv" ); // not required
let numOperandYv = parseFloat( strOperandYv ); // Float or NaN
const strPocketC = configs.getObject ( "SelectConfC" ); // REQUIRED
const boolSeparatorOn = configs.getObject ( "BoolConfCx" ); // TOGGLE
const numPocketDy = configs.getObject ( "SelectConfDy" ); // not required
const numPocketDx = configs.getObject ( "SelectConfDx" ); // not required
const numPocketEy = configs.getObject ( "SelectConfEy" ); // not required
const numPocketEx = configs.getObject ( "SelectConfEx" ); // not required
const strDigitMin = configs.get ( "StrConfF" ); // not required
let numDigitMin = parseInt( strDigitMin, 10 ); // Int or NaN
const strDigitMax = configs.get ( "StrConfG" ); // not required
let numDigitMax = parseInt( strDigitMax, 10 ); // Int or NaN
//// == Data Retrieving / ワークフローデータの参照 ==
// (Nothing. Retrieved via Expression Language in Config Retrieving)
//// == Calculating / 演算 ==
let arrOutputTsv = [];
if ( boolHeaderOn ){
let arrTmp = arr2dTsv.shift(); // Remove First Element
arrTmp.push ( strOperator );
arrOutputTsv.push ( arrTmp.join( '\t' ) );
}
for ( let i = 0; i < arr2dTsv.length; i++ ) {
let arrTmp = arr2dTsv[i].slice();
let numX;
if ( !isNaN(numOperandXid) ) {
numX = parseFloat(arr2dTsv[i][numOperandXid].replace(/,/g, ''));
}
if ( isNaN(numX) ) { // numOperandXidがNaNの場合、またはTSVからのパース結果がNaNの場合
numX = numOperandXv;
}
if ( isNaN(numX) ){
arrTmp.push ( "#N/A" );
arrOutputTsv.push ( arrTmp.join( '\t' ) );
continue;
}
let numY;
if ( !isNaN(numOperandYid) ) {
numY = parseFloat(arr2dTsv[i][numOperandYid].replace(/,/g, ''));
}
if ( isNaN(numY) ) { // numOperandYidがNaNの場合、またはTSVからのパース結果がNaNの場合
numY = numOperandYv;
}
if ( isNaN(numY) ){
arrTmp.push ( "#N/A" );
arrOutputTsv.push ( arrTmp.join( '\t' ) );
continue;
}
if ( strOperator === 'divide' && numY === 0 ) {
arrTmp.push("#DIV/0!");
arrOutputTsv.push(arrTmp.join('\t'));
continue;
}
let numResult = 0;
switch ( strOperator ) {
case 'add': numResult = numX + numY; break;
case 'subtract': numResult = numX - numY; break;
case 'multiply': numResult = numX * numY; break;
case 'divide': numResult = numX / numY; break;
case 'remainder': numResult = numX % numY; break;
case 'power': numResult = numX ** numY; break;
default: throw new Error( "\n AutomatedTask RuntimeError:" +
" Unsupported operator: " + strOperator + "\n" );
}
if ( boolSeparatorOn ){
let formatOptions = {};
if ( !isNaN(numDigitMin) ) formatOptions.minimumFractionDigits = numDigitMin;
if ( !isNaN(numDigitMax) ) formatOptions.maximumFractionDigits = numDigitMax;
arrTmp.push( numResult.toLocaleString( undefined, formatOptions ) );
} else {
arrTmp.push ( numResult );
}
arrOutputTsv.push ( arrTmp.join( '\t' ) );
}
//// == Data Updating / ワークフローデータへの代入 ==
/// ref) Retrieving / Updating from ScriptTasks
/// https://questetra.zendesk.com/hc/en-us/articles/360024574771-R2301
/// https://questetra.zendesk.com/hc/ja/articles/360024574771-R2301
if ( strPocketC !== null ){
engine.setData( strPocketC, arrOutputTsv?.join( '\n' ) ?? "" );
}
if ( numPocketDy !== null ){
engine.setData( numPocketDy, new java.math.BigDecimal( numInputTsvLines ) );
}
if ( numPocketDx !== null ){
engine.setData( numPocketDx, new java.math.BigDecimal( numInputTsvCols ) );
}
if ( numPocketEy !== null ){
engine.setData( numPocketEy, new java.math.BigDecimal( arrOutputTsv.length ) );
}
if ( numPocketEx !== null ){
engine.setData( numPocketEx, new java.math.BigDecimal( arrOutputTsv[0].split("\t").length ) );
}
} //////// END "main()" /////////////////////////////////////////////////////////////////
/**
* Parses a TSV (Tab-Separated Values) string and returns a 2D array with rectangular shape.
* This function ensures that each row in the resulting 2D array has the same number of columns,
* equal to the widest row in the original TSV input. Shorter rows are padded with empty strings.
* Blank lines in the input are ignored.
* Additionally, the function logs the minimum and maximum column counts (excluding blank lines),
* along with the total number of lines and count of blank lines.
*
* TSV(タブ区切り値)形式の文字列を解析し、2次元の配列として整形して返します。
* 入力されたTSV文字列を行単位で分割し、各行のセル数をそろえて「長方形(矩形)」の形に整えます。
* 最もセル数が多い行に合わせて、セル数が足りない行には空文字列("")を補完します。
* 空行(中身が空の行)は無視されます。
* また、最小列数・最大列数・全体の行数・空行の数をログに出力します(engine.log)。
*
*
* @param {string} strTsv - The raw TSV string, with rows separated by newline characters (`\n`)
* and cells separated by tab characters (`\t`).
*
* @returns {string[][]} A two-dimensional array where each sub-array represents a row from the TSV input,
* padded with empty strings to ensure uniform column width.
*
* @example
* const tsv = "a\tb\tc\n1\t2\nx\ty\tz\tw\n";
* const result = parseAsRectangular(tsv);
* // result:
* // [
* // ["a", "b", "c", ""],
* // ["1", "2", "", ""],
* // ["x", "y", "z", "w"]
* // ]
*/
function parseAsRectangular( strTsv ){
const arrTsv = strTsv.split("\n");
/// Get numMinWidth and numMaxWidth (blank lines are excluded)
let numMinWidth = Infinity; // cf. String-Type Max: 1 million
let numMaxWidth = 0;
let numBlanklines = 0;
for( let i = 0; i < arrTsv.length; i++ ){
if( arrTsv[i] === "" ){ // Skip blank lines
numBlanklines += 1;
continue;
}
let arrCells = arrTsv[i].split("\t");
if( numMinWidth > arrCells.length ){ numMinWidth = arrCells.length; }
if( numMaxWidth < arrCells.length ){ numMaxWidth = arrCells.length; }
}
engine.log( " AutomatedTask TsvDataCheck:" +
" MinWidth:" + numMinWidth +
" MaxWidth:" + numMaxWidth +
" Lines:" + arrTsv.length +
" (BlankLines:" + numBlanklines + ")" );
/// Get numMinWidth and numMaxWidth (blank lines are excluded)
let arr2dTsv = [];
for( let i = 0; i < arrTsv.length; i++ ){
if( arrTsv[i] === "" ){ // Skip blank lines
continue;
}
let arrTmp = [];
let arrCells = arrTsv[i].split("\t");
for( let j = 0; j < numMaxWidth; j++ ){
if( j < arrCells.length ){
arrTmp[j] = arrCells[j];
}else{
arrTmp[j] = "";
}
}
arr2dTsv.push( arrTmp );
}
return arr2dTsv;
}
/*
### NOTES
- When the process reaches this [Automated Step], the "calculation process" is automatically executed.
- The calculation result is added to the rightmost column at the output TSV.
- Binary operations can be set using numeric column X and numeric column Y (column IDs starting from zero).
- One of XY can also be set to a fixed value.
- TSV (Tab Separated Values) text is assumed to be rectangular data.
- TSV text: monthly sales tally, monthly access tally, etc.
- Data that is not rectangular is automatically formatted with blank characters.
- Blank lines (including trailing newlines) are ignored.
- Numeric columns are parsed with JavaScript `parseFloat()` after removing commas (thousand separators).
- The characters accepted are plus/minus sign, decimal digits, decimal point (.), exponent indicator, and the `Infinity` literal.
- If it cannot be converted to a number, it is calculated using the "default value".
- If no column ID is specified for XY, it is calculated using the "default value" (fixed value).
- If the "default value" is also not set, `#N/A` will be output.
- If the value of Y is "0" during division, `#DIV/0!` will be output.
- To arrange the sort order of the output TSV, place "TSV String, Convert" downstream in the workflow.
- https://support.questetra.com/addons/tsv-string-convert-2021/
### NOTES-ja
- 案件プロセスがこの自動工程に到達した際、TSVテキストが読み込まれ「計算処理」が自動実行されます
- 計算結果が最右列に列追加されたTSVが出力されます
- 数値列Xと数値列Yによる二項演算が設定可能です(列IDはゼロ始まりで設定してください)
- XYの一方を固定値に設定することも可能です
- TSV(Tab Separated Values)テキストは、矩形データを前提とします
- TSVテキスト: 月次売上集計、月次アクセス集計、など
- 矩形でないデータは、空文字によって自動整形されます
- 空行(末尾改行を含む)は無視されます
- 数値列は、カンマ(桁区切り文字)を除去したうえで、JavaScript `parseFloat()` で解析されます
- 正負符号、数値、小数点 (.)、指数記号、および `Infinity` が認識可能です
- (以外の文字に遭遇したら、その文字の前までの値を返します)
- 数値に変換できなかった場合は、「デフォルト値」にて計算されます
- XYに列IDを指定しなかった場合は、「デフォルト値」にて計算されます(固定値)
- 「デフォルト値」も未設定だった場合、 `#N/A` が出力されます
- 除算時にYの値が "0" だった場合、 `#DIV/0!` が出力されます
- 出力TSVの並び順を変更したい場合は、ワークフロー下流に『TSV 文字列, 変換』を配置します。
- https://support.questetra.com/ja/addons/tsv-string-convert-2021/
### APPENDIX
- If the first line is a header row, the column name of the calculation result will be the operator name.
- "add", "subtract", "multiply", "divide", "remainder" or "power"
- e.g.: Add column A (column ID: "0") and column B (column ID: "1")
- Operator: `Addition: X+Y`
- Column ID of X: `0`
- Column ID of Y: `1`
- e.g.: Calculate 1.1 times the value of column C (column ID: "2")
- Operator: `Multiplication: X*Y`
- Column ID of X: `2`
- Default value of X: `0`
- Column ID of Y: `null` (not set)
- Default value of Y: "1.1"
### APPENDIX-ja
- 1行目がヘッダ行の場合、計算結果列の列名は演算子名となります
- "add", "subtract", "multiply", "divide", "remainder", "power"
- eg: A列(列ID:"0")とB列(列ID:"1") の加算
- 演算子: `加算: X+Y`
- Xの列ID: `0`
- Yの列ID: `1`
- eg: C列 (列ID:"2") の値の1.1倍を計算
- 演算子: `乗算: X*Y`
- Xの列ID: `2`
- Xのデフォルト値: `0`
- Yの列ID: `null` (未設定)
- Yのデフォルト値: `1.1`
*/
Download
- tsv-string-basic-math-on-numeric-column-2025.xml
- 2025-07-02 (C) Questetra, Inc. (MIT License)
自由改変可能な JavaScript (ECMAScript) コードです。いかなる保証もありません。
(アドオン自動工程のインストールは Professional editionでのみ可能です)
(アドオン自動工程のインストールは Professional editionでのみ可能です)
Notes
- 案件プロセスがこの自動工程に到達した際、TSVテキストが読み込まれ「計算処理」が自動実行されます
- 計算結果が最右列に列追加されたTSVが出力されます
- 数値列Xと数値列Yによる二項演算が設定可能です(列IDはゼロ始まりで設定してください)
- XYの一方を固定値に設定することも可能です
- TSV(Tab Separated Values)テキストは、矩形データを前提とします
- TSVテキスト: 月次売上集計、月次アクセス集計、など
- 矩形でないデータは、空文字によって自動整形されます
- 空行(末尾改行を含む)は無視されます
- 数値列は、カンマ(桁区切り文字)を除去したうえで、JavaScript
parseFloat()で解析されます- 正負符号、数値、小数点 (.)、指数記号、および
Infinityが認識可能です - (以外の文字に遭遇したら、その文字の前までの値を返します)
- 数値に変換できなかった場合は、「デフォルト値」にて計算されます
- XYに列IDを指定しなかった場合は、「デフォルト値」にて計算されます(固定値)
- 「デフォルト値」も未設定だった場合、
#N/Aが出力されます - 除算時にYの値が “0” だった場合、
#DIV/0!が出力されます
- 正負符号、数値、小数点 (.)、指数記号、および
- 出力TSVの並び順を変更したい場合は、ワークフロー下流に『TSV 文字列, 変換』を配置します。
Capture


Appendix
- 1行目がヘッダ行の場合、計算結果列の列名は演算子名となります
- “add”, “subtract”, “multiply”, “divide”, “remainder”, “power”
- eg: A列(列ID:”0″)とB列(列ID:”1″) の加算
- 演算子:
加算: X+Y - Xの列ID:
0 - Yの列ID:
1
- 演算子:
- eg: C列 (列ID:”2″) の値の1.1倍を計算
- 演算子:
乗算: X*Y - Xの列ID:
2 - Xのデフォルト値:
0 - Yの列ID:
null(未設定) - Yのデフォルト値:
1.1
- 演算子:
