一坨屎吖 发表于 2021-7-10 09:47:52

python对excel表格中指定的内容标注颜色

本帖最后由 一坨屎吖 于 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-10 09:48:50

{:5_101:}自己顶自己

一坨屎吖 发表于 2021-7-10 14:42:59

{:5_109:}有没有大佬哟。。急求

超级玛尼哄 发表于 2021-7-12 09:56:34

学习学习

一坨屎吖 发表于 2021-7-12 12:31:02

超级玛尼哄 发表于 2021-7-12 09:56
学习学习

{:5_101:}希望哥们研究下,如何实现呢

阿奇_o 发表于 2021-7-12 15:03:36

本帖最后由 阿奇_o 于 2021-7-12 17:08 编辑

先吐槽一句,你TM牛!居然 真·中文编程!{:10_257:}{:10_245:}


----------花了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.value[:100])
    result = re.findall(p, ws.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)# 排名
    if int(v) <= 26:
      ws.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   # '排名第xx'
    if int(rank) >= 26:
      wsheet.write_rich_string(k, default, rank[:3], red, rank)
    else:
      wsheet.write(k, rank)

wbook.close()

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

一坨屎吖 发表于 2021-7-12 17:52:29

阿奇_o 发表于 2021-7-12 15:03
先吐槽一句,你TM牛!居然 真·中文编程!




兄弟,属实厉害啊,但是我刚刚运行了下,单元格内有4个条件内容,但是程序跑了之后,只要有一个内容符合条件,整个单元格就标注了颜色。我要实现的是只对单独的内容标注颜色呢。

一坨屎吖 发表于 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()





阿奇_o 发表于 2021-7-13 13:12:57

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

碗筷和米饭就在你面前,我是没办法喂你吃的{:10_312:}

ps: 你开心就好~ {:10_250:}

一坨屎吖 发表于 2021-7-13 14:52:16

阿奇_o 发表于 2021-7-13 13:12
碗筷和米饭就在你面前,我是没办法喂你吃的

ps: 你开心就好~

嗯嗯,我在改改代码,谢谢了哟!!!!

Kayko 发表于 2021-7-13 15:55:47

{:10_266:}{:10_266:}

一坨屎吖 发表于 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 = "排名第*"
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 = "*月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
    End If
    Next
End With
   
With re
.Global = 0
.Pattern = "下行平均速率(*)+(\.{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 = "排名第*。"
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 = "。*月.*?高频次.*?。"
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





页: [1]
查看完整版本: python对excel表格中指定的内容标注颜色