使用Python對Excel工作簿中的所有工作表分別求和并自動生成結(jié)果
1. 問題背景:幾十個 Sheet 都要合計,手工做很痛苦
這一篇繼續(xù)整理《超簡單:用 Python 讓 Excel 飛起來》第 6 章中的案例內(nèi)容,主題是 對一個工作簿中的所有工作表分別求和。這個場景非常貼近真實辦公:一個 Excel 工作簿里按月份、部門、項目或區(qū)域拆了很多 Sheet,每張表結(jié)構(gòu)類似,都有一列金額,現(xiàn)在需要分別計算每張表的合計值。
手工當然也能做。打開第一張表,找到金額列,寫一個 SUM;再打開第二張表,重復一次;幾十張表下來,本質(zhì)就是重復點鼠標、重復復制公式、重復檢查結(jié)果。表少的時候還能忍,表一多就容易漏算、錯算、重復算。
這張圖展示了本文的整體主題:使用 Python 對一個工作簿中的所有工作表分別求和,并自動生成結(jié)果。

從這張圖中可以看出,本文的重點不是單獨計算某一個 Sheet,而是把“遍歷所有 Sheet → 指定列求和 → 寫回合計結(jié)果 → 生成匯總表”做成一條完整自動化流程。真正有價值的不是 sum() 這一個函數(shù),而是把求和任務變成可重復執(zhí)行的批處理模板。
這里最容易犯的錯誤,是把這個案例理解成簡單求和。實際工作中更麻煩的是:有的 Sheet 是空表,有的 Sheet 缺少目標列,有的金額看起來是數(shù)字,其實是文本,還有的工作簿已經(jīng)存在“匯總”Sheet。腳本要能處理這些邊界,才算真正可用。
2. 目標效果:運行一次腳本想看到什么
這個案例的目標效果可以拆成兩層。第一層是在每張業(yè)務工作表底部自動追加一行 合計,并把指定金額列的合計值寫進去。第二層是額外生成一個 匯總 工作表,把每張 Sheet 的合計結(jié)果集中展示出來。
這張圖展示了第一層效果:腳本會在每張工作表底部自動寫入合計行。

從這張圖中可以看出,合計結(jié)果不是覆蓋原始數(shù)據(jù),而是追加在表格末尾。這個設(shè)計比較穩(wěn),因為原數(shù)據(jù)結(jié)構(gòu)不會被破壞,讀者打開每張表時,也能直接看到該表自己的合計結(jié)果。
推薦把合計結(jié)果寫在表尾,而不是直接插入到數(shù)據(jù)中間。這樣既方便閱讀,也減少破壞原有數(shù)據(jù)結(jié)構(gòu)的風險。如果后續(xù)要再次處理原始明細,表尾合計行也更容易識別和排除。
最終我們希望得到這樣的交付結(jié)果:
1. 每張業(yè)務 Sheet:
- 表尾追加“合計”行
- 指定金額列寫入合計值
2. 匯總 Sheet:
- 列出每張工作表名稱
- 列出每張表的金額合計
- 最后一行給出總計
這套輸出適合交付領(lǐng)導或業(yè)務同事:既能看每張表的局部結(jié)果,也能在匯總表里橫向?qū)Ρ人?Sheet。
3. 實現(xiàn)思路:把求和變成標準化流水線
要想讓腳本穩(wěn)定,就不能只盯著“求和”這一步。完整流程應該是:打開工作簿,遍歷所有工作表,讀取表格數(shù)據(jù),清洗金額列,計算合計,寫回當前 Sheet,記錄到匯總列表,最后生成匯總 Sheet 并保存。
這張圖展示了自動求和的完整流程,從打開工作簿到生成匯總表,每一步都對應腳本中的關(guān)鍵動作。

從這張圖中可以看出,一個可靠的自動化腳本必須具備“遍歷、清洗、計算、寫回、匯總”五個動作。如果缺少清洗,金額可能算錯;如果缺少寫回,單表結(jié)果不直觀;如果缺少匯總,領(lǐng)導仍然看不到整體對比。
我把這一節(jié)理解成一個可復用模塊。輸入是工作簿路徑和要合計的列名,輸出是每個 Sheet 的合計行和一個總匯總表。后續(xù)如果要計算最大值、最小值、平均值,其實也能沿用同一套框架,只是把計算函數(shù)換掉。
4. 環(huán)境準備:pandas 負責計算,xlwings 負責寫回 Excel
這個案例里我使用的組合是 pandas + xlwings。其中 pandas 負責數(shù)據(jù)讀取后的計算和清洗,xlwings 負責打開工作簿、遍歷工作表、把結(jié)果寫回 Excel。
pandas 擅長算數(shù)據(jù),xlwings 擅長操作 Excel 應用。這兩個工具組合在一起,適合處理這種“既要計算,又要寫回原工作簿結(jié)構(gòu)”的任務。
安裝命令如下:
pip install pandas xlwings
如果你的電腦沒有安裝 Excel,或者 Excel 被安全策略、加載項、彈窗卡住,xlwings 可能無法正常工作。這不是 Python 語法問題,而是 Excel 應用環(huán)境問題。在企業(yè)桌面環(huán)境中,這一點要提前確認。
推薦先復制一份測試工作簿,不要直接對正式文件運行腳本。尤其是腳本涉及寫回、保存、另存為這些動作時,先用樣本文件跑通,再處理正式數(shù)據(jù)。
5. 完整代碼:對所有 Sheet 分別求和并生成匯總表
下面這份代碼是一個相對完整的版本,重點考慮了幾個真實場景:自動跳過空表,自動跳過缺少目標列的 Sheet,自動跳過 匯總 Sheet,金額列支持 ¥12,345.67 這類文本數(shù)字,寫回時只在表尾追加合計行,不覆蓋原始明細數(shù)據(jù)。
import pandas as pd
import xlwings as xw
def clean_to_number(s: pd.Series) -> pd.Series:
"""
把帶貨幣符號、逗號、空格的文本金額轉(zhuǎn)換成數(shù)值。
例如:¥12,345.67 -> 12345.67
"""
s = s.astype(str).str.strip()
s = s.str.replace(",", "", regex=False)
s = s.str.replace(r"[¥¥$ ]", "", regex=True)
s = s.str.replace(r"[^0-9\.\-]", "", regex=True)
return pd.to_numeric(s, errors="coerce")
def sum_all_sheets_in_workbook(
input_xlsx: str,
sum_col: str = "銷售利潤",
summary_sheet_name: str = "匯總",
start_cell: str = "A1",
save_as: str | None = None,
) -> None:
"""
對一個工作簿中的所有工作表分別對 sum_col 求和:
1. 在每個 Sheet 末尾追加“合計”行
2. 生成或覆蓋一個“匯總”Sheet,列出每個 Sheet 的合計和總計
save_as=None:覆蓋保存原文件
save_as=路徑:另存為新文件
"""
app = xw.App(visible=False, add_book=False)
app.display_alerts = False
app.screen_updating = False
try:
wb = app.books.open(input_xlsx)
results = []
for sht in wb.sheets:
# 跳過匯總 Sheet,避免二次運行時把匯總表也拿去求和
if sht.name == summary_sheet_name:
continue
rng = sht.range(start_cell).expand("table")
if rng.value is None:
print(f"[SKIP] {sht.name}: 空表")
continue
df = rng.options(pd.DataFrame).value
if df is None or df.empty:
print(f"[SKIP] {sht.name}: 無有效數(shù)據(jù)")
continue
if sum_col not in df.columns:
print(f"[SKIP] {sht.name}: 缺少列 '{sum_col}'")
continue
# 清洗金額列并求和
num = clean_to_number(df[sum_col]).fillna(0)
total = float(num.sum())
# 寫回:在當前表格最后一行下面追加合計行
last_cell = rng.last_cell
total_row = last_cell.row + 1
# 找到 sum_col 在表格中的列序號,xlwings 使用 1-based 列號
col_idx = df.columns.get_loc(sum_col) + 1
sht.range((total_row, 1)).value = "合計"
sht.range((total_row, col_idx)).value = total
# 給合計行加粗,便于閱讀
try:
sht.range((total_row, 1), (total_row, col_idx)).api.Font.Bold = True
except Exception:
pass
results.append({
"工作表": sht.name,
f"{sum_col}合計": total
})
print(f"[OK] {sht.name}: {sum_col} 合計 = {total}")
# 生成匯總 Sheet
summary_df = pd.DataFrame(results)
if summary_df.empty:
raise RuntimeError("未得到任何可匯總結(jié)果,請檢查列名、數(shù)據(jù)區(qū)域或是否為空表。")
total_col = f"{sum_col}合計"
grand_total = float(summary_df[total_col].sum())
summary_df = summary_df.sort_values(by=total_col, ascending=False)
# 如果已存在匯總 Sheet,則清空;不存在則新建
try:
sum_sht = wb.sheets[summary_sheet_name]
sum_sht.clear()
except Exception:
sum_sht = wb.sheets.add(summary_sheet_name, before=wb.sheets[0])
sum_sht.range("A1").options(index=False).value = summary_df
# 寫入總計
last = sum_sht.range("A1").expand("table").last_cell
total_row = last.row + 1
sum_sht.range((total_row, 1)).value = "總計"
sum_sht.range((total_row, 2)).value = grand_total
try:
sum_sht.range((1, 1), (total_row, 2)).api.Columns.AutoFit()
sum_sht.range((total_row, 1), (total_row, 2)).api.Font.Bold = True
except Exception:
pass
if save_as:
wb.save(save_as)
print(f"[DONE] 已另存為:{save_as}")
else:
wb.save()
print(f"[DONE] 已覆蓋保存:{input_xlsx}")
wb.close()
finally:
app.quit()
if __name__ == "__main__":
sum_all_sheets_in_workbook(
input_xlsx="產(chǎn)品銷售統(tǒng)計表.xlsx",
sum_col="銷售利潤",
summary_sheet_name="匯總",
start_cell="A1",
save_as="產(chǎn)品銷售統(tǒng)計表_已求和.xlsx",
)
這份代碼的結(jié)構(gòu)并不復雜,但邊界處理比較重要。它不是簡單讀取所有 Sheet 后直接求和,而是先排除匯總表,再判斷是否為空表,再判斷目標列是否存在,最后才進入金額清洗和求和邏輯。
如果你直接把所有 Sheet 都拿來求和,下一次運行腳本時,匯總表也可能被重復計算,結(jié)果會越來越怪。所以跳過 summary_sheet_name 不是錦上添花,而是必須保留的安全判斷。
6. 關(guān)鍵點拆解:金額列看著像數(shù)字,其實可能是字符串
這個案例最容易翻車的地方,不是 sum() 不會用,而是金額列的數(shù)據(jù)類型不穩(wěn)定。Excel 里很多金額看起來像數(shù)字,但實際可能是文本,例如 ¥12,345.67、12,345、 8000 ,甚至混有空格和貨幣符號。
這張圖展示了金額清洗的核心過程:把原始金額文本去掉符號、逗號和無效字符,再轉(zhuǎn)換成真正可以求和的數(shù)值。

從這張圖中可以看出,求和前的關(guān)鍵動作是“清洗轉(zhuǎn)換”。如果金額列沒有先轉(zhuǎn)成數(shù)值,腳本可能得到 0、NaN,或者產(chǎn)生錯誤結(jié)果。這類問題表面上像是計算錯誤,實際上是數(shù)據(jù)類型問題。
清洗函數(shù)的核心代碼如下:
def clean_to_number(s: pd.Series) -> pd.Series:
s = s.astype(str).str.strip()
s = s.str.replace(",", "", regex=False)
s = s.str.replace(r"[¥¥$ ]", "", regex=True)
s = s.str.replace(r"[^0-9\.\-]", "", regex=True)
return pd.to_numeric(s, errors="coerce")
這段代碼做了四件事:第一,把數(shù)據(jù)統(tǒng)一轉(zhuǎn)成字符串;第二,去掉逗號;第三,去掉人民幣符號、美元符號和空格;第四,只保留數(shù)字、小數(shù)點和負號,再用 pd.to_numeric() 轉(zhuǎn)成數(shù)值。
涉及金額統(tǒng)計時,我建議永遠先做類型清洗,再做求和。不要相信 Excel 里“看起來像數(shù)字”的顯示效果。腳本處理的是底層數(shù)據(jù)類型,不是你眼睛看到的表格樣式。
7. 效果驗證:如何確認腳本真的成功
腳本運行完成,不代表結(jié)果一定正確。對這種批量求和腳本,至少要驗證三件事:每張業(yè)務 Sheet 是否寫入了合計行;匯總 Sheet 是否生成;匯總 Sheet 的總計是否等于各 Sheet 合計之和。
這張圖展示了最終匯總效果:多個工作表的合計結(jié)果集中到一張匯總表中,并可以橫向?qū)Ρ取?/p>

從這張圖中可以看出,匯總表不只是把結(jié)果堆在一起,它還承擔了橫向?qū)Ρ鹊淖饔?。哪個部門、哪個月份、哪個項目金額最高,一眼就能看出來。這才是自動生成匯總表的真正價值:減少人工統(tǒng)計,也減少人工解釋。
建議驗證時按下面幾個點檢查:
1. 打開每個業(yè)務 Sheet,確認表尾是否出現(xiàn)“合計”行
2. 檢查目標金額列是否寫入正確合計值
3. 打開“匯總”Sheet,確認每張表都有一條匯總記錄
4. 檢查“總計”是否等于所有 Sheet 合計之和
5. 抽查 1 到 2 張 Sheet,用 Excel 自帶 SUM 手工核對一次
如果想在腳本中增加簡單驗證,也可以打印每個 Sheet 的處理日志:
print(f"[OK] {sht.name}: {sum_col} 合計 = {total}")
推薦保留控制臺日志。批量腳本不應該靜默運行。哪些 Sheet 成功、哪些 Sheet 跳過、跳過原因是什么,都應該能從日志里看出來。這是后續(xù)復盤和排錯的基礎(chǔ)。
8. 常見問題與踩坑記錄
8.1 expand(“table”) 依賴連續(xù)表格
sht.range(start_cell).expand("table") 的好處是方便,它會從起始單元格自動擴展讀取連續(xù)區(qū)域。但它也有前提:表格中間不能有完全空白行或空白列。
如果你的表格中間有空行,expand 可能讀不全。這種情況下,建議先統(tǒng)一模板,或者改成固定讀取范圍,例如 A1:H2000。
8.2 匯總 Sheet 必須跳過
如果腳本第一次運行后生成了 匯總 Sheet,第二次再運行時,如果不跳過它,腳本可能會把匯總表也當成業(yè)務表繼續(xù)求和。
if sht.name == summary_sheet_name:
continue
這行代碼非常關(guān)鍵。只要腳本會生成結(jié)果 Sheet,就應該在遍歷時明確跳過結(jié)果 Sheet。
8.3 不要默認每張表都有目標列
真實工作簿里經(jīng)常會出現(xiàn)模板不統(tǒng)一的問題。有的 Sheet 叫 銷售利潤,有的可能叫 利潤 或 銷售金額。如果不判斷列名,腳本會直接報錯。
if sum_col not in df.columns:
print(f"[SKIP] {sht.name}: 缺少列 '{sum_col}'")
continue
這個判斷的意義,是讓異常 Sheet 被識別并跳過,而不是讓一個異常 Sheet 中斷整個工作簿的處理。
8.4 不建議直接覆蓋原文件
雖然代碼支持 save_as=None 覆蓋保存原文件,但我不建議初次使用時這么做。尤其是腳本會寫回每張表、生成匯總 Sheet,一旦邏輯有誤,原文件就可能被污染。
推薦使用另存為模式:
save_as="產(chǎn)品銷售統(tǒng)計表_已求和.xlsx"
這樣原始文件不會被破壞,處理結(jié)果也更方便對比。
9. 總結(jié)提升:這節(jié)真正要學的是批量計算框架
這一節(jié)看起來只是對每張工作表求和,但真正值得帶走的是一套批量計算框架:遍歷 Sheet、識別目標列、清洗數(shù)據(jù)、執(zhí)行計算、寫回結(jié)果、生成匯總表、最后驗證輸出。
如果只會寫 sum(),遇到真實辦公數(shù)據(jù)很快就會卡??;如果理解了這套流程,后續(xù)要做最大值、最小值、平均值、按條件求和、多列匯總,其實都是在同一個框架上替換計算邏輯。
辦公自動化腳本的價值,不是讓代碼看起來復雜,而是讓重復動作變得穩(wěn)定、可驗證、可復盤。這一點比單純記住某個函數(shù)更重要。
最后再提醒一次:批量寫回 Excel 前一定要先備份。自動化腳本跑得越快,錯誤擴散得也越快。先用樣本文件測試,確認合計行、匯總表、總計結(jié)果都正確,再處理正式工作簿。
以上就是使用Python對Excel工作簿中的所有工作表分別求和并自動生成結(jié)果的詳細內(nèi)容,更多關(guān)于Python Excel工作表求和的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
YOLOv5目標檢測之a(chǎn)nchor設(shè)定
在訓練yolo網(wǎng)絡(luò)檢測目標時,需要根據(jù)待檢測目標的位置大小分布情況對anchor進行調(diào)整,使其檢測效果盡可能提高,下面這篇文章主要給大家介紹了關(guān)于YOLOv5目標檢測之a(chǎn)nchor設(shè)定的相關(guān)資料,需要的朋友可以參考下2022-05-05
PyCharm新建項目時如何配置項目的Python解釋器詳解
在PyCharm中配置Python環(huán)境是開發(fā)者日常工作中的一項重要任務,尤其當接手已有項目時,這篇文章主要給大家介紹了關(guān)于PyCharm新建項目時如何配置項目的Python解釋器的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2025-06-06
Python輸出漢字字庫及將文字轉(zhuǎn)換為圖片的方法
這篇文章主要介紹了Python輸出漢字字庫及將文字轉(zhuǎn)換為圖片的方法,分別用到了codecs模塊和pygame模塊,需要的朋友可以參考下2016-06-06
關(guān)于Numpy中argsort()函數(shù)的用法解讀
這篇文章主要介紹了關(guān)于Numpy中argsort()函數(shù)的用法解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06
Django中使用haystack+whoosh實現(xiàn)搜索功能

