ノンプロ研GAS_freeeAPI講座で超初心者でもfreeeアプリが作れるようになった話
GAS_freeeAPI講座を無事に卒業
9月から始まったノンプロ研講座「GAS×freee APIコース」が、あっという間に卒業LT大会を迎えました🎉
私が参加していたのは、freeeのプレリリースにもあったこちらの講座です。
通常実務に追われる中、全くの0知識のプログラミングの演習・宿題をこなしていくのは、予想していたよりも本当に大変でした。かなり初期の頃から自力では宿題のコードを書けず、お手本の回答を写経するしかできない落ちこぼれ生徒となりました。
必死に食らいつき、なんとか全ての講座をauditし、卒業LT大会にも登壇することができ、個人的に大満足です。まじで自分、頑張った!(笑)
そして何より、素晴らしい講師陣&Teaching Assistantの方々のサポートのおかげです。本当にお世話になりありがとうございました。
卒業LTの登壇資料
メモ程度の内容ですが、SlideShareにアップしました。
卒業LTで作成した見積書一覧取得アプリ
私が卒業LTで作ったのは、freeeから見積書一覧を取得するアプリです。復習をかねて、大まかな作成の流れを書いてみることにします。
①事前準備
Googleスプレッドシートを用意、開発者用ページからfreeeアプリを作成し、スプレッドシートと連携させます。これで、スプレッドシートがアプリになります。
事前準備の詳細は、講座の講師をして下さったもりさんのブログで復習したいと思います。
②freeeの会計APIリファレンスを参照し、見積書一覧を取得してみる
下記のリクエストURLを使うと、見積書一覧の取得自体は割と簡単にできました。
ただこのままだと、全ての情報が取れてしまっている状態ですので、レスポンスの項目を定義してあげる必要があります。
また、freeeに登録されているすべての見積書が取れてしまうので、期間などの条件指定もしたいところです。
③オブジェクトとプロパティの構造を理解
まずは console.log(obj); でオブジェクトとプロパティの構造を理解します。
{ quotations:
[ { id: 27714577,
company_id: 2594733,
issue_date: '2021-05-05',
partner_id: 30735919,
partner_code: 'AAA株式会社',
title: '見積書',
total_amount: 330000,
total_vat: 30000,
sub_total: 300000,
description: '見積書a-1',
web_published_at: null,
web_downloaded_at: null,
web_confirmed_at: null,
mail_sent_at: null,
partner_name: 'AAA株式会社',
partner_title: '御中',
partner_zipcode: '',
partner_prefecture_code: null,
partner_prefecture_name: null,
partner_address1: '',
partner_address2: '',
partner_contact_info: '',
company_name: 'CSP_DEMO_ラパップ株式会社',
company_zipcode: '141-0031',
company_address1: '東京都 品川区西五反田2-8-1',
company_address2: '五反田ファーストビル 9F',
company_prefecture_code: 12,
company_prefecture_name: '東京都',
company_contact_info: '担当 佐々木',
message: '下記の通り御見積もり申し上げます。',
notes: '毎度ありがとうございますBB',
tax_entry_method: 'exclusive',
total_amount_per_vat_rate: [Object],
quotation_number: 'a-1',
partner_display_name: '㈱AAA(正式)',
quotation_status: 'unsubmitted',
quotation_layout: 'default_classic',
quotation_contents: [Object] },
{ id: 27714615,
company_id: 2594733,
issue_date: '2021-06-05',
partner_id: 30735919,
partner_code: 'AAA株式会社',
title: '見積書',
total_amount: 330000,
total_vat: 30000,
sub_total: 300000,
description: '見積書a-2',
web_published_at: null,
web_downloaded_at: null,
web_confirmed_at: null,
mail_sent_at: null,
partner_name: 'AAA株式会社',
partner_title: '御中',
partner_zipcode: '',
partner_prefecture_code: null,
partner_prefecture_name: null,
partner_address1: '',
partner_address2: '',
partner_contact_info: '',
company_name: 'CSP_DEMO_ラパップ株式会社',
company_zipcode: '141-0031',
company_address1: '東京都 品川区西五反田2-8-1',
company_address2: '五反田ファーストビル 9F',
company_prefecture_code: 12,
company_prefecture_name: '東京都',
company_contact_info: '担当 佐々木',
message: '下記の通り御見積もり申し上げます。',
notes: '毎度ありがとうございますBB',
tax_entry_method: 'exclusive',
total_amount_per_vat_rate: [Object],
quotation_number: 'a-2',
partner_display_name: '㈱AAA(正式)',
quotation_status: 'unsubmitted',
quotation_layout: 'default_classic',
quotation_contents: [Object] } ] }
:
見積書はquotationsプロパティの中に配列で存在し、詳細行はさらにその下のquotation_contentsプロパティの中に配列で存在することがわかりました。
オプジェクトとプロパティについてはノンプロ研主宰・高橋さんのブログで復習したいと思います。
④for文で配列の中身を繰り返し取得する
for…of分は配列[]の要素(中身)をひとつづつ終わりまですべて取り出してくれる便利な構文です。
for (const 定数 of 配列) {
// 処理 例:console.log(定数);
}
例えばsheetsという配列[]があったとして
for (const sheet of sheets)だとsheetsの中身をひとつづつsheetという名前で取り出して処理していくイメージのようです。
GAS講座では、演習3-10でやりました。
function myFunction3_10() {
const members = ['Bob', 'Tom', 'Jay', 'Tom'];
for(const member of members) {
console.log(member);
}
}
このfor of文を使って、見積書のデータを1つずつ取り出すことにしました。
for (const quotation of obj.quotations) {
⑤取得したい項目(プロパティ)を指定する
このままだとまだすべての項目が取れてしまうので、取得したい項目だけを取るような指定が必要です。
ここで、freeeAPIで超重要なオブジェクトの分割代入を使います。
まず、リファレンスで見積書一覧の取得のResponsesを確認し、取得したいレスポンスのプロパティを確認します。
私が取り出したいのは、見積日/取引先名/見積番号/見積書概要/行の種類/詳細/備考/数量/単位/単価/金額/消費税/合計金額 ですので、これらのプロパティを確認します。
オブジェクトの分割代入について講座の補助資料で復習したので、備忘メモとして残したいと思います。
講座の補助資料より
「オブジェクトの分割代入」とは、オブジェクトからプロパティを取り出して、個別の変数に代入する構文です。個別の変数には、プロパティ名を指定します。
const { プロパティ名1, プロパティ名2, ... } = オブジェクト
一般的なプロパティの代入
function myFunction01() {
const obj = { id: 'A001', name: 'Bob', age: 30 };
const name = obj.name;
const age = obj.age;
console.log(name, age);
}
実行結果
オブジェクトの分割代入
function myFunction02() {
const obj = { id: 'A001', name: 'Bob', age: 30 };
const { age, name } = obj;
console.log(name, age);
}
実行結果は同じですが、const { プロパティ名1, プロパティ名2, ... } = オブジェクト の形で取り出すことができました。
講座の補助資料より
メリット:オブジェクトの中から抜き出したいプロパティが増えたときに、{ }の中にプロパティ名を追加するだけでよい。
freee APIでは多くのプロパティを扱うので、ぜひ覚えておきましょう。
以下のようにオブジェクトの分割代入をすることができました。
const { issue_date, partner_name, quotation_number, description, total_amount } = quotation;
ここでポイント!
見積書はquotationsプロパティの中に配列で存在し、詳細行はさらにその下のquotation_contentsプロパティの中に配列で存在するので、for of文も、分割代入も、quotationsとquotation_contentsで分けて書く必要があります。
for (const quotation_content of quotation.quotation_contents) {
const { type, description, qty, unit, unit_price, amount, vat } = quotation_content;
これで、quotationsとquotation_content両方について、指定した項目を繰り返し取得することができました。
⑥プロパティ:discriptionが2つある問題の解消
もう完成!と思ったのですが、freeeの見積書一覧のプロパティでは、descriptionが2つ存在するという罠がありました。
const { issue_date, partner_name, quotation_number, description, total_amount } = quotation; //リファレンスと同じ名前じゃなきゃダメ
const description1 = description; //使いたい変数に渡す
const { type, description, qty, unit, unit_price, amount, vat } = quotation_content;
const description2 = description;
上記のように分割代入時にはリファレンス通りのdiscriptionを設定し、その下に使いたい変数に渡すという処理をする必要がありました。これはとても難しかったです。
⑦スプレッドシートに出力するための準備
いよいよ仕上げです。
オブジェクトから取り出した値については、このままだとうまく出力されないので、スプレッドシートに書き込むために二次元配列にする必要があります。
まず以下のように見出し行を二次元配列で宣言します。[[ ]]となっていることがポイントです。
const arrayData = [['見積日', '取引先名', '見積番号', '見積書概要', '行の種類', '詳細/備考', '数量', '単位', '単価', '金額', '消費税', '合計金額']];
演習3-13を復習しました。
そして、push()メソッドを使います。push()メソッドは配列に要素を追加するメソッドです。見出し行がすでにconst arrayData = で指定してあるので、そこに追加していきます。
arrayData.push([issue_date, partner_name, quotation_number, description1, type, description2, qty, unit, unit_price, amount, vat, total_amount]);
⑧スプレッドシートに出力
いよいよスプレッドシートへの出力です。
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('見積書一覧取得'); // 書き出すシートを名前で指定
sheet.getRange(1, 1, arrayData.length, arrayData[0].length).setValues(arrayData);
無事にスプレッドシートへの出力ができました!
補足:検索条件の指定
データの検索条件についてはParametersで指定することができます。
基本のリクエストURLに&&&で条件をくっつけていくイメージです。
try it out>Executeの機能を使えば自動で作成されます。
ただ、データ取得のたびにスクリプトエディタを開いてコードを書き換えるのは非実務的なので、実務ではスプレッドシート上で検索条件を設定する仕組みを作る必要があります。
見積の開始日と終了日をシート上で指定し、その期間の見積書だけを取得できるようにしました。
const sheetParams = ss1.getSheetByName('設定'); // 読み込むシートを名前で指定
const start_issue_date = sheetParams.getRange('B2').getValue();
const end_issue_date = sheetParams.getRange('B3').getValue();
let url = `https://api.freee.co.jp/api/1/quotations/?company_id=${company_id}&limit=100`;
// 決済状況に何か値がセットされている時だけURLに追加する
if (start_issue_date) {
url += `&start_issue_date=${start_issue_date}`;
}
if (end_issue_date) {
url += `&end_issue_date=${end_issue_date}`;
}