Python操作excel文件的第三方庫有很多,小爬就常用openPyxl庫來操作已有的excel文件,它對xlsx、xlsm等格式的支持都較好。可openPyxl也有不足,它難以實習VBA中的很多功能。如果我們平日裡對VBA語法很熟悉,則可以通過win32com.client來操縱excel文件,語法非常類似。
之所以不直接使用VBA,是因為VBA擅長跟excel打交道,不擅長跟外部應用打交道。小爬最近就遇到這樣一個自動化場景:先利用python爬蟲的方法,獲取到伺服器端的多個excel文件,然後對這些excel文件進行跨表操作,單純的VBA實現起來比較繁瑣,用python和VBA各實現一部分不利於腳本的封裝,割裂感較強。
話不多說,我們看看如何用win32com來控制excel,首先我們需要用pip安裝pywin32庫,之後就可以使用了:
下面的代碼演示了一些常規的語法操作,與vba如出一轍,只是需要代碼pythonic:
import win32com.client
import os
base_dir=os.path.dirname(os.path.abspath(__file__)) # 獲取當前路徑
xlApp = win32com.client.Dispatch('Excel.Application')
xlApp.Visible=1 # 顯示excel界面
filename="test.xlsx"
fullPath=os.path.join(base_dir,filename) # 得到完整的filepath
xlBook = xlApp.Workbooks.Open(fullPath, ReadOnly = False) #打開對飲的excel文件
sht = xlBook.Worksheets('Sheet1') # 打開對應名稱的sheet
sht.UsedRange.ClearContents() # 對當前使用區域清除內容
nrows=sht.UsedRange.Rows.Count # 獲取使用區域的行數
sht.UsedRange.Copy() #複製
sht.Activate() # 激活當前工作表光這些還不夠,比如我們希望實現excel的複製&粘貼值操作,vba的語法類似這樣:
Sub 宏1()
'
Range("A1").Select
Selection.CurrentRegion.Select
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
End Sub這段VB風格的代碼如何pythonic且不出錯呢,你可能首先會想這樣改造:
Range("A1").Select()
Selection.CurrentRegion.Select()
Selection.Copy()
Selection.PasteSpecial(Paste=xlPasteValues, Operation=xlNone, SkipBlanks=False, Transpose=False)VBA中默認你操作的當前worksheet,所以可以直接使用Range對象,Selection對象,但是python中不能直接這樣簡寫,改造和簡化後應該是:
sht.Range("A1").CurrentRegion.Copy()
sht.Range("A1").CurrentRegion.PasteSpecial(Paste=xlPasteValues, Operation=xlNone, SkipBlanks=False, Transpose=False)其實這樣還是會報錯,因為python並無法知道xlPasteValues、xlNone這些常量到底為多少,因為我們沒有提前定義它。如何查詢這些常量實際的值,一個簡單的方法還是通過VBA的對象瀏覽器,打開excel,按住快捷鍵Alt—+F11進入VBE界面,見下圖:
有了這些,上面的偽代碼就可以改成如下形式,成功運行通過:
sht.cells(1,1).PasteSpecial(Paste=-4163, Operation=-4142, SkipBlanks=False, Transpose=False)小爬知道了這些後,想用分列功能將excel某列文本型數值轉為常規的數值格式,操作如動態所示:
vba代碼示例如下:
Columns("A:A").Select
Selection.TextToColumns Destination:=Range("A1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, _
Semicolon:=False, Comma:=False, Space:=False, Other:=False, FieldInfo _
:=Array(1, 1), TrailingMinusNumbers:=True我們故技重施,可以查到xlDelimited、xlDoubleQuote 這些常量的值,但是這個Array(1, 1) 怎麼轉化為python語法,小爬目前還沒找到合適的方法,有知道的童鞋,可以留言區告訴我,謝謝~
上面的例子說明,上文提到的方法有一定局限性。其實我們可以利用選擇性粘貼(乘以1)來達到同樣的效果:文本型數字轉常規數值,演示動圖如下:
這段方法,需要藉助一個輔助單元格,將其賦值1,待操作完畢後,再清空該輔助單元格的值即可,這個用VBA代碼示例如下:
Range("B2").Select
ActiveCell.FormulaR1C1 = "1"
Range("B2").Select
Selection.Copy
Range("A2:A20").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlMultiply, _
SkipBlanks:=False, Transpose:=False這次,我們可以用上面的方法得到xlPasteAll、xlMultiply等常量的值,將上面的代碼python化即可;
利用這個方法,我們還可以很輕易得到某一列的最後一行的行號,比如A列的,可以這樣寫:
max_rowA=sht.cells(sht.Rows.Count,1).End(-4162).Row這回,你應該能看出來上面代碼中的-4162 是怎麼來的了。
希望上面列舉的示例,能給各位希望用python win32com.client來操作excel文件的童鞋,一點點借鑑和提示!還不趕緊動手試試?