###問題
色んなEXCELに、同じ場所に日付更新したことはありませんか。
今回解決したい問題は:
色んなEXCELに、同じシート、同じ場所、同じデータを入力したいです。
###環境
window 10
python 3.7.2
Excel(xlsx拡張子) ※使うライブラリopenpyxlがxlsxしか対応したいため refer to/PythonでExcelファイルを扱うライブラリの比較
###効果図
1.最初のexcel状態
python ファイルがExcelファイルと同じディレクトリに保存してありいます。もし違う場合、pythonがファイルを読み込むパスを改めて指定すべきです。
逆に言うと、更新したいExcelのファイルのディレクトリに、当pythonファイルを入れれば、実行できる
2.データ入力画面
pythonのTKで作成した画面に、入力してほしいデータ、シート名、セルの場所を入力する
3.データを入力して、実行ボタンを押すと、各EXCELにデータを書き込む
[point]実行するとき、必ず更新したいExcelを閉じて実行する、さもないと、開いたExcelに編集できず、エラーが出てしまいます。
4.Excelファイルの中に、指定のシート名がない時、更新できず、ファイル名を下記に表示する
###いよいよコードに入ります、まず全体的なコード、そして各部分を解説いきます。
# -*- coding: utf-8 -*-
"""
複数シートを同時入力
"""
import glob
from openpyxl import load_workbook
import tkinter as tk
import tkinter.messagebox as tkm
def batExcel(term, sheet, cell):
# 記入するマスタのシートを指定する
Sheet = sheet
# 複数のファイルを選択
files = glob.glob('*.xlsx')
successFile = []
failFile = []
# すべてのファイルをループする
for file in files:
wb = load_workbook(file)
# すべてのシートを読み取る
sheetnames = (wb.sheetnames)
# マスタSheet表が存在するかどうか判断
if Sheet in sheetnames:
# sheetを選択する
ws = wb[Sheet]
# cellを選択する
ws[cell] = term
wb.save(file)
wb.close()
successFile.append(file)
else:
failFile.append(file)
# 入力成功、失敗のEXCELの名前をreturn
return successFile,failFile
# ボダンをクリックするとき、発生する事件
# 引数三つ、text -> 入力したいデータ、master -> 入力したいシート、cell ->入力したいセル
def button_click(text, master, cell):
# ボタンを押すたびに、リストの中の元データをクリアする
ListBox1.delete(1, tk.END)
ListBox2.delete(1, tk.END)
files = batExcel(text, master, cell)
for i in range(len(files[0])):
ListBox1.insert(tk.END, files[0][i])
for j in files[1]:
ListBox2.insert(tk.END, j)
# GUI画面を作成
root = tk.Tk()
# タイトルを設定
root.title("会計期間")
# 画面のサイズを設定
root.geometry('400x500')
# 会計期間labelを設定
Static1 = tk.Label(text='YYYYMM形式で、会計期間をご入力ください')
Static1.pack()
# 会計期間入力欄を設定
Entry1_term = tk.Entry()
Entry1_term.pack()
# マスタシートlabelを設定
Static2 = tk.Label(text='更新するマスタ名前をご入力ください')
Static2.pack()
# マスタシート入力欄を設定
Entry2_sheet = tk.Entry()
Entry2_sheet.pack()
# マスタシートのセル場所labelを設定
Static3 = tk.Label(text='更新するセル場所をご入力ください')
Static3.pack()
# マスタシートのセル場所入力欄を設定
Entry3_cell = tk.Entry()
Entry3_cell.pack()
# 実行ボタンを設置
Button = tk.Button(text='実行ボタン', command=lambda: button_click(Entry1_term.get(), Entry2_sheet.get(), Entry3_cell.get()))
Button.pack()
# 導入成功リストボックスを設置
ListBox1 = tk.Listbox(width=50, height=10)
ListBox1.insert(tk.END,'会計期間更新成功EXCEL:')
ListBox1.pack()
# 導入失敗リストボックスを設置
ListBox2 = tk.Listbox(width=50, height=10)
ListBox2.insert(tk.END,'マスタSheetが存在しないため、会計期間更新失敗EXCEL:')
ListBox2.pack()
# GUI画面をActive、例えば、マウントクリック、画面閉じるなどの動作に反応する
root.mainloop()
tkinter データの入力画面を作りましょう refer to/コピペでできる!Tkinter
import tkinter as tk
import tkinter.messagebox as tkm
# GUI画面を作成
root = tk.Tk()
# タイトルを設定
root.title("会計期間")
# 画面のサイズを設定
root.geometry('400x500')
# 会計期間labelを設定
Static1 = tk.Label(text='YYYYMM形式で、会計期間をご入力ください')
Static1.pack()
# 会計期間入力欄を設定
Entry1_term = tk.Entry()
Entry1_term.pack()
# マスタシートlabelを設定
Static2 = tk.Label(text='更新するマスタ名前をご入力ください')
Static2.pack()
# マスタシート入力欄を設定
Entry2_sheet = tk.Entry()
Entry2_sheet.pack()
# マスタシートのセル場所labelを設定
Static3 = tk.Label(text='更新するセル場所をご入力ください')
Static3.pack()
# マスタシートのセル場所入力欄を設定
Entry3_cell = tk.Entry()
Entry3_cell.pack()
# 実行ボタンを設置
Button = tk.Button(text='実行ボタン', command=lambda: button_click(Entry1_term.get(), Entry2_sheet.get(), Entry3_cell.get()))
Button.pack()
# 導入成功リストボックスを設置
ListBox1 = tk.Listbox(width=50, height=10)
ListBox1.insert(tk.END,'会計期間更新成功EXCEL:')
ListBox1.pack()
# 導入失敗リストボックスを設置
ListBox2 = tk.Listbox(width=50, height=10)
ListBox2.insert(tk.END,'マスタSheetが存在しないため、会計期間更新失敗EXCEL:')
ListBox2.pack()
# GUI画面をActive、例えば、マウントクリック、画面閉じるなどの動作に反応する
root.mainloop()
画面出来上がり、実行ボタンがbindingする事件を設定する
Button = tk.Button(text='実行ボタン', command=lambda: button_click(Entry1_term.get(), Entry2_sheet.get(), Entry3_cell.get()))
# 下記のコードも同じ効果
Button = tk.Button(text='実行ボタン', command= button_click(Entry1_term.get(), Entry2_sheet.get(), Entry3_cell.get()))
[point]ただ、引数はEntry1_term.get()すべき、一旦変数に保存して、再度引数として使うと、うまく値を渡せない(多分スコープの問題だと、詳しくないので、すみません。。。)、下記のコードにエラーが出る
# 入力欄を設定
Entry1 = tk.Entry()
# 入力したデータを取得
Entry1_value = Entry1.get()
# 実行ボタンを設置
Button = tk.Button(text='実行ボタン', command=lambda: button_click(Entry1_value)) #error
ボタンをクリックすると、多数のexcelに、特定なシートに特定なデータを同時入力、button_click事件を定義する
# ボダンをクリックするとき、発生する事件
# 引数三つ、text -> 入力したいデータ、master -> 入力したいシート、cell ->入力したいセル
def button_click(text, master, cell):
# ボタンを押すたびに、リストの中の元データをクリアする
ListBox1.delete(1, tk.END)
ListBox2.delete(1, tk.END)
files = batExcel(text, master, cell)
for i in range(len(files[0])):
ListBox1.insert(tk.END, files[0][i])
for j in files[1]:
ListBox2.insert(tk.END, j)
[point]関数は使う前に定義しなくてはならない、ちなわち、button_click関数はButton = tk.Button(text='実行ボタン', command= button_click(Entry1_term.get(), Entry2_sheet.get(), Entry3_cell.get()))
の上に書く
多数のexcelに、特定なシートに特定なデータを同時入力 の関数を定義する
流れは下記のようになります。
・すべてのファイルに書き込むには、すべてのファイル → シート → セル という順番を読み取る、仮にまずすべてのファイルの[Sheet][A1]を取得する
import glob
from openpyxl import load_workbook
def batExcel(term, sheet, cell):
# 記入するマスタのシートを指定する
Sheet = sheet
# 複数のファイルを選択
files = glob.glob('*.xlsx')
successFile = []
failFile = []
# すべてのファイルをループする
for file in files:
wb = load_workbook(file)
# すべてのシートを読み取る
sheetnames = (wb.sheetnames)
# マスタSheet表が存在するかどうか判断
if Sheet in sheetnames:
# sheetを選択する
ws = wb[Sheet]
# cellを選択する
ws[cell] = term
wb.save(file)
wb.close()
successFile.append(file)
else:
failFile.append(file)
# 入力成功、失敗のEXCELの名前をreturn
return successFile,failFile