與解除保護(hù):分層解析與實(shí)戰(zhàn)指南)
用 Python 給 Excel 文件加保護(hù)、解除保護(hù)是辦公自動(dòng)化里看著簡(jiǎn)單、實(shí)際容易踩坑的一類需求。我最早接這類任務(wù)時(shí)以為只是調(diào)一個(gè) lock 開(kāi)關(guān)結(jié)果發(fā)現(xiàn) Excel 里至少有三種不同的“保護(hù)”文件打開(kāi)密碼、工作簿結(jié)構(gòu)保護(hù)、工作表單元格鎖定。它們處理邏輯不一樣用的 Python 庫(kù)也不一樣一旦混在一起腳本很容易變成一堆異常補(bǔ)丁。這篇文章想幫你把問(wèn)題理清楚先判斷你要保護(hù)的是哪一層再?zèng)Q定用什么工具最后順著單文件到批量、加鎖到解鎖、正常流程到排錯(cuò)這條線落地。下面寫(xiě)到的代碼和步驟我自己在 Windows 和 Linux 環(huán)境都驗(yàn)證過(guò)主要路徑但每個(gè)環(huán)境的 Excel 版本、依賴版本不一定相同你落地時(shí)應(yīng)該先用一個(gè)小文件跑通再往正式文件上鋪。1. 先分清要保護(hù)的到底是哪一層文件、工作簿還是單元格很多人打開(kāi) Excel 的“保護(hù)”按鈕時(shí)會(huì)看到一串菜單保護(hù)工作表、保護(hù)工作簿、用密碼加密、標(biāo)記為最終狀態(tài)。這些功能名字接近實(shí)際用途差別很大。如果你一開(kāi)始沒(méi)分清后面寫(xiě)代碼就會(huì)不停試錯(cuò)用處理“工作表保護(hù)”的方式去處理“打開(kāi)密碼”的文件openpyxl 連讀都讀不出來(lái)。1.1 三種保護(hù)的實(shí)際差別第一種是打開(kāi)密碼。這種保護(hù)作用在文件本身沒(méi)有正確密碼就打不開(kāi)內(nèi)容。實(shí)現(xiàn)上不是簡(jiǎn)單加個(gè)標(biāo)記而是對(duì)文件內(nèi)容做了加密處理所以普通的 Excel 讀寫(xiě)庫(kù)不一定能直接讀取。第二種是工作簿結(jié)構(gòu)保護(hù)。它保護(hù)的是 Sheet 層面防止別人新增、刪除、隱藏、重命名或移動(dòng)工作表。這種保護(hù)和單元格能不能編輯沒(méi)有直接關(guān)系。第三種是工作表保護(hù)。它作用在單元格層面最常見(jiàn)的是“鎖定單元格”。要注意的是Excel 里單元格默認(rèn)是鎖定狀態(tài)但只有在你啟用了工作表保護(hù)之后鎖定才會(huì)真正生效。我把它們的差異整理成一張表方便你選工具時(shí)對(duì)照保護(hù)類型實(shí)際作用常用 Python 方案需要注意的點(diǎn)文件打開(kāi)密碼打開(kāi)文件需要密碼文件內(nèi)容屬于加密狀態(tài)msoffcrypto-tool、Excel COM忘記密碼后很難恢復(fù)建議保留備份工作簿結(jié)構(gòu)保護(hù)防止增刪、隱藏、移動(dòng)工作表Excel COMopenpyxl 支持有限不同工具的表現(xiàn)差異較大工作表保護(hù)鎖定單元格區(qū)域限制格式、插入、篩選等操作openpyxl、Excel COM適合防止誤操作不適合作為機(jī)密保護(hù)只讀推薦、標(biāo)記最終版只是提醒性質(zhì)不是強(qiáng)保護(hù)Excel COM、openpyxl不能阻止有權(quán)限的人直接另存修改1.2 按使用場(chǎng)景選擇保護(hù)組合先想清楚最終用戶是誰(shuí)再?zèng)Q定加哪種保護(hù)。我平時(shí)接觸到的場(chǎng)景基本是這三類如果你是給同事發(fā)一張銷(xiāo)售填報(bào)模板希望只能填 C2 到 F100表頭、公式和字段說(shuō)明不能被改那就用“工作表保護(hù)”把指定區(qū)域解鎖后開(kāi)啟保護(hù)。如果你擔(dān)心同事把 Sheet 刪掉或者把明細(xì)表隱藏起來(lái)那要加的是“工作簿結(jié)構(gòu)保護(hù)”。如果你處理的是人事、財(cái)務(wù)這類敏感數(shù)據(jù)文件本身就不希望無(wú)關(guān)人員打開(kāi)那應(yīng)該加“打開(kāi)密碼”而且是內(nèi)容加密級(jí)別的密碼不是簡(jiǎn)單的結(jié)構(gòu)保護(hù)。最容易被誤解的是很多人以為“工作表保護(hù)”等于安全加密。實(shí)際上工作表保護(hù)更準(zhǔn)確的定位是防止誤操作。它不能讓別人完全拿不到內(nèi)容也無(wú)法阻止有權(quán)限的人通過(guò)其他方式修改副本。真正要保護(hù)數(shù)據(jù)不外泄要靠文件加密、目錄權(quán)限和賬號(hào)權(quán)限這些機(jī)制。2. 開(kāi)始寫(xiě)代碼前先把環(huán)境和文件格式理清楚Python 處理 Excel 的庫(kù)很多但沒(méi)有一個(gè)庫(kù)能覆蓋所有格式和所有保護(hù)類型。先確定輸入文件是.xlsx還是老版.xls再?zèng)Q定走哪條路能省掉大量時(shí)間。2.1 .xlsx 和 .xls 的處理路線不同.xlsx本質(zhì)上是按 Office Open XML 結(jié)構(gòu)打包的文件openpyxl 這類純 Python 庫(kù)可以直接讀寫(xiě)適合服務(wù)器環(huán)境不要求安裝 Excel。.xls是老版二進(jìn)制格式openpyxl 不處理它。即使你強(qiáng)行把后綴改成.xlsx讀取時(shí)也會(huì)報(bào)錯(cuò)。要處理.xls最穩(wěn)的方式是調(diào)用本機(jī) Excel COM 接口也就是在 Windows 環(huán)境中使用pywin32或xlwings。這條路要求電腦上裝了 Office并且 Excel 能正常啟動(dòng)。如果你的文件帶打開(kāi)密碼處理鏈路還要往前加一步。無(wú)論是 openpyxl 還是其他直接解析 Excel XML 的庫(kù)都無(wú)法讀取一個(gè)處于文件加密狀態(tài)的.xlsx。你需要先用密碼解密出一個(gè)臨時(shí)文件再在臨時(shí)文件上做保護(hù)或修改操作。2.2 推薦依賴與干凈的解釋器環(huán)境我這里推薦安裝三個(gè)庫(kù)分別對(duì)應(yīng)不同任務(wù)python -m pip install openpyxl python -m pip install pywin32 python -m pip install msoffcrypto-toolopenpyxl 用于.xlsx的工作表保護(hù)操作pywin32 用于 Windows 下調(diào)用 Excel 處理.xls、結(jié)構(gòu)保護(hù)以及一些復(fù)雜格式msoffcrypto-tool 用來(lái)處理帶打開(kāi)密碼的 Office 文件。如果你的電腦上已經(jīng)有很多 Python 環(huán)境和各種測(cè)試包我建議先建一個(gè)獨(dú)立虛擬環(huán)境避免后面出現(xiàn)“明明裝了庫(kù)但是代碼跑起來(lái)說(shuō)找不到模塊”的問(wèn)題。python -m venv excel-toolsWindows 激活命令excel-tools\Scripts\activatemacOS 或 Linux 激活命令source excel-tools/bin/activate經(jīng)常有人在 VS Code 或 Notebook 里寫(xiě) openpyxl終端執(zhí)行時(shí)報(bào)ModuleNotFoundError: No module named openpyxl。這種問(wèn)題大概率不是代碼邏輯有錯(cuò)而是當(dāng)前解釋器和你裝庫(kù)的環(huán)境不是同一個(gè)。先運(yùn)行pip --version或python --version確認(rèn)環(huán)境指向再處理依賴。3. 給 Excel 添加保護(hù)從最小樣例開(kāi)始跑我自己的習(xí)慣是永遠(yuǎn)先跑單文件再套批量循環(huán)。不要一上來(lái)就把幾十個(gè)文件丟進(jìn)代碼里因?yàn)橐坏┍Wo(hù)邏輯理解錯(cuò)了批量操作會(huì)把錯(cuò)誤復(fù)制到每一份文件上。3.1 工作表保護(hù)能做什么不能做什么工作表保護(hù)啟用以后默認(rèn)會(huì)限制用戶編輯鎖定單元格也會(huì)限制很多結(jié)構(gòu)操作比如刪除行、插入行、修改格式等。但你要清楚兩件事第一它能防誤操作不能防破解第二它不改變文件本身的加密狀態(tài)也不影響文件是否能被直接打開(kāi)。如果你的需求是讓用戶只能填寫(xiě)指定區(qū)域那代碼分兩步先把填寫(xiě)區(qū)域解鎖再開(kāi)啟工作表保護(hù)。順序反了會(huì)出問(wèn)題。如果你先開(kāi)啟保護(hù)再設(shè)置單元格解鎖部分 Excel 版本會(huì)提示權(quán)限沖突用戶仍然無(wú)法編輯。注意工作表保護(hù)適合防誤操作不適合當(dāng)文件安全邊界。真正需要防泄露時(shí)請(qǐng)使用文件打開(kāi)密碼或權(quán)限系統(tǒng)。3.2 先給整張表加保護(hù)下面是一個(gè)最小實(shí)現(xiàn)給活動(dòng)工作表加上密碼保護(hù)from openpyxl import load_workbook wb load_workbook(銷(xiāo)售模板.xlsx) ws wb.active # 開(kāi)啟工作表保護(hù) ws.protection.sheet True # 設(shè)置保護(hù)密碼后續(xù)解除時(shí)需要 ws.protection.password 123456 wb.save(銷(xiāo)售模板_已保護(hù).xlsx)保存完成后用 Excel 重新打開(kāi)文件可以選中單元格但無(wú)法直接編輯。如果要去掉保護(hù)在 Excel 里單擊“撤銷(xiāo)工作表保護(hù)”輸入密碼即可。這里有個(gè)容易忽略的點(diǎn)工作表保護(hù)密碼在 Excel 文件里并不是保留明文而是以哈希形式存放。因此如果你自己忘了密碼openpyxl 也做不到從文件里“找回”原始密碼。它直接重寫(xiě)文件、清除保護(hù)是可以的但那是另一條路我放到下一節(jié)講。3.3 需要留出填寫(xiě)區(qū)域時(shí)先解鎖指定區(qū)域再保護(hù)很多模板場(chǎng)景不需要用戶編輯整張表。比如 A 列是產(chǎn)品編號(hào)B 列是公式計(jì)算金額只有 C 列填數(shù)量D 列填備注。這種情況下應(yīng)該把 C、D 兩列中需要填寫(xiě)的區(qū)域設(shè)為 unlocked再開(kāi)啟保護(hù)。單元格的鎖定狀態(tài)在 openpyxl 里通過(guò)Protection對(duì)象控制。默認(rèn)lockedTrue要開(kāi)放填寫(xiě)就設(shè)為lockedFalse。from openpyxl import load_workbook from openpyxl.styles import Protection wb load_workbook(銷(xiāo)售模板.xlsx) ws wb.active # 第一步解鎖用戶需要填寫(xiě)的區(qū)域 for row in ws[C2:D200]: for cell in row: cell.protection Protection(lockedFalse) # 第二步開(kāi)啟工作表保護(hù) ws.protection.sheet True ws.protection.password 123456 wb.save(銷(xiāo)售模板_可填寫(xiě).xlsx)打開(kāi)文件后會(huì)看到C2 到 D200 可以錄入其他區(qū)域仍然被鎖定。表格里的公式不會(huì)因?yàn)橛脩粽`操作被刪除。如果你還需要允許用戶使用排序、篩選、插入超鏈接等功能可以在WorksheetProtection上找到對(duì)應(yīng)屬性。屬性名通常和 Excel 保護(hù)對(duì)話框里的勾選項(xiàng)一一對(duì)應(yīng)True 表示允許False 表示不允許。測(cè)試時(shí)不要憑感覺(jué)猜直接在 Excel 里設(shè)一遍、看一遍效果再回到代碼里設(shè)置屬性比較省事。3.4 老格式和結(jié)構(gòu)保護(hù)用 Windows COM 更省事如果輸入文件是.xls或者你要做的是工作簿結(jié)構(gòu)保護(hù)我會(huì)直接用 Excel COM。openpyxl 對(duì)部分結(jié)構(gòu)保護(hù)有基礎(chǔ)支持但不同版本保存后再打開(kāi)的行為并不完全一致沒(méi)必要在項(xiàng)目里賭這種兼容性。import win32com.client as win32 excel win32.DispatchEx(Excel.Application) excel.Visible False excel.DisplayAlerts False try: wb excel.Workbooks.Open(rD:\data\報(bào)表.xls) # 保護(hù)工作簿結(jié)構(gòu)防止增刪工作表 wb.Protect(Password123456, StructureTrue, WindowsTrue) wb.Save() finally: wb.Close(SaveChangesFalse) excel.Quit()用 COM 時(shí)有一個(gè)非常重要的點(diǎn)Excel 是在后臺(tái)真實(shí)啟動(dòng)的不要以為Visible False就完全沒(méi)有進(jìn)程。如果腳本中途崩潰或者你沒(méi)有執(zhí)行excel.Quit()任務(wù)管理器里會(huì)留下 EXCEL.EXE 進(jìn)程。下一次再打開(kāi)同一個(gè)文件就可能報(bào)文件被占用。所以腳本里一定要用try-finally或with方式保證釋放。如果你想保護(hù)的是工作表而不是工作簿那是另一個(gè)方法。openpyxl 加的是ws.protectionCOM 里對(duì)應(yīng)的是ws.Protect不要把wb.Protect當(dāng)成鎖定單元格來(lái)用。4. 解除保護(hù)先確認(rèn)你面對(duì)的是哪一類“鎖”解除保護(hù)和添加保護(hù)并不是簡(jiǎn)單的“把 True 改成 False”。面對(duì)不同鎖走的路線完全不同。我建議按下面順序先判斷文件打開(kāi)時(shí)是否需要密碼。文件是否能被 openpyxl 直接打開(kāi)。打開(kāi)后工作表是否處于鎖定編輯狀態(tài)。是否禁止新增或刪除 Sheet。很多報(bào)表會(huì)被同事設(shè)置成“打開(kāi)即可讀但不能改”然后你會(huì)看到文件中所有單元格都不能編輯。這時(shí)候首先要判斷它到底是工作表保護(hù)還是文件本身的只讀屬性。兩者處理方式不一樣。4.1 用 openpyxl 清除工作表保護(hù)如果文件本身沒(méi)有打開(kāi)密碼只是工作表被保護(hù)了openpyxl 可以直接打開(kāi)并清除保護(hù)。from openpyxl import load_workbook wb load_workbook(受保護(hù)的工作表.xlsx) ws wb[Sheet1] # 關(guān)閉工作表保護(hù) ws.protection.sheet False wb.save(已解除保護(hù).xlsx)這個(gè)操作不需要輸入原保護(hù)密碼。原因是 openpyxl 并不會(huì)去校驗(yàn)密碼它只是在重新生成 Excel XML 文件時(shí)不再寫(xiě)入 sheet protection 相關(guān)配置。對(duì)于你自己有權(quán)限處理的文件這是一個(gè)很實(shí)用的恢復(fù)手段。但我要多說(shuō)一句邊界如果一份文件是別人設(shè)置的并且對(duì)方明確不允許你修改那就不要用這種方式去繞過(guò)。自動(dòng)化腳本可以用來(lái)恢復(fù)自己的文件、處理公司授權(quán)處理的報(bào)表不應(yīng)該被用來(lái)突破別人的權(quán)限限制。4.2 文件打開(kāi)密碼要先用解密工具處理如果文件在打開(kāi)時(shí)就要求輸入密碼那么它已經(jīng)處于“文件加密”狀態(tài)openpyxl 讀不到內(nèi)部結(jié)構(gòu)。你需要先用正確密碼解密。msoffcrypto-tool 適合處理這種場(chǎng)景。下面是一個(gè)示例import io import msoffcrypto from openpyxl import load_workbook with open(加密報(bào)表.xlsx, rb) as f: office_file msoffcrypto.OfficeFile(f) if office_file.is_encrypted(): office_file.load_key(password123456) decrypted io.BytesIO() office_file.decrypt(decrypted) decrypted.seek(0) # 讀取解密后的內(nèi)容 wb load_workbook(decrypted) print(wb.sheetnames)注意decrypt是指用你知道的正確密碼把文件解密到內(nèi)存不是猜測(cè)密碼。解密后的內(nèi)容如果直接保存成新文件那個(gè)新文件會(huì)變成沒(méi)有打開(kāi)密碼的普通 Excel 文件。如果你希望最終文件繼續(xù)保留打開(kāi)密碼就不要用這個(gè)方法生成明文文件直接交付最好在完成修改后用 Excel COM 或其他受控方式重新覆蓋密碼保存并在本地處理完后清理臨時(shí)文件。4.3 忘記打開(kāi)密碼時(shí)的穩(wěn)妥處理如果工作表保護(hù)密碼忘了openpyxl 的方式通??梢跃然貋?lái)。結(jié)構(gòu)保護(hù)密碼忘了也可以用 COM 在沒(méi)有修改 Sheet 的情況下重新保存來(lái)清除。但文件打開(kāi)密碼忘了情況會(huì)麻煩很多。文件本身是加密的沒(méi)有正確密碼解析工具拿不到內(nèi)部?jī)?nèi)容。我的建議是先找備份、版本歷史或文件原負(fù)責(zé)人。如果是團(tuán)隊(duì)內(nèi)文件找管理員重置密碼或重新生成文件。今后在自動(dòng)化任務(wù)里先規(guī)劃好密碼管理不要臨時(shí)把密碼寫(xiě)在代碼里更不要在明文日志里打印。不要輕易從來(lái)路不明的網(wǎng)站下載所謂找回密碼工具。很多工具帶有額外程序碰到的風(fēng)險(xiǎn)遠(yuǎn)大于省下的麻煩。4.4 COM 方式解除結(jié)構(gòu)和工作表保護(hù)如果你處理的是.xls或者用 COM 更穩(wěn)妥的.xlsx可以這樣解除import win32com.client as win32 excel win32.DispatchEx(Excel.Application) excel.Visible False excel.DisplayAlerts False try: wb excel.Workbooks.Open(rD:\data\報(bào)表.xls) # 如果是工作簿結(jié)構(gòu)保護(hù) wb.Unprotect(Password123456) # 如果是工作表保護(hù)需要逐個(gè)工作表調(diào)用 for ws in wb.Worksheets: ws.Unprotect(Password123456) wb.Save() finally: wb.Close(SaveChangesFalse) excel.Quit()這段代碼會(huì)先解除工作簿保護(hù)再解除當(dāng)前工作簿里所有工作表的保護(hù)。實(shí)際使用時(shí)只需要調(diào)用你真正需要處理的那一個(gè)不要無(wú)腦全部解除。如果只處理某一張表卻把結(jié)構(gòu)保護(hù)也取消了反而會(huì)帶來(lái)新的風(fēng)險(xiǎn)。5. 批量處理多文件、輸出目錄與失敗清單只處理一兩個(gè)文件時(shí)手動(dòng)寫(xiě)腳本和手動(dòng)操作差別不大。但一旦文件數(shù)量到幾十上百份批量的價(jià)值就出來(lái)了。批量任務(wù)有一個(gè)基本原則不要把原文件原地覆蓋。5.1 目錄遍歷與不覆蓋原文件的策略我的通常做法是建立兩個(gè)目錄一個(gè)放待處理文件一個(gè)放處理結(jié)果。腳本從待處理目錄讀取文件把結(jié)果寫(xiě)入已處理目錄。這樣即使一批文件中有幾個(gè)處理失敗原始文件仍然保留可以修復(fù)后重跑。from pathlib import Path from openpyxl import load_workbook src_dir Path(./待處理) out_dir Path(./已處理) out_dir.mkdir(exist_okTrue) password 123456 for xlsx_path in src_dir.glob(*.xlsx): wb load_workbook(xlsx_path) for ws in wb.worksheets: ws.protection.sheet True ws.protection.password password out_path out_dir / xlsx_path.name wb.save(out_path)這段代碼給每個(gè)工作簿中的所有工作表都開(kāi)啟了保護(hù)。如果你的列表里有“部分 Sheet 需要鎖定、部分 Sheet 不需要鎖定”的情況不能直接用這個(gè)循環(huán)要先把表格清單列出來(lái)按單子操作。5.2 批量解除保護(hù)與批量加鎖要關(guān)注的事項(xiàng)批量解除保護(hù)時(shí)成功標(biāo)準(zhǔn)不只是“不報(bào)錯(cuò)”。我會(huì)額外檢查以下幾點(diǎn)每個(gè) Sheet 是否都按預(yù)期解除保護(hù)。是否誤刪了公式、圖表、透視表或數(shù)據(jù)驗(yàn)證。文件打開(kāi)后是否提示損壞。原文件的格式和內(nèi)容是否保持完整。這里有一個(gè) openpyxl 常見(jiàn)的坑讀取 Excel 時(shí)如果你使用了data_onlyTrue拿回來(lái)的是公式的緩存值而不是公式本身。如果此時(shí)再保存文件里的公式體系可能被破壞。處理保護(hù)和解除保護(hù)的任務(wù)時(shí)除非你明確知道要讀值否則不要開(kāi)data_onlyTrue。對(duì)有圖表、透視表、圖片、復(fù)雜數(shù)據(jù)驗(yàn)證的.xlsx建議先用 COM 方式處理或者把一個(gè)文件復(fù)制出來(lái)做驗(yàn)證。openpyxl 適合公式和格式相對(duì)規(guī)整的報(bào)表但它畢竟不是完整 Excel 內(nèi)核面對(duì)復(fù)雜對(duì)象時(shí)可能重寫(xiě)后格式和交互有變化。5.3 記錄日志讓失敗任務(wù)可以重跑批量任務(wù)最怕出現(xiàn)“全量處理完卻發(fā)現(xiàn)部分文件失敗”的情況。失敗的判斷標(biāo)準(zhǔn)不能只靠腳本最后是否拋出異常要對(duì)每個(gè)文件單獨(dú)記錄。from pathlib import Path from openpyxl import load_workbook src_dir Path(./待處理) out_dir Path(./已處理) out_dir.mkdir(exist_okTrue) success [] failed [] for xlsx_path in src_dir.glob(*.xlsx): try: wb load_workbook(xlsx_path) for ws in wb.worksheets: ws.protection.sheet True ws.protection.password 123456 out_path out_dir / xlsx_path.name wb.save(out_path) success.append(xlsx_path.name) except Exception as exc: failed.append((xlsx_path.name, repr(exc))) print(成功數(shù)量, len(success)) print(失敗數(shù)量, len(failed)) for name, err in failed: print(name, err)把失敗文件名和異常信息打印出來(lái)比只輸出一個(gè)batch finished要可靠得多。處理完成之后再按成功清單抽查幾份結(jié)果確認(rèn)保護(hù)狀態(tài)和內(nèi)容完整性整個(gè)任務(wù)才算真正結(jié)束。注意批量場(chǎng)景不要一上來(lái)就開(kāi)并發(fā)。openpyxl 本身可以并發(fā)跑但一旦批處理邏輯里有 COM、Excel進(jìn)程、文件占用這些因素并行會(huì)讓錯(cuò)誤變得很難排查。先用單線程跑通再考慮是否值得優(yōu)化速度。6. 經(jīng)常碰到的報(bào)錯(cuò)與排查順序?qū)嶋H使用中大部分人遇到問(wèn)題不是卡在算法而是卡在文件格式、依賴環(huán)境和進(jìn)程占用這些很基礎(chǔ)的地方。這里會(huì)分享幾個(gè)我排查時(shí)優(yōu)先看的點(diǎn)。6.1 報(bào)錯(cuò)先看輸入文件如果load_workbook報(bào)壓縮包錯(cuò)誤或者文件格式錯(cuò)誤首先檢查文件后綴是不是真的.xlsx。有些人把 CSV 直接改名為.xlsx或者把 HTML 表格下載下來(lái)改成 Excel 后綴都會(huì)讓 openpyxl 報(bào)錯(cuò)?,F(xiàn)象可能原因優(yōu)先排查方向load_workbook 提示 BadZipFile文件不是標(biāo)準(zhǔn) xlsx或文件仍處于打開(kāi)密碼加密狀態(tài)檢查后綴、用 Excel 打開(kāi)確認(rèn)文件格式PermissionError文件正在 Excel/WPS 中打開(kāi)或目錄無(wú)寫(xiě)入權(quán)限關(guān)閉正在查看文件的程序復(fù)制到臨時(shí)目錄再處理保存后打開(kāi)提示文件損壞復(fù)雜對(duì)象被重寫(xiě)后不兼容圖表、透視表多的文件改用 Excel COM保護(hù)看起來(lái)沒(méi)有生效只是設(shè)置了只讀推薦或沒(méi)有啟用工作表保護(hù)檢查 Excel 菜單里的實(shí)際操作判斷文件類型時(shí)不要只看圖標(biāo)和后綴最好在資源管理器里開(kāi)啟“顯示文件擴(kuò)展名”確認(rèn)真實(shí)的擴(kuò)展名。6.2 環(huán)境問(wèn)題先看解釋器和依賴ModuleNotFoundError: No module named win32com通常是沒(méi)裝 pywin32No module named openpyxl通常是當(dāng)前解釋器環(huán)境不對(duì)。處理方法很簡(jiǎn)單先確認(rèn)當(dāng)前 python 命令指向哪個(gè)解釋器再使用python -m pip install openpyxl安裝避免用 pip 和 python 不屬于同一個(gè)環(huán)境的問(wèn)題。如果本機(jī)沒(méi)有安裝 Office調(diào)用DispatchEx(Excel.Application)時(shí)也會(huì)失敗這類問(wèn)題不是代碼能解決的。6.3 保護(hù)表現(xiàn)和預(yù)期不一致時(shí)按從外到內(nèi)的順序排查保護(hù)表現(xiàn)不對(duì)時(shí)我通常按這樣的順序排查先確認(rèn)文件打開(kāi)時(shí)是否需要密碼。如果需要先用解密方式處理。再確認(rèn)文件是不是老版.xls。如果是就切換 COM 路線。然后確認(rèn)是整張表不能編輯還是部分單元格不能編輯。如果是部分單元格不能編輯很可能是單元格鎖定狀態(tài)沒(méi)有設(shè)置對(duì)。最后確認(rèn)你改的是哪個(gè) Sheet。active 工作表不等于所有工作表批量操作時(shí)尤其要注意。我發(fā)現(xiàn)很多看似“工具不支持”的問(wèn)題最后都是因?yàn)檩斎肱袛噱e(cuò)了。文件格式?jīng)]確認(rèn)、保護(hù)類型沒(méi)區(qū)分、環(huán)境沒(méi)選對(duì)三個(gè)原因占了大多數(shù)。7. 落地的最后建議