鱼C论坛

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

复制代码






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

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


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

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

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


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

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

  25. wb.save('changed_color.xlsx')  

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

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

  43. wbook.close()

  44. # 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小时,解决 -----------
  1. from openpyxl import Workbook
  2. import openpyxl as opx
  3. import os, re

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

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


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

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

  25. wb.save('changed_color.xlsx')  

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

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

  43. wbook.close()

  44. # 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中,改了几行代码基本实现了这个功能。
  1. import re
  2. import win32com.client
  3. import os
  4. from docx import Document
  5. 文件 = Document(r'F:工作word.docx')
  6. 具体要标颜色的区域=[]
  7. for table in 文件.tables:
  8.     for row in table.rows:
  9.         for cell in row.cells:
  10.             每个单元格数据 = cell.text
  11.             #print(每个单元格数据)
  12.             提取字符1 = re.search('%,排名第(.*?),下行平均', 每个单元格数据)
  13.             if 提取字符1 != None:
  14.                 #print(提取字符1)
  15.                 覆盖率排名 = 提取字符1.group(1)
  16.                 # print(float(覆盖率的值))
  17.                 if float(覆盖率排名) > 25:
  18.                     覆盖率排名大于25全部标颜色 = re.search('.*?(.*?),下行平均', 每个单元格数据)
  19.                     if 覆盖率排名大于25全部标颜色 != None:
  20.                         覆盖率排名大于25标颜色区域 = 覆盖率排名大于25全部标颜色.group(1)
  21.                     # print(覆盖率排名大于25标颜色区域)
  22.                     具体要标颜色的区域.append(覆盖率排名大于25标颜色区域)
  23.                     # print(具体要标颜色的区域)

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

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

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

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

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

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

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


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


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


  56. 具体要标颜色的区域.clear()
  57. doc.SaveAs2()
  58. doc.Close()
  59. 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中用正则表达式提取其实更方便。
附完整代码:
  1. Sub 宏1()
  2. Dim re As New RegExp, mat, rng As Range, Match, mat2, Match3, Length, Start
  3. For Each rng In Range("H5:H39")
  4. With re
  5. .Global = 0
  6. .Pattern = "排名第[0-9]*"
  7. Set mat = .Execute(rng)
  8.     For Each Match In mat
  9.     If IsNumeric(Replace(Match, "排名第", "")) = True Then
  10.          If (Replace(Match, "排名第", "")) > 25 Then
  11.          With re
  12.           .Global = 0
  13.           .Pattern = "[0-9]*月5G核心城.*?排名第[0-9]*"
  14.            Set mat2 = .Execute(rng)
  15.            For Each Match3 In mat2
  16.              Start = InStr(rng, Match3)
  17.              Length = Len(Match3)
  18.              With rng.Characters(Start:=Start, Length:=Length).Font
  19.             .Color = -16776961
  20.              End With
  21.            Next
  22.          End With
  23.          End If
  24.     End If
  25.     Next
  26. End With
  27.    
  28. With re
  29. .Global = 0
  30. .Pattern = "下行平均速率([1-9][0-9]*)+(\.[0-9]{1,3})?"
  31. Set mat = .Execute(rng)
  32.     For Each Match In mat
  33.     If IsNumeric(Replace(Match, "下行平均速率", "")) = True Then
  34.          If (Replace(Match, "下行平均速率", "")) < 750 Then
  35.              With re
  36.             .Global = 0
  37.             .Pattern = "下行平均速率.*?Mbps"
  38.              Set mat2 = .Execute(rng)
  39.              For Each Match3 In mat2
  40.                  Start = InStr(rng, Match3)
  41.                  Length = Len(Match3)
  42.                  With rng.Characters(Start:=Start, Length:=Length).Font
  43.                 .Color = -16776961
  44.                  End With
  45.              Next
  46.             End With
  47.          End If
  48.     End If
  49.     Next
  50. End With
  51.    
  52.    
  53. With re
  54. .Global = 0
  55. .Pattern = "排名第[0-9]*。"
  56. Set mat = .Execute(rng)
  57.     For Each Match In mat
  58.          If Replace(Replace(Match, "排名第", ""), "。", "") > 25 Then
  59.           With re
  60.             .Global = 0
  61.             .Pattern = "5G时长驻留比.*"
  62.              Set mat2 = .Execute(rng)
  63.              For Each Match3 In mat2
  64.                Start = InStr(rng, Match3)
  65.                Length = Len(Match3)
  66.                With rng.Characters(Start:=Start, Length:=Length).Font
  67.               .Color = -16776961
  68.                End With
  69.              Next
  70.           End With
  71.          End If
  72.     Next
  73. End With
  74.    


  75. With re
  76. .Global = 0
  77. .Pattern = "。[0-9]*月.*?高频次.*?。"
  78. Set mat = .Execute(rng)
  79.     For Each Match In mat
  80.          Start = InStr(rng, Match)
  81.          Length = Len(Match)
  82.          With rng.Characters(Start:=Start, Length:=Length).Font
  83.         .Color = -16776961
  84.          End With
  85.       Next
  86. End With

  87. Next
  88. End Sub



复制代码


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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-20 02:09

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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