Excel code to link range cells' colour into another - excel

I am building a residential stacking plan in which each cell = unit type with specific color given conditional formatting.
2 tables follow below for each unit reflect a sqm size and a $ value.
I need to reflect only the cells' color into the following tables.
I need a dynamic solution and would prefer avoiding vba (since I'm not proficient), but will use if necessary. Thanks in advance!
Find Image HERE

Set up your Conditional formatting as normal on the first table like this:
Note my table starts at cell C4 but yours is in a different place and should be adjusted accordingly. make sure you DON'T have the $ symbol on the formula in the rule but you do have it on the 'Applies to' section
Now copy and paste this formatting onto the second table.
Finally edit the formulas in the conditional formatting so that they point to the starting cell of the FIRST table. It should look like this:
Note that the formatting 'Applies to' the second table but refers in the Formula to the values in the first table.
The result is this:
You can repeat this for other tables if you need to.
As you are working in Excel 2003(!), follow the following steps:
Select the cells in the second table.
In the menu, choose Format - Conditional Formatting.
In the Conditional Formatting box, choose Formula Is.
In the text box, enter the cell reference of the FIRST table (eg C4="4+"), do not enter any $ symbols.
Click the Format button and select the background fill to match the one in the first table.
Add the other conditions in the same way by clicking the Add>> button.

If you change the color code values (B21:B26) from 2 rooms to 2 (to match your second table), the following should do the trick. Basically, this code is not using conditional formating. Getting the color from conditional formating can be somewhat laborious and tricky (google "excel vba find color conditional formatting"). Instead, the present code reads the color in your Color Code cells, and apply it to the other two ranges.
Private Sub BckgndColor()
Dim ColorCodeRange As Range
Dim NoOfRooms As Range
Dim CellColorIndex As Integer
Dim c As Range
Dim d As Object
Set ColorCodeRange = Worksheets("Sheet1").Range("B21:B26")
Set d = CreateObject("scripting.dictionary")
'Add the pairs (value, color) to dictionary
For Each c In ColorCodeRange.Cells
d.Add c.Value, c.Interior.ColorIndex
Next
Set NoOfRooms = Worksheets("Sheet1").Range("M25:V36") 'Here the range of Table 2 (M25:V36 in your example)
'Scan range, and assign color
For Each c In NoOfRooms.Cells
If d.Exists(c.Value) Then
c.Interior.ColorIndex = d(c.Value)
c.Offset(16, 0).Interior.ColorIndex = d(c.Value) 'If Table 3 is always 16 rows down, this shoud work
End If
Next
Set d = Nothing
End Sub

I gave the option data validation list in sheet 2, while I selecting the option by list the cells will change . for that cells I want to get color also from source table in sheet1 to sheet2 .

Related

VBA Count values based on font color

I need to add values of a range when its contents are of a certain font color (e.g., black). What I have is a a table where I am conditionally formatting the color of values. For e.g., if the "Status =Carry Over" then I am coloring the row Red. (see attachment).
Now, after the conditional formatting, I want to sum all the number values under a specific column that are NOT in red color.
I have a piece of vba code to add such values, but the problem is, the conditional coloring is throwing the code off. As long as I am manually coloring the rows, the code is ignoring the red rows. If I use the conditional coloring option, then even the colored rows are taken into account.
I am calling the below UDF using this formula =ConditionalColorSum(C2:C30)
Public Function ConditionalColorSum(rnge As Range) As Double
' Total only cells with red font numbers
Application.Volatile
Dim Total As Double, cl As Range
Total = 0
For Each cl In rnge.Cells
If cl.Font.Color = vbRed Then 'Change 'vbRed' to the color you want
Total = Total + cl.Value
End If
Next
ConditionalColorSum = Total
End Function
The Conditional formatting formula looks like above:
As per THIS
Actions such as changing the conditional formatting or table style of a range can cause what is displayed in the current user interface to be inconsistent with the values in the corresponding properties of the Range object. Use the properties of the DisplayFormat object to return the values as they are displayed in the current user interface.
The only way to get the color due to conditional formatting is to use DisplayFormat
If cl.DisplayFormat.Font.Color = vbRed Then
But per THIS
Note that the DisplayFormat property does not work in user-defined functions.
So one cannot use UDF to count the colors directly from the sheet. One can use a SUB but it would be easier just to use the same criteria that the custom format uses to count:
=COUNTIF(E2:E30,"Carry Over")
or to count where it is not red:
=COUNTIF(E2:E30,"<>Carry Over")

Excel VBA - How to automate check and select duplicates in multiple lists in multiple sheets in one workbook?

How to automate check for duplicates in multiple lists in multiple sheets in the same workbook?
I've managed to make it work semi-automatically by having a macro for each comparison that I need. That means a macro for finding duplicate values between:
Worksheets("All").Range("Annie") and Worksheets("Annie").Range("A:A")
Worksheets("All").Range("Benny") and Worksheets("Benny").Range("A:A")
etc.
etc..
Here is a screenshot that shows where I'm at, and hopefully visualizes what I am trying to do
(Annie's been to Sweden and Kenya - therefore those countries are marked red by the macro)
(Benny's been to Russia and Spain)
(And so forth)
It would be much more efficient to make just ONE code, that does this for all columns that has values in Worksheets("All"). I need to be able to have at least 50 columns with names (Annie, Benny, Charlie, Danny, Emma, Fabian, etc., etc..)
Is this possible?
Here is my code, so far (for "Benny"):
Sub findDuplicatesBenny()
Dim rng1, rng2, cell1, cell2 As Range
Set rng1 = Worksheets("All").Range("Benny")
Set rng2 = Worksheets("Benny").Range("A:A")
For Each cell1 In rng1
If IsEmpty(cell1.Value) Then Exit For
For Each cell2 In rng2
If IsEmpty(cell2.Value) Then Exit For
If cell1.Value = cell2.Value Then
cell1.Interior.ColorIndex = 22
cell1.Interior.Pattern = xlSolid
End If
Next cell2
Next cell1
End Sub
Any help will be much appreciated!
To do this with conditional formatting, you can use INDIRECT and the name (Annie, Benny, etc.) in row 1 to create a reference to each name's respective sheet. Then with COUNTIF you can count duplicates.
Under Conditional Formatting, click Use a formula to determine which cells to format.
Enter the following formula: =COUNTIF(INDIRECT("'"&A$1&"'!A:A"),A1)
Click Format to apply the coloring you want.
In the Rules Manager window, change the "Applies to" range reference as needed.
EDIT:
Just to explain more thoroughly... Two main parts to this formula:
COUNTIF: used to count the number of cells that match a criterion. Ignoring the INDIRECT for the moment, and using the example of cell A2, the formula above is equivalent to =COUNTIF(Annie!A:A,A2), which looks at column A on the Annie sheet and counts all instances of Sweden. That would return 1.
And if you were to drag that formula down, in A3 it would return 1 for Kenya, in A4, 0 for USA and so on.
In another column, you could create a similar COUNTIF referencing Benny, with similar results - 0 for Sweden, all the way down to 1 for Russia and Spain.
INDIRECT: returns the reference specified by a text string. The above formula uses INDIRECT to make the sheet and range reference (Annie!A:A, Benny!A:A and so on) dynamic.
First to explain the text string: "'"&A$1&"'!A:A". That results in 'Annie'!A:A and 'Benny'!A:A and so on:
Used inside INDIRECT these text references become range references. By wrapping the INDIRECT in a COUNTIF, the formula effectively is equivalent to the =COUNTIF(Annie!A:A,A2) above - we've just made the Annie!A:A dynamic. Note that I include a single quote ' before and after - 'Annie'!A:A. This is needed if a sheet name has a space in it, e.g. if the name is Annie Marie.
As for the conditional formatting - formatting is applied if the formula input evaluates to TRUE. I'm using a slight trick that a 0 in conditional formatting is equivalent to FALSE and 1 or more is TRUE. So the formatting will be applied to any cell where the COUNTIF returns a 1 or more. That's how duplicates are flagged/filled.

Excel 2013 color fill when number changes in a column

I'm working on data-analysis where i would like to be able to automatize color fill when looking through large amount of data where there are abundant amount of ghost logs and taking too much of my time as they are severely irrelevant.
So what i would like to do in Excel, is to be able to color fill a cell when the number changes in a column marking a different set of logs.
For instance if there are six rows of log number 456455, i would like the code to color fill the first cell when the number changes to 456456 so that it helps me identify logs faster when i know where the sets are starting. I'm kind of a newbie when it comes to Excel but this loop would help me a lot!
Thx for your time
This can be done with conditional formatting. Use a rule that compares the current cell with the cell in the row above and format if the two are different. Note that you will need to use relative references without $ signs. In the screenshot below, the conditional format is applied from row 2 to 19 and in row 2 the formula compares A2 with A1, in the next row it compares A3 with A2, and so on. If the two cells are different, the cell will change colour.
If you have some knowledge in VBA, you can implement a macro that looks at the column where you have your log number and if the value changes from one cell to another, then you highlight this cell.
I attached a template of code that works for this task.
Sub highlightChange()
Dim preVal As Integer
preVal = 0
For Each o In Range("A:A")
'Go through column
If o.Value <> preVal Then
o.Interior.Color = vbRed 'Color the selection
End If
preVal = o.Value
Next o
End Sub
There may be other solution without VBA, however, it is quite easy and practical to use a macro.

Storing/loading conditional format info in VBA

is there a way I can store and later restore conditional formatting information? Upon selecting a cell, I want to
1/ store the condformatting of the corresponding column/row in some arrays
2/ delete the condformatting of the corresponding column/row
3/ change InteriorColor of column/row to something nice (so that I see a crosshair)
4/ upon selecting another cell, I want to restore the condformatting of the original column/row and repeat the process from 1/ for the currently selected cell.
I tried something like
Public condFmt1 As FormatCondition
Set condFmt1 = Range("A1").FormatConditions.Item(1)
...
Set Range("A2").FormatConditions.Item(1) = condFmt1
however the last line gives me a runTime error 438 - Object does support this property or method. Im probably assigning wrongly.
After playing around with it for an hour, I've found a way around using FormatCondition values in VBA.
This code copies my "A1" range's conditional formatting, which is set to change the font to bold if the value is TRUE
Sub CopyFormatCondition()
Dim fC As FormatCondition
Set fC = Range("A1").FormatConditions.Item(1)
Range("A2").FormatConditions.Add Type:=xlCellValue, Operator:=fC.Operator, Formula1:=fC.Formula1
Range("A2").FormatConditions.Item(1).Font.Bold = fC.Font.Bold
End Sub
Some properties such as Type, Operator and Formula1 have to be set when the FormatCondition is being initialised, hence why I had to add a FormatCondition to the range's FormatConditions collection.
Other properties (e.g. Font and Interior) can be set after the FormatCondition's Initialization.
Assuming you're using Excel 2007 or higher, you can achieve your goal also with a Non-VBA solution:
Use an empty cell in your worksheet/workbook as a trigger cell and set it to TRUE. For convenience, name this cell DisableConditionalFormatting or similar.
Select the active area of the worksheet (Ctrl-A) and insert a new rule -> use formula to determine which cells to format. As a formula set =DisableConditionalFormatting. No need to alter the format here.
After setting the new rule, make sure to select the checkbox Stop if true in the conditional formatting rule manager
No you can toggle the conditional formatting for the worksheet on and off by changing the cell DisableConditionalFormatting.

Excel charts - setting series end dynamically

I've got a spreadsheet with plenty of graphs in it and one sheet with loads of data feeding those graphs.
I've plotted the data on each graph using
=Sheet1!$C5:$C$3000
This basically just plots the values in C5 to C3000 on a graph.
Regularly though I just want to look at a subset of the data i.e. I might just want to look at the first 1000 rows for example. Currently to do this I have to modify the formula in each of my graphs which takes time.
Would you know a way to simplify this? Ideally if I could just have a cell on single sheet that it reads in the row number from and plots all the graphs from C5 to C 'row number' would be best.
Any help would be much appreciated.
OK, I had to do a little more research, here's how to make it work,
completely within the spreadsheet (without VBA):
Using A1 as the end of your desired range,
and the chart being on the same sheet as the data:
Name the first cell of the data (C5) as a named range, say TESTRANGE.
Created a named range MYDATA as the following formula:
=OFFSET(TESTRANGE, 0, 0, Sheet1!$A$1, 1)
Now, go to the SERIES tab of the chart SOURCE DATA dialog,
and change your VALUES statement to:
=Sheet1!MYDATA
Now everytime you change the A1 cell value, it'll change the chart.
Thanks to Robert Mearns for catching the flaws in my previous answer.
This can be achieved in two steps:
Create a dynamic named range
Add some VBA code to update the charts data source to the named range
Create a dynamic named Range
Enter the number of rows in your data range into a cell on your data sheet.
Create a named range on your data sheet (Insert - Name - Define) called MyRange that has a formula similar this:
=OFFSET(Sheet1!$A$1,0,0,Sheet1!$D$1,3)
Update the formula to match your layout
Sheet1!$A$1 set this to the top left hand side of your data range
Sheet1!$D$1 set this to the cell containing the number of rows
3 set this value to the number of columns
Test that the named range is working:
Select the dropdown menus Edit - Go To, type MyRange into the reference field.
Your data area for the chart should be selected.
Add some VBA code
Open the VBA IDE (Alt-F11)
Select Sheet1 in the VBAProject window and insert this code
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address <> "$D$1" Then Exit Sub
'Change $D$1 to the cell where you have entered the number of rows
'When the sheet changes, code checks to see if the cell $D$1 has changed
ThisWorkbook.Sheets("Sheet1").ChartObjects(1).Chart.SetSourceData _
Source:=ThisWorkbook.Sheets("Sheet1").Range("MyRange")
' ThisWorkbook.Sheets("Chart1").SetSourceData _
Source:=ThisWorkbook.Sheets("Sheet1").Range("MyRange")
'The first line of code assumes that chart is embedded into Sheet1
'The second line assumes that the chart is in its own chart sheet
'Uncomment and change as required
'Add more code here to update all the other charts
End Sub
Things to watch for
Do not directly use the named range as the data source for the chart. If you enter the named range "MyRange" as the Source Data - Data Range for the chart, Excel will automatically convert the named range into an actual range. Any future changes to your named range will therefore not update your chart.
Performance might be impacted by the approaches listed above.
The OFFSET function in the named range is "volatile" which means that it recalculates whenever any cell in the workbook calculates. If performance is an issue, replace it with the INDEX formula.
=Sheet1!$A$1:INDEX(Sheet1!$1:$65536,Sheet1!$D$1,2)
The code fires everytime data is changed on Sheet1. If performance is an issue, change the code to run only when requested (i.e. via a button or menu).
You could look at dynamic ranges. If you use the OFFSET function, you can specify a starting cell and the number of rows and columns to select. This site has some useful information about assigning a name to an OFFSET range.
You can set the range for a chart dynamically in Excel. You can use something like the following VBA code to do it:
Private Sub Worksheet_Change(ByVal Target as Range)
Select Case Target
Case Cells(14, 2)
Sheet1.ChartObjects(1).Chart.SetSourceData Range("$C5:$C$" & Cells(14,2))
...
End Select
End Sub
In this case, the cell containing the number of the last row to include is B14 (remember row first when referring to the Cells object). You could also use a variable instead of the Cells reference if you wanted to do this entirely in code. (This works in both 2007 and 2003.) You can assign this procedure to a button and click it to refresh your chart once you update the cell containing the last row.
However, this may not be precisely what you want to do ... I am not aware of a way to use a formula directly within a chart to specify source data.
Edit: And as PConroy points out in a comment, you could put this code in the Change event for that worksheet, so that neither a button nor a key combination is necessary to run the code. You can also add code so that it updates each chart only when the matching cell is edited.
I've updated the example above to reflect this.
+1s for the name solution.
Note that names don't really really reference ranges, they reference formulae. That's why you can set a name to something like "=OFFSET(...)" or "=COUNT(...)". You can create named constants, just make the name reference something like "=42".
Named formulae and array formulae are the two worksheet techniques that I find myself applying to not-quite-power-user worksheets over and over again.
An easy way to do this is to just hide the rows/columns you don't want included - when you go to the graph it automatically excludes the hidden rows/columns
Enhancing the answer of #Robert Mearns, here's how to use dynamic cells ranges for graphs using only the Excel's formulas (no VBA required):
Create a dynamic named Range
Say you have 3 columns like:
A5 | Time | Data1 | Data2 |
A6 | 00:00 | 123123 | 234234 |
...
A3000 | 16:54 | 678678 | 987987 |
Now, the range of your data may change according to the data you may have, like you have 20 rows of data, 3000 rows of data or even 25000 rows of data. You want to have a graph that will be updated automatically without the need to re-set the range of your data every time you update the data itself.
Here's how to do it simply:
Define another cell that it's value will have the number of the occupied cells with data, and put the formula =COUNTIF(A:A,"<>"&"") in it. For example, this will be in cell D1.
Go to "Formulas" tab -> "Define Name" to define a name range.
In the "New Name" window:
i. Give your data range a name, like DataRange for example.
ii. In the "Refers to" set the formula to: =OFFSET(Sheet1!$A$1, 0, 0,Sheet1!$D$1,3),
where:
Sheet1!$A$1 => Reference: is the Reference from which you want to base the offset.
0 => Rows: is the number of rows, up or down, that you want the upper-left cell of the results to refer to.
0 => Columns: is the number of columns, to the left or right, that you want the upper-left cell of the results to refer to.
Sheet1!$D$1 => Height: is the height, in number of rows, that you want the result to be.
3 => Width: is the width, in number of columns, that you want the result to be.
Add a Graph, and in the "Select Data Source" window, in the Chart data range, insert the formula as you created. For the example: =Sheet1!DataRange
The Cons: If you directly use the named range as the data source for the chart, Excel will automatically convert the named range into an actual range. Any future changes to your named range will therefore not update your chart.
For that you need to edit the chart and re-set the range to =Sheet1!DataRange every time. This may not be so usable, but it's better than editing the range manually...

Resources