VBA Excel macro to apply a unique color to end of each column (to the end of values, not entire column) only if header name is present and unique

JakeP

New Member
Joined
Apr 23, 2023
Messages
14
Office Version
  1. 2019
Platform
  1. Windows
Hi, I've been unsuccessfully trying to create a macro to apply a random but unique color (light cell color with black font or dark cell color with white font) to all values in each column, only if header name is present and uniquely named. (all headers and/or cell values could be alpha/numeric), empty cells can remain white or if easier they can be the same color as the rest of that column.
Columns with same exact header name should be the same color. Can be many rows, but I don't expect to have more than about 30-50 columns but if it could be the max allowable that would be perfect.
Would like to be able to use this in future workbooks, therefore conditional formatting is not really desired.

In the future, I would also like to be able to do the same thing with rows instead of columns.

Many, many thanks for any suggestions!!



1682279172679.png
 

Excel Facts

Wildcard in VLOOKUP
Use =VLOOKUP("Apple*" to find apple, Apple, or applesauce
Hello @JakeP. Welcome to the MrExcel forum. Please accept my warmest greetings and sincere hope that all is well.

Each unique header will have its own (random) color.
For example:
1682388830505.png


Try the following macro.
VBA Code:
Sub Coloring()
  Dim i&, j&, m&, x&, y&, lr&, lc&
  Dim arr As Variant
  Dim dic As Object

  lr = Cells.Find("*", , xlValues, xlPart, xlByRows, xlPrevious).Row
  lc = Cells(1, Columns.Count).End(1).Column
  With Range("A1", Cells(lr, lc))
    .Interior.Color = xlNone
    .Font.Color = vbBlack
  End With

  Set dic = CreateObject("Scripting.Dictionary")
  For j = 1 To lc
    If Not dic.exists(Cells(1, j).Value) Then
      dic(Cells(1, j).Value) = dic.Count + 1      'Unique headers
    End If
  Next
  
  Randomize
  arr = Evaluate("ROW(1:130)")                    'random color
  For i = 1 To UBound(arr)
    x = Int(UBound(arr) * Rnd + 1)
    y = arr(i, 1)
    arr(i, 1) = arr(x, 1)
    arr(x, 1) = y
  Next i
  
  For j = 1 To lc
    With Cells(1, j)
      m = arr(dic(.Value), 1)
      With .Resize(lr).SpecialCells(xlCellTypeConstants)
        .Interior.Color = 8388608 + (m * 5000)    'initial color for 1
        If m Mod 13 < 7 Then .Font.Color = vbWhite
      End With
    End With
  Next
End Sub

If you want all cells:
1682389302513.png


Change this line:
VBA Code:
With .Resize(lr).SpecialCells(xlCellTypeConstants)

By this line:
VBA Code:
With .Resize(lr)

--------------
Let me know the result and I'll get back to you as soon as I can.
Sincerely
Dante Amor
--------------
 
Upvote 0
Hello Dante,
Thanks so much for the warm welcome and the effort to work on this macro.
I put this in a module for the file that contains the worksheet shown below.
I selected the desired range, ran the macro and got the following runtime error message.
Thanks again, JakeP
1682391323644.png
 
Upvote 0
Hi Dante,
I moved the range so it begins at A1 and tried the both versions again.
They seem to work quite good like this however, seems some of the lighter interiors have white fonts and difficult to read.
If this easy to fix, it would very nice.
Also it would be great if both versions could work on a selected range as opposed to starting at A1.
Thanks again!!
JP
1682393105310.png

1682393135630.png
 
Upvote 0
... seems some of the lighter interiors have white fonts and difficult to read.
I made some adjustments, I hope it looks better 😇.

Also it would be great if both versions could work on a selected range as opposed to starting at A1.
Ok, now it works with cell selection :cool: . (For the second version of the macro, you must change the same line ;) )

VBA Code:
Sub Coloring_v2()
  Dim i&, j&, m&, x&, y&, lr&, lc&, iniR&, iniC&
  Dim arr As Variant
  Dim dic As Object

  With Selection
    .Interior.Color = xlNone
    .Font.Color = vbBlack
    iniR = .Cells(1).Row
    iniC = .Cells(1).Column
    lc = .Columns.Count + iniC - 1
    lr = .Rows.Count + iniR - 1
  End With
 
  Set dic = CreateObject("Scripting.Dictionary")
  For j = iniC To lc
    If Not dic.exists(Cells(iniR, j).Value) Then
      dic(Cells(iniR, j).Value) = dic.Count + 1      'Unique headers
    End If
  Next
 
  Randomize
  arr = Evaluate("ROW(1:130)")                    'random color
  For i = 1 To UBound(arr)
    x = Int(UBound(arr) * Rnd + 1)
    y = arr(i, 1)
    arr(i, 1) = arr(x, 1)
    arr(x, 1) = y
  Next i
 
  For j = iniC To lc
    With Cells(iniR, j)
      m = arr(dic(.Value), 1)
      With .Resize(lr).SpecialCells(xlCellTypeConstants)
        .Interior.Color = 8388608 + (m * 5000)    'initial color for 1
        If m Mod 13 >= 1 And m Mod 13 <= 5 Then .Font.Color = vbWhite
      End With
    End With
  Next
End Sub

--------------
Let me know the result and I'll get back to you as soon as I can.
Sincerely
Dante Amor
--------------
 
Upvote 0
Hi Dante,
Getting very close :)
Both work on the selected range now, however both versions apply colors passed (below) the selected range.
You can see the top selection does not color empty cells, but the colors that did apply extended into the lower range of data.

I made the changes to code to color all cells and tried it on the lower selected range and you can see how far below the colors extended.
I think the font colors will be hard to get visibly matched with the appropriate interior color unless you know some tricks to solve for this.

Thank you, JP

1682395163547.png
 
Upvote 0
Both work on the selected range now, however both versions apply colors passed (below)
Fixed

I think the font colors will be hard to get visibly matched with the appropriate interior color
I think fixed. Look at the image:
1682432308813.png


Please try again:
VBA Code:
Sub Coloring_v2()
  Dim i&, j&, m&, x&, y&, lr&, lc&, iniR&, iniC&
  Dim arr As Variant
  Dim dic As Object

  With Selection
    .Interior.Color = xlNone
    .Font.Color = vbBlack
    iniR = .Cells(1).Row
    iniC = .Cells(1).Column
    lc = .Columns.Count + iniC - 1
    lr = .Rows.Count + iniR - 1
  End With
  
  Set dic = CreateObject("Scripting.Dictionary")
  For j = iniC To lc
    If Not dic.exists(Cells(iniR, j).Value) Then
      dic(Cells(iniR, j).Value) = dic.Count + 1      'Unique headers
    End If
  Next
  
  Randomize
  arr = Evaluate("ROW(1:130)")                    'random color
  For i = 1 To UBound(arr)
    x = Int(UBound(arr) * Rnd + 1)
    y = arr(i, 1)
    arr(i, 1) = arr(x, 1)
    arr(x, 1) = y
  Next i
  
  For j = iniC To lc
    With Cells(iniR, j)
      m = arr(dic(.Value), 1)
      With .Resize(lr - iniR + 1).SpecialCells(xlCellTypeConstants)
        .Interior.Color = 8388608 + (m * 5000)    'initial color for 1
        If m Mod 13 >= 1 And m Mod 13 <= 6 Then .Font.Color = vbWhite
      End With
    End With
  Next
End Sub

--------------
Let me know the result and I'll get back to you as soon as I can.
Sincerely
Dante Amor
--------------
 
Upvote 0
Hello Dante,
This version seems to work much better! Nice job!!

I tried the code change to the version that colored the entire range, it looks good but still applies colors below the selected range.
Is that previous line of code changed before still valid in this latest code version?

I hate to ask, but would be it be to much, if you could change this to work the same way for rows instead of columns?

Thanks again!!



1682472426516.png
1682472467584.png
 
Upvote 0
Hello Dante,
I believe I figured out the code change to make it color all cells only in the selected range.
Thank your VERY much for your quick and knowledgeable support!! :)

What do you think about changes to have it work for rows instead of columns?

BR, JP


1682473460620.png
1682473640766.png
 
Upvote 0

Forum statistics

Threads
1,223,912
Messages
6,175,346
Members
452,638
Latest member
Oluwabukunmi

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top