GASでGoogleスプレッドシートの複数シートを一括編集|エクセルの作業グループ代替

「エクセルのように、Google スプレッドシートで複数のシートを一括編集できたら便利なのに…」と思ったことはありませんか?

エクセルの「作業グループ」機能では、複数のシートを選択して同時編集できますが、Googleスプレッドシートには同様の機能がありません。

そのため、シートごとに手作業でコピー&ペーストをする必要があり、シート数が多いと手間がかかります。

そこで、本記事ではGoogle Apps Script(GAS)を使って、複数シートを一括編集する方法をご紹介します。

データや書式をまとめてコピーできるため、エクセルの作業グループ機能の代替手段として活用できます。

目次

完成イメージ

  • コピー元の範囲を選択し、「更新」ボタンで確定
  • サイドバーでコピー先のシートを選択
  • 「データを貼り付け」ボタンで一括反映

スクリプトを実行すると、サイドバーが表示されます。

その中でコピーするデータと貼り付け先を選択して一括反映します。

手順

STEP
スプレッドシートを開く

一括編集したいデータのあるスプレッドシートを開きます。

STEP
一括入力したい元データを範囲選択

基準となるシートにデータを入力します。

その後、他のシートにもデータを反映させたい範囲を選択します。

(例えば、シート1 A2:A4 で入力したデータを、GASで他のシートの A2:A4 にコピーします。)

STEP
GASエディタを開く

Googleスプレッドシートを開き、メニューの「拡張機能」から「Apps Script」をクリックしてGASエディタを開きます。

STEP
メインスクリプト(.gs ファイル)を作成

function myFunction(){

}

が最初から入っているため、消去して以下のスクリプトを貼り付けます。

function showSheetSelector() {
  var html = HtmlService.createHtmlOutputFromFile('SheetSelector')
      .setWidth(300)
      .setHeight(500);
  SpreadsheetApp.getUi().showSidebar(html);
}

function getSheetNames() {
  var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
  return sheets.map(sheet => sheet.getName());
}

// 「更新」ボタンを押したときにコピー元のデータをプロパティに保存
function storeSelectedRangeInfo() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getActiveSheet();
  var range = sheet.getActiveRange();

  if (!range) {
    return { sheetName: sheet.getName(), range: "範囲が選択されていません" };
  }

  var rangeInfo = {
    sheetName: sheet.getName(),
    rangeA1: range.getA1Notation(),
    values: JSON.stringify(range.getValues()),
    backgrounds: JSON.stringify(range.getBackgrounds()),
    fontWeights: JSON.stringify(range.getFontWeights()),
    fontColors: JSON.stringify(range.getFontColors()),
    numberFormats: JSON.stringify(range.getNumberFormats()),
    horizontalAlignments: JSON.stringify(range.getHorizontalAlignments()),
    verticalAlignments: JSON.stringify(range.getVerticalAlignments()),
    startRow: range.getRow(),
    startColumn: range.getColumn(),
    numRows: range.getNumRows(),
    numCols: range.getNumColumns()
  };

  // プロパティストアに保存
  PropertiesService.getScriptProperties().setProperty("storedRangeInfo", JSON.stringify(rangeInfo));

  return { sheetName: sheet.getName(), range: range.getA1Notation() };
}

// 「データをコピー」ボタンを押したときに、保存したデータを取得してコピー
function copyStoredDataToSheets(selectedSheets) {
  var storedData = PropertiesService.getScriptProperties().getProperty("storedRangeInfo");

  if (!storedData) {
    return "コピー元のデータが保存されていません。「更新」ボタンを押してください。";
  }

  var storedRangeInfo = JSON.parse(storedData);
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  selectedSheets.forEach(function(sheetName) {
    var sheet = ss.getSheetByName(sheetName);
    if (sheet) {
      var targetRange = sheet.getRange(
        storedRangeInfo.startRow, 
        storedRangeInfo.startColumn, 
        storedRangeInfo.numRows, 
        storedRangeInfo.numCols
      );

      targetRange.setValues(JSON.parse(storedRangeInfo.values));
      targetRange.setBackgrounds(JSON.parse(storedRangeInfo.backgrounds));
      targetRange.setFontWeights(JSON.parse(storedRangeInfo.fontWeights));
      targetRange.setFontColors(JSON.parse(storedRangeInfo.fontColors));
      targetRange.setHorizontalAlignments(JSON.parse(storedRangeInfo.horizontalAlignments));
      targetRange.setVerticalAlignments(JSON.parse(storedRangeInfo.verticalAlignments));
      targetRange.setNumberFormats(JSON.parse(storedRangeInfo.numberFormats));
    }
  });

  return "データと書式がコピーされました。";
}
スクリプトの説明
showSheetSelector()
function showSheetSelector() {
var html = HtmlService.createHtmlOutputFromFile('SheetSelector')
.setWidth(300)
.setHeight(500);
SpreadsheetApp.getUi().showSidebar(html);
}
  • サイドバーを表示し、コピー元・コピー先のシートを選択できるようにします。
  • HtmlService.createHtmlOutputFromFile('SheetSelector')SheetSelector.html のUIをロード。
  • SpreadsheetApp.getUi().showSidebar(html) でスプレッドシートのサイドバーとして表示。
getSheetgetSheetNames()Names()
function getSheetNames() {
  var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
  return sheets.map(sheet => sheet.getName());
}
  • スプレッドシート内の すべてのシート名を取得 し、サイドバーのチェックボックスに反映します。
  • SpreadsheetApp.getActiveSpreadsheet().getSheets() でシート一覧を取得。
  • .map(sheet => sheet.getName()) でシート名のみをリスト化。
storeSelectedRangeInfo()
function storeSelectedRangeInfo() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getActiveSheet();
  var range = sheet.getActiveRange();

  if (!range) {
    return { sheetName: sheet.getName(), range: "範囲が選択されていません" };
  }

  var rangeInfo = {
    sheetName: sheet.getName(),
    rangeA1: range.getA1Notation(),
    values: JSON.stringify(range.getValues()),
    backgrounds: JSON.stringify(range.getBackgrounds()),
    fontWeights: JSON.stringify(range.getFontWeights()),
    fontColors: JSON.stringify(range.getFontColors()),
    numberFormats: JSON.stringify(range.getNumberFormats()),
    horizontalAlignments: JSON.stringify(range.getHorizontalAlignments()),
    verticalAlignments: JSON.stringify(range.getVerticalAlignments()),
    startRow: range.getRow(),
    startColumn: range.getColumn(),
    numRows: range.getNumRows(),
    numCols: range.getNumColumns()
  };

  // プロパティストアに保存
  PropertiesService.getScriptProperties().setProperty("storedRangeInfo", JSON.stringify(rangeInfo));

  return { sheetName: sheet.getName(), range: range.getA1Notation() };
}
  • 現在選択している範囲(コピー元)のデータを保存します。
  • データ本体 (getValues())
  • 背景色 (getBackgrounds())
  • フォントの太さ (getFontWeights())
  • フォントの色 (getFontColors())
  • セルの配置(水平・垂直) (getHorizontalAlignments(), getVerticalAlignments())
  • 数値のフォーマット (getNumberFormats())
  • 開始行・列・範囲のサイズ
copyStoredDataToSheets(selectedSheets)
function copyStoredDataToSheets(selectedSheets) {
  var storedData = PropertiesService.getScriptProperties().getProperty("storedRangeInfo");

  if (!storedData) {
    return "コピー元のデータが保存されていません。「更新」ボタンを押してください。";
  }

  var storedRangeInfo = JSON.parse(storedData);
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  selectedSheets.forEach(function(sheetName) {
    var sheet = ss.getSheetByName(sheetName);
    if (sheet) {
      var targetRange = sheet.getRange(
        storedRangeInfo.startRow, 
        storedRangeInfo.startColumn, 
        storedRangeInfo.numRows, 
        storedRangeInfo.numCols
      );

      targetRange.setValues(JSON.parse(storedRangeInfo.values));
      targetRange.setBackgrounds(JSON.parse(storedRangeInfo.backgrounds));
      targetRange.setFontWeights(JSON.parse(storedRangeInfo.fontWeights));
      targetRange.setFontColors(JSON.parse(storedRangeInfo.fontColors));
      targetRange.setHorizontalAlignments(JSON.parse(storedRangeInfo.horizontalAlignments));
      targetRange.setVerticalAlignments(JSON.parse(storedRangeInfo.verticalAlignments));
      targetRange.setNumberFormats(JSON.parse(storedRangeInfo.numberFormats));
    }
  });

  return "データと書式がコピーされました。";
}
  • 保存したデータを選択したシートに一括コピーします。
  • PropertiesService.getScriptProperties().getProperty("storedRangeInfo") で保存されたデータを取得。
  • JSON.parse() で文字列データをオブジェクトに変換。
  • getSheetByName(sheetName) でコピー先のシートを取得し、データをセット。
STEP
メインスクリプト(.gs ファイル)を保存

スクリプトを書いたら、好きな名前を付けて保存します。

(例:「データ一括編集」)

STEP
サイドバーの HTML を作成

<!DOCTYPE html>

<html>

  <head>

    <base target=”_top”>

  </head>

  <body>

  </body>

</html>

が最初から入っているため、消去して以下のスクリプトを貼り付けます。

<!DOCTYPE html>
<html>
<head>
  <script>
    function loadSheets() {
      google.script.run.withSuccessHandler(function(sheetNames) {
        var container = document.getElementById("sheetList");
        container.innerHTML = "";
        sheetNames.forEach(function(name) {
          var checkbox = document.createElement("input");
          checkbox.type = "checkbox";
          checkbox.value = name;
          checkbox.id = name;

          var label = document.createElement("label");
          label.htmlFor = name;
          label.appendChild(document.createTextNode(name));

          var div = document.createElement("div");
          div.appendChild(checkbox);
          div.appendChild(label);

          container.appendChild(div);
        });
      }).getSheetNames();
    }

    function updateStoredRange() {
      google.script.run.withSuccessHandler(function(rangeInfo) {
        document.getElementById("selectedRange").innerText = 
          "コピー元:" + rangeInfo.sheetName + "(" + rangeInfo.range + ")";
      }).storeSelectedRangeInfo();
    }

    function copyData() {
      var selectedSheets = [];
      document.querySelectorAll("#sheetList input:checked").forEach(function(checkbox) {
        selectedSheets.push(checkbox.value);
      });

      if (selectedSheets.length === 0) {
        showMessage("コピー先のシートを選択してください。", "red");
        return;
      }

      google.script.run.withSuccessHandler(function(msg) {
        showMessage("✅ " + msg, "green"); // UI にメッセージを表示
      }).copyStoredDataToSheets(selectedSheets);
    }

    function showMessage(message, color) {
      var statusElement = document.getElementById("statusMessage");
      statusElement.innerText = message;
      statusElement.style.color = color;

      // 3秒後にメッセージを非表示にする
      setTimeout(function() {
        statusElement.innerText = "";
      }, 3000);
    }
  </script>
</head>
<body onload="loadSheets(); updateStoredRange();">
  <h3>コピーした情報</h3>
  <p id="selectedRange">選択範囲を取得中...</p>
  <button onclick="updateStoredRange()">更新</button> <!-- クリックでコピー元を確定 -->
  
  <h3>貼り付け先のシートを選択</h3>
  <div id="sheetList"></div>
  <button onclick="copyData()">データを貼り付け</button>

  <p id="statusMessage" style="font-weight: bold;"></p> <!-- メッセージ表示エリア -->
</body>
</html>
スクリプトの説明
loadSheets()
    function loadSheets() {
      google.script.run.withSuccessHandler(function(sheetNames) {
        var container = document.getElementById("sheetList");
        container.innerHTML = "";
        sheetNames.forEach(function(name) {
          var checkbox = document.createElement("input");
          checkbox.type = "checkbox";
          checkbox.value = name;
          checkbox.id = name;

          var label = document.createElement("label");
          label.htmlFor = name;
          label.appendChild(document.createTextNode(name));

          var div = document.createElement("div");
          div.appendChild(checkbox);
          div.appendChild(label);

          container.appendChild(div);
        });
      }).getSheetNames();
    }
  • スプレッドシート内の すべてのシート名を取得し、チェックボックスを生成します。
  • google.script.run.withSuccessHandler() を使って getSheetNames() を呼び出し、シート名を取得。
  • document.createElement("input") でチェックボックスを動的に作成。
  • container.appendChild(div) でUIに追加。
updateStoredRange()
    function updateStoredRange() {
      google.script.run.withSuccessHandler(function(rangeInfo) {
        document.getElementById("selectedRange").innerText = 
          "コピー元:" + rangeInfo.sheetName + "(" + rangeInfo.range + ")";
      }).storeSelectedRangeInfo();
    }
  • コピー元の情報を更新します(現在選択している範囲を取得し、表示)。
  • google.script.run.withSuccessHandler() を使って storeSelectedRangeInfo() を呼び出し、コピー元の情報を更新。
  • document.getElementById("selectedRange").innerText にコピー元のシート名と範囲を表示。
copyData()
    function copyData() {
      var selectedSheets = [];
      document.querySelectorAll("#sheetList input:checked").forEach(function(checkbox) {
        selectedSheets.push(checkbox.value);
      });

      if (selectedSheets.length === 0) {
        showMessage("コピー先のシートを選択してください。", "red");
        return;
      }

      google.script.run.withSuccessHandler(function(msg) {
        showMessage("✅ " + msg, "green"); // UI にメッセージを表示
      }).copyStoredDataToSheets(selectedSheets);
    }
  • 選択したシートにデータをコピー する処理を実行します。
  • document.querySelectorAll("#sheetList input:checked") で選択されたシートを取得。
  • google.script.run.withSuccessHandler() を使って copyStoredDataToSheets(selectedSheets) を実行。
  • showMessage("✅ " + msg, "green") でコピー成功のメッセージを表示。
showMessage()
    function showMessage(message, color) {
      var statusElement = document.getElementById("statusMessage");
      statusElement.innerText = message;
      statusElement.style.color = color;

      // 3秒後にメッセージを非表示にする
      setTimeout(function() {
        statusElement.innerText = "";
      }, 3000);
  • 実行結果のメッセージを画面に表示し、3秒後に自動で消します。
  • document.getElementById("statusMessage").innerText = message; でメッセージを表示。
  • setTimeout() を使い 3秒後にメッセージを非表示。
STEP
サイドバーの HTML を保存

「SheetSelector」の名前を付けてHTMLファイルを保存します。

(スクリプト実行時に、このファイル名でHTMLファイルを呼び出すため指定のファイル名)

STEP
メインスクリプト(.gs ファイル)を実行

メインスクリプトを実行します。

初めてそのスクリプトを実行する場合は権限の確認が必要です。

そのため、『権限を確認』を押します。

許可の詳細手順

「詳細」をクリックします。

無題のプロジェクト(安全ではないページ)に移動」をクリックします。

許可」をクリックします。

STEP
表示されたサイドバーからコピー情報を確認

サイドバーが表示されるとともに選択した範囲がコピーされます。

一括入力する元データの範囲が合っていることを確認します。

(コピー範囲を変更する場合)

範囲を変更する場合は、範囲選択しなおして「更新」ボタンを押します。

STEP
一括入力先のシートを選択・データ貼り付け

データ反映先のシートを選択します。

選択後、「データを貼り付け」ボタンを押します。

STEP
各シートにデータ一括反映

コピーしたデータが一括で各シートに貼り付けられます。

他にもコピーしたいデータがある場合は、同様の手順で「更新」⇒「データを貼り付け」ボタンを押します。

スクリプトによる一括編集のメリット・デメリット

メリットデメリット
複数のシートを一括で編集できる
データだけでなく、書式も適用可能
スクリプトの初期設定が必要
エクセルの「作業グループ」のようにリアルタイムでは反映されない
メリット
複数のシートを一括で編集できる

シートごとに手作業で編集する必要がなく、選択した複数のシートに同じデータや書式を一括適用できます。繰り返し作業を削減し、業務の効率が向上します。

データだけでなく、書式も適用可能

フォントや背景色、セルの配置などの書式も含めてコピーできるため、統一感のあるフォーマットを簡単に適用できます。

デメリット
スクリプトの初期設定が必要

標準機能ではないため、スクリプトの作成や権限の設定が必要です。

ですが、一度設定すれば簡単に使えます。

エクセルの「作業グループ」のようにリアルタイムでは反映されない

エクセルの「作業グループ」と異なり、リアルタイムでの編集はできません。

「更新」「貼り付け」ボタンを押して適用する手順が必要 になります。

スクリプトの繰り返し実行にはマクロインポートが便利

スクリプトを繰り返し実行する場合、Google スプレッドシートの「マクロにインポート」機能を活用すると便利 です。

マクロに登録すれば、ショートカットキーやメニューから簡単にスクリプトを実行 でき、毎回 Apps Script の編集画面を開く手間を省けます。

マクロインポート方法
STEP
マクロのインポート

スプレッドシートで「拡張機能」>「マクロ」>「マクロをインポート」を選択します。

「showSheetSelector」(データ一括編集)をリストから選び、「関数を追加」をクリックします。

選択した関数がマクロとしてメニューに追加されます。

STEP
マクロの名前を変更する

追加されたマクロの名前を変更するには、「拡張機能」>「マクロ」>「マクロを管理」を選択します。

追加したマクロの名前をクリックして編集し、分かりやすい名前に変更します。

マクロにショートカットキーを設定することも可能です。
例:「Ctrl + Alt + Shift + 3」

STEP
マクロからスクリプトを実行

追加したマクロをクリックすると、スクリプトが実行されます。

空白行(列)の削除をしたいシートが複数ある場合は、この方法を使うと便利です。

まとめ

今回のスクリプトを活用すれば、Google スプレッドシートでも複数のシートに対してデータと書式を一括で適用できます。

特に、一括編集したいシートが多数ある場合に作業を効率化できます。

ぜひご活用ください。

弊社では、Google Apps Script(GAS)を活用した業務効率化のサポートを提供しております。

GASのカスタマイズやエラー対応にお困りの際は、ぜひお気軽にご相談ください。

また、ITツールの導入支援やIT導入補助金の申請サポートも行っております。

貴方の業務改善を全力でサポートいたします。

お問い合わせはこちら

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次