範囲選択されているセルを取得し、順番に処理する - Excel

Office Scriptsを利用して、範囲選択されているセルを取得し、順番に処理するコードを紹介します。

概要

Office Scriptsで選択されている範囲のセルを順番に処理したい場合があります。
選択範囲を取得するには、workbook.getSelectedRange() メソッドで選択範囲を取得し、選択範囲の行数と列数をgetRowCount(), getColumnCount()で求め、 ループでgetCell() メソッドを呼び出し処理します。

実装例

下図の表を用意します。1から30までの数値がセルに入力されています。
12345
678910
1112131415
1617181920
2122232425
2627282930


コード

Office Scriptsを作成し、以下のコードを記述します。
function main(workbook: ExcelScript.Workbook) {
    let selectedRange: ExcelScript.Range = workbook.getSelectedRange();
    let rowCount = selectedRange.getRowCount();
    let colCount = selectedRange.getColumnCount();

    let ResultText:string = "";

    for (let i = 0; i < rowCount; i++) {
        for (let j = 0; j < colCount; j++) {
            let cell: ExcelScript.Range = selectedRange.getCell(i, j);
            let cellnum:number = cell.getValue() as number;
            cellnum++;
            cell.setValue(cellnum);
        }
    }
}


解説

workbook.getSelectedRange() メソッドを呼び出し、選択されている範囲を取得し、selectedRange変数に代入します。
    let selectedRange: ExcelScript.Range = workbook.getSelectedRange();

選択範囲のExcelScript.Rangeオブジェクトの、getRowCount() getColumnCount() メソッドを呼び出し、選択されている範囲の行数と列数を求めます。
    let rowCount = selectedRange.getRowCount();
    let colCount = selectedRange.getColumnCount();

for ループでループ変数の値を、0からrowCount、colCount まで変化させて選択範囲のセルを一つずつアクセスします。
    for (let i = 0; i < rowCount; i++) {
        for (let j = 0; j < colCount; j++) {
          /* 略 */
        }
    }

ループ内の処理は以下のコードです。
selectedRange.getCell()メソッドでセルのオブジェクトを取得します。パラメーターの値が (0,0) の場合は、選択範囲の一番左上のセルが選択されます。 パラメータの値をループ変数にすることで、選択範囲のセルを一つずつ順番に取得できます。
取得したセルのオブジェクトをcell変数に代入します。セルの値を getValue() メソッドっで取得します。 今回は数値として取得するため、as number を記述して、nmumber型の変数に代入しています。
数値に1を加算し、元のセルにsetValue()メソッドで値を設定しなおします。

この処理により、スクリプトを実行すると、選択されている範囲のセルの数値に1が加算される動作になります。
    let cell: ExcelScript.Range = selectedRange.getCell(i, j);
    let cellnum:number = cell.getValue() as number;
    cellnum++;
    cell.setValue(cellnum);

実行結果

セルを選択した状態で、コードエディターの[実行]ボタンをクリックして、Office Scritpsを実行します。


スクリプトを実行すると下図の画面になります。選択したセルの数値に1が足された値になります。


選択したセルに対して処理が実行できました。

補足:数値でないセルの値の場合の実行結果

選択範囲に数値でないセル(下図のD7セルに"A"が、D8セルに"B")が入力されている場合にどのような結果になるか確認します。


スクリプトを実行すると下図の結果になります。アルファベットが入力されていたセルは空になります。

パフォーマンス改善

上記のコードですが、forループ内の getValue() メソッドにオレンジ色の波線が表示されています。 これはアラートのメッセージです。マウスオーバーすると、以下のメッセージが表示されます。


ワーニング メッセージ
Invoking read methods inside of a loop could lead to slow performance of the script. For more information, please visit https://aka.ms/office-scripts-performance(Office Scripts Error)

ループで複数回 getValue() メソッドを呼び出すことはパフォーマンスの低下になるとのアラートです。
対処方法は、getValues() メソッドを呼び出し、選択範囲の値をまとめて一度の呼び出しで値を取得します。
以下のコードに変更します。



修正コード
function main(workbook: ExcelScript.Workbook) {
    let selectedRange: ExcelScript.Range = workbook.getSelectedRange();
    let rowCount = selectedRange.getRowCount();
    let colCount = selectedRange.getColumnCount();

    let ResultText:string = "";
    let values = selectedRange.getValues()

    for (let i = 0; i < rowCount; i++) {
        for (let j = 0; j < colCount; j++) {
          let cellnum: number = values[i][j] as number;
          cellnum++;
          let cell: ExcelScript.Range = selectedRange.getCell(i, j);
          cell.setValue(cellnum);
        }
    }
}
または、
修正コード
function main(workbook: ExcelScript.Workbook) {
    let selectedRange: ExcelScript.Range = workbook.getSelectedRange();
  
    let ResultText:string = "";
    let values = selectedRange.getValues()

    for (let i = 0; i < values.length; i++) {
        for (let j = 0; j < values[i].length; j++) {
          let cellnum: number = values[i][j] as number;
          cellnum++;
          let cell: ExcelScript.Range = selectedRange.getCell(i, j);
          cell.setValue(cellnum);
        }
    }
}

getValues()した段階でnumber型として扱う場合は以下のコードで記述することもできます。
修正コード
function main(workbook: ExcelScript.Workbook) {
    let selectedRange: ExcelScript.Range = workbook.getSelectedRange();

    let ResultText:string = "";
    let values:number[][] = selectedRange.getValues() as number[][];

    for (let i = 0; i < values.length; i++) {
      for (let j = 0; j < values[i].length; j++) {
        let cellnum: number = values[i][j];
        cellnum++;
        let cell: ExcelScript.Range = selectedRange.getCell(i, j);
        cell.setValue(cellnum);
      }
    }
}

ループの手前で、getValues()メソッドで選択範囲の値をまとめて取得します。値は2次元の配列で取得できます。
let values = selectedRange.getValues()
let values:number[][] = selectedRange.getValues() as number[][];

ループ内の処理は同様です。getValueメソッドで値を取得するのではなく、values変数の2次元配列から値を読み取ります。
ループは、values配列の数ループします。getRowCount() getColumnCount() メソッドで選択範囲の行数と列数を取得してループする方法もあります。
    for (let i = 0; i < values.length; i++) {
      for (let j = 0; j < values[i].length; j++) {
        let cellnum: number = values[i][j];
        cellnum++;
        let cell: ExcelScript.Range = selectedRange.getCell(i, j);
        cell.setValue(cellnum);
      }
    }
コードを変更すると、オレンジ色の波線が消えます。


スクリプトを実行して、選択した範囲のセルの値が1増加する、同じ動作になることを確認します。


著者
iPentec.com の代表。ハードウェア、サーバー投資、管理などを担当。
Office 365やデータベースの記事なども担当。
最終更新日: 2024-01-20
作成日: 2023-01-02
iPentec all rights reserverd.