概要・目標
持ち運び用のノートPCにExcelをインストールしていないのでcsvファイルが表形式で照会できない。
スプレッドシートでの代用は可能だが、スプレッドシートで表示するにはネット接続が必要で、無駄なパケット通信をしたくない。
CSVファイルの照会だけならオフラインで十分。
色々とググっているとpythonのpandasライブラリでCSVファイルの読み込みやhtmlの出力もできることがわかった。
pythonの勉強を目的としてcsvファイルを読み込んでブラウザに表示するプログラムを作成する。
環境
- Windows10
- python 3.8.1
- VSCode
やること、やる順
- pandasをpipでインストールする
- pythonプログラムを作成する
- ブラウザで表示する
pandasをpipでインストールする
VSCodeのターミナルでお決まりのコマンド pip install pandas
を実行する。
なぜかエラー発生...ソース書く前に想定外のエラーを引くキャラなんで、これぐらいのエラーが発生することはお見通し。
(1)
ERROR: Could not install packages due to an EnvironmentError: [WinError 5] アクセスが拒否されました。: 'c:\\program files\\python38\\lib\\site-packages\\pip-19.2.3.dist-info\\entry_points.txt'
Consider using the `--user` option or check the permissions.
(2)
WARNING: You are using pip version 19.2.3, however version 19.3.1 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' command.
(1)・・・アクセスが拒否されましたやpermissionsって出てるからおそらく権限なんでしょうね。
VSCodeのターミナルは諦めて、コマンドプロンプトを管理者で起動してpipコマンドを実行すると正常にインストールできた。
(2)python3.8.1でインストールされたpipのバージョンが古いので警告が出ている。
''で表示されたコマンドを実行し、pipのアップグレードを(1)の実行前に実施した。
pythonプログラムを作成する
pandasのread_csv()でCSVファイルを読み込み、to_html()でCSVデータを
に変換し、htmlに書き込む。
読み込んだCSVファイルで空白がある場合は欠損値として扱かわれNaNに変換されるため、na_filter=False
で変換しないようにする。
htmlのタイトルにはCSVファイル名を表示する。
main.py
import os
import pandas as pd
import sys
def main():
# 引数1からCSVファイルを取得する
args = sys.argv
haserror = False
csvfile = ''
# 引数なしはエラーとする
if 1 == len(args):
print("CSVファイルが指定されていません。")
haserror = True
else:
csvfile = args[1]
# ファイル名が不正の場合はエラー
if os.path.exists(csvfile) == False:
print("指定したファイルは存在しません。")
haserror = True
# CSVファイルではない場合はエラーとする
if csvfile.endswith(".csv") == False:
print("CSVファイル以外が指定されています。")
haserror = True
if haserror == True:
return()
else:
print("CSVファイルをhtmlに変換します。")
# CSVファイル読み込み
csvdata = pd.read_csv(csvfile, na_filter=False)
# htmlファイル読み込み
htmldata = ''
with open('templete.html',mode='r',encoding='utf-8') as htmlfile:
htmldata = htmlfile.read()
# CSVファイルをhtmlに変換
rpdict = { "filename" : os.path.basename(csvfile), "table" : csvdata.to_html() }
htmldata = htmldata.format(**rpdict)
# htmlファイル出力
with open('csvconverted.html',mode='w',encoding='utf-8') as outputhtml:
outputhtml.write(htmldata)
if __name__== '__main__':
main()
変換前html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title> {filename} </title>
<link rel="stylesheet" type="text/css" href="style.css"/>
</head>
<body>
<div class="csvlist">
{table}
</div>
</body>
</html>
変換後html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title> test.csv </title>
<link rel="stylesheet" type="text/css" href="style.css"/>
</head>
<body>
<div class="csvlist">
<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>日付</th>
<th>休日区分</th>
<th>出勤時刻</th>
<th>退勤時刻</th>
<th>労働時間</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>2019/12/1</td>
<td>法休</td>
<td>09:00</td>
<td>13:00</td>
<td>04:00</td>
</tr>
<tr>
<th>1</th>
<td>2019/12/2</td>
<td></td>
<td>09:00</td>
<td>21:30</td>
<td>11:30</td>
</tr>
<tr>
<th>2</th>
<td>2019/12/3</td>
<td></td>
<td>09:00</td>
<td>21:30</td>
<td>11:30</td>
</tr>
<tr>
<th>3</th>
<td>2019/12/4</td>
<td></td>
<td>09:00</td>
<td>21:00</td>
<td>11:00</td>
</tr>
<tr>
<th>4</th>
<td>2019/12/5</td>
<td></td>
<td>09:00</td>
<td>20:00</td>
<td>10:00</td>
</tr>
<tr>
<th>5</th>
<td>2019/12/6</td>
<td></td>
<td>09:00</td>
<td>20:00</td>
<td>10:00</td>
</tr>
<tr>
<th>6</th>
<td>2019/12/7</td>
<td>公休</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th>7</th>
<td>2019/12/8</td>
<td>法休</td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
ふりかえり
- htmlファイルに出力されたCSVファイルの内容が文字化けしていた。open()でencoding指定していなかったため、デフォルト(shift-jis)の文字コードで処理されてしまう。encoding='utf-8'を指定して文字化けしないようにした。
- templete.htmlにてファイル名とcsv内容を出力するフィールドに対してformat()実行時にKeyErrorが発生した。当初はformat(key="")を2か所コーディングしていたが、1つずつformatすると対象文字列内から指定したkey項目に置換されるため、置換されなかったkey項目が存在してることをKeyErrorになっていた。formatの使い方は難しい・・・置換対象はkey-value形式のディクショナリ形式で宣言し、formatにはディクショナリを指定して置換すると正しく置換できた。
- read_csv()での実行結果が2次元配列型で参照できるため、扱いやすくてびっくりした。
製作物はこちら
https://github.com/otowmoyarng/FreeStudyRepo/tree/master/20191228-pythoncsvviewer