近期有一个客户现场,需要他们自己的OA、ERP、PLM三个系统的自动化流程设计,在这些系统的交互过程中会产生EXCEL文件的编辑和处理,所以就涉及到了EXCEL文件的自动化处理。
说是自动化处理,第一个想到的方法肯定是使用Pandas库对数据进行一系列的编辑,但是不出意外就要出意外了,整个客户现场的环境都是加密的,系统下载的文件也全都是加密的,找客户的IT咨询了一下,回复是无法进行解密,需要自己想办法…
那没得办法,只能尝试去使用EXCEL软件去操作,但是,意外又发生了,当我使用EXCEL打开加密的文件时,还真打开了,因为登入使用的测试账户具有访问文件的权限,但是意外在哪?意外在在我使用EXCEL打开文件后的1min内,电脑直接强制关机了,后续咨询了客户的IT,说他们会有版权问题,只能使用WPS打开文件…
那能怎么办,继续捣鼓…
查找了一些资料,发现WPS是有COM接口的。所谓COM接口,COM(Component Object Model)是Windows系统的一种技术,用于不同程序之间的交互。WPS Office提供了COM接口,允许外部程序如Python通过win32com.client模块控制WPS的功能。
这下算是看到了曙光,继续查找资料,找到了各个文件类型对应的COM接口标识符。
EXCEL文件对应ET.ApplicationWORD文件对应Ket.ApplicationPPT文件对应WPP.Application
于是乎开始尝试,首先下载Python依赖
pip install pywin32
这里我以EXCEL为例,我们先创建一个WPS实例
import win32com.client
wps = win32com.client.Dispatch("ET.Application")
wps.Visible = True # 让wps实例在桌面可见
这样就创建好了一个实例,然后我们打开一个EXCEL文件,接着上文的代码添加
# 将excel_path修改成目标文件路径
workbook = wps.Workbooks.Open(excel_path)
# 读取excel中的sheet,指定sheet工作簿
sheet = workbook.Sheets(sheet_name)
这样我们的工作表对象和工作簿对象就都创建好了,后续就可以开始增删改查了,这里我写了几个方法,用来快速的读、写EXCEL文件
def read_wps_by_x_y(sheet, row_index, col_index):
"""
功能: 根据横、纵坐标读取EXCEL文件的值
sheet: 传入的工作簿对象
row_index: 要读取数据的横坐标
col_index: 要读取数据的纵坐标
返回值: 目标单元格的值
"""
return sheet.Cells(row_index,col_index).Value
def read_wps_by_line(workbook, sheet,start_row,end_row):
"""
功能: 读取EXCEL行
workbook: 工作表对象
sheet: 工作簿对象
start_row: 读取的第一行的索引
end_row: 读取的最后一行的索引
返回值: 读取的所有数据,二维数组
"""
data = []
# 按行读取数据
for row_index in range(start_row, end_row + 1):
row_data = []
col_index = 1
while sheet.Cells(row_index, col_index).Value is not None: # 读取每一列直到空单元格
row_data.append(sheet.Cells(row_index, col_index).Value)
col_index += 1
data.append(row_data)
return data
def write_wps_by_x_y(workbook,sheet, row_index, col_index, data):
"""
功能: 根据单元格坐标写入wps
workbook: 工作表对象
sheet: 工作簿对象
row_index: 要写入数据的横坐标
col_index: 要写入数据的纵坐标
data:写入值,置空表示清除单元格内容
"""
sheet.Cells(row_index, col_index).Value = data
workbook.Save()
def write_wps_by_line(workbook,sheet,data,start_row,start_col):
"""
功能: 写入一整行数据
workbook: 工作表对象
sheet: 工作簿对象
start_row: 开始写入行编号
start_col: 开始写入列标号
data: 要写入的数据,二维数组,表示多行,例如[[1,2,3],[4,5,6]]
"""
# 写入数据到表格
num_rows = len(data) # 数据的行数
print(f"读取到数据{num_rows}行")
num_cols = len(data[0]) # 数据的列数
sheet.Range(sheet.Cells(start_row, start_col), sheet.Cells(num_rows+start_row-1, num_cols)).Value = data
# 保存表格
workbook.Save()
def copy_sheet_to_excel_by_value(wps,workbook,sheet,save_path):
"""
功能: 将单独的sheet中的单元格都以值的格式保存到另一个excel文件
wps: wps实例
workbook: 工作表对象
sheet: 工作簿对象
save_path: 保存路径
"""
# 创建一个新的工作簿
new_workbook = wps.Workbooks.Add() # 新建工作簿
new_sheet = new_workbook.Sheets(1) # 获取新工作簿的第一个工作表
new_sheet.Name = sheet.Name
# 遍历原工作表的所有单元格,将公式转换为值
used_range = sheet.UsedRange # 获取工作表的已使用范围
for row in range(1, used_range.Rows.Count + 1): # 遍历行
for col in range(1, used_range.Columns.Count + 1):
cell = sheet.Cells(row, col)
# 复制值
new_sheet.Cells(row, col).Value = cell.Value
new_workbook.SaveAs(save_path)
new_workbook.Close()
def close_wps(wps, workbook):
"""
功能: 关闭WPS和工作表
wps: wps实例
workbook: 工作表对象
"""
# 关闭表格
workbook.Close()
wps.Quit()
这样就可以操作WPS来读取EXCEL表格了。
比如我要写入表格中的第1行第1列,写入123,可以直接调用方法
write_wps_by_x_y(workbook,sheet,1,1,"123")
比如我要读取表格中的第1行第1列的值,也可以直接调用方法
read_wps_by_x_y(sheet,1,1)
比如我要写入一整行数据,写到第1行,第1列开始,数据为[1,2,3,4,5,6],可以直接调用方法
write_wps_by_line(workbook,sheet,[[1,2,3,4,5,6]],1,1)
但是还是建议使用Pandas来操作EXCEL文件,但是如果遇到上面的这种情况,这种方法也可以当作备选方法,也可以很好的去解决实际的需求问题。
