AutomationFlowsAI & RAG › AI Document Parser: PDF/Image/CSV to Google Sheets

AI Document Parser: PDF/Image/CSV to Google Sheets

Original n8n title: Smart Document Parser for Invoices, Logs or Sensor Reports (pdf/image/csv to Sheet)

Smart Document Parser for Invoices, Logs or Sensor Reports (PDF/Image/csv to Sheet). Uses googleSheets, lmChatGoogleGemini, chainLlm, extractFromFile. Webhook trigger; 12 nodes.

Webhook trigger★★★★☆ complexityAI-powered12 nodesGoogle SheetsGoogle Gemini ChatChain LlmN8N Nodes Tesseractjs
AI & RAG Trigger: Webhook Nodes: 12 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Chainllm → Google Sheets recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "c92ZApSKwsRmg6zb",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Smart Document Parser for Invoices, Logs or Sensor Reports (PDF/Image/csv to Sheet)",
  "tags": [],
  "nodes": [
    {
      "id": "98517a08-3fc4-4c0c-aa4b-44d93c864eb4",
      "name": "Check file type",
      "type": "n8n-nodes-base.switch",
      "position": [
        220,
        860
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "40ee8e68-2b72-4ba9-b7a2-8c976852d48b",
                    "operator": {
                      "type": "string",
                      "operation": "contains"
                    },
                    "leftValue": "={{ $('Webhook Invoice upload').item.binary.file.mimeType }}",
                    "rightValue": "image"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "c4315e16-313f-4363-a625-71436498e46a",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $('Webhook Invoice upload').item.binary.file.mimeType }}",
                    "rightValue": "application/pdf"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "cffb0678-f006-47e0-91ea-afd17f133a77",
                    "operator": {
                      "type": "string",
                      "operation": "contains"
                    },
                    "leftValue": "={{ $('Webhook Invoice upload').item.binary.file.mimeType }}",
                    "rightValue": "csv"
                  }
                ]
              }
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "6ef5d99c-b842-4290-9766-8b780df66f6b",
      "name": "Invoice data",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        738,
        1110
      ],
      "parameters": {
        "columns": {
          "value": {
            "total": "={{ $json.total }}",
            "currency": "={{ $json.currency }}",
            "due_date": "={{ $json.due_date }}",
            "subtotal": "={{ $json.subtotal }}",
            "tax_total": "={{ $json.tax_total }}",
            "invoice_id": "={{ $json.invoice_id }}",
            "vendor_name": "={{ $json.vendor_name }}",
            "invoice_date": "={{ $json.invoice_date }}",
            "customer_name": "={{ $json.customer_name }}"
          },
          "schema": [
            {
              "id": "invoice_id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "invoice_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "invoice_date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "invoice_date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "due_date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "due_date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "customer_name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "customer_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "vendor_name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "vendor_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "subtotal",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "subtotal",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "tax_total",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "tax_total",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "total",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "total",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "currency",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "currency",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "customer_address",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "customer_address",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "customer_tax_id",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "customer_tax_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "vendor_address",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "vendor_address",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "vendor_tax_id",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "vendor_tax_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "vendor_iban",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "vendor_iban",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "vendor_bic",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "vendor_bic",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "line_id",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "line_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "description",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "description",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "quantity",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "quantity",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "unit_price",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "unit_price",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "line_total",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "line_total",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "tax_rate",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "tax_rate",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "invoice_id"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 0,
          "cachedResultUrl": "",
          "cachedResultName": "Invoice"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "0",
          "cachedResultUrl": "",
          "cachedResultName": ""
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "6b0ce6fd-5d09-4bc2-a3b2-cc8c0e2878d6",
      "name": "Invoice Data",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1256,
        760
      ],
      "parameters": {
        "columns": {
          "value": {
            "total": "={{ $json.total }}",
            "currency": "={{ $json.currency }}",
            "due_date": "={{ $json.due_date }}",
            "subtotal": "={{ $json.subtotal }}",
            "tax_total": "={{ $json.tax_total }}",
            "invoice_id": "={{ $json.invoice_id }}",
            "vendor_name": "={{ $json.vendor_name }}",
            "invoice_date": "={{ $json.invoice_date }}",
            "customer_name": "={{ $json.customer_name }}"
          },
          "schema": [
            {
              "id": "invoice_id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "invoice_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "invoice_date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "invoice_date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "due_date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "due_date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "customer_name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "customer_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "vendor_name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "vendor_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "subtotal",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "subtotal",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "tax_total",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "tax_total",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "total",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "total",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "currency",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "currency",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Accounting",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Accounting",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "invoice_id"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 0,
          "cachedResultUrl": "",
          "cachedResultName": "Invoice"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "0",
          "cachedResultUrl": "",
          "cachedResultName": ""
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "7f5b8ffe-d4e8-4b7b-803e-6c37d0da0221",
      "name": "Transfrom data",
      "type": "n8n-nodes-base.code",
      "position": [
        1036,
        760
      ],
      "parameters": {
        "jsCode": "const raw = $input.first().json.text || '';\n\n// 1. Remove code block syntax like ```json ... ```\nconst cleaned = raw.replace(/```json|```/g, '').trim();\n\n\n  const parsed = JSON.parse(cleaned);\n  return [{ json: parsed }];"
      },
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "b818ac61-4837-4a9f-b90e-bb6b4b7739c1",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        748,
        880
      ],
      "parameters": {
        "options": {},
        "modelName": "models/gemini-1.5-flash"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "2941bf32-0db6-4486-8696-e207de09364c",
      "name": "Format data from text",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        660,
        660
      ],
      "parameters": {
        "text": "=Extract the following invoice details from the given raw text:\n\n- invoice_id  \n- invoice_date  \n- due_date  \n- customer_name  \n- vendor_name  \n- subtotal  \n- tax_total  \n- total  \n- currency\n\nUse the following input text:\n{{ $json.text }}\n\nReturn the result as a valid JSON object using this exact structure:\n\n{\n  \"invoice_id\": \"string or null\",\n  \"invoice_date\": \"string (e.g., 2024-10-10) or null\",\n  \"due_date\": \"string (e.g., 2024-10-25) or null\",\n  \"customer_name\": \"string or null\",\n  \"vendor_name\": \"string or null\",\n  \"subtotal\": \"string or null\",\n  \"tax_total\": \"string or null\",\n  \"total\": \"string or null\",\n  \"currency\": \"string (e.g., \u20ac, $, \u00a3) or null\"\n}\n\nIf any field is missing or not found, set it as `null`. Return only the JSON output without extra text.\n",
        "batching": {},
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "7c829587-f028-4332-831f-92f9529b72ca",
      "name": "Webhook Invoice upload",
      "type": "n8n-nodes-base.webhook",
      "position": [
        0,
        860
      ],
      "parameters": {
        "path": "uploadDoc",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2
    },
    {
      "id": "05176b33-fcda-4f1a-84fa-2449108a0a54",
      "name": "PDF to Text",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        440,
        860
      ],
      "parameters": {
        "options": {},
        "operation": "pdf",
        "binaryPropertyName": "file"
      },
      "typeVersion": 1
    },
    {
      "id": "81690344-d04c-428b-b720-bb539fbe2bbe",
      "name": "Image to Text",
      "type": "n8n-nodes-tesseractjs.tesseractNode",
      "position": [
        440,
        660
      ],
      "parameters": {
        "options": {},
        "inputDataFieldName": "file"
      },
      "typeVersion": 1
    },
    {
      "id": "a0f49ed7-1d42-4df8-a802-74754d1549c0",
      "name": "CSV to JSON",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        440,
        1110
      ],
      "parameters": {
        "options": {},
        "binaryPropertyName": "file"
      },
      "typeVersion": 1
    },
    {
      "id": "0473ba6b-734e-4f53-8ecb-86711db1bd76",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -60,
        1300
      ],
      "parameters": {
        "color": 2,
        "width": 1500,
        "height": 540,
        "content": "---\n### **Purpose**\n * To automatically extract structured data from uploaded documents (PDFs, images, or CSVs) \u2014 such as invoices, logs, or reports \u2014 and save the results into Google Sheets using AI and OCR.\n\n---\n### **Core Logic**\n1. **Webhook Trigger** receives the uploaded document.\n2. **Switch Node** detects file type:\n   *  Image \u2192 Parsed using **Tesseract OCR**\n   *  PDF \u2192 Parsed via built-in PDF extractor\n   *  CSV \u2192 Parsed as raw text\n3. Extracted text is sent to **Google Gemini AI** to identify fields like:\n   * `invoice_id`, `invoice_date`, `total`, etc.\n4. AI output is converted into valid JSON.\n5. JSON is **appended to Google Sheets** via `appendOrUpdate`.\n\n---\n### **Outcome**\n* Extracted invoice/report data is stored cleanly in a Google Sheet.\n* Works with scanned documents, images, and structured files.\n* Enables AI-powered automation of manual data entry workflows."
      },
      "typeVersion": 1
    },
    {
      "id": "63a9e69e-566c-4db6-9d31-b25f438fbd26",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -72,
        550
      ],
      "parameters": {
        "color": 7,
        "width": 1500,
        "height": 720,
        "content": "## Smart Document Parser for Invoices, Logs or Sensor Reports (PDF/Image/csv to Sheet)"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "b5ae5035-b75f-4f8d-8d43-020fdb2c529e",
  "connections": {
    "CSV to JSON": {
      "main": [
        [
          {
            "node": "Invoice data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "PDF to Text": {
      "main": [
        [
          {
            "node": "Format data from text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Image to Text": {
      "main": [
        [
          {
            "node": "Format data from text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Transfrom data": {
      "main": [
        [
          {
            "node": "Invoice Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check file type": {
      "main": [
        [
          {
            "node": "Image to Text",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "PDF to Text",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "CSV to JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format data from text": {
      "main": [
        [
          {
            "node": "Transfrom data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook Invoice upload": {
      "main": [
        [
          {
            "node": "Check file type",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Format data from text",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

How this works

Extract valuable insights from invoices, logs, or sensor reports effortlessly, saving hours of manual data entry by converting PDFs, images, or CSVs into organised Google Sheets. This workflow suits small business owners handling supplier invoices, field technicians processing sensor data, or analysts reviewing equipment logs who need quick, accurate data structuring without advanced coding skills. The key step involves the Google Gemini AI model intelligently parsing the document content after initial text extraction, followed by formatting and appending the results to your sheet for seamless analysis.

Use this workflow when dealing with unstructured documents arriving via uploads or APIs, such as automated invoice processing from email attachments or batch-converting sensor images from IoT devices. Avoid it for highly customised extractions requiring domain-specific rules, where a dedicated OCR service like Tesseract might need tuning, or for real-time streaming data that demands lower latency than webhook triggers allow. Common variations include adapting the AI prompts for medical reports or financial statements, or integrating with email nodes to pull files directly from inboxes.

About this workflow

Smart Document Parser for Invoices, Logs or Sensor Reports (PDF/Image/csv to Sheet). Uses googleSheets, lmChatGoogleGemini, chainLlm, extractFromFile. Webhook trigger; 12 nodes.

Source: https://github.com/abbasZaidi110/n8n-Parse-Invoices-Documents-with-Gemini-AI-OCR-and-Google-Sheets-Integration/blob/main/main.json — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

ANIS_HUB 1. Uses gmail, googleDrive, googleSheets, httpRequest. Webhook trigger; 89 nodes.

Gmail, Google Drive, Google Sheets +3
AI & RAG

Resume Screening & Behavioral Interviews with Gemini, Elevenlabs, & Notion ATS copy. Uses outputParserStructured, chainLlm, googleDrive, stickyNote. Webhook trigger; 67 nodes.

Output Parser Structured, Chain Llm, Google Drive +9
AI & RAG

Candidate Engagement | Resume Screening | AI Voice Interviews | Applicant Insights

Output Parser Structured, Chain Llm, Google Drive +9
AI & RAG

leads. Uses supabase, gmail, formTrigger, httpRequest. Webhook trigger; 62 nodes.

Supabase, Gmail, Form Trigger +13
AI & RAG

Categories: Accounting Automation • OCR Processing • AI Data Extraction • Business Tools

HTTP Request, OpenRouter Chat, Google Gemini Chat +4