シフト、変換します！


###

###


###
こんにちは！前回

https://qiita.com/Nakagawa11210/items/2b5fac6f92a2dce63593

という記事を書いていた者です。
前の記事を読んでくださった方も、初めましての方も、よろしくお願いします！

さて、実は私、レジとサービスカウンターの仕事をしているのですが、あの特売日を教えてくれる Bot（↑の記事です）を作ってから、ふと思ったのです。
# 📝<font color="rainbo">**仕事でも使えるものを作りたい**</font>

　……と。

いう経緯で、この手作業を思い出しました！！

 実は今、現場ではシフト表の他に「ローテーション」という、各レジへ何時に誰に行ってもらうかが表示されたものがあります。
 
 この「ローテーション」には今日誰が何時に出勤するのかがパッと見てわからないため、シフト表から一日ずつ丁寧に「出勤する人の氏名」「勤務時間」を紙にちまちまと書いては貼り付けているのです。


 1日分ずつ手書きで書いていた物が、まとめてアプリが自動で書き込んでくれたら、うれしいですよね！

 そこで、（前置きが長くなりましたが）
 ### 💡シフト表から簡潔に「氏名」と「勤務時間」を抽出したものを出してくれるアプリを作りました！
ここにエクセルファイルをアップロードします！↓
 <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079343/bc46b337-3dff-4461-b402-3d96601254a2.png" width=80%>


入れたファイルの写真↓ （私の場合はこんなファイルを入れました。複数シートＯＫです！）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079343/0d261202-7d29-4074-9bdb-c47c8a0565fc.png" width=60%>


アプリが情報を抽出して表にしてくれた写真↓

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079343/d438f5dc-760a-48bc-a4ce-b470b63fd9a3.png" width=60%>


このボタンを押すと、エクセルファイルにしてくれます！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079343/c10ed204-d5dd-49a5-b165-ed11e7a52716.png" width=60%>


こんな感じです！（複数シートを読み取った場合でも、変換後は1シートにまとめて表示してくれます！）

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079343/ce02308a-e57e-4932-8b4d-9d590d8ec9a5.png" width=60%>


# <font color="rainb">**ペンを使わなくなりました（良い意味）**</font>
これを使ってみてから早数日、

 シフト表を用意する（印刷したもの）→（格子状になっている小さな紙があるので）名前を書く→勤務時間を書く（間違わないように！）→ローテーションに貼り付ける
 
から↓↓↓


 シフト表を用意する（データのままでOK）→アプリに入れる→ Excel 変換したものを印刷→切ってローテーションに貼り付ける

### 

このように今まで忙しい合間を縫って書いていた作業が大幅に短縮されました！
空いた時間で今回は、苦手な包装の練習（サービスカウンターの仕事もあるので）をしました！

ちなみにこのアプリ、まだまだデジタル初心者の私はどうやって作ったのかというと……


# <font color="rainb">**困ったときは聞いてみよう ChatGPT**</font>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079343/410ff634-b142-4dff-af90-5e9c77caccf2.png" width=80%>


はい。このように聞いてみました。

幸いシフトを作る際に使用しているツールは、ボタン一つで Excel ファイルに変換することができたので……

#### まずはファイルからどのような情報を読み取ることができるのかを確認しました。


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079343/35fda35c-f35c-4b5b-a1e6-35dc0874d500.png" width=80%>


そうして、まずは電子の世界にいる ChatGPT に希望通りの表を作ってもらった後、これをアプリとして作れるかを聞きました。
##


# 📌<font color="brown">**材料です。**</font>
今回は
・pandas / openpyxl
・Python
・Streamlit
・メモ帳
・コマンドプロンプト

を使用しました。
なぜ、今回 Streamlit を使用することにしたかというと、 ChatGPT にもアドバイスをもらった上で、アプリを作るのに「HTML/CSS/JS」を使わなくても、「Python」という一つの言語だけでサクッとできるという点に惹かれたからです。


以下、ChatGPT に教わった作り方です。
簡単に4つの手順で解説します。
## ① <font color="rainb">**環境を整える**</font>
[Python]( https://www.python.org/downloads/
 "Python公式サイト") と [Streamlit]( https://streamlit.io/
 "Python公式サイト") をインストールしたり、「pandas / openpyxl」を PC のコマンドプロンプトに入力することで、Excel ファイルを読み込んでくれるようにします。
 
 （ Python をインストールした時の画像です）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079343/84f96764-371d-46cc-928b-1e55174b2b34.png" width=60%>

 
## ② 💻<font color="rainb">**コードを書き込む**</font>
ローカルアプリなので、自分の PC にフォルダと中に一つファイルを作り、「メモ帳」に Python のコードを書きます。（コードは ChatGPT が出してくれます）

```ruby:qiita.rb
import streamlit as st
import pandas as pd
import io
from openpyxl import Workbook
from openpyxl.styles import Border, Side, Font, Alignment

st.set_page_config(page_title="勤務表抽出アプリ", page_icon="🗓️")
st.markdown("<h1 style='text-align: center; color: teal;'>✨ シフト、変換します！ ✨</h1>", unsafe_allow_html=True)

uploaded_file = st.file_uploader("Excelファイル（複数シートOK）をアップロードしてください", type="xlsx")

def extract_schedule(df):
    try:
        df_data = df.iloc[5:].copy()
        df_data.columns = df.iloc[3].tolist() + df.columns[len(df.iloc[3]):].tolist()
        df_schedule = df_data[['氏名', '勤務']].dropna()
        df_schedule = df_schedule[1:].reset_index(drop=True)
        df_schedule = df_schedule[
            ~(df_schedule['氏名'].astype(str).str.contains("氏名")) &
            ~(df_schedule['勤務'].astype(str).str.contains("勤務"))
        ].reset_index(drop=True)
        return df_schedule
    except:
        return None

if uploaded_file is not None:
    try:
        xls = pd.ExcelFile(uploaded_file)
        sheet_names = xls.sheet_names

        wb = Workbook()
        ws = wb.active
        ws.title = "勤務表まとめ"

        # スタイル
        border = Border(
            left=Side(style='thin'),
            right=Side(style='thin'),
            top=Side(style='thin'),
            bottom=Side(style='thin')
        )
        header_font = Font(bold=True)
        center = Alignment(horizontal='center')

        current_row = 1

        for sheet in sheet_names:
            df = xls.parse(sheet)
            schedule_df = extract_schedule(df)
            if schedule_df is not None:
                st.subheader(f"📅 {sheet} の勤務表")
                st.dataframe(schedule_df)

                # ▶ 日付タイトル（結合セルで見出し）
                ws.merge_cells(start_row=current_row, start_column=1, end_row=current_row, end_column=2)
                cell = ws.cell(row=current_row, column=1, value=f"▶ {sheet}")
                cell.font = header_font
                cell.alignment = center
                current_row += 1

                # ▶ ヘッダー行
                ws.cell(row=current_row, column=1, value="氏名").font = header_font
                ws.cell(row=current_row, column=2, value="勤務時間").font = header_font
                current_row += 1

                # ▶ データ行
                for _, row in schedule_df.iterrows():
                    ws.cell(row=current_row, column=1, value=row['氏名'])
                    ws.cell(row=current_row, column=2, value=row['勤務'])
                    current_row += 1

                # ▶ 罫線を追加
                for r in ws.iter_rows(min_row=current_row - len(schedule_df), max_row=current_row - 1, min_col=1, max_col=2):
                    for cell in r:
                        cell.border = border

                # ▶ 最後に 2 行あける
                current_row += 2

            else:
                st.error(f"❌ シート「{sheet}」の勤務表を抽出できませんでした")

        # Excelデータをダウンロードできるように
        output = io.BytesIO()
        wb.save(output)

        st.download_button(
            label="📥 日付付き勤務表をダウンロード",
            data=output.getvalue(),
            file_name="勤務表_まとめ.xlsx",
            mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
        )

    except Exception as e:
        st.error(f"❌ エラーが発生しました: {e}")

```



## ③ <font color="rainb">**実行する**</font>
あとはコマンドプロンプトに「cd "PC上のフォルダの場所"streamlit run app.py」を入力すれば、自動的にサイトを開いてくれます！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079343/b7635f92-9ddd-434d-982a-a809a8744997.png" width=60%>


## ④<font color="rainb">**整える**</font>
アプリを使うたびにコマンドプロンプトに入力して開くのは大変なので、デスクトップにショートカットを作り、クリックするだけでアプリを開けるようにします！

そのためには、この Python で書かれているアプリのプログラムを「exe化」、つまり Python 環境なしでも実行可能にする必要があります。
参考にしたのはこちらのサイトです。

[Python のスクリプトを Pyinstallerでexe 化する方法]( https://techplay.jp/column/1646
 "https://techplay.jp/column/1646")

そうして exe 化したものを、
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079343/e2d3dd40-5d08-42ea-acf9-ba5e2c1cb283.png" width=60%>


（ Windows の場合）
アプリの中にある（ exe 化すると自動的に作成される）「 dist 」フォルダを開く
➡中の run_streamlit を 右クリック「その他のオプションを確認」
➡「送る（ N ）」
➡「デスクトップ（ショートカットを作成）」を押すことで、デスクトップに表示されます！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079343/4de876ad-f935-4ad6-8f57-22afa289e258.png" width=60%>

###
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079343/ad1b5d9f-1cce-4953-b272-1b6b5142b561.png" width=60%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079343/e8656d6d-4cbb-422a-acc4-c7eced4f5bb7.png" width=80%>

ということで、完成です✨



 # 🚀<font color="rainb">**心残り**</font>

ちょっと悔しかったので載せますが……
本来はアプリを作るにあたり、インストール不要、リアルタイムで変化していく「CodePen」で、大まかな見た目のバランスと簡単なデータを読み込むアプリの試作を作ってみてから、 Streamlit でしっかり作りこんでいこうと思っていたのですが、（言語の置き換えは ChatGPT が助けてくれるので）HTML、CSS、JS の3項目のうち、JSの部分がうまくいかず、何度試してもエラーに……


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079343/690bc701-6e19-4eb3-baec-94caa8288384.png" width=60%>



こちらもコードは ChatGPT に教わりながら作っていました。
また、ファイル読み込みのために使用していた JavaScript のエラー処理も結局どう対応すれば良かったのかわかりませんでした……


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079343/a170fdba-4722-4cef-a179-13e625942938.png" width=60%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079343/059bb530-889a-42ca-8922-33f908c917fe.png" width=60%>


初心者にはエラーの特定や対処に対し、自分でもよくわかっていないまま指示文を出してしまうため、結果的に質問の質が落ちてしまいます。そこが ChatGPT を頼っていて難しいところでした……

ということでこの方法も、もう少し勉強を進めた後にリトライしてみようと考えています！

## 参考文献

この記事は以下の情報を参考にして執筆しました。

- [Python のスクリプトを Pyinstallerでexe 化する方法](https://techplay.jp/column/1646)
- 

### 

ここまで読んでいただき、ありがとうございました！！