週間プログラミング④:Pythonで名簿作成アプリを作ろう

コンテンツ
IT・テクノロジー

GUIアプリとは?

 今週はPythonでエクセルの名簿ファイルに名前・電話番号・性別を登録するGUIアプリを作ります。

 さて、GUIアプリというのはGraphical User Interfaceの略で、カーソルでボタンを押したり、スライドさせたりといった直感的な操作が可能な画面のことをいいます。もっと言えば、マウスで操作できるのは基本的に全てGUIと呼ばれるものです。

 私達がパソコンと聞いて想像する作業の殆ど全てはGUIで行うことができます。ブラウザの操作やword、EXCELは全てGUIアプリです。
 GUIの反対の概念にCUIというものがあります。これは、例えばコマンドプロンプトなどがそうです。

CUI.PNG


PythonでGUIアプリを作るには?

 PythonでGUIのアプリを作る際、有名なモジュールにtkinterがあります。昔からあるモジュールですが、コードが長くなるなど、やや使いにくいです。
 そこで、今回は最近開発されたPySimpleGUIを使ってみます。インストールしていない人は、プロンプトで

$pip install pysimplegui

と打ち、インストールしましょう。

作りたいアプリの機能

 次のような操作が可能なアプリを目指します。

①GUIで氏名・電話番号・性別を入力する
②アプリがエクセルファイル”meibo.xslx”を作成する(開く)
③meibo.xslxに入力された情報を書き込む

 このようなアプリがあれば、いちいちエクセルファイルを開かなくとも名簿管理が可能になります!

プログラミング

モジュール
使うモジュールは以下の通りです。
import PySimpleGUI as sg
import os
import openpyxl
import datetime

PySimpleGUIはGUIの設計、osはファイル操作、openpyxlでエクセルファイルの操作、datetimeで日付の取得です。
エクセルファイルの作成
 一番初めにアプリを使うときは、ファイルが存在しません。ですので、まずファイルを作成します。しかし、2回目以降はファイルが存在するため、同じようにファイルを作ると内容が白紙で上書きされます。従って、もしファイルが存在していればファイルを作る操作を行わないようにします。
 os.path.exists(file_name)はfime_nameが同じ階層にあればTrue、なけれがFalseを返します。

file_name = 'meibo.xlsx'
if os.path.exists(file_name) == False:
    book = openpyxl.Workbook()
    book.save(file_name)

1行目の設定
表の1行目ではその行が何の値なのか示す必要があります。
sheet['A1'] とすることで、A1に任意の値を入れることができます。
 これは何度上書きされても大丈夫なので、一回目とそれ以外で特に場合分けしません。

book = openpyxl.load_workbook(file_name)
sheet = book['Sheet']
sheet['A1'] = '作成日'
sheet['B1'] = '氏名'
sheet['C1'] = '性別'
sheet['D1'] = '電話'
book.save(file_name)

 ここまでを実行すると、
12.PNG

となり、行名が入ったことがわかります。

レイアウトの設定とGUIの生成
 layoutというリストを作成し、GUIの情報を書き込んで行きます。基本的に、リストのn番目の要素はそのままn行目として反映されます。
 そしてwhileループでイベントを検知するまでGUIの表示を続けるようにします。もし「確定」ボタンが押されれば、GUIを閉じます。

layout = [
    [sg.Text('名簿入力')],
    [sg.Text('名前', size=(15, 1)), sg.InputText('武田ヒロト')],
    [sg.Text('電話番号', size=(15, 1)), sg.InputText('123-4567-8901')],
    [sg.Text('性別',size=(15,1)),sg.Radio('男',group_id ='sex'),sg.Radio('女',group_id ='sex')],
    [sg.Submit(button_text='確定')]
]
window = sg.Window('名簿作成アプリ',layout)
while True:
    event,values = window.read()
    if event in (None,'確定'):
        break

ここまでを実行すると、以下のような画面を生成できます。
めいぼ.PNG

エクセルファイルに書き込む準備
 次に、入力された情報を取り出します。入力された情報はvaluesに入っているので、

name = values[0]
phone = values[1]
if values[2] == True:
    sex = "男"
else:
    sex = '女'

というようにして、情報を取り出します。
もし男を選択すると、valuesには

{0: '武田ヒロト', 1: '123-4567-8901', 2: True, 3: False}

という感じにデータが格納されます。もし"2"がTrueなら男ですし、Falseなら必然的に女です。
 日付は
time = datetime.date.today()
today = str(time.year) + '/' + str(time.month) + '/' + str(time.day)

というように処理します。datetime.today()はそのままだと2020-1-1というフォームで値を返すので、そのままエクセルファイルに書き込むと表示が汚くなります。時間を2020/1/1のようにスラッシュで区切るためにこのような形にします。

エクセルファイルに書き込み

 あとは取得した情報を書き込むだけです。
 最後の行に追加する必要がありますので、エクセルファイルの最後の行をsheet.max_rowを使って取得します。エクセルの中では1から行を数えますが、Pythonでは0から数えることに注意します。

book = openpyxl.load_workbook(file_name)
row = sheet.max_row +1
sheet = book['Sheet']
sheet['A'+str(row)] = today
sheet['B'+str(row)] = name
sheet['C'+str(row)] = sex
sheet['D'+str(row)] = phone
book.save(file_name)
print(values)
#GUIを閉じる
window.close()

ここまでを実行すると、
14.PNG

 このように、名簿に情報が記録されてます。
 さらに、

15.PNG

 と別の情報を入力すると、、、

16.PNG

 このように、後ろにきちんと情報が追加されていることが分かります。

プログラム全体

import PySimpleGUI as sg
import os
import openpyxl
import datetime
#エクセルファイルが無ければ作る
file_name = 'meibo.xlsx'
if os.path.exists(file_name) == False:
    book = openpyxl.Workbook()
    book.save(file_name)
#エクセルファイルの一行目を設定
book = openpyxl.load_workbook(file_name)
sheet = book['Sheet']
sheet['A1'] = '作成日'
sheet['B1'] = '氏名'
sheet['C1'] = '性別'
sheet['D1'] = '電話'
book.save(file_name)
#レイアウト定義
layout = [
    [sg.Text('名簿入力')],
    [sg.Text('名前', size=(15, 1)), sg.InputText('武田ヒロト')],
    [sg.Text('電話番号', size=(15, 1)), sg.InputText('123-4567-8901')],
    [sg.Text('性別',size=(15,1)),sg.Radio('男',group_id ='sex'),sg.Radio('女',group_id ='sex')],
    [sg.Submit(button_text='確定')]
]
window = sg.Window('名簿作成アプリ',layout)
#確定ボタンが押されるまで表示を続ける
while True:
    event,values = window.read()
    print(event,values)
    if event in (None,'確定'):
        break
#エクセルファイルに書き込むために変数を整理
name = values[0]
phone = values[1]
if values[2] == True:
    sex = "男"
else:
    sex = '女'
#時間を2020/1/1のようにスラッシュで区切る
time = datetime.date.today()
today = str(time.year) + '/' + str(time.month) + '/' + str(time.day)
#書き込み
book = openpyxl.load_workbook(file_name)
row = sheet.max_row +1
sheet = book['Sheet']
sheet['A'+str(row)] = today
sheet['B'+str(row)] = name
sheet['C'+str(row)] = sex
sheet['D'+str(row)] = phone
book.save(file_name)
#GUIを閉じる
window.close()
サービス数40万件のスキルマーケット、あなたにぴったりのサービスを探す