SpreadJSでTRIMRANGE関数とトリム参照を使う

2025年7月2日にリリースされた「SpreadJS(スプレッドJS)」の最新バージョン「V18.1J」では、2024年にExcelに追加されたTRIMRANGE関数とトリム参照と同等の機能が搭載されました。この機能を使うことで、指定範囲の先頭側または末尾側にある空白セルを計算対象から取り除くことができます。

本記事では、この「TRIMRANGE関数」と「トリム参照」の基本的な動作や実際のアプリケーションで活用できる使用例について解説します。

TRIMRANGE関数とは

TRIMRANGE関数は、先頭側または末尾側にある空白セルを計算対象から取り除きます。

この関数の構文と引数は次のとおりです。

=TRIMRANGE(range,[trim_rows],[trim_cols])
引数説明
rangeトリミングする範囲(または配列)
trim_rows(オプション)トリミングする行
0:なし
1:先頭の空白行
2:末尾の空白行
3:先頭および末尾の空白行(既定値)
trim_cols(オプション)トリミングする列
0:なし
1:先頭の空白列
2:末尾の空白列
3:先頭および末尾の空白列(既定値)

例えば10行を表示したシートのA列でA4セル、A6セル、A8セルにだけ値が設定されている場合を考えます。このときB1セルに数式「ROWS(A:A)」を設定すると、シート上のすべての行数である「10」がB1セルに表示されます。

TRIMRANGE関数を使用しない例

次に、ROWS関数の引数としてセル範囲「A:A」の代わりにTRIMRANGE関数の戻り値を渡すようにした数式「ROWS(TRIMRANGE(A:A,3,0))」をB2セルに設定します。この場合は、TRIMRANGE関数の機能が働いてA4セルよりも上の行とA8セルよりも下の行が除外され、B2セルには「5」が表示されます。

TRIMRANGE関数の使用例

トリム参照とは

トリム参照は、TRIMRANGE関数を明示的に使用しないで先頭側または末尾側にある空白セルを計算対象から除外するための簡略記法です。

この記法では、従来のコロン(:)範囲演算子にドット(.)を追加することで、範囲の除外方法を指定します。トリム参照には以下の3種類があります。

トリム参照タイプ構文等価なTRIMRANGE関数説明
すべてトリムA1.:.E10=TRIMRANGE(A1:E10, 3, 3)先頭および末尾の空白をトリミング
末尾をトリムA1:.E10=TRIMRANGE(A1:E10, 2, 2)末尾の空白のみをトリミング
先頭をトリムA1.:E10=TRIMRANGE(A1:E10, 1, 1)先頭の空白のみをトリミング

B3セルに、ROWS関数の引数にトリム参照を使ってセル範囲を指定した数式「ROWS(A.:.A)」を設定すると、トリム参照の機能が働いてA4セルよりも上の行とA8セルよりも下の行が除外され、B3セルには「5」が表示されます。

この動作は、ROWS関数の引数としてTRIMRANGE関数の戻り値を渡した場合と同じです。

TRIM参照

SpreadJSを使用して実用例を解説

先ほどのROWS関数の例では、TRIMRANGE関数やトリム参照の便利さをそれほど実感できない方もいらっしゃるかもしれません。ここでは、デモで紹介している3種類の実用的な機能を実装したサンプルを作成します。

実装する機能は次のとおりです。これらすべての機能でTRIMRANGE関数/トリム参照を使用します。

開発環境

事前準備

今回作成するファイルは次の4つです。

index.htmlページ本体。ページの要素としてSpreadJSコントロールを配置します
app.jsSpreadJSコントロールを作成するコードを記載します
data.jsSpreadJSコントロールに表示するデータを記載します
styles.css各種ページ要素のスタイル定義を記載します

SpreadJSコントロールの使用にはSpreadJSのモジュールを環境に配置する必要があります。npmなどから入手する方法もありますが、今回は環境に直接SpreadJSのモジュールを配置していきます。あらかじめSpreadJSの製品版かトライアル版をご用意ください。トライアル版は以下より無償で入手可能です。

  • scripts/gc.spread.sheets.all.18.1.4.min.js
  • scripts/resources/gc.spread.sheets.resources.ja.18.1.4.min.js
  • css/gc.spread.sheets.excel2013white.18.1.4.css

TRIMRANGE関数とトリム参照を実装する

それでは、SpreadJSコントロールを作成してTRIMRANGE関数とトリム参照を実装しましょう。

最初に、SpreadJSライブラリの参照設定をHTMLファイルに追加します。SpreadJSのモジュールに加えて、前述の「app.js」、「data.js」、「styles.css」への参照も追加します。また設定した数式が確認できるように、SpreadJSを表示する領域に加えて、数式テキストボックスを表示する領域も定義します。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <link href="css/gc.spread.sheets.excel2013white.18.1.4.css" rel="stylesheet"/>
    <script src="scripts/gc.spread.sheets.all.18.1.4.min.js"></script>
    <script src="scripts/resources/gc.spread.sheets.resources.ja.18.1.4.min.js"></script>
    <link href="css/styles.css" rel="stylesheet"/>
    <script src="scripts/data.js"></script>
    <script src="scripts/app.js"></script>
</head>
<body>
    <div id="ft" contenteditable="true"></div>
    <div id="ss"></div>
</body>
</html>

続いて「app.js」と「data.js」および「styles.css」を次のように作成します。
※ ライセンスキーを設定しない場合、トライアル版を示すメッセージが表示されます。ライセンスキーの設定方法についてはこちらをご覧ください。

// ライセンスキーとカルチャの設定
GC.Spread.Sheets.LicenseKey = 'ここにSpreadJSのライセンスキーを設定します';
GC.Spread.Common.CultureManager.culture('ja-jp');

window.onload = () => {
    // SpreadJSの生成
    const spread = new GC.Spread.Sheets.Workbook("ss");
    spread.options.allowDynamicArray = true;
    spread.setSheetCount(2);

    // 数式テキストボックスの生成
    const formulaTextBox = new GC.Spread.Sheets.FormulaTextBox.FormulaTextBox(
        document.getElementById("ft")
    );
    formulaTextBox.workbook(spread);

    // sheet1の設定
    const sheet1 = spread.getSheet(0);
    const data = getData();
    const colInfos = [
        { name: '', displayName: 'ID', size: 50 },
        { name: 'date', displayName: '日付', formatter: 'yyyy/MM/dd', size: 120 },
        { name: 'inbound', displayName: '入庫', size: 100 },
        { name: 'outbound', displayName: '出庫', size: 100 },
        { name: '', displayName: '在庫', size: 100 },
        { name: 'note', displayName: '特記事項', size: 120 }
    ];
    sheet1.autoGenerateColumns = false;
    sheet1.bindColumns(colInfos);
    sheet1.setDataSource(data);
    sheet1.getRange(-1, 1, -1, 1).hAlign(GC.Spread.Sheets.HorizontalAlign.center);
    sheet1.getRange(-1, 5, -1, 1).hAlign(GC.Spread.Sheets.HorizontalAlign.center);

    // 【TRIMRANGE関数を使用しない場合】
    // sheet1.getCell(0,0).formula('SEQUENCE(ROWS(B:F),1)');
    // sheet1.getCell(0,4).formula('INDEX(SCAN(0,C:C-D:D,SUM),A:A)');
    // const validation = GC.Spread.Sheets.DataValidation;
    // const formula = 'sheet2!A:A';
    // const validator = new validation.createFormulaListValidator(formula);
    // sheet1.getRange(-1, 5, -1, 1).validator(validator);

    // 【TRIMRANGE関数を使用する場合】
    sheet1.getCell(0, 0).formula('SEQUENCE(ROWS(TRIMRANGE(B:F,2,0)),1)');
    sheet1.getCell(0, 4).formula('INDEX(SCAN(0,C:C-D:D,SUM),TRIMRANGE(A:A,2,0))');
    const validation = GC.Spread.Sheets.DataValidation;
    const formula = 'TRIMRANGE(sheet2!A:A,2,0)';
    const validator = new validation.createFormulaListValidator(formula);
    sheet1.getRange(-1, 5, -1, 1).validator(validator);

    // 【トリム参照を使用する場合】
    // sheet1.getCell(0,0).formula('SEQUENCE(ROWS(B:.F),1)');
    // sheet1.getCell(0,4).formula('INDEX(SCAN(0,C:C-D:D,SUM),A:.A)');
    // const validation = GC.Spread.Sheets.DataValidation;
    // const formula = 'sheet2!A:.A';
    // const validator = new validation.createFormulaListValidator(formula);
    // sheet1.getRange(-1, 5, -1, 1).validator(validator);

    // sheet2の設定
    const sheet2 = spread.getSheet(1);
    sheet2.setColumnCount(1);
    sheet2.setColumnWidth(0, 140);
    sheet2.setRowCount(10);
    sheet2.setValue(0, 0, "特記事項のリスト", GC.Spread.Sheets.SheetArea.colHeader);
    sheet2.setValue(0, 0, " ");
    sheet2.setValue(1, 0, "輸入");
    sheet2.setValue(2, 0, "輸出");
    sheet2.setValue(3, 0, "輸入+輸出");
}
const getData = () => {
  return [
    { date: '2025/8/1', inbound: 100, outbound: 10 },
    { date: '2025/8/4', outbound: 20 },
    { date: '2025/8/5', outbound: 30 },
    { date: '2025/8/6', inbound: 200, note: '輸入' },
    { date: '2025/8/7', outbound: 20 },
    { date: '2025/8/8', outbound: 100, note: '輸出' },
    { date: '2025/8/12', outbound: 60 },
    { date: '2025/8/18', inbound: 100, outbound: 50, note: '輸入+輸出' },
    { date: '2025/8/19', outbound: 20 },
    {},
    {},
    {},
    {},
    {},
    {}
  ];
}
/* 数式テキストボックスのスタイル */
#ft {
   width: 690px;
   height: 25px;
   border: 1px solid silver !important;
   margin-bottom: 10px;
   padding: 5px;
   font-family: Meiryo;
}

/* SpreadJSのスタイル */
#ss {
   width: 700px;
   height: 350px;
   border: 1px solid silver;
}

以上で、アプリケーションが完成しました。以降では、TRIMRANGE関数/トリム参照を使った各機能について見ていきます。

オートナンバー

アプリケーションを実行してID列のA1セルをクリックすると、上部の数式テキストボックスに数式が表示されます。

オートナンバー

A1セルには下記のコードで数式が設定されています。これによりID列では、動的配列数式のSEQUENCE関数を使ったオートナンバーを実現しています。

・・・(中略)・・・
sheet1.getCell(0, 0).formula('SEQUENCE(ROWS(TRIMRANGE(B:F,2,0)),1)');
・・・(中略)・・・

SEQUENCE関数内に設定されているROWS関数の引数でTRIMRANGE関数を使用しない場合は、以下のようにID列のすべての行に連番が設定されてしまいます。

TRIMRANGE関数を使用しない例(1)
TRIMRANGE関数を使用しない場合はID列のすべての行に連番が設定されてしまう

一方、TRIMRANGE関数を使えば最初の画像のように末尾の空白行には連番が設定されなくなります。

ここで、日付列のB10セルに「2025/08/20」を入力してEnterキーを押下すると、次のようにID列の連番が自動的に追加されます。

在庫の自動計算

在庫列のE1セルをクリックすると、数式テキストボックス内の数式が下のようになります。

在庫の自動計算

E1セルにはINDEX関数と動的配列数式のSCAN関数を使った数式が設定されており、これにより在庫列のセルでは「直前の在庫数+入庫数-出庫数」が自動計算されます。この数式は、下記のコードで設定しています。

・・・(中略)・・・
sheet1.getCell(0, 4).formula('INDEX(SCAN(0,C:C-D:D,SUM),TRIMRANGE(A:A,2,0))');
・・・(中略)・・・

INDEX関数の第2引数でTRIMRANGE関数を使用しない場合は、ID列が空白の行にも在庫が表示されてしまいます。

TRIMRANGE関数を使用しない例(2)
TRIMRANGE関数を使用しない場合はID列が空白の行にも在庫が表示されてしまう

一方、TRIMRANGE関数を使うことで空白行に不要な在庫が表示されることがなくなります。

アプリケーションの実行直後に出庫列のD10セルに「10」を入力してEnterキーを押下すると、次のように10行目の在庫が自動的に計算されます。

数式リスト検証

特記事項列のF8セルをクリックすると、数式リスト検証の機能が働いて入力可能なリストが表示されます。

数式リスト検証

数式リスト検証を使った入力規則ではDataValidation名前空間のcreateFormulaListValidator関数のコンストラクタで引数としてセル範囲を渡します。

特記事項列に数式リスト検証を設定するコードは次のとおりです。

・・・(中略)・・・
const validation = GC.Spread.Sheets.DataValidation;
const formula = 'TRIMRANGE(sheet2!A:A,2,0)';
const validator = new validation.createFormulaListValidator(formula);
sheet1.getRange(-1, 5, -1, 1).validator(validator);
・・・(中略)・・・

このコードでは、数式リスト検証のリストとしてsheet2のA列のすべてのセルを対象としていますが、TRIMRANGE関数を使うことで対象範囲にあるA5からA10までの不要なセルを除外しています。

数式リスト検証

TRIMRANGE関数を使用しない場合は、余分な空白データがリストに追加されてしまいます。

TRIMRANGE関数を使用しない例(3)
TRIMRANGE関数を使用しない場合は余分な空白データがリストに追加されてしまう

以上、TRIMRANGE関数を使う場合を例に説明してきましたが、「app.js」でコメントアウトする箇所を次のように変更してトリム参照を使った場合にも全く同じ動作になります。

・・・(中略)・・・
    // 【TRIMRANGE関数を使用する場合】
    // sheet1.getCell(0, 0).formula('SEQUENCE(ROWS(TRIMRANGE(B:F,2,0)),1)');
    // sheet1.getCell(0, 4).formula('INDEX(SCAN(0,C:C-D:D,SUM),TRIMRANGE(A:A,2,0))');
    // const validation = GC.Spread.Sheets.DataValidation;
    // const formula = 'TRIMRANGE(sheet2!A:A,2,0)';
    // const validator = new validation.createFormulaListValidator(formula);
    // sheet1.getRange(-1, 5, -1, 1).validator(validator);

    // 【トリム参照を使用する場合】
    sheet1.getCell(0,0).formula('SEQUENCE(ROWS(B:.F),1)');
    sheet1.getCell(0,4).formula('INDEX(SCAN(0,C:C-D:D,SUM),A:.A)');
    const validation = GC.Spread.Sheets.DataValidation;
    const formula = 'sheet2!A:.A';
    const validator = new validation.createFormulaListValidator(formula);
    sheet1.getRange(-1, 5, -1, 1).validator(validator);
・・・(中略)・・・

今回ご紹介した内容については以下のデモアプリケーションで確認できます(“Run Project”をクリックするとデモが起動します)。

さいごに

今回の記事では、「SpreadJS」の「TRIMRANGE関数」と「トリム参照」の機能と使用方法について解説しました。

製品サイトでは、SpreadJSの機能を手軽に体験できるデモアプリケーションやトライアル版も公開しておりますので、こちらもご確認ください。

また、ご導入前の製品に関するご相談、ご導入後の各種サービスに関するご質問など、お気軽にお問合せください。

\  この記事をシェアする  /