33import gspread
44import gspread_formatting
55from enum import Enum
6+ import pandas as pd
67
78FONT_SIZE_PTS = 10
89PTS_PIXELS_RATIO = 4 / 3
@@ -35,7 +36,9 @@ class CHART_TYPES(Enum):
3536 "bold_header" : True ,
3637 "center_header" : True ,
3738 "freeze_header" : True ,
38- "column_widths" : {"justify" : True , "buffer_chars" : DEFAULT_BUFFER_CHARS }
39+ "column_widths" : {"justify" : True , "buffer_chars" : DEFAULT_BUFFER_CHARS },
40+ "extra_columns" : 0 ,
41+ "extra_columns_width" : 50 ,
3942}
4043
4144def extract_credentials (authentication_response ):
@@ -169,7 +172,7 @@ def fill_worksheet_with_df(
169172 df ,
170173 worksheet_name ,
171174 overlapBehavior ,
172- sheet_formatting_options = DEFAULT_SHEET_FORMATTING_OPTIONS ,
175+ sheet_formatting_options = {} ,
173176 column_formatting_options = {}
174177 ):
175178 """
@@ -199,38 +202,47 @@ def fill_worksheet_with_df(
199202 title = worksheet_name , rows = df .shape [0 ], cols = df .shape [1 ]
200203 )
201204
205+ sheet_formatting_options_filled = {** DEFAULT_SHEET_FORMATTING_OPTIONS , ** sheet_formatting_options }
206+
207+ # Add extra blank columns to the right of the worksheet
208+ df_to_insert = pd .concat (
209+ [df ] + [pd .Series (" " , index = df .index , name = "" )] * sheet_formatting_options_filled ["extra_columns" ],
210+ axis = 1
211+ )
202212 # Add data to worksheet
203- worksheet .update ([df .columns .values .tolist ()] + df .fillna ("NA" ).values .tolist ())
213+ worksheet .update ([df_to_insert .columns .values .tolist ()] + df_to_insert .fillna ("NA" ).values .tolist ())
204214
205215 # Format worksheet
206216 # Justify Column Widths
207- if "column_widths" not in sheet_formatting_options or sheet_formatting_options ["column_widths" ]["justify" ]:
217+ if "column_widths" not in sheet_formatting_options_filled or sheet_formatting_options_filled ["column_widths" ]["justify" ]:
208218 text_widths = df .astype (str ).columns .map (
209219 lambda column_name : df [column_name ].astype (str ).str .len ().max ()
210220 )
211221 header_widths = df .columns .str .len ()
212222 buffer_chars = (
213223 DEFAULT_BUFFER_CHARS
214- if ("column_widths" not in sheet_formatting_options or "buffer_chars" not in sheet_formatting_options ["column_widths" ])
215- else sheet_formatting_options ["column_widths" ]["buffer_chars" ]
224+ if ("column_widths" not in sheet_formatting_options_filled or "buffer_chars" not in sheet_formatting_options_filled ["column_widths" ])
225+ else sheet_formatting_options_filled ["column_widths" ]["buffer_chars" ]
216226 )
217- column_widths = [
227+ data_column_widths = [
218228 round ((max (len_tuple ) + buffer_chars ) * FONT_SIZE_PTS * 1 / PTS_PIXELS_RATIO )
219229 for len_tuple in zip (text_widths , header_widths )
220230 ]
231+ extra_column_widths = [sheet_formatting_options_filled ["extra_columns_width" ]] * sheet_formatting_options_filled ["extra_columns" ]
232+ combined_column_widths = data_column_widths + extra_column_widths
221233 column_positions = [
222- gspread .utils .rowcol_to_a1 (1 , i + 1 )[0 ] for i , _ in enumerate (column_widths )
234+ gspread .utils .rowcol_to_a1 (1 , i + 1 )[0 ] for i , _ in enumerate (combined_column_widths )
223235 ]
224- gspread_formatting .set_column_widths (worksheet , zip (column_positions , column_widths ))
236+ gspread_formatting .set_column_widths (worksheet , zip (column_positions , combined_column_widths ))
225237 # Freeze Header
226- if "freeze_header" not in sheet_formatting_options or sheet_formatting_options ["freeze_header" ]:
238+ if "freeze_header" not in sheet_formatting_options_filled or sheet_formatting_options_filled ["freeze_header" ]:
227239 gspread_formatting .set_frozen (worksheet , rows = 1 )
228240 base_format_options = gspread_formatting .CellFormat ()
229241 # Bold Header
230- if "bold_header" not in sheet_formatting_options or sheet_formatting_options ["bold_header" ]:
242+ if "bold_header" not in sheet_formatting_options_filled or sheet_formatting_options_filled ["bold_header" ]:
231243 base_format_options += gspread_formatting .CellFormat (textFormat = gspread_formatting .TextFormat (bold = True ))
232244 # Center Header
233- if "center_header" not in sheet_formatting_options or sheet_formatting_options ["center_header" ]:
245+ if "center_header" not in sheet_formatting_options_filled or sheet_formatting_options_filled ["center_header" ]:
234246 base_format_options += gspread_formatting .CellFormat (horizontalAlignment = "CENTER" )
235247 # Handle column specific formatting
236248 for column in column_formatting_options :
@@ -313,7 +325,7 @@ def fill_spreadsheet_with_df_dict(sheet, df_dict, overlapBehavior, sheet_formatt
313325 for worksheet_name , df in df_dict .items ():
314326 fill_worksheet_with_df (
315327 sheet , df , worksheet_name , overlapBehavior ,
316- sheet_formatting_options = sheet_formatting_options .get (worksheet_name , DEFAULT_SHEET_FORMATTING_OPTIONS ),
328+ sheet_formatting_options = sheet_formatting_options .get (worksheet_name , {} ),
317329 column_formatting_options = column_formatting_options .get (worksheet_name , {})
318330 )
319331
@@ -338,7 +350,12 @@ def update_sheet_raw(sheets_authentication_response, sheet, *updates):
338350 "title" : "" ,
339351 "x_axis_title" : "" ,
340352 "y_axis_title" : "" ,
341- "chart_position" : None # Means it will be created in a new sheet
353+ "invert_x_axis" : False ,
354+ "chart_position" : None , # None means it will be created in a new sheet
355+ "chart_position_offset_x" : 0 ,
356+ "chart_position_offset_y" : 0 ,
357+ "chart_width" : 600 ,
358+ "chart_height" : 371 ,
342359}
343360
344361@dataclass
@@ -366,11 +383,14 @@ def _cell_to_grid_coordinate(cell, worksheet):
366383
367384def add_chart_to_sheet (sheets_authentication_response , sheet , worksheet , chart_type , domain , series , ** chart_args ):
368385 complete_chart_args = {** DEFAULT_CHART_ARGS , ** chart_args }
369- print (worksheet .id )
370386 if complete_chart_args ["chart_position" ] is not None :
371387 position_dict = {
372388 "overlayPosition" : {
373- "anchorCell" : _cell_to_grid_coordinate (complete_chart_args ["chart_position" ], worksheet )
389+ "anchorCell" : _cell_to_grid_coordinate (complete_chart_args ["chart_position" ], worksheet ),
390+ "offsetXPixels" : complete_chart_args ["chart_position_offset_x" ],
391+ "offsetYPixels" : complete_chart_args ["chart_position_offset_y" ],
392+ "widthPixels" : complete_chart_args ["chart_width" ],
393+ "heightPixels" : complete_chart_args ["chart_height" ],
374394 }
375395 }
376396 else :
@@ -385,6 +405,7 @@ def add_chart_to_sheet(sheets_authentication_response, sheet, worksheet, chart_t
385405 ],
386406 },
387407 },
408+ "reversed" : complete_chart_args ["invert_x_axis" ],
388409 },
389410 ]
390411 formatted_series = [
@@ -411,8 +432,6 @@ def add_chart_to_sheet(sheets_authentication_response, sheet, worksheet, chart_t
411432 "title" : complete_chart_args ["y_axis_title" ],
412433 "position" : "LEFT_AXIS" ,
413434 })
414- print (formatted_domains )
415- print (formatted_series )
416435 request = {
417436 "addChart" : {
418437 "chart" : {
@@ -432,7 +451,6 @@ def add_chart_to_sheet(sheets_authentication_response, sheet, worksheet, chart_t
432451 },
433452 },
434453 }
435- print (request )
436454
437455 response = update_sheet_raw (sheets_authentication_response , sheet , request )
438456 return response
0 commit comments