4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[備忘録] GradioでExcel風インターフェースを実装してみる

Last updated at Posted at 2025-04-26

GradioでExcel風インターフェースの画面を実装してみたの備忘録です。

細かい機能や操作性はまだ改善の余地がありますが、データテーブルで情報を確認・編集したり、エクスポート・インポートしたりするユースケースに活用できそうです。完全にExcelと互換というわけではありませんが、シンプルなデータ操作ツールとして機能します。このような操作したいケースもあるのでは・・・?

画面例

image.png

テーブルのセルの値を編集することができる
行、列の追加、削除もできる

image.png

ファイルを読み込んだときの例、ファイル出力もある

環境準備

pip install "gradio>=3.15,<4" pandas openpyxl

実装

image.png

import gradio as gr
import pandas as pd
import os
import tempfile
import uuid

# サンプルデータ作成
def create_sample_data():
    data = {
        '商品名': ['製品A', '製品B', '製品C', '製品D', '製品E'],
        '価格': [1000, 2000, 1500, 3000, 2500],
        '在庫数': [10, 5, 15, 8, 12],
        '入荷日': ['2025-01-01', '2025-01-15', '2025-02-01', '2025-02-15', '2025-03-01']
    }
    df = pd.DataFrame(data)
    # 日付列を適切なデータ型に変換
    df["入荷日"] = pd.to_datetime(df["入荷日"]).dt.date
    return df

def excel_like_app():
    with gr.Blocks() as app:
        gr.Markdown("# GradioによるExcel風インターフェース")
        
        # 状態管理(元データとフィルタリング結果を保持)
        state = gr.State(value={
            "data": create_sample_data(),
            "filtered_data": None
        })
        
        # ファイル操作UI
        with gr.Row():
            file_input = gr.File(label="インポート", type="filepath")
            import_btn = gr.Button("読み込む")
            export_btn = gr.Button("エクスポート")
            file_output = gr.File(label="エクスポート結果")
        
        # フィルタリング・ソートUI
        with gr.Row():
            with gr.Column(scale=1):
                filter_col = gr.Dropdown(choices=create_sample_data().columns.tolist(), label="フィルター列")
                filter_val = gr.Textbox(label="フィルター値")
                apply_filter = gr.Button("フィルター適用")
                reset_filter = gr.Button("リセット")
            
            with gr.Column(scale=1):
                sort_col = gr.Dropdown(choices=create_sample_data().columns.tolist(), label="並べ替え列")
                sort_asc = gr.Checkbox(label="昇順", value=True)
                apply_sort = gr.Button("並べ替え適用")
        
        # データフレーム
        df = gr.Dataframe(
            value=create_sample_data(),
            datatype=["str", "number", "number", "date"],
            interactive=True
        )
        
        # 機能説明
        with gr.Accordion("使い方", open=False):
            gr.Markdown("""
            - **編集**: セルをクリックして直接編集(右クリックで行の追加・削除なども可能)
            - **フィルタリング**: 列と値を指定して「フィルター適用」
            - **並べ替え**: 列と順序を指定して「並べ替え適用」
            - **インポート/エクスポート**: Excelファイルの読み込み・保存
            """)
        
        # フィルタリング関数
        def filter_data(state, column, value):
            if not column or not value:
                return state["data"], state
            
            df = state["data"]
            filtered_df = df[df[column].astype(str).str.contains(value, case=False)]
            state["filtered_data"] = filtered_df
            return filtered_df, state
        
        # フィルターリセット関数
        def reset_filter_data(state):
            state["filtered_data"] = None
            return state["data"], state
        
        # 並べ替え関数
        def sort_data(state, column, ascending):
            if not column:
                return state["data"], state
                
            df = state["filtered_data"] if state["filtered_data"] is not None else state["data"].copy()
            sorted_df = df.sort_values(by=column, ascending=ascending)
            
            if state["filtered_data"] is not None:
                state["filtered_data"] = sorted_df
            
            return sorted_df, state
        
        # エクスポート関数
        def export_to_excel(df):
            if df is None or len(df) == 0:
                return None
                
            # 一時ファイル作成(ユニークなファイル名)
            temp_dir = tempfile.gettempdir()
            unique_id = uuid.uuid4().hex[:8]
            output_path = os.path.join(temp_dir, f"excel_export_{unique_id}.xlsx")
            
            # Excelファイルに保存
            df.to_excel(output_path, index=False)
            
            return output_path
        
        # インポート関数
        def import_from_excel(file):
            if file is None:
                return create_sample_data(), {"data": create_sample_data(), "filtered_data": None}
                
            try:
                df = pd.read_excel(file)
                return df, {"data": df, "filtered_data": None}
            except Exception as e:
                print(f"インポートエラー: {e}")
                return create_sample_data(), {"data": create_sample_data(), "filtered_data": None}
        
        # イベントハンドラーの設定
        apply_filter.click(
            fn=filter_data,
            inputs=[state, filter_col, filter_val],
            outputs=[df, state]
        )
        
        reset_filter.click(
            fn=reset_filter_data,
            inputs=[state],
            outputs=[df, state]
        )
        
        apply_sort.click(
            fn=sort_data,
            inputs=[state, sort_col, sort_asc],
            outputs=[df, state]
        )
        
        export_btn.click(
            fn=export_to_excel,
            inputs=[df],
            outputs=[file_output]
        )
        
        import_btn.click(
            fn=import_from_excel,
            inputs=[file_input],
            outputs=[df, state]
        )
    
    return app

# アプリケーション起動
if __name__ == "__main__":
    app = excel_like_app()
    app.launch()

解説

image.png

1. 基本構造

このアプリはGradioのBlocksインターフェースを使用して構築されています。主要コンポーネントは以下の通りです:

  • インタラクティブなDataframe: interactive=Trueを設定することでセル編集が可能になります
  • 状態管理: gr.Stateを使って元データとフィルタリング結果を保持します
  • UI要素: ファイル操作、フィルタリング、ソート用のコントロールを配置しています

2. 主要機能の実装ポイント

フィルタリング機能

フィルタリング機能は、特定の列の値が指定された文字列を含むかどうかを確認します。filtered_dataという状態変数に結果を保存することで、複数の操作(例:フィルタリング後のソート)を可能にしています。

ソート機能

ソート機能は、現在表示されているデータ(フィルタリング済みまたは元データ)を指定された列でソートします。

ファイル入出力

  • エクスポート: 現在のデータフレームをExcelファイルとして保存します
  • インポート: Excelファイルからデータを読み込み、データフレームと状態を更新します

データ編集

セルを直接クリックして編集できます。また、Dataframeコンポーネントの右クリックメニューから行の追加、削除、コピーなどの操作が可能です。

3. 実装上の注意点

  • Gradioのバージョン: 3.15以降でinteractive=Trueが安定して動作します
  • データ型の設定: datatype=["str", "number", "number", "date"]でUIの挙動を最適化
  • 状態管理の設計: gr.Stateを使った状態管理が、複合操作のキーポイントです
  • エラー処理: 特にファイル操作時には適切なエラー処理が重要です
  • UI設計: gr.Rowgr.Columnでレイアウトを調整できます

このシンプルな実装をベースに、独自の機能を追加したり、より複雑なデータ処理を組み込んだりすることが可能です。

参考情報

免責事項

本記事の作成にあたり、文章・図解の生成に生成AIを活用しました。最終的な編集と確認は筆者が行っています。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?