Python 自动化教程(1) 概述,第一篇 Excel自动化首篇

人生苦短, 我用Python!  Python语法简炼、易上手,且有丰富的库可用,实现一个应用很简洁。

Python常用于自动化。自动化的基本含义,是把人的动作写成程序,让计算机代替人工作。主要分为几类:

1、自动化办公:对excel、word、ppt等office文档或pdf进行批量化、自动化等处理。

2、自动化媒体处理:对图片、视频等媒体文件进行批量化、自动化等处理。

3、自动化机器人:比如微信客服/聊天机器人、网站操作/录入、网络爬虫/网页信息抓取、自动化数据服务等

由于python开发社区的广泛性,各类自动化python都有对应的库,可以很方便的调用。

本系列教程旨在示范各类典型的自动化、理解相关库及其编程使用方法。

学习者需要有Python基础编程知识。

开发环境是:Python3,  PyCharm IDE, 操作系统:Win10

 系列教程:

Python 自动化教程(1) 概述,第一篇 Excel自动化

Python 自动化教程(2) : Excel自动化:使用pandas库

Python 自动化教程(3) : 自动生成PPT文件 Part 1

Python 自动化教程(4) : 自动生成PPT文件 Part 2

Python 自动化教程(5) : 自动生成Word文件

Python 自动化教程(6) : PDF文件处理​​​​​​​

第一篇  Excel自动化

Excel自动化,是用Python程序创建、编辑、修改Excel文件,处理其中的数据,从而无人化、大批量处理excel文件数据。

处理excel常用的库有:openpyxl、xlwings、xlrd、xlwt等。数据处理的库常用 pandas

这里主要讲 openpyxl、xlwings、pandas 三个库。

一、首先用 PIP 安装 openpyxl、xlwings、pandas 库

打开命令行窗口,分别输入三行命令

pip install openpyxl
pip install xlwings
pip install pandas

为快速下载,可以使用 阿里云 镜像 (pandas 库比较大)

pip install openpyxl -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
pip install xlwings  -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
pip install pandas  -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com

二、Excel的基本概念

WorkBook (工作簿) 一个Excel文件就是一个WorkBook(工作簿)

WorkSheet(工作表)  一个WorkBook(工作簿)中包含多张WorkSheet工作表。每个WorkSheet有一个标题(title), 如:Sheet1

Cell (单元格),  一个WorkSheet工作表包含多个单元格。一个单元格有行号、列号。例如:B3

Reference Address (引用地址):  B3 表示一个单元格, B3:D6 表示一个区域(Range),包含多个单元格。  Sheet2!B3:D6 表示 工作表Sheet2中的 B3:D6 这个区域

三、openpyxl 库的基本使用方法

用PyCharm创建一个新项目,创建一个新的.py文件,在程序开头引用 openpyxl

import openpyxl

import openpyxl as xl
import openpyxl as xl 是将openpyxl库起一个别名xl,  以便后续程序简化书写

1, 打开Excel文件, 打印所有的工作表标题

import openpyxl as xl

filename = "202201报表.xlsx"

# 打开excel文件,取得workbook对象
workbook = xl.load_workbook(filename)

# 列出所有worksheet
for worksheet in workbook:
    print(type(worksheet), worksheet.title)  # 打印worksheet的类型, 标题

其中:excel文件 202201报表.xlsx 是这样的。 py程序和excel文件可以在此下载

注意:

1、由于程序中未指明文件路径,因此要将 202201报表.xlsx 文件放在 .py程序文件同一目录下。

2、openpyxl 库只支持  .xlsx 文件, 不支持 后缀为 .xls 的老格式excel文件(Excel 2003之前的)。

3、如果执行程序时, excel文件正在被 Excel程序打开,会因为共享冲突而出错。

PermissionError: [Errno 13] Permission denied: '202201报表.xlsx'

运行程序,结果如下

<class 'openpyxl.worksheet.worksheet.Worksheet'> 商品销售
<class 'openpyxl.worksheet.worksheet.Worksheet'> 客户
<class 'openpyxl.worksheet.worksheet.Worksheet'> 库存
<class 'openpyxl.worksheet.worksheet.Worksheet'> 汇总

说明:

1、workbook = xl.load_workbook(filename) 打开文件。

      如果要创建新的excel文件。一般情况下,是复制一个模板文件到新的文件。

      例如:

import shutil

template_file = "报表模板.xlsx"
new_file = "新报表.xlsx"
# 使用shutil库的copyfile()函数复制文件,如new_file文件不存在则创建新文件
shutil.copyfile(template_file, new_file)

2、xl.load_workbook(filename)的返回值 workbook 是一个Workbook对象

3、通过 for worksheet in workbook: 循环可以获得每一张工作表 Worksheet对象

2, 通过标题,取得WorkSheet

# 如果 workbook 中有名为 '商品销售' 的 worksheet
if '商品销售' in workbook:
    # 取得 worksheet
    worksheet = workbook['商品销售']

3、通过地址取得单元格Cell对象, 读取单元格的值、修改值

# 取得一个单元格
cell = worksheet["B3"]
print(type(cell))

# 取得单元格的值
print(cell.value)

# 取得单元格的行号(数字, 第一行列为1), 列号(数字, A列为1)
print('row, col=', cell.row, cell.column)

# 取得单元格的另一个方法:使用row, col 数字
row = 3
col = 2
cell2 = worksheet.cell(row, col)  # 相当于 B3

# 写入单元格的值
cell2.value = "北京"

运行程序,结果如下

<class 'openpyxl.cell.cell.Cell'>
深圳
row, col= 3 2

说明:

1、worksheet[address] 返回一个 Cell对象。  cell.value 可以读取或写入值

     如果cell中有公式,则 cell.value 返回公式字符串,如: '= B2 + D2',  如果要修改公式,直接将公式字符串赋值给 cell.value即可。例如: cell.value = '=B3+D2'

2、cell.row 取得单元格的行(整数,第一行是1) 

      cell.column 取得单元格的列(整数,A列 是1,依次类推) 

3、取得单元格B3有两个写法: 第一种是使用引用地址字符串: worksheet['B3']

第二种是使用 行、列数值, 如: worksheet(row=3, column=2)  , 第二种便于书写循环程序,批量读取数值, 例如:

for row in range(1, 11):
    for col in range(1, 5):
        print(worksheet.cell(row, col).value)

4、通过地址取得一个区域(多个单元格), 读取区域的值

# 取得一个区域
range1 = worksheet['A1:B5']
print(range1)

# 取得区域内所有单元格的值
data = []
for row in range1:
    row_values = []
    for cell in row:
        row_values.append(cell.value)
    data.append(row_values)
print(data)

运行程序,结果如下

((<Cell '商品销售'.A1>, <Cell '商品销售'.B1>), (<Cell '商品销售'.A2>, <Cell '商品销售'.B2>), (<Cell '商品销售'.A3>, <Cell '商品销售'.B3>))
[['地区分类', '城市'], ['二类', '广州'], ['一类', '北京']]

说明:

range1 = worksheet['A1:B3']   # 取A1: B3区域

print(range1) 显示 range1 是一个tuple,  其中每一个子元素是一行(多个cell对象的 tuple),共3行,即range tuple包含了多个行、多个列的cell

for row in range1  这个循环列出每一行

for cell in row  这个循环列出一行内的每一个cell

row_values 是一行的数值列表

data 是所有数据的列表, print(data) 显示出所有cell的值

5、Worksheet 的最大行数、最大列数

# 工作表的最大行数
print(worksheet.max_row)

# 工作表的最大行数
print(worksheet.max_column)

工作表实际使用的最大行数、最大列数

6、保存文件(保存WorkBook),关闭文件(关闭WorkBook)

# 保存文件
workbook.save(filename)

# 关闭文件
workbook.close()

保存WorkBook,则将数据修改存入文件了。不保存直接关闭,修改就丢了。

7、openpyxl 库小结

以上是 openpyxl 库的基本操作,常规工作中基本够用了。比如:

(1) 合并报表:每个月有一个报表,通过python读取多个文件,写入另一个汇总文件。

(2)拆分报表:将一个汇总表,生成多个子表。

(3)读取或写入数据

 (4)修改图表: 在excel文件中预先手工生成图表,修改数据即可更新图表。

openpyxl库还可以处理单元格的颜色、字体、边框,创建图表等复杂操作。但平时用的很少。一般情况,我们手工创建 excel文件模板、编写好公式、画好图表,python程序读写数值即可。

三、xlwings 库的基本使用方法

     与openpyxl库一样, xlwings库可以读写excel文件。不同的是, xlwings库是调用本机安装的Microsoft Excel程序打开并读写excel文件,因此运行 python程序的本机必须安装Excel程序。相反,openpyxl库不依赖Excel程序,因此openpyxl可以在linux服务器上使用。 同时,由于xlwings使用Microsoft Excel, 因此能打开老式的 .xls文件,  具有Microsoft Excel所具备的一切能力。

1, 使用xlwings打开Excel文件, 打印所有的工作表标题

import xlwings as xw

# 创建 App对象
app = xw.App(visible=True, add_book=False)
print(type(app))

# 使用App对象, 打开excel文件
filename = "202201报表.xlsx"
workbook = app.books.open(filename)
print(type(workbook))

# 列出所有 worksheet
for sheet in workbook.sheets:
    print(type(sheet), sheet.name)  # 注意:要使用 sheet.name 取得工作表标题

workbook.close()
app.quit()  # 退出Excel程序

运行结果:

<class 'xlwings.main.App'>
<class 'xlwings.main.Book'>
<class 'xlwings.main.Sheet'> 商品销售
<class 'xlwings.main.Sheet'> 客户
<class 'xlwings.main.Sheet'> 库存
<class 'xlwings.main.Sheet'> 汇总

说明:

1, 与openpyxl库不同, 使用xlwings库时,首先要创建 App对象,再用App对象打开excel文件
      app = xw.App(visible=True, add_book=False)。 一个App对象就是 一个Excel程序实例。

     visible=True 表示显示Microsoft Excel界面。运行时可以看到Excel界面出现了。

     add_book=False 表示打开Excel 程序时,不添加空白工作表

2,  通过 for worksheet in workbook: 循环可以获得每一张工作表 (与openpyxl库一样)

3,使用 worksheet.name 取得工作表标题。 (与openpyxl库使用 worksheet.title 不同)

4,由于是使用Excel程序打开文件,打开后文件被锁定,其他程序将无法同时读写该excel文件。

5,结束前,要调用  app.quit()  退出Excel程序 (否则Excel程序将不会关闭)

2, 通过标题,取得WorkSheet

# 取得 标题是 '商品销售' 的 worksheet
worksheet = workbook.sheets('商品销售')
print(type(worksheet))

说明:  xlwings库不支持  in 写法:    if  '标题' in workbook

3、通过地址取得单元格, 读取单元格的值、修改值

# 取得一个单元格 B3
cell = worksheet['B3']
print(type(cell), cell.value)  # 打印cell的类型, 读取cell的值

# 设置单元格的值
cell.value = "新城"

# 取得单元格的行号(数字, 第一行列为1), 列号(数字, A列为1)
print('row, col=', cell.row, cell.column)

# 取得 E2 格中的公式、 值
print(worksheet['E2'].formula, worksheet['E2'].value)

说明:

(1)、worksheet[address] 返回一个 Range 对象。  cell.value 可以读取或写入值

(2)、cell.row 取得单元格的行(整数,第一行是1) 

      cell.column 取得单元格的列(整数,A列 是1,依次类推) 

(3)、使用 cell.formula 读取或设置单元格的公式,  使用 cell.value读取或设置单元格的值

# 另一种方式:使用row, col 数字取得 B3 单元格
row = 3
col = 2
cell2 = worksheet.cells(row, col)
print(type(cell2), cell2.value)

(4)、取得单元格B3的第二种写法是使用 行、列数值, 如: worksheet(row, column) 

 4、通过地址取得一个区域(多个单元格), 读取区域的值

# 取得一个区域
range1 = worksheet['A1:B3']

# 取得区域内所有单元格胡值
print(range1.value)

运行结果:

<class 'xlwings.main.Range'> 新城
[['地区分类', '城市'], ['二类', '广州'], ['一类', '新城']]

可以看到:   range1.value 直接返回一个 list, 每个元素表示一行,直接是各单元格的值。(这个比openpyxl 方便一点)

5、保存文件(保存WorkBook),关闭文件(关闭WorkBook)、退出App

# workbook 保存
workbook.save(filename)

# workbook 关闭
workbook.close()

# 注意:要退出 app(即关闭Microsoft Excel程序)
app.quit()

6、xlwings 库基本用法小结

xlwings 库用法与 openpyxl库 大同小异。

7、xlwings库的特殊用法:在Microsoft Excel程序中调用 python程序

    xlwings 库有一个很好用的功能:将python程序作为Microsoft Excel的插件/扩展程序运行,就是说,无需打开Python 或 PyCharm, 在Excel程序中直接运行python。另外,也可以用python语言为Exce编写用户自定义函数(User Defined Function, 简称UDF), 扩展Excel的功能。

    众所周知, Microsoft Office程序(包括Excel) 支持 以Visual Basic for Application 或 CSharp 语言编写扩展程序,允许用户增强Excel的功能。 xlwings作为python与Excel的桥梁,支持将python程序作为Microsoft Excel的插件/扩展程序运行。

    使用方法如下。

     首先,关闭Excel程序, 打开命令行窗口,输入以下命令,安装 xlwings for Excel 的插件 (addin). 

xlwings addin install

运行结果:表明xlwings for Excel 的插件(addin) 安装成功。

xlwings version: 0.27.11
Successfully installed the xlwings add-in! Please restart Excel.
There is already an existing ~/.xlwings/xlwings.conf file. Run 'xlwings config create --force' if you want to reset your configuration.

   然后, 重新启动Microsoft Excel程序, 则可以看到 Excel 多了一个名为 xlwings 的菜单页

 菜单页上有多个选项和文本框,不用管它们。我们只使用上图最左边红色方框指示的 "Run Main"这个按钮就够了。

按下 "Run Main" 按钮会发生什么呢?

比如:当前打开的文件名是 abcd.xlsx, 当按下 "Run Main" 按钮,Excel会调用xlwings库,xlwings库将寻找 与 abcd.xlsx 文件同一个目录下的同名.py文件 (即:abcd.py), 运行这个python文件中的 main() 函数。  main() 函数以python编写,写什么内容都行,比如:可以从网络、或数据库读取数据,再写入工作表中。

注意:

1、xlwings库不支持中文名的.py文件。因此,使用该功能的excel文件名不能包含中文(否则出错)。

2、xlwings库将以import 模块的方式加载 .py文件。 因此,使用该功能的excel文件名必须以英文字母开头、且不能包含空格、特殊字符等,excel文件名必须是一个合法的python变量名,且不能与已有的python库重名。否则出错。

3、本人认为,上述两点是xlwings库的bug。 没办法只能遵守。 (PS: 本人将xlwings addin 改了一下,可不受此限制)

实战:

将 “202201报表.xlsx” 文件复制一份,改名为 abcd.xlsx,  在同目录下编写一个名为 abcd.py 程序文件。程序如下:

import xlwings as xw


def main():
    # 获得调用本程序的 workbook
    workbook = xw.Book.caller()
    # 获得当前激活的 worksheet
    worksheet = xw.sheets.active
    # 在 B9 单元格中写入一个数值
    worksheet['B9'].value = "你好,我来了"

abcd.py 中只定义了一个 main() 函数, 该函数无输入参数。

代码注释写得很清楚: 首先用 xw.Book.caller() 获得调用本程序的 workbook对象,然后,取得当前工作表,在单元格B12中写入一串文字。

用Excel程序打开abcd.xlsx,  点击 xlwings菜单的 "run main"按钮, 运行效果如下:

 如图: 在Excel程序中,点击 xlwings 菜单中的 Run main 按钮(左上红框), B9单元格(蓝框) 将自动写入python程序运行的结果。

实际上,  .py程序可以是任意合法的python程序,可以调用各种库、写多个函数。

xlwings为扩展Excel功能提供了无限的潜力和想象力.

比如:  读取Excel单元格中的股票名称,到网络上查出该股票当前价格。

             读取Excel单元格中的人员名称,在数据库中查出该人员上班有否迟到。

总之,运行python, 一切都可行。

xlwings for Excel 插件功能是否很棒呢!

本篇小结:

本篇讲解了 openpyxl, xlwings库的基本用法。py程序和excel文件可以在此下载

事实上,在处理excel 大数据量的时候,我们直接使用 pandas 库就可以了,pandas 将调用openpyxl 或 xlwings库读写excel文件。往往我们将不需要直接使用openpyxl, xlwings库,但了解这两个库对深入理解pandas是有必要的。

下一篇,我们将讲解 pandas 库,操作excel数据。

练习作业及其答案:

1,写一个python程序,在excel文件 ”202201报表.xlsx“ 的 "商品销售" Worksheet 上 自动找到 值为 "广州" 的单元格

答案:

import openpyxl

def find(sheet1, value):
    """ 在sheet1中查找值为value的单元格, 找到到返回Cell对象,找不到则返回None"""
    for row in range(1, sheet1.max_row + 1):
        for col in range(1, sheet1.max_column + 1):
            cell = sheet1.cell(row, col)
            if cell.value == value:
                return cell


filename = "202201报表.xlsx"
workbook = openpyxl.load_workbook(filename)
cell = find(workbook['商品销售'], '广州')
print(cell)

运行结果:  <Cell '商品销售'.B2>

2,  写一个python程序,在excel文件 ”202201报表.xlsx“ 的 "商品销售" Worksheet 上 自动找到两个值    "广州",  "金额" 的两个单元格交叉的单元格的值, 就是说:找到广州的金额

import openpyxl

def find(sheet1, value):
    """ 在sheet1中查找值为value的单元格, 找到返回Cell对象,找不到则返回None"""
    for row in range(1, sheet1.max_row + 1):
        for col in range(1, sheet1.max_column + 1):
            cell = sheet1.cell(row, col)
            if cell.value == value:
                return cell


def find2(sheet1, value1, value2):
    """ 在sheet1中查找值为value1, value2的两个单元格, 返回其交叉的Cell,找不到则返回None"""
    cell1 = find(sheet1, value1)
    cell2 = find(sheet1, value2)
    if cell1 and cell2:
        return sheet1.cell(cell1.row, cell2.column)


def find_file(filename, sheetname, value1, value2):
    """ 在文件中,指定工作表名, 查找值为value1, value2的两个单元格, 返回其交叉的Cell,找不到则返回None"""
    workbook = openpyxl.load_workbook(filename)
    if sheetname in workbook:
        return find2(workbook[sheetname], value1, value2)


# 使用范例: 查找 商品销售表中 广州的金额
cell = find_file("202201报表.xlsx", '商品销售', '广州', '金额')
if cell:
    print(cell.value)
else:
    print('not found')

运行结果:  1003

找到广州的金额是1003

这个是有用的,比如说:每月有一个报表文件,我们要找到某个月,某业务,某地区的金额。

使用场景可以是:  你对微信机器人讲,请找2022年1月广州商品销售金额。机器人分析后,定位为202201报表.xlsx文件,把数据找出来,回答你。这个故事我们将在随后的章节中实现它。

3,  在excel文件 ”202201报表.xlsx“ 的 "库存" Worksheet 上, 表格的位置不是从 A1开始的。

 请编写一个python程序, 自动找到 "库存" Worksheet中的表格。

import openpyxl


def find_first_cell(sheet1):
    """ 在sheet1中查找值不为空的第一个单元格, 找到返回Cell对象,找不到则返回None"""
    for row in range(1, sheet1.max_row + 1):
        for col in range(1, sheet1.max_column + 1):
            cell = sheet1.cell(row, col)
            if cell.value is not None:
                return cell


def expand_column(cell):
    """ 从单元格cell出发,水平向右查找,找到最后一个不为空值的Cell对象 """
    for col in range(cell.column + 1, cell.parent.max_column + 2):
        c = cell.parent.cell(cell.row, col)
        if c.value is None:
            return cell.parent.cell(cell.row, col - 1)


def expand_row(cell):
    """ 从单元格cell出发,垂直向下查找,找到最后一个不为空值的Cell对象 """
    for row in range(cell.row + 1, cell.parent.max_row + 2):
        c = cell.parent.cell(row, cell.column)
        if c.value is None:
            return cell.parent.cell(row - 1, cell.column)


def find_table(sheet1):
    """ 查找sheet1中的首个表格。 返回 tuple, 每一个元素是一行Cell.  找不到则返回空的tuple """
    result = []
    cell = find_first_cell(sheet1)  # 查找值不为空的第一个单元格
    if cell:
        cell1 = expand_column(cell)  # 向右扩展
        cell2 = expand_row(cell)  # 向下扩展
        if cell1 and cell2:
            # 构造返回值
            for row in range(cell.row, cell2.row + 1):
                r = []
                for col in range(cell.column, cell1.column + 1):
                    r.append(cell.parent.cell(row, col))
                result.append(tuple(r))
    return tuple(result)



# 使用范例
filename = "202201报表.xlsx"
workbook = openpyxl.load_workbook(filename)
sheet1 = workbook['库存']
area = find_table(sheet1)
if len(area) > 0:
    print(area)
else:
    print("not found")

运行结果:  

((<Cell '库存'.B6>, <Cell '库存'.C6>, <Cell '库存'.D6>), (<Cell '库存'.B7>, <Cell '库存'.C7>,...

这个结果与使用   sheet['B6:D10'] 返回值是一样的。

使用场景可以是:  你对微信机器人讲,请查一下库存情况。机器人分析后,定位为当前 月份是202201,  查找202201报表.xlsx文件的库存工作表,把表格找出来,列个表回答你。

猜你喜欢

转载自blog.csdn.net/c80486/article/details/126073783