- 前言
有朋友讓幫忙做個導出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的格式要保持一致,否則會導致導出文件的單元格內容錯誤。