用Python手撕一個批量填充數(shù)據(jù)到excel表格的工具,解放雙手!

Hi~大家好!
今天這篇文章是根據(jù)批量填充數(shù)據(jù)的進階版。基礎(chǔ)版本就一段很簡單的代碼。雖然簡單,但如果這個模板或者數(shù)據(jù)發(fā)生變化,還是要改來改去的,所以本文就在基礎(chǔ)版本上進行改進,只需要動動鼠標就可以填充大量數(shù)據(jù)到Excel工作表中。
文末附完整源碼、示例文件和工具獲取方式!
GUI界面設(shè)計
在開始設(shè)計GUI界面時,要明確我們需要實現(xiàn)什么功能,可以先設(shè)計出圖紙,再動手去寫代碼!本文根據(jù)需求,最后得出以下GUI界面圖紙:
通過 打開文件按鈕選擇數(shù)據(jù)文件或者在輸入框中輸入數(shù)據(jù)文件文件路徑,但只支持csv、xlsx、xls格式的文件,并把數(shù)據(jù)文件中的列標題傳入選擇或輸入數(shù)據(jù)列標題框中。通過 打開模板按鈕選擇模板文件或者在輸入框中輸入模板文件的路徑,只支持xlsx和xls格式的文件,并把模板表格中的空白單元格坐標傳入選擇或輸入單元格坐標框中。通過 選擇或輸入數(shù)據(jù)列標題框選擇要填充的數(shù)據(jù)列。通過 選擇或輸入單元格坐標框選擇各個數(shù)據(jù)列填充的位置。通過 繼續(xù)按鈕把數(shù)據(jù)列標題和單元格坐標存儲入列表中。通過 開始填充按鈕選擇保存路徑和輸入文件名稱,最后開始填充數(shù)據(jù)。通過 信息展示框展示操作信息。當數(shù)據(jù)列標題和單元格坐標選擇錯誤時,可以通過 刪除元素按鈕刪除列表中的錯誤數(shù)據(jù)。通過 退出程序按鈕直接結(jié)束工具的運行
根據(jù)圖紙和基本功能思路最后得出以下代碼:
# 主題設(shè)置
sg.theme('BrownBlue')
# 布局設(shè)置
layout = [
# 選擇數(shù)據(jù)文件框和按鈕 file_types 后面跟的是支持的文件格式,傳入的是元組,元組中只包含一個元素時,需要在元素后面添加逗號
[sg.Text('請選擇文件:', font=("微軟雅黑", 12)),
sg.InputText(key='please_select_file', size=(78, 1), font=("微軟雅黑", 10), enable_events=True),
sg.FileBrowse('打開文件', file_types=(("Text Files", "*.csv*"), ("Text Files", "*.xls*")), font=("微軟雅黑", 12))],
# 選擇模板框和按鈕 xls包括xlsx格式
[sg.Text('請選擇模板:', font=("微軟雅黑", 12)),
sg.InputText(key='template', size=(78, 1), font=("微軟雅黑", 10), enable_events=True),
sg.FileBrowse('打開模板', file_types=(("Text Files", "*.xls*"),), font=("微軟雅黑", 12))],
[sg.Text('請選擇或輸入數(shù)據(jù)列標題:', font=("微軟雅黑", 12)),
sg.Combo(values='', tooltip='請選擇或輸入數(shù)據(jù)列:', font=("微軟雅黑", 10), auto_size_text=True,
size=(15, 10), key='value'),
sg.Text('請選擇或輸入單元格坐標:', font=("微軟雅黑", 12)),
sg.Combo(values='', tooltip='請選擇或輸入單元格坐標:', font=("微軟雅黑", 10), auto_size_text=True,
size=(15, 10), key='keys'),
sg.Button('繼續(xù)', font=("微軟雅黑", 12)),
sg.Button('開始填充', font=("微軟雅黑", 12))],
[sg.Text('信息展示:', justification='center')],
[sg.Output(size=(100, 10), font=("微軟雅黑", 10))],
[sg.Text('', font=("微軟雅黑", 12), size=(0, 0)), sg.Button('刪除元素', font=("微軟雅黑", 12)),
sg.Text('', font=("微軟雅黑", 12), size=(62, 0)), sg.Button('退出程序', font=("微軟雅黑", 12))]
]
# 創(chuàng)建窗口
window = sg.Window('數(shù)據(jù)填充工具', layout, font=("微軟雅黑", 12), default_element_size=(80, 1))
# 事件循環(huán)
while True:
# 退出按鈕
event, values = window.read()
if event in (None, '退出程序'):
break
window.close()
界面效果:
事件循環(huán)設(shè)置
打開文件按鈕只要實現(xiàn)的是傳入數(shù)據(jù)文件,然后獲取數(shù)據(jù)文件的標題行并傳入對應(yīng)的框中:
if event == 'please_select_file':
fileName = values['please_select_file']
if os.path.exists(fileName):
# 因為pandas讀取文件因格式而異,所以需要判斷
if fileName.split('.')[-1] == 'csv':
df = pd.read_csv(fileName, encoding='utf-8')
# 獲取標題行
keys = df.columns.to_list()
# 傳入相應(yīng)的的框
window["value"].Update(values=keys, font=("微軟雅黑", 10), size=(15, 8))
elif fileName.split('.')[-1] == 'xls' or 'xlsx':
df = pd.read_excel(fileName, encoding='utf-8')
keys = df.columns.to_list()
window["value"].Update(values=keys, font=("微軟雅黑", 10), size=(15, 8))
else:
print('文件格式不正確,請重新選擇文件!')
sg.popup('文件格式不正確,請重新選擇文件!')
else:
print('文件不存在,請重新選擇文件!')
sg.popup('文件不存在,請重新選擇文件!')
打開模板按鈕只要實現(xiàn)的是傳入模板文件,以及獲取模板表格中的空白表格坐標;其中,之所以使用openpyxl打開模板文件,是因為后面是openpyxl進行填充數(shù)據(jù)的。而列表推導式中,第一個for循環(huán)取出單元格對象,第二個循環(huán)把對象內(nèi)容轉(zhuǎn)換為字符串格式,通過正則表達式取出單元格坐標,最后通過if判斷單元格內(nèi)容是否為None,是的話就傳入列表中,需要注意的是:如果是合并單元格的,會被分開計算為單個單元格。
if event == 'template':
fileName = values['template']
if os.path.exists(fileName):
wb = openpyxl.load_workbook(fileName)
sheets = wb.sheetnames # 獲取全部sheet
ws = wb[sheets[0]] # 默認獲取第一個工作表
data_row = []
# 列表推導式,獲取模板表格中的空白表格坐標
data = [data_row.append(i) for row in ws.rows for i in
re.findall("<.*? '.*?'.([A-Z]+\d+)>", str("{}".format(row))) if ws[str(i)].value == None]
window["keys"].Update(values=data_row, font=("微軟雅黑", 10), size=(15, 8))
else:
print('文件不存在,請重新選擇文件')
sg.popup('文件不存在,請重新選擇文件')
繼續(xù)選擇按鈕只要實現(xiàn)的是:獲取用戶在選擇或輸入數(shù)據(jù)列標題框和選擇或輸入單元格坐標框一次次輸入的內(nèi)容,存儲到valuelist和keyslist列表中:
if event == '繼續(xù)':
if values['value'] and values['keys']:
a = values['value']
b = values['keys']
valuelist.append(a)
keyslist.append(b)
print(f'選擇: {a}:{b} 完畢,請繼續(xù);或者點擊開始進行數(shù)據(jù)填充!')
else:
print('數(shù)據(jù)列標題或者單元格坐標未選擇!')
sg.popup('數(shù)據(jù)列標題或單元格坐標未選擇!')
判斷兩個列表中的內(nèi)容是否存在,存在就把數(shù)據(jù)傳入Datainput函數(shù)中,files是一個保存路徑彈窗,先選擇路徑,然后在輸入文件名稱,最后開始填充:
if event == '開始填充':
if len(keyslist) and len(valuelist) != 0:
files = sg.popup_get_folder('請選擇存儲路徑和輸入文件名稱:')
Datainput(files, valuelist, keyslist)
else:
print('數(shù)據(jù)列標題或者單元格坐標未選擇!')
sg.popup('數(shù)據(jù)列標題或單元格坐標未選擇!')刪除元素按鈕只要用python自帶函數(shù)remove來刪除列表中的元素,為了防止元素不存在而導致報錯,這里加一個條件判斷:
if event == '刪除元素':
if values['value'] or values['keys']:
a = values['value']
b = values['keys']
if a in valuelist:
valuelist.remove(a)
print('刪除成功!')
else:
print('表格列標題不存在!')
sg.popup('表格列標題不存在!')
if b in keyslist:
keyslist.remove(b)
print('刪除成功!')
else:
print('單元格坐標不存在!')
sg.popup('單元格坐標不存在!')數(shù)據(jù)填充函數(shù)
Datainput函數(shù)接收通過開始填充按鈕傳入的列標題和單元格坐標,并開始填充數(shù)據(jù):
def Datainput(files, key, value):
for p in range(len(df[key[0]])): # 計算excel工作表其中一列數(shù)據(jù)的數(shù)目,然后進行遍歷這個數(shù)值
sheet = wb.copy_worksheet(ws) # 復制原有工作表
sheet.title = str(df[key[0]][p]) # 設(shè)置工作表名稱
for i in range(len(key)): # 計算excel工作表中標題數(shù)目
sheet[value[i]].value = df[key[i]][p] # 寫入數(shù)據(jù)
print('正在填充,請稍等!')
# 彈窗進度條
sg.one_line_progress_meter('正在填充,請稍等!', p + 1, 100, orientation='h',
bar_color=('#F47264', '#FFFFFF'))
wb.save(files)
print('已完成...')
sg.popup('已完成!') # 彈窗
打包運行
打包可以通過pyinstaller庫,安裝只需要pip命令即可!安裝后在命令行窗口cd到文件所在的文件目錄中,最后用下面命令進行打包。
pyinstaller -F -w 名稱.py
打包時可能會報錯:

報錯源于一個hook-sqlalchemy.py文件,一個簡單的解決方法是找到它直接回收刪除它(最后暫未發(fā)現(xiàn)刪除它對打包后的exe文件有什么影響),等打包完成后在放回去即可:

最終效果展示。沒錄到鼠標,后面選擇完單元格坐標后,是點擊了繼續(xù),選擇完成后是點擊了開始填充;如果你選擇錯誤標題和單元格坐標,可以點擊刪除元素按鈕刪除;打開表格時有點卡,后面出現(xiàn)的兩個彈窗直接點擊“是”和“關(guān)閉”即可:

結(jié)語
把一個簡單的腳本制作成一個可運行的工具,代碼量變多了,但用起來方便了很多,只要是能節(jié)省時間,解放雙手(雖然還要動手),避免重復性、機器式操作。
以上便是本文全部內(nèi)容,代碼在測試過程中暫未發(fā)現(xiàn)什么bug,可正常運行。如果你感興趣的話,點個贊和在看支持一下唄。
完整源碼、示例文件和工具可在公眾號后臺發(fā)送填充數(shù)據(jù)獲取!
3、谷歌程序員少輸一個“&”,差點讓全球Chrome筆記本變磚
今天因為您的點贊和在看,讓我元氣滿滿!
