巧⽤pythonwin32com模块操作excel⽂件
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库,之后就可以使⽤了:
import win32com.client
下⾯的代码演⽰了⼀些常规的语法操作,与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()
widechartomultibyteSelection.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界⾯,见下图:
有了这些,上⾯的伪代码就可以改成如下形式,成功运⾏通过:
⼩爬知道了这些后,想⽤分列功能将excel某列⽂本型数值转为常规的数值格式,操作如动态所⽰,
think in java pdf
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"
爬虫软件 appRange("B2").Select
Selection.Copy
Range("A2:A20").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlMultiply, _
SkipBlanks:=False, Transpose:=False
这次,我们可以⽤上⾯的⽅法得到xlPasteAll、xlMultiply等常量的值,将上⾯的代码python化即可;
利⽤这个⽅法,我们还可以很轻易得到某⼀列的最后⼀⾏的⾏号,⽐如A列的,可以这样写:
max_lls(sht.Rows.Count,1).End(-4162).Row
这回,你应该能看出来上⾯代码中的-4162 是怎么来的了。
希望上⾯列举的⽰例,能给各位希望⽤python win32com.client来操作excel⽂件的童鞋,⼀点点借鉴和提⽰!还不赶紧动⼿试试?
=============================================================================================
(2020-08-27⽇更新)
详细内容如下:
Parameters
PARAMETERS
Name Required/Optional Data
type
Description
Destination Optional Variant A Range object that specifies where Microsoft Excel will place the results. If the range
is larger than a single cell, the top left cell is used.
DataType Optional The format of the text to be split into columns.
TextQualifier Optional Specifies whether to use single, double, or no quotes as the text qualifier.
ConsecutiveDelimiter Optional Variant True to have Excel consider consecutive delimiters as one delimiter. The default value is False.
Tab Optional Variant True to have DataType be xlDelimited and to have the tab character be a delimiter.
The default value is False.
Semicolon Optional Variant True to have DataType be xlDelimited and to have the semicolon be a delimiter. The
default value is False.
Comma Optional Variant True to have DataType be xlDelimited and to have the comma be a delimiter. The
default value is False.
Space Optional Variant True to have DataType be xlDelimited and to have the space character be a delimiter.
The default value is False.
Other Optional Variant True to have DataType be xlDelimited and to have the character specified by
the OtherChar argument be a delimiter. The default value is False.
OtherChar Optional Variant Required if Other is True; the delimiter character when Other is True. If more than one character is specified, only the first character of the string is used; the remaining characters are ignored.
FieldInfo Optional Variant An array containing parse information for the individual columns of data. The interpretation depends on the value of DataType.
When the data is delimited, this argument is an array of two-element arrays, with each two-element array specifying the conversion options for a particular column. The first element is the column number (1-based), and the second element is one of
the constants specifying how the column is parsed.
DecimalSeparator Optional Variant The decimal separator that Microsoft Excel uses when recognizing numbers. The
default setting is the system setting.
ThousandsSeparator Optional Variant The thousands separator that Excel uses when recognizing numbers. The default
setting is the system setting.
TrailingMinusNumbers Optional Variant Numbers that begin with a minus character.
可以看到关于excel录屏得到的VBA分列的代码中,“FieldInfo :=Array(1, 1)”,FieldInfo 字段是可选的,当我们并不准备把数据分成⼏列的时候,可以不需要该字段。⽐如我想要对F列进⾏分列,将⽂本型数字转为数字,pythonic(win32com.client)的代码是这样的,亲测可⽤:treasurer
workNumSht.Columns("F:F").TextToColumns(Destination=workNumSht.Range("F1"), DataType=2, TrailingMinusNumbers=True)
=============================================================================================
(2020-12-21⽇更新)
上⽂的⽅法中,当时⼩爬还没能到VBA中的Array类型如何利⽤python win32com模块来表达,现已到解决办法。我们知道在VBA中,如下代码就可以轻松将某⼀⾏值写⼊⼀个⼀维数组:
dim arr() as string
arr=sheet.Range("A1:M1").Value
我们就可以假定vba中的sheet.Range("A1:M1").Value 属性可以得到⼀个类似于Array(1,1)的数组对象。我们可以这样去验证这个vba数组对象在python win32com中是如何实现的。我试着利⽤win32com模块来print(type(sht.Range("A1:B1").Value)),结果系统返回了⼀个Tuple元组类型。
这个时候,我们VBA中录制得到的分列功能(TextToColumns)就可以随意python化了。⽐如下图中,我们希望将B列的字母和数字分开成两列:
VBA录制宏得到这段分列的代码如下:
Sub宏1()
'
'
Columns("B:B").Select
Selection.TextToColumns Destination:=Range("B1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=False, _
Semicolon:=False, Comma:=False, Space:=False, Other:=True, OtherChar _
:="_", FieldInfo:=Array(Array(1, 1), Array(2, 1)), TrailingMinusNumbers:=True
dev c++下载End Sub
我们在python win32com.client中可以这样表达:
xlDelimited=1
xlDoubleQuote=1
sht.Columns("B:B").TextToColumns(Destination=sht.Range("B1"), DataType=xlDelimited,
TextQualifier=xlDoubleQuote, ConsecutiveDelimiter=False, Tab=False, Semicolon=False,
Comma=False, Space=False, Other=True, OtherChar ="_", FieldInfo=((1, 1),(2,1)),
TrailingMinusNumbers=True)
该⽅法亲测可⽤,特此奉上~~~
快来扫码关注我的获取更多爬⾍、数据分析的知识!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论