日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

pywin32+excel(一)——Python使用win32com/pywin32操作excel

發布時間:2023/12/10 python 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 pywin32+excel(一)——Python使用win32com/pywin32操作excel 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 1. 正式使用
    • 1.0 代碼demo
    • 1.1關于offset的說明
    • 1.2 range使用
      • 1.2.1 合并單元格的搜索問題
      • 1.2.2 獲取Range對象范圍
    • 1.3 小trick
      • 1.3.1 兩個list構成一個dict
      • 1.3.2 不使用多余的庫實現 字符串中 數字和字母分開
    • 1.4 win32com.client.gencache.EnsureDispatch和Dispatch以及DispatchEx的區別
    • 1.5 win32關閉當前程序操作的excel時也關閉了其他的excel窗口
  • 2.wps和office沖突的問題
    • 2.1 問題1
      • 2.1.1 問題1.1
      • 2.1.1 問題1.2
    • 2.2 問題2 不用管
    • 2.3查看當前調用對象的名字和版本
  • 3. 部署時候的問題
    • 福昕閱讀器com口沖突(`服務器沒有響應`錯誤)
  • win32com相關的使用document

1. 正式使用

一千個讀者一千個哈姆雷特,單純 save()表 close()工作薄 還有quit()Excel APP,這三個寫法就有很多不同的解釋。。。

不喜歡解釋太多,直接看代碼吧,給一個簡單的讀取某個excel文件 修改后保存的例子。

1.0 代碼demo

excel = win32.Dispatch('Excel.Application') excel.Visible = False # 如果是True 會打開excel程序(界面) excel.DisplayAlerts = 0 # 不顯示警告信息 wb = excel.Workbooks.open('./xxx.xls') # 打開一個excel文件 最好使用絕對路徑 # office的函數調用時候不是特別在意大小寫(有些函數大小寫錯了照樣可以運行,有些就不行。。) wps有嚴格的大小寫限制 ws = wb.Worksheets('Sheet1') # 具體工作簿里的哪張工作表 一般默認Sheet1 操作都是對工作表操作的c_column = [15, 16, 18, 41] # 需要寫入的數據 xing = 10 # 某一行,這里指第十行 ws.Cells(11, 5).Value = 2 # Cells(row,col) 先行后列 Cells(11,5)就指的是 E11單元格 ws.Cells(11, 5).offset(3,2).Value =1 # E11 偏移后 到了 F13 ws.Range('D' + str(xing)).value = c_column[0] # 這里指對D10寫入數據 15 ws.Range('E' + str(xing)).value = c_column[1] # 這里指對E10寫入數據 16 ws.Range('F' + str(xing)).value = c_column[2] # 這里指對F10寫入數據 18 ws.Range('G' + str(xing)).value = c_column[3] # 這里指對G10寫入數據 41 wb.save # 保存表格(將修改保存到當前正在修改的表格) 保存當前工作簿 wb.SaveAs('xxx.xls') # 另存為為另一個表格 路徑也要是絕對路徑(如果不想修改原表格 可以注銷掉上一句 另存為即可) 將工作簿另存為 wb.Close(False) # True就是關閉該文件,并保存。不保存就是False 關閉工作簿 excel.Quit() # 關閉excel操作環境。

1.1關于offset的說明

參考Excel VBA中Offset函數的用法和自己實測

  • Offset函數實為定位函數。首先要找到中心點,如果以單元格A1為中心點,則A1的位置就是Offset(0,0)。
  • 上圖以A1為中心,Offset兩個參數分別是行和列。以0為起點。
  • 同理,E11 (11,5)偏移(3,2)后 (11+3-1,5+2-1)得到(13,6)即 F13
  • E11偏移(1,0)到D11 (11,5)偏移(1,0) 即 (11+1-1,5+0-1)=(11,4)=11D 即 D11
  • 所以offset(0,0)反倒會向左上移動一個。想要保持不變,應該是offset(1,1)。。。實測
  • 上 左 是 負向 下 右 是正向
  • 這一結論和網上搜到的VBA代碼結論不一致,可能是pywin32庫的問題
  • 此外,注意到如果寫入單元格的內容很長,不會自動拉長單元格,需要自己打開excel之后手動縮放(也就是保持格式不變啦)

1.2 range使用

1.2.1 合并單元格的搜索問題

如果想定義Range(比如在A1-D10這個范圍內的單元格搜索“報賬單”),則需要使用Range對象,根據
Application.Range property (Excel),可知,定義Range的方式有兩種:

//續上面的代碼: range=ws.Range("A1:D10").Find('報賬單') #返回的對象仍然是一個range 或者 range=ws.Range(ws.Cell(1,1),ws.Cell(10,4)) # 使用Cell(row,col)對象來定義起始單元格 print(range.Address) #可以Range對象的Address屬性來打印出 搜索結果的 第一項的首行首列編號

此外,在遇到合并單元格時,返回的Range對象的Address地址范圍只有左上角第一個的值,如果想要獲得該合并單元格所有的行/列,可以使用offset
比如上述工作表,如果Find(‘10V’) 使用range.Address返回的只是$D$38,同時,使用range.Areas.count返回的只是1,也就是說 這個合并單元格的起始位置是$D$38且只有1個(并不是返回基本單元格的數量)。為了方便后續操作,參考Find方法如何找到合并單元格的位置,針對這種問題有兩種常見解決方法

  • 使用offset
  • 使用Range對象的MergeArea屬性 Range.MergeArea property (Excel)
  • 由于我面臨的場景不是單一合并(只是列方向或只是行方向),同時有許多合并單元格且合并的行數/列數并不一致,不能寫死,所以采用第二種方法,使用Range對象的MergeArea屬性(也是大多數情況下更方便推薦的一種)

    range_freq = ws.Range(ws.Cells(1, 1), ws.Cells(10, 11)).Find('freq') range_range=range_freq.Find('range') print(range_range.Address,range_range.Areas.count) for i in range_range.MergeArea:print(i.Address)print(i.row,i.column) # 以數字形式代替字母打印出列號,行號 和 Cell(row,col)形式類似 // 此時打印出來就可以看到這個合并單元格里所有的基本單元格的(合并的行或者列都會打印出來) //如果某個合并單元格既有行合并又有列合并,則先按照行打印,再打印列

    上圖的excel表格區域打印后(先行后列):

    $D$38 $E$38 $D$39 $E$39 $D$40 $E$40 $D$41 $E$41 $D$42 $E$42 $D$43 $E$43 $D$44 $E$44 $D$45 $E$45 $D$46 $E$46 $D$47 $E$47

    1.2.2 獲取Range對象范圍

    # 獲取10行-20行 1-9列之間的一個區域 freq_range = ws.Range(ws.Cells(10, 1),ws.Cells(20, 9)) freq_start_line = freq_range.Row # 區域起始行 等價于 freq_range.End(-4162).Row 有標題 freq_end_line = freq_range.End(-4121).Row # 區域的最后一行 但是注意 這里這個值一般需要-1 因為返回的是當前區域最后一行的下一行

    參考:MSDN——關于Range的End()

    在Python中使用時,似乎不認識 xlUp 這些關鍵字,所以直接用對應的數值代替。Down對應最下面一行,ToLeft對應最左側一欄 同理,Up就是最上面一行 ToRight就是最右邊一列,四個數值就是Range的范圍了


    1.3 小trick

    1.3.1 兩個list構成一個dict

    主要參考:Convert two lists into a dictionary

    方法一是性能最高的方法,方法二類似列表構造器,但是成為字典構造器會更合適一點

    //方法一 a=['1','2','3'] b=[1,2,3] c=dict(zip(a,b)) c Out[5]: {'1': 1, '2': 2, '3': 3} //方法二 new_dict = {k: v for k, v in zip(keys, values)}

    1.3.2 不使用多余的庫實現 字符串中 數字和字母分開

    參考
    Python 分割文本使得 字母和數字 分開?

    但是最后發現還是re模塊用起來最簡單直接


    1.4 win32com.client.gencache.EnsureDispatch和Dispatch以及DispatchEx的區別

    在使用win32com調用excel的使用過程中,最常見的創建excel對象的方式有以下三種:

    # 第一種 excel = win32.gencache.EnsureDispatch('Excel.Application') # 第二種 excel = win32com.client.Dispatch('Excel.Application') # 第三種 excel = win32com.client.DispatchEx('Excel.Application')

    參考

  • Python筆記:使用pywin32處理excel文件: win32com.client.DispatchEx('Excel.Application') #也可以用Dispatch,前者開啟新進程,后者會復用進程中的excel進程
  • 排坑:運行win32com.client.Dispatch(‘Word.Application’)和docx.Documents.Open()報錯
    :DispatchEx會使用獨立進程
  • 調用win32com.client.gencache.EnsureDispatch后的坑 object has no attribute:說明使用win32com.client.gencache.EnsureDispatch()這個方式對函數調用的大小寫會把控更嚴格,而win32com.client.Dispatch()則不會
  • Stack overflow-win32.Dispatch vs win32.gencache in Python. What are the pros and cons?
  • 如下程序所示,

    import win32com.client as win32 xl_dis = win32.Dispatch("Excel.Application") xl_dis Out[3]: <COMObject Excel.Application>import win32com.client as win32 xl_ens = win32.gencache.EnsureDispatch("Excel.Application") xl_ens Out[3]: <win32com.gen_py.Microsoft Excel 14.0 Object Library._Application instance at 0x35671240>

    Dispatch調用屬于late binding 調用時python不知道Excel object有哪些屬性和方法可以使用

    而EnsureDispatch調用屬于earlybinding 調用時python知道Excel object有哪些屬性和方法可以使用,這是因為EnsureDispatch會先運行makeup.py文件, 反正找找自己的目錄,類似D:\anaconda\Lib\site-packages\win32com\client

    此外,還可以在C:\Users\用戶名\AppData\Local\Temp\gen_py\3.7\00020813-0000-0000-C000-000000000046x0x1x8類似的目錄下找到這些內容,隨便打開一個,里面就是這個object的屬性方法,python也就是通過讀取這些文件才知道這個com對象有什么屬性方法的。

    如果先使用了EnsureDispatch,那么就會產生這些文件,此時,不管調用Dispatch還是EnsureDispatch結果都一樣。但是如果刪除了這些文件,二者的不同之處就又會顯現,所以最大的不同就是一個會產這些輔助文件,一個不會。這些東西是寫在緩存文件夾位置的,不確定什么時候就會被清理

    個人觀點:EnsureDispatch用在寫程序的時候,程序弄完之后,就用Dispatch比較好吧

    使用EnsureDispatch的時候,有時候需要刪除緩存下的內容,重新產一遍

    def open_excel():try:try:excel = win32.gencache.EnsureDispatch('Excel.Application')# print(excel.Name,excel.Version)except AttributeError:import shutilimport sys# Remove cache and try again.MODULE_LIST = [m.__name__ for m in sys.modules.values()]for module in MODULE_LIST:if re.match(r'win32com\.gen_py\..+', module):del sys.modules[module]shutil.rmtree(os.path.join(os.environ.get('LOCALAPPDATA'), 'Temp', 'gen_py'))excel = win32.gencache.EnsureDispatch('Excel.Application')excel.Visible = False # True 打開excel界面excel.DisplayAlerts = 0 # 不彈窗顯示警告信息 覆蓋同名文件時不彈出確認框(但是無法打開同名文件時會出錯 這個不屬于彈窗警告信息)except Exception as e:print('ERROR 02: excel打開錯誤:', e)else:return excel

    1.5 win32關閉當前程序操作的excel時也關閉了其他的excel窗口

    參考Advanced Python and COM,可能是我沒有認真看,找不出相關的有效信息。

  • Python筆記:使用pywin32處理excel文件: win32com.client.DispatchEx('Excel.Application') #也可以用Dispatch,前者開啟新進程,后者會復用進程中的excel進程
  • excel=win32.DispatchEx("Excel.Application") # 很奇怪 一開始使用上述語句,報錯 (-2147221005, '無效的類字符串', None, None)# 然后把大寫換小寫,然后可以正常執行,正常執行后,再換成大寫也可以正常執行了 # 我以前是使用 win32.gencache.EnsureDispatch('Excel.Application')這種方式的 excel=win32.DispatchEx("excel.Application")

    使用DispatchEx確實是新開了一個excel進程,關閉時候只關閉當前excel進程,而不會影響以及打開的其他excel進程。good

    2.wps和office沖突的問題

    2.1 問題1

    Rebuilding cache of generated files for COM support has no attribute 'CLSIDToClassMap'

    搜索后,根據Issue in using win32com to access Excel file可知

    // 如果想確保python啟動一個新的excel實例(例如,訪問xlsm文件中的宏),則使用 xlApp = win32com.client.DispatchEx("Excel.Application") //這樣,我可以關閉應用程序而不會損害已經打開的實例。否則,我可以簡單地使用 xlApp = win32com.client.Dispatch("Excel.Application")

    pywin32這里的坑挺多的

    2.1.1 問題1.1

    excel打開錯誤: module 'win32com.gen_py.45541000-5750-5300-4B49-4E47534F4655x0x3x0' has no attribute 'CLSIDToClassMap'

    參考:rdapaz/win32com.client.py,感謝這位大佬,大致就是把緩存清除,重新加載模塊中的一個文件

    try:xl = client.gencache.EnsureDispatch('Excel.Application') except AttributeError:# Corner case dependencies.import osimport reimport sysimport shutil# Remove cache and try again.MODULE_LIST = [m.__name__ for m in sys.modules.values()]for module in MODULE_LIST:if re.match(r'win32com\.gen_py\..+', module):del sys.modules[module]shutil.rmtree(os.path.join(os.environ.get('LOCALAPPDATA'), 'Temp', 'gen_py'))from win32com import clientxl = client.gencache.EnsureDispatch('Excel.Application')

    2.1.1 問題1.2

    應該才是真的核心問題,在問題1.1解決后報錯:

    AttributeError: '<win32com.gen_py.Upgrade WPS Spreadsheets 3.0 Object Library (Beta).Workbooks instance at 0x1553056241672>' object has no attribute 'open'

    也就是說 我調用的明明是excel 但是卻使用了wps(大概就是端口沖突了),核心要解決的問題。
    搜索發現:1. 安裝并卸載WPS后,導致office COM組件調用失敗的解決方案,大哥你真是個天使,我這個小白對端口和注冊表一看就頭大,愛你。
    部分文章截取:
    造成問題的原因是WPS惡意修改了office的com組件注冊信息,并且,不知道為什么,卸載和重新安裝都沒有修復 。WPS把office的接口全部指向自己,對應注冊表里 計算機\HKEY_CLASSES_ROOT\Interface{000208**-0000-0000-C0000-000000000046}\TypeLib 默認值改為了{45541000-5750-5300-4B49-4E47534F4655},原本應該為{00020813-0000-0000-C000-000000000046},Version改為了3.0,原本應該是1.7(office2010)。共有100+項,將以上修改正常就好了。附上修改后的注冊表文件。

    • 先試試這個2. WPS Office 與 Microsoft Office 出現沖突的解決方法 操作后,重啟了Pycharm,報錯信息已經發生了變化
    AttributeError: '<win32com.gen_py.Microsoft Excel 16.0 Object Library.Workbooks instance at 0x1898809804360>' object has no attribute 'open'

    不用修改注冊表?直接使用wps配置工具取消兼容?(反正我把wps配置工具里的所有默認關聯打開文件全都取消了,哈哈哈),有興趣的可以自己去根據
    1. 安裝并卸載WPS后,導致office COM組件調用失敗的解決方案這里面給的注冊表去看看,看是不是使用wps配置工具后 注冊表文件發生了改變。

    反正是可以用了,解決,yeah!

    2.2 問題2 不用管

    pywintypes.com_error: (-2147417851, '服務器出現意外情況。', None, None)

    嘗試過讀寫excel數據出現服務器出現意外:我電腦上沒有福昕閱讀器或者其他閱讀器的插件,看過了,無效。

    還有很多方法:

  • open的文件名/路徑過長,反正服務器報錯,涉及的問題其實很多,出現這個報錯不要考慮了,造成這個錯誤的可能太寬泛
  • 2.3查看當前調用對象的名字和版本

    • Application.Version property (Excel)
    excel=win32.client.Dispatch('Excel.Application') print(excel.Name) print(excel.Version)

    Microsoft Excel 15.0(office2013對應的版本) 不是很區分大小寫(上面改成小寫的 excel.name 或者 excel.version都可以)

    但是如果在office2016版本(Microsoft Excel 16.0)運行小寫形式的屬性name和version,則報錯

    '<win32com.gen_py.Microsoft Excel 16.0 Object Library._Application instance at 0x3142152794952>' object has no attribute 'name'

    所以為了防止版本沖突(微軟office官方給的都是大寫),最好都改成大寫

    3. 部署時候的問題

    福昕閱讀器com口沖突(服務器沒有響應錯誤)

    部署在其他人電腦的時候,報錯
    服務器沒有響應 這個錯誤。

    然后想起之前搜索相關錯誤的時候,出現過 excel中如果有福昕閱讀器插件的話,會占用excel的com口,所以試了一下,關閉了那人電腦上的福昕閱讀器的com加載項。 就ok了

    win32com相關的使用document

    中文:

    • python win32com.client
    • win32com 處理word和excel文檔說明
    • python用win32com對Excel的一些操作
    • win32com 處理word和excel文檔說明
    • python3,用win32com操作excel及其宏
    • Python Win32com模塊操作excel的幾個應用(一)
    • Python-Win32com-Excel

    英文:

    • excelapp.py
    • Automating Windows Applications Using COM
    • Python Excel Mini Cookbook
    • Python 2.7: Read and Write Excel file with win32com
    • 下面這兩個網站其實屬于一個ip
      • Python and com blowing the rest away
      • PyWin32 Documentation

    相關函數參考

    • Application.Range property (Excel)
    • Range object (Excel)
    • Range.MergeArea property (Excel)
    • Workbooks object (Excel)
    • Worksheet object (Excel)
    • Application.Cells property (Excel)
    • Worksheet.SaveAs method (Excel)
    • Workbooks.Close method (Excel)
    • Workbooks.Open method (Excel)
    • Application.Quit method (Excel)
    • Workbook.Save method (Excel)
    • Workbook.SaveAs method (Excel)
    • win32.Dispatch vs win32.gencache in Python. What are the pros and cons?
    • Python Programming on Win32-ebook-online

    總結

    以上是生活随笔為你收集整理的pywin32+excel(一)——Python使用win32com/pywin32操作excel的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。