zoukankan      html  css  js  c++  java
  • 巧用python win32com模块操作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()
        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文件的童鞋,一点点借鉴和提示!还不赶紧动手试试?

    =============================================================================================

    (2020-08-27日更新)

    再次查阅了微软的官方文档后,找到关于数据分列(TextToColumns)实现文本型数值转为常规数值的解决方法,见网址:https://docs.microsoft.com/en-us/office/vba/api/excel.range.texttocolumns

    详细内容如下:

    Parameters

    PARAMETERS
    NameRequired/OptionalData typeDescription
    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 XlTextParsingType The format of the text to be split into columns.
    TextQualifier Optional XlTextQualifier 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 XlColumnDataType 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)的代码是这样的,亲测可用:

    workNumSht.Columns("F:F").TextToColumns(Destination=workNumSht.Range("F1"), DataType=2, TrailingMinusNumbers=True)
  • 相关阅读:
    css之页面顶部阴影
    css之使用 :not() 在菜单上应用/取消应用边框
    CSS之黑白图像
    AMD/CMD规范
    HTTP学习笔记
    MUI之ajax获取后台接口数据
    Git提交代码规范
    Unicode与UTF-8/UTF-16/UTF-32的区别
    系统编程书籍推荐
    单口双线PC连接转换器 手机电脑耳机转接线
  • 原文地址:https://www.cnblogs.com/new-june/p/13568912.html
Copyright © 2011-2022 走看看