news 2026/5/1 3:30:31

Python用Flask后端解析Excel图表,Vue3+ECharts前端动态还原(附全套代码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python用Flask后端解析Excel图表,Vue3+ECharts前端动态还原(附全套代码)

以下是完整的Flask + Vue 3 前端模板方案,实现上传 Excel 文件(不再用链接),后端解析chart1.xml,返回结构化数据,前端用 ECharts 渲染图表。

项目结构

project/ ├── app.py ├── templates/ │ └── index.html

1. 后端:app.py

importxml.etree.ElementTreeasETimportiofromzipfileimportZipFile,BadZipFilefromflaskimportFlask,render_template,request,jsonifyfromflask_corsimportCORS# 可选,如果有跨域需求app=Flask(__name__)CORS(app)# 允许跨域(同域其实不需要,但留着保险)defparse_chart_from_bytes(file_data):res={}result={}try:archive=ZipFile(io.BytesIO(file_data))chart_data=archive.read('xl/charts/chart1.xml')res['code']=200res['msg']="获取图表信息成功"tree=ET.parse(io.BytesIO(chart_data))root=tree.getroot()ns={'c':'http://schemas.openxmlformats.org/drawingml/2006/chart','a':'http://schemas.openxmlformats.org/drawingml/2006/main'}# 图表类型type_mapping=[('pieChart','饼图','pie'),('lineChart','折线图','line'),('barChart','柱形图','bar'),('areaChart','面积图','line'),('scatterChart','散点图','scatter'),('radarChart','雷达图','radar'),]chart_type_cn='其它'echarts_type='line'is_area=Falsefortag,cn,enintype_mapping:ifroot.find(f'.//c:{tag}',ns)isnotNone:chart_type_cn=cn echarts_type=enifcn=='面积图':is_area=Truebreakresult['chart_type_cn']=chart_type_cn result['echarts_type']=echarts_type result['is_area']=is_area# 标题title_text=""title_elem=root.find('.//c:title/c:tx/c:rich',ns)iftitle_elemisnotNone:fortintitle_elem.iterfind('.//a:t',ns):ift.text:title_text+=t.text result['title']=title_text.strip()or"无标题"# 系列数据series_list=[]ser_elements=root.findall('.//c:ser',ns)foridx,serinenumerate(ser_elements):# 系列名称name_elem=ser.find('c:tx/c:v',ns)name=name_elem.textifname_elemisnotNoneelsef"系列{idx+1}"# 类别(X轴)cat_vs=ser.findall('c:cat//c:pt/c:v',ns)categories=[v.textforvincat_vsifv.textisnotNone]# 数值(Y轴)val_vs=ser.findall('c:val//c:pt/c:v',ns)values=[]forvinval_vs:ifv.text:try:values.append(float(v.text))exceptValueError:values.append(v.text)series_list.append({"name":name,"categories":categories,"data":values})# 共享类别轴(如果每个系列都没有独立类别)ifseries_listandall(len(s['categories'])==0forsinseries_list):shared_vs=root.findall('.//c:cat//c:pt/c:v',ns)shared_cat=[v.textforvinshared_vsifv.textisnotNone]ifshared_cat:forsinseries_list:s['categories']=shared_cat# 饼图特殊处理ifchart_type_cn=="饼图"andseries_list:forsinseries_list:pie_data=[]cats=s['categories']or[f"项{i+1}"foriinrange(len(s['data']))]fori,valinenumerate(s['data']):name=cats[i]ifi<len(cats)elsef"项{i+1}"value=valifisinstance(val,(int,float))else0pie_data.append({"name":name,"value":value})s['data']=pie_data# 最终类别轴(非饼图)ifchart_type_cn!="饼图"andseries_listandseries_list[0]['categories']:result['categories']=series_list[0]['categories']else:result['categories']=[]# 系列(只保留 name 和 data)result['series']=[{"name":s["name"],"data":s["data"]}forsinseries_list]res['data']=resultexceptBadZipFile:res['code']=404res['msg']="无效的Excel文件"exceptKeyError:res['code']=404res['msg']="未找到图表信息(无chart1.xml)"exceptExceptionase:res['code']=500res['msg']=f"解析失败:{str(e)}"returnres@app.route('/')defindex():returnrender_template('index.html')@app.route('/api/upload_chart',methods=['POST'])defupload_chart():if'file'notinrequest.files:returnjsonify({"code":400,"msg":"没有上传文件"})file=request.files['file']iffile.filename==''ornotfile.filename.lower().endswith('.xlsx'):returnjsonify({"code":400,"msg":"请上传 .xlsx 文件"})file_data=file.read()returnjsonify(parse_chart_from_bytes(file_data))if__name__=='__main__':app.run(host='127.0.0.1',port=5000,debug=True)

2. 前端模板:templates/index.html

<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><title>上传 Excel → ECharts 渲染</title><scriptsrc="https://cdn.jsdelivr.net/npm/vue@3.4.21/dist/vue.global.prod.js"></script><scriptsrc="https://cdn.jsdelivr.net/npm/echarts@5.5.0/dist/echarts.min.js"></script><style>body{font-family:Arial,sans-serif;padding:20px;background:#f5f5f5;}.container{max-width:800px;margin:auto;background:white;padding:30px;border-radius:8px;box-shadow:0 2px 10pxrgba(0,0,0,0.1);}input[type="file"]{padding:10px;margin-bottom:15px;}button{padding:12px 24px;font-size:16px;background:#409eff;color:white;border:none;border-radius:4px;cursor:pointer;}button:hover{background:#66b1ff;}button:disabled{background:#a0cfff;cursor:not-allowed;}#chart{width:100%;height:600px;margin-top:30px;}.msg{margin:15px 0;font-weight:bold;color:#e6a23c;}</style></head><body><divid="app"class="container"><h2>上传 Excel 文件 → ECharts 渲染图表</h2><inputtype="file"accept=".xlsx"@change="onFileChange"/><button@click="uploadAndRender":disabled="!selectedFile">上传并渲染图表</button><divclass="msg">{{ message }}</div><divref="chartRef"id="chart"></div></div><script>const{createApp,ref,onMounted,nextTick}=Vue;createApp({setup(){constselectedFile=ref(null);constmessage=ref('请选择一个包含图表的 .xlsx 文件');constchartRef=ref(null);letmyChart=null;onMounted(()=>{myChart=echarts.init(chartRef.value);});constonFileChange=(e)=>{constfile=e.target.files[0];if(file&&file.name.endsWith('.xlsx')){selectedFile.value=file;message.value=`已选择文件:${file.name}`;}else{selectedFile.value=null;message.value='请上传 .xlsx 文件';}};constuploadAndRender=async()=>{if(!selectedFile.value)return;message.value='正在上传并解析...';constformData=newFormData();formData.append('file',selectedFile.value);try{constresponse=awaitfetch('/api/upload_chart',{method:'POST',body:formData});constjson=awaitresponse.json();if(json.code!==200){message.value=`错误:${json.msg}`;return;}constdata=json.data;constoption={title:{text:data.title,left:'center',textStyle:{fontSize:18}},tooltip:{trigger:data.echarts_type==='pie'?'item':'axis'},legend:{data:data.series.map(s=>s.name),top:30}};if(data.echarts_type==='pie'){option.series=data.series.map(s=>({type:'pie',name:s.name,radius:'55%',center:['50%','60%'],data:s.data,emphasis:{itemStyle:{shadowBlur:10,shadowOffsetX:0,shadowColor:'rgba(0, 0, 0, 0.5)'}}}));}elseif(data.echarts_type==='radar'){constmaxVal=Math.max(...data.series.flatMap(s=>s.data.filter(v=>typeofv==='number')),100);option.radar={indicator:data.categories.map(name=>({name,max:maxVal*1.2}))};option.series=[{type:'radar',data:data.series.map(s=>({name:s.name,value:s.data}))}];}else{option.xAxis={type:'category',data:data.categories};option.yAxis={type:'value'};option.series=data.series.map(s=>({type:data.echarts_type,name:s.name,data:s.data,areaStyle:data.is_area?{opacity:0.3}:undefined,smooth:data.echarts_type==='line'?true:false}));}awaitnextTick();myChart.setOption(option,true);message.value=`渲染成功!图表类型:${data.chart_type_cn}${data.series.length}个系列)`;}catch(err){message.value='上传或解析失败:'+err.message;console.error(err);}};return{selectedFile,message,chartRef,onFileChange,uploadAndRender};}}).mount('#app');</script></body></html>

使用方式

  1. 安装依赖:
    pipinstallflask flask-cors
  2. 把上面的文件按结构放好。
  3. 运行:
    python app.py
  4. 浏览器打开http://127.0.0.1:5000
  5. 选择一个包含图表(chart1)的.xlsx文件 → 点击“上传并渲染图表”

功能特点

  • 支持上传本地 Excel 文件解析(安全,只读内存)。
  • 支持单/多系列图表。
  • 饼图、折线、柱形、面积、散点、雷达图基本还原。
  • 前端美化了些样式和交互。

相关文章

Python 使用 openpyxl 从 URL 读取 Excel 并获取 Sheet 及单元格样式信息
Python 解析 Excel 图表(Chart)信息实战:从 xlsx 中提取标题、字体和数据

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/28 1:45:33

Oracle 迁移 KingbaseES 避坑指南:工具选型、参数配置与性能调优

Oracle至KingbaseES迁移最佳实践 Oracle迁移至KingbaseES前需先明确目标数据库对Oracle数据库的兼容度&#xff0c;得出结论后再进行迁移。本小节从Oracle兼容特性概览和Oracle数据库迁移实战两方面来介绍整体迁移操作步骤。 Oracle兼容特性概览 通常&#xff0c;异构数据库…

作者头像 李华
网站建设 2026/4/29 13:05:51

垃圾处理器真实体验测评:5款热门机型使用体验全解析

垃圾处理器真实体验测评&#xff1a;5款热门机型使用体验全解析作为一个家电测评作者&#xff0c;我测试过超过20款垃圾处理器&#xff0c;而我自己的家庭使用垃圾处理器也已经超过5年。今天&#xff0c;我不谈枯燥的参数&#xff0c;只想和你分享真实的使用体验&#xff1a;垃…

作者头像 李华
网站建设 2026/4/18 12:57:02

ros2 run 配置参数

在ROS2中&#xff0c;通过ros2 run配置节点参数主要涉及命令行参数传递、参数文件和Launch文件集成三种方式。以下以ROS2 Jazzy为例详细说明&#xff1a; 1️⃣ 命令行直接传递参数 ros2 run <package_name> <executable_name> \--ros-args \-p <parameter_name…

作者头像 李华
网站建设 2026/4/29 20:32:07

SSM299的球鞋商品竞拍卖网站vue

目录SSM299球鞋竞拍卖网站Vue摘要开发技术源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;SSM299球鞋竞拍卖网站Vue摘要 该平台基于Vue.js前端框架与SSM&#xff08;SpringSpringMVCMyBatis&#xff09;后端架构开发&#xff0c;专注于…

作者头像 李华
网站建设 2026/4/27 0:54:36

光束驱动AI计算实现超级计算机级性能

张量运算是一种支撑现代技术特别是人工智能的高级数学形式。这些运算远超人们日常遇到的简单计算。可以将其想象为同时在多个维度操控魔方&#xff0c;通过旋转、切片或重新排列各个层面。人类和传统计算机必须将这些任务分解为序列&#xff0c;但光可以同时执行所有操作。如今…

作者头像 李华