Python openpyxl conditional format containsText - python

I all.
I have this code.
I need to add conditional format at the cells, the code working with numbers, but not with texts.
With texts or haven't effect or generate errors on file open
import pandas as pd
from openpyxl import formatting, styles
from openpyxl.formatting.rule import ColorScaleRule, CellIsRule, FormulaRule, Rule
from openpyxl.styles.differential import DifferentialStyle
df = pd.DataFrame({"Name": ['A', 'B', 'C', 'D', 'E'],
"Status": ['SUCCESS', 'FAIL', 'SUCCESS', 'FAIL', 'FAIL'],
"Value": [10, 15, 20, 25, 30]})
writer = pd.ExcelWriter('C:\\Users\\emarmis\\OneDrive - Ericsson AB\\WORK\\DEV\\PYTHON\\Ferie\\test.xlsx', engine='openpyxl')
df.to_excel(writer, 'TEST', startrow=1, startcol=1)
wb = writer.book
ws = writer.sheets['TEST']
red_color = 'ff0000'
yellow_color = 'ffff00'
red_fill = styles.PatternFill(start_color=red_color, end_color=red_color, fill_type='solid')
yellow_fill = styles.PatternFill(start_color=yellow_color, end_color=yellow_color, fill_type='solid')
# This not working
rule = Rule(type='containsText', operator='containsText', text='"FAIL"')
#rule = Rule(type='containsText', operator='containsText', text='FAIL') # same problem with or without double quote on text
rule.dfx = DifferentialStyle(fill=red_fill)
ws.conditional_formatting.add('D3:D7', rule)
# This generate error at the file open
#ws.conditional_formatting.add('D3:D7', formatting.rule.CellIsRule(operator='containsText', formula=['FAIL'], fill=red_fill))
ws.conditional_formatting.add('E3:E7', formatting.rule.CellIsRule(operator='lessThan', formula=['20'], fill=red_fill))
ws.conditional_formatting.add('E3:E7', formatting.rule.CellIsRule(operator='greaterThan', formula=['25'], fill=yellow_fill))
wb.close()
writer.save()
This is the result of the code above
Any suggestions?
Regards,
Marco

Dont know if this helps but it worked for me. Thou i cant get additional conditions to work.
String 'c-tur' gets red text with a another red fill:
red_text = Font(color="9C0006")
red_fill = PatternFill(bgColor="FFC7CE")
dxf_c = DifferentialStyle(font=red_text, fill=red_fill)
rule_c = Rule(type="containsText", operator="containsText", text="c-tur", dxf=dxf_c)
rule_c.formula = ['NOT(ISERROR(SEARCH("c-tur",B2)))']
ws.conditional_formatting.add('B2:'+column_name+str(antal_kolumn), rule_c)

Related

Exporting a pandas dataframe to excel using xlwings

import xlwings as xw
import pandas as pd
I'm trying to export a df into a specific sheet on excel I'm getting the following error:
self._oleobj_.Invoke(*(args + (value,) + defArgs))
TypeError: Objects for SAFEARRAYS must be sequences (of sequences), or a buffer object.
This is a simplified version of my DataFrame
df=pd.DataFrame(
{
'Color': ['red','blue','red','red','green','red','yellow'],
'Type': ['Oil', 'Aluminium', 'Oil', 'Oil', 'Cement Paint', 'Synthetic Rubber', 'Emulsion'],
'Finish' : ['Satin', 'Matte', 'Matte', 'Satin', 'Semi-gloss', 'Satin', 'Satin'],
'Use' : ['Interior', 'Exterior', 'Interior', 'Interior', 'Exterior', 'Exterior', 'Exterior'],
'Price' : [55, 75, 60, 60, 55, 75, 50]
}
)
Here's my code:
df = df.loc[(df['Price'] == 55) & (df['Color'] == 'red')]
df1 = df.loc[(df['Price'] == 55) & (df['Color'] == 'blue')]
df2 = df.loc[(df['Price'] == 55) & (df['Color'] == 'yellow') & (df['Color'] == 'green')]
# Load Wookbook
app = xw.App(visible = False)
wb = xw.Book(File_path)
Sheet1 = wb.sheets['Sheet1']
Sheet2 = wb.sheets['Sheet2']
Sheet3 = wb.sheets['Sheet3']
#Write data into Workbook
Sheet1.range('A1').options(index=False, header=False ).value = df
Sheet2.range('A1').options(index=False, header=False ).value = df2
Sheet3.range('A1').options(index=False, header=False ).value = df2
#Save data in Workbook and close wb
LPLwb.save()
LPLwb.close()
LPLapp.quit()
The end goal is to be able to export the different dfs into the specific sheets. I've done this before with no issue, but now I'm getting an odd error I had never gotten before. Googled it for a while but found nothing.
Any direction would be highly appreciated! Thanks

Coloring Columns with Pandas

I am trying to color columns in group_1, but I am getting this issue, any solution?
group_1 = [award, 'mean', 'max']
def change_color(workbook_param, color_hex_code):
"""Returns color format for excelsheet."""
header_format = workbook_param.add_format({
'bold': True,
'text_wrap': True,
'valign': 'top',
'fg_color': color_hex_code,
'border': 1})
return header_format
group_1_data = describe_df[columns= group_1].copy()
group_1_ind = [describe_df.columns.to_list().index(patient) for patient in group_1]
group_1_ind # [0, 3, 4]
group_1_data = describe_df[columns= group_1].copy()
^
SyntaxError: invalid syntax
the group_1_data gets inputted into here below
# Combining dataFrames in excel
excelName = input("Label your excel file: ")
xlsxAUTO = '.xlsx'
excelAutoNamed = excelName + xlsxAUTO
# Create a Pandas Excel writer.
writer = pd.ExcelWriter(excelAutoNamed,engine='xlsxwriter')
# Convert the dataframe to an XlsxWriter Excel object.
describe_df.to_excel(writer,sheet_name='Validation',startrow=0 , startcol=0)
df.to_excel(writer,sheet_name='Validation',startrow=len(df.columns), startcol=0)
# Get the xlsxwriter workbook and worksheet objects. You can change sheet name as well.
workbook = writer.book
worksheet = writer.sheets['Validation']
# Do the modifications for desired columns.
for col_num, value in zip(group_1_ind, group_1_data.columns.values):
worksheet.write(0, col_num + 1, value, change_color(workbook, '#e3fc03'))
writer.save()
I have also tried group_1_data = describe_df[group_1].copy()

openpyxl conditional formatting - Rule is in Excel file but not the formatting

My goal is to create an Excel file and change the background color of some cells based on their value using conditional formatting, using openpyxl.
When I open the file created with Excel, I can see that the rule is there, but the rule does not include the formatting to apply (background color set to none). The cells have thus no background color, although the border of the cells respecting the formula are not visible, like when the background is white.
I don't see if I made a mistake, or if there is some trouble with openpyxl.
Here is a MWE:
from openpyxl import Workbook
from openpyxl.styles import PatternFill
from openpyxl.formatting.rule import CellIsRule
wb = Workbook()
ws = wb.active
ws['B2'] = -2
ws['B3'] = -1
ws['B4'] = 0
ws['C2'] = -1
ws['C3'] = 0
ws['C4'] = 1
fill = PatternFill(start_color='538DD5', fill_type='solid')
ws.conditional_formatting.add('B2:C4', CellIsRule(operator='lessThan', formula=[0], fill=fill))
wb.save('mwe.xlsx')
wb.close()
You need to add the parameter end_color like this :
fill = PatternFill(start_color='538DD5',end_color='538DD5',fill_type='solid')
check this link : https://openpyxl.readthedocs.io/en/stable/formatting.html
from openpyxl import Workbook
from openpyxl.styles import PatternFill
from openpyxl.formatting.rule import CellIsRule
wb = Workbook()
ws = wb.active
ws['B2'] = -2
ws['B3'] = -1
ws['B4'] = 0
ws['C2'] = -1
ws['C3'] = 0
ws['C4'] = 1
fill = PatternFill(start_color='538DD5',end_color='538DD5',fill_type='solid')
#print(fill)
ws.conditional_formatting.add('B2:C4', CellIsRule(operator='lessThan', formula=[0], fill=fill))
wb.save('mwe.xlsx')
wb.close()
result :
Following #GiovaniSalazar answer, I did more tests.
The parameters used for the color (start_color, end_color, fgColor, bgColor) do not have the same behaviour with conditional formatting and simple formatting (bug in openpyxl ?).
Here is a comparison of both. The only one working for both formatting is start_color + end_color.
from openpyxl import Workbook
from openpyxl.styles import PatternFill
from openpyxl.formatting.rule import CellIsRule
wb = Workbook()
ws = wb.active
ws['C2'] = -4
ws['C3'] = -3
ws['C4'] = -2
ws['C5'] = -1
ws['D2'] = 4
ws['D3'] = 3
ws['D4'] = 2
ws['D5'] = 1
ws['C1'] = 'Cond. formatting'
ws['F1'] = 'Formatting'
ws['A2'] = 'start+end'
fill = PatternFill(start_color='538DD5', end_color='538DD5', fill_type='solid')
# OK
ws.conditional_formatting.add('C2:D2', CellIsRule(operator='lessThan', formula=[0], fill=fill))
# OK
ws['F2'].fill = fill
ws['A3'] = 'start'
fill = PatternFill(start_color='538DD5', fill_type='solid')
# Problem (white background)
ws.conditional_formatting.add('C3:D3', CellIsRule(operator='lessThan', formula=[0], fill=fill))
# OK
ws['F3'].fill = fill
ws['A4'] = 'fgColor'
fill = PatternFill(fgColor='538DD5', fill_type='solid')
# Problem (white background)
ws.conditional_formatting.add('C4:D4', CellIsRule(operator='lessThan', formula=[0], fill=fill))
# OK
ws['F4'].fill = fill
ws['A5'] = 'bgColor'
fill = PatternFill(bgColor='538DD5', fill_type='solid')
# OK
ws.conditional_formatting.add('C5:D5', CellIsRule(operator='lessThan', formula=[0], fill=fill))
# Problem (black background)
ws['F5'].fill = fill
wb.save('mwe.xlsx')
wb.close()
Output Excel file:
Output Excel file

how to make a list from result of a function?

When I run my code it works very well and makes an excel file I named exel.xlsx, but there is no information in exel.xlsx.
I think I make a mistake in making a list but I can't find a solution.
def randStr(length=7):
characters = list('bcdghijkmnpqrtuvwxyz23456789')
shuffle(characters)
exel = ''.join(characters[:length])
listb = [exel]
listb.append(exel)
workbook = xlsxwriter.Workbook('Exel.xlsx')
worksheet = workbook.add_worksheet('randomise')
chart = workbook.add_chart({'type': 'line'})
expenses = (listb)
row = 0
col = 0
workbook.close()
return exel
import xlsxwriter
workbook = xlsxwriter.Workbook('chart_line.xlsx')
worksheet = workbook.add_worksheet()
# Add the worksheet data to be plotted.
data = [10, 40, 50, 20, 10, 50]
worksheet.write_column('A1', data)
# Create a new chart object.
chart = workbook.add_chart({'type': 'line'})
# Add a series to the chart.
chart.add_series({'values': '=Sheet1!$A$1:$A$6'})
# Insert the chart into the worksheet.
worksheet.insert_chart('C1', chart)
workbook.close()
This is the basic way to add_chart , then adding the values to chart and inserting the chart .
But you are not adding any value to your chart. Moreover you are not adding any value to the column/row in sheet.
I ran your code , sheet with name "randomise" is created , but no data in it, as you havent added anything
solved!
def randStr(length=7):
characters = list('bcdghijkmnpqrtuvwxyz23456789')
shuffle(characters)
listc=''.join(characters[:length])
return listc
listb=[]
if __name__ == '__main__':
for i in range(20):
value1=(randStr())
listb.append(value1)
workbook = xlsxwriter.Workbook('Exel.xlsx')
worksheet = workbook.add_worksheet('randomise')
worksheet.write_column(0,0,listb)
chart = workbook.add_chart({'type': 'line'})
expenses =(listb)
row = 0
col = 0
workbook.close()
img = makeImage(value1, width=512)
with open('%d.png' % i, 'wb') as f:
f.write(img)
print (i)

Looping through a spreadsheet and plotting all columns with xlsxwriter, Pandas

I bet I'm really close here. I'm trying to look at spreadsheets with potentially 100's of columns and create a plot in a new spreadsheet for each column on the fly. I've got a few of these working where I simply call multiple calls to chart1,chart2,chart3......
What I have below loops fine, inserts the data in the first sheet, creates the second sheet and inserts only the first chart. How do I write the loop to create "n" charts?
I bet it's a silly trivial thing.
Thanks in advance.
Input Data:
https://drive.google.com/open?id=1sts5axnT7aQ04zHv8nPwhnrQPDb7oZlV
import pandas as pd
import codecs
import csv
import os
import xlsxwriter
import datetime
df3 = pd.read_csv('TEST.csv', index_col=0, header=[0], low_memory=False, na_filter=True, encoding='utf-8')
writer2 = pd.ExcelWriter('TEST.xlsx', engine='xlsxwriter')
#define the sheetname
stage = 10
sheetname1 = "Stage_" +str(stage)
print(sheetname1)
df3.to_excel(writer2, sheet_name = sheetname1 , startrow=4, startcol=0, encoding='utf8')
maxcol = df3.shape[1]-1
maxlen = df3.shape[0]-1
print(maxcol, maxlen)
#set the workbook value
c = df3[['TWO']]
workbook = writer2.book
#set the worksheet value
sheetname2 = "Stage_" +str(stage) +str("_P")
c.to_excel(writer2, sheet_name = sheetname2 , startrow=4, startcol=0, encoding='utf8')
print(sheetname2)
worksheet = writer2.sheets[ sheetname2 ]
for i in range(2, maxcol):
TITLE = df3.columns[i]
LOC_NUM = (i - 1) * 34 - 33
LOCATION = "C" +str(LOC_NUM)
print("TITLE:", TITLE, "GRAPH_LOCATION:", LOC_NUM,LOCATION, "LENGTH:", maxlen, "INDICE:", i)
chart = workbook.add_chart({'type': 'line'})
chart.set_size({'width': 1200, 'height': 640})
chart.add_series({"values" : [ sheetname1 , 7, i ,maxlen, i ],"name" : TITLE })
chart.set_x_axis({'name': 'Time (s)', 'position_axis': 'on_tick'})
chart.set_y_axis({'name': 'Test', 'major_gridlines': {'visible': False}})
# Turn off chart legend. It is on by default in Excel.
chart.set_legend({'position': 'none'})
worksheet.insert_chart( LOCATION , chart )
writer2.save()

Categories