- 前言
有朋友让帮忙做个导出Excel的程序,正好看了github上很火的一个项目Python - 100天从新手到大师的相关内容就做了个简单的程序。
废话不多,直接开干。
- 需求
需求很简单,就是把一个Excel中的内容每行内容导出一个固定模版的Excel表格,源文件单元格对应填入模板相应单元格中。
- 程序设计流程图
- 用的python库
下面说下用到的python库
tkinter:提供程序界面操作
openpyxl:提供对Excel的操作
string:自定义文字模版
re:正则表达式
os:文件操作
- 源代码

import tkinter import tkinter.messagebox import tkinter.filedialog from openpyxl import load_workbook from openpyxl import Workbook import os from string import Template import re # define main function def main(): # 创建导出目录 if not os.path.exists('生成'): os.mkdir('生成') source_path = "" def get_source_path(): nonlocal source_path source_path = tkinter.filedialog.askopenfilename(title='选择文件', filetypes=[('表格', '.xlsx')]) label.config(text='文件路径:' + source_path) # create main top window top = tkinter.Tk() # set window-size top.geometry('640x360') # set window-title top.title("excel模版转换") # create text-obj label = tkinter.Label(top, text="文件路径:", font='Arial-32', fg='red') label.pack(side='top') # create panel container for btn panel = tkinter.Frame(top) # create btn-obj set into certain panel btn1 = tkinter.Button(panel, text='打开数据源文件', command=get_source_path) btn1.pack(side='left') btn2 = tkinter.Button(panel, text='生成', command=lambda: read_cell_maps(source_path)) btn2.pack(side='right') panel.pack(side='bottom') # start main loop tkinter.mainloop() # read excel-map text def read_cell_maps(source_path): # read source-xls if os.path.isfile(source_path): source_workbook = load_workbook(source_path) else: tkinter.messagebox.showinfo('温馨提示', '源文件不存在') return # read target-model-xls if os.path.isfile('./模版.xlsx'): model_workbook = load_workbook('./模版.xlsx') else: tkinter.messagebox.showinfo('温馨提示', '模版文件不存在') return # read maps data set map-relation fo= open('./maps.txt','r') rowmap = [x for x in fo.readlines()] fo.close() for sheet in source_workbook.worksheets: rowcount = sheet.max_row print(sheet.title+':'+ str(rowcount)) for rownum in range(int(rowmap[0]),rowcount+1): for map in rowmap[1].split(','): # 模版语句 tempstring=map.split('=')[1] # 正则匹配 pattern=re.compile('\\{(.*?)}') res=pattern.findall(tempstring) temp = Template(tempstring) # 设定模版内容 mapdic={x:sheet[x+str(rownum)].value for x in res} # 此处将模版单元格数据替换成数据源单元格数据 model_workbook.active[map.split('=')[0]].value=temp.safe_substitute(mapdic) # 另存为 tempstring = rowmap[2] pattern = re.compile('\\{(.*?)}') res = pattern.findall(tempstring) temp = Template(tempstring) mapdic = {x: sheet[x + str(rownum)].value for x in res} temp.safe_substitute(mapdic) print(rowmap[2]) model_workbook.save('./生成/{}.xlsx'.format(temp.safe_substitute(mapdic))) tkinter.messagebox.showinfo('温馨提示', '转换完成!') if __name__ == '__main__': main()
源代码打包文件:打包文件
- 思考
1.程序很简单,没有将excel的操作单独做个操作类
2.学会了使用string template,方便套用各种字符串模版
3.可以优化的点:可以使用多线程分别处理不同的sheet,甚至多线程去处理每个sheet中的数据,这将大大提高运行速度
ps:源文件中sheet的格式要保持一致,否则会导致导出文件的单元格内容错误。