シートから取った配列を並べたい
Google Apps Script(GAS)において、スプレッドシートのデータを操作・処理する機会は非常に多いでしょう。スプレッドシートからgetValues()メソッドを用いてデータを取得すると、GAS側では「二次元配列(配列の中に配列が入ったデータ構造)」としてデータを扱うことになります。
取得したデータを特定の列(例えば、担当者名、売上金額、日付など)を基準にして昇順・降順に並び替えたい場合、GASの標準機能である配列のsort()メソッドを活用します。基本となる単一条件でのソートから、実務で頻出する「複数条件」でのソート方法まで、localeCompare を使っている理由を交えて書きます。
1列だけ基準にする
まずは、単一条件(特定の列にある文字列の昇順)で二次元配列を並び替える基本的なコードとメカニズムを見ていきましょう。
文字列1列での並び替え
const data = [[1, "B"], [2, "A"], [3, "C"]];
data.sort((a, b) => a[1].localeCompare(b[1]));
Logger.log(data);
localeCompare を使っている理由
- 1行目:
const data = [[1, "B"], [2, "A"], [3, "C"]];
この行では、ソートの対象となる二次元配列を定義しています。各要素である一次元配列は、インデックス0に「数値」、インデックス1に「文字列」を持っています。実務においては、スプレッドシートの行データ(1行目、2行目…)に相当します。 - 2行目:
data.sort((a, b) => a[1].localeCompare(b[1]));
ここがソートの要となる処理です。sort()メソッドは、配列内の要素2つ(ここでは変数aとb)を比較しながら並び替えを行います。a[1]およびb[1]は、それぞれの配列の2番目の要素(インデックス1にある文字列)を指しています。文字列同士の比較であるため、localeCompare()メソッドを用いて昇順にソートしています。 - 3行目:
Logger.log(data);
ソート後の配列をログに出力します。実行結果は[[2, "A"], [1, "B"], [3, "C"]]となり、文字列「A」「B」「C」のアルファベット順に配列全体が並び替わっていることが確認できます。
同じ部署の中で金額を下げる
実務においては、「第1条件で担当者名(文字列)を昇順にし、担当者名が同じ場合は第2条件として売上(数値)を降順にする」といった、複数条件でのソートが求められることが多々あります。
複数条件ソートの文字列1列での並び替え
先ほどの基本コードを応用し、複数条件に対応させたコードが以下になります。
const data = [
[1, "B"],
[2, "A"],
[3, "B"],
[4, "A"]
];
data.sort((a, b) => {
// 第1条件: インデックス1の文字列で昇順比較
const stringCompare = a[1].localeCompare(b[1]);
// 文字列が異なる場合は、第1条件の比較結果を採用
if (stringCompare !== 0) {
return stringCompare;
}
// 第2条件: 文字列が同じ場合のみ、インデックス0の数値で降順比較
return b[0] - a[0];
});
Logger.log(data);
部署が同じなら成績の大きい順
このコードでは、まず第1条件としてlocaleCompare()を利用して文字列の比較を行っています。戻り値が0以外(つまり異なる文字列)であれば、その結果をそのままreturnして並び替えを決定します。
もし戻り値が0(文字列が完全に一致)だった場合のみ、IF文を抜けて次の処理へ進み、第2条件である数値の比較(b[0] - a[0])を行います。この仕組みを理解しておけば、条件が3つ、4つと増えても同様にIF文を追加するだけで柔軟に対応可能です。
実務では、スプレッドシートから読み込んだ全社員の成績データ一覧を「部署順(昇順)」>「成績額(降順)」でソートして日報を自動作成する、といった自動化スクリプトで非常に強力な武器となります。
sort が元データを壊す
GASで配列のソート処理を実装する上で、初学者が陥りやすい重要な仕様とエラー対策を3つ解説します。
1. sort()は「破壊的メソッド」である
JavaScriptおよびGASの仕様において、sort()メソッドは破壊的メソッドと呼ばれます。これは、戻り値として新しい配列を作成して返すのではなく、元の配列データそのものを直接書き換えてしまうという性質を指します。
もし、ソート前の元の配列データも別の用途(元の順番での保存など)で保持しておきたい場合は、意図しないデータの上書きを防ぐために注意が必要です。その場合は、以下のようにスプレッド構文などを用いて元の配列をコピー(シャローコピー)してからソートを行う対策が有効です。
// 元の配列を維持し、新しい配列を作成してソートする対策例
const sortedData = [...data].sort((a, b) => a[1].localeCompare(b[1]));
2. 文字列と数値の比較方法の明確な違い
ソート対象のデータ型(数値か文字列か)によって、適切な比較演算を使い分ける必要があります。間違った比較方法を用いると、例えば数値の「10」が「2」より前に来てしまうなどの致命的なバグが発生します。
| データ型 | 昇順の書き方 | 降順の書き方 | メカニズムと解説 |
|---|---|---|---|
| 数値 | a[0] - b[0] |
b[0] - a[0] |
単純な引き算の演算結果(正の数、負の数、ゼロ)を利用して順序を決定します。直感的に記述できます。 |
| 文字列 | a[1].localeCompare(b[1]) |
b[1].localeCompare(a[1]) |
localeCompareを使用することで、辞書順での正確な比較が可能になります。日本語(ひらがなや漢字)を含む文字列のソートには必須のメソッドです。 |
3. よくあるエラー:空データや未定義値の混入
スプレッドシートの最終行までデータを取得した際、空の行や未定義(undefined)のデータが混入していると、ソート実行時にエラーが発生することがあります。
例えば、a[1]が空である場合、a[1].localeCompareを実行しようとしてTypeError: Cannot read properties of undefinedというエラーが表示され、スクリプトが停止します。これを防ぐためには、ソートを実行する前にfilter()メソッドを使用して空白行を除外するデータのクレンジングを行うことが推奨されます。
// 空白行を除外してからソートする対策例
const safeData = data.filter(row => row[1] !== "");
safeData.sort((a, b) => a[1].localeCompare(b[1]));
数値は引き算、文字は localeCompare
GASにおいて二次元配列を特定の列でソートする技術は、スプレッドシートのデータ操作を自動化する上で避けては通れない非常に重要なテクニックです。
本記事で紹介したように、数値には引き算、文字列にはlocaleCompare()を用いるという基本を押さえ、sort()が破壊的メソッドであるという仕様に十分注意して実装を行ってください。これらの基本仕様を理解し、複数条件のソートロジックを組み合わせることで、実務における複雑なデータ処理もスムーズかつ正確に解決できるでしょう。

