Exporting a pandas dataframe to excel using xlwings - python

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

Related

Python xlsxwriter. Header_format sub-property of columns parameter not working as expected

I need to set a table header in Excel with the next date format: 'mmm-yy'.
Formatting I've set:
title_date_format = workbook.add_format({
'text_wrap': True,
'font_size': 11,
'num_format': 'mmm-yy'
})
Column settings:
column_settings = []
index = 0
for column in df.columns:
if index < 3:
dct = {}
dct['header'] = column
column_settings.append(dct)
else:
dct = {}
formula = '=[#[Value]]*[#Qty]'
dct['header'] = column
dct['formula'] = formula
dct['header_format'] = title_date_format
column_settings.append(dct)
index += 1
Table creation:
# Create a table
worksheet.add_table(0, 0, max_row + 2, max_col - 1, {
'columns': column_settings
})
The problem is that only the 'text_wrap' and font_size' sub-properties work fine. The column header, which is a date, stays in '1/24/2022' format instead of 'Jan-22', so 'num_format': 'mmm-yy' doesn't apply.
Full example:
import datetime as dt
import pandas as pd
import numpy as np
import xlsxwriter
initial_data = {
'Category': ['catA', 'catB', 'catC', 'catC'],
'Item': ['item1', 'item2', 'item3', 'item4']
}
df = pd.DataFrame(initial_data)
# Add columns with month-year
for year in range(2,4):
if year == 2:
for month in range(11,13):
date_str = str(month) + '/1/202' + str(year)
df[date_str] = ''
else:
for month in range(1,4):
date_str = str(month) + '/1/202' + str(year)
df[date_str] = ''
writer = pd.ExcelWriter('test.xlsx', engine='xlsxwriter')
df.to_excel(writer, sheet_name='Sheet1', header=False, startrow=1, index=False)
workbook = writer.book
worksheet = writer.sheets['Sheet1']
title_date_format = workbook.add_format({
'text_wrap': True,
'font_name': 'Calibri',
'font_size': 10,
'num_format': 'mmm-yy'
})
column_settings = []
for column in df.columns:
dct = {}
dct['header'] = column
dct['header_format'] = title_date_format
column_settings.append(dct)
(max_row, max_col) = df.shape
worksheet.add_table(0, 0, max_row, max_col - 1, {
'columns': column_settings,
'style': 'Table Style Light 9'
})
writer.save()
Any ideas on how to make it work?
Thank you
The issue is that the column headers are strings and the date number format only applies to numbers. So the solution would be to turn the column headers into datetime numbers so that the format can be applied. However, as far as I can see Table column headers in Excel need to be strings, so that isn't an option.
So as a workaround you could format the header strings that you are currently using into the format that you want:
# ...
from datetime import datetime
# ...
for year in range(2,4):
if year == 2:
for month in range(11,13):
date_str = datetime(2022, month, 1).strftime("%b-%y")
df[date_str] = ''
else:
for month in range(1,4):
date_str = datetime(2024, month, 1).strftime("%b-%y")
df[date_str] = ''
Output:

how to pysimplegui manage dataframe in excel?

i want to delete dataframe unnamed in red arrow , and the i want to add some text when i click submit i have index from 1 not in 0 like this
Data_entry.xlsx
can you give me solution about this problem ?
in above my code in python 3
import PySimpleGUI as sg
import pandas as pd
# importing openpyxl module
import openpyxl
# Give the location of the file
path = "C:\\Users\\Admin\\Desktop\\WEB\\PYTHON_PYSIMPLEGUI\\Data_Entry.xlsx"
sg.theme('DarkGreen7')
EXCEL_FILE = 'Data_Entry.xlsx'
df = pd.read_excel(EXCEL_FILE)
my_img = sg.Image(r'C:\Users\master\Desktop\WEB\PYTHON_PYSIMPLEGUI\logo.png')
"""
# Template Taskbar
menu_def = [['File', ['Open', 'Save', 'Exit',]],
['Edit', ['Paste', ['Special', 'Normal',], 'Undo'],],
['Help', 'About...'],]
"""
menu_def = [['File', ['Exit']],['Help', 'About...'],]
layout = [
[sg.Menu(menu_def)],
[sg.Column([[my_img]], justification='center')],
[sg.Text('Simacan ( SIstem Monitoring And Controling Absen Nilai')],
[sg.Text('Nama', size=(15,1)), sg.InputText(key='Nama')],
[sg.Text('Kehadiran', size=(15,1)), sg.Combo(['Hadir', 'Sakit', 'Tidak Masuk'], key='Keterangan')],
[sg.Submit(), sg.Exit()]
]
window =sg.Window('Aplikasi Simacan versi 1.2', layout,size=(800, 600), font='Courier 12')
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == 'Exit':
break
if event == 'Submit':
df = df.append(values, ignore_index=True)
df.to_excel(EXCEL_FILE, index=True)
sg.popup('Data saved !')
print(event, values)
window.close()
There's are some issues here.
Create a blank excel file to store your data.
Open excel file as a dataframe, option index_col set the index column or you may get Unnamed: 0 column as index in your dataframe.
df = pd.read_excel(EXCEL_FILE, index_col=[0])
There's one extra item 0 in dictionary values, it is the key of sg.Menu, should remove it before you append the values to your dataframe by
del values[0]
You can re-index your dataframe by
df.index = np.arange(1, len(df)+1)
You can save dataframe to your excel file only before end of you script, of course, write each new record to your excel file is still fine.

Python openpyxl conditional format containsText

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)

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()

Change the name of excel worksheet with pandas

import pandas as pd
import numpy as np
df = pd.read_excel(r"C:\Users\venkagop\Subbu\promo validation testing\P 02. Promotions-UK C1.xls")
df = df[['Promotions', 'Promotions: AE', 'Promotions: Anaplan ID', 'Promotions: Is Optima Scenario?', 'Promotions: SIDs', 'Set Inactive?', 'Start Date', 'End Date', 'Promo Period', 'Promo Optima Status', 'Change Promo Status']]
df = df[(df['Promo Period'] == 'FY1819')]
df = df[(df['Set Inactive?'] == 0 ) & (df['Promotions: Is Optima Scenario?'] == 1)]
df.dropna(subset=['Promotions: SIDs'], inplace=True)
df['Optima vs Anaplan Promo Status Validation'] = ""
df['Optima vs Anaplan Promo Status Validation'] = np.where(df['Promo Optima Status'] == df['Change Promo Status'], 'True', 'False')
df.to_excel(r"C:\Users\venkagop\Subbu\mytest.xls", index = False)
#after this i want to change sheeet1 name to some other name#
There are 2 ways you can approach this problem.
Approach 1
Save the excel file to the correct worksheet name from the beginning, by using the sheet_name argument.
import pandas as pd
writer = pd.ExcelWriter(r'C:\Users\venkagop\Subbu\mytest.xls')
df.to_excel(writer, sheet_name='MySheetName', index=False)
writer.save()
Approach 2
If Approach 1 is not possible, change the worksheet name at a later stage using openpyxl. The advantage of this method is you remove the cost of converting pandas dataframe to Excel format again.
import openpyxl
file_loc = r'C:\Users\venkagop\Subbu\mytest.xls'
ss = openpyxl.load_workbook(file_loc)
ss_sheet = ss.get_sheet_by_name('Sheet1')
ss_sheet.title = 'MySheetName'
ss.save(file_loc)

Categories