python / 学习 · 2021年8月17日 0

tkinter打开excel文档修改保存(python)

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 表示第1列。这里再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)#保存

演示