tkinter開啟excel文件修改儲存(python)

語言: CN / TW / HK

tkinter 是 Python 的標準 GUI 庫。內建到 python 的安裝包中,可以直接import使用。

學習用tkinter 元件treeview顯示excel內容再通過點選修改儲存回去新工作表。

除了tkinter的內容,還涉及到excel文件的操作。

這裡我用到openpyxl庫,這是第三方庫要pip安裝。在windows系統下邊學邊寫,這裡作一個記錄總結。

開始前

開始時設想是開啟一個介面裡面有開啟,儲存按鈕。點開選擇文件後內容顯示到介面上,然後在treview內雙擊修改,改完點儲存按鈕儲存。

實力有限,就換了另一個方法(繞了一下)。實現開啟修改儲存,下面會說到。

開寫,開啟視窗

首先要顯示個視窗。上面說到的兩個按鈕選檔案後顯示內容到上面沒找到解決方法。我做的是先一個視窗顯示開啟按鈕,選中文件後再開啟一個顯示內容的視窗。

import tkinter as tk
from tkinter import filedialog

def openbook():
    fpath=filedialog.askopenfilename()
    print(fpath)
    if fpath:
        pass

wino=tk.Tk()
wino.geometry('200x100')
btno=tk.Button(wino,text='開啟', command=openbook)
btno.pack(side=tk.TOP,expand = tk.YES)
wino.mainloop()

tkinter庫裡的filedialog開啟選擇檔案對話方塊。

geometry()視窗大小

那麼現在就清楚了,在openbook裡面pass寫一個函式替換。

 

開啟excel

(只對有一行標題的內容,看下面文件demo圖片)

def win_openxls(fpath):
    global wino
    wino.destroy()
    savepath=fpath
    w=xl.load_workbook(fpath)
    name=w.sheetnames
    print(name)

    sheet=w[name[0]]
    n=sheet.max_row
    col=sheet.max_column

    xlarr=[]
    for r in sheet.rows:
        arr=[]
    for cell in r:
            arr.append(cell.value)
        xlarr.append(arr)
 
    win=tk.Tk()
    win.geometry('800x400')

    colname=[]
    for c in range(col):
        colname.append(c)

    tree=ttk.Treeview(win,show='headings',columns=colname,selectmode = 'browse')#單行選中模式

    for c in range(col):
        tree.column(c,width=90,anchor='center')
        tree.heading(c,text=xlarr[0][c])#顯示標題

    titles=xlarr[0]

    del(xlarr[0])#刪了第一個,不刪顯示內容第一行與標題重複

    for i in range(n-1):
        tree.insert('',i,values=xlarr[i])#顯示內容

    tree.pack(side=tk.TOP,fill=None,)

    btn1=tk.Button(win,text='儲存', command=savebook)
    btn1.pack(side=tk.BOTTOM,expand = tk.YES)

    #tree.bind('<Double-Button-1>',viewclick)#後面用到,監控滑鼠雙擊
    win.mainloop()

這個函式是開啟文件內容顯示到介面上。替換openbook的pass。

文件內容demo這樣的

 

執行選擇這個文件後

wino.destroy()#關閉選擇窗

sheet=w[name[0]]#讀取Sheet1工作表內容

n=sheet.max_row#取內容行數

col=sheet.max_column#取內容列數

xlarr.append(arr)#列表儲存excel內容

colname.append(c)#列表儲存用到treeview標題

還有些在程式碼註釋了。

 

編輯內容

用到上面註釋掉的監控滑鼠雙擊。

tree.bind('<Double-Button-1>',viewclick)

雙擊後viewclick函式處理,彈出一個窗修改再儲存回去。

def viewclick(event):
    global nwin
    global tree
    global enty
    global sitem
    global colint
    for item in tree.selection():
        ttext=tree.item(item,'values')
        sitem=item

    col=tree.identify_column(event.x)
    colint=int(str(col.replace('#','')))
    
    nwin=tk.Tk()#編輯視窗
    nwin.geometry("260x100")
    label1 = tk.Label(nwin, text="修改:")
    label1.pack(side=tk.LEFT, fill=None)
    enty=tk.Text(nwin,width=300,height=300,wrap = tk.WORD)
    enty=tk.Entry(nwin)
    enty.pack(side=tk.LEFT, fill=None)
    btn=tk.Button(nwin,text='確認', command=getv)
    btn.pack(side=tk.LEFT,padx=6,ipadx=6)
    enty.insert('end',ttext[colint-1])#編輯框顯示值
    openwin.append(nwin)
  
    if len(openwin)>1:
        openwin.pop(0).destroy()
    nwin.protocol('WM_DELETE_WINDOW', initopenwin)#繫結時件,關閉窗清除變數值
    nwin.mainloop()

tree.selection()#取到items(選了那行)

tree.item(item,'values')#選中行的所有值

tree.identify_column(event.x)#event.x選中的x座標,identify_column()返回座標列標如:#1 表示第2列。這裡再replace就取裡面的數字。

openwin.pop(0).destroy()#防止開啟多個編輯視窗

取值函式

def getv():
    global nwin
    global enty
    global tree
    global sitem
    global colint
    global openwin
    editxt=enty.get()
    tree.set(sitem,(colint-1),editxt)
    openwin=[]
    nwin.destroy()

取到修改的值

tree.set(sitem,(colint-1),editxt)#更新修改後顯示。

儲存

def savebook():
    global w
    global tree
    global titles
    global savepath
    
    ws=w.create_sheet('change1')
    ws.append(titles)
    for itm in tree.get_children():
        ws.append(tree.item(itm)['values'])   
     w.save(savepath)
     messagebox.showinfo('提示','儲存成功')

w.create_sheet('change1')#建立工作表

ws.append(titles)#新增首行

tree.get_children()#取到treeview標題下面的內容

w.save(savepath)#儲存

演示