Change Cell color when it selected and back original color after leaving it - excel

I'd like to change Color Cell when I select it. I use this function but I can't back the original color of the Cell.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Static rngcolor As Range
If Not rngcolor Is Nothing Then rngcolor.Interior.ColorIndex = xlNone
Set rngcolor = Target
rngcolor.Interior.Color = vbYellow
End Sub

You need to store the original Color as well as the cell reference. Also, the user might select more than one cell, each of which may have its own color.
Here's a starting point to deal with these complexities. Note that this accounts for the user selecting a contiguous range of >= 1 cells. They may also select a non-contiguous mutli cell range. A second more complex version provides for this
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Static rngcolor As Range
Static OldColor As Variant
Dim rw As Long, cl As Long
If Not rngcolor Is Nothing Then
If IsArray(OldColor) Then
On Error GoTo NoRestore
For rw = 1 To rngcolor.Rows.Count
For cl = 1 To rngcolor.Columns.Count
If IsEmpty(OldColor(rw, cl)) Then
rngcolor.Cells(rw, cl).Interior.ColorIndex = xlNone
Else
rngcolor.Cells(rw, cl).Interior.Color = OldColor(rw, cl)
End If
Next
Next
On Error GoTo 0
Else
If IsEmpty(OldColor) Then
rngcolor.Interior.ColorIndex = xlNone
Else
rngcolor.Interior.Color = OldColor
End If
End If
End If
NoRestore:
On Error GoTo 0
Set rngcolor = Target
ReDim OldColor(1 To Target.Rows.Count, 1 To Target.Columns.Count)
For rw = 1 To Target.Rows.Count
For cl = 1 To Target.Columns.Count
If Target.Cells(rw, cl).Interior.ColorIndex = xlNone Then
OldColor(rw, cl) = Empty
Else
OldColor(rw, cl) = Target.Cells(rw, cl).Interior.Color
End If
Next
Next
rngcolor.Interior.Color = vbYellow
End Sub
Version to account for a non-contiguous range selection
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Static rngcolor As Range
Static OldColor As Variant
Dim OldColrRng As Variant
Dim ar As Long, rw As Long, cl As Long
If Not rngcolor Is Nothing Then
If IsArray(OldColor) Then
On Error GoTo NoRestore
For ar = 1 To rngcolor.Areas.Count
For rw = 1 To rngcolor.Areas(ar).Rows.Count
For cl = 1 To rngcolor.Areas(ar).Columns.Count
If IsEmpty(OldColor(ar)(rw, cl)) Then
rngcolor.Areas(ar).Cells(rw, cl).Interior.ColorIndex = xlNone
Else
rngcolor.Areas(ar).Cells(rw, cl).Interior.Color = OldColor(ar)(rw, cl)
End If
Next
Next
Next
On Error GoTo 0
Else
If IsEmpty(OldColor) Then
rngcolor.Interior.ColorIndex = xlNone
Else
rngcolor.Interior.Color = OldColor
End If
End If
End If
NoRestore:
On Error GoTo 0
Set rngcolor = Target
ReDim OldColor(1 To Target.Areas.Count)
For ar = 1 To Target.Areas.Count
ReDim OldColrRng(1 To Target.Areas(ar).Rows.Count, 1 To Target.Areas(ar).Columns.Count)
OldColor(ar) = OldColrRng
Next
For ar = 1 To Target.Areas.Count
For rw = 1 To Target.Areas(ar).Rows.Count
For cl = 1 To Target.Areas(ar).Columns.Count
If Target.Areas(ar).Cells(rw, cl).Interior.ColorIndex = xlNone Then
OldColor(ar)(rw, cl) = Empty
Else
OldColor(ar)(rw, cl) = Target.Areas(ar).Cells(rw, cl).Interior.Color
End If
Next
Next
Next
rngcolor.Interior.Color = vbYellow
End Sub
Note: Using Static (or global) variables is vulnerable to being stopped by an error, either in this code or other code. Depending on how important it is to restore the colors, you may want to store the Range reference and colors somewhere else: eg in cells on a (hidden) sheet, in (hidden) names, in a external repository (eg text or ini file, in the registary etc), or in an CustomXmlPart

To get this done with the original colour of the cell (as per comments) is a lot more complicated than you've done in your example (setting it back to xlnone). The following sub with accompanying function will do the trick for any RGB colour available.
Public rngcolor As Range
Public rngcolor2 As Variant
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not rngcolor Is Nothing Then
If Not rngcolor2 = "" Then
If rngcolor2 = 16777215 Then
rngcolor.Interior.ColorIndex = xlNone
Else
rngcolor.Interior.Color = rngcolor2
End If
End If
End If
Set rngcolor = Target
rngcolor2 = Color(Target)
rngcolor.Interior.Color = vbYellow
End Sub
The function getting the RGB colour form the cell: (source)
Function Color(rng As Range, Optional formatType As Integer = 0) As Variant
Dim colorVal As Variant
colorVal = Cells(rng.Row, rng.Column).Interior.Color
Select Case formatType
Case 1
Color = Hex(colorVal)
Case 2
Color = (colorVal Mod 256) & ", " & ((colorVal \ 256) Mod 256) & ", " & (colorVal \ 65536)
Case 3
Color = Cells(rng.Row, rng.Column).Interior.ColorIndex
Case Else
Color = colorVal
End Select
End Function
This stores the original cell and original colour as an RGB value in a public variable, and resets the deselected cell to these values.
Please note, if multiple cells are selected at once, their interior colour will be reset to that of the first cell in the selection.
Also note the value 16777215 is for RGB white, the default cell colour, equal to xlNone. If the exception for this is left out, the cell will be filled with white, instead of being reset to no colour. If you have cells specifically coloured white, omit this step.

Related

Change font color for a row of text in cell which contains a certain value

I am writing a check in/out program in excel and have gotten te request that if a line contains "|0|" it should get a different font color.
I've tried with Instr and Cells().Characters but I cannot seem to figure out how to do it.
The cells can have a variety of rows of text. Which is easy enough to solve with splitting them on a return and having a for loop loop, but I cannot seem to figure out how to assign a different font color to a row of text that contains the required value.
Image for illustration of the data:
How do I best solve this?
Added information:
The goal of this is that on button press the whole line of text where the |O| is would be collored differently. Other lines of text that do not have this will remain the same color.
Like in this image as a concept
[]
try this
Public Sub ExampleMainSub()
Dim cell As Range
For Each cell In Selection
If HasMySymbols(cell.Value) Then
WorkWithCellContent cell
Else
cell.Font.ColorIndex = xlAutomatic
cell.Font.TintAndShade = 0
End If
Next cell
End Sub
Private Sub WorkWithCellContent(ByVal cell As Range)
Dim arr As Variant
arr = Split(cell.Value, Chr(10))
Dim firstPosOfRow As Long
firstPosOfRow = 1
Dim subLine As Variant
For Each subLine In arr
If HasMySymbols(subLine) Then
cell.Characters(start:=firstPosOfRow, Length:=Len(subLine)).Font.Color = vbRed
Else
cell.Characters(start:=firstPosOfRow, Length:=Len(subLine)).Font.ColorIndex = xlAutomatic
End If
firstPosOfRow = firstPosOfRow + Len(subLine) + 1 '+1 is needed
Next subLine
End Sub
Private Function HasMySymbols(ByVal somestring As String) As Boolean
HasMySymbols = InStr(1, somestring, "|0|") > 0
End Function
Try this. It works for me.
Sub ChangeRowFontColour()
Dim rng As Range
Dim TextToFind As String
Dim FirstFound As String
TextToFind = "Specific Text"
With ActiveSheet.UsedRange
Set rng = .Cells.Find(TextToFind, LookIn:=xlValues)
If Not rng Is Nothing Then
FirstFound = rng.Address
Do
rng.EntireRow.Font.ColorIndex = 3
For Each part In rng
lenOfPart = Len(part)
lenTextToFind = Len(TextToFind)
For i = 1 To lenOfPart
tempStr = Mid(part, i, lenTextToFind)
If tempStr = TextToFind Then
part.Characters(Start:=i, Length:=lenTextToFind).Font.ColorIndex = 0
End If
Next i
Next
Set rng = .FindNext(rng)
Loop While Not rng Is Nothing And rng.Address <> FirstFound
End If
End With
End Sub

Adding a note to a cell based on another cell

I am trying to add a specific note to a cell based on the cell value to explain what the cell contents are. I am trying to use the code below to do this but I get a run-time error '1004' on the following line:
Target.Cells.Comment.Text Text:=Comment_E
Private Sub Worksheet_Change(ByVal Target As Range)
'Defining what column is being changed
If Target.Column = 3 Then
'Adding a comment to the cell
Dim Status_Col As String
Dim NA As String
Dim i As Integer
'Types
Dim Comment_T As String
'Explainations
Dim Comment_E As String
i = 4
Comment_T = Target.Cells.Value
For i = 4 To 10 ' checking the list of types
If Cells(i, 14).Value = Comment_T Then
Comment_E = Cells(i, 15).Value
End If
Next i
Target.Cells.Select
Target.Cells.AddComment
Target.Cells.Comment.Visible = False
Target.Cells.Comment.Text Text:=Comment_E
Selection.ShapeRange.ScaleHeight 0.48, msoFalse, msoScaleFromTopLeft
Selection.ShapeRange.ScaleWidth 3.32, msoFalse, msoScaleFromTopLeft
End If
End Sub
You need to account for the case where a cell already has a comment, and the case where multiple cells are updated (eg fill down).
Few fixes/suggestions:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim v, cmt As Comment, rng As Range, c As Range
'any changes in Col3?
Set rng = Application.Intersect(Target, Me.Columns(3))
'optionally set some limit for the size of change you want to handle
If rng.Cells.CountLarge > 100 Then Exit Sub
'now process each cell in the col3 range
For Each c In rng.Cells
v = Application.VLookup(c.Value, Me.Range("N4:O10"), 2, False)
If Not IsError(v) Then
Set cmt = c.Comment 'already has a comment?
If cmt Is Nothing Then
Set cmt = c.AddComment() 'no comment so add one
With cmt 'formatting...
.Visible = False
.Shape.Height = 30 'fixed height/width is easier
.Shape.Width = 100
End With
End If
cmt.Text v 'set/replace text
End If
Next c
End Sub

Error when clearing multiple cells in Excel

I'm using Worksheet_Change to make a value (either 1 or 0) appear in the next cell (Bx) when a value is entered in a range of cells (A1:A10).
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("A1:A10")) Is Nothing Then
If Target.Value = 1 Then
Target.Offset(0, 1).Value = 1
Else:
Target.Offset(0, 1).Value = 0
End If
End If
End Sub
The problem occurs when I try to clear the cells in column A.
When I select the cells I want to clear and press "Delete" I get "Run-time error '13' - Type mismatch" on the line "IF Target.Value = 1".
I would also like the cells in the B column to be cleared if I clear cells in the A column. E.g. if I delete cell A2:A5, B2:B5 should be cleared.
From what I understand the problem is that when selecting multiple cells it returns an array as the Target, and this is a mismatch with the Integer.
Is there a way around this problem?
Try this. You need to cater for multiple cells in some way, for the reasons you mention, and add an extra clause to your If.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim r As Range, r1 As Range
Set r = Intersect(Target, Range("A1:A10"))
If Not r Is Nothing Then
For Each r1 In r
If r1.Value = 1 Then
r1.Offset(0, 1).Value = 1
ElseIf r1.Value = vbNullString Then
r1.Offset(0, 1).Value = vbNullString
Else
r1.Offset(0, 1).Value = 0
End If
Next r1
End If
End Sub
In a first step we add the functionality that multiple cells are selected and changed:
Private Sub Worksheet_Change_Var1(ByVal Target As Range)
Dim targetCell As Range
'If Target.Range.count
If Not Intersect(Target, Range("A1:A10")) Is Nothing Then
If Target.Cells.Count > 1 Then
For Each targetCell In Target
If targetCell.Value = 1 Then
targetCell.Offset(0, 1).Value = 1
Else
targetCell.Offset(0, 1).Value = 0
End If
Next targetCell
Else
If Target.Value = 1 Then
Target.Offset(0, 1).Value = 1
Else
Target.Offset(0, 1).Value = 0
End If
End If
End If
End Sub
In the 2nd step we understand that also the "one cell" case can be handled in the same way and we add an if clause for the "cell(s) cleared" case:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim targetCell As Range
'If Target.Range.count
If Not Intersect(Target, Range("A1:A10")) Is Nothing Then
For Each targetCell In Target
If targetCell.Value = 1 Then
targetCell.Offset(0, 1).Value = 1
Else
targetCell.Offset(0, 1).Value = 0
End If
'if cell in col A is empty, then clear cell in col B
If targetCell.Value = "" Then targetCell.Offset(0, 1).ClearContents
Next targetCell
End If
End Sub

Maintain count of each change to cell value

Suppose I have a value in cell A1 and everytime the cell value of A1 changes, the cell on b1 counts the change.
I have a code it works just with A1(value)cell and b1(count on change) cell. i would like to apply this function on cell E2:E709 (value) cells and F2:F709 (count on change) cell.
Private Sub Worksheet_Change(ByVal Target As Range)
Static OldVal As Variant
If Target.Address(False, False) = "A1" Then
Application.EnableEvents = False
If Target.Value <> OldVal Then
Target.Offset(, 1).Value = Target.Offset(, 1).Value + 1
OldVal = Target.Value
End If
Application.EnableEvents = True
End If
End Sub
Try code below:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
' If change was outside range we are interested in, then quit Sub
If Intersect(Target, Range("E2:E709")) Is Nothing Then Exit Sub
' store reference to cell in F column for simplicity
Dim c As Range: Set c = Target.Offset(0, 1)
' check if cell in F column has any value, if not, then assign it 1
If c.Value = "" Then
c.Value = 1
' else increment it by one
Else
c.Value = c.Value + 1
End If
End Sub
Consider:
Private Sub Worksheet_Change(ByVal Target As Range)
Static OldVal(2 To 709) As Variant
Dim E As Range, F As Range, r As Range, Intersekt As Range
Dim rw As Long
Set E = Range("E2:E709")
Set F = Range("F2:F709")
Set Intersekt = Intersect(E, Target)
If Intersekt Is Nothing Then Exit Sub
Application.EnableEvents = False
For Each r In Intersekt
rw = r.Row
If r.Value <> OldVal(rw) Then
r.Offset(0, 1).Value = r.Offset(0, 1).Value + 1
OldVal(rw) = r.Value
End If
Next r
Application.EnableEvents = True
End Sub
We use an array for OldVal rather than a single item.We use a (potentially) multi-cell IntersektRange` to facilitate changing more than one cell at a time.

Excel Cell Color by AutoCAD color in contents

Output I'm hoping for is similar to this page: http://sub-atomic.com/~moses/acadcolors.html, but in Excel.
What we're trying to do is to tie AutoCAD colors to a cell. I want to be able to enter a color number in the cell (say color 10, which is red), and have the cell change to that color. I don't know how to do this without doing a macro. I assume it's going to be VBA of some type.
I have the RGB equivalents from the site above - I assume I can pull some type of a lookup.
I realize this can be done with a particularly nasty bit of conditional formatting, but I'd really prefer something a little more streamlined.
Help?
EDIT: UGP provided some really good code which did exactly what I needed. This is the final code I wound up using (adjusted for my sheet naming and with a bit of additional functionality).
Private Sub Worksheet_Change(ByVal Target As Range)
Dim KeyCells As Range
Set KeyCells = Range(Cells(1, 6), Cells(1000, 6))
If Not Application.Intersect(KeyCells, Range(Target.Address)) _
Is Nothing Then
CellChanged = Target.Address 'Cell that changed
If IsNumeric(Worksheets("Master").Range(CellChanged).Value) Then
If Worksheets("Master").Range(CellChanged).Value = 0 Then
Worksheets("Master").Range(CellChanged).Interior.ColorIndex = xlNone
Worksheets("Master").Range(CellChanged).Font.Color = vbBlack
Else
Worksheets("Master").Range(CellChanged).Interior.Color =
Color(Worksheets("Master").Range(CellChanged).Value)
Worksheets("Master").Range(CellChanged).Font.Color =
textColor(Worksheets("Master").Range(CellChanged).Value)
End If
End If
End If
End Sub
Function Color(ByRef ID As Integer) As Long
Dim R, G, B As Integer
For i = 3 To 257
If ID = Worksheets("Colors").Cells(i, 1).Value Then
R = Worksheets("Colors").Cells(i, 2).Value
G = Worksheets("Colors").Cells(i, 3).Value
B = Worksheets("Colors").Cells(i, 4).Value
Color = RGB(R, G, B)
Exit For
End If
Next i
End Function
Function textColor(ByRef ID As Integer) As Long
If ID <= 9 Then
textColor = vbBlack
Else
If ID Mod 10 >= 4 Then
textColor = vbWhite
Else
textColor = vbBlack
End If
End If
End Function
Put this code in Sheet1 by opening the editor with alt+f11:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim KeyCells As Range
Set KeyCells = Range(Cells(1, 1), Cells(1000, 1000))
If Not Application.Intersect(KeyCells, Range(Target.Address)) _
Is Nothing Then
CellChanged = Target.Address 'Cell that changed
If IsNumeric(Worksheets("Sheet1").Range(CellChanged).Value) Then
Worksheets("Sheet1").Range(CellChanged).Interior.Color = Color(Worksheets("Sheet1").Range(CellChanged).Value)
End If
End If
End Sub
Function Color(ByRef ID As Integer) As Long
Dim R, G, B As Integer
For i = 2 To 256
If ID = Worksheets("Sheet2").Cells(i, 4).Value Then
R = Worksheets("Sheet2").Cells(i, 5).Value
G = Worksheets("Sheet2").Cells(i, 6).Value
B = Worksheets("Sheet2").Cells(i, 7).Value
Color = RGB(R, G, B)
Exit For
End If
Next i
End Function
It'll check for user input from Cell(1,1) to Cell(1000,1000) then it grabs the Color from Sheet2 where i put the autocad table you linked like this (copy and paste the table):

Resources