GASでCSVを
スプレッドシートに取り込む方法

手作業のコピペで文字化けや列ズレに悩まされていませんか。Utilities.parseCsv(CSV文字列を二次元配列に変換するGASの標準メソッド)を使えば、CSVの取り込みをコードで安全に自動化できます。

|対象: GAS / スプレッドシート / CSV取り込み

Table of Contents

CSV取り込みでつまずくポイント

CSV(カンマ区切りのテキストファイル)の取り込みは単純そうに見えて、手作業や自作のコードでは次のような落とし穴があります。 GASの標準メソッドを使えば、この多くを避けられます。

セル内のカンマで列がズレる

住所や備考にカンマが混ざると、split(",")では列がずれてしまう

日本語が文字化けする

ExcelのCSVはShift_JISが多く、UTF-8として読むと文字が壊れる

改行を含むセルで行が崩れる

セル内改行があると、1行として扱えず取り込みが破綻する

毎回の手作業が地味に重い

定期的に届くCSVを人が貼り付けるのは手間もミスも増える

Utilities.parseCsvの基本

Utilities.parseCsv(文字列)は、CSV文字列を二次元配列(行の配列。各行がセルの配列)に変換します。 二重引用符で囲まれたカンマは1つのセルとして正しく扱われるため、split(",")の自作より安全です。

function parseCsvBasic() {
  const csv =
    '氏名,メール,備考\n' +
    '山田太郎,taro@example.com,"東京都,渋谷区"\n' +
    '佐藤花子,hanako@example.com,リピーター';

  // 文字列を二次元配列に変換する
  const data = Utilities.parseCsv(csv);

  Logger.log(data.length);      // 3(ヘッダー含む)
  Logger.log(data[1][0]);       // 山田太郎
  Logger.log(data[1][2]);       // 東京都,渋谷区(引用符内のカンマも1セル扱い)
}

返ってくる値はすべて文字列です。数値として計算したい場合は、後でNumber()で変換します。

Driveに置いたCSVを取り込む

実務で多いのは、Googleドライブに保存されたCSVを取り込むパターンです。DriveApp.getFileByIdでファイルを取得し、Blob(ファイルの中身)を文字列にしてからparseCsvにかけ、setValuesでシートに一括書き込みします。

function importCsvFromDrive(fileId, sheetName) {
  // Driveに置いたCSVファイルを読み込む
  const blob = DriveApp.getFileById(fileId).getBlob();
  const csv = blob.getDataAsString("UTF-8");

  const data = Utilities.parseCsv(csv);
  if (data.length === 0) return;

  const sheet = SpreadsheetApp.getActive().getSheetByName(sheetName);
  sheet.clearContents(); // 既存の内容を消してから丸ごと入れ替える
  sheet
    .getRange(1, 1, data.length, data[0].length)
    .setValues(data);

  Logger.log(data.length + "行を取り込みました");
}

ファイルIDはDriveでファイルを開いたときのURLの/d/~/の部分です。上のコードはシートを丸ごと入れ替える方式で、マスタデータの更新に向いています。

文字化け(Shift_JIS)を防ぐ

取り込んだ日本語が「譁�喧縺�」のように化けるときは、文字コードの指定が原因です。 ExcelやWindowsの基幹システムが出力するCSVはShift_JIS(Windows-31J)のことが多く、UTF-8として読むと文字化けします。getDataAsStringに文字コードを渡して明示しましょう。

function importShiftJisCsv(fileId, sheetName) {
  const blob = DriveApp.getFileById(fileId).getBlob();

  // Excelや基幹システムが吐き出すCSVはShift_JISが多い。
  // UTF-8として読むと日本語が文字化けするため文字コードを明示する。
  const csv = blob.getDataAsString("Shift_JIS");

  const data = Utilities.parseCsv(csv);
  const sheet = SpreadsheetApp.getActive().getSheetByName(sheetName);
  sheet.clearContents();
  sheet.getRange(1, 1, data.length, data[0].length).setValues(data);
}

どちらの文字コードか分からないときは、"UTF-8""Shift_JIS"の両方で読み、正しく表示される方を選びます。

URLから取得したCSVを取り込む

外部システムやオープンデータが公開するCSVは、UrlFetchApp.fetchでダウンロードしてそのまま取り込めます。取得に失敗したときのために、ステータスコードの確認を入れておくと安全です。

function importCsvFromUrl(url, sheetName) {
  const res = UrlFetchApp.fetch(url, { muteHttpExceptions: true });
  if (res.getResponseCode() !== 200) {
    throw new Error("CSVの取得に失敗しました: " + res.getResponseCode());
  }

  // getContentTextに文字コードを渡すこともできる(既定はUTF-8)
  const data = Utilities.parseCsv(res.getContentText("UTF-8"));

  const sheet = SpreadsheetApp.getActive().getSheetByName(sheetName);
  sheet.clearContents();
  sheet.getRange(1, 1, data.length, data[0].length).setValues(data);
}

重複を避けて差分だけ追記する

毎回シートを入れ替えるのではなく、既存データはそのままに新しい行だけを足したい場合は、 キー列(IDやメールなど一意になる列)で「取り込み済み」を判定してから追記します。Setで既出チェックすると高速です。

function appendNewRowsFromCsv(fileId, sheetName, keyColIndex) {
  const csv = DriveApp.getFileById(fileId).getBlob().getDataAsString("UTF-8");
  const rows = Utilities.parseCsv(csv).slice(1); // ヘッダー行を除く

  const sheet = SpreadsheetApp.getActive().getSheetByName(sheetName);

  // 既存シートのキー列を集めて「取り込み済み」の集合を作る
  const existing = sheet.getDataRange().getValues().slice(1);
  const seen = new Set(existing.map((r) => String(r[keyColIndex]).trim()));

  const newRows = rows.filter(
    (r) => !seen.has(String(r[keyColIndex]).trim())
  );

  if (newRows.length > 0) {
    sheet
      .getRange(sheet.getLastRow() + 1, 1, newRows.length, newRows[0].length)
      .setValues(newRows);
  }
  Logger.log(newRows.length + "件を新規追加しました");
}

同じCSVを2回取り込んでも二重登録されないため、定期実行と組み合わせやすいのが利点です。

タブ区切り(TSV)と定期実行

parseCsvは第2引数で区切り文字を指定できます。タブ区切り(TSV)やセミコロン区切りのファイルも同じ関数で扱えます。

function parseTsv() {
  const tsv = "商品\t単価\nりんご\t120\nみかん\t80";

  // 第2引数で区切り文字を指定できる(タブ・セミコロンなど1文字)
  const data = Utilities.parseCsv(tsv, "\t");

  Logger.log(data[1][0]); // りんご
  Logger.log(data[1][1]); // 120
  return data;
}

最後に、時間主導トリガーで取り込みを自動化します。差分追記の関数と組み合わせれば、毎朝新しいデータだけを安全に反映できます。

function createDailyImportTrigger() {
  ScriptApp.newTrigger("dailyImportJob")
    .timeBased()
    .everyDays(1)
    .atHour(7)
    .create();
}

function dailyImportJob() {
  const FILE_ID = "取り込みたいCSVのファイルID";
  // キー列(例: 0列目のID)で重複を避けながら差分だけ追記する
  appendNewRowsFromCsv(FILE_ID, "取込データ", 0);
}

まとめ

CSVの取り込みは、Utilities.parseCsvで二次元配列に変換し、setValuesで一括書き込みするのが基本形です。文字コードの明示で文字化けを防ぎ、キー列での重複判定と定期トリガーを加えれば、 手作業ゼロで安全なデータ連携が組めます。取り込みの逆方向(CSV出力)や取り込み後の重複整理も、同じ考え方で自動化できます。

よくある質問

split(",")はセルの中身にカンマや改行が含まれると壊れてしまいます。CSVは値にカンマや改行を含めるとき二重引用符("...")で囲む決まりがあり、Utilities.parseCsvはこの引用符を正しく解釈して二次元配列に変換します。実務のCSVでは住所や備考にカンマが混ざることが多いので、自作のsplitではなくparseCsvを使うのが安全です。

ExcelやWindowsで保存したCSVはShift_JIS(Windows-31J)のことが多く、UTF-8として読むと文字化けします。Blobを文字列にするときにgetDataAsString("Shift_JIS")のように文字コードを明示すると直ります。逆にUTF-8のファイルはgetDataAsString("UTF-8")、迷ったら両方試して正しく表示される方を選びます。

parseCsvの結果はすべて文字列ですが、setValuesで書き込むとスプレッドシート側が「012」を数値の12、「2026-07-20」を日付として自動変換します。電話番号や郵便番号など文字列のまま残したい列は、事前にsetNumberFormat("@")で書式を「書式なしテキスト」にしておくと変換を防げます。

読み込めます。Utilities.parseCsvは第2引数に区切り文字を指定できるので、Utilities.parseCsv(text, "\t")とすればタブ区切り、セミコロン区切りなら";"を渡します。区切り文字は1文字だけ指定できます。

数万行を超えるCSVでは、6分の実行時間制限に達したり、setValuesで一度に書き込むデータ量が大きすぎてエラーになることがあります。行を数千件ずつに区切って複数回に分けて書き込む、処理位置をPropertiesServiceに保存して分割実行するなどの対策が有効です。

できます。時間主導トリガー(ScriptApp.newTrigger)で毎朝決まった時刻に取り込み関数を実行すれば、Driveの決まったフォルダに置かれたCSVや、外部システムが公開するCSV URLを自動で反映できます。重複を避ける追記処理と組み合わせると、差分だけを安全に取り込めます。

GAS開発・業務Webシステムを
相談する。

CSV取り込み以外にも、基幹システムとのデータ連携・帳票出力・Gmail自動化など、日々の業務を自動化するGAS開発をご相談いただけます。

AI×GAS自動化を見る