鱼C论坛

 找回密码
 立即注册
查看: 4599|回复: 11

[已解决]python对excel表格中指定的内容标注颜色

[复制链接]
发表于 2021-7-10 09:47:52 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 一坨屎吖 于 2021-7-17 19:22 编辑

工作中经常要对满足一定条件的excel单元格中指定的内容标注颜色:
所有排名26名之后的分公司文字描述部分颜色标红,速率小于750Mbps的分公司颜色标红,以及高频次小区颜色标红。
excel已经用读取并且用正则表达式提取,目前就卡在标颜色这里。
完整代码如下:
import openpyxl as vb
import re
import win32com.client
import os

路径 = r'C:\Users\Administrator\Desktop\py垃圾\解决文本颜色标注\工作颜色编辑.xlsx'
工作簿 = vb.load_workbook(路径)
工作表 = 工作簿['2021']
单元格区域 = 工作表['H4:H39']
具体要标颜色的区域=[]
for 数据 in 单元格区域:    # 循环每行
    for 单元格 in 数据:   # 循环每个单元格

        每个单元格数据=单元格.value
        提取字符1 = re.search('%,排名第(.*?),下行平均', 每个单元格数据)
        if 提取字符1 != None:
            # print(提取字符1)
            覆盖率排名 = 提取字符1.group(1)
            # print(float(覆盖率的值))
            if float(覆盖率排名) > 25:
                覆盖率排名大于25全部标颜色 = re.search('.*?(.*?),下行平均', 每个单元格数据)
                if 覆盖率排名大于25全部标颜色 != None:
                    覆盖率排名大于25标颜色区域 = 覆盖率排名大于25全部标颜色.group(1)
                #print(覆盖率排名大于25标颜色区域)
                具体要标颜色的区域.append(覆盖率排名大于25标颜色区域)
                #print(具体要标颜色的区域)

        提取字符2 = re.search('下行平均速率(.*?)Mbps', 每个单元格数据)
        if 提取字符2 != None:
            # print(提取字符1)
            速率值 = 提取字符2.group(1)
            #print(float(速率值))

            if float(速率值) < 750:
                速率小于750Mps全部标颜色 = re.search('排名第.*?,(.*?),上行平均速率', 每个单元格数据)
                if 速率小于750Mps全部标颜色 != None:
                    速率小于750Mps全部标颜色区域 = 速率小于750Mps全部标颜色.group(1)

                具体要标颜色的区域.append(速率小于750Mps全部标颜色区域)
                #print(具体要标颜色的区域)

        提取字符3 = re.search('中路测问题待解决.*?个。(.*?)5G时长驻留', 每个单元格数据)
        if 提取字符3 != None:
            高频次小区 = 提取字符3.group(1)
            具体要标颜色的区域.append(高频次小区)

        提取字符4 = re.search('5G时.*?排名第(.*?)。', 每个单元格数据)

        if 提取字符4 != None:
            驻留比排名 = 提取字符4.group(1)
            #print(float(驻留比排名))
            if float(驻留比排名) > 25:

                驻留比排名区域 = re.search('.*?(5G时长.*)', 每个单元格数据)
                if 驻留比排名区域 != None:
                    驻留比排名区域标颜色区域 = 驻留比排名区域.group(1)
                具体要标颜色的区域.append(驻留比排名区域标颜色区域)
                #print(具体要标颜色的区域)

    app = win32com.client.DispatchEx("Excel.Application")
    doc = app.Workbooks.Open(os.path.abspath(路径))
    WinSheet=doc.Worksheets('2021')
    print(具体要标颜色的区域)

    for word in set(具体要标颜色的区域):
        while app.Selection.Find.Execute(word, False, False, False, False, False, True, 0, True, "", 0):
            app.Selection.Font.Color = 255  # 替换为红色
        WinSheet.Range(0, 0).Select()
    具体要标颜色的区域.clear()
    WinSheet.SaveAs2()
    WinSheet.Close()
    app.Quit()





最佳答案
2021-7-12 15:03:36
本帖最后由 阿奇_o 于 2021-7-12 17:08 编辑

先吐槽一句,你TM牛!居然 真·中文编程!


----------花了2小时,解决 -----------
from openpyxl import Workbook 
import openpyxl as opx
import os, re 

fpath = ".\\工作颜色编辑.xlsx"
wb = opx.load_workbook(fpath)
ws = wb['2021']
print(ws['H5'].value)
'''6月5G核心城区道路拉网测试覆盖率98.01%,排名第15,下行平均速率772.59Mbps,上行平均速率98.23Mbps,优于竞对,其中路测问题待解决12个。6月巴南出现高频次(大于10次)问题小区中,SA无线接通率问题小区2个,SA无线掉线率问题小区1个。5G时长
驻留比67.69% ,排名第5。'''
p = r'''(\d+月).*(覆盖率\d+(\.\d+)?%).*(排名第\d+).*(下行平均速率\d+(\.\d+)?Mbps).*(上行平均速率\d+(\.\d+)?Mbps).*(路测问题待解决\d+个).*'''
'''6月5G核心城区道路拉网测试覆盖率97.54%,排名第24,下行平均速率732.64Mbps,上行平均速率108Mbps,优于竞对,其中路测问题待解决8个。5G时长驻留比57.33% ,排名第22。'''
result = {}
for i in range(5, 40):
    # print(ws[f'H{i}'].value[:100])
    result[f'H{i}'] = re.findall(p, ws[f'H{i}'].value)

for k, v in result.items():
    print(k, v)


# 修改颜色 https://openpyxl.readthedocs.io/en/stable/styles.html
from openpyxl.styles import Font 
red_font = Font(color='FF0000') # red font

for k, v in result.items():
    # print(v[0][3][3:])  # 排名
    if int(v[0][3][3:]) <= 26:
        ws[k].font = red_font

wb.save('changed_color.xlsx')  

# 问题:openpyxl 只能 改变整个cell的字体颜色,不能针对其中不同字符做不同的颜色处理。
# https://stackoverflow.com/questions/49522658/openpyxl-change-one-words-color-in-the-same-cell

# Google...后, 发现可以用 xlsxwriter的write_rich_string() 解决!
import xlsxwriter
wbook = xlsxwriter.Workbook('copy_and_change_color同一单元不同颜色.xlsx')  
wsheet = wbook.add_worksheet()
wsheet.set_column('H:H', 40)
# 注:xlsxwriter模块不能对现存excel文件进行处理,只能用openpyxl读取后,再写到新的wb中
default = wbook.add_format({'color': 'black'})
red = wbook.add_format({'color': 'red'})
blue = wbook.add_format({'color': 'blue'})
for k, v in result.items():
    rank = v[0][3]   # '排名第xx'
    if int(rank[3:]) >= 26:
        wsheet.write_rich_string(k, default, rank[:3], red, rank[3:])
    else:
        wsheet.write(k, rank)

wbook.close()

# https://xlsxwriter.readthedocs.io/example_rich_strings.html

工作颜色编辑.rar

9.73 KB, 下载次数: 2

看板文字颜色输出完整代码.rar

1.13 KB, 下载次数: 2

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2021-7-10 09:48:50 | 显示全部楼层
自己顶自己
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-7-10 14:42:59 | 显示全部楼层
有没有大佬哟。。急求
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-7-12 09:56:34 | 显示全部楼层

回帖奖励 +1 鱼币

学习学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-7-12 12:31:02 | 显示全部楼层

希望哥们研究下,如何实现呢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-7-12 15:03:36 | 显示全部楼层    本楼为最佳答案   
本帖最后由 阿奇_o 于 2021-7-12 17:08 编辑

先吐槽一句,你TM牛!居然 真·中文编程!


----------花了2小时,解决 -----------
from openpyxl import Workbook 
import openpyxl as opx
import os, re 

fpath = ".\\工作颜色编辑.xlsx"
wb = opx.load_workbook(fpath)
ws = wb['2021']
print(ws['H5'].value)
'''6月5G核心城区道路拉网测试覆盖率98.01%,排名第15,下行平均速率772.59Mbps,上行平均速率98.23Mbps,优于竞对,其中路测问题待解决12个。6月巴南出现高频次(大于10次)问题小区中,SA无线接通率问题小区2个,SA无线掉线率问题小区1个。5G时长
驻留比67.69% ,排名第5。'''
p = r'''(\d+月).*(覆盖率\d+(\.\d+)?%).*(排名第\d+).*(下行平均速率\d+(\.\d+)?Mbps).*(上行平均速率\d+(\.\d+)?Mbps).*(路测问题待解决\d+个).*'''
'''6月5G核心城区道路拉网测试覆盖率97.54%,排名第24,下行平均速率732.64Mbps,上行平均速率108Mbps,优于竞对,其中路测问题待解决8个。5G时长驻留比57.33% ,排名第22。'''
result = {}
for i in range(5, 40):
    # print(ws[f'H{i}'].value[:100])
    result[f'H{i}'] = re.findall(p, ws[f'H{i}'].value)

for k, v in result.items():
    print(k, v)


# 修改颜色 https://openpyxl.readthedocs.io/en/stable/styles.html
from openpyxl.styles import Font 
red_font = Font(color='FF0000') # red font

for k, v in result.items():
    # print(v[0][3][3:])  # 排名
    if int(v[0][3][3:]) <= 26:
        ws[k].font = red_font

wb.save('changed_color.xlsx')  

# 问题:openpyxl 只能 改变整个cell的字体颜色,不能针对其中不同字符做不同的颜色处理。
# https://stackoverflow.com/questions/49522658/openpyxl-change-one-words-color-in-the-same-cell

# Google...后, 发现可以用 xlsxwriter的write_rich_string() 解决!
import xlsxwriter
wbook = xlsxwriter.Workbook('copy_and_change_color同一单元不同颜色.xlsx')  
wsheet = wbook.add_worksheet()
wsheet.set_column('H:H', 40)
# 注:xlsxwriter模块不能对现存excel文件进行处理,只能用openpyxl读取后,再写到新的wb中
default = wbook.add_format({'color': 'black'})
red = wbook.add_format({'color': 'red'})
blue = wbook.add_format({'color': 'blue'})
for k, v in result.items():
    rank = v[0][3]   # '排名第xx'
    if int(rank[3:]) >= 26:
        wsheet.write_rich_string(k, default, rank[:3], red, rank[3:])
    else:
        wsheet.write(k, rank)

wbook.close()

# https://xlsxwriter.readthedocs.io/example_rich_strings.html
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-7-12 17:52:29 | 显示全部楼层
阿奇_o 发表于 2021-7-12 15:03
先吐槽一句,你TM牛!居然 真·中文编程!

兄弟,属实厉害啊,但是我刚刚运行了下,单元格内有4个条件内容,但是程序跑了之后,只要有一个内容符合条件,整个单元格就标注了颜色。我要实现的是只对单独的内容标注颜色呢。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-7-12 17:54:14 | 显示全部楼层
本帖最后由 一坨屎吖 于 2021-7-17 19:21 编辑

我把excel内容复制在word中,改了几行代码基本实现了这个功能。
import re
import win32com.client
import os
from docx import Document
文件 = Document(r'F:工作word.docx')
具体要标颜色的区域=[]
for table in 文件.tables:
    for row in table.rows:
        for cell in row.cells:
            每个单元格数据 = cell.text
            #print(每个单元格数据)
            提取字符1 = re.search('%,排名第(.*?),下行平均', 每个单元格数据)
            if 提取字符1 != None:
                #print(提取字符1)
                覆盖率排名 = 提取字符1.group(1)
                # print(float(覆盖率的值))
                if float(覆盖率排名) > 25:
                    覆盖率排名大于25全部标颜色 = re.search('.*?(.*?),下行平均', 每个单元格数据)
                    if 覆盖率排名大于25全部标颜色 != None:
                        覆盖率排名大于25标颜色区域 = 覆盖率排名大于25全部标颜色.group(1)
                    # print(覆盖率排名大于25标颜色区域)
                    具体要标颜色的区域.append(覆盖率排名大于25标颜色区域)
                    # print(具体要标颜色的区域)

            提取字符2 = re.search('下行平均速率(.*?)Mbps', 每个单元格数据)
            if 提取字符2 != None:
                # print(提取字符1)
                速率值 = 提取字符2.group(1)
                # print(float(速率值))

                if float(速率值) < 750:
                    速率小于750Mps全部标颜色 = re.search('排名第.*?,(.*?),上行平均速率', 每个单元格数据)
                    if 速率小于750Mps全部标颜色 != None:
                        速率小于750Mps全部标颜色区域 = 速率小于750Mps全部标颜色.group(1)

                    具体要标颜色的区域.append(速率小于750Mps全部标颜色区域)
                    # print(具体要标颜色的区域)

            提取字符3 = re.search('中路测问题待解决.*?个。(.*?)5G时长驻留', 每个单元格数据)
            if 提取字符3 != None:
                高频次小区 = 提取字符3.group(1)
                具体要标颜色的区域.append(高频次小区)

            提取字符4 = re.search('5G时.*?排名第(.*?)。', 每个单元格数据)

            if 提取字符4 != None:
                驻留比排名 = 提取字符4.group(1)
                # print(float(驻留比排名))
                if float(驻留比排名) > 25:

                    驻留比排名区域 = re.search('.*?(5G时长.*)', 每个单元格数据)
                    if 驻留比排名区域 != None:
                        驻留比排名区域标颜色区域 = 驻留比排名区域.group(1)
                    具体要标颜色的区域.append(驻留比排名区域标颜色区域)
                    #print(具体要标颜色的区域)


文件.save(r'F:工作word.docx')
app = win32com.client.DispatchEx("Word.Application")
doc = app.Documents.Open(os.path.abspath(r'F:工作word.docx'))


for word in set(具体要标颜色的区域):
    while app.Selection.Find.Execute(word, False, False, False, False, False, True, 0, True, "", 0):
        app.Selection.Font.Color = 255  # 替换为红色
    doc.Range(0, 0).Select()


具体要标颜色的区域.clear()
doc.SaveAs2()
doc.Close()
app.Quit()





想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-7-13 13:12:57 | 显示全部楼层
一坨屎吖 发表于 2021-7-12 17:52
兄弟,属实厉害啊,但是我刚刚运行了下,单元格内有4个条件内容,但是程序跑了之后,只要有一个内容符合 ...

碗筷和米饭就在你面前,我是没办法喂你吃的  

ps: 你开心就好~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-7-13 14:52:16 | 显示全部楼层
阿奇_o 发表于 2021-7-13 13:12
碗筷和米饭就在你面前,我是没办法喂你吃的  

ps: 你开心就好~

嗯嗯,我在改改代码,谢谢了哟!!!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-7-13 15:55:47 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2021-7-13 16:41:24 | 显示全部楼层
本帖最后由 一坨屎吖 于 2021-7-17 19:20 编辑

这个咋vba中用正则表达式提取其实更方便。
附完整代码:
Sub 宏1()
Dim re As New RegExp, mat, rng As Range, Match, mat2, Match3, Length, Start
For Each rng In Range("H5:H39")
With re
.Global = 0
.Pattern = "排名第[0-9]*"
Set mat = .Execute(rng)
    For Each Match In mat
    If IsNumeric(Replace(Match, "排名第", "")) = True Then
         If (Replace(Match, "排名第", "")) > 25 Then
         With re
          .Global = 0
          .Pattern = "[0-9]*月5G核心城.*?排名第[0-9]*"
           Set mat2 = .Execute(rng)
           For Each Match3 In mat2
             Start = InStr(rng, Match3)
             Length = Len(Match3)
             With rng.Characters(Start:=Start, Length:=Length).Font
            .Color = -16776961
             End With
           Next
         End With
         End If
    End If
    Next
 End With
   
With re
.Global = 0
.Pattern = "下行平均速率([1-9][0-9]*)+(\.[0-9]{1,3})?"
Set mat = .Execute(rng)
    For Each Match In mat
    If IsNumeric(Replace(Match, "下行平均速率", "")) = True Then
         If (Replace(Match, "下行平均速率", "")) < 750 Then
             With re
            .Global = 0
            .Pattern = "下行平均速率.*?Mbps"
             Set mat2 = .Execute(rng)
             For Each Match3 In mat2
                 Start = InStr(rng, Match3)
                 Length = Len(Match3)
                 With rng.Characters(Start:=Start, Length:=Length).Font
                .Color = -16776961
                 End With
             Next
            End With
         End If
    End If
    Next
 End With
   
   
With re
.Global = 0
.Pattern = "排名第[0-9]*。"
Set mat = .Execute(rng)
    For Each Match In mat
         If Replace(Replace(Match, "排名第", ""), "。", "") > 25 Then
          With re
            .Global = 0
            .Pattern = "5G时长驻留比.*"
             Set mat2 = .Execute(rng)
             For Each Match3 In mat2
               Start = InStr(rng, Match3)
               Length = Len(Match3)
               With rng.Characters(Start:=Start, Length:=Length).Font
              .Color = -16776961
               End With
             Next
          End With
         End If
    Next
 End With
   


With re
.Global = 0
.Pattern = "。[0-9]*月.*?高频次.*?。"
Set mat = .Execute(rng)
    For Each Match In mat
         Start = InStr(rng, Match)
         Length = Len(Match)
         With rng.Characters(Start:=Start, Length:=Length).Font
        .Color = -16776961
         End With
      Next
 End With

Next
End Sub

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-14 01:03

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表