PythonでExcelのデータを読み込み、名前をつけて保存する。
Pythonの練習第2弾。今回は、かなり昔の記事エクセルからデータを読み込み、Peakを検出しエクセルに出力する - 生物屋さんのためのゼロからのプログラミングをPythonを使って書いてみた。ただし、今回はエクセルのデータの読み込みと書き出しのみを行った。
ソースコードは下記。
import tkinter
import tkinter.filedialog
import openpyxl
import numpy as np
#エクセルの読み込みと書き込み、そして保存する関数
def openFile(event):
fileType = [("excel", "*.xlsx")]
iDir = "/Users/Desktop/"
filePath = tkinter.filedialog.askopenfilename(filetypes = fileType, initialdir = iDir)
wb = openpyxl.load_workbook(filePath)
sheet = wb.active
#入れ物の作成
u = np.zeros((sheet.max_column, sheet.max_row))
#入れ物に数値を入れる
for i in range(1,sheet.max_column+1):
for j in range(1, sheet.max_row+1):
u[i-1][j-1] = sheet.cell(row=j, column=i).value
#データを入れるためのシートを作る
wb.create_sheet(index=2, title="Copy Data")
sheet2 = wb["Copy Data"]
# シートにデータを貼り付ける
for i in range(1, sheet.max_column+1):
for j in range(1, sheet.max_row+1):
sheet2.cell(row=j, column=i).value = u[i-1][j-1]
#新しいExcelファイルを名前をつけて保存する
closePath = tkinter.filedialog.asksaveasfilename()
wb.save(closePath+".xlsx")
#GUIの作成
root = tkinter.Tk()
root.title("Excel Test")
root.geometry("100x100")
#イベントを起こすためのボタンの作成
button1 = tkinter.Button(text = "Open", width = 50)
button1.bind("<Button-1>", openFile)
button1.pack()
#実行
root.mainloop()このプログラムを実行すると、オープンダイアログが立ち上がるので、目的のExcelファイルを選択。今回は下記のような単純な数字が並んだものにした。
そして、すぐに保存用のダイアログが立ち上がるので、適当に名前をつけて保存すると、
のように、新しいシートにデータを書き込める。
幾つかのコードを見ていく。
まず、Javaでエクセルを取り扱うには、
poi-3.17.jar poi.examples-3.17.jar poi.excelant-3.17.jar poi-ooxml-3.17.jar poi-ooxml-schemas-3.17.jar poi-scratchpad-3.17.jar xmlbeans-2.6.0.jar
上記のjarファイルをEclipseに入れる必要があった(詳細はEclipseでImageJのPlugin作成 -マウスでクリックした場所にOval ROIを描き、Excelファイルにデータを書き出す。- - 生物屋さんのためのゼロからのプログラミング参照)。
一方、Pythonの場合は、まず、ターミナルで、
sudo pip3 install openpyxl
と入力すると、"openpyxl"がインストールできる。
ただし、この時、インストールされた"openpyxl"は「”ライブラリ”⇨”Frameworks”⇨”Python.framework”⇨”Versions”⇨”3.6”⇨”lib”⇨”Python3.6”⇨”site-packages”」に入っているので(僕のMacでは)、”site-packages”の中から出して、一つ上の”Python3.6”に移す必要がある。
そして、
import openpyxl
を書くだけで、PythonでExcelが扱えるようになる。
(ただし、Mac Excel 2011とopenpyxlの相性が悪いのか、Mac Excel 2011で作成したExcelファイルは開けなかったが、Mac Excel 2016で作成したExcelファイルは扱えた。理由は不明)
Excelファイルを開く場合、多くのサイトでは、カレントディレクトリに開きたいExcelファイルを移して、Excelファイル名をコードに手入力する方法を紹介している。
しかし、これでは使い勝手が非常に悪いので、オープンダイアログを使って開きたいExcelファイルを選択できるようにした。ソースコードは下記。
fileType = [("excel", "*.xlsx")]
iDir = "/Users/Desktop/"
filePath = tkinter.filedialog.askopenfilename(filetypes = fileType, initialdir = iDir)
wb = openpyxl.load_workbook(filePath)実質一行で完結するので、Javaに比べると非常に楽である。
次に、なんらかの数値処理を行うために、Excelのデータを配列に取り込むためのコードが下記。
#入れ物の作成
u = np.zeros((sheet.max_column, sheet.max_row))
#入れ物に数値を入れる
for i in range(1,sheet.max_column+1):
for j in range(1, sheet.max_row+1):
u[i-1][j-1] = sheet.cell(row=j, column=i).value配列には"numpy"を使用した。"numpy"のインストールには、"openpyxl"と同様に、ターミナルで
sudo pip3 install numpy
と入力することでインストールでき、"openpyxl"と同様に”Python3.6”に移せば使えるようになる。
まだnumpyの使い方がよく分からなかったため、下記の部分で”作りたい大きさ”の空の入れ物を作った。
#入れ物の作成
u = np.zeros((sheet.max_column, sheet.max_row))Excelのデータを配列に入れる時の注意点として、数の数え方の違いがある。
#入れ物に数値を入れる
for i in range(1,sheet.max_column+1):
for j in range(1, sheet.max_row+1):
u[i-1][j-1] = sheet.cell(row=j, column=i).value上記の部分でExcelのデータを配列に入れているのだが、エクセル上では”1”から数え始めるのに対し、配列は”0”から始まるため微調整が必要となる。
Excelにデータを貼る場合も、Pythonは非常に楽であった。コードは下記。
# シートにデータを貼り付ける
for i in range(1, sheet.max_column+1):
for j in range(1, sheet.max_row+1):
sheet2.cell(row=j, column=i).value = u[i-1][j-1]Javaの場合は、記入するための"cell"を最初に作る必要があり、これを怠ったり、記入するデータサイズと異なっているとエラーが生じていた。なので、Excel操作に関しては圧倒的にPythonが楽そうである。
最後に、保存ダイアログを使ったExcelファイルの保存方法は下記。
#新しいExcelファイルを名前をつけて保存する
closePath = tkinter.filedialog.asksaveasfilename()
wb.save(closePath+".xlsx")オープンダイアログと同様、一行で終わるので非常に楽である。
上記のコードをグローバル変数を使った物に少しmodifyしたので、追記。
import tkinter
import tkinter.filedialog
import openpyxl
import numpy as np
#エクセルファイルを開く
def openFile(event):
global sheet
global wb
fileType = [("excel", "*.xlsx")]
iDir = "/Users/Desktop/"
filePath = tkinter.filedialog.askopenfilename(filetypes = fileType, initialdir = iDir)
wb = openpyxl.load_workbook(filePath)
sheet = wb.active
getData()
#ExcelファイルのDataを取得
def getData ():
global u
global sheet2
u = np.zeros((sheet.max_column, sheet.max_row))
for i in range(1, sheet.max_column+1):
for j in range(1, sheet.max_row+1):
u[i-1][j-1] = sheet.cell(row = j, column = i).value
#Excelファイルを名前をつけて保存する
def saveFile(event):
wb.create_sheet(index=1, title="Copy")
sheet2 = wb["Copy"]
for i in range(1, sheet.max_column + 1):
for j in range(1, sheet.max_row + 1):
sheet2.cell(row=j, column=i).value = (u[i - 1][j - 1]) * 2
closePath = tkinter.filedialog.asksaveasfilename()
wb.save(closePath+".xlsx")
#GUIの作成およびボタンの設置
root = tkinter.Tk()
root.title("Test")
root.geometry("100x100")
openButton = tkinter.Button(text = "Open", width = 25)
saveButton = tkinter.Button (text = "Save", width = 25)
openButton.bind("<Button-1>", openFile)
saveButton.bind("<Button-1>", saveFile)
openButton.pack()
saveButton.pack()
root.mainloop()関数間で変数を共有できるように、global文を使った。
具体的には、下記の部分などである。
global u
global sheet2こうすることで、関数をまたいで変数を使える。
このコードを実行すると、
のように2つのボタンがついたGUIが立ち上がり、OpenボタンでExcelファイルを呼び出し、Saveボタンで名前を付けて保存できるようにした。