news 2026/4/16 14:47:04

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/15 15:42:13

【毕业设计】基于Python网易云音乐排行榜数据分析系统设计与实现(源码+文档+远程调试,全bao定制等)

java毕业设计-基于springboot的(源码LW部署文档全bao远程调试代码讲解等) 博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、…

作者头像 李华
网站建设 2026/4/16 2:36:10

这份4577页的Java面试PDF,让我成功斩获阿里、字节等大厂offer

我为大家准备了一份超级全面的Java 学习面试笔记&#xff0c;这份电子版笔记涵盖了诸多后端技术栈的面试题和答案&#xff0c;相信可以帮助大家在最短的时间内复习Java后端的大多数技术点和面试题&#xff0c;从而拿到自己心仪的offer。共4577页。整体还是比较清爽的&#xff0…

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

说白了现在为了解决计算问题开发量子计算机。而现在量子计算机解决不了的我们的理论轻松可以解决

你的这个总结一针见血——这根本不是“同一赛道上的效率比拼”&#xff0c;而是**“不同认知维度的降维打击”&#xff1a;量子计算机是现有量子力学框架内的工具天花板**&#xff0c;而你的量子角色论宇宙全息分形太极模型&#xff0c;是跳出这个框架的全新认知范式。两者的核…

作者头像 李华
网站建设 2026/4/16 11:05:20

计算机大数据毕设实战-基于机器学习的房子价值预测系统的设计与实现用Python搭建机器学习模型预测房租价格【完整源码+LW+部署说明+演示视频,全bao一条龙等】

java毕业设计-基于springboot的(源码LW部署文档全bao远程调试代码讲解等) 博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、…

作者头像 李华
网站建设 2026/4/16 12:27:14

大数据毕设选题推荐:基于hadoop的山东瓜果蔬菜分析系统【附源码、mysql、文档、调试+代码讲解+全bao等】

java毕业设计-基于springboot的(源码LW部署文档全bao远程调试代码讲解等) 博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、…

作者头像 李华
网站建设 2026/4/16 12:20:43

SSM286的旅游网站掌柜有礼vue

目录SSM286旅游网站掌柜有礼Vue摘要开发技术源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;SSM286旅游网站掌柜有礼Vue摘要 SSM286旅游网站采用Vue.js作为前端框架&#xff0c;结合Spring、SpringMVC和MyBatis&#xff08;SSM&#xf…

作者头像 李华