VLM Run AIとGmailを使ってGoogle Driveの画像から出退勤データをSheetsに抽出
これは自動化ワークフローで、11個のノードを含みます。主にGmail, Webhook, GoogleDrive, HttpRequest, VlmRunなどのノードを使用。 VLM Run AI と Gmail リマインダーを使用して、Google ドライブの写真から出席データをスプレッドシートに抽出します
- •Googleアカウント + Gmail API認証情報
- •HTTP Webhookエンドポイント(n8nが自動生成)
- •Google Drive API認証情報
- •ターゲットAPIの認証情報が必要な場合あり
カテゴリー
{
"meta": {
"instanceId": "96d35e452e0d9a182973416b7532cfc5643239aaaa764a5bf74d52ca84f4a35c",
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "0968592f-243a-4fb9-809c-2434e9375da3",
"name": "VLM Run for Extraction",
"type": "@vlm-run/n8n-nodes-vlmrun.vlmRun",
"position": [
496,
-96
],
"parameters": {
"operation": "executeAgent",
"agentPrompt": "=Analyze the image of user list names and show them in the following json format, make sure to follow this exact structure, where val1 will be current date, val2 will be total user count and rest of the values will be the user names:\n{ \\\"majorDimension\\\": \\\"ROWS\\\", \\\"values\\\": [ [\\\"val1\\\", \\\"val2\\\"] ] }",
"agentCallbackUrl": "https://playground.attensys.ai/webhook/check-attendance"
},
"credentials": {
"vlmRunApi": {
"id": "B7ZYM8AfBgjnOEOl",
"name": "VLM Run account 5"
}
},
"typeVersion": 1
},
{
"id": "32cf5900-f3f2-4a05-b3d0-97848189f513",
"name": "付箋",
"type": "n8n-nodes-base.stickyNote",
"position": [
864,
-480
],
"parameters": {
"color": 7,
"width": 464,
"height": 576,
"content": "## 🟣 Append to Sheets + Send Email\n\n* ➕ **HTTP Request** calls Google Sheets `values:append` with `valueInputOption=RAW`, `insertDataOption=INSERT_ROWS`, `includeValuesInResponse=true`, then ✉️ **Gmail** sends the formatted attendance to the chosen recipient\n\n* 📥 Appends the received row into **Sheet1!A:Z** and formats the message where the first item is the date, the last item is the total, and the rest are numbered names\n\n🧪 Example input:\n{\"majorDimension\":\"ROWS\",\"values\":[[\"2025-10-03\",\"6\",\"Camila Torres Rivera\",...,\"Anisah Anif\"]]}\n\n\n📊 Result: a new row with date in column A, total count in column B, then each attendee name across subsequent columns, and an email sent with subject `Attendance List`\n"
},
"typeVersion": 1
},
{
"id": "e37ad5b4-1df1-4d4c-b07a-358ea7c2f8ef",
"name": "付箋1",
"type": "n8n-nodes-base.stickyNote",
"position": [
432,
-480
],
"parameters": {
"width": 416,
"height": 576,
"content": "## 🟡 VLM Run: Extraction Logic\n\n\n- 🤖 **Execute Agent** processes the downloaded image. \n- 📝 **Prompt**: Return JSON in format `{ \"majorDimension\": \"ROWS\", \"values\": [[\"YYYY-MM-DD\", \"user_count\", \"name1\", \"name2\", ...]] }`. \n- 🌐 Result posted to n8n webhook **`check-attendance`** (test endpoint). \n- 📩 Webhook receives ready-to-append Sheets payload. \n- 🧠 *Example output*: \n `{\"majorDimension\":\"ROWS\",\"values\":[[\"2025-10-03\",\"6\",\"Camila Torres Rivera\",\"Mellissa\"]]}`\n\n\n"
},
"typeVersion": 1
},
{
"id": "c4b6f7e3-31ff-49ff-9640-c90950141a33",
"name": "付箋2",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
-480
],
"parameters": {
"color": 7,
"width": 416,
"height": 576,
"content": "## 🟢 Google Drive: Monitor & Download\n\n* ⏱️ Google Drive Trigger checks the target folder every minute for **fileCreated** events\n\n* 🗂️ Trigger scope: the attendance images folder you selected\n\n* 🔗 Passes the new file **id** to the next node\n\n* ⬇️ Google Drive node downloads the file as binary under **data**\n\n* 📦 Output: the binary file is ready for the attendance extraction step\n"
},
"typeVersion": 1
},
{
"id": "fbb0adca-34a1-41c0-847b-5fb7304f2c4a",
"name": "付箋4",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
-864
],
"parameters": {
"color": 7,
"width": 848,
"height": 368,
"content": "## 🧾 Attendance Extraction Pipeline\n\n**Overview:**\n\nUploads land in Google Drive → VLM Run’s Execute Agent reads names from the image or scan → Agent posts a clean JSON to the n8n Webhook → The workflow appends the row into Google Sheets.\n\n\nPerfect for:\nWhiteboard standups, workshop sign-ins, classroom roll calls.\n\n\n**Requirements:**\n\n* VLM Run API credentials with access to Execute Agent\n* Google Drive OAuth2 for trigger and download\n* Google Sheets OAuth2 for `values:append`\n* n8n Webhook reachable at `check-attendance` on the test endpoint\n"
},
"typeVersion": 1
},
{
"id": "3d69f4a9-20f0-487e-9402-cd7f2ec1bd73",
"name": "リスト受信",
"type": "n8n-nodes-base.webhook",
"position": [
704,
-96
],
"webhookId": "706a3754-0987-4153-9193-29c27827d442",
"parameters": {
"path": "check-attendance",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2.1
},
{
"id": "0e9e1a63-80b6-4366-bbf9-dd18bfab4efb",
"name": "リストアップロード監視",
"type": "n8n-nodes-base.googleDriveTrigger",
"notes": "Monitors Google Drive folder for new receipt uploads and triggers processing automatically.",
"position": [
64,
-96
],
"parameters": {
"event": "fileCreated",
"options": {},
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
},
"triggerOn": "specificFolder",
"folderToWatch": {
"__rl": true,
"mode": "list",
"value": "1S6baavqJn98MjUlbB6KtmARCWuWEekIZ",
"cachedResultUrl": "https://drive.google.com/drive/folders/1S6baavqJn98MjUlbB6KtmARCWuWEekIZ",
"cachedResultName": "test_data"
}
},
"credentials": {
"googleDriveOAuth2Api": {
"id": "zYyIOFMdGz258avn",
"name": "Google Drive account 6"
}
},
"typeVersion": 1
},
{
"id": "bcdf4ec9-602c-402b-a929-54a0b73f2d70",
"name": "リストダウンロード",
"type": "n8n-nodes-base.googleDrive",
"notes": "Downloads receipt files from Google Drive for AI processing.",
"position": [
240,
-96
],
"parameters": {
"fileId": {
"__rl": true,
"mode": "id",
"value": "={{ $json.id }}"
},
"options": {
"binaryPropertyName": "data"
},
"operation": "download"
},
"credentials": {
"googleDriveOAuth2Api": {
"id": "zYyIOFMdGz258avn",
"name": "Google Drive account 6"
}
},
"typeVersion": 3
},
{
"id": "93549d62-06ba-491d-bb82-c9c79beeca71",
"name": "新規出勤データをSheetに追加",
"type": "n8n-nodes-base.httpRequest",
"position": [
944,
-80
],
"parameters": {
"url": "https://sheets.googleapis.com/v4/spreadsheets/1lg0aJKvd7E2pbhumHNjcgxUfEQKvlBs9h1zZbhSeqas/values/Sheet1!A:Z:append",
"method": "POST",
"options": {},
"jsonBody": "={{ $json.body.response }}",
"sendBody": true,
"sendQuery": true,
"sendHeaders": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"queryParameters": {
"parameters": [
{
"name": "valueInputOption",
"value": "RAW"
},
{
"name": "insertDataOption",
"value": "INSERT_ROWS"
},
{
"name": "includeValuesInResponse",
"value": "true"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"nodeCredentialType": "googleSheetsOAuth2Api"
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "sdLQgQJjowDNfXMU",
"name": "Google Sheets account 7"
}
},
"typeVersion": 4.2
},
{
"id": "bc39bbf9-24a1-422a-99d8-d318bb15c59c",
"name": "メッセージ送信",
"type": "n8n-nodes-base.gmail",
"position": [
1168,
-80
],
"webhookId": "dc974b24-8060-48c3-a143-c4441b191061",
"parameters": {
"sendTo": "mehediahamed@iut-dhaka.edu",
"message": "={{\n(() => {\n const raw = $json.updates?.updatedData?.values;\n\n // Normalize to a flat array of strings\n const parts = Array.isArray(raw)\n ? (Array.isArray(raw[0]) ? raw[0] : raw).map(String)\n : String(raw || \"\").split(\",\").map(s => s.trim());\n\n if (!parts.length) return \"No data received\";\n\n const date = parts[0];\n const total = parts[1];\n const names = parts.slice(2).filter(Boolean);\n\n // Optional pretty date without relying on timezone parsing\n const prettyDate = /^(\\d{4})-(\\d{2})-(\\d{2})$/.test(date)\n ? date.replace(/^(\\d{4})-(\\d{2})-(\\d{2})$/, \"$3-$2-$1\")\n : date;\n\n const list = names.map((n, i) => `${i + 1}. ${n}`).join(\"<br>\");\n\n return `Today's Attendance List (${prettyDate})<br>Total: ${total}<br>${list}`;\n})()\n}}\n",
"options": {},
"subject": "Attendance List"
},
"credentials": {
"gmailOAuth2": {
"id": "GrK9vxqscIwcG24Y",
"name": "Gmail account 4"
}
},
"typeVersion": 2.1
},
{
"id": "4c50399f-3901-4067-859c-241834696ea5",
"name": "付箋3",
"type": "n8n-nodes-base.stickyNote",
"position": [
864,
-640
],
"parameters": {
"color": 5,
"width": 464,
"height": 144,
"content": "## 📝 Webhook: Set Public Callback URL\n\nPaste your n8n webhook’s Production URL into VLM Run’s Callback URL field—no localhost URLs (they’re unreachable)."
},
"typeVersion": 1
}
],
"pinData": {},
"connections": {
"bcdf4ec9-602c-402b-a929-54a0b73f2d70": {
"main": [
[
{
"node": "0968592f-243a-4fb9-809c-2434e9375da3",
"type": "main",
"index": 0
}
]
]
},
"3d69f4a9-20f0-487e-9402-cd7f2ec1bd73": {
"main": [
[
{
"node": "93549d62-06ba-491d-bb82-c9c79beeca71",
"type": "main",
"index": 0
}
]
]
},
"0e9e1a63-80b6-4366-bbf9-dd18bfab4efb": {
"main": [
[
{
"node": "bcdf4ec9-602c-402b-a929-54a0b73f2d70",
"type": "main",
"index": 0
}
]
]
},
"93549d62-06ba-491d-bb82-c9c79beeca71": {
"main": [
[
{
"node": "bc39bbf9-24a1-422a-99d8-d318bb15c59c",
"type": "main",
"index": 0
}
]
]
}
}
}このワークフローの使い方は?
上記のJSON設定コードをコピーし、n8nインスタンスで新しいワークフローを作成して「JSONからインポート」を選択、設定を貼り付けて認証情報を必要に応じて変更してください。
このワークフローはどんな場面に適していますか?
中級
有料ですか?
このワークフローは完全無料です。ただし、ワークフローで使用するサードパーティサービス(OpenAI APIなど)は別途料金が発生する場合があります。
関連ワークフロー
Shahrear
@shahrearI’m Shahrear, a Software Engineer with over 5 years of experience in full-stack development and workflow automation. I specialize in building intelligent automations using n8n, helping teams streamline operations and boost productivity. I’m also an expert in developing custom n8n nodes, with published work on npm - including the @vlm-run/n8n-nodes-vlmrun package. Linkedin - https://www.linkedin.com/in/shahrear-amin/ Email - shahrearbinamin33@gmail.com
このワークフローを共有