GPTs×GASで作る!実践的レシート読み取りアプリの作り方

この記事は約10分で読めます。

サステックスのエンジニア、鈴木です。

近年の生成AIバブルによって、様々な企業やユーザーがLLMやAIのツールやサービスを提供するようになってきました。昔からキャッチアップが大変な業界でしたが、さらに最新の情報をキャッチアップする必要が出てきました。

本記事では、GPTs×GASを活用して、レシート読み取りアプリを作成したので、解説していきます。

目次

はじめに

業務効率化のニーズが高まる中、特に経理業務における領収書管理は多くの企業が抱える課題となっています。今回は、この課題を解決するため、GPTsとGoogle Apps Script(GAS)を組み合わせたレシート読み取りアプリケーションの開発プロセスをご紹介します。このアプリは、レシート画像から必要な情報を自動的に抽出し、スプレッドシートに記録する機能を実現します。

開発方針の決定(なぜGPTsとGASを選んだのか)

技術選定においては、開発効率と実用性のバランスを重視しました。GPTsは高度な画像認識能力を持ち、テキスト抽出の精度が高いという特徴があります。一方、GASはGoogleスプレッドシートとの親和性が高く、環境構築が不要で即座に開発に着手できるという利点があります。また、無料で利用できる点も、プロジェクトの初期段階での採用を後押しする要因となりました。

GPTsの実装 〜GPTsの基本設定とアクションの設定〜

GPTsの実装では、「レシート読み取りアプリ」という名前で、シンプルながら実用的なシステムを構築しました。以下が具体的な実装コードです。

※ 今回は、購入日、店舗、品物、金額という基本的な情報を読み取り項目として設定しました。 以下のコードを、GPTs設定画面のアクション > スキーマに追加してください。

openapi: 3.1.0

info:

  title: Receipt Data API

  version: 1.0.0

  description: API for receiving receipt data

servers:

  - url: "https://script.google.com"

paths:

  /macros/s/{GASのデプロイID}/exec:

    post:

      summary: Receive receipt data

      description: Endpoint to receive receipt data in JSON format

      operationId: receiveReceiptData

      requestBody:

        required: true

        content:

          application/json:

            schema:

              type: object

              properties:

                purchase_date:

                  type: string

                  format: date

                  example: "2025-01-19"

                  description: "Date of purchase"

                store_name:

                  type: string

                  example: "株式会社ABC"

                  description: "Name of the store"

                description:

                  type: string

                  example: "ソフトウェア開発費用"

                  description: "Description of the purchase"

                amount:

                  type: integer

                  example: 98000

                  description: "Amount of the purchase"

              required:

                - purchase_date

                - store_name

                - description

                - amount

      responses:

        "200":

          description: Successfully received receipt data

          content:

            application/json:

              schema:

                type: object

                properties:

                  message:

                    type: string

                    example: "Receipt data received successfully"

        "400":

          description: Bad Request

          content:

            application/json:

              schema:

                type: object

                properties:

                  message:

                    type: string

                    example: "Invalid input"

        "500":

          description: Internal Server Error

          content:

            application/json:

              schema:

                type: object

                properties:

                  message:

                    type: string

                    example: "An error occurred while processing the request"

GASの実装

以下のようなコードを使用してスプレッドシートとの連携を実現しています:

// リクエストを処理し、レシートデータをスプレッドシートに保存する関数

function doPost(e) {

  try {

    // リクエストの検証

    if (!e || !e.postData || !e.postData.contents) {

      throw new Error("Invalid request format");

    }

    // JSONデータをパースして取得

    const json = JSON.parse(e.postData.contents);

    // 必須フィールドの存在チェック

    validateRequestData(json);

    // データの正規化(日付フォーマットの統一、金額の数値化など)

    const normalizedData = normalizeData(json);

    // スプレッドシートへの書き込み

    const result = writeToSpreadsheet(normalizedData);

    // 成功レスポンスを返す

    return createJsonResponse({

      status: "success",

      message: "Data successfully saved",

      savedData: normalizedData,

      rowNumber: result.rowNumber

    }, 200);

  } catch (error) {

    // エラーログの記録

    Logger.log(`Error: ${error.toString()}\nStack: ${error.stack}`);

    // エラーレスポンスを返す

    return createJsonResponse({

      status: "error",

      message: error.message,

      details: error.toString()

    }, 400);

  }

}

// リクエストデータのバリデーション

function validateRequestData(data) {

  const requiredFields = ['purchase_date', 'store_name', 'description', 'amount'];

  const missingFields = requiredFields.filter(field => !data[field]);

  if (missingFields.length > 0) {

    throw new Error(`Missing required fields: ${missingFields.join(', ')}`);

  }

}

// データの正規化

function normalizeData(data) {

  return {

    purchase_date: formatDate(data.purchase_date),

    store_name: data.store_name.trim(),

    description: data.description.trim(),

    amount: Number(data.amount)

  };

}

// 日付のフォーマット

function formatDate(dateStr) {

  try {

    const date = new Date(dateStr);

    if (isNaN(date.getTime())) throw new Error();

    return Utilities.formatDate(date, 'Asia/Tokyo', 'yyyy-MM-dd');

  } catch {

    throw new Error('Invalid date format');

  }

}

// スプレッドシートへの書き込み

function writeToSpreadsheet(data) {

  const sheet = SpreadsheetApp.getActiveSheet();

  const nextRow = sheet.getLastRow() + 1;

  const values = [

    data.purchase_date,

    data.store_name,

    data.description,

    data.amount

  ];

  sheet.getRange(nextRow, 1, 1, values.length).setValues([values]);

  return {

    rowNumber: nextRow

  };

}

// JSONレスポンスの作成

function createJsonResponse(data, responseCode = 200) {

  return ContentService.createTextOutput(JSON.stringify(data))

    .setMimeType(ContentService.MimeType.JSON);

}

GASのデプロイ

  1. スクリプトエディタでプロジェクトを作成
  2. 上記のコード(4-1で記載したもの)を貼り付け
  3. デプロイ → 新しいデプロイ を選択
  4. 種類をウェブアプリケーションに設定
  5. 以下の設定を行う:

実行するユーザー: 自分

アクセスできるユーザー: 全員

  1. デプロイを実行しデプロイIDを取得
  2. 取得したGASのデプロイIDをGPTsのアクション設定に組み込む

※ レシートをGPTsにアップロードして送信後、確認するを押して、スプレッドシートに登録できたら大丈夫です。

6. まとめと応用

今回解説したGPTsとGASを組み合わせたアプローチは、様々な業務効率化プロジェクトに応用できます。名刺管理システムや文書の自動分類システムなど、画像認識とデータ処理を組み合わせたアプリケーション開発に特に有効です。

開発の重要なポイントは、最初からすべての機能を実装しようとせず、基本機能を確実に実装してから段階的に拡張していくことです。GPTsとGASを使った実装は環境構築が不要で動作検証が容易なため、プロトタイプ作成に最適です。

これらの技術とアプローチを活用することで、効率的なシステム開発が可能になります。ぜひ実際の業務でも試してみてください。

目次