get cell fill color using openpyxl - openpyxl

I would like to get the background fill value for a particular cell in a sheet using openpyxl. I thought that the selected answer from this post openpyxl : Is there a way to search an Excel spreadsheet for cells with specific fill color? would help me, but it isn't working properly.
Here is my current code:
wb1 = Workbook()
ws1 = wb1.create_sheet('new sheet', 0)
ws1.cell(1,1).value = 0.5 # cell A1
rule = ColorScaleRule(start_type='num', start_value=0, start_color='FFFFFF',
end_type='num', end_value=1, end_color='FF007F')
ws1.add(range_string='A1', cfRule=rule)
print('rgb_fg: ', ws1.cell(1,1).fill.fgColor.rgb)
print('rgb_bg: ', ws1.cell(1,1).fill.bgColor.rgb)
output:
rgb_fg: 00000000
rgb_bg: 00000000
Since I assigned 0.5 as the value of cell "A1" in ws1, then I would have no reason to think that the rgb of this cell would be 00000000 (black). It should be a light salmon red color, which is what I get if the sheet is saved and I view it.
Note I printed fgColor and bgColor just to cover all my bases (or the ones I can think of)
Perhaps something funky happens when a ColorScaleRule is applied to a cell so its fill value can't be read in the way I expect?

Conditional formatting is not handled the same way as static colors. Background colors from those conditional rules are dynamic and therefore left to only be applied by spreadsheet software, not the library itself. Therefore, you will not be able to determine this value with openpyxl.
The good news is that if you were to save the spreadsheet, you would see that your code is correct and the cell does appear pink.

Related

How to iterate over an Excel file and ID colored cell values

I have an excel workbook that has cells of a column colored with specific colors to keep or exclude certain users that will then be used to filter another excel workbook.
I want to loop through this column and identify cells with red background and add a functional column stating 0 and identify cells with yellow background and add 1 to this same functional column so as to work as the filter for the other workbook.
I'm hoping to use OpenPyXL to complete this task.
column_pi = ws["A"]
for cell in column_pi:
f cell.fill.fgColor == "00FF0000": # Red Hex
# add column stating 0 as value
Have also tried this but no luck, returning nothing
red_fill = PatternFill(fill_type=None, start_color='00FF0000', end_color='00FF0000')
yellow_fill = PatternFill(fill_type=None, start_color='00FFFF00', end_color='00FFFF00')
for cell in column_pi:
if cell.fill == yellow_fill:
print(cell)
Works with no hex codes provided for no_fill
no_fill = PatternFill(fill_type=None)
for cell in column_pi:
if cell.fill == no_fill:
print(cell)
Any thoughts on the best way to iterate over the values and check the fill/background color are of a specific color and then add a functional column like this?
fill is a set of more complicated variables, so looking for it to be exactly equal only to red_fill or yellow_fill here isn't going to work. The complication is mostly due to being able to set a colour either as a static rgba value, or as one that will automatically update when the theme is changed. Styles in openpyxl, with parameters like PatternFill, are easy ways to set multiple of these values at once.
If you look up cell.fill for a particular cell, it returns something like:
<openpyxl.styles.fills.PatternFill object>
Parameters:
patternType='solid', fgColor=<openpyxl.styles.colors.Color object>
Parameters:
rgb='FFD9D9D9', indexed=None, auto=None, theme=None, tint=0.0, type='rgb', bgColor=<openpyxl.styles.colors.Color object>
Parameters:
rgb='00000000', indexed=None, auto=None, theme=None, tint=0.0, type='rgb'
You can specify these values directly as part of cell.fill.fill_type (synonym for cell.fill.patternType), cell.fill.fgColor, and cell.fill.bgColor. Plus sub-attributes like cell.fill.fgColor.rgb.
You could also make it quicker by picking knowncell.fill.fgColor of a cell you know to have red_fill, if one exists. That way, you could check any of fill_type, fgColor and/or bgColor match. Try:
red_fill = knowncell.fill
for cell in column_pi:
if cell.fill.fgColor == red_fill.fgColor and cell.fill.fill_type == red_fill.fill_type:
print(cell)
However, you can't match knowncell.fill directly with cell.fill, I think because a new openpyxl style object is created each time you define a new one.

Copying an Object Across a Workbook

I have a workbook which displays a little coloured box based on some input metrics from another worksheet within the workbook. I want to display these little coloured boxes in an additional worksheet in the workbook. Is there a way to copy a shape across worksheets so that the colour will still update with the metrics rather than using the code again for a separate worksheet?
I essentially want to display this textbox with the coloured boxes/arrows in another worksheet as well.
A pretty dirty way to do something like this would be the Indirect-Picture-Copy-Solution.
Asume the art is at Sheet1 B2:D8 then just input a picture in Sheet2 (the picture doesn't matter, just pick the first you can find)
While the Picture is selected input in the formula bar =Sheet1!B2:D8.
Hope that helps ;)
EDIT
For making it dynamically put in any module:
Public Function testing() As Range
Set testing = Range(Sheet1.Shapes("Dia 1").TopLeftCell, Sheet1.Shapes("Dia 1").BottomRightCell)
End Function
(Make sure to change the names to fit your workbook/sheet/shapes....-names)
Then define a name (I'll pick TETE for this example)
Refers to: =testing()
Then the picture-formula is: =TETE
Whenever the size or position changes, your picture fits to it... still not a good way to solve your problem (to my eye)
Funny fact: making the picture-formula directly to =testing() will just pop an error

Assign cell background color to rgb from referenced cells

I'm working in excel on programatically setting a cell's background color to be a specific RGB color that is referenced in nearby cells. Here's what I'm trying to do:
You can see that I manually set the background color to be the RGB values specified in the cells in the same row on the left, as highlighted in the picture. The first purple cell has RGB (148,91,128).
I want to do this in VBA or maybe even conditional formatting if possible. So far I have tried this simple vba line of code to see if it would work:
Range("F1").Interior.Color = RGB(C1, D1, E1)
However this line of code sets the cell to have a black background like this:
If the code had worked correctly, this cell should have been a nearly white color, not black. Any ideas on why this isn't working? Am I making a mistake is the way I reference the cells for RGB?
It would be nice to be able to assign the range "F1:F__" to reference the cells to the left on each row too, not just one cell. Thanks!
Try this:
Range("F1").Interior.Color = RGB(Range("C1"), Range("D1"), Range("E1"))
In your version of code C1, D1, E1 are taken as variables and they have default value 0, so macro assign color equal to RGB(0, 0, 0) which is black.

How can I color code a graph in Excel using VBA, using the RGB mix?

I would like to use VBA to modify the color in a graph/chart in Excel based on values in 3 cells (correlated to RGB).
For example, cells A1 (Red), A2 (Green), and A3 (Blue) would each have a value that would correspond to a certain color. Based upon those values, the bar graph color would change to whatever the RGB color indicated. 115-20-110 would give me a pink bar color.
I currently have
ActiveChart.SeriesCollection.Interior.Color = RGB(A1, A2, A3)
But I don't really know VBA and it isn't working. Any help is appreciated, and if there is a less obtuse way I would be interested of course.
Thank you
Try:
ActiveChart.SeriesCollection(1).Interior.Color = RGB(Range("A1").Value, _
Range("A2").Value, _
Range("A3").Value)
SeriesCollection represents all of the series on the chart - you need to pick one to color...

Aspose.Cells - Set Border For Range

I'm currently working with Aspose.Cells. I've largely managed to do what I need to do however one issue remains; I can't see an easy way to apply a border to a defined range. I can for a cell, however when applying the style to the range all cells in the range are formatted.
The only way I can see around this is to write a method to enumerate all cells within the range to determine the right border attributes. This seems a slightly hideous way to achieve what I see as a simple task, so am hoping there is a better way!
Is there?
Ok let's start.
Assuming we want to add borders to a range from A2 cell to H6 cell range.
Always remember that cell index in Aspose is Zero based.
So the A2 cell has index of row 1 and column 0.
Define the range
Dim range = current_worksheet.Cells.CreateRange(1, 0, 5, 8)
Set the borders
range.SetOutlineBorder(Aspose.Cells.BorderType.TopBorder,Aspose.Cells.CellBorderType.Thick,Drawing.Color.Blue)
range.SetOutlineBorder(Aspose.Cells.BorderType.BottomBorder,Aspose.Cells.CellBorderType.Thick, Drawing.Color.Blue)
range.SetOutlineBorder(Aspose.Cells.BorderType.LeftBorder,Aspose.Cells.CellBorderType.Thick, Drawing.Color.Blue)
range.SetOutlineBorder(Aspose.Cells.BorderType.RightBorder,Aspose.Cells.CellBorderType.Thick, Drawing.Color.Blue)
That's it!