I want to use the value in cell as a dynamic way to change the range in my macro, more specifically when changing the colour of a cell.
Lets says CELL A1 hosts the desirable range data. The macro will always look at this cell. The text in A1 = 'B4' therefore I want this to be the selected cell to have a colour fill. This will be repeated quite a few times and the data will change, this is why i need it to be a dynamic macro not conditional formatting.
Below is the standard colour macro and is far as i can get, VBA noob sorry.
Sub Colour2()
'
' Colour2 Macro
'
'
Range("B4").Select
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 16731903
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End Sub
Hope this makes sense and thanks for your understanding and help.
M
Highlight Range Supplied in a Cell
This is an automated solution. You run nothing. Just copy the codes in the appropriate modules.
As you change the range address in cell A1, the color is applied to the cells of the supplied range address and the range is selected.
Sheet object module e.g. Sheet1 (the name not in parentheses in the VBE Project Explorer)
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Const mAddress As String = "A1"
Const ColorValue As Long = 16731903
Dim mCell As Range: Set mCell = Range(mAddress)
If Not Intersect(mCell, Target) Is Nothing Then
On Error Resume Next
Dim rg As Range: Set rg = Range(mCell.Value)
On Error GoTo 0
If Not rg Is Nothing Then
Application.ScreenUpdating = False
' Removes the colors from all cells before applying the color.
applyColor rg, ColorValue, True
' Applies the color without removing the previously applied colors.
'applyColor rg, ColorValue
rg.Select
Application.ScreenUpdating = True
End If
End If
End Sub
Standard Module e.g. Module1 (optionally in the same sheet object module)
Sub applyColor( _
ByVal rg As Range, _
ByVal ColorValue As Long, _
Optional ByVal resetBeforeApply As Boolean = False)
If resetBeforeApply Then
rg.Worksheet.Cells.Interior.Color = xlNone
End If
With rg.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = ColorValue
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End Sub
The standard module is preferred because it could then easily be used for other worksheets.
Related
Hello All,
Currently working on SpecialCells(xlCellTypeVisible) where after filtering data, the cells would get highlighted with green color as shown in image 1, but when the formula is used Row no is also getting selected.
The result which I need to get visible cells would highlighted with no extra row added as shown in image 2.
Below is formula used.
OB2.ActiveSheet.UsedRange.Offset(1, 0).SpecialCells(xlCellTypeVisible).Rows.Select
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorAccent6
.TintAndShade = 0.399975585192419
.PatternTintAndShade = 0
End With
We try to remove the header by using .Offset(1,0). This however adds a row to the bottom. Consider:
Sub RemoveHeaderRow()
Dim tablee As Range
Dim tableeBody As Range
Set tablee = Range("A1").CurrentRegion
Set tableeBody = tablee.Offset(1, 0).Resize(tablee.Rows.Count - 1, tablee.Columns.Count)
tableeBody.Select
End Sub
This is the range to use SpecialCells on.
New user, was referred to your helpful website by a friendly team member.
Problem: Trying to force a user in excel to fill in a cell in a column (column O) before filling in a cell in columns I-L. The problem lies in that not every cell in the columns needs to be filled in. I've found a VBA code that has somewhat helped but the problem is the pop up will still occur if column O is filled before there is text in just one of the cells in column I-L (and therefore the error occurs unless all 4 cells in the row are filled in). As mentioned, the goal is (for example) to get O264 to be filled in first before any of the cells in column I,J,K or L264 are filled in.
Further exacerbating this issue is there are multiple rows I need this applied to, believe this is where the range fits in. However, playing with the range line in excel does not work in the way I've tried.
Code below:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("I:L")) Is Nothing Then
If Target.Cells.Count > 1 Or IsEmpty(Target) Then Exit Sub
If Target.Offset(, -1).Value = "" Then
MsgBox "You must first enter feedback in column ""O"""
Target.Value = ""
Target.Offset(, -1).Select
End If
End If
End Sub
This could be a case where you might need to aid the user a little more. You could do that by hiding the dependent cells, by locking them, by greying them out, etc. My feeling is that displaying a message box whenever a user enters data in the wrong order is a little too reactive.
In the example below, the target cells are locked and greyed until something is entered in column 'O'. You'd also need to create a list of target rows if you have more than one.
In your code behind the appropriate sheet, the skeleton code below should get you started. I've included a couple of helper functions to make the code a little clearer for you:
Option Explicit
Private Const SHEET_PASSWORD As String = "xyz" 'whatever password you choose.
Private Const TARGET_ROWS As String = "2,4,6" 'your target rows, separated by commas.
Private Const TARGET_COLUMN As String = "O"
Private Const DEPENDENT_COLUMNS As String = "I:L"
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rng As Range, cell As Range
Set rng = Intersect(Target, Me.Columns(TARGET_COLUMN))
'Exit routine if we're not in the target column.
If rng Is Nothing Then Exit Sub
'Process the target column cells.
For Each cell In rng.Cells
If IsTargetRow(cell.Row) Then
SetDependentStates cell
End If
Next
End Sub
Private Sub SetDependentStates(cell As Range)
Dim DependentRange As Range
'Define the Dependent range based on passed cell row.
Set DependentRange = Intersect( _
cell.EntireRow, _
Me.Range(DEPENDENT_COLUMNS) _
)
'Lock/unlock and paint Dependent rows, based on
'contents of passed cell.
Application.EnableEvents = False 'prevent capture of change event.
Me.Unprotect SHEET_PASSWORD
With DependentRange.Cells
If Len(cell.Value) = 0 Then
.ClearContents
.Locked = True
With .Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorDark1
.TintAndShade = -0.249977111117893
.PatternTintAndShade = 0
End With
Else
.Locked = False
With .Interior
.Pattern = xlNone
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End If
End With
Me.Protect SHEET_PASSWORD
Me.EnableSelection = xlUnlockedCells
Application.EnableEvents = True
End Sub
Private Function IsTargetRow(rowNum As Long) As Boolean
Dim v As Variant
'Tests if the pass row number is in the target row list.
For Each v In Split(TARGET_ROWS, ",")
If CLng(v) = rowNum Then
IsTargetRow = True
Exit Function
End If
Next
End Function
Public Sub InitialiseDependentStates()
Dim v As Variant
Dim cell As Range
'Define your unlocked cells.
'This is a simple example, adjust as you wish.
With Me
.Unprotect SHEET_PASSWORD
.Cells.Locked = False
.Protect SHEET_PASSWORD
.EnableSelection = xlUnlockedCells
End With
For Each v In Split(TARGET_ROWS, ",")
Set cell = Me.Range(TARGET_COLUMN & v)
SetDependentStates cell
Next
End Sub
You'll likely want to initialise the dependent states when the workbook is opened. Do this in the code behind the Workbook:
Private Sub Workbook_Open()
Sheet1.InitialiseDependentStates 'use whichever sheet you're using.
End Sub
Trying to write a code that will find red cells and change them to green within a selection. I am a total beginner so this will look barbaric but here it is. I can get it to go down a column and change the colors along the way but what I am really looking to do is have it do that within a selection and when it gets to the bottom of the selected column go back up to the next column within the selection and so on until there is no data available. Here is what I have. Thanks a bunch for any help!
Sub change_colour()
Do While ActiveCell.Value <> ""
Do While Selection.Interior.Color = 255
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 5296274
.TintAndShade = 0
.PatternTintAndShade = 0
End With
ActiveCell.Offset(1, 0).Select
Loop
ActiveCell.Offset(1, 0).Activate
Loop
End Sub
What I would do is set a Range variable to the current selection, and just loop through that range and check the color. If it is red, change it.
You're close, but there's some unnecessary code here (which is to be expected as you're learning).
I think the key is declaring and assigning the Range variable and the use of a For..Each loop.
Public Sub Change_Colour()
Dim rSel As Range, c As Range
Set rSel = Selection
For Each c In rSel
If c.Interior.Color = 255 Then
c.Interior.Color = 5296274
End If
Next c
End Sub
So this code declares two range variables rSel and c. rSel is initiated as the user's selection. I use the For..Each loop with the range variable c to loop through all of the cells in the selection.
The If statement is a stripped-down version of what you have, checking to see if the cell's color is red and changing it to green if so.
I have this code for workbook:
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
'toggles worksheet colors
'code will remove all color
'and color active row and column
If ActiveCell.Interior.ColorIndex <> xlNone Then
Cells.Interior.ColorIndex = xlNone
Else
Cells.Interior.ColorIndex = xlNone
ActiveCell.EntireRow.Interior.ColorIndex = 4
End If
End Sub
and works good. but if a row has an initial color, it will be removed. let me know how
active row will be highlighted and by changing the row, will get its initial color?
Damn, I couldn't find the Add-In but I recreated the code for you. Please note that this is not thoroughly tested. In whatever small tests that I did, it works...
Logic:
Create a hidden sheet.
Store the current cell's formats in row 1 of that hidden sheet
Store the currently selected row number in active sheet to cell A2 of the hidden sheet
when you move to a different row then retrieve the last row number and restore it.
Code:
In thisWorkbook code area
Private Sub Workbook_Open()
Dim ws As Worksheet
'~~> Delete the Temp sheet we created i.e if we created
Application.DisplayAlerts = False
On Error Resume Next
Sheets("MyHiddenSheet").Delete
On Error GoTo 0
Application.DisplayAlerts = True
'~~> ReCreate the Sheet
Set ws = ThisWorkbook.Sheets.Add
'~~> i am using a normal name. Chnage as applicable
ws.Name = "MyHiddenSheet"
'~~> Hide the sheet
ws.Visible = xlSheetVeryHidden
End Sub
In relevant sheet code area. I am using Sheet1 as an example
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
'~~> Don't do anything if multiple cells are selected
If Target.Cells.CountLarge > 1 Then Exit Sub
Dim ws As Worksheet
'~~> Set our relevant sheet
Set ws = ThisWorkbook.Sheets("MyHiddenSheet")
'~~> Get the row number of the last row we had selected earlier
'~~> For obvious reasons, this will be empty for the first use.
If Len(Trim(ws.Cells(2, 1).Value)) <> 0 Then
'~~> If user has moved to another row then
'~~> Restor the old row
If Target.Row <> Val(ws.Cells(2, 1).Value) Then
ws.Rows(1).Copy
Rows(ws.Cells(2, 1).Value).PasteSpecial xlFormats
End If
End If
'~~> Copy the current row's format to the hidden sheet
Rows(Target.Row).Copy
ws.Rows(1).PasteSpecial xlFormats
'~~> Store the current rows value in cell A2
ws.Cells(2, 1).Value = Target.Row
'~~> Highlight the current row in a shade of blue.
'~~> Chnage as applicable
With Rows(Target.Row).Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorAccent5
.TintAndShade = 0.799981688894314
.PatternTintAndShade = 0
Rows(Target.Row).Select
End With
'~~> Remove the `Ants` which appear after you do a copy
Application.CutCopyMode = False
End Sub
Screenshots:
Here's an alternate approach which makes use of the fact that Excel always "overlays" Conditional Formatting on top of whatever formatting is already on the sheet.
Define a worksheet-level name "ROWNUM" and assign a value of 0.
Add a conditional format using the formula =(ROW()=ROWNUM) and add whatever formatting you want to use for row highlighting.
Your SelectionChange sub is then just:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Me.Names("ROWNUM").RefersToR1C1 = "=" & Target.Cells(1).Row
End Sub
I am trying to use conditional formatting (green - yellow - red color scales) on 844 distinct rows to track premium volume over the last six years (years are columns). Here is the tricky part in between each volume column is number of items. I would like to format each row for premium volume and leave the number of items unchanged.
At this point I am selecting each individual premium volume cell by holding ctrl down and then selecting the conditional formatting.
I am trying to automate this so I don't have to continue this process for 844 rows and future spreadsheets as well.
I attached a picture of the worksheet for your reference.
Any help is greatly appreciated!!!
Thanks,
Brad
I got some basic code for the conditional formatting by running the Macro Recorder. I replaced all the occurrences of Selection with a rng variable, and set that rng variable as a parameter to the subroutine so the Sub can be called in a loop:
Sub SetRangeCF(rng As Excel.Range)
rng.FormatConditions.AddColorScale ColorScaleType:=3
rng.FormatConditions(rng.FormatConditions.Count).SetFirstPriority
rng.FormatConditions(1).ColorScaleCriteria(1).Type = _
xlConditionValueLowestValue
With rng.FormatConditions(1).ColorScaleCriteria(1).FormatColor
.Color = 8109667
.TintAndShade = 0
End With
rng.FormatConditions(1).ColorScaleCriteria(2).Type = _
xlConditionValuePercentile
rng.FormatConditions(1).ColorScaleCriteria(2).Value = 50
With rng.FormatConditions(1).ColorScaleCriteria(2).FormatColor
.Color = 8711167
.TintAndShade = 0
End With
rng.FormatConditions(1).ColorScaleCriteria(3).Type = _
xlConditionValueHighestValue
With rng.FormatConditions(1).ColorScaleCriteria(3).FormatColor
.Color = 7039480
.TintAndShade = 0
End With
End Sub
Then you call the sub above in a loop, in this case once for any row that has a value in column A. This assumes that the condtional formatting starts in row 2 and that you have uninterrupted data in column A. If not, you'd have to adjust this looping code:
Sub SetEachRow()
Dim ws As Excel.Worksheet
Dim LastRow As Long
Dim cell As Excel.Range
Set ws = ActiveSheet 'change as necessary
With ws
LastRow = .Range("A" & .Rows.Count).End(xlUp).Row
For Each cell In .Range("A1:A" & LastRow)http://stackoverflow.com/questions/10245638/excel-changes-conditional-formatting-formula?rq=1
cell.EntireRow.FormatConditions.Delete
SetRangeCF cell.EntireRow
Next cell
End With
End Sub
I don't know what the limit of rows is that this will work on, but 1,000 worked fine for me.