openpyxl appending rows with style - openpyxl

I am appending rows to openpyxl and I want to do that with different styles
for i, row in enumerate(mydata):
ws.append(row)
if (my_logic_is_true):
ws.row_dimensions[(i+1)].fill = redFill
ws.row_dimensions[(i+1)].font = Font(bold=True)
else:
ws.row_dimensions[(i+1)].fill = greenFill
Problem: Instead of applying the style on the whole row, it applies the style (fill and bold) to all the cells of the row after the last written cell for the row.
Say for example, for each row, I am writing three cells, then the style would be applied to 4th cell onwards.

This is covered in the documentation: row and column styles are hints to apply the formats for future cells. If you want to style a whole or column then you will have to apply the styles to all relevant cells yourself.

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.

VLookup table array from another sheet

Ive a sheet in which a cell value to be dynamically changed based on the cell value in the same row. So we have to pick that cell value first and then use that value to search in another sheet. Here is the code I have got. The sheet I have to search is Mapper
ActiveSheet.Range("P2").Select
formularwcount = ActiveSheet.UsedRange.Rows.Count
ActiveCell.FormulaR1C1 = "=VLOOKUP(RC[-11], Mapper!C[-13]:C[2],3,FALSE)"
In this code they are using R1C1 convention which I didnt understand what they mean by putting Mapper!C[-13]:C[2] there as the table array. Im only a 10 days old developer with VBA. Anyone please tell what does that mean.
I found this information by Googling "R1C1":
Cell References
In place of a named cell, an alternative approach is to use a cell (or grid) reference. Most cell references indicate another cell in the same spreadsheet, but a cell reference can also refer to a cell in a different sheet within the same spreadsheet, or (depending on the implementation) to a cell in another spreadsheet entirely, or to a value from a remote application.
A typical cell reference in "A1" style consists of one or two case-insensitive letters to identify the column (if there are up to 256 columns: A–Z and AA–IV) followed by a row number (e.g., in the range 1–65536). Either part can be relative (it changes when the formula it is in is moved or copied), or absolute (indicated with $ in front of the part concerned of the cell reference).
The alternative "R1C1" reference style consists of the letter R, the row number, the letter C, and the column number; relative row or column numbers are indicated by enclosing the number in square brackets. Most current spreadsheets use the A1 style, some providing the R1C1 style as a compatibility option.
Source: Wikipedia: Spreadsheets

Count number of times data is repeated in a column and show number in another column?

I have a UserForm that finds and copies a range of data and pastes it along with new data from the UserForm into a different sheet. I am wanting for it to also count the number of times some of that data is repeated in the new sheet. I have tried several different approches but none are working. Right now this is what I have:
.Range("I1").Value = iVal = Application.WorksheetFunction.CountIf(Range("A3:A103"), "CrisisNameTextBox1.Value")
This puts "TRUE" in the corresponding cell instead of the number of times the data is repeated.
You probably could use this function in the corresponding cell:
=COUNTIF( [range], [cell] )
The [range] is the range you want to check (use $ to make sure its value does not change from one cell to another)
The [cell] is the cell you are currently checking.
Assign the function to the cells you want and it should work
If you want to drag/copy this formula from one cell to an other : use the $ character to lock the coordinates you don't want to be changed. I.e :
$A1 Will prevent the column from being changed, but will allow the row
A$1 Will prevent the row from being changed, but will allow the column
$A$1 Will prevent both coordinates from being changed
The same applies to ranges ($A1:$F15, $A1:F1, $A$1:F15, A1:$F15, etc.)

Excel - Highlight Rows based on look up value from another sheet

Hi I have an excel sheet, that has a column called as Company name
in another sheet there is there are couple of look ups.. i need to look up those and highlight them in different colors based on the look up list.
for example, in the above scenario, i need Company A Highligted in oone color and company C in another.
If highlighting is challgeng, i dont mind even having a seperate coloumn next to it that says, if it is a partner or competitor.
i tried the below formula under conditional formatting .. but doesnt work for different colours... it colors everything the same
=NOT(ISNA(VLOOKUP(B1,'Lookup List'!$A$2:$D$200,1,FALSE)))
Please try selecting Company Name column and HOME > Styles - Conditional Formatting, New Rule..., Use a formula to determine which cells to format and Format values where this formula is true::
=COUNTIF('Lookup List'!$A:$A,B1)
Format..., select colour Fill (highlight) of your choice, OK, OK.
Then repeat with:
=COUNTIF('Lookup List'!$B:$B,B1)
with a different fill.
If every entry is one colour or the other then one CF rule is sufficient, with the other colour applied as standard fill.

Format One Cell with ColorScale Based on Range of Cell Values

I need to format a single cell with a gradient color based on the values of a range of cells. Similar to the conditional formatting with a ColorScale, except only applying the formatting to a single cell based on the values of a range of cells.
Most likely this will need to be done in VBA. I can't seem to find a simple way to do this without rewriting a similar script to the built-in ColorScale methods.
Example:
B10 formatted with a color in a scale based upon the values of B10:B40. ColorScale would be type 3 with Low, Mid (50%), and High. But I don't want to format any cells other than B10, just use the values of the range B10:B40
I will then do the same for B11:B41, but only formatting B11, then B12:B42, B13:B43, etc..
All I need is to figure out how to create a ColorScale based on a range of values but only apply the formatting to one of the cells.
Edit:
If someone knows a way to create a color scale script similar to the conditional formatting one built into Excel, that would also be a good fix. If I can just calculate the scale from the values in the range of cells and apply to the one cell with the color grade, that would be a solution.
I think what you are after is a 3-color scale for B10 to B40 (so that B10 acquires a colour based on that cell's ranking in the range) together with a separate rule that applies white formatting (in appearance, no formatting) to B11:B40. The latter rule should be at the top of the list of rules and Stop if True checked.