excel-automation
macOS上でExcelファイルの作成・解析・操作を行うスキル。openpyxlによるプロフェッショナルなフォーマット、投資銀行の財務モデル向けに標準ライブラリのzipfile+xmlを使った複雑なxlsmファイルの解析、およびAppleScriptによるExcelウィンドウ制御に対応。フォーマット済みのExcelレポート作成、openpyxlでは処理できない財務モデルの解析、macOS上でのExcel自動化が必要な場面で活用する。
description の原文を見る
Create, parse, and control Excel files on macOS. Professional formatting with openpyxl, complex xlsm parsing with stdlib zipfile+xml for investment bank financial models, and Excel window control via AppleScript. Use when creating formatted Excel reports, parsing financial models that openpyxl cannot handle, or automating Excel on macOS.
SKILL.md 本文
Excel オートメーション
プロフェッショナルな Excel ファイルを作成し、複雑な財務モデルを解析し、macOS で Excel を制御します。
クイックスタート
# フォーマット済み Excel レポートを作成
uv run --with openpyxl scripts/create_formatted_excel.py output.xlsx
# openpyxl が処理できない複雑な xlsm を解析
uv run scripts/parse_complex_excel.py model.xlsm # シート一覧表示
uv run scripts/parse_complex_excel.py model.xlsm "DCF" # シート抽出
uv run scripts/parse_complex_excel.py model.xlsm --fix # 破損した名前を修正
# AppleScript で Excel を制御(ハング防止のためタイムアウト付き)
timeout 5 osascript -e 'tell application "Microsoft Excel" to activate'
概要
3 つの機能:
| 機能 | ツール | 使用時期 |
|---|---|---|
| 作成 フォーマット済み Excel | openpyxl | レポート、モックアップ、ダッシュボード |
| 解析 複雑な xlsm/xlsx | zipfile + xml.etree | 財務モデル、VBA ワークブック、>1MB ファイル |
| 制御 Excel ウィンドウ | AppleScript (osascript) | ズーム、スクロール、セル選択をプログラム的に実行 |
ツール選択の判定木
ファイルがシンプル(データエクスポート、VBA なし、<1MB)?
├─ はい → openpyxl または pandas
└─ いいえ
├─ .xlsm または投資銀行製 / >1MB?
│ └─ はい → zipfile + xml.etree.ElementTree (stdlib)
└─ 本当の .xls(BIFF 形式)?
└─ はい → xlrd
「複雑な」Excel の特徴: ファイル >1MB、.xlsm 拡張子、投資銀行/ブローカー製、VBA マクロ含む。
重要: 最初に必ず file <path> を実行してください — 拡張子は嘘をつくことがあります。.xls ファイルが実は ZIP ベースの xlsx かもしれません。
Excel ファイル作成(openpyxl)
プロフェッショナルカラー規約(投資銀行標準)
| 色 | RGB コード | 意味 |
|---|---|---|
| Blue | 0000FF | ユーザー入力 / 仮定値 |
| Black | 000000 | 計算値 |
| Green | 008000 | クロスシート参照 |
| White on dark blue | FFFFFF on 4472C4 | セクションヘッダー |
| Dark blue text | 1F4E79 | タイトル |
コアフォーマッティングパターン
from openpyxl.styles import Font, PatternFill, Border, Side, Alignment
# フォント
BLUE_FONT = Font(color="0000FF", size=10, name="Calibri")
BLACK_FONT_BOLD = Font(color="000000", size=10, name="Calibri", bold=True)
GREEN_FONT = Font(color="008000", size=10, name="Calibri")
HEADER_FONT = Font(color="FFFFFF", size=12, name="Calibri", bold=True)
# 塗りつぶし
DARK_BLUE_FILL = PatternFill("solid", fgColor="4472C4")
LIGHT_BLUE_FILL = PatternFill("solid", fgColor="D9E1F2")
INPUT_GREEN_FILL = PatternFill("solid", fgColor="E2EFDA")
LIGHT_GRAY_FILL = PatternFill("solid", fgColor="F2F2F2")
# 枠線
THIN_BORDER = Border(bottom=Side(style="thin", color="B2B2B2"))
BOTTOM_DOUBLE = Border(bottom=Side(style="double", color="000000"))
数値フォーマットコード
| フォーマット | コード | 例 |
|---|---|---|
| 通貨 | '$#,##0' | $1,234 |
| 通貨(小数点付き) | '$#,##0.00' | $1,234.56 |
| パーセンテージ | '0.0%' | 12.3% |
| パーセンテージ(2 小数点) | '0.00%' | 12.34% |
| カンマ付き数値 | '#,##0' | 1,234 |
| 倍数 | '0.0x' | 1.5x |
条件付き書式(感応度テーブル)
感応度分析用の赤から緑のグラデーション:
from openpyxl.formatting.rule import ColorScaleRule
rule = ColorScaleRule(
start_type="min", start_color="F8696B", # Red (low)
mid_type="percentile", mid_value=50, mid_color="FFEB84", # Yellow (mid)
end_type="max", end_color="63BE7B" # Green (high)
)
ws.conditional_formatting.add(f"B2:F6", rule)
実行
uv run --with openpyxl scripts/create_formatted_excel.py
完全なテンプレートスクリプト: scripts/create_formatted_excel.py を参照
複雑な Excel の解析(zipfile + xml)
openpyxl が複雑な xlsm ファイル(破損した DefinedNames、複雑な VBA)で失敗した場合、stdlib を直接使用します。
XLSX 内部 ZIP 構造
file.xlsx (ZIP アーカイブ)
├── [Content_Types].xml
├── xl/
│ ├── workbook.xml ← シート名 + 順序
│ ├── sharedStrings.xml ← すべてのテキスト値(ルックアップテーブル)
│ ├── worksheets/
│ │ ├── sheet1.xml ← シート 1 のセルデータ
│ │ ├── sheet2.xml ← シート 2 のセルデータ
│ │ └── ...
│ └── _rels/
│ └── workbook.xml.rels ← rId → sheetN.xml のマッピング
└── _rels/.rels
シート名解決(2 ステップ)
workbook.xml のシート名は _rels/workbook.xml.rels を通じて物理ファイルにリンクされます:
import zipfile
import xml.etree.ElementTree as ET
MAIN_NS = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'
REL_NS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'
RELS_NS = 'http://schemas.openxmlformats.org/package/2006/relationships'
def get_sheet_path(zf, sheet_name):
"""シート名を ZIP 内の物理 XML ファイルパスに解決します。"""
# ステップ 1: workbook.xml → シート名の rId を検索
wb_xml = ET.fromstring(zf.read('xl/workbook.xml'))
sheets = wb_xml.findall(f'.//{{{MAIN_NS}}}sheet')
rid = None
for s in sheets:
if s.get('name') == sheet_name:
rid = s.get(f'{{{REL_NS}}}id')
break
if not rid:
raise ValueError(f"Sheet '{sheet_name}' not found")
# ステップ 2: workbook.xml.rels → rId をファイルパスにマップ
rels_xml = ET.fromstring(zf.read('xl/_rels/workbook.xml.rels'))
for rel in rels_xml.findall(f'{{{RELS_NS}}}Relationship'):
if rel.get('Id') == rid:
return 'xl/' + rel.get('Target')
raise ValueError(f"No file mapping for {rid}")
セルデータ抽出
def extract_cells(zf, sheet_path):
"""シート XML からすべてのセル値を抽出します。"""
# 共有文字列ルックアップを構築
shared = []
try:
ss_xml = ET.fromstring(zf.read('xl/sharedStrings.xml'))
for si in ss_xml.findall(f'{{{MAIN_NS}}}si'):
texts = si.itertext()
shared.append(''.join(texts))
except KeyError:
pass # 共有文字列なし
# シートセルを解析
sheet_xml = ET.fromstring(zf.read(sheet_path))
rows = sheet_xml.findall(f'.//{{{MAIN_NS}}}row')
data = {}
for row in rows:
for cell in row.findall(f'{{{MAIN_NS}}}c'):
ref = cell.get('r') # 例:"A1"
cell_type = cell.get('t') # "s" = 共有文字列、None = 数値
val_el = cell.find(f'{{{MAIN_NS}}}v')
if val_el is not None and val_el.text:
if cell_type == 's':
data[ref] = shared[int(val_el.text)]
else:
try:
data[ref] = float(val_el.text)
except ValueError:
data[ref] = val_el.text
return data
破損した DefinedNames の修正
投資銀行の xlsm ファイルはしばしば「Formula removed」を含む破損した <definedName> エントリを持っています:
def fix_defined_names(zf_in_path, zf_out_path):
"""破損した DefinedNames を削除して再パッケージ化します。"""
import shutil, tempfile
with tempfile.TemporaryDirectory() as tmp:
tmp = Path(tmp)
with zipfile.ZipFile(zf_in_path, 'r') as zf:
zf.extractall(tmp)
wb_xml_path = tmp / 'xl' / 'workbook.xml'
tree = ET.parse(wb_xml_path)
root = tree.getroot()
ns = {'main': MAIN_NS}
defined_names = root.find('.//main:definedNames', ns)
if defined_names is not None:
for name in list(defined_names):
if name.text and "Formula removed" in name.text:
defined_names.remove(name)
tree.write(wb_xml_path, encoding='utf-8', xml_declaration=True)
with zipfile.ZipFile(zf_out_path, 'w', zipfile.ZIP_DEFLATED) as zf:
for fp in tmp.rglob('*'):
if fp.is_file():
zf.write(fp, fp.relative_to(tmp))
完全なテンプレートスクリプト: scripts/parse_complex_excel.py を参照
macOS での Excel 制御(AppleScript)
すべてのコマンドは macOS の Microsoft Excel で検証済みです。
検証済みコマンド
# Excel をアクティベート(前面に表示)
osascript -e 'tell application "Microsoft Excel" to activate'
# ファイルを開く
osascript -e 'tell application "Microsoft Excel" to open POSIX file "/path/to/file.xlsx"'
# ズームレベルを設定(パーセンテージ)
osascript -e 'tell application "Microsoft Excel"
set zoom of active window to 120
end tell'
# 特定の行にスクロール
osascript -e 'tell application "Microsoft Excel"
set scroll row of active window to 45
end tell'
# 特定の列にスクロール
osascript -e 'tell application "Microsoft Excel"
set scroll column of active window to 3
end tell'
# セル範囲を選択
osascript -e 'tell application "Microsoft Excel"
select range "A1" of active sheet
end tell'
# 特定のシートを名前で選択
osascript -e 'tell application "Microsoft Excel"
activate object sheet "DCF" of active workbook
end tell'
タイミングとタイムアウト
AppleScript コマンドと後続の操作(例:スクリーンショット)の間に sleep 1 を常に追加して、UI レンダリングを許可してください。
重要: Excel が実行されていないか応答していない場合、osascript は無期限にハングします。常に timeout でラップしてください:
# 安全なパターン:5 秒タイムアウト
timeout 5 osascript -e 'tell application "Microsoft Excel" to activate'
# 終了コードを確認:124 = タイムアウト
if [ $? -eq 124 ]; then
echo "Excel が応答していません — 実行中ですか?"
fi
よくある間違い
| 間違い | 修正 |
|---|---|
| openpyxl が複雑な xlsm で失敗 → モンキーパッチを試みる | 即座に zipfile + xml.etree に切り替え |
中国語文字を wc -c でカウント | wc -m を使用(文字数、バイト数ではなく;中国語 = 3 バイト/文字) |
| ファイル拡張子を信頼 | 最初に file <path> を実行して実形式を確認 |
openpyxl load_workbook が大きい xlsm でハング | ワークブック全体を読み込む代わりに zipfile で対象抽出を使用 |
重要な注記
- Python スクリプトは
uv run --with openpyxlで実行(システム Python は使用しないでください) - LibreOffice(
soffice --headless)はフォーマット変換と数式再計算が可能です - 詳細なフォーマット参照:
references/formatting-reference.mdを参照
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- daymade
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/daymade/claude-code-skills / ライセンス: MIT
関連スキル
hugging-face-trackio
Trackioを使用してMLトレーニング実験を追跡・可視化できます。トレーニング中のメトリクスログ記録(Python API)、トレーニング診断のアラート発火、ログされたメトリクスの取得・分析(CLI)が必要な場合に活用してください。リアルタイムダッシュボード表示、Webhookを使用したアラート、HF Space同期、自動化向けのJSON出力に対応しています。
btc-bottom-model
ビットコインのサイクルタイミングモデルで、加重スコアリングシステムを搭載しています。日次パルス(4指標、32ポイント)とウィークリー構造(9指標、68ポイント)の2カテゴリーにわたる13の指標を追跡し、0~100のマーケットヒートスコアを算出します。ETFフロー、ファンディングレート、ロング/ショート比率、恐怖・貪欲指数、LTH-MVRV、NUPL、SOPR(LTH+STH)、LTH供給率、移動平均倍率(365日MA、200週MA)、週次RSI、出来高トレンドに対応します。市場サイクル全体を通じて買いと売りの両方の推奨を提供します。ビットコインの底値拾い、BTCサイクルポジション、買い時・売り時、オンチェーン指標、MVRV、NUPL、SOPR、LTH動向、ETFの流出入、ファンディングレート、恐怖指数、ビットコインが過熱状態か、マイナーコスト、暗号資産市場のセンチメント、BTCのポジションサイジング、「今ビットコインを買うべきか」「BTCが天井をつけているか」「オンチェーン指標は何を示しているか」といった質問の際にこのスキルを活用します。
protein_solubility_optimization
タンパク質の溶解性最適化 - タンパク質の溶解性を最適化します。タンパク質の特性を計算し、溶解性と親水性を予測し、有効な変異を提案します。タンパク質配列の特性計算、タンパク質機能の予測、親水性計算、ゼロショット配列予測を含むタンパク質エンジニアリング業務に使用できます。3つのSCPサーバーから4つのツールを統合しています。
research-lookup
Parallel Chat APIまたはPerplexity sonar-pro-searchを使用して、最新の研究情報を検索できます。学術論文の検索にも対応しています。クエリは自動的に最適なバックエンドにルーティングされるため、論文の検索、研究データの収集、科学情報の検証に活用できます。
tree-formatting
ggtree(R)またはiTOL(ウェブ)を使用して、系統樹の可視化とフォーマットを行います。系統樹を図として描画する際、ツリーレイアウトの選択、分類学に基づく枝やラベルの色付け、クレードの折りたたみ、サポート値の表示、またはツリーへのオーバーレイ追加が必要な場合に使用してください。系統推定(protein-phylogenyスキルを使用)やドメイン注釈(今後の独立したスキル)には使用しないでください。
querying-indonesian-gov-data
インドネシア政府の50以上のAPIとデータソースに接続できます。BPJPH(ハラール認証)、BOM(食品安全)、OJK(金融適正性)、BPS(統計)、BMKG(気象・地震)、インドネシア中央銀行(為替レート)、IDX(株式)、CKAN公開データポータル、pasal.id(第三者法MCP)に対応しています。インドネシア政府データを活用したアプリ開発、.go.idウェブサイトのスクレイピング、ハラール認証の確認、企業の法的適正性の検証、金融機関ステータスの照会、またはインドネシアMCPサーバーへの接続時に使用できます。CSRF処理、CKAN API使用方法、IP制限回避など、すぐに実行可能なPythonパターンを含んでいます。