多数のexcelに、特定なシートに特定なデータを同時入力

###問題
色んなEXCELに、同じ場所に日付更新したことはありませんか。
今回解決したい問題は：
色んなEXCELに、同じシート、同じ場所、同じデータを入力したいです。

###環境
window 10
python 3.7.2
Excel(xlsx拡張子)　※使うライブラリopenpyxlがxlsxしか対応したいため　[refer to/PythonでExcelファイルを扱うライブラリの比較](https://note.nkmk.me/python-excel-library/)

###効果図
1.最初のexcel状態
python ファイルがExcelファイルと同じディレクトリに保存してありいます。もし違う場合、pythonがファイルを読み込むパスを改めて指定すべきです。
逆に言うと、更新したいExcelのファイルのディレクトリに、当pythonファイルを入れれば、実行できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704481/5df467fc-059b-1dfa-d501-d70b03786e58.png)


名前が違うEXCELのセルA1に日付を入れたいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704481/3513d6d3-f4c8-692a-6dc7-961698d19ee0.png)

2.データ入力画面
pythonのTKで作成した画面に、入力してほしいデータ、シート名、セルの場所を入力する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704481/e5fd0ce4-e070-0951-c335-88c4a33054ac.png)

3.データを入力して、実行ボタンを押すと、各EXCELにデータを書き込む
[point]実行するとき、必ず更新したいExcelを閉じて実行する、さもないと、開いたExcelに編集できず、エラーが出てしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704481/280320bc-9966-5661-5084-31e7ff40cbfc.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704481/e3047a28-0d62-9cd2-cd2c-99a81256b09d.png)

4.Excelファイルの中に、指定のシート名がない時、更新できず、ファイル名を下記に表示する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704481/2857b66e-0ab0-b4b7-34fd-0dc588f848d7.png)

###いよいよコードに入ります、まず全体的なコード、そして各部分を解説いきます。


```py:py
# -*- 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](https://nnahito.gitbooks.io/tkinter/content/)


```py:py

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する事件を設定する


```py:py

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()すべき、一旦変数に保存して、再度引数として使うと、うまく値を渡せない（多分スコープの問題だと、詳しくないので、すみません。。。）、下記のコードにエラーが出る

```py:py

# 入力欄を設定
Entry1 = tk.Entry()
# 入力したデータを取得
Entry1_value = Entry1.get()
# 実行ボタンを設置
Button = tk.Button(text='実行ボタン', command=lambda: button_click(Entry1_value)) #error
```

ボタンをクリックすると、多数のexcelに、特定なシートに特定なデータを同時入力、button_click事件を定義する

```py:py

# ボダンをクリックするとき、発生する事件
# 引数三つ、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]を取得する

```py:py

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
```