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()
{:5_101:}自己顶自己 {:5_109:}有没有大佬哟。。急求 学习学习 超级玛尼哄 发表于 2021-7-12 09:56
学习学习
{:5_101:}希望哥们研究下,如何实现呢 本帖最后由 阿奇_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
阿奇_o 发表于 2021-7-12 15:03
先吐槽一句,你TM牛!居然 真·中文编程!
兄弟,属实厉害啊,但是我刚刚运行了下,单元格内有4个条件内容,但是程序跑了之后,只要有一个内容符合条件,整个单元格就标注了颜色。我要实现的是只对单独的内容标注颜色呢。 本帖最后由 一坨屎吖 于 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()
一坨屎吖 发表于 2021-7-12 17:52
兄弟,属实厉害啊,但是我刚刚运行了下,单元格内有4个条件内容,但是程序跑了之后,只要有一个内容符合 ...
碗筷和米饭就在你面前,我是没办法喂你吃的{:10_312:}
ps: 你开心就好~ {:10_250:} 阿奇_o 发表于 2021-7-13 13:12
碗筷和米饭就在你面前,我是没办法喂你吃的
ps: 你开心就好~
嗯嗯,我在改改代码,谢谢了哟!!!! {:10_266:}{:10_266:} 本帖最后由 一坨屎吖 于 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]