Dify实战:AI自动生成Excel并打包ZIP的落地指南 简介这是一份基于 Dify AI 平台创建 Excel 表的示例项目面向正在学习低代码 AI 应用开发的工程师演示如何借助 Dify 工具编排与 Python Flask 后端协作快速生成和交付表格数据。资源包共 3 个文件包括 Dify 工作流编排配置yml、Flask 服务脚本py和一份示例生成的 Excel 表格xlsx整体仅 10KB结构精简便于导入分析和二次改造。借助该示例读者可以完整看到 Dify 应用与 Web 服务之间的串联方式理解 Flask 接口如何接收 Dify 请求、调用处理逻辑并写出 xlsx 文件同时了解配置文件中的节点编排思路包括各节点之间如何传递数据、如何设置输入输出参数为后续扩展智能数据录入、自动化分析等功能打下基础。目前已有 260 人学习下载适合具备基础 Python 知识、希望快速上手 Dify 与 Excel 场景的开发者。资源体积虽小但提供了可运行的完整骨架可作为模板直接嵌入实际业务系统节省从零搭建的时间。 如果最近你在做AI应用大概率已经听说过Dify这个开源大模型应用开发平台基本把工作流编排 RAG Agent 应用发布串成了一条流水线。上个月我在Dify社区版里折腾了一个小项目用途很简单让AI根据一段自然语言描述自动生成一份Excel表并且把多张表打包成zip压缩包给用户下载。做成之后我又补了报表模板填充、批量导出这些能力整个应用现在跑得很稳。这篇就把它从头到尾拆一遍包括我踩过的坑和改过的方案给正好想用Dify做表格类生成应用的人一个可以直接参考的落地路径。1. 项目构想为什么要在Dify里做Excel表.zip1.1 核心需求从纯文本到结构化Excel文件的自动化最初的需求特别朴素来自一个经常要交付表格的同事他每次都要根据一堆零散数据手动整理Excel列名、格式、筛选条件都得自己设计一天能在这上面耗掉两三个小时。他问我能不能做一个网页工具输入一段话比如生成一张2023年各季度销售统计表包含地区、销售额、同比增长率对面直接吐回来一个Excel文件。这个需求拆开看其实有三层第一层是让大模型理解用户意图把自然语言转成Excel的表头结构和行数据第二层是把这些结构化数据真正写进.xlsx文件第三层是当用户要多张表打包给我时把多个Excel文件压缩成zip再传回来。前两层是很多AI生成Excel演示都做过的第三层才是让这个应用真正能落地到生产环境的关键——批量交付、带附件下载、一键存到本地的体验和把表格内容显示在对话框里完全不是一回事。1.2 方案选型为什么不用传统后端代码而是选Dify其实用传统后端做这个事更直接前端传一段文本后端调大模型接口拿到JSON再用Python的openpyxl库写Excel走一个download接口返回文件。代码量不大实现也不难。但我之所以最终选Dify核心原因是后续的迭代需求非常多且不确定用户可能突然要加一个把现有Excel某列数据提取统计的工作流可能想接知识库让模型按固定模板生成表格也可能想让应用支持多人同时用还要查看历史记录。如果用传统代码每加一个需求都要改接口、改数据库、重新部署。Dify的工作流把这些常见能力都预置了LLM节点、代码节点、条件分支、HTTP请求节点、文件变量、对话历史甚至可以直接发不到微信/飞书/网站小部件。我只需要关注数据怎么流转不需要维护服务端基础设施。另外Dify社区版可以本地部署数据和技术栈都在自己手里对于内部工具类应用来说安全感高很多。2. Dify应用形态与Excel生成的技术路径2.1 三种应用形态聊天助手、工作流、Agent怎么选Dify里创建应用时有三种主要形态聊天助手Chatflow、工作流Workflow、Agent。做Excel生成这种输入一段需求输出一个文件的场景我在前两版分别试了Chatflow和Workflow最终的结论是如果你希望用户在对话过程中追加修改要求比如把第一张表的列名改成英文那就用Chatflow如果用户是一次性提完整需求、直接拿结果用Workflow更干净执行链路更短、调试更直观。我这个应用最初用的是Chatflow后来切成了Workflow原因是同事们的使用习惯基本都是提一句完整需求—下载结果很少在对话里来回修改Workflow版少了一个对话层响应更快也更好定位问题。而Agent形态暂时没必要用因为这里不需要自主调用多个工具把调LLM生成数据和用代码写Excel两个步骤用工作流编排就足够了。2.2 Excel生成的核心机制代码节点与Python操作Dify工作流里有一个非常实用的节点——代码节点支持Python和Node.js。生成Excel这件事本质上是结构化数据 → .xlsx文件技术上最稳的做法是在代码节点里用Python的openpyxl库来生成文件而不是让大模型直接生成一个Excel文件的二进制内容。大模型做文本和JSON很擅长但让它在一次输出里构造完整的xlsx二进制基本不可能所以路径必须是LLM节点把用户的自然语言需求转成表头headers和行数据rows输出成结构化JSON代码节点接收这个JSON用Python逐行写入工作簿保存为.xlsx如果用户要求多个文件就循环生成多个xlsx再用Python的zipfile模块或shutil.make_archive把它们压缩成一个.zip文件工作流将文件路径传给直接回复节点Dify负责把文件作为附件返回给前端用户下载。这里有一个关键点代码节点里处理文件时最好把生成的文件写到临时目录比如/tmpDify运行时会读取这个路径并处理下载。在不同版本的Dify里代码节点对文件类型变量的支持有差异有些版本要用DifyFile包装有些版本直接返回路径字符串就行我用到的是当前社区版1.x代码里用的写法后面会完整给出。2.3 为什么偏要加一层zip多文件批量交付的逻辑最初版本我只做了单个Excel文件输出但一上线就发现几个痛点一是用户经常一次要季度表的1到12月共12张表逐个点击下载太麻烦二是很多用户的下一步动作是直接把这个月的表格包转发给领导或归档一个zip文件显然更接近他们的操作习惯三是Dify直接输出多个文件时前端展示体验并不算好浏览器通常会把多个附件挤在一个列表里文件一多容易漏。所以我在工作流里加了一个是否打包的分支单文件直接传多文件自动打包成zip再传。实测下来这个改动让应用的接受度高了很多。打包用Python标准库的zipfile就够了代码只有几行import zipfile import os def make_zip(files, zip_name): with zipfile.ZipFile(zip_name, w, zipfile.ZIP_DEFLATED) as zf: for fpath in files: zf.write(fpath, arcnameos.path.basename(fpath)) return zip_name注意里面arcname参数的设置它可以控制压缩包内文件的显示名避免出现一串乱码路径。3. 从零搭建Excel表.zip应用的完整实现3.1 准备Dify环境和工作流骨架我这边用的是Docker Compose方式部署的Dify社区版。如果你是第一次部署官方文档有详细步骤这里简单提一下我验证过的流程先装好Docker和Docker Compose然后clone dify仓库在docker目录下执行docker compose up -d等容器都起来后就可以通过本机IP:80访问控制台了。迁移和升级过程中遇到过几次文件或镜像版本对不上的问题目前建议是直接参考官方latest版本的分支来部署不要混用不同版本镜像。创建应用时我选了工作流类型初始画布上默认有开始和直接回复两个节点。我把整个链条设计成五个节点开始节点接收用户输入的表格需求描述string、文件前缀名string可选、是否打包zipbooleanLLM节点把需求描述解析为结构化JSON包含sheet列表每个sheet有sheet_name、headers、rows三部分代码节点1根据JSON生成Excel文件如果有多个sheet/多个文件就生成多个xlsx条件分支节点判断是否为多文件或用户勾选打包代码节点2或直接回复节点把文件列表打包成zip然后交给直接回复节点输出。这个骨架的妙处在于后面想加模板、RAG或历史记录都可以在不改链路主体的情况下做扩展。3.2 输入设计让LLM稳定输出可解析的JSONLLM节点是整个流程里最不稳定的环节。如果直接让模型生成一个Excel文件它可能给你一段Markdown表格文本也可能给你JSON很容易把下游代码节点弄崩溃。我最后采用的提示词策略是让LLM只输出一个严格的JSON对象并且用固定的字段名。我的LLM节点提示词大概长这样你是表格数据专家。用户会给出表格需求请你 1. 判断需要生成哪些工作表sheet 2. 为每个sheet设计合适的英文列名headers 3. 根据需求生成合理的示例数据rows至少5行 4. 只输出JSON不要输出任何其他文字。 输出格式 { sheets: [ { sheet_name: 销售数据, headers: [region, sales, growth_rate], rows: [ [华东, 120000, 0.15], [华北, 98000, 0.08] ] } ] }为什么列名用英文因为中文列名在代码里做变量名或索引时容易出问题而最终写入Excel时可以再设置表头为中文显示名或者保留英文表头并根据用户需求来决定。我这里实际保留的是用户最初需求的语言只是提示词要求用英文变量模型输出后再映射为中文表头。这里还有一个坑模型偶尔会在JSON前后加上json的Markdown代码块标记代码节点里用json.loads直接解析会失败。我在代码节点里做了一个容错处理先把文本里的Markdown代码块去掉再尝试解析代码在后面统一给。3.3 代码节点实现用Python生成Excel并打包zipDify工作流的代码节点支持定义输入变量和输出变量。我这个应用里代码节点的输入变量是data字符串类型内容为上一步LLM节点输出的JSON文本和zip_enabled布尔类型输出变量是file_paths文件路径字符串列表和zip_path字符串。代码节点里写Python的核心逻辑import json import os import re import zipfile from openpyxl import Workbook def remove_code_markdown(text): text text.strip() text re.sub(r^(?:json)?\s*, , text) text re.sub(r\s*$, , text) return text def main(data: str, zip_enabled: bool) - dict: data remove_code_markdown(data) parsed json.loads(data) sheets parsed.get(sheets, []) tmp_dir /tmp/excel_output os.makedirs(tmp_dir, exist_okTrue) created_files [] for idx, sheet in enumerate(sheets): wb Workbook() ws wb.active ws.title str(sheet.get(sheet_name, fSheet{idx1}))[:31] # Excel sheet名最长31字符 headers sheet.get(headers, []) if headers: ws.append(headers) for row in sheet.get(rows, []): ws.append(row) file_path os.path.join(tmp_dir, f{sheet.get(sheet_name, sheet)}_{idx1}.xlsx) wb.save(file_path) created_files.append(file_path) zip_path if zip_enabled and len(created_files) 1: zip_path os.path.join(tmp_dir, output.zip) with zipfile.ZipFile(zip_path, w, zipfile.ZIP_DEFLATED) as zf: for fp in created_files: zf.write(fp, arcnameos.path.basename(fp)) return { file_paths: created_files, zip_path: zip_path }实际运行时要注意几个细节Excel工作表名不能超过31个字符且不能包含[]:*?/\这些字符否则openpyxl保存时会报错所以我在设置ws.title时做了截断和清洗文件名我也做了处理避免中文文件名在某些环境里乱码。另外如果用户只勾选了打包但只有一个文件zip就不必生成了代码里用and len(created_files) 1把这个情况拦掉了避免产出一个只管装了一个文件的压缩包这种反人类设计。3.4 输出处理怎么让用户真正下载到文件Dify工作流的直接回复节点支持输出文件类型变量。我在代码节点之后加了一个条件分支如果zip_path非空就直接把zip文件传给直接回复节点否则把file_paths列表传下去再由一个简单的循环或直接回复展示多个文件。在Dify 1.x版本里代码节点的文件输出需要包装成Dify的文件对象不同版本写法略有不同。我用的版本里是这样处理的from dify_plugin import DifyFile file_obj DifyFile( pathzip_path, mimetypeapplication/zip ) return { file: file_obj }单个Excel文件同理只是mimetype要改成application/vnd.openxmlformats-officedocument.spreadsheetml.sheet。如果你用的Dify版本还没有dify_plugin这个包可以退回到路径字符串方案代码节点返回文件路径直接回复节点会自动识别并让用户下载。这个和版本绑定比较深建议做的时候先在Dify控制台里跑一次看节点的输出到底是文件对象还是普通字符串。我在测试时就踩过一次按老教程的写法输出文件对象结果新版控制台提示类型不匹配后来看了官方更新日志才发现代码节点的文件接口升级了改一下包装方式就好了。版本升级带来的API变动是Dify这类快速演进项目里最常见的坑之一我的建议是写代码之前先确认当前版本的代码节点支持哪些变量类型不要直接抄旧帖。4. 问题排查Excel生成场景的高频坑4.1 环境问题openpyxl在Dify代码沙箱里能不能用很多人在Dify工作流里用Python写Excel第一个坑就是代码节点报ModuleNotFoundError: No module named openpyxl。不同Dify版本预装的Python库不一样老版本镜像可能不带openpyxl而代码沙箱的依赖安装又不像普通服务器那样随便pip install。我这边测试的社区版1.x默认有openpyxl但这个只能算运气好。保险起见我在代码里加了一层动态检测和降级方案如果openpyxl不可用就尝试用csv模块生成CSV文件并把扩展名改成.xlsx虽然不推荐或者直接在应用里的系统提示/环境配置里注册自定义依赖。如果你的代码节点支持配置依赖优先在节点配置里把openpyxl声明上这样比在代码里try/except更专业也更稳定。4.2 LLM输出不稳定JSON格式和字段缺失的兜底LLM节点输出的JSON偶尔会缺字段——比如用户需求比较模糊时模型可能不生成rows只生成headers或者把sheet_name写成中文以外的奇怪字符。我在代码节点里做了一个比较健壮的解析器每一层都做默认值兜底。headers sheet.get(headers) or [] rows sheet.get(rows) or [] if not headers: headers [col1, col2, col3]如果rows为空我还会根据headers生成几个占位行避免打开Excel看到只有表头没有数据的空表。另外我强烈建议在LLM节点的模型参数里把temperature调到0或者0.1减少随机性并开启JSON模式Dify里有些模型支持response format为json_object当模型支持时一定要开这样能明显减少解析失败的概率。4.3 zip中文文件名乱码与路径问题打包zip时最常见的幺蛾子是中文文件名乱码。Python的zipfile模块在Windows上解压时如果文件名不是UTF-8编码就会出现乱码。为了让压缩包在现代系统里正常显示中文文件名我在写zip时显式用UTF-8去处理文件名zinfo zipfile.ZipInfo(filename, date_time...) zinfo.flag_bits | 0x800 # 启用UTF-8标志位 zf.writestr(zinfo, open(fp, rb).read())代码稍微啰嗦一点但能保证用户下载后在Windows和macOS上都正常显示。还有一个细节写文件路径的时候要用绝对路径而且尽量不要让路径里出现中文目录否则在某些Linux容器和Windows之间做文件流转时可能出现隐藏的编解码问题。4.4 大文件与大表格的性能边界我测试过一次性生成十张表、每张表几千行的数据代码节点执行时间大约在20秒左右。这个体验虽然能接受但不太适合做高频并发。Dify代码节点的执行是有超时限制的默认不高的场景下如果数据量过大可能触发超时。我的建议是数据量大的时候不要让LLM直接生成全部行数据而是让LLM只生成表格结构和规则再让代码节点根据规则用程序批量造数。比如用户要1000行随机销售数据LLM只需要输出列名和数据类型规则代码里用random生成1000行。这样既快又稳还能避免大模型在长输出时丢三落四导致JSON截断。5. 扩展思考这个架构还能做什么5.1 模板填充从生成新表到填已有模板生成新Excel只是第一步。在实际使用中很多用户手里已经有一套固定格式的Excel模板比如日报模板、报销模板AI要做的不是重新设计表结构而是把数据填到指定单元格。这个功能我在Dify里也验证过先在开始节点上传一个模板xlsx文件Dify支持文件输入再用Python的openpyxl读取模板定位到目标sheet和单元格把LLM生成的数据写入对应区域最后保存输出。核心代码大概是from openpyxl import load_workbook wb load_workbook(template_path) ws wb[日报] ws[A1] date_str ws[B2] sales_amount wb.save(output_path)这种方式比从头生成整个sheet稳定得多尤其适合对格式有强制要求的企业场景。只要模板不变哪怕换个模型都无所谓因为最终数据写入完全由代码节点保证。5.2 与数据导入导出闭环Excel作为系统间的桥梁我们内部不少业务系统的导出功能在格式上并不统一有了自然语言生成Excel包这个能力后可以把它和RAG检索、数据库查询串起来先让AI从知识库或数据库里拿到某段数据的JSON再自动填入模板最后打包输出。这就变成了一个完整的数据交付闭环。比如输入把本月各区域的设备故障数量整理成一张统计表并给出环比工作流可以先把查询需求路由到数据库节点拿到记录后用相同的Excel生成逻辑输出文件。5.3 让Excel变成下游处理的入口反过来Dify也能处理用户上传Excel文件后AI分析的需求。我开始节点支持文件上传类型直接允许用户上传xlsx然后用代码节点读取数据再用LLM节点做分析和总结。把生成Excel和读取Excel两个方向的能力都做出来后这个应用就从一个文件生成器升格成了一个表格数据工作台覆盖创建—处理—导出的整个流程。6. 一点实操心得做这个应用前前后后大概花了两周大部分时间都花在调LLM输出的稳定性和适配Dify版本细节上真正写Excel逻辑的时间反而很少。我的一个体会是Dify这类平台的价值不在于让你少写代码而在于把提示词工程、模型切换、文件流转、应用部署这些原本要拼在一套系统里的环节打通了。你依然需要懂Python、懂JSON、懂文件I/O但这些能力可以被聚焦到单个代码节点里而不是散落在一个大后端项目里。如果这个场景你也打算做我建议先跑通最小链路LLM转JSON → 代码生成单文件 → 直接回复再逐步加多文件、zip打包、模板填充这些高级功能。不要一上来就奔着完整版去Dify节点一多调试心态容易崩。先用最简版本让用户用起来拿到真实反馈后再迭代这个节奏在AI应用开发里比什么都重要。本文还有配套的精品资源点击获取

相关新闻

最新新闻

CodeGraph 装完即战力:一条命令建好本地代码知识图谱,AI Agent 五分钟接入全链路

CodeGraph 装完即战力:一条命令建好本地代码知识图谱,AI Agent 五分钟接入全链路

CodeGraph 装完即战力:一条命令建好本地代码知识图谱,AI Agent 五分钟接入全链路 【免费下载链接】codegraph Pre-indexed code knowledge graph, auto syncs on code changes, for Claude Code, Codex, Gemini, Cursor, OpenCode, AntiGravity, Kiro, C…

2026/9/8 18:55:35
大模型算法工程师实战指南:从原理到微调部署全流程解析

大模型算法工程师实战指南:从原理到微调部署全流程解析

1. 先说清楚:这门特训到底在练什么 市面上教你"入门AI"的课程多如牛毛,但真正能让你完成身份转换、从普通开发者/算法工程师转型为大语言模型算法工程师的体系化训练,其实少得可怜。这个特训的定位非常清晰:它不是给你念…

2026/9/8 18:55:35
电销外包录音质检收费标准与合规选型指南

电销外包录音质检收费标准与合规选型指南

数据来源与采信声明数据截止日期:本文数据截止日期为2026年9月。利益冲突声明:本文由第三方自媒体评测团队撰写,团队成员具备3年以上企业服务行业研究经验。本团队声明未接受优先呼、沃丰科技、智齿科技、容联云任何品牌方的付费委托或赞助&a…

2026/9/8 18:55:35
Cesium中基于turf.js的等值线图生成与渲染实践

Cesium中基于turf.js的等值线图生成与渲染实践

简介:基于Cesium与krigingjs实现等值线图的可运行示例,面向GIS开发、前端可视化及地理数据分析人员,帮助解决在三维地球场景中展示等值区域与热力分布的需求。资源将普通克里格插值算法封装为kriging.js,并附上test.js测试脚本&am…

2026/9/8 18:55:35
从外部 OData 到 SAP Gateway,SEGW 重定义服务的集成链路全解析

从外部 OData 到 SAP Gateway,SEGW 重定义服务的集成链路全解析

很多 SAP Gateway 项目真正麻烦的地方,并不是我们自己从零编写一个 OData 服务,而是企业里已经存在一套外部 OData API,SAP 系统还需要把它纳入自己的 Gateway 服务体系。 外面的系统已经能提供 $metadata,也已经有 Entity、EntitySet、Association 以及各种数据访问能力。…

2026/9/8 18:55:35
AI数据采集实战:质量与分布决定模型上限,避开数据陷阱

AI数据采集实战:质量与分布决定模型上限,避开数据陷阱

做模型做到后面,你会发现一个扎心的现实:最值钱的东西不是模型结构,不是调参技巧,而是数据。前阵子我帮朋友复盘一个视觉检测项目。团队花了三个月从各种渠道攒了60万张图片,存储用好几个TB,训练一轮要跑好…

2026/9/8 18:50:35