AUTOMATION NOTE — 015

ClaudeでGASを爆速開発!情シス向けClaudecode Design実践ガイド

「またGASの改修依頼か…」

情シスとしてGoogle Workspaceを運用していると、Google Apps Script (GAS) でのちょっとした自動化や連携は日常茶飯事ですよね。しかし、限られたリソースの中で、毎回イチからコードを書いてテストして…となると、かなりの時間がかかってしまいます。

「AIを使えばコードが書けるらしい」と耳にするものの、実際に試してみると「思った通りのコードが出てこない」「結局自分で直す手間がかかる」といった経験はありませんか?AIにコード生成を依頼する際、どのように指示すれば期待通りの結果が得られるのか、その「コツ」が分からず悩んでいる情シス担当者も多いのではないでしょうか。

この記事では、AIチャットボット「Claude」を活用して、情シスのGAS開発を効率化する「Claudecode Design」という考え方をご紹介します。これは単にAIにコードを丸投げするのではなく、AIの特性を理解し、効果的なプロンプト(指示文)を設計することで、AIと「共創」しながら高品質なコードを生み出すための手法です。

この記事を読んだほうが良い人

  • GAS開発に時間を取られている情シス担当者
  • AI(Claude)をGAS開発に活用したいと考えているが、具体的な方法が分からない人
  • AIにコード生成を依頼する際のプロンプト設計に悩んでいる人
  • AIを活用して自身のスキルアップを目指したい人

Claudecode Designとは?情シスがAIと「共創」するコード開発

Claudecode Designとは、Anthropic社が開発するAIモデル「Claude」に対し、情シス業務で利用するGoogle Apps Script (GAS) などのコードを高品質かつ効率的に生成させるための、プロンプト設計の考え方と実践手法を指します。

これは、単に「こんなコードを書いて」と指示するだけではありません。AIが最も能力を発揮できるように、AIの「役割」「目的」「制約」「期待する出力形式」などを明確に伝えることで、人間とAIが協力してコードを開発する「共創」のプロセスを重視します。

情シス現場では、このClaudecode Designを取り入れることで、以下のようなメリットが期待できます。

  • 開発効率の大幅な向上: 定型的な処理や構文の記述をAIに任せることで、コード作成時間を短縮できます。
  • コード品質の向上: AIが生成するコードは、一般的なベストプラクティスや効率的な記述方法に基づいていることが多く、品質の底上げに繋がります。
  • 学習機会の創出: 生成されたコードをレビューすることで、自身のコーディング知識や新しいGASの書き方を学ぶ機会にもなります。
  • 属人化の解消: 特定の担当者しか書けなかったスクリプトも、AIの助けを借りることで、他のメンバーも理解・修正しやすくなります。

Claudecode Designの3つの基本原則

Claudecode Designを実践する上で重要なのは、Claudeに「何を」「どのように」伝えれば良いか、という点です。以下の3つの基本原則を意識することで、AIからのアウトプットは格段に良くなります。

1. 明確な「役割」と「目的」の指示

Claudeに、どのような立場で、どのような目標を達成してほしいのかを明確に伝えます。これにより、Claudeは指示された役割に基づいて、より適切な知識とトーンで応答します。

例: * 「あなたは熟練したGoogle Apps Script (GAS) エンジニアです。」 * 「あなたの目的は、Google Workspaceの管理者である私が抱える特定の業務課題を、GASで解決することです。」 * 「生成するコードは、可読性が高く、保守しやすいものにしてください。」

2. 具体的な「制約」と「条件」の提示

コードを生成する上で、どのような制約や条件があるのかを具体的に伝えます。これにより、AIは不要な機能を省き、必要な要件を満たしたコードを生成しやすくなります。

例: * 「GASのトリガーは使用せず、手動実行を想定してください。」 * 「特定のGoogleスプレッドシートのシート1という名前のシートを対象とします。」 * 「エラーが発生した場合は、Logger.log() でログを出力し、処理を中断しないようにエラーハンドリングを実装してください。」 * 「外部サービスとの連携は不要です。」 * 「ES6の記法(constlet、アロー関数など)を積極的に使用してください。」

3. 期待する「出力形式」と「例」の提示

生成してほしいコードの形式や、もし可能であれば具体的な入出力の例を提示します。これにより、AIはより正確に、期待通りの構造でコードを生成できます。

例: * 「一つの関数 processSpreadsheetData() 内に処理をまとめてください。」 * 「各処理ブロックには、日本語で簡潔なコメントを付与してください。」 * 「関数名や変数名はキャメルケースで記述してください。」 * 「もし、ある関数が複数の引数を取る場合、その引数の型や期待する値の範囲についてコメントで補足してください。」

実践!Claudecode DesignでGASを書いてみよう

それでは、実際にClaudecode Designの原則を使ってGASのコードを生成してみましょう。今回は「Googleフォームの回答を特定の条件で集計し、Slackに通知するGAS」を例に考えます。

シナリオ:月末の残業申請フォーム集計とSlack通知

毎月、従業員からGoogleフォームで残業申請を提出してもらっています。月末にそのフォーム回答をスプレッドシートに集計し、合計残業時間が一定時間(例: 20時間)を超えている従業員がいる場合、情シスのSlackチャンネルに通知したい、というシナリオです。

ステップ1: プロンプトの設計

上記の3つの基本原則を盛り込んで、Claudeに渡すプロンプトを作成します。

あなたは熟練したGoogle Apps Script (GAS) エンジニアです。
あなたの目的は、Google Workspaceの管理者である私が抱える、月末の残業申請集計とSlack通知の業務課題を解決することです。

以下に要件を提示します。

**目的:**
Googleフォームの回答が記録されているスプレッドシートから、月末にその月の残業時間を集計し、合計残業時間が20時間を超える従業員がいた場合、指定のSlackチャンネルに通知するGASを作成してください。

**制約と条件:**
1.  GASは手動実行を想定します。トリガーは設定しないでください。
2.  対象のスプレッドシートIDは `[ここにスプレッドシートID]` とします。
3.  フォーム回答が記録されているシート名は `フォームの回答1` とします。
4.  スプレッドシートの列構成は以下の通りです。
    *   A列: タイムスタンプ
    *   B列: 従業員名
    *   C列: 残業時間 (数値、時間単位)
5.  Slackへの通知には、Incoming Webhookを使用します。Webhook URLは `[ここにSlack Webhook URL]` とします。
6.  エラーハンドリングを適切に実装し、処理が中断しないようにしてください。エラーが発生した場合は `Logger.log()` で詳細を記録してください。
7.  生成するコードは、可読性が高く、保守しやすいものにしてください。
8.  ES6の記法(`const`、`let`、アロー関数など)を積極的に使用してください。

**期待する出力形式:**
1.  一つの関数 `sendMonthlyOvertimeNotification()` に処理をまとめてください。
2.  各処理ブロックには、日本語で簡潔なコメントを付与してください。
3.  Slackに送信するメッセージは、合計残業時間が20時間を超えた従業員のリストと、それぞれの合計残業時間を分かりやすく記載してください。

ステップ2: Claudeでのコード生成

このプロンプトをClaudeに渡し、生成されたコードの例を示します。

function sendMonthlyOvertimeNotification() {
  // スプレッドシートIDとSlack Webhook URLは、ご自身の環境に合わせて設定してください。
  const SPREADSHEET_ID = 'ここにスプレッドシートID';
  const SHEET_NAME = 'フォームの回答1';
  const SLACK_WEBHOOK_URL = 'ここにSlack Webhook URL';
  const OVERTIME_THRESHOLD = 20; // 通知する残業時間の閾値(時間)

  try {
    // スプレッドシートとシートを取得
    const spreadsheet = SpreadsheetApp.openById(SPREADSHEET_ID);
    const sheet = spreadsheet.getSheetByName(SHEET_NAME);

    if (!sheet) {
      throw new Error(`シート '${SHEET_NAME}' が見つかりません。`);
    }

    // データ範囲を取得し、ヘッダー行を除いて全データを取得
    const range = sheet.getDataRange();
    const values = range.getValues();

    if (values.length <= 1) { // ヘッダーのみ、またはデータがない場合
      Logger.log('処理対象のデータがありません。');
      return;
    }

    const header = values[0];
    const dataRows = values.slice(1); // ヘッダー行を除外

    // 今月のデータをフィルタリングし、従業員ごとの残業時間を集計
    const currentMonth = new Date().getMonth(); // 0-11
    const currentYear = new Date().getFullYear();

    const overtimeByEmployee = {};

    dataRows.forEach(row => {
      const timestamp = new Date(row[0]); // A列: タイムスタンプ
      const employeeName = row[1];       // B列: 従業員名
      const overtimeHours = parseFloat(row[2]); // C列: 残業時間

      // 今月のデータか、かつ残業時間が数値として有効かチェック
      if (timestamp.getMonth() === currentMonth && timestamp.getFullYear() === currentYear && !isNaN(overtimeHours)) {
        overtimeByEmployee[employeeName] = (overtimeByEmployee[employeeName] || 0) + overtimeHours;
      }
    });

    // 閾値を超えた従業員を特定
    const employeesOverThreshold = Object.entries(overtimeByEmployee)
      .filter(([, totalOvertime]) => totalOvertime > OVERTIME_THRESHOLD);

    // Slack通知メッセージの作成
    let slackMessage = '';
    if (employeesOverThreshold.length > 0) {
      slackMessage = `*【月末残業申請通知】*\n\n以下の従業員が今月の残業時間${OVERTIME_THRESHOLD}時間を超えています。\n\n`;
      employeesOverThreshold.forEach(([name, totalOvertime]) => {
        slackMessage += `- ${name}: ${totalOvertime.toFixed(1)} 時間\n`;
      });
      slackMessage += `\n詳細はスプレッドシートをご確認ください。`;
    } else {
      slackMessage = `今月の残業時間が${OVERTIME_THRESHOLD}時間を超えた従業員はいませんでした。`;
    }

    // Slackにメッセージを送信
    const options = {
      'method': 'post',
      'contentType': 'application/json',
      'payload': JSON.stringify({ 'text': slackMessage })
    };
    UrlFetchApp.fetch(SLACK_WEBHOOK_URL, options);

    Logger.log('Slack通知処理が完了しました。');

  } catch (e) {
    Logger.log(`エラーが発生しました: ${e.message}`);
  }
}

ステップ3: 生成コードのレビューと修正

Claudeが生成したコードは、上記の要件を概ね満たしています。しかし、そのまま実運用に使うのではなく、必ず以下の観点でレビューと必要に応じた修正を行いましょう。

  • 動作確認: まずはテスト用のスプレッドシートとSlackチャンネルで実際に実行し、期待通りに動作するか確認します。
  • コードの意図理解: 生成されたコードの各行が何を意図しているのか、完全に理解できるか確認します。不明な点があれば、Claudeに「この部分は何をしていますか?」と質問して解説を求めたり、自分で調べたりします。
  • 汎用性・堅牢性: 今回の例では月末処理ですが、月初めに実行した場合の挙動はどうか?シート名や列順が変わった場合の対応は?など、想定外のケースに対する堅牢性を確認します。必要であれば、Claudeに「指定した日付範囲のデータを取得するように修正してください」といった追加の指示を与えて、コードを改善します。
  • セキュリティ: 特に外部サービス連携を行う場合、機密情報(APIキー、Webhook URLなど)がコード内に直接埋め込まれていないか、あるいは安全な方法で管理されているかを確認します。GASではPropertiesServiceを使うのが一般的です。

例えば、今回のコードでは SPREADSHEET_IDSLACK_WEBHOOK_URL がコードに直接書かれています。これをPropertiesServiceを使って安全に管理するようにClaudeに修正を依頼することもできます。

修正依頼のプロンプト例:

上記のGASコードについて、以下の修正をお願いします。
1.  `SPREADSHEET_ID` と `SLACK_WEBHOOK_URL` を、PropertiesServiceを使ってスクリプトプロパティから取得するように変更してください。
2.  `setScriptProperties()` という設定用の関数も追加し、これらのプロパティを一度だけ設定できるようにしてください。

Claudeに修正依頼をすると、以下のようなコードが生成されます。

// スクリプトプロパティを設定する関数(初回のみ実行)
function setScriptProperties() {
  const scriptProperties = PropertiesService.getScriptProperties();
  scriptProperties.setProperty('SPREADSHEET_ID', 'ここにスプレッドシートID');
  scriptProperties.setProperty('SLACK_WEBHOOK_URL', 'ここにSlack Webhook URL');
  Logger.log('スクリプトプロパティが設定されました。');
}

function sendMonthlyOvertimeNotification() {
  // PropertiesServiceから設定値を取得
  const scriptProperties = PropertiesService.getScriptProperties();
  const SPREADSHEET_ID = scriptProperties.getProperty('SPREADSHEET_ID');
  const SLACK_WEBHOOK_URL = scriptProperties.getProperty('SLACK_WEBHOOK_URL');

  const SHEET_NAME = 'フォームの回答1';
  const OVERTIME_THRESHOLD = 20; // 通知する残業時間の閾値(時間)

  // プロパティが設定されていない場合はエラーとして処理を中断
  if (!SPREADSHEET_ID || !SLACK_WEBHOOK_URL) {
    Logger.log('エラー: SPREADSHEET_ID または SLACK_WEBHOOK_URL がスクリプトプロパティに設定されていません。setScriptProperties() 関数を実行してください。');
    return;
  }

  try {
    // スプレッドシートとシートを取得
    const spreadsheet = SpreadsheetApp.openById(SPREADSHEET_ID);
    const sheet = spreadsheet.getSheetByName(SHEET_NAME);

    if (!sheet) {
      throw new Error(`シート '${SHEET_NAME}' が見つかりません。`);
    }

    // データ範囲を取得し、ヘッダー行を除いて全データを取得
    const range = sheet.getDataRange();
    const values = range.getValues();

    if (values.length <= 1) { // ヘッダーのみ、またはデータがない場合
      Logger.log('処理対象のデータがありません。');
      return;
    }

    const header = values[0];
    const dataRows = values.slice(1); // ヘッダー行を除外

    // 今月のデータをフィルタリングし、従業員ごとの残業時間を集計
    const currentMonth = new Date().getMonth(); // 0-11
    const currentYear = new Date().getFullYear();

    const overtimeByEmployee = {};

    dataRows.forEach(row => {
      const timestamp = new Date(row[0]); // A列: タイムスタンプ
      const employeeName = row[1];       // B列: 従業員名
      const overtimeHours = parseFloat(row[2]); // C列: 残業時間

      // 今月のデータか、かつ残業時間が数値として有効かチェック
      if (timestamp.getMonth() === currentMonth && timestamp.getFullYear() === currentYear && !isNaN(overtimeHours)) {
        overtimeByEmployee[employeeName] = (overtimeByEmployee[employeeName] || 0) + overtimeHours;
      }
    });

    // 閾値を超えた従業員を特定
    const employeesOverThreshold = Object.entries(overtimeByEmployee)
      .filter(([, totalOvertime]) => totalOvertime > OVERTIME_THRESHOLD);

    // Slack通知メッセージの作成
    let slackMessage = '';
    if (employeesOverThreshold.length > 0) {
      slackMessage = `*【月末残業申請通知】*\n\n以下の従業員が今月の残業時間${OVERTIME_THRESHOLD}時間を超えています。\n\n`;
      employeesOverThreshold.forEach(([name, totalOvertime]) => {
        slackMessage += `- ${name}: ${totalOvertime.toFixed(1)} 時間\n`;
      });
      slackMessage += `\n詳細はスプレッドシートをご確認ください。`;
    } else {
      slackMessage = `今月の残業時間が${OVERTIME_THRESHOLD}時間を超えた従業員はいませんでした。`;
    }

    // Slackにメッセージを送信
    const options = {
      'method': 'post',
      'contentType': 'application/json',
      'payload': JSON.stringify({ 'text': slackMessage })
    };
    UrlFetchApp.fetch(SLACK_WEBHOOK_URL, options);

    Logger.log('Slack通知処理が完了しました。');

  } catch (e) {
    Logger.log(`エラーが発生しました: ${e.message}`);
  }
}

このように、AIと対話しながらコードを改善していくプロセスが、Claudecode Designの真髄です。

Claudecode Designを実務で活かすためのヒント

イテレーション(繰り返し)の重要性

一度のプロンプトで完璧なコードが生成されることは稀です。最初は大まかな指示でコードを生成させ、その後「この部分を修正して」「この機能を追加して」と具体的なフィードバックを与えながら、段階的に理想のコードに近づけていく「イテレーション」を意識しましょう。

テストの習慣化

AIが生成したコードも、人間が書いたコードと同様に必ずテストが必要です。特に情シス業務では、データの整合性やセキュリティに関わる重要な処理が多いため、本番環境にデプロイする前に十分なテストを行いましょう。

セキュリティ意識

AIにプロンプトを与える際、機密情報(パスワード、APIキー、個人情報など)を直接入力することは避けましょう。AIモデルは学習データとして利用される可能性があるため、安全な情報管理を常に心がけてください。

AIの得意・不得意の理解

AIは、定型的なコードの生成、構文チェック、基本的なアルゴリズムの実装などは得意です。しかし、複雑なビジネスロジックの理解、曖昧な要件定義からの設計、最新のAPI変更への対応などは苦手な場合があります。AIの得意な部分を最大限に活用し、人間が考えるべき部分に集中することが重要です。

考察: 情シスの未来とAI共創の可能性

Claudecode DesignのようなAIを活用したコード開発は、情シスの業務に大きな変革をもたらす可能性を秘めています。これまでコードを書くことに抵抗があった担当者でも、AIの助けを借りることで、より多くの自動化や効率化を実現できるようになります。

これは、情シスが「コードを書く専門家」から「AIを使いこなして課題を解決するプロデューサー」へと役割を変えていくことを意味します。AIはあくまで強力なツールであり、最終的な設計、レビュー、そして責任は人間にあります。AIの能力を最大限に引き出すためのプロンプト設計スキルは、これからの情シスに求められる重要な能力の一つになるでしょう。

AIと共創することで、情シスはルーティンワークから解放され、より戦略的な業務や、会社全体の生産性向上に貢献できる時間が増えます。

まとめ

この記事では、Claudeを活用してGoogle Apps Script (GAS) の開発を効率化する「Claudecode Design」について解説しました。

  • Claudecode Designは、AIの「役割」「目的」「制約」「出力形式」を明確に伝えることで、高品質なコードをAIと「共創」する手法です。
  • 3つの基本原則(役割と目的の指示、制約と条件の提示、期待する出力形式の提示)を意識することで、AIからのアウトプットは格段に良くなります。
  • AIが生成したコードも、必ずレビューとテストを行い、必要に応じて修正や改善を繰り返すことが重要です。
  • AIは強力なツールですが、最終的な判断と責任は人間にあります。セキュリティ意識を持ち、AIの得意不得意を理解して活用しましょう。

ぜひ、この記事で紹介したClaudecode Designの考え方を参考に、日々のGAS開発にClaudeを取り入れてみてください。まずは身近なGASタスクから試してみて、AIとの「共創」の楽しさと効率性を実感することをおすすめします。プロンプト設計のスキルを磨くことで、あなたの情シス業務はより生産的で創造的なものへと変わっていきます。



コーポレートITのご相談はお気軽に

この記事で書いたような業務改善・自動化の設計から実装まで、DRASENASではコーポレートITの現場に寄り添った支援を行っています。 「まず相談だけ」でも大歓迎です。DRASENAS 公式サイトからお気軽にどうぞ。

CONTACT

御社の IT 部門、ここにあります。

「ITのことはあまりわからない」── そのような状態からで、まったく問題ございません。まずはお気軽にご相談ください。

一社ずつ、一から。