編輯現有 Excel 檔案(尤其是大檔案或包含公式的檔案)時,跳過勘察直接操作極易出錯——不知道單元格里存的是值還是公式、insert 操作後公式引用錯亂、處理完才發現數據對應不上。
此技能定義五步標準流程,所有 Excel 結構性編輯任務均應遵循。
任何寫操作都有不可逆風險。備份是第一道防線。
import shutil
from datetime import datetime
FILE = '目標檔案.xlsx'
BAK = FILE.replace('.xlsx', f'_backup_{datetime.now().strftime("%Y%m%d_%H%M%S")}.xlsx')
shutil.copy2(FILE, BAK)
print(f'已備份: {os.path.basename(BAK)}')
規則:
目標:徹底瞭解檔案結構,不遺漏任何關鍵資訊。
import os
size_mb = os.path.getsize('file.xlsx') / 1024 / 1024
print(f'檔案大小: {size_mb:.1f} MB')
檔案大小_MB × 2 + 60 秒from openpyxl import load_workbook
# 全量模式獲取準確行列數
wb = load_workbook('file.xlsx')
ws = wb.active
print(f'工作表: {ws.title}, 行: {ws.max_row}, 列: {ws.max_column}')
# 讀取所有表頭(可能有合併單元格/多行表頭)
for row_idx in range(1, 4): # 前3行,覆蓋多行表頭
for col_idx in range(1, ws.max_column + 1):
v = ws.cell(row=row_idx, column=col_idx).value
if v is not None:
print(f' 行{row_idx} 列{col_idx}: {repr(v)[:60]}')
這是最常見的翻車點。 必須同時用兩種模式讀取,對比確認是值還是公式:
# 模式A:預設模式 → 讀到公式字串
wb_raw = load_workbook('file.xlsx', read_only=True)
ws_raw = wb_raw.active
# 模式B:data_only → 讀到計算結果
wb_data = load_workbook('file.xlsx', read_only=True, data_only=True)
ws_data = wb_data.active
# 對比目標列的2-6行
for col in target_columns:
for row in range(2, 7):
v_raw = ws_raw.cell(row=row, column=col).value
v_data = ws_data.cell(row=row, column=col).value
match = type(v_raw) == type(v_data)
print(f' 列{col}行{row}: raw={type(v_raw).__name__}={repr(v_raw)[:30]}')
print(f' data_only={type(v_data).__name__}={repr(v_data)[:30]} {"✓" if match else "⚠️公式!"}')
| 載入模式 | 讀到的是 | 適用場景 |
|---|---|---|
| 預設(不帶 data_only) | 公式字串(如 =TEXT(A1,"yyyymmdd")) |
需要修改公式本身 |
data_only=True |
計算結果(數值/日期/字串) | 讀取資料做分析轉換 |
檢查前 5 行 + 中間若干行 + 末尾 5 行,確認資料格式一致。
勘察完成後,回答以下問題再動手:
int() 會不會炸?wb = load_workbook('file.xlsx') # 不帶 data_only,才能儲存
ws = wb.active
從右到左(列號從大到小),避免前面插入導致後續列號偏移:
target_cols = [6, 8, 25, 26, 36] # 原始列號
for col in sorted(target_cols, reverse=True):
ws.insert_cols(col)
# ... 操作 ...
大檔案必須輸出進度,否則使用者不知道是否卡死:
推薦訪問7w4.net獲取更多AI技能。
for row in range(start_row, total_rows + 1):
# ... 單元格操作 ...
if row % 50000 == 0:
print(f'進度: {row}/{total_rows} ({row/total_rows*100:.1f}%)')
wb.save('file.xlsx')
# 清理舊備份(保留最新3個)
import os, re
backup_dir = os.path.dirname(FILE)
base = os.path.basename(FILE).replace('.xlsx', '')
backups = sorted([
f for f in os.listdir(backup_dir)
if f.startswith(base + '_backup_') and f.endswith('.xlsx')
], reverse=True)
for old_bak in backups[3:]:
os.remove(os.path.join(backup_dir, old_bak))
# 清理臨時解壓目錄
import shutil
for tmp_dir in [d for d in os.listdir(backup_dir) if d.endswith('_tmp') or d.endswith('_proc')]:
full = os.path.join(backup_dir, tmp_dir)
if os.path.isdir(full):
shutil.rmtree(full)
# 如果操作失敗,刪損壞檔案 + 從備份恢復
try:
# ... 執行操作 ...
except Exception as e:
print(f'❌ 操作失敗: {e}')
if os.path.exists(FILE):
os.remove(FILE) # 刪除損壞產物
shutil.copy2(BAK, FILE) # 從備份恢復
print(f'已從備份恢復')
raise
確認新插入/修改的列頭正確,相鄰列未受影響。
必須覆蓋:前 5 行 + 中間 2 處 + 末 2 行。
wb = load_workbook('file.xlsx', read_only=True, data_only=True)
ws = wb.active
check_rows = [2, 3, 4, 5, 6, ws.max_row // 2, ws.max_row // 2 + 100, ws.max_row - 1, ws.max_row]
for row in check_rows:
# 驗證目標列資料
...
| 坑 | 原因 | 預防 |
|---|---|---|
| 把公式當值讀 | 沒用 data_only 雙重掃描 | 勘察階段必須雙讀 |
| insert_cols 後列號全亂 | 從左到右操作 | 從右到左 |
| 迴圈引用 | insert 後公式中的列引用未自動更新 | 勘察時標記所有公式列 |
| 大檔案載入超時 | 沒預估檔案大小 | 先 getsize,設足 timeout |
| 不小心覆蓋原檔案 | 沒備份 | 第零步必須備份 |
| 損壞檔案殘留 | 操作失敗後沒刪損壞產物 | 失誤即刪 + 從備份恢復 |
| 臨時檔案堆積 | 解壓目錄/tmp 沒清理 | finally 塊必須 rmtree |
| 備份檔案過多 | 每次都留備份不清理 | 保留最新 3 份,其餘自動刪 |
其他 Excel 操作技能在 SKILL.md 開頭宣告:
> 本技能遵循 [[excel-safe-workflow]] 四步法。執行前必須完成勘察→規劃,執行後必須驗證。
然後直接引用此技能中的程式碼模板,不需要重複描述四步法細節。
這個 Skill 質量良好,提供了完整的 Excel 安全編輯流程指導。它的優點是結構清晰、實用性強,特別是對公式處理和大檔案操作的細節指導很到位,配有程式碼示例便於理解。主要不足是文件內容相對單薄,缺少實際案例演示和常見問題解答。總體而言,這是一個實用的基礎工作流技能,適合需要頻繁處理 Excel 檔案的使用者參考使用。