8
n8n 中文网amn8n.com

Google报告

高级

这是一个Document Extraction, AI Chatbot领域的自动化工作流,包含 26 个节点。主要使用 Set, Code, Merge, Aggregate, GoogleSheets 等节点。 使用AI分析从Google Sheets生成多期财务报告

前置要求
  • Google Sheets API 凭证
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "id": "p3BhWvtYryFCnIMZ",
  "meta": {
    "instanceId": "eb2e35a6e4ba3ff63ef980c031da61d993b4f2faa0ccc19283b4ab43f9ca13e6"
  },
  "name": "Google报告",
  "tags": [],
  "nodes": [
    {
      "id": "de33033e-aff3-4999-8c76-f586716a8b50",
      "name": "DeepSeek 聊天模型",
      "type": "@n8n/n8n-nodes-langchain.lmChatDeepSeek",
      "position": [
        -360,
        340
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "deepSeekApi": {
          "id": "FiU3VouUwvrGU8CJ",
          "name": "DeepSeek account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "030b27e4-55c0-478d-b401-aca4c9aa14a8",
      "name": "窗口缓冲记忆1",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        -240,
        360
      ],
      "parameters": {},
      "typeVersion": 1.3
    },
    {
      "id": "c504a6ec-0783-4a36-bdbf-45e5b11963f9",
      "name": "调用 n8n 工作流工具",
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "position": [
        -80,
        360
      ],
      "parameters": {
        "workflowId": {
          "__rl": true,
          "mode": "list",
          "value": "4ASVA3i1vaFwj20h",
          "cachedResultName": "Sub flowBao cao doanh thu"
        },
        "workflowInputs": {
          "value": {
            "End_Current": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('End_Current', ``, 'string') }}",
            "End_LastYear": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('End_LastYear', ``, 'string') }}",
            "End_LastMonth": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('End_LastMonth', ``, 'string') }}",
            "Start_Current": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Start_Current', ``, 'string') }}",
            "Start_LastYear": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Start_LastYear', ``, 'string') }}",
            "Start_LastMonth": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Start_LastMonth', ``, 'string') }}"
          },
          "schema": [
            {
              "id": "Start_Current",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Start_Current",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "End_Current",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "End_Current",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Start_LastMonth",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Start_LastMonth",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "End_LastMonth",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "End_LastMonth",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Start_LastYear",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Start_LastYear",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "End_LastYear",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "End_LastYear",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "99e1edc5-f43f-4c1b-8649-99b77ac6479c",
      "name": "当收到聊天消息时",
      "type": "@n8n/n8n-nodes-langchain.chatTrigger",
      "position": [
        -600,
        100
      ],
      "webhookId": "fbf93f24-cc03-4c72-9b6f-5d441f3b097c",
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.1
    },
    {
      "id": "0eeaa722-fdf0-4afd-a837-94d26e14c1dd",
      "name": "AI 代理",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -300,
        100
      ],
      "parameters": {
        "options": {
          "systemMessage": "=You are the company accountant. Summarize revenue and expense information from the tool, evaluate, compare, and respond accordingly. You are required to provide all information for reporting purposes, including:\n\nStart date (Start_Current),\n\nEnd date (End_Current),\n\nStart date of last month,\n\nEnd date of last month,\n\nStart of last year,\n\nEnd of last year\n\nAll dates must be in the format dd/Mm/yyyy.\n\nGenerate the output as JSON in the format without showing it in the chat, for json format example:\n\n{\n  \"Start_Current\": \"01/07/2025\",\n  \"End_Current\": \"31/07/2025\",\n  \"Start_LastMonth\": \"01/06/2025\",\n  \"End_LastMonth\": \"30/06/2025\",\n  \"Start_LastYear\": \"01/01/2024\",\n  \"End_LastYear\": \"31/12/20"
        },
        "hasOutputParser": true
      },
      "typeVersion": 2
    },
    {
      "id": "934c56a4-7534-4add-8095-1f085256af7a",
      "name": "便签",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -360,
        700
      ],
      "parameters": {
        "color": 6,
        "width": 2340,
        "height": 1180,
        "content": "## 子工作流:Google Analytics数据"
      },
      "typeVersion": 1
    },
    {
      "id": "4140bc3a-d19a-4274-8ba4-84f7334a46e7",
      "name": "当由另一个工作流执行时",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        -100,
        1100
      ],
      "parameters": {
        "workflowInputs": {
          "values": [
            {
              "name": "Start_Current"
            },
            {
              "name": "End_Current"
            },
            {
              "name": "Start_LastMonth"
            },
            {
              "name": "End_LastMonth"
            },
            {
              "name": "Start_LastYear"
            },
            {
              "name": "End_LastYear"
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "8bf4a0f4-1b40-4ac1-8138-6c831f6003e1",
      "name": "格式化日期",
      "type": "n8n-nodes-base.set",
      "position": [
        60,
        1100
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "7bbe88fb-9866-4bae-8db4-48be473fa179",
              "name": "Start_Current",
              "type": "string",
              "value": "={{ $json.Start_Current }}"
            },
            {
              "id": "7566ba91-566f-4a1e-8e85-af9d7975f266",
              "name": "End_Current",
              "type": "string",
              "value": "={{ $json.End_Current }}"
            },
            {
              "id": "db654f49-36d6-48da-9189-ff536bedd21e",
              "name": "Start_LastMonth",
              "type": "string",
              "value": "={{ $json.Start_LastMonth }}"
            },
            {
              "id": "5d708106-3c8f-4a73-b5d2-62fc93fe42f5",
              "name": "End_LastMonth",
              "type": "string",
              "value": "={{ $json.End_LastMonth }}"
            },
            {
              "id": "e4c9946c-21c0-48aa-8327-7135eaf2c4b2",
              "name": "Start_LastYear",
              "type": "string",
              "value": "={{ $json.Start_LastYear }}"
            },
            {
              "id": "38afadf2-7d8d-45d1-9ab0-970ca1497f8f",
              "name": "End_LastYear",
              "type": "string",
              "value": "={{ $json.End_LastYear }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "7fc2f2eb-b4d5-4ea3-bc18-e0324d65c826",
      "name": "从Google表格获取收入",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        340,
        1100
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1168390826,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1UAMO24QtfkR50VGu1wpksuYiWffi28pHfm6bihd5IP8/edit#gid=1168390826",
          "cachedResultName": "Doanh thu theo ngày"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1UAMO24QtfkR50VGu1wpksuYiWffi28pHfm6bihd5IP8",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1UAMO24QtfkR50VGu1wpksuYiWffi28pHfm6bihd5IP8/edit?usp=drivesdk",
          "cachedResultName": "Data Bao cao kinh doanh"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "0Zfrl7z70DMniz8b",
          "name": "Google Sheets account"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "91092c78-4d3a-478f-b42d-c92c86595f9e",
      "name": "透视上期",
      "type": "n8n-nodes-base.code",
      "onError": "continueRegularOutput",
      "position": [
        540,
        1260
      ],
      "parameters": {
        "jsCode": "// Lấy Start_LastMonth và End_LastMonth từ node Format Date\nconst startCurrentRaw = $('Format Date').first().json.Start_LastMonth;\nconst endCurrentRaw = $('Format Date').first().json.End_LastMonth;\n\n// Debug: In ra giá trị thô của Start_LastMonth và End_LastMonth\nconsole.log('Start Current Raw:', startCurrentRaw);\nconsole.log('End Current Raw:', endCurrentRaw);\n\n// Hàm chuyển đổi định dạng ngày DD/MM/YYYY hoặc YYYY-MM-DD thành Date object\nfunction parseDate(dateStr) {\n  if (!dateStr || typeof dateStr !== 'string') {\n    console.log('Invalid date string:', dateStr);\n    return null;\n  }\n  if (dateStr.includes('/')) {\n    const [day, month, year] = dateStr.split('/').map(Number);\n    return new Date(year, month - 1, day);\n  } else if (dateStr.includes('-')) {\n    return new Date(dateStr);\n  }\n  console.log('Unrecognized date format:', dateStr);\n  return null;\n}\n\n// Chuyển đổi Start_LastMonth và End_LastMonth thành Date object\nconst startCurrent = parseDate(startCurrentRaw);\nconst endCurrent = parseDate(endCurrentRaw);\n\n// Debug: In ra giá trị sau khi chuyển đổi\nconsole.log('Start Current Parsed:', startCurrent);\nconsole.log('End Current Parsed:', endCurrent);\n\n// Kiểm tra nếu Start_LastMonth hoặc End_LastMonth không hợp lệ\nif (!startCurrent || !endCurrent) {\n  throw new Error('Invalid Start_LastMonth or End_LastMonth date format');\n}\n\n// Tạo một object để lưu trữ tổng Số tiền theo Phân loại\nconst aggregatedData = {};\n\n// Hàm chuẩn hóa chuỗi: loại bỏ khoảng trắng thừa và chuyển về chữ thường\nfunction normalizeString(str) {\n  return str ? str.trim().toLowerCase() : '';\n}\n\n// Lọc và tính tổng\nfor (const item of $input.all()) {\n  // Chuyển Date từ định dạng DD/MM/YYYY hoặc YYYY-MM-DD thành Date object\n  const itemDate = parseDate(item.json.Date);\n\n  if (!itemDate) {\n    console.log('Skipping item due to invalid date:', item.json);\n    continue;\n  }\n\n  const amount = Number(item.json['Số tiền']) || 0;\n\n  // Kiểm tra nếu Date nằm trong khoảng Start_LastMonth và End_LastMonth\n  if (itemDate >= startCurrent && itemDate <= endCurrent) {\n    // Chuẩn hóa Phân loại trước khi tạo key\n    const phanLoai = normalizeString(item.json['Phân loại']);\n\n    // Tạo key duy nhất từ Phân loại\n    const key = phanLoai;\n\n    // Debug: In ra key để kiểm tra\n    console.log('Key:', key);\n\n    // Nếu key chưa tồn tại, khởi tạo giá trị ban đầu\n    if (!aggregatedData[key]) {\n      aggregatedData[key] = {\n        'Phân loại': item.json['Phân loại'], // Giữ nguyên giá trị gốc để hiển thị\n        'Tổng số tiền': 0\n      };\n    }\n\n    // Cộng dồn Số tiền vào Tổng số tiền\n    aggregatedData[key]['Tổng số tiền'] += amount;\n  }\n}\n\n// Debug: In ra số lượng nhóm và dữ liệu đã gộp\nconsole.log('Number of groups:', Object.keys(aggregatedData).length);\nconsole.log('Aggregated Data:', aggregatedData);\n\n// Chuyển object aggregatedData thành mảng để trả về\nconst result = Object.values(aggregatedData);\n\nreturn result.map(item => ({ json: item }));"
      },
      "retryOnFail": true,
      "typeVersion": 2
    },
    {
      "id": "03bf6db2-3d53-4507-b286-0b166e8ab8a3",
      "name": "透视本期",
      "type": "n8n-nodes-base.code",
      "onError": "continueRegularOutput",
      "position": [
        480,
        940
      ],
      "parameters": {
        "jsCode": "// Lấy Start_Current và End_Current từ node Format Date\nconst startCurrentRaw = $('Format Date').first().json.Start_Current;\nconst endCurrentRaw = $('Format Date').first().json.End_Current;\n\n// Debug: In ra giá trị thô của Start_Current và End_Current\nconsole.log('Start Current Raw:', startCurrentRaw);\nconsole.log('End Current Raw:', endCurrentRaw);\n\n// Hàm chuyển đổi định dạng ngày DD/MM/YYYY hoặc YYYY-MM-DD thành Date object\nfunction parseDate(dateStr) {\n  if (!dateStr || typeof dateStr !== 'string') {\n    console.log('Invalid date string:', dateStr);\n    return null;\n  }\n  if (dateStr.includes('/')) {\n    const [day, month, year] = dateStr.split('/').map(Number);\n    return new Date(year, month - 1, day);\n  } else if (dateStr.includes('-')) {\n    return new Date(dateStr);\n  }\n  console.log('Unrecognized date format:', dateStr);\n  return null;\n}\n\n// Chuyển đổi Start_Current và End_Current thành Date object\nconst startCurrent = parseDate(startCurrentRaw);\nconst endCurrent = parseDate(endCurrentRaw);\n\n// Debug: In ra giá trị sau khi chuyển đổi\nconsole.log('Start Current Parsed:', startCurrent);\nconsole.log('End Current Parsed:', endCurrent);\n\n// Kiểm tra nếu Start_Current hoặc End_Current không hợp lệ\nif (!startCurrent || !endCurrent) {\n  throw new Error('Invalid Start_Current or End_Current date format');\n}\n\n// Tạo một object để lưu trữ tổng Số tiền theo Phân loại\nconst aggregatedData = {};\n\n// Hàm chuẩn hóa chuỗi: loại bỏ khoảng trắng thừa và chuyển về chữ thường\nfunction normalizeString(str) {\n  return str ? str.trim().toLowerCase() : '';\n}\n\n// Lọc và tính tổng\nfor (const item of $input.all()) {\n  // Chuyển Date từ định dạng DD/MM/YYYY hoặc YYYY-MM-DD thành Date object\n  const itemDate = parseDate(item.json.Date);\n\n  if (!itemDate) {\n    console.log('Skipping item due to invalid date:', item.json);\n    continue;\n  }\n\n  const amount = Number(item.json['Số tiền']) || 0;\n\n  // Kiểm tra nếu Date nằm trong khoảng Start_Current và End_Current\n  if (itemDate >= startCurrent && itemDate <= endCurrent) {\n    // Chuẩn hóa Phân loại trước khi tạo key\n    const phanLoai = normalizeString(item.json['Phân loại']);\n\n    // Tạo key duy nhất từ Phân loại\n    const key = phanLoai;\n\n    // Debug: In ra key để kiểm tra\n    console.log('Key:', key);\n\n    // Nếu key chưa tồn tại, khởi tạo giá trị ban đầu\n    if (!aggregatedData[key]) {\n      aggregatedData[key] = {\n        'Phân loại': item.json['Phân loại'], // Giữ nguyên giá trị gốc để hiển thị\n        'Tổng số tiền': 0\n      };\n    }\n\n    // Cộng dồn Số tiền vào Tổng số tiền\n    aggregatedData[key]['Tổng số tiền'] += amount;\n  }\n}\n\n// Debug: In ra số lượng nhóm và dữ liệu đã gộp\nconsole.log('Number of groups:', Object.keys(aggregatedData).length);\nconsole.log('Aggregated Data:', aggregatedData);\n\n// Chuyển object aggregatedData thành mảng để trả về\nconst result = Object.values(aggregatedData);\n\nreturn result.map(item => ({ json: item }));"
      },
      "retryOnFail": true,
      "typeVersion": 2
    },
    {
      "id": "aa5957fa-35a9-42a2-8c47-cdff23f9e683",
      "name": "格式化本期数据",
      "type": "n8n-nodes-base.set",
      "position": [
        700,
        780
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "657e8f86-3f7e-44d0-9428-4150ec0b5e59",
              "name": "currentCycle.startDate",
              "type": "string",
              "value": "={{ $('Format Date').item.json.Start_Current }}"
            },
            {
              "id": "e2b7aa83-66d2-4579-9f1b-1cfa08d08f3c",
              "name": "currentCycle.endDate",
              "type": "string",
              "value": "={{ $('Format Date').item.json.End_Current }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "82656e1d-2361-4ce1-b28d-19c7469abc99",
      "name": "本期汇总",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        700,
        940
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "f13eaa1b-bd70-4ee2-a588-e633c5a73c65",
      "name": "格式化上期数据",
      "type": "n8n-nodes-base.set",
      "position": [
        720,
        1100
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "657e8f86-3f7e-44d0-9428-4150ec0b5e59",
              "name": "lastMonthCycle.startDate",
              "type": "string",
              "value": "={{ $('Format Date').item.json.Start_LastMonth }}"
            },
            {
              "id": "e2b7aa83-66d2-4579-9f1b-1cfa08d08f3c",
              "name": "lastMonthCycle.endDate",
              "type": "string",
              "value": "={{ $('Format Date').item.json.End_LastMonth }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "6377a403-c89b-4a21-928a-077ee5106019",
      "name": "上期汇总",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        720,
        1260
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "4fe96658-e302-42a8-8eba-9e059c3583bf",
      "name": "上月转账数据汇总",
      "type": "n8n-nodes-base.merge",
      "position": [
        960,
        1180
      ],
      "parameters": {},
      "typeVersion": 3.1
    },
    {
      "id": "d2c5d065-a199-4551-a3f5-fb21994186a3",
      "name": "本月转账数据汇总",
      "type": "n8n-nodes-base.merge",
      "position": [
        960,
        800
      ],
      "parameters": {},
      "typeVersion": 3.1
    },
    {
      "id": "fa5e3abc-df57-4140-a68e-f328b33b6bd6",
      "name": "更改标题1",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        1180,
        800
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "Chu kỳ hiện tại"
      },
      "typeVersion": 1
    },
    {
      "id": "cabe2138-71bb-4b40-add9-f9ac8f7b7f55",
      "name": "更改标题2",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        1180,
        1180
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "Chu kỳ tháng trước"
      },
      "typeVersion": 1
    },
    {
      "id": "db552cf2-6f91-44ee-aa37-84d3753b983c",
      "name": "收集全部",
      "type": "n8n-nodes-base.merge",
      "position": [
        1520,
        1180
      ],
      "parameters": {
        "numberInputs": 3
      },
      "typeVersion": 3.1
    },
    {
      "id": "dcc23ef7-3e1c-4aa5-aee8-dcfc06ee0097",
      "name": "更改结果标题",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        1740,
        1180
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "data doanh thu"
      },
      "typeVersion": 1
    },
    {
      "id": "e17379be-782f-4c9f-bbd4-b99e8b844613",
      "name": "格式化去年数据",
      "type": "n8n-nodes-base.set",
      "position": [
        720,
        1480
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "657e8f86-3f7e-44d0-9428-4150ec0b5e59",
              "name": "lastYearCycle.startDate",
              "type": "string",
              "value": "={{ $('Format Date').item.json.Start_LastYear }}"
            },
            {
              "id": "e2b7aa83-66d2-4579-9f1b-1cfa08d08f3c",
              "name": "lastYearCycle.endDate",
              "type": "string",
              "value": "={{ $('Format Date').item.json.End_LastYear }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "ef07c8d5-7bb8-41b3-bf52-4d6dd73e1c8c",
      "name": "透视去年",
      "type": "n8n-nodes-base.code",
      "onError": "continueRegularOutput",
      "position": [
        500,
        1680
      ],
      "parameters": {
        "jsCode": "// Get Start_LastYear and End_LastYear from node Format Date\nconst startCurrentRaw = $('Format Date').first().json.Start_LastYear;\nconst endCurrentRaw = $('Format Date').first().json.End_LastYear;\n\n// Debug: Start_LastYear and End_LastYear\nconsole.log('Start Current Raw:', startCurrentRaw);\nconsole.log('End Current Raw:', endCurrentRaw);\n\n// format DD/MM/YYYY or YYYY-MM-DD to Date object\nfunction parseDate(dateStr) {\n  if (!dateStr || typeof dateStr !== 'string') {\n    console.log('Invalid date string:', dateStr);\n    return null;\n  }\n  if (dateStr.includes('/')) {\n    const [day, month, year] = dateStr.split('/').map(Number);\n    return new Date(year, month - 1, day);\n  } else if (dateStr.includes('-')) {\n    return new Date(dateStr);\n  }\n  console.log('Unrecognized date format:', dateStr);\n  return null;\n}\n\n// change Start_LastYear and End_LastYear to Date object\nconst startCurrent = parseDate(startCurrentRaw);\nconst endCurrent = parseDate(endCurrentRaw);\n\n// Debug: print\nconsole.log('Start Current Parsed:', startCurrent);\nconsole.log('End Current Parsed:', endCurrent);\n\n// Validate Start_LastYear or End_LastYear\nif (!startCurrent || !endCurrent) {\n  throw new Error('Invalid Start_LastYear or End_LastYear date format');\n}\n\n// Create object Sum by Type\nconst aggregatedData = {};\n\n// trim\nfunction normalizeString(str) {\n  return str ? str.trim().toLowerCase() : '';\n}\n\n// Filter and summary\nfor (const item of $input.all()) {\n  // Format DD/MM/YYYY or YYYY-MM-DD to Date object\n  const itemDate = parseDate(item.json.Date);\n\n  if (!itemDate) {\n    console.log('Skipping item due to invalid date:', item.json);\n    continue;\n  }\n\n  const amount = Number(item.json['Số tiền']) || 0;\n\n  // Validate Date between Start_LastYear and End_LastYear\n  if (itemDate >= startCurrent && itemDate <= endCurrent) {\n    // Format\n    const phanLoai = normalizeString(item.json['Phân loại']);\n\n    // create key\n    const key = phanLoai;\n\n    // Debug: print\n    console.log('Key:', key);\n\n    // Check\n    if (!aggregatedData[key]) {\n      aggregatedData[key] = {\n        'Phân loại': item.json['Phân loại'], // Keep\n        'Tổng số tiền': 0\n      };\n    }\n\n    // Add to Sum amount\n    aggregatedData[key]['Tổng số tiền'] += amount;\n  }\n}\n\n// Debug: print\nconsole.log('Number of groups:', Object.keys(aggregatedData).length);\nconsole.log('Aggregated Data:', aggregatedData);\n\n// Format object aggregatedData to array\nconst result = Object.values(aggregatedData);\n\nreturn result.map(item => ({ json: item }));"
      },
      "retryOnFail": true,
      "typeVersion": 2
    },
    {
      "id": "c5695aff-f725-4dd1-8f5f-61c37cc3fb06",
      "name": "去年汇总",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        720,
        1680
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "ed643ebd-1524-4af4-b1ba-0ddd705460c8",
      "name": "添加去年数据",
      "type": "n8n-nodes-base.merge",
      "position": [
        960,
        1620
      ],
      "parameters": {},
      "typeVersion": 3.1
    },
    {
      "id": "10b6ecab-05b6-4cb9-ae6f-1e6d242f7a96",
      "name": "更改标题",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        1180,
        1620
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "Chu kỳ năm trước"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "eec79b51-8f52-447f-9890-59c12f6b7eb6",
  "connections": {
    "Collect all": {
      "main": [
        [
          {
            "node": "Change title out come",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Date": {
      "main": [
        [
          {
            "node": "Get revenual from google sheet",
            "type": "main",
            "index": 0
          },
          {
            "node": "Format data current circle",
            "type": "main",
            "index": 0
          },
          {
            "node": "Format data last circle",
            "type": "main",
            "index": 0
          },
          {
            "node": "Format data last year circle",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Change title": {
      "main": [
        [
          {
            "node": "Collect all",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Change title 1": {
      "main": [
        [
          {
            "node": "Collect all",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Change title 2": {
      "main": [
        [
          {
            "node": "Collect all",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Sum last circle": {
      "main": [
        [
          {
            "node": "Sum data last transfer month",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Pivot last circle": {
      "main": [
        [
          {
            "node": "Sum last circle",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Add data last year": {
      "main": [
        [
          {
            "node": "Change title",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sum current circle": {
      "main": [
        [
          {
            "node": "Sum data current transfer month",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "DeepSeek Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Pivot current circle": {
      "main": [
        [
          {
            "node": "Sum current circle",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sum last year circle": {
      "main": [
        [
          {
            "node": "Add data last year",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Pivot last year cirle": {
      "main": [
        [
          {
            "node": "Sum last year circle",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Window Buffer Memory1": {
      "ai_memory": [
        [
          {
            "node": "AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Call n8n Workflow Tool": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Format data last circle": {
      "main": [
        [
          {
            "node": "Sum data last transfer month",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format data current circle": {
      "main": [
        [
          {
            "node": "Sum data current transfer month",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When chat message received": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format data last year circle": {
      "main": [
        [
          {
            "node": "Add data last year",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sum data last transfer month": {
      "main": [
        [
          {
            "node": "Change title 2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get revenual from google sheet": {
      "main": [
        [
          {
            "node": "Pivot current circle",
            "type": "main",
            "index": 0
          },
          {
            "node": "Pivot last circle",
            "type": "main",
            "index": 0
          },
          {
            "node": "Pivot last year cirle",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sum data current transfer month": {
      "main": [
        [
          {
            "node": "Change title 1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When Executed by Another Workflow": {
      "main": [
        [
          {
            "node": "Format Date",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。

这个工作流适合什么场景?

高级 - 文档提取, AI 聊天机器人

需要付费吗?

本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。

工作流信息
难度等级
高级
节点数量26
分类2
节点类型12
难度说明

适合高级用户,包含 16+ 个节点的复杂工作流

外部链接
在 n8n.io 查看

分享此工作流