This is a section of my python code, this class retrieves a sheet from smartsheet and turns it into a df, which later uses to display on a table on my GUI. I've been trying to change row colors but cant seem to get it right, in the code I managed to change the color of columns, however when I pass self.table.rowcolors... it does nothing. Anyone has an idea of what else I could try?
class SmartsheetFrame(Frame):
def __init__(self, master):
super().__init__(master)
self.configure(bg='white')
# Get the sheet
sheet_id = 3839061875025796
ss_client = smartsheet.Smartsheet(access_token=os.environ.get('SMARTSHEET_ACCESS_TOKEN'))
sheet = ss_client.Sheets.get_sheet(sheet_id)
rows = sheet.rows
columns = sheet.columns
#Creating a dataframe from the sheet
df = pd.DataFrame(columns=[col.title for col in columns])
for row in rows:
df.loc[row.id] = [col.value for col in row.cells]
last_4_rows = df.tail(4)
# Create a Table widget and set its properties
self.table = pt.Table(self, dataframe=df, showstatusbar=True, height=600, width=1200)
# Specify the row index you want to color
self.table.columncolors['AEM ID'] = 'forestgreen'
self.table.columncolors['Intel ID'] = 'midnightblue'
self.table.columncolors['Site'] = 'darkslategrey'
self.table.columncolors['Mode'] = 'firebrick'
self.table.redraw()
self.table.show()
I've tried many methods that I found online, so far I've managed to chage the color of columns, but havent been able to do the same for rows
Related
I am building a table that updates the values of an output DF into a csv file (or whatever output defined).
I defined a generate_agrid(df) function that outputs a class that contains a data method that is a pd.DataFrame. When I run the code grid_table = generate_agrid(df), the grid_table generated contains the original df, even if I modify it in the UI. I noticed that when I checked the input that my update function received.
What I want is to:
Graph the data in df -> update DF data in the UI and return -> save new df data into a csv every time I press update button
Why does my generate_agrid method always returns the initial DF used as an input? How can i update it?
My code
import streamlit as st
from metrics.get_metrics import get_data
from metrics.config import PATH_SAMPLES
filename: str = 'updated_sample.csv'
save_path = PATH_SAMPLES.joinpath(filename)
def generate_agrid(data: pd.DataFrame):
gb = GridOptionsBuilder.from_dataframe(data)
gb.configure_default_column(editable=True) # Make columns editable
gb.configure_pagination(paginationAutoPageSize=True) # Add pagination
gb.configure_side_bar() # Add a sidebar
gb.configure_selection('multiple', use_checkbox=True,
groupSelectsChildren="Group checkbox select children") # Enable multi-row selection
gridOptions = gb.build()
grid_response = AgGrid(
data,
gridOptions=gridOptions,
data_return_mode=DataReturnMode.AS_INPUT,
update_on='MANUAL', # <- Should it let me update before returning?
fit_columns_on_grid_load=False,
theme=AgGridTheme.STREAMLIT, # Add theme color to the table
enable_enterprise_modules=True,
height=350,
width='100%',
reload_data=True
)
data = grid_response['data']
selected = grid_response['selected_rows']
df = pd.DataFrame(selected) # Pass the selected rows to a new dataframe df
return grid_response
def update(grid_table: classmethod, filename: str = 'updated_sample.csv'):
save_path = PATH_SAMPLES.joinpath(filename)
grid_table_df = pd.DataFrame(grid_table['data'])
grid_table_df.to_csv(save_path, index=False)
# First data gather
df = get_data()
if __name__ == '__main__':
# Start graphing
grid_table = generate_agrid(df)
# Update
st.sidebar.button("Update", on_click=update, args=[grid_table])
Found the issue, it was just a small parameter that was activated.
While instantiating the AgGrid, I had to eliminate the reload_data=True parameter. Doing that, everything worked as expected and the data could be successfully updated after manually inputting and pressing "update"
This is how AgGrid must be instantiated
grid_response = AgGrid(
data,
gridOptions=gridOptions,
data_return_mode=DataReturnMode.AS_INPUT,
update_on='MANUAL',
fit_columns_on_grid_load=False,
theme=AgGridTheme.STREAMLIT, # Add theme color to the table
enable_enterprise_modules=True,
height=350,
width='100%',
)
I've got the following code:
def pivot_table(wb: object, ws1: object, pt_ws: object, ws_name: str, pt_name: str, pt_rows: list, pt_filters: list, pt_fields: list):
"""
wb = workbook1 reference
ws1 = worksheet1 that contain the data
pt_ws = pivot table worksheet number
ws_name = pivot table worksheet name
pt_name = name given to pivot table
pt_rows, pt_cols, pt_filters, pt_fields: values selected for filling the pivot tables
"""
# pivot table location
pt_loc = len(pt_filters) + 2
# grab the pivot table source data
#to edit with new data
pc = wb.PivotCaches().Create(SourceType=win32c.xlDatabase, SourceData=ws1.Range("A9:Q10807"))
# create the pivot table object
pc.CreatePivotTable(TableDestination=f'{ws_name}!R{pt_loc}C1', TableName=pt_name)
# selecte the pivot table work sheet and location to create the pivot table
pt_ws.Select()
pt_ws.Cells(pt_loc, 1).Select()
# Visiblity True or False
pt_ws.PivotTables(pt_name).ShowValuesRow = False
pt_ws.PivotTables(pt_name).RowGrand = False
pt_ws.PivotTables(pt_name).ColumnGrand = False
pt_ws.PivotTables(pt_name).RowAxisLayout(win32c.xlTabularRow)
Now I would like to hide subtotals for all columns with python. Anyone know how to do this?
I've tried the following:
#pt_ws.PivotTables("User ID").RowGrand = False
pt_ws.PivotTables("User ID").ColumnGrand = False
pt_ws.PivotTables("User Group").RowGrand = False
pt_ws.PivotTables("User Group").ColumnGrand = False
pt_ws.PivotTables("Risk Description").RowGrand = False
pt_ws.PivotTables("Risk Description").ColumnGrand = False
Hpwever this gives an error..
com_error: (-2147352567, 'Exception occurred.', (0, 'Microsoft Excel', 'PivotTables method of Worksheet class failed', 'xlmain11.chm', 0, -2146827284), None)
Please help!
As defined in the Subtotals documentation at the end of the Remarks part, you need to set all values of Subtotals tuple to be False.
To hide all subtotals your code should look like that
for field in fields:
field.Subtotals = tuple(False for _ in range(12))
here field should be an item from the PivotFields collection. For example, to disable subtotals for User Id
pt.PivotFields('User Id').Subtotals = tuple(False for _ in range(12))
TL; DR
How do I load a spreadsheet template using OpenPyXL
workbook = openpyxl.load_workbook('template.xlsx')
then create a new one and fill the rows data with XlsxWriter?
xls_workbook = xlsxwriter.Workbook('proposal.xlsx')
# Missing step
xls_workbook = workbook.add_worksheet(workbook)
xls_workbook.write(CELL_COST, cost)
Details
I have a spreadsheet with several tabs with a quite complex formatting (used as a sales proposal), so there is a lot of formatting that must be preserved.
So, instead of programatically create the spreadsheet, I have to:
Open the template for reading using OpenPyXL
Extract the template and save it into a template.py file
Create the sales pitch spreadsheets using the template, creating new tables with XlsxWriter.
Is there a simple way of extracting the template or do really I need recreate the whole layout programmatically?
I have run into the same "problem" and have not found much about it. So finally I code a little function to copy the template sheet and some styling.
It's 2 years late but I hope it helps someone who comes to this question.
def openpyxl_to_xlsxwriter(openpyxl_workbook, xlsxwriter_workbook):
template_sheets = openpyxl_workbook.get_sheet_names()
# Copy all the sheets from the openpyxl template to the xlsxwriter workbook.
for sheet_name in template_sheets:
xlsxwriter_workbook.add_worksheet(sheet_name)
for sheet in template_sheets:
openpyxl_active_sheet = openpyxl_workbook.get_sheet_by_name(sheet)
xlsxwriter_active_sheet = xlsxwriter_workbook.get_worksheet_by_name(sheet)
for row in openpyxl_active_sheet.rows:
for cell in row:
# # Copy some STYLES # #
# Copy font color and Background color
cell_style = {}
theme = cell.fill.start_color.theme
tint = cell.fill.start_color.tint
font_theme = cell.font.color.theme
font_tint = cell.font.color.tint
font_color = theme_and_tint_to_rgb(openpyxl_workbook, font_theme, font_tint)
cell_style['font_color'] = font_color
try:
background_color = theme_and_tint_to_rgb(openpyxl_workbook, theme, tint)
cell_style['bg_color'] = background_color
except:
pass
cell_format = xlsxwriter_workbook.add_format(cell_style)
# Copy border
border_left = cell.border.left.border_style
border_right = cell.border.right.border_style
border_top = cell.border.top.border_style
border_bottom = cell.border.bottom.border_style
if border_left:
cell_format.set_left()
if border_right:
cell_format.set_right()
if border_top:
cell_format.set_top()
if border_bottom:
cell_format.set_bottom()
# Copy Cell Width and Height
cell_height = openpyxl_active_sheet.row_dimensions[cell.row].height
cell_width = openpyxl_active_sheet.column_dimensions[cell.column_letter].width
column_index = cell.column - 1
xlsxwriter_active_sheet.set_column(column_index, column_index, cell_width)
row_index = cell.row - 1
xlsxwriter_active_sheet.set_row(row_index, cell_height)
# Copy Cell Value
xlsxwriter_active_sheet.write(cell.coordinate, cell.value, cell_format)
I'm creating a leaflet map in folium using MarkerCluster. I have been all over the documentation and searched for examples, but I cannot figure out how to customize the color for a given MarkerCluster or FeatureGroup (e.g., one set in green rather than default blue).
I tried creating the markers individually and iteratively adding them to the MarkerCluster, and that gave me the color I wanted, but then the iFrame html table woudn't function properly, and the popups were not appearing.
The code I've written works flawlessly (an html table used for popups is not supplied), but I'd really like to be able to change the color for one set of markers and retain the popups using the methods in my code. Any guidance would be greatly appreciated!
or_map = folium.Map(location=OR_COORDINATES, zoom_start=8)
res_popups, res_locations = [], []
com_popups, com_locations = [], []
for idx, row in geo.iterrows():
if row['Type'] == 'Residential':
res_locations.append([row['geometry'].y, row['geometry'].x])
property_type = row['Type']
property_name = row['Name']
address = row['address']
total_units = row['Total Unit']
iframe = folium.IFrame(table(property_type, property_name,
address, total_units), width=width,
height=height)
res_popups.append(iframe)
else:
com_locations.append([row['geometry'].y, row['geometry'].x])
property_type = row['Type']
property_name = row['Name']
address = row['address']
total_units = row['Total Unit']
iframe = folium.IFrame(table(property_type, property_name, address,
total_units), width=width,
height=height)
com_popups.append(iframe)
r = folium.FeatureGroup(name='UCPM Residential Properties')
r.add_child(MarkerCluster(locations=res_locations, popups=res_popups))
or_map.add_child(r)
c = folium.FeatureGroup(name='UCPM Commercial Properties')
c.add_child(MarkerCluster(locations=com_locations, popups=com_popups))
or_map.add_child(c)
display(or_map)
Instead of just dumping all your locations into the Cluster, you could loop over them and create a Marker for each of them - that way you can set the Marker's color. After creation, you can add the Marker to the desired MarkerCluster.
for com_location, com_popup in zip(com_locations, com_popups):
folium.Marker(com_location,
popup=com_popup
icon=folium.Icon(color='red', icon='info-sign')
).add_to(cluster)
A different approach would be to modify the style function, as shown here (In[4] and In[5]).
I'm trying to show several rows from database in a TreeView but all I am getting are some dummy rows as you can see in the image below.
class SettingsDialog(gtk.Dialog):
def __init__(self):
gtk.Dialog.__init__(self, "Server Settings", self, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
# Instantiate ServerManager
self.server_manager = ServerManager()
# Create TreeStore for Server list
self.liststore = gtk.ListStore(str, str)
self.treeview = gtk.TreeView(self.liststore)
# Create TreeViewColumns to display data
cell = gtk.CellRendererText()
col = gtk.TreeViewColumn("Name")
col.pack_start(cell, True)
self.treeview.append_column(col)
cell = gtk.CellRendererText()
col = gtk.TreeViewColumn("URL")
col.pack_start(cell, True)
self.treeview.append_column(col)
self.vbox.pack_start(self.treeview)
self.resize(500,350)
self.set_position(gtk.WIN_POS_CENTER)
self.show_all()
self.load_server_list()
def load_server_list(self):
self.liststore.clear()
servers = self.server_manager.list()
for name, url in servers.iteritems():
self.liststore.append([name, url])
self.show_all()
Data returned from self.server_manager.list() is valid an added to the list store perfectly. There seems to be something wrong with the CellRenderers but I wasn't able to find the error.
You have to set an attribute mapping on the column. For example, the cellrenderer's text attribute value will be displayed in the treeview cell. It is taken from the values on the data model (self.liststore). The column number on the model where the value is taken from is specified in the attribute mapping.
## Take value for *text* attribute of the cell renderer from the model's 3rd column
col = gtk.TreeViewColumn(title, cellrenderer, text=2)