本文于2023年8月22日首发于本人同名公众号:Excel活学活用,更多文章案例请搜索关注!
内容提要
- 突出显示行列,保留原有背景色
大家好,我是冷水泡茶,前天我发了一篇小文【Excel VBA 突出显示高亮行列】,通过VBA代码,把当前单元格所在行列高亮显示,实际也就是给单元格所在十字区域填上一个背景色:
原来的代码有一点缺陷,就是会影响到单元格原有的背景色,也就是说,只能在没有背景色的表格使用,否则,原来设置好的背景色会被破坏得七零八落,简直不忍直视,代码的使用价值大打折扣。本来也有考虑到能恢复原来的背景色的,但由于赶着当天更新公众号文章,另外也没有考虑清楚,觉得可能会比较繁琐,也就没有去做这样的功能。
但是,昨天公众号后台有粉丝留言,询问会不会影响表格中原有颜色:
我就回复他说会影响的,要想不影响也可能实现,但似乎没什么必要。本以为就此拉倒,但今天他又留言,说找了好久都没有解决办法,隔着屏幕我都感觉到一丝丝失望:
好吧,这就让我感觉不解决这个问题都有点不好意思了。于是,今天下午我抽了点时间研究了一下,终于实现可以高亮但不影响原有单元格的背景色,我们一起来看看吧:
基本思路
1、当我们点击一个单元格的时候,我们会定义一个需要高亮的区域,在给它填色之前,我们把该区域的所有单元格的背景色记下来,然后才给它高亮。
2、当选中另一个单元格时,首先要还原上次标色的区域的背景色,然后再记下当前区域单元格的原有背景色,最后,把当前单元格所在行、列标色。
程序代码
1、模块1,HighLight过程,高亮显示:
Public LastRange As Range ' 用于存储上次突出显示的区域
Public currCell As Range
Public Dic As Object
Public blnHighLight As Boolean
Sub HighLight()
On Error Resume Next
Dim dataRange As Range
Dim currRange As Range
Dim lastRow As Long
Dim lastCol As Long
Dim rng As Range
Set Dic = CreateObject("Scripting.Dictionary")
'获取工作表的数据区域,这里假设数据区域从A1开始,向右和向下延伸
With ActiveSheet
lastRow = .UsedRange.Rows.Count
lastCol = .UsedRange.Columns.Count
Set dataRange = .Range("A1").Resize(lastRow, lastCol)
'检查选定的单元格是否在数据区域内
If Not Intersect(currCell, dataRange) Is Nothing Then
Set currRange = Union(currCell.EntireRow, currCell.EntireColumn)
Set currRange = Intersect(currRange, dataRange)
Else
lastRow = Application.WorksheetFunction.Max(lastRow, currCell.Row)
lastCol = Application.WorksheetFunction.Max(lastCol, currCell.Column)
Set dataRange = Range(Cells(1, 1), Cells(lastRow, lastCol))
Set currRange = Union(currCell.EntireRow, currCell.EntireColumn)
Set currRange = Intersect(currRange, dataRange)
End If
For Each rng In currRange
Dic(rng.Address) = rng.Interior.Color
Next
currRange.Interior.Color = RGB(245, 245, 220)
Set LastRange = currRange
End With
EndSub
代码解析:
(1)定义公共变量,lastRange,上一个高亮区域;currCell,当前单元格;Dic,字典,用于存放单元格原来的背景色;blnHighLight ,逻辑变量,用来判断是否启用高亮。
(2)设置数据区域为当前活动工作表的已使用区域。
(3)判断当前单元格是否在数据区域之内,如果在的话,就把当前区域设置在数据区域之内,以当前单元格为中心的十字区域;如果当前单元格不在数据区域之内,则把数据区域扩展到包括当前单元格,再在新的数据区域内,设置一个以当前单元格为中心的十字区域(非整行、整列,如果设置成整行整列,那就有问题了,高亮区域的单元格太多,都装入字典的话,程序根本没法运行,所以如果工作表数据量非常大的话,可能就不太适合这种方法了)。
(4)非常关键的一步,把当前准备高亮的十字区域中所有单元格的地址作为字典的key,其背景色作为字典的item,统统装入字典。
(5)对当前区域标色,可以根据需要调整设置。
(6)把当前区域赋值给LastRange,以备在选择单元格变化、工作表切换、文件关闭时,恢复其背景色。
2、其他过程:
Private Sub CmdHighLight_Click()
If Not LastRange Is Nothing Then
For Each rng In LastRange
rng.Interior.Color = Dic(rng.Address)
Next
Set LastRange = Nothing ' 清除上次突出显示的区域
Dic.RemoveAll
End If
If blnHighLight Then
blnHighLight = False
Me.CmdHighLight.Caption = "开启高亮"
Else
blnHighLight = True
Me.CmdHighLight.Caption = "取消高亮"
End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
IfblnHighLightThen
If Not LastRange Is Nothing Then
For Each rng In LastRange
rng.Interior.Color = Dic(rng.Address)
Next
Set LastRange = Nothing ' 清除上次突出显示的区域
Dic.RemoveAll
End If
Set currCell = Target.Cells(1, 1)
Call HighLight
End If
End Sub
Private Sub Worksheet_Deactivate()
Dim rng As Range
If Not LastRange Is Nothing Then
For Each rng In LastRange
rng.Interior.Color = Dic(rng.Address)
Next
Set LastRange = Nothing ' 清除上次突出显示的区域
Dic.RemoveAll
End If
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim rng As Range, ws As Worksheet, btn As OLEObject
If Not LastRange Is Nothing Then
For Each rng In LastRange
rng.Interior.Color = Dic(rng.Address)
Next
Set LastRange = Nothing ' 清除上次突出显示的区域
End If
'在关闭工作簿前,把开启或取消高亮的命令按钮的Caption恢复成“开启高亮”
For Each ws In ThisWorkbook.Sheets
For Each btn In ws.OLEObjects
If btn.Object.Caption = "取消高亮" Then
btn.Object.Caption = "开启高亮"
End If
Next
Next
ThisWorkbook.Save
End Sub
代码解析:
(1)CmdHighLight,增加一个切换是否启用高亮的命令按钮,在切换之前,先还原高亮单元格的背景色,通过字典就一行代码,非常方便。
rng.Interior.Color = Dic(rng.Address)
每点击一次,就切换命令按钮的Caption,变量blnHighlight的值。
(2)Worksheet_SelectionChange,工作表的选择区域变化事件,根据blnHighLight的值 ,决定是否启用高亮。如果启用,则先还原上次高亮区域的背景色,把currCell设置为目标区域的第一个单元格,避免多行多列高亮。然后调用HighLight过程。
(3)Worksheet_Deactivate,工作表变为非激活状态事件,就是激活了其他工作表,则还原高亮单元格原来的背景色。
(4)Workbook_BeforeClose,工作表关闭前事件,先还原上次设置的高亮单元格的背景色,然后循环工作表,找到Caption为“取消高亮”的控件,并把它改为“开启高亮”(主要原因是,如果我们点“开启高亮”后,没有点“取消高亮”就关闭工作表的,下次启动时,该命令按钮的Caption为“取消高亮”,而这时blnHighLight的值为FALSE,要多点两次才能“开启高亮”),保存工作表。
3、注意事项:
(1)本工作表在关闭前会自动保存,如果你要通过不保存就关闭工作表以取消保存前的操作,要把Workbook_BeforeClose中的ThisWorkbook.Save代码删掉。
(2)如果要在其他工作表使用,要把第一个工作表中的代码复制过去,再在新的工作表上增加一个命令按钮,Name改为“CmdHighLight”,Caption改不改无所谓,点击一次就自动修改。
~~~~~~End~~~~~~
喜欢就点个赞、点在看、留个言呗!分享一下更给力!感谢!