😀

ボイスノートの回答レコードをGASで自動取得する

に公開

前提

  • 週報用途のボイスノートをKaonavi上で毎週、各部署ごとに新規シートとして作成
  • Kaonavi 公開 API v2 を使用して、以下を実行
    • シート一覧を取得(/sheet_layouts または /sheets
    • 各シートの回答レコード取得(/sheets/{sheet_id}/records
  • 実装は Google Apps Script(GAS) 上で行う

私の要求

  • API1(シート一覧の取得) → API2(回答レコード取得)をループで処理する
  • 汎用的なスクリプトを毎週再利用したい
  • 全て GAS で完結させたい

実装上の制限と注意点

  • Kaonavi API は、1リクエストにつき1シート分の回答しか取得できない構成となっており、複数シート分の取得はループ処理が必要

  • APIのレート制限:

  • 1社あたり毎時最大約 3,000 回の呼び出し

  • 更新リクエストは毎分最大 5 回まで(本処理は取得系ですが、全体設計で注意要)

  • 認証には Consumer Key/Consumer Secret による Basic 認証からアクセストークン取得(Bearer token)方式が必要

全体処理の流れ

  1. アクセストークンを取得
  2. /sheet_layouts(または /sheets)でシート一覧を取得
  3. シート名や作成日で、対象の「今週の週報」シートをフィルタ
  4. 各対象シートID に対して /sheets/{sheet_id}/records をループで実行
  5. 取得したレコードを Google スプレッドシートに出力/集計
  6. 必要に応じてレート制御・エラーハンドリング縛りを実装

サンプルコード(GAS)

// --- ① アクセストークン取得 ---
function getAccessToken_() {
  const consumerKey = 'YOUR_CONSUMER_KEY';
  const consumerSecret = 'YOUR_CONSUMER_SECRET';
  const cred = Utilities.base64Encode(consumerKey + ':' + consumerSecret);
  const resp = UrlFetchApp.fetch('https://api.kaonavi.jp/api/v2.0/token', {
    method: 'post',
    headers: {
      'Authorization': 'Basic ' + cred,
      'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
    },
    payload: 'grant_type=client_credentials'
  });
  return JSON.parse(resp.getContentText()).access_token;
}

// --- ② メイン処理 ---
function fetchKaonaviVoiceNoteRecords() {
  const token = getAccessToken_();
  const headers = {
    'Content-Type': 'application/json',
    'Kaonavi-Token': token
  };

  // シートレイアウト一覧取得
  const resp = UrlFetchApp.fetch(
    'https://api.kaonavi.jp/api/v2.0/sheet_layouts',
    { method: 'get', headers }
  );
  const sheetLayouts = JSON.parse(resp.getContentText()).sheets;

  // 今週の週報シートをフィルタ(例:yyyyMMdd形式)
  const thisWeek = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyyMMdd');
  const targets = sheetLayouts.filter(s => s.name && s.name.includes('週報_' + thisWeek));

  const result = [];

  // 各シートからレコード取得
  targets.forEach(s => {
    const recResp = UrlFetchApp.fetch(
      `https://api.kaonavi.jp/api/v2.0/sheets/${s.id}/records`,
      { method: 'get', headers }
    );
    const recJson = JSON.parse(recResp.getContentText());
    recJson.member_data.forEach(member => {
      member.records.forEach(r => {
        result.push({
          sheetId: s.id,
          sheetName: s.name,
          memberCode: member.code,
          answers: r.custom_fields.map(f => ({
            fieldId: f.id,
            values: f.values
          }))
        });
      });
    });
  });

  // スプレッドシートに書き出し
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  let sheet = ss.getSheetByName('週報回答一覧');
  if (!sheet) sheet = ss.insertSheet('週報回答一覧');
  sheet.clearContents();
  sheet.appendRow(['シートID', 'シート名', '社員コード', '回答内容(JSON)']);
  result.forEach(r => sheet.appendRow([r.sheetId, r.sheetName, r.memberCode, JSON.stringify(r.answers)]));
}

要点まとめ

項目 内容
API 利用構成 シート一覧 → シート単位で回答レコード取得
汎用性 命名規則(例:週報_YYYYMMDD)により毎週の再利用可能
制限事項 レート制限/1リクエスト = 1シート分のみ取得可能
出力形式 Google スプレッドシートにJSON形式で出力可能
自動化手段 時間主導型のトリガー設定などで毎週自動実行

参考

Discussion