AutomationFlowsData & Sheets › Export Google Sheets to CSV or Excel and Email Files with Gmail

Export Google Sheets to CSV or Excel and Email Files with Gmail

ByisaWOW @isawow on n8n.io

This workflow collects a Google Sheet ID and export preferences via an n8n Form, reads the selected tab from Google Sheets, converts the rows to CSV or Excel (XLSX), and sends the generated file as a Gmail attachment to the requester. Receives a request through an n8n Form that…

Event trigger★★★★☆ complexity11 nodesForm TriggerGoogle SheetsSpreadsheet FileGmail
Data & Sheets Trigger: Event Nodes: 11 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #17189 — we link there as the canonical source.

This workflow follows the Form Trigger → Gmail 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": "pB7y7FbH23hCMDlJ",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Google Sheets to CSV or Excel Exporter",
  "tags": [],
  "nodes": [
    {
      "id": "1ba22a95-55ca-4f34-8413-c6c43f23f3b6",
      "name": "Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1056,
        -80
      ],
      "parameters": {
        "width": 440,
        "height": 960,
        "content": "## Google Sheets to CSV or Excel Exporter\n\nTurn any Google Sheet into a downloadable CSV or Excel file without writing code. A user submits a short form with a Sheet ID, an email address, and a format choice. The workflow reads the sheet, builds the file, and emails it straight to their inbox. It is handy for teams who need quick, self-serve exports.\n\n### How it works\n1. **1. Form - User Requests Sheet Export** collects the Sheet ID, email, format, tab name, and file name.\n2. **2. Sheets - Read Data from User Sheet** pulls the rows from the chosen tab.\n3. **3. Code - Validate Input and Attach Context** checks the input and stops with a clear message if the sheet is empty.\n4. **4. Switch - Route to CSV or XLSX** sends the run down the CSV or the Excel path.\n5. A **Spreadsheet File** node builds the file and **7. Gmail - Email File to User** sends it as an attachment.\n\n### Setup steps\n1. Open node 2 and connect your Google Sheets OAuth2 credential with read access.\n2. Open node 7 and connect your Gmail OAuth2 credential.\n3. Save and activate the workflow, then open the form URL and run a test export.\n\n### Customization\n- Google Sheets returns up to 1000 rows by default. For larger sheets, export from Google directly.\n- Share the source sheet with the connected Google account, or the read will fail."
      },
      "typeVersion": 1
    },
    {
      "id": "5cdceade-1852-4901-8ae4-6e7021c0d600",
      "name": "S1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1536,
        112
      ],
      "parameters": {
        "color": 7,
        "width": 563,
        "height": 440,
        "content": "## 1. Collect request and read sheet\nThe form takes the Sheet ID, email, format, tab, and file name. Google Sheets then reads the rows from the chosen tab."
      },
      "typeVersion": 1
    },
    {
      "id": "d5a2dd18-1394-439c-a7d5-4f7f174e281a",
      "name": "S2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2160,
        160
      ],
      "parameters": {
        "color": 7,
        "width": 561,
        "height": 360,
        "content": "## 2. Validate and route\nThe Code node checks the input and stops with a clear error if the sheet is empty. The Switch node picks the CSV or the Excel path."
      },
      "typeVersion": 1
    },
    {
      "id": "6d02c894-736c-42a9-a856-b15209802e1e",
      "name": "S3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2800,
        16
      ],
      "parameters": {
        "color": 7,
        "width": 699,
        "height": 682,
        "content": "## 3. Build the file and email it\nThe Spreadsheet File nodes create the CSV or Excel file. Gmail then sends it to the user as an attachment."
      },
      "typeVersion": 1
    },
    {
      "id": "4b5d8994-8af7-4f66-8b3f-c7373133f7b7",
      "name": "1. Form - User Requests Sheet Export",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        1632,
        304
      ],
      "parameters": {
        "options": {
          "path": "sheets-export",
          "buttonLabel": "Export My Sheet",
          "appendAttribution": false
        },
        "formTitle": "Google Sheets Exporter",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Your Email Address",
              "placeholder": "user@example.com - the exported file will be sent here",
              "requiredField": true
            },
            {
              "fieldLabel": "Google Sheet ID",
              "placeholder": "Paste the Sheet ID from the URL - the long string between /d/ and /edit",
              "requiredField": true
            },
            {
              "fieldLabel": "Sheet Tab Name",
              "placeholder": "Leave blank to use the first tab, or enter the exact tab name e.g. Sales Data"
            },
            {
              "fieldType": "dropdown",
              "fieldLabel": "Export Format",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Excel (.xlsx)"
                  },
                  {
                    "option": "CSV (.csv)"
                  }
                ]
              },
              "requiredField": true
            },
            {
              "fieldLabel": "File Name (without extension)",
              "placeholder": "e.g. Q2-Sales-Report - leave blank for default Export"
            }
          ]
        },
        "formDescription": "Enter your Google Sheet details below. We will convert the data to your chosen format and email the file to you within seconds."
      },
      "typeVersion": 2.2
    },
    {
      "id": "cd2cc99b-3e5f-4f34-b7d3-ca90472ef00e",
      "name": "2. Sheets - Read Data from User Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1872,
        304
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $json['Sheet Tab Name'] && $json['Sheet Tab Name'].trim() !== '' ? $json['Sheet Tab Name'].trim() : 'Sheet1' }}"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json['Google Sheet ID'].trim() }}"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "e63b1ffc-4c06-4563-93fa-1a51f34f2de9",
      "name": "3. Code - Validate Input and Attach Context",
      "type": "n8n-nodes-base.code",
      "position": [
        2256,
        304
      ],
      "parameters": {
        "jsCode": "// Validate that sheet has data and pass form context forward\nconst rows    = $input.all();\nconst form    = $('1. Form - User Requests Sheet Export').first().json;\n\nconst userEmail  = (form['Your Email Address']         || '').trim();\nconst sheetId    = (form['Google Sheet ID']            || '').trim();\nconst tabName    = (form['Sheet Tab Name']             || '').trim();\nconst format     = (form['Export Format']              || 'Excel (.xlsx)').trim();\nconst rawName    = (form['File Name (without extension)'] || '').trim();\nconst fileName   = rawName !== '' ? rawName : 'Export';\n\n// Validate email\nif (!userEmail || !userEmail.includes('@')) {\n  throw new Error('Valid email address is required.');\n}\n\n// Validate sheet ID\nif (!sheetId) {\n  throw new Error('Google Sheet ID is required.');\n}\n\n// Check that sheet returned data\nif (!rows || rows.length === 0 || !rows[0].json || Object.keys(rows[0].json).length === 0) {\n  throw new Error(\n    'The sheet appears to be empty or the tab name is incorrect. ' +\n    'Sheet ID: ' + sheetId + '. Tab: ' + (tabName || 'Sheet1')\n  );\n}\n\n// Detect format: xlsx or csv\nconst isXlsx = format.toLowerCase().includes('excel') || format.toLowerCase().includes('xlsx');\nconst fileExt  = isXlsx ? 'xlsx' : 'csv';\nconst mimeType = isXlsx ? 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' : 'text/csv';\n\n// Pass all context on each row so Convert File node can access it\nreturn rows.map(function(item) {\n  return {\n    json: {\n      ...item.json,\n      _meta: {\n        userEmail,\n        sheetId,\n        fileName,\n        fileExt,\n        mimeType,\n        isXlsx,\n        totalRows: rows.length\n      }\n    }\n  };\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "22ce9572-7626-4788-8004-4e99e6773be8",
      "name": "4. Switch - Route to CSV or XLSX",
      "type": "n8n-nodes-base.switch",
      "position": [
        2496,
        304
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "xlsx",
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "r-xlsx",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json._meta.isXlsx }}",
                    "rightValue": ""
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "csv",
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "r-csv",
                    "operator": {
                      "type": "boolean",
                      "operation": "false",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json._meta.isXlsx }}",
                    "rightValue": ""
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.4
    },
    {
      "id": "a56f2f34-04d9-466e-b275-d16c28495fb9",
      "name": "5. Spreadsheet File - Convert to XLSX",
      "type": "n8n-nodes-base.spreadsheetFile",
      "position": [
        2960,
        192
      ],
      "parameters": {
        "options": {
          "fileName": "={{ $json._meta.fileName + '.xlsx' }}"
        },
        "operation": "toFile",
        "fileFormat": "xlsx"
      },
      "typeVersion": 2
    },
    {
      "id": "aa69490b-c05e-4caf-a2a7-c0cb7503a211",
      "name": "6. Spreadsheet File - Convert to CSV",
      "type": "n8n-nodes-base.spreadsheetFile",
      "position": [
        2960,
        416
      ],
      "parameters": {
        "options": {
          "fileName": "={{ $json._meta.fileName + '.csv' }}"
        },
        "operation": "toFile",
        "fileFormat": "csv"
      },
      "typeVersion": 2
    },
    {
      "id": "a8b0b07d-7b28-457f-a78c-9fc3a68217d3",
      "name": "7. Gmail - Email File to User",
      "type": "n8n-nodes-base.gmail",
      "position": [
        3312,
        288
      ],
      "parameters": {
        "sendTo": "={{ $('3. Code - Validate Input and Attach Context').first().json._meta.userEmail }}",
        "message": "=<div style=\"font-family:Arial,sans-serif;max-width:580px;margin:0 auto;background:#f9fafb;\">\n  <div style=\"background:#1d4ed8;padding:20px 24px;border-radius:8px 8px 0 0;\">\n    <h2 style=\"color:#fff;margin:0;font-size:17px;\">Your Sheet Export is Ready</h2>\n  </div>\n  <div style=\"background:#fff;padding:20px 24px;border:1px solid #e5e7eb;border-top:none;\">\n    <p style=\"font-size:14px;color:#374151;margin:0 0 14px;\">Your Google Sheet data has been exported and attached to this email.</p>\n    <div style=\"background:#eff6ff;border-left:4px solid #1d4ed8;padding:12px 14px;border-radius:0 6px 6px 0;margin-bottom:14px;\">\n      <table style=\"font-size:13px;width:100%;\">\n        <tr><td style=\"color:#6b7280;padding:3px 0;width:100px;\">File</td><td style=\"color:#111827;font-weight:600;\">{{ $('3. Code - Validate Input and Attach Context').first().json._meta.fileName }}.{{ $('3. Code - Validate Input and Attach Context').first().json._meta.fileExt }}</td></tr>\n        <tr><td style=\"color:#6b7280;padding:3px 0;\">Format</td><td style=\"color:#111827;\">{{ $('3. Code - Validate Input and Attach Context').first().json._meta.fileExt.toUpperCase() }}</td></tr>\n        <tr><td style=\"color:#6b7280;padding:3px 0;\">Rows</td><td style=\"color:#111827;\">{{ $('3. Code - Validate Input and Attach Context').first().json._meta.totalRows }}</td></tr>\n      </table>\n    </div>\n    <p style=\"font-size:12px;color:#9ca3af;margin:0;\">Exported by Google Sheets Exporter via n8n. Sheet ID: {{ $('3. Code - Validate Input and Attach Context').first().json._meta.sheetId }}</p>\n  </div>\n</div>",
        "options": {
          "senderName": "Sheets Exporter",
          "attachmentsUi": {
            "attachmentsBinary": [
              {}
            ]
          },
          "appendAttribution": false
        },
        "subject": "=Your export is ready - {{ $('3. Code - Validate Input and Attach Context').first().json._meta.fileName }}.{{ $('3. Code - Validate Input and Attach Context').first().json._meta.fileExt }}"
      },
      "typeVersion": 2.1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "1b7c15cc-b339-455e-b646-f0b7341d1264",
  "nodeGroups": [],
  "connections": {
    "4. Switch - Route to CSV or XLSX": {
      "main": [
        [
          {
            "node": "5. Spreadsheet File - Convert to XLSX",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "6. Spreadsheet File - Convert to CSV",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "1. Form - User Requests Sheet Export": {
      "main": [
        [
          {
            "node": "2. Sheets - Read Data from User Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6. Spreadsheet File - Convert to CSV": {
      "main": [
        [
          {
            "node": "7. Gmail - Email File to User",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "2. Sheets - Read Data from User Sheet": {
      "main": [
        [
          {
            "node": "3. Code - Validate Input and Attach Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5. Spreadsheet File - Convert to XLSX": {
      "main": [
        [
          {
            "node": "7. Gmail - Email File to User",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "3. Code - Validate Input and Attach Context": {
      "main": [
        [
          {
            "node": "4. Switch - Route to CSV or XLSX",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

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

About this workflow

This workflow collects a Google Sheet ID and export preferences via an n8n Form, reads the selected tab from Google Sheets, converts the rows to CSV or Excel (XLSX), and sends the generated file as a Gmail attachment to the requester. Receives a request through an n8n Form that…

Source: https://n8n.io/workflows/17189/ — original creator credit. Request a take-down →

More Data & Sheets workflows → · Browse all categories →

Related workflows

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

Data & Sheets

cdp_router. Uses gmailTrigger, telegramTrigger, googleSheets, httpRequest. Event-driven trigger; 53 nodes.

Gmail Trigger, Telegram Trigger, Google Sheets +4
Data & Sheets

cdp_router. Uses gmailTrigger, telegramTrigger, googleSheets, httpRequest. Event-driven trigger; 53 nodes.

Gmail Trigger, Telegram Trigger, Google Sheets +4
Data & Sheets

This workflow triggers on an n8n Form submission, checks Google Sheets for duplicate clients, and for new entries creates and shares a Google Drive folder, creates a Notion database page, sends a Gmai

Form Trigger, Google Sheets, Google Drive +2
Data & Sheets

Shopify Csv Import. Uses formTrigger, moveBinaryData, spreadsheetFile, googleSheets. Event-driven trigger; 12 nodes.

Form Trigger, Move Binary Data, Spreadsheet File +2
Data & Sheets

Video for workflow process

Form Trigger, Airtable, Google Sheets +1