1.word 

from docx import Document
# -*- coding: utf-8 -*-
import os
from docx import Document
import win32com.client
import datetime
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
i = datetime.datetime.now()
date = ("%s年%02d月%02d日" % (i.year, i.month, i.day))
time = ("%02d时%02d分%02d秒" % (i.hour, i.minute, i.second))  # 小时前有个空格为了send_email查找前两个字符转int型方便

Docx = Document()
Docx.add_heading("这是一个一级标题", level=1)
Docx.add_paragraph("更新于"+time, "Title").alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT


A = Docx.add_paragraph("My name is aaa")
A.add_run("我学习的很快乐,啊哈哈哈哈哈,非常好 Good!!!")
Docx.add_heading("这是一个二级标题", level=2)
A = Docx.add_paragraph("这个是二级标题的内容呀")
B = A.add_run("二级标题里面的正文 继续添加!!!!!!!")
B.font.bold = True  # 同时我要对这些正文进行加粗~~~~
B.font.size = (20)
Docx.add_heading("我爱学习Python以下就是python的logo呀", level=3)
# Docx.add_picture("1.png")
Docx.add_table(rows=5, cols=5)
Docx.save("D:\\Python.docx")

win32com 在word实现

读取图片处理

import win32com.client

def set_image_format(doc_path):
    """
    设置Word文档中第一张图片的格式,包括大小、文字环绕和距正文的距离。

    Parameters:
    - doc_path (str): Word文档的文件路径。

    Returns:
    无
    """
    # 打开Word应用
    word = win32com.client.gencache.EnsureDispatch('kwps.Application')
    word.Visible = True

    # 打开文档
    doc = word.Documents.Open(doc_path)

    # 获取文档中的所有内联形状(包括图片)
    inline_shapes = doc.InlineShapes

    # 获取第一个内联形状
    if inline_shapes.Count >= 1:
        first_image = inline_shapes(1)

        # 将内联形状转换为形状对象
        shape = first_image.ConvertToShape()

        # 设置图片大小
        shape.LockAspectRatio = 0  # 允许调整宽度和高度独立
        shape.Width = word.CentimetersToPoints(14.65)  # 设置宽度
        shape.Height = word.CentimetersToPoints(5.69)  # 设置高度

        # 设置文字环绕
        shape.WrapFormat.Type = win32com.client.constants.wdWrapSquare  # 四周型
        shape.WrapFormat.Side = win32com.client.constants.wdWrapBoth  # 环绕文字两边

        # 设置距正文的距离
        shape.WrapFormat.DistanceTop = 0  # 上:0厘米
        shape.WrapFormat.DistanceBottom = 0  # 下:0厘米
        shape.WrapFormat.DistanceLeft = word.CentimetersToPoints(0.32)  # 左:0.32厘米
        shape.WrapFormat.DistanceRight = word.CentimetersToPoints(0.32)  # 右:0.32厘米

    # 保存并关闭文档
    doc.Save()
    doc.Close()

读取图表处理

import win32com.client


def set_chart_format(doc_path):
    """
    设置Word文档中第一个图表的格式,包括大小、文字环绕和距正文的距离。

    Parameters:
    - doc_path (str): Word文档的文件路径。

    Returns:
    无
    """
    # 打开Word应用
    word = win32com.client.gencache.EnsureDispatch('kwps.Application')
    word.Visible = True

    # 打开文档
    doc = word.Documents.Open(doc_path)

    # 获取文档中的所有形状
    shapes = doc.Shapes

    # 获取第一个图表
    first_chart = shapes(1)

    if first_chart:
        # 设置图表大小
        first_chart.Width = word.CentimetersToPoints(14.65)
        first_chart.Height = word.CentimetersToPoints(5.69)

        # 设置文字环绕
        first_chart.WrapFormat.Type = win32com.client.constants.wdWrapSquare  # 四周型
        first_chart.WrapFormat.Side = win32com.client.constants.wdWrapBoth  # 环绕文字两边

        # 设置距正文的距离
        first_chart.WrapFormat.DistanceTop = 0  # 上:0厘米
        first_chart.WrapFormat.DistanceBottom = 0  # 下:0厘米
        first_chart.WrapFormat.DistanceLeft = word.CentimetersToPoints(0.32)  # 左:0.32厘米
        first_chart.WrapFormat.DistanceRight = word.CentimetersToPoints(0.32)  # 右:0.32厘米

        # 设置位置为页边距
        first_chart.RelativeHorizontalPosition = 1  # 1代表页边距
        first_chart.RelativeVerticalPosition = 1  # 1代表页边距

    # 保存并关闭文档
    doc.Save()
    doc.Close()

读取表格处理,复制、设置格式

import win32com.client
def copy_table_data(source_doc_path, target_doc_path, table=1):
    """
    复制源Word文档中的表格数据到目标文档中,同时设置格式。

    Parameters:
    - source_doc_path (str): 源Word文档的文件路径。
    - target_doc_path (str): 目标Word文档的文件路径。
    - table (int): 要复制的表格的索引,默认为1。

    Returns:
    无
    """
    # 打开Word应用
    word = win32com.client.Dispatch('KWPS.Application')

    # 打开源文档
    source_doc = word.Documents.Open(source_doc_path)
    source_table = source_doc.Tables.Item(table)  # 获取第几个表格

    # 打开目标文档
    target_doc = word.Documents.Open(target_doc_path)
    target_table = target_doc.Tables.Item(table) # 获取第几个表格

    # 复制源表格的数据到目标表格,并设置格式
    for row in range(1, source_table.Rows.Count + 1):
        for col in range(1, source_table.Columns.Count + 1):
            try:
                text = source_table.Cell(row, col).Range.Text.strip().replace('\n', '').replace('\r', '').replace('\x07', '')
                if text:
                    target_table.Cell(row, col).Range.Text = text

                # 设置单元格格式
                cell_range = target_table.Cell(row, col).Range
                cell_range.Font.Name = 'Times New Roman'  # 字体选择:Times New Roman
                cell_range.Font.Size = 10.5  # 字号:五号
                cell_range.Font.NameFarEast = '仿宋_GB2312'  # 汉字字体:仿宋_GB2312

                # 设置特定行的格式
                if table == 1:
                    if col in [5, 9, 13, 17, 18, 19]:  # 列索引[5, 9, 13, 17, 18, 19]
                        cell_range.Font.Bold = True
                    elif '合计' in text or '月均' in text:
                        cell_range.Font.Bold = True
                    else:
                        cell_range.Font.Bold = False

                elif table == 2:
                    if 'XXXX有限公司' in text:
                        for col in range(1, target_table.Columns.Count + 1):
                            target_table.Cell(row, col).Range.Font.Bold = True

            except Exception as e:
                pass

    # 关闭文档和Word应用
    source_doc.Close()
    target_doc.Save()
    target_doc.Close()

# 请注意,上述代码中的路径和索引可能需要根据实际情况进行调整。

2.excel


#!/usr/bin/env python3
# coding: utf-8
import xlrd
import xlwt
# 打开excel文件,创建一个workbook对象,book对象也就是fruits.xlsx文件,表含有sheet名
rbook = xlrd.open_workbook("C:\\Users\\yys53\\Desktop\\333(1).xlsx")
# sheets方法返回对象列表,[<xlrd.sheet.Sheet object at 0x103f147f0>]
rbook.sheets()
# xls默认有3个工作簿,Sheet1,Sheet2,Sheet3
rsheet = rbook.sheet_by_index(0)  # 取第一个工作簿
import re
# 循环工作簿的所有行
i = 0
workbook = xlwt.Workbook(encoding='gbk')
sheet = workbook.add_sheet("Miss")

for row in rsheet.get_rows():
    i += 1
    if i <=14:
        a = re.compile("(.*?)(\\d+).*?(\d+.\d{15})", re.S).findall(row[0].value)
        if a:
            print(a[0])
            sheet.write(i, 0, a[0][0].strip())
            sheet.write(i, 1, a[0][1].strip())
            sheet.write(i, 2, a[0][2].strip())
            style = xlwt.easyxf('align: wrap on')
            sheet.col(0).width = 256 * 20
        else:
            print(row[0].value)
    if i > 14:
        # print(row[0].value)
        a = re.compile("KEGG_PATHWAY    hsa\\d+:(.*?)(\\d+).*?(\d+.\d{15}).*?", re.S).findall(row[0].value)
        if a:
            print(a[0])
            sheet.write(i, 0, a[0][0].strip())
            sheet.write(i, 1, a[0][1].strip())
            sheet.write(i, 2, a[0][2].strip())

            sheet.col(0).width = 256 * 20
            workbook.save('text.xls')

2.1win32com

win32com.client.Dispatch  win32.gencache.EnsureDispatch 都是用于创建 Python 中的 COM 对象实例的方法,用于与外部的 COM 组件(例如 Microsoft Office 应用程序、Windows 脚本宿主等)进行交互。下面是它们之间的主要区别:

  1. win32com.client.Dispatch
    • 这是 pywin32 包中的标准方法,用于动态地创建 COM 对象实例。
    • 在每次调用 Dispatch 方法时,都会在运行时检查注册表以查找适当的 COM 对象,因此会稍微耗费一些时间。
    • 适用于不确定对象类型或需要在运行时动态创建 COM 对象的情况。

示例:

import win32com.client

excel = win32com.client.Dispatch("Excel.Application")
word = win32com.client.Dispatch("Word.Application")

 

  1. win32.gencache.EnsureDispatch
    • 这是 pywin32 包中的另一种方法,用于创建 COM 对象实例。不同之处在于,它会在第一次调用时自动生成一个缓存的 Python 类,以加快后续调用。
    • 第一次调用时,会生成 COM 对象的缓存 Python 类并存储在磁盘上,之后的调用将直接使用这个缓存的类,避免了运行时的注册表查找,因此速度更快。
    • 适用于频繁地使用相同类型的 COM 对象,因为第一次创建时可能会有稍微的延迟。

示例:

import win32.gencache

excel = win32.gencache.EnsureDispatch("Excel.Application")
word = win32.gencache.EnsureDispatch("Word.Application")

总结:如果您在代码中频繁地使用相同类型的 COM 对象,EnsureDispatch 可能会更有效,因为它在第一次创建后会自动生成缓存。如果您需要动态地创建不同类型的 COM 对象,或者对速度要求不是很高,可以使用 Dispatch 方法。

win32.gencache.EnsureDispatch 在性能方面通常会更快,因为它在第一次调用时会生成缓存的 Python 类,之后的调用会直接使用这个缓存的类,避免了运行时的注册表查找。这样可以减少对注册表的访问并加速 COM 对象的创建。

另一方面,win32com.client.Dispatch 是在每次调用时都会在运行时检查注册表来查找适当的 COM 对象,因此可能会稍微耗费一些时间。

总的来说,如果您在代码中频繁地使用相同类型的 COM 对象,win32.gencache.EnsureDispatch 可能会更有效,因为它会在第一次创建后生成缓存,并且后续的调用会受益于这个缓存。如果您需要动态地创建不同类型的 COM 对象,或者对速度要求不是很高,win32com.client.Dispatch 也是一个合适的选择。最终的选择取决于您的使用场景和性能需求。

需要安装pypiwin32

pip install pypiwin32
import win32com.client as win32
from win32com.client import constants

xls_app = win32.Dispatch('ket.Application')
file_name = r"C:\Users\yys53\PycharmProjects\untitled1\data.xlsx"
# xls_app = xls_app.Workbooks.Open(file_name)

# wb = xls_app.Workbooks.Add()
wb = xls_app.Workbooks.Open(file_name)
# wb = xls_app.Workbooks.Add() # excel不存在时候可以创建
ws = wb.Worksheets(1)
ws.Name = 'my_new_sheet'
xls_app.Visible = True

# wb.SaveAs('New_workbook.xlsx')
# 添加数据
ws.Range("A1").Value = "1"
ws.Range("A2").Value = "2"
ws.Range("A3").Value = "3"
ws.Range("A4").Value = "2"
ws.Range("A5").Value = "1"
ws.Range("A6").Value = "-1"
#ws.Range("A2", "C2").Value = "23" # 写入多列

# ws.column_dimensions["A"].hidden = True
# # 隐藏列
# ws.Columns("C").EntireColumn.Hidden = True
# # 隐藏行
# ws.Rows(3).EntireRow.Hidden = True
# 添加折线
# XlChartType 图表的类型
# left和top是按照像素来配置图表插入的位置
# def hidden_column(path, column, sheet_name=0):
#     '''
#     :param path: 文件路径
#     :param column: 列名,如A,B,C,可以传入单个,可以是区间[B,E]
#     :return:
#     '''
#     try:
#         wb = load_workbook(path, data_only=True)
#         if isinstance(sheet_name, str):
#             ws = wb.get_sheet_by_name(sheet_name)
#         else:
#             ws = wb.worksheets[sheet_name]
#         if isinstance(column, list):
#             ws.column_dimensions.group(column[0], column[1], hidden=True)
#         else:
#             ws.column_dimensions[column].hidden = True
#         wb.save(path)
#     except Exception as e:
#         print("打开文件失败:%s" % e)

new_shape=ws.Shapes.AddChart2(Left=20,Top=10)#
chart=new_shape.Chart
chart.ChartType = constants.xlXYScatterLines# 设置图表的类型
chart.SetSourceData(Source=ws.Range("A1:A6"))
# wb.ActiveChart.ChartTitle.Text = "图表"
# wb.ActiveChart.Delete('图表 1')
# my_new_sheet
# cha1 = ws.chart

# 设置标题ChartObjects(1)代表第一个图表
cha1 = wb.Worksheets("my_new_sheet").ChartObjects(1).Chart

cha1.HasTitle = True
wb.ActiveChart.ChartTitle.Text = "图表2"

wb.Save()

xls_app.Quit()
del xls_app

注意(我的wps用的ket版本的)

win32com.client.Dispatch("et.Application")#wps正式版
win32com.client.Dispatch("ket.Application")#wps抢先版
win32com.client.Dispatch("EXCEL.Application")#office EXCEL版

2.2 隐藏excel行列

import time

import win32com.client as win32
xls_app = win32.Dispatch('ket.Application')
file_name = filepath
wb = xls_app.Workbooks.Open(file_name)
ws = wb.Worksheets('区域通报')
# ws.Name = '每日净增副本'
xls_app.Visible = True
# 写入控制防止没保存
# ws.Range("A1000").Value = ""
# # 隐藏列
# ws.Columns("C").EntireColumn.Hidden = True
for row in hide_col_list:
# 隐藏行
    log.info("隐藏%s" % row)
    ws.Rows(row).EntireRow.Hidden = True
    
for row in not_hide_col_list:
    ws.Rows(row).EntireRow.Hidden = False
# # 隐藏列
# ws.Columns("C").EntireColumn.Hidden = True

log.info("file_name=%s" % file_name)
# xls_app.Save(r"F:\需要完成任务.xlsx")
time.sleep(2)

wb.Save()

wb.Close()
xls_app.Quit()
del xls_app

2.3 读取表格,所有数据,numpy定位索引

ws = wb.Worksheets('区域排名')
# ws.Name = '每日净增副本'
# sheet.Cells(row, col).Value
# 读取列
date = ws.Columns("F").Value
# 读取单元格
# ws.Cells(row, col).Value
# 读取行
one_list = ws.Rows("1").Value

读取一个sheet数据(所有内容)

sheet_data=ws.Worksheets(1).UsedRange.Value

 使用numpy定位数据中包含'银行'关键词的行列位置的示例

import numpy as np

# 假设 sheet_data 是你的 Excel 数据
data_array = np.array(sheet_data)

# 查找数组中包含'银行'的索引位置
indices = np.where(data_array == '银行')

# 由于索引从0开始,将结果加1以匹配 Excel 中的索引
row_index, col_index = indices
row_index = row_index[0] + 1
col_index = col_index[0] + 1

# 打印包含'银行'的行和列索引
print("包含 '银行' 的行索引:", row_index)
print("包含 '银行' 的列索引:", col_index)

 2.4 查询函数

import win32com.client
import os

xlApp = win32com.client.Dispatch('Excel.Application')
xlApp.Visible = False

xls = xlApp.Workbooks.Open(os.getcwd() + "\\test.xls")

sheet = xls.Worksheets(1)

info = sheet.UsedRange
nrows = info.Rows.Count
ncols = info.Columns.Count
xls.Close(SaveChanges=0)

2.5设置样式

ws.Range("A1:B1").Interior.ColorIndex=44           #刷单元格颜色
worksheet.Range(worksheet.Cells(row_number, 1), worksheet.Cells(row_number, worksheet.Columns.Count)).Interior.Color = (0x1C1CF5) # 设置一行颜色
ws.Range("A2").Font.ColorIndex=23                   #刷字体颜色
ws.Range('A2:B2').NumberFormatLocal = "@"     #设置单元格格式为文本
ws.Range("A1:B1").Font.Bold = True            #加粗
ws.Range("C1:D1").Merge()          #合并单元格,合并之后读写均需选中第一个单元格
 
ws.Range("A1:T1").Columns.AutoFit() 
#自动调节边框宽度,有时调节出来不准确,需要手动再校正
ws.Range("A1").ColumnWidth = 40          # 手动设置宽度

.Font.ColorIndex方法

无色 = -4142,
   自动 = -4105,
   黑色 = 1,

   白色 = 2

   红色 = 3,
   鲜绿 = 4,  

   蓝色 = 5,

 黄色 = 6,
   粉红 = 7,
   青绿 = 8,

   深红 = 9,
  绿色 = 10,

   深蓝 = 11,
 深黄 = 12,

   紫罗兰 = 13,
   青色 = 14,

  灰色25 = 15,

  褐色 = 53,
   橄榄 = 52,
   深绿 = 51,
   深青 = 49,
   靛蓝 = 55,
   灰色80 = 56,
   橙色 = 46,
     蓝灰 = 47,
   灰色50 = 16,
   浅橙色 = 45,
   酸橙色 = 43,
   海绿 = 50,
   水绿色 = 42,
   浅蓝 = 41,   
   灰色40 = 48,
   金色 = 44,
   天蓝 = 33,
   梅红 = 54,
    玫瑰红 = 38,
   茶色 = 40,
   浅黄 = 36,
   浅绿 = 35,
   浅青绿 = 34,
   淡蓝 = 37,
   淡紫 = 39,
2.6 新建一个空excel文件

from win32com.client import Dispatch
app = Dispatch ("Excel.Application")
wb = app.Workbooks.Add ()
wb.SaveAs('f:\myfile.xlsx')

2.7 指定区域截图

方法1

使用 win32com 在 Excel 中对指定的单元格区域进行截图,并且保留彩色格式,可以使用 Excel 的 Range.CopyPicture 方法。该方法允许复制指定范围的图片,并可以将其粘贴到剪贴板,然后保存为图片文件。下面是一个示例代码,演示如何指定范围截图并保存为彩色图片:

import win32com.client as win32
from PIL import ImageGrab

# 打开 Excel 应用
excel = win32.Dispatch('Excel.Application')

# 打开已有的 Excel 文件
workbook = excel.Workbooks.Open(r"文件路径.xlsx")

# 选择工作表
sheet = workbook.Sheets(1)

# 指定截图范围(例如 A1 到 D10)
range_to_capture = sheet.Range("A1:D10")

# 复制指定范围为图片,指定 `Appearance` 为 `1`(xlScreen)保留彩色
range_to_capture.CopyPicture(Appearance=1, Format=2)  # 1: 保持彩色, 2: 作为图片 (xlBitmap)

# 从剪贴板抓取图片
image = ImageGrab.grabclipboard()

# 检查是否成功抓取图片
if isinstance(image, ImageGrab.Image.Image):
    # 保存图片到文件
    image.save(r"C:\path\to\save\image.png", "PNG")
    print("截图成功!图片已保存。")
else:
    print("未能成功抓取图片,请检查范围或剪贴板。")

# 关闭工作簿
workbook.Close(SaveChanges=False)

# 退出 Excel 应用
excel.Quit()

代码解释:

  1. range_to_capture.CopyPicture(Appearance=1, Format=2)CopyPicture 方法用于复制指定范围为图片。参数 Appearance=1 表示保留彩色,Format=2 表示复制为图片格式。
  2. ImageGrab.grabclipboard():使用 Pillow 库的 ImageGrab 模块从剪贴板抓取图片。
  3. 保存图片:抓取成功后,将图片保存为 PNG 格式。

关键点:

  • Appearance=1:表示保留彩色(xlScreen)。
  • Format=2:表示复制为位图格式图片(xlBitmap)。
  • ImageGrab.grabclipboard():从剪贴板抓取 Excel 复制的图片内容。

通过这种方式,你可以对 Excel 中的指定范围进行截图并保存为彩色图片。确保你已经安装了 Pillow 库来处理截图并保存图片(可以通过 pip install Pillow 来安装)。

方法2

from win32com.client import Dispatch, DispatchEx
import pythoncom
from PIL import ImageGrab, Image
import uuid
import time


# screen_area——类似格式"A1:J10"
def excel_catch_screen(filename, sheetname, screen_area, img_name='', pic_path=''):
    """ 对excel的表格区域进行截图——用例:excel_catch_screen(ur"D:\Desktop\123.xlsx", "Sheet1", "A1:J10")"""
    pythoncom.CoInitialize()  # excel多线程相关

    excel = DispatchEx('ket.Application')  # 启动excel
    excel.Visible = False  # 可视化
    excel.DisplayAlerts = False  # 是否显示警告
    wb = excel.Workbooks.Open(filename)  # 打开excel
    wb.Sheets(sheetname).select # 視圖切換到sheetname表
    ws = wb.Sheets(sheetname)  # 选择sheet

    ws.Range(screen_area).CopyPicture()  # 复制图片区域
    ws.Paste()  # 粘贴 ws.Paste(ws.Range('B1'))  # 将图片移动到具体位置
    time.sleep(1)
    name = str(uuid.uuid4())  # 重命名唯一值
    new_shape_name = name[:6]
    excel.Selection.ShapeRange.Name = new_shape_name  # 将刚刚选择的Shape重命名,避免与已有图片混淆
    
    ws.Shapes(new_shape_name).Copy()  # 选择图片
    img = ImageGrab.grabclipboard()  # 获取剪贴板的图片数据
    if not img_name:
        img_name = 'D:\\woai\\' + name + ".PNG"
    print(img_name)
    img.save(img_name)  # 保存图片
    wb.Close(SaveChanges=0)  # 关闭工作薄,不保存
    excel.Quit()  # 退出excel
    pythoncom.CoUninitialize()


if __name__ == '__main__':
    pass
    excel_catch_screen(r"D:\woai\资产报废模板.xlsx", "Sheet1", "A1:F5", img_name="D:\\woai\\ceshi.PNG")

2.8 修改图表数据范围

主要使用到chartObject来获取chart对象。

import win32com.client as win32
from win32com.client import constants
file_name = r"D:\农行控制\data.xlsx"

xls_app = win32.gencache.EnsureDispatch('ket.Application')
# wb = xls_app.Workbooks.Add()
wb = xls_app.Workbooks.Open(file_name)
ws = wb.Worksheets(1)
ws.Name = 'my_new_sheet'
xls_app.Visible = True

chart = ws.ChartObjects('图表 1').Chart #获得chart对象
# chart = ws.ChartObjects(1).Chart # 方法2

chart.SetSourceData(ws.Range("A1:A5"))

2.9 从excel中直接复制表格

下面这种复制表格的方法,往往会导致表格列宽度比较异常——超过页面宽度。

sheet=wb.Worksheets(1)#将变量sheet指向excel的第一张表
sheet.Range('A1:B5').Copy()# 复制表中A1到B5的范围,A1为左上角的单元格坐标,B5为右下角的坐标
parag=doc.doc.Paragraphs.Last#将变量parag指向word文档中最后一段的段尾
parag.Range.Paste()#粘贴刚才复制过的表格

保留源格式粘贴表格

为了解决上述的问题,可以先在excel中讲字体和表格列宽都调节好。然后粘贴的时候,选择保持原格式即可。

from win32com.client import constants 
parag.Range.PasteAndFormat(constants.wdFormatOriginalFormatting)

以图片形式粘贴表格

还有一种比较省事的方法,就是把表格粘贴成图片。这样能保证表格能在页面宽度内显示完。缺点是无法编辑边表格内容。

sheet=wb.Worksheets(1)
sheet.Range('A1:B5').CopyPicture()# 只有这里和之前复制excel有差别
parag=doc.doc.Paragraphs.Last#
parag.Range.Paste()#以图片形式粘贴刚才复制过的表格

 2.10 设置公式

# 为某单元格写入公式,也可覆盖原有的公式
ws.Range("A1").Formula = '=COUNTIF(J15:J1424,"X")+COUNTIF(J15:J1424,"O")'

2.11 清空

# 清除所有内容,包括格式,外边框,颜色等

ws.Range("A1:B5").Clear()

# 只清除单元格内容

ws.Range("A1:B5").ClearContents()

2.12 设置数据标签

链接

chart = ws.ChartObjects('图表 9').Chart #获得chart对象
chart.ChartTitle.Text = "1995 Rainfall Totals by Month"

x = chart.SeriesCollection('2023年加权利率').Points(100)
x.HasDataLabel = True
x.DataLabel.Text = "ewr"

2.13.打开Excel文件失败: 没有检测到wps程序,请检查是否安装或 module win32com.gen_py.45541000-5750-5300-4B49-4E47534F4655x0x3x0 has no attribute CLSIDToClassMap

module 'win32com.gen_py.45541000-5750-5300-4B49-4E47534F4655x0x3x0' has no attribute 'CLSIDToClassMap'

module 'win32com.gen_py.45541000-5750-5300-4B49-4E47534F4655x0x3x0' has no attribute 'CLSIDToClassMap'
    raise e
  File "C:\Users\user\AppData\Roaming\达观RPA开发平台\temp\run_file.py", line 52, in <module>
    xls_app = win32.Dispatch('ket.Application')
  File "D:\datagrand-rpa\rpa-studio\resources\main\server\win32\engine\lib\site-packages\win32com\client\__init__.py", line 96, in Dispatch
    return __WrapDispatch(dispatch, userName, resultCLSID, typeinfo, clsctx=clsctx)
  File "D:\datagrand-rpa\rpa-studio\resources\main\server\win32\engine\lib\site-packages\win32com\client\__init__.py", line 37, in __WrapDispatch
    klass = gencache.GetClassForCLSID(resultCLSID)
  File "D:\datagrand-rpa\rpa-studio\resources\main\server\win32\engine\lib\site-packages\win32com\client\gencache.py", line 183, in GetClassForCLSID
    mod = GetModuleForCLSID(clsid)
  File "D:\datagrand-rpa\rpa-studio\resources\main\server\win32\engine\lib\site-packages\win32com\client\gencache.py", line 226, in GetModuleForCLSID


可以尝试手动删除缓存文件。缓存文件通常位于用户目录的%USERPROFILE%\AppData\Local\Temp\gen_py文件夹中。你可以删除整个文件夹或者只删除与出现错误相关的缓存文件

使用python删除下面文件夹和文件

import os
import shutil

folder_path = os.path.expandvars("%USERPROFILE%\\AppData\\Local\\Temp\\gen_py")

# 首先删除文件夹下的所有文件
for filename in os.listdir(folder_path):
    file_path = os.path.join(folder_path, filename)
    try:
        if os.path.isfile(file_path) or os.path.islink(file_path):
            os.unlink(file_path)
        elif os.path.isdir(file_path):
            shutil.rmtree(file_path)
    except Exception as e:
        print("删除失败")

2.14 删除空行案例

1.多线程删除(33秒)

import win32com.client as win32
import os
import threading
import numpy as np

def check_empty_rows(data, start_row, end_row, result):
    data_array = np.array(data)
    columns = data_array.shape[1] if len(data_array) > 0 else 0
    for row in range(end_row, start_row-1, -1):
        if row-1 < len(data_array):  # 检查索引是否超出范围
            is_empty = True
            for column in range(columns):
                if data_array[row-1][column] is not None and str(data_array[row-1][column]).strip() != "":
                    is_empty = False
                    break
            if is_empty:
                result.append(row)

def delete_empty_rows(filepath):
    excel = win32.gencache.EnsureDispatch('ket.Application')
    excel.Visible = True
    excel.DisplayAlerts = False

    workbook = excel.Workbooks.Open(filepath)
    worksheet = workbook.Worksheets(1)
    data = worksheet.UsedRange.Value

    total_rows = len(data)
    threads = 4  # 设置您想要的线程数
    rows_per_thread = total_rows // threads

    result = []

    thread_list = []
    for i in range(threads):
        start_row = i * rows_per_thread + 1
        end_row = start_row + rows_per_thread
        if i == threads - 1:
            end_row = total_rows + 1
        t = threading.Thread(target=check_empty_rows, args=(data, start_row, end_row, result))
        thread_list.append(t)
        t.start()

    for t in thread_list:
        t.join()

    result.sort(reverse=True)
    for row in result:
        worksheet.Rows(row).Delete()

    workbook.Save()
    workbook.Close()

    print("Empty rows deleted successfully.")

# 调用函数来执行操作
excel_filepath = r"D:\SAP报表导出\序时账\新需求\merged2023-06-01 - 副本.xlsx"
delete_empty_rows(excel_filepath)

2.munpy删除(34秒)

import win32com.client as win32
import numpy as np

# 创建Excel应用程序对象
excel = win32.Dispatch('ket.Application')

# 打开Excel文件
workbook = excel.Workbooks.Open(r"D:\SAP报表导出\序时账\新需求\merged2023-06-01 - 副本.xlsx")

# 设置Excel可见
excel.Visible = True
excel.DisplayAlerts = False

# 获取第一个工作表
worksheet = workbook.Worksheets(1)

# 读取所有数据
used_range = worksheet.UsedRange
data = used_range.Value

# 转换为numpy数组
np_data = np.array(data)

# 判断空行
empty_rows = np.where(np.all(np_data == None, axis=1))[0]

# 逆序删除空行
empty_rows = np.flip(empty_rows)
print(empty_rows)
# 删除空行
for row in empty_rows:
    worksheet.Rows(row + 1).Delete()

# 保存并关闭Excel文件
workbook.Save()
workbook.Close()

# 退出Excel应用程序
excel.Quit()

2.15启用或禁用Excel中的某个COM加载项

通过使用win32com库,你可以在Python中控制COM组件,包括启用或禁用Excel中的某个COM加载项。下面是一个示例代码,展示如何使用win32com来启用或禁用Excel中的COM加载项:

import win32com.client as win32

def on_or_off_addin(flag='on'):
    # 创建Excel Application实例
    excel_app = win32.Dispatch("Excel.Application")
    
    # 获取COM Add-ins集合
    com_addins = excel_app.COMAddIns
    excel_app.DisplayAlerts = False  # 控制是否显示警告框
    
    # 通过ProgID查找特定的COM Add-in
    target_addin = None
    for com_addin in com_addins:
        if com_addin.ProgID == "WDF.Addin":
            target_addin = com_addin
            break
    
    # 启用COM Add-in
    if target_addin and flag == 'on':
        target_addin.Connect = True
    
    # 禁用COM Add-in
    if target_addin and flag == 'off':
        target_addin.Connect = False
    
    # 退出Excel Application
    excel_app.Quit()

# 测试启用COM Add-in
on_or_off_addin('on')

# 测试禁用COM Add-in
# on_or_off_addin('off')

在上面的代码中,你需要将"Your.Addin.ProgID"替换为你想要启用或禁用的COM加载项的ProgID。然后,根据你想要启用还是禁用,你可以取消代码中注释的相应部分。

请注意,要运行此代码,你需要安装pywin32win32com.client)库。你可以使用以下命令来安装:

pip install pywin32

此代码会在Python中创建一个Excel应用程序实例,然后通过COM Add-ins集合查找特定的COM加载项,并根据需要启用或禁用它。最后,记得在完成操作后关闭Excel应用程序。在实际操作中,请确保你明确了解你要启用或禁用的COM加载项的ProgID,并小心操作,以避免对Excel应用程序产生意外影响。

2.16 过将数字转换得到列名

def get_column_letter(n):
    string = ""
    while n > 0:
        n, remainder = divmod(n - 1, 26)
        string = chr(65 + remainder) + string
    return string

# 测试函数
print(get_column_letter(5))  # 输出: E

以下是关于如何使用 win32com 在 Excel 中设置特定字符的格式的详细文档:


2.17 使用 win32com 设置 Excel 单元格中特定字符的格式

在 Excel 中,我们经常需要对单元格中的特定字符应用不同的格式。使用 win32com,我们可以通过 GetCharacters 方法来实现这一点。以下是如何在 Python 中使用 win32com 来设置 Excel 中特定字符的格式的步骤:

1. 安装 pywin32 包

首先,确保你已经安装了 pywin32 包。如果还没有安装,可以使用以下命令来安装:

pip install pywin32

2. 编写代码

以下是一个示例代码,演示了如何使用 win32com 设置 Excel 单元格中指定字符的格式:

import win32com.client

# 启动 Excel 应用程序
excel = win32com.client.Dispatch("Excel.Application")
excel.Visible = True  # 使 Excel 可见

# 打开一个工作簿
workbook = excel.Workbooks.Add()
sheet = workbook.Sheets(1)

# 向单元格 A1 中写入一些文本
cell = sheet.Cells(1, 1)
cell.Value = "Hello, World!"

# 设置特定字符的格式
start_pos = 1  # 起始字符位置
length = 5     # 字符长度

# 使用 GetCharacters 方法获取特定字符的对象
characters = cell.GetCharacters(start_pos, length)

# 设置字符的格式
characters.Font.Bold = True       # 设置字符加粗
characters.Font.Italic = True     # 设置字符斜体
characters.Font.ColorIndex = 3    # 设置字符颜色为红色(3 代表红色)

# 保存并关闭工作簿
workbook.SaveAs("formatted_text.xlsx")
workbook.Close()

# 退出 Excel 应用程序
excel.Quit()

3. 代码解释

  • 启动 Excel 应用程序:使用 win32com.client.Dispatch 启动 Excel 应用程序并设置为可见。
  • 打开一个工作簿:创建一个新的工作簿并获取第一个工作表。
  • 向单元格写入文本:将文本 "Hello, World!" 写入单元格 A1。
  • 设置特定字符的格式:通过 GetCharacters(start, length) 方法获取指定范围内的字符对象,并对这些字符的格式进行设置,如加粗、斜体、颜色等。
  • 保存并关闭工作簿:将工作簿保存为 "formatted_text.xlsx" 并关闭它。
  • 退出 Excel 应用程序:退出 Excel 应用程序以释放资源。

4. 注意事项

  • start_pos 和 length 参数是基于 1 的索引,即第一个字符的位置是 1。
  • Font.ColorIndex 使用的是 Excel 中的颜色索引,3 代表红色,你可以根据需要调整颜色索引。
  • 确保在操作完成后关闭 Excel 应用程序,以避免内存泄漏和资源浪费。

这个方法使你能够在 Excel 中灵活地设置文本格式,特别是在处理需要高亮显示或格式化特定文本的场景时非常有用。


你可以根据实际需求调整代码中的参数和格式设置。希望这个文档对你的工作有帮助!

 

3.office文件 (word, ppt, excel等) 转为pdf

#-*- coding:utf-8 -*-
import os
from win32com.client import Dispatch, constants, gencache, DispatchEx


class PDFConverter:
    def __init__(self, pathname, export='.'):
        self._handle_postfix = ['doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx']
        self._filename_list = list()
        self._export_folder = os.path.join(os.path.abspath('.'), 'pdfconver')
        if not os.path.exists(self._export_folder):
                os.mkdir(self._export_folder)
        self._enumerate_filename(pathname)
    
    def _enumerate_filename(self, pathname):
        '''
        读取所有文件名
        '''
        full_pathname = os.path.abspath(pathname)
        if os.path.isfile(full_pathname):
            if self._is_legal_postfix(full_pathname):
                self._filename_list.append(full_pathname)
            else:
                raise TypeError('文件 {} 后缀名不合法!仅支持如下文件类型:{}。'.format(pathname, '、'.join(self._handle_postfix)))
        elif os.path.isdir(full_pathname):
            for relpath, _, files in os.walk(full_pathname):
                for name in files:
                    filename = os.path.join(full_pathname, relpath, name)
                    if self._is_legal_postfix(filename):
                        self._filename_list.append(os.path.join(filename))
        else:
            raise TypeError('文件/文件夹 {} 不存在或不合法!'.format(pathname))

    def _is_legal_postfix(self, filename):
        return filename.split('.')[-1].lower() in self._handle_postfix and not os.path.basename(filename).startswith('~')
    
    def run_conver(self):
        '''
        进行批量处理,根据后缀名调用函数执行转换
        '''
        print('需要转换的文件数:', len(self._filename_list))
        for filename in self._filename_list:
            postfix = filename.split('.')[-1].lower()
            funcCall = getattr(self, postfix)
            print('原文件:', filename)
            funcCall(filename)
        print('转换完成!')
    
    def doc(self, filename):
        '''
        doc 和 docx 文件转换
        '''
        name = os.path.basename(filename).split('.')[0] + '.pdf'
        exportfile = os.path.join(self._export_folder, name)
        print('保存 PDF 文件:', exportfile)
        gencache.EnsureModule('{00020905-0000-0000-C000-000000000046}', 0, 8, 4)
        w = Dispatch("Word.Application")
        doc = w.Documents.Open(filename)
        doc.ExportAsFixedFormat(exportfile, constants.wdExportFormatPDF,
                Item=constants.wdExportDocumentWithMarkup,
                CreateBookmarks=constants.wdExportCreateHeadingBookmarks)
        
        w.Quit(constants.wdDoNotSaveChanges)
    
    def docx(self, filename):
        self.doc(filename)
    
    def xls(self, filename):
        '''
        xls 和 xlsx 文件转换
        '''
        name = os.path.basename(filename).split('.')[0] + '.pdf'
        exportfile = os.path.join(self._export_folder, name)
        xlApp = DispatchEx("Excel.Application")
        xlApp.Visible = False    
        xlApp.DisplayAlerts = 0   
        books = xlApp.Workbooks.Open(filename,False)
        books.ExportAsFixedFormat(0, exportfile)
        books.Close(False)
        print('保存 PDF 文件:', exportfile)
        xlApp.Quit()
    
    def xlsx(self, filename):
        self.xls(filename)
    
    def ppt(self, filename):
        '''
        ppt 和 pptx 文件转换
        '''
        name = os.path.basename(filename).split('.')[0] + '.pdf'
        exportfile = os.path.join(self._export_folder, name)
        gencache.EnsureModule('{00020905-0000-0000-C000-000000000046}', 0, 8, 4)
        p = Dispatch("PowerPoint.Application")
        ppt = p.Presentations.Open(filename, False, False, False)
        ppt.ExportAsFixedFormat(exportfile, 2, PrintRange=None)
        print('保存 PDF 文件:', exportfile)
        p.Quit()
    
    def pptx(self, filename):
        self.ppt(filename)



if __name__ == "__main__":
    
    # 支持文件夹批量导入
    folder = 'tmp' 
    pathname = os.path.join(os.path.abspath('.'), folder)
    
    # 也支持单个文件的转换
    # pathname = 'test.doc'

    pdfConverter = PDFConverter(pathname)
    pdfConverter.run_conver()

方法二:

import win32com.client

# 创建Excel应用对象
excel = win32com.client.Dispatch("ket.Application")

# 打开Excel文件
wb = excel.Workbooks.Open('你的文件路径')

# 设置页面为纵向布局
wb.Worksheets[1].PageSetup.Orientation = 1

# 设置页面缩放以适应一页宽
wb.Worksheets[1].PageSetup.Zoom = False
wb.Worksheets[1].PageSetup.FitToPagesWide = 1
wb.Worksheets[1].PageSetup.FitToPagesTall = False

# 导出为PDF
wb.ExportAsFixedFormat(0, '你的PDF文件路径')

# 关闭工作簿和应用
wb.Close()
excel.Quit()

4.excel的不同sheet存为pdf

#-*- coding:utf-8 -*-

import os
from win32com.client import Dispatch, constants, gencache, DispatchEx
import xlrd

class PDFConverter:
    def __init__(self, pathname,sheetnum, export='.'):
        self.sheetnum = sheetnum
        self._handle_postfix = ['doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx']
        self._filename_list = list()
        self._export_folder = os.path.join(os.path.abspath('.'), 'pdfconver')
        if not os.path.exists(self._export_folder):
            os.mkdir(self._export_folder)
        self._enumerate_filename(pathname)

    def _enumerate_filename(self, pathname):
        '''
        读取所有文件名
        '''
        full_pathname = os.path.abspath(pathname)
        if os.path.isfile(full_pathname):
            if self._is_legal_postfix(full_pathname):
                self._filename_list.append(full_pathname)
            else:
                raise TypeError('文件 {} 后缀名不合法!仅支持如下文件类型:{}。'.format(pathname, '、'.join(self._handle_postfix)))
        elif os.path.isdir(full_pathname):
            for relpath, _, files in os.walk(full_pathname):
                for name in files:
                    filename = os.path.join(full_pathname, relpath, name)
                    if self._is_legal_postfix(filename):
                        self._filename_list.append(os.path.join(filename))
        else:
            raise TypeError('文件/文件夹 {} 不存在或不合法!'.format(pathname))

    def _is_legal_postfix(self, filename):
        return filename.split('.')[-1].lower() in self._handle_postfix and not os.path.basename(filename).startswith(
            '~')

    def run_conver(self):
        '''
        进行批量处理,根据后缀名调用函数执行转换
        '''
        print('需要转换的文件数:', len(self._filename_list))
        for filename in self._filename_list:
            postfix = filename.split('.')[-1].lower()
            funcCall = getattr(self, postfix)
            print('原文件:', filename)
            funcCall(filename)
        print('转换完成!')

    def xls(self, filename):
        '''
        xls 和 xlsx 文件转换
        '''
        xlApp = DispatchEx("Excel.Application")
        xlApp.Visible = False
        xlApp.DisplayAlerts = 0
        books = xlApp.Workbooks.Open(filename, False)
        # 循环保存每一个sheet
        for i in range(1, self.sheetnum+1):
            sheetName = books.Sheets(i).Name
            xlSheet = books.Worksheets(sheetName)
            name = sheetName + '.pdf'
            exportfile = os.path.join(self._export_folder, name)
            xlSheet.ExportAsFixedFormat(0, exportfile)
            print('保存 PDF 文件:', exportfile)
        books.Close(False)
        xlApp.Quit()

    def xlsx(self, filename):
        self.xls(filename)


if __name__ == "__main__":
    # 支持单个文件的转换
    pathname = u'原始数据.xlsx'
    # 获取到文件的sheet数
    b = xlrd.open_workbook(pathname)
    sheetnum = len(b.sheets())
    pdfConverter = PDFConverter(pathname, sheetnum)
    pdfConverter.run_conver()

5.ppt

 

模块安装

pip install python-pptx

slide(幻灯片):一个PPT由一系列slide构成。

slide_master(幻灯片母版):母版可定义主题样式基准。

slide_layouts(模版):创建幻灯片时可选择的模版。

shape(形状):包含一切可视元素,通过slide.shapes可访问slide内元素。

placeholder(占位符):在模板中占据位置,如图片、文字等。

paragraph(段落):文本段,可以直接设置整段文本样式。

text(文本):段落内的文本,通过paragraph.add_run()生成。

获取Slide(每一张幻灯片)

from pptx import Presentation
ppt_path = r"C:\Users\yys53\Desktop\222.pptx"
prs = Presentation(ppt_path)

for slide in prs.slides:
    print(slide)

出现报错

KeyError: "There is no item named 'ppt/slides/NULL' in the archive"

解决,修改源码C:\Users\yys53\OneDrive\python\install\Lib\site-packages\pptx\opc\pkgreader.py

def load_from_xml(baseURI, rels_item_xml):
    """
    Return |_SerializedRelationshipCollection| instance loaded with the
    relationships contained in *rels_item_xml*. Returns an empty
    collection if *rels_item_xml* is |None|.
    """
    srels = _SerializedRelationshipCollection()
    if rels_item_xml is not None:
        rels_elm = parse_xml(rels_item_xml)
        for rel_elm in rels_elm.relationship_lst:
            srels._srels.append(_SerializedRelationship(baseURI, rel_elm))
    return srels

↓↓↓↓↓↓↓↓↓↓修改为 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

def load_from_xml(baseURI, rels_item_xml):
    """
    Return |_SerializedRelationshipCollection| instance loaded with the
    relationships contained in *rels_item_xml*. Returns an empty
    collection if *rels_item_xml* is |None|.
    """
    srels = _SerializedRelationshipCollection()
    if rels_item_xml is not None:
        if 'NULL' in str(rels_item_xml):
            print('NULL found and skiped')
            pass
        else:
            rels_elm = parse_xml(rels_item_xml)
            for rel_elm in rels_elm.relationship_lst:
                srels._srels.append(_SerializedRelationship(baseURI, rel_elm))
    return srels

 

获取Shape形状(方框)

from pptx import Presentation
ppt_path = r"C:\Users\yys53\OneDrive\终极数学题.pptx"
prs = Presentation(ppt_path)

for slide in prs.slides:
    for shape in slide.shapes:
        print(shape)

判断每个Shape中是否存在文字 

  • shape.has_text_frame :是否有文字
  • shape.text_frame :获取文字框
from pptx import Presentation
ppt_path = r"C:\Users\yys53\OneDrive\终极数学题.pptx"
prs = Presentation(ppt_path)

for slide in prs.slides:
    for shape in slide.shapes:
        if shape.has_text_frame:
            text_frame = shape.text_frame
            print(text_frame.text)

来自 https://blog.csdn.net/weixin_41261833/article/details/106406229