ノーコードで現場DX：試作しながらスマホで検査依頼ができる仕組みを構築しました

# 📱AppSheetで検査依頼アプリを作った話

**🧩 はじめに**
こんにちは。お惣菜の商品開発をしているminami🐸です。
わたしたち食品開発の段階で避けては通れない「商品の保存検査」
食の安全が担保されませんので、これを通らないことには販売をすることができません。


今回は開発現場の検体作成（＝実際に検査をする商品）業務の中でも、「検査依頼表の作成」と「検査依頼」までの自動化を目指し、アプリを作成しました。

この記事は実際の業務の中で、FBをもらいながらアプリ開発を進めている様子を記載しています。
なにか参考になれる部分があると幸いです🐸


## 目次

- [作ったもの：検査依頼アプリ](#作ったもの検査依頼アプリ)
- [作り方](#作り方)
- [技術構成と工夫した点](#技術構成と工夫した点)
- [実際にチームメンバのアシスタントたちに使ってみてもらいました](#実際にチームメンバのアシスタントたちに使ってみてもらいました)
- [検体依頼メールを自動送信（GAS）](#検体依頼メールを自動送信gas)
- [最後に](#最後に)




### 作ったもの：検査依頼アプリ
**概要**
・スマホからアクセス可能なAppSheetアプリ

・入力内容はGoogleスプレッドシートに自動記録

・フォーム形式で、項目ごとに入力しやすく設計

・入力後、自動で担当者に通知


**入力できる主な項目**
<details> <summary>クリックで展開</summary>
・担当者

・試作品画像

・サンプル保管場所

・検体名

・検査内容（温度、時間等～）

・検査項目　各種
</details>

 ### 🚀作り方

①Gシートに必要な項目を横軸に書きだし、拡張機能/AppSheet/アプリを作成を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4048408/3c4a7b93-3909-4b4b-873f-22ab6d36e445.png)

➁データを選択し、入れたい項目を編集していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4048408/e2527bf6-510f-4fe4-be27-ec40be6c8326.png)

③項目の少ないものについては、Enumでボタン登録にして、選択を簡単にしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4048408/baa6e3a3-c9f5-41dc-9cc1-aa11c4341f11.png)

④項目の多いものについては、Googleスプレッドシートにシートを追加して、ドロップダウンで項目追加ができるようにしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4048408/94861945-e747-4698-87b0-e22165aa10e5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4048408/1b6c5335-7db7-43d3-9c9e-b08ad100080d.png)


⑤検体画像をファイル保管（タイプを画像に）
現場での出来栄え確認に使用します。
<details> <summary>クリックで展開</summary>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4048408/87fe472a-77ff-4402-a27e-eeee41b62e7a.png)
</details>

**こちらが実際に動かした操作画面です:writing_hand::writing_hand::writing_hand:**

https://x.com/minami00901/status/1924450770159857678


### 技術構成と工夫した点
Googleスプレッドシートをデータベースとして使用
→ 社内で共有・編集しやすく、既存データとの連携も可能

AppSheetでノーコードアプリ化
→ 専用アカウントなしでも使える（GoogleアカウントでOK）

スマホから1分で入力完了できるように、フォームUIを簡潔に設計

試作・検体画像をアプリで保存
→検体と商品仕様が一致するように。最終の仕様書画像にも流用◎



**アプリで入力したものが、このようにGoogleスプレッドシートへ入力されました**
こちらが元の検査依頼書になってまいります。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4048408/30df7c87-8782-431d-8113-2c2b7ae88763.png)


### 実際にチームメンバのアシスタントたちに使ってみてもらいました

参考記事

https://note.com/minami00901/n/n8d593885c31c

🐸：昨日、みんなに妙な招待メールが届いていると思うのだけど…（アカウント追加メール）

**ＫＹ氏：アプリをダウンロードしてみて、今いれてみました**


…はやい🐸。。。説明するよりも先に実践してくれました。
入力は１分もかからず、終わりました。

**ＫＭ氏：ＰＣ入力が無いのはいいけど、いっぱいある時にはシートに直接打った方がはやいかも**

…確かに、ごもっともです🐸🐸🐸状況に応じて使いわけましょう。

**ＡＭ氏：追加・修正してもらいたい箇所があります。**

・検体情報　初発の検体は保存温度を入力しない（設定できますか？）
・商品区分　半製品/製品/原料/開封後原料/お申し出　５パターンで区分をしたいです
・検体作成　作成日をいれてください。カレンダー選択希望
・検査区分　TK（テスト試作）、ロット（現場試作）選択したい
・検体に貼るバーコードナンバーを入力できる項目がほしいです
・〇△×◎‥‥（…以降は🐸の守備範囲を超える。。。）


**……バーコードナンバー？！？！？！？！🐸**


AIのようにボールを打ちまくるAM氏:baseball:
最後は変化球でこのようなシールを添付して検体管理をしたい、とのボールを投げてきました…
<details> <summary>クリックで展開</summary>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4048408/635bf5ac-9a1d-4d24-aca1-4610fecc84f9.png)
</details>
ひとまず、こちらを手入力で数字を入れる項目を作成。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4048408/a512a455-2d08-4192-9392-838b46dbd74e.png)

長いコードを手入力は間違いものとなので、できればバーコードスキャンしたら、そのまま数字が入力されるようにしたいと思い、スキャナ機能をつけました:fist:

タイプはTextのまま、フォーム設定で「Scannable」に☑するだけ🐸

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4048408/2ea8fcc2-3b17-4eb1-9d46-560c01ef69e6.png)





**（さらにもう一球）ＡＭ氏：開発だけでなく、品質管理がお申し出品の検査をだすことがあります。**


…かしこまりました🐸
品質管理にもアプリの共有をして、みんなで使えるようにします🐸


**（止めのもう一球）品質管理HR氏：自分で依頼書を書かなくなると、検査に出し忘れちゃいそう。**

それは大いに困りますので、**出荷当日の朝9：00に検体発送お知らせメールを自動送信する**よう、GASで設定させていただきました🐸:baseball:
（タイトルに合わず、こちらはコードを使用しました）

### 検体依頼メールを自動送信（GAS）

```
function sendSpecimenReminder() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('依頼シート');
  const data = sheet.getDataRange().getValues();

  const today = new Date();
  today.setHours(0, 0, 0, 0); // 時刻を0にして日付比較のために整える

  const targetColumnDate = 12; // M列（0始まりの13列目）
  const specimenNameColumn = 6; // G列（検体名）

  const specimensToday = [];

  for (let i = 1; i < data.length; i++) {
    const rawValue = data[i][targetColumnDate];
    let rowDate;

    // セルの値が日付か文字列かを確認し、変換
    if (rawValue instanceof Date) {
      rowDate = new Date(rawValue);
    } else if (typeof rawValue === "string" && rawValue.trim() !== "") {
      // 文字列を日付として解析（日本形式対応）
      const parsed = new Date(rawValue.replace(/-/g, "/")); // ハイフンもスラッシュに変換して対応
      if (!isNaN(parsed)) {
        rowDate = parsed;
      }
    }

    if (rowDate && !isNaN(rowDate)) {
      rowDate.setHours(0, 0, 0, 0);
      if (rowDate.getTime() === today.getTime()) {
        const specimenName = data[i][specimenNameColumn];
        if (specimenName) {
          specimensToday.push("・" + specimenName);
        }
      }
    }
  }

  // 件数が1件以上あればメール送信
  if (specimensToday.length > 0) {
    const subject = "本日の検体出荷連絡";
    const body = [
      "おはようございます。",
      "今日は検体があります。",
      "よろしくお願い致します。",
      "",
      specimensToday.join("\n")
    ].join("\n");

    MailApp.sendEmail({
      to: "　　　", // 宛先メールアドレス
      subject: subject,
      body: body
    });
  }

  Logger.log("対象データ件数: " + specimensToday.length);
}
```
:writing_hand:トリガー設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4048408/98230051-b096-499e-8abf-897506fea1b9.png)


これで検査出し忘れ（開発遅れ）防止です。


### 最後に

お付き合いいただき、ありがとうございました。
何かお役立ちできることがあれば幸いです。
つくったアプリを実際に使ってもらうことで、知らなかった作業も分かり（今までありがとうございます）、より効率的な作業支援につながるものができることを実感できました。
実はAM氏はデジタルがお世辞にも明るい人では無いのですが、実際に使ってもらうとぐいぐいと乗り出して、提案してくれました。ユーザー（クライアント）の意見をよりよく吸い上げて反映できれば、開発したアプリもより可愛がってもらえるのではないかな、とも思いました:blush:


使ってくれる皆さまのために、喜んでもらえるアプリをつくりをしたい、
お買い求めいただくお客さまに、おいしい、と喜んでもらえるお惣菜がつくりたい、

食品開発も、アプリ開発も、モノつくりの目標は同じでした🐸🐸