{
  "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
          }
        ]
      ]
    }
  }
}