Googleスプレッドシートから自動で共有フォルダを作成する方法|メールアドレスを入力するだけ!

目次

はじめに

「取引先ごとにGoogleドライブの共有フォルダを作るのが大変…」
「手作業でフォルダを作って、メールで共有設定して…もう限界!」

そんな方に向けて、今回は
💡 スプレッドシートに顧客名とメールアドレスを入力するだけで、Googleドライブ上に共有フォルダを自動作成できる仕組み
を紹介します。

配布用のサンプルシートも用意していますので、
コピーしてすぐにお試しいただけます。


準備:スプレッドシートをコピーする

まずは、今回のサンプルシートをコピーしてください。
以下のリンクをクリックして「コピーを作成」を押します。

👉 フォルダ自動作成スプレッドシートをコピーする

コピーを作成すると、自分のGoogleドライブに保存されます。

全体の構成

今回の仕組みは次の4つのパートで構成されています👇

シート名役割
初期設定親フォルダのURLや閲覧権限など、環境設定をまとめる
顧客一覧顧客名とメールアドレス、権限を入力するシート
Apps ScriptスプレッドシートからGoogleドライブ操作を自動化
メニュー機能「フォルダ作成ボタン」をスプレッドシート上に表示

STEP1:親フォルダのURLを設定

まず「初期設定」シートを開いてください。
このシートに、フォルダを作りたい親フォルダのURLを入力します。

https://drive.google.com/drive/folders/xxxxxxxxxxxxxxxxxxxx

このフォルダの中に、顧客ごとのフォルダが自動で作成されます。

💡 ポイント

自分のアカウントで編集権限があるフォルダを指定しましょう。
共有ドライブでもマイドライブでもOKです。

設定項目値(例)説明
親フォルダURLhttps://drive.google.com/drive/folders/1Abxxxフォルダを作成する場所
閲覧権限閲覧者または編集者GASを実行した際の、共有フォルダのデフォルトの権限を設定します

💡 ポイント

  • URLはフォルダを開いて「URL欄をコピー」すればOK。
  • コードに直接IDを書く必要がないため、安全で汎用的に使えます。

ステップ2:顧客一覧シートの作成

次に「顧客一覧」シートを作ります。
顧客名とメールアドレス、権限を入力するだけでフォルダが自動生成されます。
権限を入力していない場合は、初期設定で入力した権限が利用されます。

顧客名メールアドレス権限フォルダURLステータス現在の権限
株式会社Aa@example.com閲覧者(自動入力)作成済み閲覧者
株式会社Bb@example.com編集者(自動入力)作成済み編集者
株式会社Cc@example.com閲覧者(未作成)閲覧者

💡 補足

  • 「フォルダURL」と「ステータス」、「現在の権限」はスクリプトが自動で入力します。
  • メールアドレスはGmailアドレス推奨(外部共有制限を避けるため)。

●イメージ図


ステップ3:Apps Scriptを設定する

スプレッドシート上部メニューから
[拡張機能]→[Apps Script] を開き、以下のコードを貼り付けます。

📜 メインスクリプト

// ==========================================
// 📂 フォルダ作成ツール(2025最新版)
// ==========================================

function onOpen() {
  const ui = SpreadsheetApp.getUi();
  ui.createMenu("📂 フォルダ作成ツール")
    .addItem("フォルダを作成", "createFolders")
    .addItem("権限だけ更新", "updatePermissionsOnly")
    .addToUi();
}

// ==========================================
// 🔧 共通関数・設定
// ==========================================

// 初期設定!B3 のデフォルト権限を取得
function getDefaultPermission_() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const setSheet = ss.getSheetByName("初期設定");
  const v = (setSheet.getRange("B3").getValue() || "").toString().trim();
  return normalizePermission_(v || "閲覧者");
}

// 権限ラベルを内部コード化
function normalizePermission_(label) {
  const t = (label || "").toString().trim();
  return (t === "編集者" || t === "EDIT") ? "EDIT" : "VIEW";
}

// メールアドレス簡易チェック
function isValidEmail_(email) {
  if (!email) return false;
  const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return re.test(String(email).trim());
}

// フォルダURLからIDを抽出
function getFolderIdFromUrl_(url) {
  const m = String(url || "").match(/[-\w]{25,}/);
  return m ? m[0] : null;
}

// 現在のDrive共有状態をF列へ反映
function updatePermissionStatusInSheet_(rows) {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const listSheet = ss.getSheetByName("顧客一覧");
  const data = listSheet.getDataRange().getValues();
  const header = data[0] || [];
  const urlIndex = header.indexOf("フォルダURL");
  let permNowIndex = header.indexOf("現在の権限"); // F列

  if (permNowIndex === -1) {
    permNowIndex = header.length;
    listSheet.getRange(1, permNowIndex + 1).setValue("現在の権限");
  }

  for (const rowNum of rows) {
    const folderUrl = (data[rowNum - 1][urlIndex] || "").toString().trim();
    if (!folderUrl) continue;

    const id = getFolderIdFromUrl_(folderUrl);
    if (!id) {
      listSheet.getRange(rowNum, permNowIndex + 1).setValue("不明");
      continue;
    }

    try {
      const folder = DriveApp.getFolderById(id);
      const access = folder.getSharingAccess();
      const perm = folder.getSharingPermission();
      let label = "非公開";

      if (access === DriveApp.Access.ANYONE_WITH_LINK) {
        label = (perm === DriveApp.Permission.EDIT) ? "編集者" : "閲覧者";
      } else {
        const editors = folder.getEditors();
        const viewers = folder.getViewers();
        if (editors.length > 0) label = "編集者";
        else if (viewers.length > 0) label = "閲覧者";
      }

      listSheet.getRange(rowNum, permNowIndex + 1).setValue(label);

    } catch (e) {
      listSheet.getRange(rowNum, permNowIndex + 1).setValue("エラー");
    }
  }
}

// ==========================================
// 📁 フォルダ作成処理
// ==========================================

function createFolders() {
  const lock = LockService.getDocumentLock();
  if (!lock.tryLock(30000)) {
    SpreadsheetApp.getUi().alert("別の処理が実行中です。しばらくしてから再実行してください。");
    return;
  }

  try {
    const ss = SpreadsheetApp.getActiveSpreadsheet();
    const setSheet = ss.getSheetByName("初期設定");
    const listSheet = ss.getSheetByName("顧客一覧");

    // 親フォルダ確認
    const parentUrl = (setSheet.getRange("B2").getValue() || "").toString().trim();
    const parentId = getFolderIdFromUrl_(parentUrl);
    if (!parentId) {
      SpreadsheetApp.getUi().alert("親フォルダURLが正しくありません。");
      return;
    }

    const parentFolder = DriveApp.getFolderById(parentId);
    const data = listSheet.getDataRange().getValues();
    const header = data[0];
    const nameIndex = header.indexOf("顧客名");
    const emailIndex = header.indexOf("メールアドレス");
    const permIndex = header.indexOf("権限");
    const urlIndex = header.indexOf("フォルダURL");
    const statusIndex = header.indexOf("ステータス");
    const defaultPerm = getDefaultPermission_();

    let createdCount = 0, skippedCount = 0, errorCount = 0;
    const targetRows = [];

    for (let i = 1; i < data.length; i++) {
      const row = data[i];
      const company = (row[nameIndex] || "").toString().trim();
      const email = (row[emailIndex] || "").toString().trim();
      const permLabel = (row[permIndex] || "").toString().trim();
      const url = (row[urlIndex] || "").toString().trim();
      const status = (row[statusIndex] || "").toString().trim();

      // ====== スキップ条件 ======
      if (!company || status === "作成済み" || url) { skippedCount++; continue; }
      if (!email) { // ★ メールが無い場合はフォルダ作成しない
        listSheet.getRange(i + 1, statusIndex + 1).setValue("スキップ:メールなし");
        skippedCount++;
        continue;
      }
      if (!isValidEmail_(email)) {
        listSheet.getRange(i + 1, statusIndex + 1).setValue("エラー: メール形式不正");
        errorCount++;
        continue;
      }

      const permCode = normalizePermission_(permLabel || defaultPerm);

      // ====== フォルダ作成 ======
      let newFolder;
      try {
        newFolder = parentFolder.createFolder(company);

        // Gmail → 個別共有、非Gmail → リンク共有
        if (/@gmail\.com$/i.test(email)) {
          if (permCode === "EDIT") newFolder.addEditor(email);
          else newFolder.addViewer(email);
        } else {
          const access = DriveApp.Access.ANYONE_WITH_LINK;
          const permission = (permCode === "EDIT") ? DriveApp.Permission.EDIT : DriveApp.Permission.VIEW;
          newFolder.setSharing(access, permission);
        }

        // シート更新
        listSheet.getRange(i + 1, urlIndex + 1).setValue(newFolder.getUrl());
        listSheet.getRange(i + 1, statusIndex + 1).setValue("作成済み");
        targetRows.push(i + 1);
        createdCount++;

      } catch (e) {
        if (newFolder) try { newFolder.setTrashed(true); } catch {}
        listSheet.getRange(i + 1, statusIndex + 1).setValue("エラー: " + (e.message || e));
        errorCount++;
      }
    }

    SpreadsheetApp.getUi().alert(
      `フォルダ作成完了\n\n新規作成:${createdCount} 件\nスキップ:${skippedCount} 件\nエラー:${errorCount} 件`
    );

    if (targetRows.length > 0) updatePermissionStatusInSheet_(targetRows);

  } finally {
    lock.releaseLock();
  }
}

// ==========================================
// 🔁 権限だけ更新処理
// ==========================================

function updatePermissionsOnly() {
  const lock = LockService.getDocumentLock();
  if (!lock.tryLock(30000)) {
    SpreadsheetApp.getUi().alert("別の処理が実行中です。");
    return;
  }

  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const listSheet = ss.getSheetByName("顧客一覧");
  const data = listSheet.getDataRange().getValues();
  const header = data[0] || [];

  const emailIndex  = header.indexOf("メールアドレス");
  const permIndex   = header.indexOf("権限");
  const urlIndex    = header.indexOf("フォルダURL");
  const statusIndex = header.indexOf("ステータス");
  const defaultPerm = getDefaultPermission_();

  let updated = 0, skipped = 0, errorCount = 0;
  const targetRows = [];

  for (let i = 1; i < data.length; i++) {
    const email = (data[i][emailIndex] || "").toString().trim();
    const permLabel = (data[i][permIndex] || "").toString().trim();
    const folderUrl = (data[i][urlIndex] || "").toString().trim();

    if (!folderUrl) { skipped++; continue; }
    const fid = getFolderIdFromUrl_(folderUrl);
    if (!fid) { skipped++; continue; }

    const permCode = normalizePermission_(permLabel || defaultPerm);

    try {
      const folder = DriveApp.getFolderById(fid);

      // 共有を一旦リセット
      try { folder.setSharing(DriveApp.Access.PRIVATE, DriveApp.Permission.NONE); } catch {}
      try {
        folder.getEditors().forEach(u => { try { folder.removeEditor(u); } catch {} });
        folder.getViewers().forEach(u => { try { folder.removeViewer(u); } catch {} });
      } catch {}

      // 再共有
      if (email && /@gmail\.com$/i.test(email)) {
        if (permCode === "EDIT") folder.addEditor(email);
        else folder.addViewer(email);
      } else {
        const access = DriveApp.Access.ANYONE_WITH_LINK;
        const permission = (permCode === "EDIT") ? DriveApp.Permission.EDIT : DriveApp.Permission.VIEW;
        folder.setSharing(access, permission);
      }

      listSheet.getRange(i + 1, statusIndex + 1).setValue("権限更新済み");
      targetRows.push(i + 1);
      updated++;

    } catch (e) {
      listSheet.getRange(i + 1, statusIndex + 1).setValue("エラー: 権限更新失敗(" + (e.message || e) + ")");
      errorCount++;
    }
  }

  SpreadsheetApp.getUi().alert(
    `権限更新完了\n\n更新:${updated} 件\nスキップ:${skipped} 件\nエラー:${errorCount} 件`
  );

  if (targetRows.length > 0) updatePermissionStatusInSheet_(targetRows);
  lock.releaseLock();
}


ステップ4:初回実行と権限許可

このスクリプトは、初回だけ「アクセス許可」の設定が必要です。

手順

  1. Apps Scriptの画面で「onOpen」を選択
  2. ▶(実行)をクリック
  3. 「権限を確認」→「続行」→使用中のGoogleアカウントを選択
  4. 「このアプリは確認されていません」→「詳細」→「安全ではないページに移動」→「続行」

完了したら、スプレッドシートを再読み込みします。


ステップ5:メニューを確認

上部に以下のメニューが追加されていれば成功です。

📂 フォルダ作成ツール → フォルダを作成

これで準備完了です!


STEP6:フォルダを一括作成!

上部メニューから
📂 フォルダ作成ツール → フォルダを作成
をクリック!

すると、スクリプトが自動で以下を実行します👇

  • 「初期設定」の親フォルダ内にサブフォルダを作成
    ちなみに、共有になっていないB、Cは問題ないです。
    理由は、Bのメールアドレスは自分自身のアドレスを指定している、Cはアドレスが存在しないため、共有になっていません。
  • 各フォルダを入力したメールアドレスに共有
  • 「フォルダURL」列に自動記入
  • 「作成状況」を「作成済み」に更新

わずか数秒で、複数の顧客フォルダを一括で作成できます!

↓A社は共有できている

↓ 招待されたアドレスにはメールが届きます


おまけ機能

権限だけを変更する機能を追加したため、おまけとしての載せておきます。

作成したフォルダの権限だけを変更したい場合は、C列の「権限」を変更し、メニューのフォルダ作成ツールより、「権限だけ更新」を選択することで、フォルダの権限だけを更新することができます。

もし、間違えて権限を付けてしまった場合に利用してください。

よくある質問

Q. メニューが出ない
→ 初回の「onOpen」実行がまだです。STEP4を確認。

Q. Gmail以外のメールで共有されない
→ Googleアカウントが必要です。共有できない場合は「リンク共有」に切り替わります。

Q. もう一度押したら重複フォルダが作成された
→ 「作成済み」列をチェックして、スクリプトでスキップ設定を追加済みです。
 同名フォルダを避けるには、フォルダ名に日付を含めるのもおすすめです。


まとめ

今回の仕組みでできること:

✅ 顧客ごとのフォルダを自動で作成
✅ メールアドレスへの共有設定も自動化
✅ フォルダURLをスプレッドシートに一覧表示

もう、手作業で「新規フォルダ → 共有 → コピー → 貼り付け」なんて必要ありません。


カスタマイズ例(応用編)

  • サブフォルダも同時に作る(例:請求書/契約書)
  • フォルダ名に日付を含める
  • フォルダ作成後に自動でGmail下書きを生成

おわりに

今回のサンプルをコピーすれば、
すぐに自分の環境でも試せます!

まずは小規模な顧客リストから始めて、
「仕組みで時間を節約する」体験をしてみてください。


🗂️ サンプルシートをコピーする
👉 フォルダ自動作成スプレッドシート


しんのひとこと

業務で同じ作業を何度も繰り返しているなら、
それは「自動化のチャンス」です。

今回のように、スプレッドシート × Googleドライブ × GAS の組み合わせで、
「仕組みで時間を生み出す」ことができます。

「毎回同じ作業がある」なら、まずは1つ自動化してみてください。
その1回が、1年間の大きな時短につながります。

👉 パソコン移行でお困りの方はお問い合わせフォームからお気軽にどうぞ。

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

この記事を書いた人

コメント

コメントする

CAPTCHA



reCaptcha の認証期間が終了しました。ページを再読み込みしてください。

目次