機械系エンジニアの備忘録

20代独身社会人。仕事では機械・機構の研究開発を行っているエンジニアが、自分の専門分野ではないpythonを扱って楽しむブログです。

MENU

【python】【Tkinter】【Excel】GUIからCSVをExcelに変換する方法(part3)

CSVのデータの区切りに対応するためにコードを書き足す

■はじめに

前回、GUIからCSVを選択して、データを抽出してExcelにまとめるアプリを作りました。またユーザーが設定を間違えた時にエラーメッセージを表示させるようにしました。

stjun.hatenablog.com

 

stjun.hatenablog.com

stjun.hatenablog.com

 また処理部分だけを見たい場合は以下記事を見てください。

stjun.hatenablog.com

 今回はCSVのデータの区切り方に対応できるように改良します。

具体的にはこれまではデータがスペースで区切られているCSVを対象にしました。しかし、このままでは次のようにカンマで区切られたCSVには対応できません。

f:id:stjun:20190825184403p:plain

そこでユーザーがGUIから上記を選択できるようにします。

■コード

#GUIから行・列を指定して,CSVからExcelファイルを自動生成
#データの区切りがスペースかカンマで対応
#これにより様々なCSVにも対応できる
import tkinter as tk
import tkinter.filedialog as fl
import tkinter.messagebox as mb
import numpy as np
import openpyxl as px
from openpyxl.chart import ScatterChart,Reference,Series

#メインウインド
root=tk.Tk()
#root.geometry("500x300")
root.title("CSVからExcelファイルに変換+散布図を自動作成")


#frameの作成
frame1=tk.LabelFrame(root,text="実行タブ",foreground="green")
frame1.grid(row=0,columnspan=2,sticky="we")

frame2=tk.LabelFrame(root,text="詳細タブ",foreground="green")
frame2.grid(row=1,sticky="we")



#frame1に表示する部品
message=tk.Label(frame1,text="ファイルを選択してください",width=30)
message.grid(row=0,column=0)

blank=tk.Label(frame1,width=3)
blank.grid(row=0,column=1)



#frame2に表示する部品
#下の説明
text_title=tk.Label(frame2,text="Excelのファイル名",width=20)
text_title.grid(row=0,column=0,padx=5)

text_row=tk.Label(frame2,text="データは何行目からか",width=20)
text_row.grid(row=0,column=1,padx=5)

text_column=tk.Label(frame2,text="何列あるか",width=20)
text_column.grid(row=0,column=2,padx=5)


#必要な項目の欄
entry_title=tk.Entry(frame2,width=20)
entry_title.insert(tk.END,"テスト")
entry_title.grid(row=1,column=0,padx=5)


entry_row=tk.Entry(frame2,width=20)
entry_row.insert(tk.END,"2")
entry_row.grid(row=1,column=1,padx=5,pady=5)

entry_column=tk.Entry(frame2,width=20)
entry_column.insert(tk.END,"3")
entry_column.grid(row=1,column=2,padx=5,pady=5)

#データの区切り方を指定できるラジオボタンを作成
frame3=tk.LabelFrame(frame2,text="CSVの区切り方",foreground="green")
frame3.grid(row=2,column=0,sticky="we")

var=tk.IntVar()
var.set(0)

radio_space=tk.Radiobutton(frame3,value=0,variable=var,text="スペース")
radio_space.pack()
radio_comma=tk.Radiobutton(frame3,value=1,variable=var,text="カンマ")
radio_comma.pack()

#CSVからExcelを作成する処理の部分
def get(*args):

    filetype=[("all file","*")]    
    path=fl.askopenfilename(initialdir="C:/Users/ユーザー名/Desktop",filetypes=filetype,title="ファイルを選んで下さい")
    
    #必要な変数の取得
    title_name_str=entry_title.get()
    skiprow_str=entry_row.get()
    skiprow_int=int(skiprow_str)
    variable_number_str=entry_column.get()
    variable_number_int=int(variable_number_str)
    
    #以下は前回と同じ、CSVファイルのデータを読み込み表示させる
    try:
        csv_data_separate=var.get()
        if csv_data_separate==0:
            data= np.loadtxt(fname=path, skiprows=skiprow_int-1)
        else:
            data= np.loadtxt(fname=path,delimiter=",", skiprows=skiprow_int-1) 
    except:
        mb.showinfo("エラー","エラー。設定を確認してください")

    #新しいExcelの作成とアクティブ化
    wb=px.Workbook()
    ws=wb.active

    #Excelシートの名前を設定
    ws.title="計算結果"

    #Excel一行目にどんな物理量について計算したか記載するためのリスト
    list_target=["x軸","物理量A(単位)","物理量B(単位)"]

    #Excelの1行目に記載していく
    for i in range(len(list_target)):
        ws.cell(row=1,column=i+1,value=list_target[i])
    
    data_all=[0]*variable_number_int
    for i in range(variable_number_int):
        data_all[i]=data[:,i]
    

    #計算結果をセルに代入する
    for j in range(variable_number_int):
        for i in range(len(data_all[0])):
            ws.cell(row=i+2,column=j+1,value=data_all[j][i])
    
    #グラフとして散布図を作成する
    chart =ScatterChart()
    #グラフのタイトル
    chart.title = "散布図のテスト"
    #x軸のタイトル
    chart.x_axis.title = 'x軸'
    #y軸のタイトル
    chart.y_axis.title = 'y軸'

    #x軸とするデータ
    x_values = Reference(ws, min_col=1, min_row=2, max_row=len(data_all[0])+1)
    for i in range(2, len(data)):
        #y軸とするデータ
        y_values = Reference(ws, min_col=i, min_row=1, max_row=len(data_all[0])+1)
        #x軸とy軸の組み合わせを決める
        con = Series(y_values, x_values, title_from_data=True)
        #マーカーの形
        con.marker.symbol = 'circle' 
        #マーカーの塗りつぶし
        con.marker.graphicalProperties.solidFill ="FFFFFF"
        #マーカーの枠線の色
        con.marker.graphicalProperties.line.solidFill = "000000"
        #散布図に系列を追加
        chart.series.append(con)

    #シートにグラフを追加
    ws.add_chart(chart, "A10")

    #Excelデータをデスクトップに保存する(ユーザー名にお使いのPCの名前を入れてください)
    wb.save(r"/Users/ユーザー/Desktop/"+title_name_str+".xlsx")
    
    message["text"]="Excelファイルを作成しました"


#frame1に表示する部品2
button=tk.Button(frame1,text="選ぶ",width=10,command=get)
button.grid(row=0,column=2)

root.mainloop()

試しに次の2つのCSVを対象に動かしてみたいと思います。

f:id:stjun:20190822231927p:plainf:id:stjun:20190825184403p:plain

上記コードを実行すると以下の画面が現れます。

f:id:stjun:20190825184914p:plain

下部のラジオボタンCSVの区切り方でdata01.csvでは「スペース」を、data05.csvでは「カンマ」を選択すると次のようにちゃんとExcelファイルが作成されます。

f:id:stjun:20190825170211p:plain

また間違えた場合はちゃんとエラーメッセージがでます。

f:id:stjun:20190825185415p:plain

 

■買って良かったもの紹介

今日紹介するのはKindleです。

 

 Amazonではkindle unlimitedという月額980円で和書12万冊、洋書120万冊の読み放題サービスがあります。pythonの本もあります。

紙の本も良いですが、出先で様々な本を読みたい時にKindleを重宝しています。

 

■最後に

まだまだ改良していきます。