※本記事はプロモーションを含みます
目次
結合のままだと集計がずれる
Googleスプレッドシートにおいて、見た目を美しく整えるために人間がセル結合を利用するケースは非常に多いです。なので、特に日本企業の業務においては、帳票やレポートの視認性を高める目的で、ヘッダー行や備考欄が複雑に結合されたシートが頻繁に作成されます。
ただし、人間が見やすいように結合されたシートを、プログラムで処理しやすい表形式データに直す前処理として、セル結合の解除は必須のプロセスとなります。というのは、GAS(Google Apps Script)を用いてデータを二次元配列として取得し、集計や外部データベースへのエクスポートを行う際、結合されたセルが混ざっていると、行と列のインデックスにズレが生じてプログラムが意図した通りに動作しなくなるからです。なので、この課題を解決するための実装方法と、確認すべき注意点について解説します。
範囲の結合を外す
GASを用いて結合されたセルを解除するには、Rangeオブジェクトに対して用意されているbreakApart()メソッドを使用します。なので、まずは最も基本となるA1:C1を解除する処理を確認しましょう。
A1:C1 を解除する
const sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange("A1:C1").breakApart();
getRange のあとに breakApart
2行のシンプルなコードですが、それぞれの役割を正確に理解しておくことが重要です。
- 1行目:
const sheet = SpreadsheetApp.getActiveSheet();
この行では、スプレッドシートの中で現在アクティブになっている(ユーザーが開いて操作している)シートのオブジェクトを取得し、定数sheetに格納しています。もし特定の名前を持つシートを対象にしたい場合は、SpreadsheetApp.getActiveSpreadsheet().getSheetByName("シート名")という記述に変更することで、柔軟に対応可能です。 - 2行目:
sheet.getRange("A1:C1").breakApart();
取得したシートオブジェクトに対して、getRange("A1:C1")メソッドで操作対象のセル範囲(ここではA列1行目からC列1行目まで)を指定しています。探した指定範囲に対してbreakApart()メソッドを呼び出しています。これにより、指定範囲内に存在するセルの結合状態が解除されます。
ただし、範囲指定の方法はA1記法だけでなく、getRange(1, 1, 1, 3)(1行目の1列目から、1行分、3列分の範囲)のように数値のインデックスを用いた指定も可能です。なので、ループ処理の中で動的に範囲を変えたい場合は、こちらのインデックス指定が多用されます。
値は左上だけ残る
セル結合の解除をプログラムで自動化するにあたり、breakApart()メソッドの特有の仕様を正確に把握しておく必要があります。
1. 対象範囲内に含まれる結合状態をすべて解除します
breakApart()メソッドを実行すると、プログラムが指定した範囲内に含まれるすべての結合セルを検知して、一括でバラバラの単一セルに戻します。たとえば、getRange("A1:D10")のように広い範囲を指定した場合、その範囲内に「A1:B2」の結合と「C3:D5」の結合が点在していたとしても、プログラムがそれらをすべて一度の実行で解除します。なので、非常に強力で便利な挙動と言えます。
2. 解除後、結合時の値は左上のセルにのみ配置されます
この仕様は、データの整形において最も重要です。というのは、セル結合を解除した後、結合されていた範囲に表示されていた値(文字列や数値)が移動するからです。GASの仕様では、解除後、結合時の値は左上のセルにのみ配置されます。
例えば、「A1:C1」が結合されていて「売上実績」という文字列が入っていたとします。ただし、この結合を解除すると、「売上実績」という文字列は「A1」セルにのみ残り、「B1」および「C1」セルは空白のセルとなってしまいます。
| 状態 | A1 | B1 | C1 |
|---|---|---|---|
| 結合時(A1:C1) | 売上実績 | ||
| 解除後(breakApart実行) | 売上実績 | (空白) | (空白) |
データベースの世界では「1セル=1データ」が原則です。なので、解除したことによって生じた「B1」や「C1」の空白セルをそのままにしておくと、後のデータ抽出処理でプログラムが「空のデータ」として扱ってしまいます。というのは、実務においては解除した直後に、空白となったセルに対して左上のセルの値をコピーして埋め合わせる補完ロジックを組み込むのが一般的な手法だからです。
取り込み前に結合を外す
では、実際のビジネス現場において、このスクリプトはどのようなフローで活用されるのでしょうか。代表的なのは「各部署から集まった申請書(スプレッドシート)を読み込み、社内システムに取り込む」といったシナリオです。
多くの場合、入力用の申請書フォーマットはレイアウト重視で作られており、至る所にセル結合が施されています。なので、このデータをシステムに取り込むための手順は次のようなステップになります。
- バックアップと作業用シートの生成:原本データを破壊しないよう、対象シートを別名でコピーして一時的な作業用シートを作成します。
- 結合の全面解除:作業用シートのデータが存在する全範囲(
getDataRange()などを使用)に対して、breakApart()を実行し、すべての結合を解除します。 - 欠損データの補完処理:前述の通り、解除後は左上のセル以外が空白になるため、GASの配列処理を用いて「上のセルが空でなければ、その値を下の空白セルにコピーする」といったアルゴリズムを実行し、データの欠損を埋めます。
- クリーンデータの抽出:きれいな二次元の表形式データ(テーブルデータ)になった状態の値を抽出し、CSV出力やAPI経由でデータベースへ送信します。
このように、breakApart()によるセル結合の解除は、単なる見た目の変更ではありません。なので、システム間連携を成功させるための「データクレンジングの第一歩」として機能します。
結合が無くても呼べてしまう
非常に便利で強力なメソッドですが、実務で運用するスクリプトに組み込む際には、特有の注意点に意識を向ける必要があります。
エラーが出ないことによる不要なAPI呼び出し
注意点: 範囲内に結合セルが存在しない場合に実行してもエラーにはなりませんが、不要なAPI呼び出しとなるため注意が必要です。
GASにおいて、スプレッドシートの操作(SpreadsheetAppクラスを介した各種メソッドの実行)は、Googleのサーバーとシート本体との間で通信を発生させる「API呼び出し」に該当します。なので、この通信は、JavaScript内での純粋な計算処理(配列の操作など)と比較して、非常に処理時間がかかります。
breakApart()メソッドは、指定した範囲に結合セルがひとつも含まれていなかったとしても、エラーを出して停止することはありません。プログラムが正常に終了するので、開発者は「とりあえずシート全体に毎回実行しておけば安心だろう」と考えがちです。
ただし、毎回広大な範囲に対して不要なAPI呼び出しを繰り返すと、スクリプト全体の実行時間が少しずつ延びていきます。というのは、GASには「1回のスクリプト実行時間は最大6分間」という厳格な制限があるため、不要なAPI呼び出しが蓄積することでタイムアウトエラーを引き起こす原因となり得るからです。
落とし穴を回避するための対策
このパフォーマンス低下を防ぐためには、メソッドを盲目的に実行するのではなく、実行範囲をまとめて処理することが求められます。なので、シート全体ではなく「結合が含まれている可能性が高いヘッダー部分の数行にのみ実行する」など、必要最小限の範囲に絞ってbreakApart()を呼び出す設計を心掛けましょう。確認しながら実装を進めることで、高速で安定したスクリプトを構築できます。
外してから配列で触る
Google Apps Scriptを用いてスプレッドシートのセル結合を解除する実装方法について、基本コードから詳細な仕様、そして実務上の注意点まで解説しました。
人間にとって優しい結合セルも、システム開発においてはデータの不整合を招く存在となります。ただし、breakApart()メソッドの「解除後の値は左上のみに残る」という仕様や、「不要な呼び出しによるパフォーマンス低下」という注意点を正しく理解し、適切に対処することで、どんなに複雑なシートであっても自在に正規化することが可能になります。なので、結合は外してから配列で触るようにしましょう。

