見出し画像

NotionとDomoをGoogleスプレッドシートでデータ連携する方法をご紹介:【連載】Notionでタスク管理&モチベーションアップ!第3回

こんにちは、アタラ合同会社コンサルタントの川田貴俊です。

前回の記事ではNotionのデータをDomoに取り込んでダッシュボードにしたものをご紹介しました。

連載第3回の今回は、ダッシュボードで使用しているデータの連携方法(主にNotion→Googleスプレッドシート)を解説します。

Domoには様々なSaaSツールからデータを接続することができるのですが、Notionから直接接続することはできません(Notionはデータを管理することを主としたツールではないので、当然と言えば当然のことですが)。そこで、中間にGoogle スプレッドシートを挟むことで、NotionからDomoへのデータ接続を実現しています。


Notion→Google スプレッドシートの連携

使ったツールは以下の2つです。

Google Apps Script (以下、GAS)
:Googleが提供する各種サービスの自動化/連携を行うためのローコード開発ツール※。

Notion API
:Notion のデータベースを操作するためのAPI※

※この記事を読まれる方はそれなりに技術に詳しい、あるいは自分で調べる意欲のある方だと思うので、技術的な用語の説明は省略します。

実装の大きな流れは下記のとおりです。

  1. Notionでの事前設定

  2. データ格納用のGoogle スプレッドシートを準備

  3. GASでNotion APIを実行するコード作成

  4. スケジュール実行の設定

1. Notionでの事前設定

ここでは

  1. インテグレーションの設定

  2. トークンの取得

  3. データベースの構造とIDの確認

  4. インテグレーションとデータベースを紐付ける

を行います。

こちらのサイトを大いに参考にさせていただきました。この記事がなかったらおそらく初めの時点で挫折してました。この場を借りて感謝申し上げます。

1.1. インテグレーションの設定

こちらのサイトから

「新しいインテグレーションを作成する」を選びます。

基本情報の設定を行えるので、

  • 「名前」を入力(ここでは、notion_tips100 としました)

  • 関連ワークスペースに、使用しているNotionスペースを選択

  • 「コンテンツを読み取る」にチェック

して、「送信」ボタンを押します。

1.2. トークンの取得

その後、シークレット情報が表示されるので、「トークン」を表示させて控えておきます。GASでコードを書く際に必要になります。

1.3. データベースの構造とIDの確認

対象となるNotionのデータベースの構造を確認しておきます。ここで言う構造とは、プロパティの名前、種類(テキスト型、日付型)等です。

IDはこのデータベースを識別するためのもので、URLから確認できます。下記太字に該当する32文字の英数字がIDとなります。
例 https://www.notion.so/2afb0XXXXXXXXXXXXXXXXXXXXXXXXX5e

1.4. インテグレーションとデータベースを紐付ける

下記手順で操作し、1.1.で作成したインテグレーションの名前を探して選択します(2022年10月ごろにNotionの仕様が変わって、以前と設定方法が変わったそうです。下記は2022年12月に確認した方法になります)。

これでNotion側の事前設定は終了です。

2. データ格納用のGoogle スプレッドシートを準備

データ出力先となるGoogle スプレッドシートを作成します。Notionデータベースと完全一致である必要はありませんが、カラム名や並びはできるだけ揃えておいた方が、後々の作業をしやすいです。

3. GASでNotion APIを実行するコード作成

スプレッドシートのメニュー「拡張機能>Apps Script」をクリック。

ファイル名を付けて(ここでは writing_export.gs としました)、下記のコードを貼り付けます。

//API取得に使用するデータをセット
function getNotionDbData(database_id, start_cursor_arg, page_size_arg) {
  const url = 'https://api.notion.com/v1/databases/' + database_id + '/query';
  const token = 'secret_oXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXI';
 
  let headers = {
    'content-type' : 'application/json; charset=UTF-8',
    'Authorization': 'Bearer ' + token,
    'Notion-Version': '2021-08-16',   
  }
  
 
  let pre_payload = {
    'page_size' : page_size_arg,
    'start_cursor' : start_cursor_arg, 
  }
 
  let options ={
    'method': 'post',
    'headers': headers,
    'payload': JSON.stringify(pre_payload),
  }
 
 
  let notion_data = UrlFetchApp.fetch(url, options);
  notion_data = JSON.parse(notion_data);
 
  return notion_data;
}
 
 
//スプレッドシートに書き込むようのメソッド
function writeSpreadSheet(sheet_name, target_array, loop_num, colmn){
  //スプレッドシートのシートのクラスを取得
  const kiji_sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheet_name);
  let row = 2 + loop_num * 100;
  
  //取得した配列をもとにスプレッドシートに記述する
    target_array.forEach((value) => {
      kiji_sheet.getRange(row, colmn).setValue(value);
      //次の行を作成するために1行追加
      row = row + 1;
  });
}
 
 
//スプレッドシートをリセットするメソッド
function resetSpreadSheet(sheet_name){
  //スプレッドシートのシートのクラスを取得
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheet_name);
  const lastRow = sheet.getLastRow();
  const lastCol = sheet.getLastColumn();
 
  
  //取得した配列をもとにスプレッドシートに記述する
    for(let col=1; col<=lastCol; col++){
      for(let row=2; row<=lastRow; row++){
        sheet.getRange(row, col).setValue("");
      }
    }
 
}
 
 
 
function notionDataToSpreadSheetKiji(){
  const sheet_name_kiji = 'デタコン記事執筆状況';
 
  let db_data=1;
  let nx_cursor;
  let kiji_datas;
  let kiji_ids;
 
  let kiji_titles;
  let kiji_persons;
  let kiji_statuses;
  let kiji_months;
  let kiji_mchk_dates;
  let kiji_fins;
  let kiji_mchk_nums;
  let kiji_pvs;
 
  let kiji_title;
  let kiji_person;
  let kiji_status;
  let kiji_month;
  let kiji_mchk_date;
  let kiji_fin;
  let kiji_mchk_num;
  let kiji_pv;
  let kiji_id;
 
  let loop_num = 0;
 
  resetSpreadSheet(sheet_name_kiji)
 
  do{
    //上記のgetNotionDbDataを実行してdb_dataに格納する
    if(db_data == 1){
      nx_cursor = undefined;
    }else{
      nx_cursor = db_data.next_cursor;
    }
 
    db_data = getNotionDbData('72XXXXXXXXXXXXXXXXXXXXXXXXXXXXe4', undefined, 100);
    kiji_datas = db_data.results;
 
    kiji_ids = [];
    kiji_titles = [];
    kiji_persons = [];
    kiji_statuses = [];
    kiji_months = [];
    kiji_mchk_dates = [];
    kiji_fins = [];
    kiji_mchk_nums = [];
    kiji_pvs = [];
 
 
    //スプレッドシートに格納する値を抽出して配列に格納する
    kiji_datas.forEach((kiji)=>{
      kiji_id = kiji.id;
      kiji_ids.push(kiji_id);
    
 
      //記事タイトルだけを取得して配列に格納する
      kiji_title = kiji.properties.名前.title[0];
      if(kiji_title === null || kiji_title === void 0)
        {kiji_titles.push("")}
      else
        {kiji_titles.push(kiji_title.text.content)}
      ;
 
 
      //記事の担当を取得して配列に格納する
      kiji_person = kiji.properties.担当.people[0];
      if(kiji_person === null || kiji_person === void 0)
        {kiji_persons.push("")}
      else
        {kiji_persons.push(kiji_person.name)}
      ;
 
 
      //記事のステータスを取得して配列に格納する
      kiji_status = kiji.properties.ステータス.select;
      if(kiji_status === null)
        {kiji_statuses.push("")}
      else
        {kiji_statuses.push(kiji_status.name)}
      ;
 
      //記事のカテゴリーを取得して配列に格納する
      kiji_month = kiji.properties.執筆納期.select;
      if(kiji_month === null)
        {kiji_months.push("")}
      else
        {kiji_months.push(kiji_month.name)}
      ;
 
      //記事のチェック依頼日を取得して配列に格納する
      kiji_mchk_date = kiji.properties.マーケ校正入.date;
      if(kiji_mchk_date === null)
        {kiji_mchk_dates.push("")}
      else
        {kiji_mchk_dates.push(kiji_mchk_date.start)}
      ;
 
      //記事の公開日を取得して配列に格納する
      kiji_fin = kiji.properties.掲載日.date;
      if(kiji_fin === null)
        {kiji_fins.push("")}
      else
        {kiji_fins.push(kiji_fin.start)}
      ;
 
      //記事のチェック項目数を取得して配列に格納する
      kiji_mchk_num = kiji.properties.マーケ提案数.number;
      if(kiji_mchk_num === null || kiji_mchk_num === void 0)
        {kiji_mchk_nums.push("")}
      else
        {kiji_mchk_nums.push(kiji_mchk_num)}
      ;
 
      //記事のPV数を取得するためのIDを取得して配列に格納する
      kiji_pv = kiji.properties.PV数紐づけID.rich_text[0];
      if(kiji_pv === null || kiji_pv === void 0)
        {kiji_pvs.push("")}
      else
        {kiji_pvs.push(kiji_pv.plain_text)}
      ;
    }
    )
 
    //スプレッドシートに書き込むメソッドを使用して配列の値を入力していく
    writeSpreadSheet(sheet_name_kiji, kiji_titles, loop_num, 1);
    writeSpreadSheet(sheet_name_kiji, kiji_persons, loop_num, 2);
    writeSpreadSheet(sheet_name_kiji, kiji_statuses, loop_num, 3);
    writeSpreadSheet(sheet_name_kiji, kiji_months, loop_num, 4);
    writeSpreadSheet(sheet_name_kiji, kiji_mchk_dates, loop_num, 5);
    writeSpreadSheet(sheet_name_kiji, kiji_fins, loop_num, 6)
    writeSpreadSheet(sheet_name_kiji, kiji_mchk_nums, loop_num, 7);
    writeSpreadSheet(sheet_name_kiji, kiji_pvs, loop_num, 8);
 
    loop_num++;
  }
  while(db_data.has_more == true);
 
}

この手の記事ではコードの解説をするのが普通だと思うのですが、そこは参考にさせていただいた記事に譲り、試行錯誤しながら解決してきた点をダイジェストで記載します。

Notion APIでは100行を超えるデータベースを一度に読み込めない

100行以下のデータベースであれば全く気にする必要はないですが、そうでない場合は読み込み方法を工夫する必要があります。

データベースを読み込んだ結果として、has_moreプロパティにそれ以降も行が続くかどうかがtrue/falseで返ってきます。trueの場合、次のカーソル位置がnext_cursorプロパティに格納されているので、続きはそこから読み込みを始め、falseなら終了という処理をする必要がありました。

参考させていただいたサイト

プロパティの種類に応じてコードを書き換える

当たり前と言えば当たり前ですが、プロパティの種類(テキスト型、日付型、セレクト型、マルチセレクト型、ユーザー型、etc)に応じて読み込む手順(コードの記述)も変えなければいけません。

Notionではシンプルに見えていても、内部のデータの持ち方は複雑な場合もあり、Notion APIの公式リファレンスと格闘しながら何度も試行錯誤しました。

4. スケジュール実行の設定

コード作成が終わったら画面左上の時計マークをクリックし、「トリガーを追加」をクリックします。「実行する関数を選択」へ、最初に実行する関数(このコードではnotionDataToSpreadSheetKiji)を選び、残りの項目も適宜設定します。

設定画面

これでNotion→Google スプレッドシートの連携は終了です。Google スプレッドシート→BIツールの設定は各ツールの手順に従って行います。

おわりに

私がNotionを使い始めたのはアタラに入社してからでした。あまりの便利さに魅了され、入社前から使っていたBIツールと組み合わせて、なにかできたらおもしろそうだなということはかなり初期から考えていました。

しかしやり始めたら、どうやってデータをつなぎこめばいいんだろう?という点から考える必要があり、自分としては先の見えない困難な道を選んでしまったなと感じた日もありました。いろいろなサイトを調べて先人達の知恵を拝借しながら歩みを進めて来ましたが、簡単に成功することは少なく、試行錯誤の連続でした。

ピンポイントで自分のやりたいことに合った情報はありませんでしたが、それらがあればこそヒントが手に入り、いろいろなことを試すことができたのは事実です。その結果、当初やりたかったこと以上のものを構築できました。今回の記事が同じような問題に困っている方の役に立てば嬉しく思います。

ここまで読んでいただき、ありがとうございました。

BIツールの活用やデータ活用を推進しよう

  • BIツールを導入したものの、うまく活用できていない

  • データ活用を組織に定着させるためのノウハウがない

  • 見るべき指標が複雑・多様化していて、どれを見ればよいのかわからない

  • ダッシュボード化の際、どのようなデータを取得すればいいかわからない

  • データがなかなか集められない

  • ビジネス課題解決のための指標を可視化し、すぐに判断したい

  • どのBIツールを選べばいいかわからない、選べない

という方は、まずはライトな相談から。支援内容とお問い合わせはこちらをクリック


※本記事の内容、所属等は公開日時点のものです。




この記事が参加している募集

アタラでは一緒に働くメンバーを募集しています