このページでは、初学者向けに、freee会計APIと「 Google Apps Script」を連携して、Google スプレッドシートにデータを出力するまでを動画を使いながら学びます。
※本動画およびサンプルコードは、自習のためのサンプル動画・コードとなり、サポート対象外となります。動画・コードに対するご質問へのご回答・サポートは行なっておりませんので、ご了承ください。
準備するもの
Googleスプレッドシートを使うためのGoogleアカウントをご準備ください。
1. Googleスプレッドシートの動作確認
この動画では、freee会計 API と連携するための Googleスプレッドシートを準備し、Google Apps Scriptが動作するかどうかを確認します。
この動画内で利用しているコードは以下です。
freeeを試すコード.gs
function myFunction() {
Logger.log("今からメッセージを出力します");
Browser.msgBox("I’m freee");
Logger.log("メッセージを出力しました");
const Sheet = SpreadsheetApp.getActiveSheet();
Sheet.getRange(1,2).setValue("ここに値を表示");
}
2. Google OAuth 2.0 クライアントIDの登録
この動画では、freee会計 API の操作に必要な認可手順「OAuth 2.0」を使えるようにするための設定を行います。
動画内に表示される「OAuth2ライブラリ」のスクリプトIDは以下となります。
1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF
コールバックURIの文字列は以下となります。
https://script.google.com/macros/d/{SCRIPT ID}/usercallback
URI中の {SCRIPT ID}は、Sclipt IDは、Googe Apps Scriptのエディタ画面で確認できます。スプレッドシート上部のメニューから [ツール]→[スクリプトエディタ]からエディタ画面を開き、左メニューから[プロジェクトの設定]→[ID]→[スクリプトID]の順に確認してください。
3. Google スプレッドシートの動作確認
この動画では、Google スプレッドシートとfreee会計APIを連携し、事業所のIDを取得するまでを行います。
この動画内で利用しているコードは以下です。
freee_GoogleAppsScript3.gs
const Client_ID = '「Client ID」';
const Client_Secret = '「Client Secret」';
function alertAuth() {
var service = getService();
var authorizationUrl = service.getAuthorizationUrl();
Logger.log(authorizationUrl);
}
function getService() {
return OAuth2.createService('freee')
.setAuthorizationBaseUrl('https://accounts.secure.freee.co.jp/public_api/authorize')
.setTokenUrl('https://accounts.secure.freee.co.jp/public_api/token')
.setClientId(Client_ID)
.setClientSecret(Client_Secret)
.setCallbackFunction('authCallback')
.setPropertyStore(PropertiesService.getUserProperties())
}
function authCallback(request) {
var service = getService();
var isAuthorized = service.handleCallback(request);
if (isAuthorized){
return HtmlService.createHtmlOutput('認証が成功したのでタブを閉じてください');
} else {
return HtmlService.createHtmlOutput('認証に失敗しています');
}
}
function getJigyousho() {
const accessToken = getService().getAccessToken();
const requestUrl = 'https://api.freee.co.jp/api/1/companies';
const params = {
method: 'get',
headers:{'Authorization':'Bearer ' + accessToken}
};
const response = UrlFetchApp.fetch(requestUrl, params);
Logger.log(response);
const Sheets = SpreadsheetApp.getActiveSheet();
Sheets.getRange(1,2).setValue(JSON.parse(response).companies[0].id);
}
4. 取引先の取得
この動画では、取引先データを取得するまでを行います。
この動画内で利用しているコードは以下です。
freee_GoogleAppsScript4.gs
const Client_ID2 = '「Client ID」';
const Client_Secret2 = '「Client Secret」';
//認証のエンドポイント
function alertAuth2() {
const service = getService2();
const authorizationUrl = service.getAuthorizationUrl();
Logger.log(authorizationUrl);//認証用URLがログ出力される
}
//freeeAPIのサービスを取得
function getService2() {
return OAuth2.createService('freee')
.setAuthorizationBaseUrl('https://accounts.secure.freee.co.jp/public_api/authorize')
.setTokenUrl('https://accounts.secure.freee.co.jp/public_api/token')
.setClientId(Client_ID2)
.setClientSecret(Client_Secret2)
.setCallbackFunction('authCallback')
.setPropertyStore(PropertiesService.getUserProperties())
}
//認証コールバック関数
function authCallback(request) {
const service = getService2();
const isAuthorized = service.handleCallback(request);
if (isAuthorized) {
return HtmlService.createHtmlOutput('認証に成功しました。タブを閉じてください。');
} else {
return HtmlService.createHtmlOutput('認証に失敗しました。');
}
}
//取引先を取得
function getTorihikisaki() {
const Sheets = SpreadsheetApp.getActiveSheet();
const accessToken = getService2().getAccessToken();
const requestUrl = 'https://api.freee.co.jp/api/1/partners?company_id=' + Sheets.getRange(1,2).getValue();
const params = {
method: 'get',
headers:{'Authorization':'Bearer ' + accessToken}
};
const response = UrlFetchApp.fetch(requestUrl, params);
Logger.log(response);
for(let i = 0; i < JSON.parse(response).partners.length; i++) {
Sheets.getRange(i + 5,2).setValue(JSON.parse(response).partners[i].id);
Sheets.getRange(i + 5,3).setValue(JSON.parse(response).partners[i].name);
}
}
//取引先の詳細を取得
function getTorihikisakiDetail() {
const Sheets = SpreadsheetApp.getActiveSheet();
const accessToken = getService2().getAccessToken();
const requestUrl = 'https://api.freee.co.jp/api/1/partners/' + Sheets.getRange(5,2).getValue() + '?company_id=' + Sheets.getRange(1,2).getValue();
const params = {
method: 'get',
headers:{'Authorization':'Bearer ' + accessToken}
};
const response = UrlFetchApp.fetch(requestUrl, params);
Logger.log(response);
Logger.log(JSON.parse(response).partner.id.name);
if (JSON.parse(response).partner.name) {
Sheets.getRange(5,4).setValue(JSON.parse(response).partner.long_name);
Sheets.getRange(5,5).setValue(JSON.parse(response).partner.name_kana);
Sheets.getRange(5,6).setValue(JSON.parse(response).partner.address_attributes.street_name1);
Sheets.getRange(5,7).setValue(JSON.parse(response).partner.email);
Sheets.getRange(5,8).setValue(JSON.parse(response).partner.phone);
}
}
5. 取引先の追加
この動画では、取引先データをfreee会計に追加するまでを行います。
この動画内で利用しているコードは以下です。
freee_GoogleAppsScript5.gs
const Client_ID3 = '「Client ID」';
const Client_Secret3 = '「Client Secret」';
//認証のエンドポイント
function alertAuth3() {
const service = getService3();
const authorizationUrl = service.getAuthorizationUrl();
Logger.log(authorizationUrl);//認証用URLがログ出力される
}
//freeeAPIのサービスを取得
function getService3() {
return OAuth2.createService('freee')
.setAuthorizationBaseUrl('https://accounts.secure.freee.co.jp/public_api/authorize')
.setTokenUrl('https://accounts.secure.freee.co.jp/public_api/token')
.setClientId(Client_ID3)
.setClientSecret(Client_Secret3)
.setCallbackFunction('authCallback')
.setPropertyStore(PropertiesService.getUserProperties())
}
//認証コールバック関数
function authCallback(request) {
var service = getService3();
var isAuthorized = service.handleCallback(request);
if (isAuthorized) {
return HtmlService.createHtmlOutput('認証に成功しました。タブを閉じてください。');
} else {
return HtmlService.createHtmlOutput('認証に失敗しました。');
}
}
//取引先を追加
function postTorihikisaki() {
const Sheets = SpreadsheetApp.getActiveSheet();
const accessToken = getService3().getAccessToken();
const requestUrl = 'https://api.freee.co.jp/api/1/partners';
const body = {
'company_id': parseInt(Sheets.getRange(1,2).getValue(), 10),
'name': Sheets.getRange(3,3).getValue(),
'long_name': Sheets.getRange(3,4).getValue(),
'name_kana': Sheets.getRange(3,5).getValue(),
'address_attributes': {
'street_name1': Sheets.getRange(3,6).getValue()
},
'email': Sheets.getRange(3,7).getValue(),
'phone': Sheets.getRange(3,8).getValue()
};
const params = {
method: 'post',
headers: {
'Authorization':'Bearer ' + accessToken,
},
'contentType': 'application/json',
payload: JSON.stringify(body)
};
const response = UrlFetchApp.fetch(requestUrl, params);
Logger.log(response);
}
6. 取引先情報の編集
この動画では、freee会計の取引先情報の編集を行います。
この動画内で利用しているコードは以下です。
freee_GoogleAppsScript6.gs
const Client_ID4 = '「Client ID」';
const Client_Secret4 = '「Client Secret」';
//「認証のエンドポイント」関数を貼り付け
function showAuth4() {
const service = getService4();
const authorizationUrl = service.getAuthorizationUrl();
Logger.log(authorizationUrl);
}
//freeeAPIのサービスを取得
function getService4() {
return OAuth2.createService('freee')
.setAuthorizationBaseUrl('https://accounts.secure.freee.co.jp/public_api/authorize')
.setTokenUrl('https://accounts.secure.freee.co.jp/public_api/token')
.setClientId(Client_ID4)
.setClientSecret(Client_Secret4)
.setCallbackFunction('authCallback')
.setPropertyStore(PropertiesService.getUserProperties())
}
//認証コールバック関数
function authCallback(request) {
const service = getService4();
const isAuthorized = service.handleCallback(request);
if (isAuthorized){
return HtmlService.createHtmlOutput('認証が成功したのでタブを閉じてください');
} else {
return HtmlService.createHtmlOutput('認証に失敗しています');
}
}
//取引先を取得
function getTorihikisaki2() {
const Sheets = SpreadsheetApp.getActiveSheet();
const accessToken = getService4().getAccessToken();
const requestUrl = 'https://api.freee.co.jp/api/1/partners?company_id=' + Sheets.getRange(1,2).getValue();
const params = {
method: 'get',
headers:{'Authorization':'Bearer ' + accessToken}
};
const response = UrlFetchApp.fetch(requestUrl, params);
// Logger.log(response);
for(let i = 0; i < JSON.parse(response).partners.length; i++) {
Sheets.getRange(i + 5,2).setValue(JSON.parse(response).partners[i].id);
Sheets.getRange(i + 5,3).setValue(JSON.parse(response).partners[i].name);
}
}
//取引先の詳細を取得
function getTorihikisakiDetail2() {
const Sheets = SpreadsheetApp.getActiveSheet();
const accessToken = getService4().getAccessToken();
const requestUrl = 'https://api.freee.co.jp/api/1/partners/' + Sheets.getRange(5,2).getValue() + '?company_id=' + Sheets.getRange(1,2).getValue();
const params = {
method: 'get',
headers:{'Authorization':'Bearer ' + accessToken}
};
const response = UrlFetchApp.fetch(requestUrl, params);
Logger.log(response);
Logger.log(JSON.parse(response).partner.id.name);
if (JSON.parse(response).partner.name) {
Sheets.getRange(5,4).setValue(JSON.parse(response).partner.long_name);
Sheets.getRange(5,5).setValue(JSON.parse(response).partner.name_kana);
Sheets.getRange(5,6).setValue(JSON.parse(response).partner.address_attributes.street_name1);
Sheets.getRange(5,7).setValue(JSON.parse(response).partner.email);
Sheets.getRange(5,8).setValue(JSON.parse(response).partner.phone);
}
}
//取引先の編集&更新
function putTorihikisaki() {
const Sheets = SpreadsheetApp.getActiveSheet();
const accessToken = getService4().getAccessToken();
const requestUrl = 'https://api.freee.co.jp/api/1/partners/' + Sheets.getRange(5,2).getValue();
const body = {
'company_id': parseInt(Sheets.getRange(1,2).getValue(), 10),
'name': Sheets.getRange(5,3).getValue(),
'long_name': Sheets.getRange(5,4).getValue(),
'name_kana': Sheets.getRange(5,5).getValue(),
'address_attributes': {
'street_name1': Sheets.getRange(5,6).getValue()
},
'email': Sheets.getRange(5,7).getValue(),
'phone': Sheets.getRange(5,8).getValue()
};
const params = {
method: 'put',
headers: {
'Authorization':'Bearer ' + accessToken,
},
'contentType': 'application/json',
payload: JSON.stringify(body)
};
const response = UrlFetchApp.fetch(requestUrl, params);
Logger.log(response);
}
7. 税区分、勘定科目の取得
この動画では、freee会計から税区分と勘定科目を取得しています。
この動画内で利用しているコードは以下です。
freee_GoogleAppsScript7.gs
const Client_ID5 = '[Client_ID]';
const Client_Secret5 = '[Client_Secret]';
//認証のエンドポイント
function showAuth5() {
const service = getService5();
const authorizationUrl = service.getAuthorizationUrl();
Logger.log(authorizationUrl);//認証用URLがログ出力される
}
//freeeAPIのサービスを取得
function getService5() {
return OAuth2.createService('freee')
.setAuthorizationBaseUrl('https://accounts.secure.freee.co.jp/public_api/authorize')
.setTokenUrl('https://accounts.secure.freee.co.jp/public_api/token')
.setClientId(Client_ID5)
.setClientSecret(Client_Secret5)
.setCallbackFunction('authCallback')
.setPropertyStore(PropertiesService.getUserProperties())
}
//認証コールバック関数
function authCallback(request) {
const service = getService5();
const isAuthorized = service.handleCallback(request);
if (isAuthorized) {
return HtmlService.createHtmlOutput('認証に成功しました。タブを閉じてください。');
} else {
return HtmlService.createHtmlOutput('認証に失敗しました。');
}
}
//税区分を取得
function getZeikubun() {
const Sheets = SpreadsheetApp.getActiveSheet();
const accessToken = getService2().getAccessToken();
const requestUrl = 'https://api.freee.co.jp/api/1/taxes/codes?company_id=' + Sheets.getRange(1,2).getValue();
const params = {
method: 'get',
headers:{'Authorization':'Bearer ' + accessToken}
};
const response = UrlFetchApp.fetch(requestUrl, params);
Logger.log(response);
for(let i = 0; i < JSON.parse(response).taxes.length; i++) {
Sheets.getRange(i + 3,2).setValue(JSON.parse(response).taxes[i].code);
Sheets.getRange(i + 3,3).setValue(JSON.parse(response).taxes[i].name);
Sheets.getRange(i + 3,4).setValue(JSON.parse(response).taxes[i].name_ja);
}
}
//勘定科目を取得
function getKanjoukamoku() {
const Sheets = SpreadsheetApp.getActiveSheet();
const accessToken = getService2().getAccessToken();
const requestUrl = 'https://api.freee.co.jp/api/1/account_items/?company_id=' + Sheets.getRange(1,2).getValue();
const params = {
method: 'get',
headers:{'Authorization':'Bearer ' + accessToken}
};
const response = UrlFetchApp.fetch(requestUrl, params);
Logger.log(response);
for(let i = 0; i < JSON.parse(response).account_items.length; i++) {
Sheets.getRange(i + 3,5).setValue(JSON.parse(response).account_items[i].id);
Sheets.getRange(i + 3,6).setValue(JSON.parse(response).account_items[i].name);
Sheets.getRange(i + 3,7).setValue(JSON.parse(response).account_items[i].shortcut);
}
}
//勘定科目の詳細を取得
function getKanjoukamokuDetail() {
const Sheets = SpreadsheetApp.getActiveSheet();
const accessToken = getService2().getAccessToken();
const requestUrl = 'https://api.freee.co.jp/api/1/account_items/' + '?company_id=' + Sheets.getRange(1,2).getValue();
const params = {
method: 'get',
headers:{'Authorization':'Bearer ' + accessToken}
};
const response = UrlFetchApp.fetch(requestUrl, params);
Logger.log(response);
for(let i = 0; i < JSON.parse(response).account_items.length; i++) {
Sheets.getRange(i + 3,8).setValue(JSON.parse(response).account_items[i].account_category);
Sheets.getRange(i + 3,9).setValue(JSON.parse(response).account_items[i].corresponding_income_name);
}
}
8. 仕訳の登録
この動画では、Googleスプレッドシートから仕訳のデータ登録を行います。
この動画内で利用しているコードは以下です。
freee_GoogleAppsScript8.gs
const Client_ID6 = '「Client ID」';
const Client_Secret6 = '「Client Secret」';
//認証のエンドポイント
function showAuth6() {
const service = getService6();
const authorizationUrl = service.getAuthorizationUrl();
Logger.log(authorizationUrl);
}
//freeeAPIのサービスを取得
function getService6() {
return OAuth2.createService('freee')
.setAuthorizationBaseUrl('https://accounts.secure.freee.co.jp/public_api/authorize')
.setTokenUrl('https://accounts.secure.freee.co.jp/public_api/token')
.setClientId(Client_ID6)
.setClientSecret(Client_Secret6)
.setCallbackFunction('authCallback')
.setPropertyStore(PropertiesService.getUserProperties())
}
//認証コールバック関数
function authCallback(request) {
const service = getService6();
const isAuthorized = service.handleCallback(request);
if (isAuthorized){
return HtmlService.createHtmlOutput('認証が成功したのでタブを閉じてください');
} else {
return HtmlService.createHtmlOutput('認証に失敗しています');
}
}
//仕分けを登録
function postDeals() {
const detailData = function(record) {
const postDetailRecords = [];
for (let row = 0; row < 1; row++) {
postDetailRecords[row] = {
tax_code: Sheets.getRange(4,4).getValue(),
account_item_id: Sheets.getRange(4,5).getValue(),
amount: parseInt(Sheets.getRange(4,6).getValue(), 10),
description: Sheets.getRange(4,7).getValue()
};
}
return postDetailRecords;
};
const Sheets = SpreadsheetApp.getActiveSheet();
const accessToken = getService6().getAccessToken();
const requestUrl = 'https://api.freee.co.jp/api/1/deals';
const body = {
'issue_date': Sheets.getRange(4,1).getDisplayValue(), // =TODAY()関数をセルに設定
'type': Sheets.getRange(4,2).getValue(),
'company_id': parseInt(Sheets.getRange(1,2).getValue(), 10),
'partner_id': Sheets.getRange(4,3).getValue(),
'details': detailData(),
};
const params = {
method: 'post',
headers: {
'Authorization':'Bearer ' + accessToken,
},
'contentType': 'application/json',
payload: JSON.stringify(body)
};
const response = UrlFetchApp.fetch(requestUrl, params);
Logger.log(response);
}
9. 経費精算の追加
この動画では、シートから経費精算の登録を行っています。
この動画内で利用しているコードは以下です。
freee_GoogleAppsScript9.gs
const Client_ID7 = '[Client_ID]';
const Client_Secret7 = '[Client_Secret]';
//認証のエンドポイント
function showAuth7() {
const service = getService7();
const authorizationUrl = service.getAuthorizationUrl();
Logger.log(authorizationUrl);
}
//freeeAPIのサービスを取得
function getService7() {
return OAuth2.createService('freee')
.setAuthorizationBaseUrl('https://accounts.secure.freee.co.jp/public_api/authorize')
.setTokenUrl('https://accounts.secure.freee.co.jp/public_api/token')
.setClientId(Client_ID7)
.setClientSecret(Client_Secret7)
.setCallbackFunction('authCallback')
.setPropertyStore(PropertiesService.getUserProperties())
}
//認証コールバック関数
function authCallback(request) {
const service = getService7();
const isAuthorized = service.handleCallback(request);
if (isAuthorized){
return HtmlService.createHtmlOutput('認証が成功したのでタブを閉じてください');
} else {
return HtmlService.createHtmlOutput('認証に失敗しています');
}
}
//経費申請の作成
function postExpenses() {
const detailData = function(record) {
const postDetailRecords = [];
for (let row = 0; row < 1; row++) {
postDetailRecords[row] = {
'transaction_date': Sheets.getRange(3,4).getDisplayValue(),
'description': Sheets.getRange(3,5).getValue(),
'amount': parseInt(Sheets.getRange(3,6).getValue(), 10)
};
}
return postDetailRecords;
};
const Sheets = SpreadsheetApp.getActiveSheet();
const accessToken = getService7().getAccessToken();
const requestUrl = 'https://api.freee.co.jp/api/1/expense_applications';
const body = {
'company_id': parseInt(Sheets.getRange(1,2).getValue(), 10),
'title': Sheets.getRange(3,1).getValue(),
'issue_date': Sheets.getRange(3,2).getDisplayValue(),
'description': Sheets.getRange(3,3).getValue(),
'expense_application_lines': detailData(),
};
const params = {
method: 'post',
headers: {
'Authorization':'Bearer ' + accessToken,
},
'contentType': 'application/json',
payload: JSON.stringify(body)
};
const response = UrlFetchApp.fetch(requestUrl, params);
Logger.log(response);
}
10. 請求書の登録
この動画では、請求書発行のためのデータをシートから登録しています。
この動画内で利用しているコードは以下です。
freee_GoogleAppsScript10.gs
const Client_ID8 = '[Client_ID]';
const Client_Secret8 = '[Client_Secret]';
//認証のエンドポイント
function showAuth8() {
const service = getService8();
const authorizationUrl = service.getAuthorizationUrl();
Logger.log(authorizationUrl);
}
//freeeAPIのサービスを取得
function getService8() {
return OAuth2.createService('freee')
.setAuthorizationBaseUrl('https://accounts.secure.freee.co.jp/public_api/authorize')
.setTokenUrl('https://accounts.secure.freee.co.jp/public_api/token')
.setClientId(Client_ID8)
.setClientSecret(Client_Secret8)
.setCallbackFunction('authCallback')
.setPropertyStore(PropertiesService.getUserProperties())
}
//認証コールバック関数
function authCallback(request) {
const service = getService8();
const isAuthorized = service.handleCallback(request);
if (isAuthorized){
return HtmlService.createHtmlOutput('認証が成功したのでタブを閉じてください');
} else {
return HtmlService.createHtmlOutput('認証に失敗しています');
}
}
//請求書の登録
function postInvoices() {
const detailData = function(record) {
const postDetailRecords = [];
for (let row = 0; row < 1; row++) {
postDetailRecords[row] = {
'order': row,
'type': Sheets.getRange(4,12).getValue(),
'qty': parseInt(Sheets.getRange(4,13).getValue(), 10),
'unit': Sheets.getRange(4,14).getValue(),
'unit_price': parseInt(Sheets.getRange(4,15).getValue(), 10),
'vat': parseInt(Sheets.getRange(4,16).getValue(), 10),
'description': Sheets.getRange(4,17).getValue(),
'tax_code': Sheets.getRange(4,18).getValue(),
'account_item_id': Sheets.getRange(4,19).getValue()
};
}
return postDetailRecords;
};
const Sheets = SpreadsheetApp.getActiveSheet();
const accessToken = getService8().getAccessToken();
const requestUrl = 'https://api.freee.co.jp/api/1/invoices';
const body = {
'company_id': parseInt(Sheets.getRange(1,2).getValue(), 10),
'issue_date': Sheets.getRange(4,1).getDisplayValue(),
'partner_id': Sheets.getRange(4,2).getValue(),
'title': Sheets.getRange(4,3).getValue(),
'invoice_status': Sheets.getRange(4,4).getValue(),
'partner_display_name': Sheets.getRange(4,5).getValue(),
'partner_title': Sheets.getRange(4,6).getValue(),
'partner_zipcode': Sheets.getRange(4,7).getValue(),
'payment_type': Sheets.getRange(4,8).getValue(),
'message': Sheets.getRange(4,9).getValue(),
'notes': Sheets.getRange(4,10).getValue(),
'tax_entry_method': Sheets.getRange(4,11).getValue(),
'invoice_contents': detailData(),
};
const params = {
method: 'post',
headers: {
'Authorization':'Bearer ' + accessToken,
},
'contentType': 'application/json',
payload: JSON.stringify(body)
};
const response = UrlFetchApp.fetch(requestUrl, params);
Logger.log(response);
}