2-04 / Series
2-04 № 04 · 2026

処理は Excel の外、
Python と Flet の側に。

マクロ・グラフ・ピボットを Python に出し、画面は Flet で被せる

処理は、Excel の中ではなく Python の側に置く。

2-03: 土台を据える ── SQLite・PostgreSQL・pgvector・DuckDB・Polars でデータの置き場を据えた。この章では、その上のデータを実際に動かす。Excel と Word に埋まったマクロ・VBA・グラフ・ピボットを Python に出し、人が触る画面が要るところには Flet を被せる。

要るのは、書く能力ではなく使う能力だ

これまでの常識では、プログラミングを学ぶとは、文法を覚え、アルゴリズムを設計し、コードを書けるようになることだった。

いまは違う。何を処理したいかを言葉にし、AI にコードを書いてもらい、実行し、結果を確かめる。要るのは 使う能力 だ。

Excel の関数を覚える時間と、Python を AI に書いてもらえるようになる時間を比べれば、後者のほうがはるかに短い。そして Excel の関数は Excel の中で効くが、Python はあらゆるデータに効く。

書く能力ではなく、使う能力。これが新しいリテラシーである。

コードを書く能力は要らない。読める能力で足りる。読めれば、返ってきたコードが正しそうかどうかは判断できる。エラーが出たら、そのエラー文をそのまま貼って渡せば、原因と修正版が返る。エラーは終わりではなく、次の指示の入力だ。

flowchart LR Want["やりたい処理
(日本語で説明)"] AI(("AI")) Code["Python コード"] Run["実行"] Out["結果
確認"] Err["エラー文"] Want -->|頼む| AI AI -->|書く| Code Code --> Run Run -->|成功| Out Run -->|失敗| Err Err -->|貼り付け| AI classDef good fill:#e8f5e9,stroke:#7a9a6d,color:#3a4d34 classDef bad fill:#fef3e7,stroke:#c89559,color:#5a3f1a class Want,Out good class AI,Code,Err bad

頼むときのこつは三つだ。入力と出力を明示する。一つずつ頼む。結果を見て直す。「orders.xlsx を読んで、商品ごとの売上合計を summary.json に書き出して」と、入口と出口の形が決まっていれば、AI は迷わない。

Excel と Word に埋まった処理を、Python に出す

自立編で Office から離れるとき、最後まで残る問題が、*Excel と Word の中に埋まった業務ロジック* だ。マクロ、VBA、グラフ、ピボット ── この四つを Python に外部化する。ここが最初の一手になる。

VBA の中身は、たいてい「セルからデータを読む → 何か計算する → 別のセルに書く」の組み合わせだ。これは Polars で素直に書き換えられる。

  1. Excel の VBA エディタ(Alt + F11)を開く
  2. モジュールのコードをコピーして AI に渡す
  3. 「これを Polars + Python に書き換えて」と頼む
  4. 返ってきたコードを JupyterLab のセルに貼って Shift+Enter
import polars as pl

df = pl.read_excel("orders.xlsx", sheet_name="raw")
result = (
    df.filter(pl.col("status") == "確定")
      .group_by("customer")
      .agg(total=(pl.col("qty") * pl.col("price")).sum())
      .sort("total", descending=True)
)
result.write_excel("monthly_summary.xlsx")

Excel はやめなくてよい。Polars は .xlsx を直接読み書きし、書式を保ったまま編集したいときは openpyxl を使う。原則は一つだけある ── .xlsx のまま扱うことだ。CSV に落とすと、書式も数式も体裁も一緒に落ちる。

Word と PowerPoint にも VBA はいる

VBA は Excel だけの話ではない。Word にも同じように埋まっている。差し込み印刷の自動化、テンプレートからの文書生成、書式の一括変換、配ったフォームの回収と集計 ── どれも Python に出せる。

PowerPoint のマクロも同じだ。python-pptx で外に出せる。

先に出すほど、後が軽い

VBA は、Excel 互換の表計算ソフトではそのまま動かない。Office からの乗り換えで一番大きな問題は、ここにある。処理を Python に出してしまえば、ファイルの側は「データ + レイアウト」だけになり、2-07: 文書を取り戻す ── 読む物は adoc、触る表は格子、刷る紙はテンプレート の持ち方にそのまま乗る。

外に出す理由は、乗り換えだけではない。

そして、守りの理由がある。*VBA は、2022 年までメール添付によるマルウェアの主な入口だった*。日本で最も広がった Emotet は、マクロ付きの Excel や Word を添付し、「コンテンツの有効化」を押させて感染した(JPCERT/CC、2022 年 2 月の注意喚起)。 Microsoft は 2022 年 7 月から、インターネットから届いたファイルのマクロを Windows の Office で既定で止め、添付のマクロを使う攻撃は約 66% 減った(Proofpoint、2022 年 7 月)。だが止まるのは、外から届いたファイルだけだ。業務ロジックを VBA に置いている限り、社内ではマクロを有効にし続け、「有効化」を押す習慣が残る。処理を Python に出せば、マクロを有効にする理由そのものが無くなる。

「VBA を Python に書き換えるのは大変では」と思うかもしれない。渡し方はコピーと貼り付けだけだ。

JupyterLab を入れる ── 標準は uv、科学計算は Miniforge

Python を使うには実行環境が要る。事務の仕事に最も合う入口は JupyterLab だ。ブラウザで動く「Python のスプレッドシート」で、セルに Python を書いて Shift+Enter、その場で結果が出る。Excel のセルに =SUM(A1:A100) と書いて Enter を押すのと同じ感覚だ。

Excel のピボットテーブルとの違いは、残るものにある。

Python 本体とライブラリの入れ方は、用途で二択だ。

入れ方 適している用途 特徴
uv(標準) 日常の Python、CLI ツール、Web、業務スクリプト、Polars / FastAPI / 文書まわり 圧倒的に速い。Rust 製で、PyPI を素直に扱う。uv tool install で配れる
Miniforge(DS/科学計算) データ分析、機械学習、画像処理、科学計算、GPU(numpy / scipy / scikit-learn / pytorch / tensorflow / gdal など) conda-forge を既定で使う FLOSS 版 conda。複雑な C/C++/Fortran 依存をコンパイル済みバイナリで配る

まず uv から入れる。ほとんどの場面はこれで足りる。

# Mac / Linux:公式インストーラ(Windows は PowerShell の一行)
curl -LsSf https://astral.sh/uv/install.sh | sh

uv init tools && cd tools          # 仕事用の Python の環境を一つ作る
uv add jupyterlab polars altair    # 入れる。以降の章の道具も、ここに足す
uv run jupyter lab                 # 開く

ブラウザが開き、新しいノートブックを作って、セルに書いて Shift+Enter。ここまでだ。この環境が、この連載の Python の置き場になる。2-03 の DuckDB も、ここに足す。

uv で行き詰まるのは、科学計算まわりが多い。numpy / scipy / pytorch / tensorflow のビルドが手元で失敗する(BLAS / LAPACK / CUDA との結合)、GIS 系 (gdal、rasterio)や生物系で C/C++ 依存が膨大になる、GPU の深層学習で CUDA の版を揃える必要がある ── このときは Miniforge に切り替える。Anaconda の商用条項に縛られず、 conda の依存解決の強さだけを使える。

# Miniforge(完全 FLOSS)
curl -L -O https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh
bash Miniforge3-*.sh

# 以後はこれで環境を作る
conda create -n ds jupyterlab polars numpy scipy scikit-learn
conda activate ds

迷ったら uv。uv のエラーが続いたら Miniforge。どちらも AI が同じように扱える ── 「uv で入れて」「conda で入れて」と頼めば、それぞれの作法でコマンドが返る。

ピボットと VLOOKUP を、Polars のコードにする

JupyterLab に Polars を組み合わせると、Excel でピボットテーブル・VLOOKUP・IF・フィルタでやっていた操作が、そのままコードになる。

Excel で Polars で
ピボットテーブル(行・列・値) df.pivot(...) または df.group_by(...).agg(...)
VLOOKUP / XLOOKUP df.join(other, on="...")
IF / IFS(計算列) df.with_columns(...) + pl.when().then().otherwise()
フィルタ df.filter(...)
ソート df.sort(...)
重複削除 df.unique(...)
累積合計・前月比 ウィンドウ関数(cum_sum、shift、pct_change)

月別商品別のクロス集計は、Excel なら行に「商品」、列に「月」、値に「売上」をマウスでドラッグして数分。翌月はもう一度同じマウスを動かす。Polars なら二行だ。

df = pl.read_excel("orders.xlsx")
df.pivot(values="price", index="item", on="month", aggregate_function="sum")

セルで Shift+Enter、下にクロス集計表が出る。翌月は再実行するだけだ。 VLOOKUP の置き換えも同じ形になる。

orders   = pl.read_excel("orders.xlsx")
products = pl.read_excel("products.xlsx")

orders.join(products, on="item_id", how="left")

複数の列で結合するときも on=["item_id", "date"] と並べるだけだ。条件で計算列を足すのも、上から順に when().then() を足していく形になる。ネストした IF を数えながら書く必要は無くなる。

文法は覚えなくてよい。「orders.xlsx を読んで、商品ごとの月別売上を集計、上位 10 商品だけを取り出して、前月比のパーセントも付けて」と日本語で頼めば、Polars のコードが返る。

グラフは matplotlib と Altair で描く

可視化に使うライブラリは二つある。

matplotlib は、何でも描ける事実上の標準だ。折れ線・棒・散布・ヒストグラム・ヒートマップ・3D・地図・出版品質の図まで、二十年を超える蓄積がある(初版は 2003 年)。機能は最大で、書き方は長い。

Altair は、「この列を X 軸、この列を Y 軸、この列で色分け」と宣言的に書く。 Vega-Lite が土台で、出力はそのままインタラクティブな HTML になる。ズーム、ホバー、選択が標準で付いてくる。

import altair as alt
import polars as pl

df = pl.read_excel("orders.xlsx")
alt.Chart(df).mark_bar().encode(
    x="item",
    y="qty:Q",
    color="month",
)

JupyterLab のセルで Shift+Enter、下に積み上げ棒グラフが出る。Excel で同じ図を作るなら、ピボット、グラフ、凡例の調整で数分かかる。ここでは六行だ。

どちらのライブラリも、人が文法を覚えるのは骨が折れる。だから覚えない。「orders.xlsx の月別売上を、商品ごとに色分けした積み上げ棒グラフで。凡例は右上、 Y 軸は 100 万単位で」と頼み、返ってきた図を見て「色をもっと落ち着いた色に」と返す。これで済む。

Excel のグラフ機能との違いは、毎月の再生成と再現性に出る。マウス操作は記録が残らず、翌月もう一度同じ手を動かすことになる。コードは記録として残り、Git に入り、 python report.py で PNG も SVG も HTML も出る。

人のための入出力を、基幹から剥がす

ここからが、この章の要になる。

基幹システム(ERP、業務システム、データウェアハウス)は、組織で共有するデータの 記録元 として残す。そこは触らない。しかし、次の四つは記録元の役目ではない。

これらは 人にとっての入出力 だ。基幹から剥がして、手元の JupyterLab と Python と SQLite に降ろす。基幹とは、API か JSON / Parquet のエクスポートで読み書きするだけの関係になる。

負荷の面からも、分けたほうが速い

基幹システムは記録元として最適化されている。小さく速いトランザクション、インデックスで一行を引く処理が中心だ(OLTP)。一方、帳票・グラフ・集計は真逆の性質を持つ。数百万行をスキャンして集約し、複数のテーブルを結合する、長く重いクエリだ(OLAP)。

この二つを同じシステムの上で動かすと、こうなる。

必要なデータを基幹から定期的に SQLite / Parquet にエクスポートし(または API で読み出し)、手元で集計と帳票化をすれば、基幹には読み出しだけの軽い負荷しか掛からない。集計は手元で何度でも回せる。集計は Polars と DuckDB の仕事だ(2-03)。

*人のための入出力を手元に降ろすことは、生産性の話であると同時に、基幹を守る負荷分離でもある。* この分離があるから、2-12: API を作る ── FastAPI で基幹のロジックを出す の基幹書き換えは、記録元だけを相手にする小さな仕事になる。

手元に降りてくるもの

剥がすと、組織が抱えていた複雑さの一部が要らなくなる。

請求書の発行も、同じ形で降りる

会計ソフトや ERP の画面で出していた請求書も、同じ形をしている。会計そのもの (仕訳・税務)は会計ソフトに残し、降ろすのは発行の側だ。

百通の請求書 PDF を月末に一括生成し、メール送信まで Python で書ける。cron で日時を決めて回す。データは手元に残る。見積書、契約書、月次レポート、商品カタログ、納品書 ── 同じ構造で書けるものは、すべて基幹から手元へ降りる。

個人の生産性向上は、組織の単純化に直結する。一人 + AI が、これまで基幹システムと専門部門で支えていた仕事を、順に引き取っていく。

道具は CLI から始め、Flet へ伸ばす

手元に降ろした処理を、人が使う道具の形にする。ここで最初から Flutter や React Native や Swift を選ばない。三つの層を、下から順に登る。

層 道具 役目
第一層 CLI ツール(Python) 処理本体を書いて、動かして、確かめる
第二層 Flet アプリ(Python) 画面が要るときに、Python のまま GUI を載せる
第三層 Flutter アプリ(Dart) Flet の部品で足りないときだけ
flowchart TB Start(["新しい道具を作る"]) L1["第一層: CLI ツール(Python)
処理本体・確認"] Q1{"画面が要るか"} Done1(["uv tool install で配る"]) L2["第二層: Flet アプリ(Python)
Mac / Win / Linux / Web / iOS / Android"] Q2{"Flet で足りるか"} Done2(["各 OS の実行ファイルか
ストアで配る"]) L3["第三層: Flutter アプリ(Dart)
Flet の部品で足りないとき"] Start --> L1 --> Q1 Q1 -->|不要| Done1 Q1 -->|必要| L2 --> Q2 Q2 -->|足りる| Done2 Q2 -->|足りない| L3 classDef good fill:#e8f5e9,stroke:#7a9a6d,color:#3a4d34 classDef bad fill:#fef3e7,stroke:#c89559,color:#5a3f1a class L1,L2 good class L3 bad

アプリの本体は、入力を取って、処理して、出力することだ。だから最初に書くのはコマンドラインツールになる。テストしやすく、直しやすく、AI が書きやすい。動くようになったら、それで配れる ── uv tool install <ツール名> で、Python が入っているすべての OS に届く。データを処理する、ファイルを変換する、API を叩く。この種の道具は、第一層で完結する。

第二層に上がるのは、操作する人が技術者ではないとき、視覚的な手応えが要るとき、入力欄が複数あるときだ。

Flet を選ぶ理由は、同じ Python が全部の画面で動くことだ

Flet は、Python で書く GUI フレームワークだ。内側で Flutter のレンダリングエンジンを使うが、書くのは Python だけになる。第一層で書いた CLI の処理を、ほぼそのまま画面に載せられる。

import flet as ft

@ft.component
def Greeting():
    name, set_name = ft.use_state("")
    return ft.Column([
        ft.TextField(label="名前", on_change=lambda e: set_name(e.control.value)),
        ft.Text(f"こんにちは、{name}さん" if name else ""),
    ])

ft.run(lambda page: page.render(Greeting))

テキスト欄と表示領域のある GUI が、これで動く。*同じコードが、Mac でも Windows でも Linux でも、Web ブラウザでも、iOS / Android でも動く*。この連載で作る道具の画面は、 Flet を既定にする。

道具立ての軽さも効く。Flutter の開発環境(Android Studio・SDK・Xcode)が要らず、 Flet は Python の環境だけで足りる(Flutter の側は、配る形に組むときだけ展開される)。 CLI で動く処理に Flet の画面を足す追加の手間は、ライブラリの導入と数十行のコードだ。

現場で動く道具の形

第一層・第二層で完結する道具を、いくつか挙げる。

CLI で足りるもの

Flet で画面を被せるもの

Flet は、Mac・Windows・Linux の実行ファイルも、App Store と Play Store に出す形も作れる(flet build)。第三層の Flutter に上がるのは、Flet の部品で足りない画面が要るときだけだ。社内や自分のための道具なら、第一層か第二層で足りる。

どれも、この章の Python と 2-03 の SQLite をそのまま使う。新しい枠組みを覚え直す必要は無い。

flet-mcp が、いまの版の書き方を渡す

Flet には MCP サーバ(flet-mcp)がある。AI の MCP 設定にこれを足すと、AI は 手元に入っている版 のドキュメントをその場で引ける。

これが効くのは、GUI のフレームワークが最も版で変わる場所だからだ。学習データの中にある古い書き方をそのまま出してしまうと、動かないコードから始めることになる。flet-mcp があると、AI は書く前にいまの書き方を確かめる。古い書き方が出にくくなる。

やることは、MCP の設定に flet-mcp を足して、AI に「Flet の書き方は MCP で確かめてから書いて」と伝えることだけだ。この一手間が、Flet を連載の既定の画面にできる理由でもある。

確かめ方

この章は、次の五つができていれば済みだ。

  1. ブラウザで JupyterLab が開き、セルに import polars と書いて Shift+Enter が通る
  2. 手元の .xlsx を Polars が読み、商品別・月別のクロス集計が画面に表で出る
  3. 同じノートブックで Altair の図が描かれ、マウスを乗せると値が出る
  4. 基幹から出したデータだけで月次の帳票が作れて、基幹に触らずに何度でも作り直せる
  5. Flet のアプリが手元の画面で立ち上がり、同じコードが Web ブラウザでも開く
uv run jupyter lab
uv run python -c "import polars, altair, flet; print('ok')"

人が持つ物

人が渡す値

AI が「やる前に言う」操作

確かめた版と日付

まとめ

処理を、Excel の中から Python の側へ。

ここで身につけた Python は、この先の章でそのまま使う。次章では、その道具とアプリの前に門番を置く。PocketBase で認証を一つにまとめ、どのアプリも同じ入口を通るようにする。


関連記事