AppSheetで学んだノウハウ集
AppSheetはGoogleが提供するノーコード/ローコードアプリ開発プラットフォームです。 スプレッドシートやデータベースを基にして、モバイルアプリやWebアプリを素早く構築できる点が特徴です。
本記事では、実際にAppSheetを利用する中で得られたノウハウや、つまずきやすいポイントについてまとめます。
AppSheetは、コードを書かずにビジネスアプリケーションを作成できるプラットフォームです。
主な特徴:
- データソースの柔軟性: Google スプレッドシート、Excel、SQL データベースなど多様なデータソースに対応
- 直感的なUI: ドラッグ&ドロップでアプリを構築
- モバイル対応: iOS、Android、Web に対応したレスポンシブアプリを自動生成
- ワークフロー機能: データの変更をトリガーにした自動化処理が可能
AppSheetのプランには行数やデータベース数の制限がありますが、外部のデータソースを利用する場合にはその制限がありません。
例えば、Google スプレッドシートをデータソースとして使う場合、Coreプランでも2,500行以上のデータを扱うことができます。
Google Workspace を利用している組織では、AppSheet の Core プランが付随してくることが多いため、外部データソース(特にスプレッドシート)を活用することで、追加コストなしで大規模なデータを扱うアプリケーションを構築できます。
ポイント:
- AppSheet データベースを使わず、Google スプレッドシートや外部DBを利用する
- Core プランの制限を気にせず大量データを扱える
- Google Workspace ユーザーなら追加コストなしで活用可能
ワークフロー的なアプリを作る場合、「提出」「承認」「却下」などのステータス項目は、手動で入力するよりも、提出アクションなどで自動更新させたほうが利用者の操作として明確であり、間違いが起きません。
また、オートメーション(Bot)の処理で更新したいケースもあります。
よくある問題
ユーザー操作で更新させたくないため、項目の editable を管理画面のUIでオフにすると、アクションやオートメーションの設定で更新対象として選択できなくなってしまいます。
解決方法
editable の設定を関数(式)で設定し、FALSE としておきましょう。
手順:
- カラム設定で
EDITABLE?をクリック - チェックボックスを外すのではなく、式エディタで
FALSEと入力
こうすることで、ユーザーからは編集不可となりますが、アクション/オートメーションでは設定可能となります。
EDITABLE?: FALSEポイント:
- UI上でチェックを外すのではなく、式で
FALSEを設定 - アクション・オートメーションからの更新は可能になる
- ワークフロー系アプリでのステータス管理に必須のテクニック
複数のユーザーが同じレコードを同時に編集する可能性がある場合、更新の競合を検知する仕組み(楽観ロック) が必要です。
AppSheet では、バージョン番号やタイムスタンプを使った楽観ロックを実装できます。
実装方法
1. バージョン管理用のカラムを追加
データソース(スプレッドシート等)に以下のカラムを追加します:
version(Number型): バージョン番号を格納- または
updated_at(DateTime型): 最終更新日時を格納
2. 初期値・更新時の設定
カラム設定で以下を設定:
Initial value: 0 (または NOW() for DateTime)3. 更新時にバージョンをインクリメント
更新アクション(または保存時)に以下の設定を追加:
- Data: Set these columns
- Column:
version - Value:
[version] + 1
4. 楽観ロック検証の追加
フォーム送信時に、現在のバージョンと元のバージョンを比較:
Valid_If: [version] = [_THISROW_BEFORE].[version]または、カスタムアクションで検証:
Condition: [version] = LOOKUP([_THISROW].[_RowNumber], "テーブル名", "_RowNumber", "version")タイムスタンプを使う方法
バージョン番号の代わりに、更新日時で判定する方法もあります:
1. カラム設定
updated_at(DateTime型)- App formula:
NOW()
2. 検証
Valid_If: [updated_at] = [_THISROW_BEFORE].[updated_at]競合時の対応
競合を検知した場合は、以下のような対応が可能です:
- エラーメッセージを表示して再入力を促す
- Show_If 式でワーニングを表示
- 別の承認フローに回す
ポイント:
- バージョン番号またはタイムスタンプで更新競合を検知
[_THISROW_BEFORE]を使って編集開始時の値と比較- Valid_If や Condition で検証を実装
- スプレッドシートベースでも排他制御が可能
AppSheet でデータを絞り込む方法として、スライス(Slice) と セキュリティフィルタ(Security Filter) がありますが、用途と挙動が大きく異なります。
スライス(Slice)とは
スライスは、テーブルのデータを 表示用に絞り込む 機能です。
特徴:
- UI/UX の改善が主な目的
- ビューごとに異なるデータセットを表示
- 式の評価はクライアント側で実行
注意点: ⚠️ セキュリティ上の保護機能ではありません
スライスで絞り込まれたデータであっても、技術的な知識があれば、ネットワーク通信の内容を確認することで フィルタ前の全データにアクセスできてしまいます。
セキュリティフィルタ(Security Filter)とは
セキュリティフィルタは、アクセス制御 のための機能です。
特徴:
- ユーザーがアクセスできるデータを制限
- サーバー側でフィルタリング実行
- フィルタ条件に合わないデータはクライアントに送信されない
設定方法:
- Data > Tables > 対象テーブルを選択
- Security Filter セクションで式を設定
例: [所属部署] = USEREMAIL()
例: [作成者] = USEREMAIL()使い分けの基準
| 用途 | 使用する機能 |
|---|---|
| 機密情報・個人情報の保護 | セキュリティフィルタ |
| 他部署のデータを絶対に見せたくない | セキュリティフィルタ |
| ビューごとに表示内容を変えたい | スライス |
| UI/UXの改善 | スライス |
| パフォーマンスの向上 | スライス |
実装例
セキュリティフィルタの例(部署別アクセス制御):
// テーブルのSecurity Filterに設定
[所属部署] = LOOKUP(USEREMAIL(), "ユーザーマスタ", "メールアドレス", "所属部署")これにより、ユーザーは自分の所属部署のデータ のみ にアクセスできます。
スライスの例(表示用の絞り込み):
// スライスのRow filter conditionに設定
[ステータス] = "承認済み"これは表示を絞り込むだけで、セキュリティ保護にはなりません。
重要なポイント
⚠️ 権限のないユーザーに絶対に見せてはいけない情報は、必ずセキュリティフィルタを使用してください。
- スライスだけではセキュリティ保護にならない
- ネットワーク通信を解析すれば全データが見える可能性がある
- 個人情報や機密情報は必ずセキュリティフィルタで保護
ポイント:
- セキュリティフィルタ = サーバー側でのアクセス制御(セキュリティ保護)
- スライス = クライアント側での表示制御(UI/UX改善)
- 機密情報の保護には必ずセキュリティフィルタを使用
- 用途に応じて適切に使い分ける
AppSheet では、テーブルを追加すると 詳細画面(Detail View) と 編集画面(Form View) が自動生成されます。
初心者が見落としがちなポイントですが、これらの自動生成ビューの存在を理解し、適切にカスタマイズすることが重要です。
自動生成されるビュー
テーブルごとに以下のビューが自動生成されます:
1. Detail View(詳細画面)
- 命名規則:
テーブル名_Detail - 用途: 1件のレコードの詳細情報を表示
- 一覧からレコードをタップした際に表示される画面
2. Form View(編集/新規作成画面)
- 命名規則:
テーブル名_Form - 用途: レコードの新規作成・編集
- 「+」ボタンや編集ボタンから表示される画面
自動生成ビューのカスタマイズが必要なケース
以下のような場合は、自動生成されたビューを編集する必要があります:
1. 表示項目の制御
// Detail Viewで特定の項目を非表示にする
Show_If: FALSE2. 編集可能項目の制限
// Form Viewで特定条件下のみ編集可能にする
Editable_If: [ステータス] = "下書き"3. レイアウトの変更
- View Options > View Type で表示形式を変更
- Column order で項目の並び順を調整
Reference View(参照ビュー)の活用
子テーブルのデータを親レコードの詳細画面に表示する場合、Reference View を使用します。
設定手順:
- 子テーブルのビューを作成(例:
注文明細_List) - 親テーブルの Detail View を開く
- View Options > Reference Views で子テーブルのビューを追加
- フィルタ条件を設定
例: 注文ヘッダーに注文明細を表示
// 注文明細_List のフィルタ条件
[注文ID] = [_THISROW].[注文ID]これにより、注文詳細画面で関連する注文明細が自動的に表示されます。
よくあるパターン
パターン1: 詳細画面で関連データを表示
親レコードの詳細画面に、子レコードのリストを表示:
- 受注 → 受注明細
- プロジェクト → タスク一覧
- 顧客 → 商談履歴
パターン2: Form Viewでの条件付き表示
ステータスに応じて編集可能な項目を変更:
// 承認者コメント欄の表示制御
Show_If: [ステータス] IN LIST("承認", "却下")
// 申請者は承認後は編集不可
Editable_If: AND([ステータス] = "下書き", USEREMAIL() = [申請者])自動生成ビューを見つける方法
UX > Views で以下のビューを確認:
テーブル名_Detailテーブル名_Form
これらは System Views セクションに配置されることもあります。
注意点
⚠️ 自動生成ビューを削除しても、再生成されることがあります
カスタマイズした内容が消えないよう、以下の対応を推奨:
- 自動生成ビューを直接編集する
- または、新しいビューを作成して自動生成ビューを無効化
ポイント:
- テーブル追加時に Detail View と Form View が自動生成される
- カスタマイズが必要な場合は、これらのビューを編集
- Reference View で親子関係のデータを表示
- 自動生成ビューの存在を理解することが AppSheet 開発の基本
AppSheet では USEREMAIL() 関数でログインユーザーのメールアドレスを取得できますが、ユーザーマスタテーブルを用意することで、より柔軟な権限制御が可能になります。
ユーザーマスタの基本構成
以下のようなユーザーマスタテーブルを作成します:
| メールアドレス | 氏名 | 所属部署 | 権限レベル | 承認者フラグ |
|---|---|---|---|---|
| [email protected] | 山田太郎 | 営業部 | 一般 | FALSE |
| [email protected] | 佐藤花子 | 営業部 | 管理者 | TRUE |
| [email protected] | 鈴木次郎 | 総務部 | 一般 | FALSE |
LOOKUP関数との組み合わせ
ユーザーマスタから現在のユーザー情報を取得:
// 現在のユーザーの所属部署を取得
LOOKUP(USEREMAIL(), "ユーザーマスタ", "メールアドレス", "所属部署")
// 現在のユーザーの権限レベルを取得
LOOKUP(USEREMAIL(), "ユーザーマスタ", "メールアドレス", "権限レベル")
// 現在のユーザーが承認者かどうか
LOOKUP(USEREMAIL(), "ユーザーマスタ", "メールアドレス", "承認者フラグ")実践的な活用例
1. 部署別データアクセス制御
// テーブルのSecurity Filter
[所属部署] = LOOKUP(USEREMAIL(), "ユーザーマスタ", "メールアドレス", "所属部署")自分の所属部署のデータのみアクセス可能になります。
2. 権限レベルによる表示制御
// 管理者のみ表示されるボタン
Show_If: LOOKUP(USEREMAIL(), "ユーザーマスタ", "メールアドレス", "権限レベル") = "管理者"
// 一般ユーザーは自分が作成したレコードのみ編集可能
Editable_If: OR(
[作成者] = USEREMAIL(),
LOOKUP(USEREMAIL(), "ユーザーマスタ", "メールアドレス", "権限レベル") = "管理者"
)3. 承認ワークフローの実装
- ステータスの項目を持たせることで、データの状態に合わせた処理を行えるワークフローを構成することができます。
// 承認ボタンの表示条件
Show_If: AND(
[ステータス] = "申請中",
LOOKUP(USEREMAIL(), "ユーザーマスタ", "メールアドレス", "承認者フラグ") = TRUE
)4. 初期値の自動設定
// 申請者の所属部署を自動設定
Initial value: LOOKUP(USEREMAIL(), "ユーザーマスタ", "メールアドレス", "所属部署")
// 申請者の氏名を自動設定
Initial value: LOOKUP(USEREMAIL(), "ユーザーマスタ", "メールアドレス", "氏名")Virtual Column での効率化
毎回 LOOKUP を書くのは冗長なので、Virtual Column(仮想列)を活用します。
例: ユーザー情報の Virtual Column
テーブルに以下の Virtual Column を追加:
// 列名: _CurrentUserDept
App formula: LOOKUP(USEREMAIL(), "ユーザーマスタ", "メールアドレス", "所属部署")
// 列名: _CurrentUserRole
App formula: LOOKUP(USEREMAIL(), "ユーザーマスタ", "メールアドレス", "権限レベル")
// 列名: _IsApprover
App formula: LOOKUP(USEREMAIL(), "ユーザーマスタ", "メールアドレス", "承認者フラグ")これらを使って簡潔に記述:
// Security Filter
[所属部署] = [_CurrentUserDept]
// Show_If
[_IsApprover] = TRUE上司・部下関係の実装
ユーザーマスタに上司の情報を持たせることで、階層的な権限制御も可能:
| メールアドレス | 氏名 | 上司メールアドレス |
|---|---|---|
| [email protected] | 山田太郎 | [email protected] |
| [email protected] | 佐藤花子 | NULL |
// 自分または自分の部下が作成したレコードのみ表示
Security Filter: OR(
[作成者] = USEREMAIL(),
LOOKUP([作成者], "ユーザーマスタ", "メールアドレス", "上司メールアドレス") = USEREMAIL()
)ユーザーマスタ運用のポイント
メリット:
- メールアドレスだけでなく、部署・役職・権限などの属性を管理できる
- スプレッドシート上で簡単にユーザー情報を更新できる
- 組織変更に柔軟に対応可能
- 複雑な権限制御を実装できる
運用上の注意:
- ユーザーマスタに登録されていないユーザーはアクセスできなくなる
- メールアドレスの入力ミスに注意
- 定期的なメンテナンスが必要
ポイント:
- ユーザーマスタ + LOOKUP で柔軟な権限制御を実現
- Virtual Column で LOOKUP の記述を効率化
- 部署・権限レベル・承認者フラグなどの属性を活用
- 組織変更にも柔軟に対応可能
Google フォームを AppSheet のデータソースとすることで、不特定多数からの申込を受け付け、AppSheet で管理・処理するという連携が可能です。
ユースケース
- イベントの参加申込フォーム → AppSheet で受付管理
- アンケート回答 → AppSheet で集計・分析
- 問い合わせフォーム → AppSheet で対応状況管理
- 予約フォーム → AppSheet で予約管理
実装方法
1. Google フォームの作成
通常通り Google フォームを作成し、回答先のスプレッドシートを指定します。
2. AppSheet でスプレッドシートを接続
フォームの回答が保存されるスプレッドシートを AppSheet のデータソースとして追加します。
Data > New Table > Google Sheets
→ フォーム回答シートを選択3. データ構造の調整
Google フォームの回答シートは以下の構造になります:
| タイムスタンプ | 質問1 | 質問2 | 質問3 |
|---|---|---|---|
| 2025/10/01 10:00:00 | 回答A | 回答B | 回答C |
AppSheet 側で適切なカラム型を設定:
- タイムスタンプ → DateTime 型
- 選択式の質問 → Enum 型
- 記述式の質問 → Text 型
4. 管理用カラムの追加
フォーム回答シートに、管理用の列を追加します:
| カラム名 | 用途 | 型 |
|---|---|---|
| 処理ステータス | 未対応/対応中/完了 | Enum |
| 担当者 | 対応者のメールアドレス | Text |
| 対応メモ | 内部メモ | LongText |
| 対応日時 | 対応完了日時 | DateTime |
5. AppSheet での処理フロー構築
// 新規申込の自動検知(Bot)
Condition: [処理ステータス] = ""
Action: Set [処理ステータス] = "未対応"
// 担当者割当アクション
Action: Set these columns
- 処理ステータス: "対応中"
- 担当者: USEREMAIL()
// 完了処理アクション
Action: Set these columns
- 処理ステータス: "完了"
- 対応日時: NOW()利点と注意点
利点:
- Google フォームで誰でも簡単に入力できる
- AppSheet のログイン不要で申込を受け付けられる
- フォームは一般公開、管理は AppSheet で権限制御
- 既存の Google フォームをそのまま活用可能
注意点:
- フォーム側から追加された列は AppSheet に自動反映されない(再同期が必要)
- フォーム回答者は AppSheet にアクセスできないため、回答確認はメールなどで別途対応
- タイムスタンプは Key として使用可能(重複しないため)
実装例:イベント参加申込システム
Google フォーム側:
- 氏名
- メールアドレス
- 参加希望日
- 備考
AppSheet 側の追加カラム:
- 受付番号(自動採番)
- 承認ステータス(未承認/承認/却下)
- 承認者
- 承認日時
処理フロー:
- フォームから申込 → スプレッドシートに記録
- AppSheet の Bot が新規申込を検知し、受付番号を自動採番
- 管理者が AppSheet で承認/却下を判断
- 承認時に自動メール送信(Automation)
フォームとの連携パターン
パターン1: フォームで受付、AppSheet で管理
- 外部からの申込: Google フォーム
- 内部での管理・処理: AppSheet
パターン2: 両方で入力可能
- 一般ユーザー: Google フォーム
- 管理者・スタッフ: AppSheet から直接入力
パターン3: 段階的な処理
- Google フォーム → 初回申込
- AppSheet → 内部処理・ステータス管理
- Google フォーム → 追加情報の収集(別フォーム)
ポイント:
- Google フォームで不特定多数からの入力を受付
- AppSheet で管理・処理フローを構築
- ログイン不要の入力と権限管理された処理を両立
- 既存フォームの活用で導入が容易
AppSheet で PDF 生成や画像保存などのファイル操作を行う際、ファイルの保存先パスとデータソースのパスが異なることで、生成したファイルにアクセスできない問題が発生することがあります。
よくある問題
現象:
- Automation(Bot)で PDF を生成
- PDF の URL は生成されるが、アクセスすると「ファイルが見つかりません」エラー
- 画像ファイルが表示されない
原因:
- データソース(スプレッドシート等)の保存先:
/TeamDrive/AppSheetData/Data/DataStore - アプリのデフォルト保存先:
/AppSheetData/Data/AppName - パスが異なるため、ファイルにアクセスできない
解決方法:デフォルトパスの変更
AppSheet のデフォルトファイル保存先を、データソースと同じパスに変更します。
手順:
- Settings(設定) を開く
- Information セクションに移動
- Default app folder を見つける
- パスを変更:
変更前: /AppSheetData/Data/[アプリ名]
変更後: /[TeamDrive名]/AppSheetData/Data/DataStoreまたは、データソースが Google ドライブの場合:
/AppSheetData/Data/DataStore- Save をクリック
パスの確認方法
データソースのパスを確認:
- Data > Tables でテーブルを選択
- Source の欄でスプレッドシートの場所を確認
- パスをコピー
アプリのデフォルトパスを確認:
- Settings > Information
- Default app folder の値を確認
この2つのパスが一致するように設定します。
適用例:PDF生成の自動化
シナリオ: 請求書を PDF 生成して、AppSheet 内でダウンロード可能にする
1. PDF テンプレート作成
- Content > Create > PDF Template
2. Bot で PDF 生成
Event: 請求書確定時
Process: Create a file from a template
Template: 請求書テンプレート
File name: CONCATENATE("請求書_", [請求番号], ".pdf")3. デフォルトパス設定
Settings > Information > Default app folder
→ データソースと同じパスに変更4. 生成された PDF へのアクセス
- 生成された PDF のパスがデータソースと同じため、URL でアクセス可能
- Detail View で PDF リンクを表示
他の活用例
画像アップロード機能:
- ユーザーがアップロードした画像
- データソースと同じフォルダに保存
- 他のユーザーも参照可能
Excel エクスポート:
- データを Excel 形式でエクスポート
- 共有ドライブに保存
- チーム内で共有
注意点
⚠️ パス変更の影響:
- 既存のファイル参照に影響が出る可能性がある
- 変更前に既存ファイルの配置を確認
- 必要に応じてファイルを移動
共有ドライブ利用時:
- TeamDrive(共有ドライブ)を使用する場合、パスに TeamDrive 名を含める
- アクセス権限の設定も忘れずに
ポイント:
- PDF や画像ファイルが見つからない場合、まずパスを確認
- Default app folder をデータソースと同じパスに設定
- ファイル生成の Automation 設定前に必ず確認
- 共有ドライブ利用時はパスに注意
本記事では、AppSheet を実務で活用するための8つのノウハウをまとめました。
- 外部データソース活用: Core プランでも大量データを扱える
- editable設定: 式で
FALSEを設定してアクション/オートメーションから更新可能に - 楽観ロック: バージョン管理で更新競合を検知
- セキュリティフィルタ: スライスではなくセキュリティフィルタで機密情報を保護
- 自動生成ビュー: Detail/Form View の存在を理解してカスタマイズ
- ユーザーマスタ: LOOKUP と組み合わせて柔軟な権限制御を実現
- Google フォーム連携: 不特定多数からの入力と管理システムを統合
- デフォルトパス設定: PDF 生成や画像保存のためのパス設定
これらのノウハウを活用することで、より実用的で安全な AppSheet アプリケーションを構築できます。
特に、セキュリティフィルタによる適切なアクセス制御とユーザーマスタを活用した権限管理は、業務アプリケーションとして運用する上で必須の知識です。
AppSheet はノーコードツールですが、これらの仕組みを理解することで、エンタープライズレベルのアプリケーション開発も可能になります。
- コメント -
- 関連記事 -
- 記事検索 -
このサイトではcookieを利用して、サイト訪問者の識別に利用します。 cookieの利用に同意いただくことで、サイト訪問者は記事のいいね機能等をご利用いただけます。 なお、サイト運営者はアクセス統計としてcookieの情報を利用する場合があります。