great-tables icon indicating copy to clipboard operation
great-tables copied to clipboard

Issue when attempting to save

Open HansMellman opened this issue 9 months ago • 11 comments
trafficstars

Code

(
    GT(qb)
    .tab_header(
        title=md("<img src='https://i.imgur.com/xJYzCF8.png' width='90' height='90' style='vertical-align: middle;'> &#x1F3C8; **Analysis by Position Group** &#x1F3C8; <img src='https://i.imgur.com/xJYzCF8.png' width='90' height='90' style='vertical-align: middle;'>"), ## add small footballs to the title. ## these characters cause issues when saving. 
        subtitle=md("_**2065 Regular Season**_")
    )
    .fmt_image(
        columns='Team',
        path=analysis_path,
        file_pattern="{}.png"
    )
    .cols_align(
        align="center", columns=None
    )
    .cols_label(
        Team = (" "),
        Position_Group = (" "),
        Intelligence = ("Intel"),
        Performance_Grade = ("Performance"),
        Current_Overall = ("Current"),
        Future_Overall = ("Future"),
        PenaltiesCommitted = ("Penalties"),
        Pedigree_Percentage = ("Pedigree"),
        Intelligence_vs_league_avg = ("Int"),
        PenaltiesCommitted_vs_league_avg = ("Pen"),
        Performance_Grade_vs_league_avg = ("Perf"),
        Current_Overall_vs_league_avg = ("Curr"),
        Future_Overall_vs_league_avg = ("Fut"),
        Experience_vs_league_avg = ("Exp"),
        Pedigree_Percentage_vs_league_avg = ("Pedigree")
    )
    .tab_options(
        container_width = "100%",
        heading_background_color="#990033",
        table_border_top_color="#990033",
        table_font_names="Calibri",
        table_font_size="20px"
    )
    .tab_style(
        style=style.fill(
            color=map_colour_analysis),
        locations=loc.body("Position_Group")
        )
    .tab_style(
        style=style.text(
            color=text_colour_analysis),
        locations=loc.body("Position_Group")
        )
    .tab_spanner(
        label=md('**Cumulative**'),
        columns=['PenaltiesCommitted', 'Pedigree_Percentage']
    )
    .tab_spanner(
        label=md('**Group Averages**'),
        columns=['Intelligence', 'Performance_Grade', 'Current_Overall', 'Future_Overall', 'Experience']
    )
    .tab_spanner(
        label=md('**Versus League Average**'), ### MAYBE THE ORDER HERE NEEDS TO BE CHANGED TO HAVE PENALTIES SECOND LAST LIKE THE LEFT HAND COLUMNS?
        columns=['Intelligence_vs_league_avg', 'Performance_Grade_vs_league_avg', 'Current_Overall_vs_league_avg', 'Future_Overall_vs_league_avg', 'Experience_vs_league_avg','PenaltiesCommitted_vs_league_avg', 'Pedigree_Percentage_vs_league_avg']
    )
    .fmt_percent(['Intelligence_vs_league_avg', 'PenaltiesCommitted_vs_league_avg', 'Performance_Grade_vs_league_avg', 'Current_Overall_vs_league_avg', 'Future_Overall_vs_league_avg', 'Experience_vs_league_avg', 'Pedigree_Percentage_vs_league_avg'], decimals=1, drop_trailing_zeros=True, scale_values=False)
    .data_color(
        columns=['Intelligence_vs_league_avg', 'Performance_Grade_vs_league_avg', 'Current_Overall_vs_league_avg', 'Future_Overall_vs_league_avg', 'Experience_vs_league_avg', 'Pedigree_Percentage_vs_league_avg'],  # Target the "Diff" column
        palette=["#FF0000", "#FFFF00", "#00FF00"],  # Red to green gradient
        domain=None  # Automatically inferred from data
    )
    .data_color(
        columns=['PenaltiesCommitted_vs_league_avg'],
        palette=["#FF0000", "#FFFF00", "#00FF00"],  # Red to green gradient,
        domain=None,
        reverse=True
    )
    .tab_style(
        style=[
            style.fill(color="#EDEDED"),
            #style.text(weight="bold")
        ],
        locations=loc.body(columns=['Intelligence', 'Performance_Grade', 'Current_Overall', 'Future_Overall', 'Experience'])) ## Does colouring and bolding actually help?
    .tab_style(
        style=[
            style.fill(color="#F7F7F7"),
        ],
        locations=loc.body(columns=['PenaltiesCommitted', 'Pedigree_Percentage'])
    )
).save(f"{output_dir}/QB_Analysis.png", selector='table', scale=2.0, expand=0, web_driver='chrome', window_size=(6000, 6000), debug_port=None, _debug_dump=None)

Description

I am getting a Javascript error when trying to save an image, I had previously been able to use the exact same script to do this around 1 month ago - this is a fresh venv so a new install of GT if that is pertinent to note. Any idea what could be causing it or how I could solve it/proceed with saving these images?

Traceback

---------------------------------------------------------------------------
JavascriptException                       Traceback (most recent call last)
Cell In[16], line 85
      1 (
      2     GT(qb)
      3     .tab_header(
      4         title=md("<img src='https://i.imgur.com/xJYzCF8.png' width='90' height='90' style='vertical-align: middle;'> &#x1F3C8; **Analysis by Position Group** &#x1F3C8; <img src='https://i.imgur.com/xJYzCF8.png' width='90' height='90' style='vertical-align: middle;'>"), ## add small footballs to the title. ## these characters cause issues when saving. 
      5         subtitle=md("_**2065 Regular Season**_")
      6     )
      7     .fmt_image(
      8         columns='Team',
      9         path=analysis_path,
     10         file_pattern="{}.png"
     11     )
     12     .cols_align(
     13         align="center", columns=None
     14     )
     15     .cols_label(
     16         Team = (" "),
     17         Position_Group = (" "),
     18         Intelligence = ("Intel"),
     19         Performance_Grade = ("Performance"),
     20         Current_Overall = ("Current"),
     21         Future_Overall = ("Future"),
     22         PenaltiesCommitted = ("Penalties"),
     23         Pedigree_Percentage = ("Pedigree"),
     24         Intelligence_vs_league_avg = ("Int"),
     25         PenaltiesCommitted_vs_league_avg = ("Pen"),
     26         Performance_Grade_vs_league_avg = ("Perf"),
     27         Current_Overall_vs_league_avg = ("Curr"),
     28         Future_Overall_vs_league_avg = ("Fut"),
     29         Experience_vs_league_avg = ("Exp"),
     30         Pedigree_Percentage_vs_league_avg = ("Pedigree")
     31     )
     32     .tab_options(
     33         container_width = "100%",
     34         heading_background_color="#990033",
     35         table_border_top_color="#990033",
     36         table_font_names="Calibri",
     37         table_font_size="20px"
     38     )
     39     .tab_style(
     40         style=style.fill(
     41             color=map_colour_analysis),
     42         locations=loc.body("Position_Group")
     43         )
     44     .tab_style(
     45         style=style.text(
     46             color=text_colour_analysis),
     47         locations=loc.body("Position_Group")
     48         )
     49     .tab_spanner(
     50         label=md('**Cumulative**'),
     51         columns=['PenaltiesCommitted', 'Pedigree_Percentage']
     52     )
     53     .tab_spanner(
     54         label=md('**Group Averages**'),
     55         columns=['Intelligence', 'Performance_Grade', 'Current_Overall', 'Future_Overall', 'Experience']
     56     )
     57     .tab_spanner(
     58         label=md('**Versus League Average**'), ### MAYBE THE ORDER HERE NEEDS TO BE CHANGED TO HAVE PENALTIES SECOND LAST LIKE THE LEFT HAND COLUMNS?
     59         columns=['Intelligence_vs_league_avg', 'Performance_Grade_vs_league_avg', 'Current_Overall_vs_league_avg', 'Future_Overall_vs_league_avg', 'Experience_vs_league_avg','PenaltiesCommitted_vs_league_avg', 'Pedigree_Percentage_vs_league_avg']
     60     )
     61     .fmt_percent(['Intelligence_vs_league_avg', 'PenaltiesCommitted_vs_league_avg', 'Performance_Grade_vs_league_avg', 'Current_Overall_vs_league_avg', 'Future_Overall_vs_league_avg', 'Experience_vs_league_avg', 'Pedigree_Percentage_vs_league_avg'], decimals=1, drop_trailing_zeros=True, scale_values=False)
     62     .data_color(
     63         columns=['Intelligence_vs_league_avg', 'Performance_Grade_vs_league_avg', 'Current_Overall_vs_league_avg', 'Future_Overall_vs_league_avg', 'Experience_vs_league_avg', 'Pedigree_Percentage_vs_league_avg'],  # Target the "Diff" column
     64         palette=["#FF0000", "#FFFF00", "#00FF00"],  # Red to green gradient
     65         domain=None  # Automatically inferred from data
     66     )
     67     .data_color(
     68         columns=['PenaltiesCommitted_vs_league_avg'],
     69         palette=["#FF0000", "#FFFF00", "#00FF00"],  # Red to green gradient,
     70         domain=None,
     71         reverse=True
     72     )
     73     .tab_style(
     74         style=[
     75             style.fill(color="#EDEDED"),
     76             #style.text(weight="bold")
     77         ],
     78         locations=loc.body(columns=['Intelligence', 'Performance_Grade', 'Current_Overall', 'Future_Overall', 'Experience'])) ## Does colouring and bolding actually help?
     79     .tab_style(
     80         style=[
     81             style.fill(color="#F7F7F7"),
     82         ],
     83         locations=loc.body(columns=['PenaltiesCommitted', 'Pedigree_Percentage'])
     84     )
---> 85 ).save(f"{output_dir}/QB_Analysis.png", selector='table', scale=2.0, expand=0, web_driver='chrome', window_size=(6000, 6000), debug_port=None, _debug_dump=None)

File d:\Python_Projects\FOF_CSV_PRACTICE\FOF_PENALTIES\.venv\Lib\site-packages\great_tables\_export.py:458, in save(self, file, selector, scale, expand, web_driver, window_size, debug_port, encoding, _debug_dump)
    455     encoded = base64.b64encode(html_content.encode(encoding=encoding)).decode(encoding=encoding)
    456     headless_browser.get(f"data:text/html;base64,{encoded}")
--> 458     _save_screenshot(headless_browser, scale, file, debug=_debug_dump)
    460 if debug_port and web_driver not in {"chrome", "firefox"}:
    461     warnings.warn("debug_port argument only supported on chrome and firefox")

File d:\Python_Projects\FOF_CSV_PRACTICE\FOF_PENALTIES\.venv\Lib\site-packages\great_tables\_export.py:498, in _save_screenshot(driver, scale, path, debug)
    495 original_size = driver.get_window_size()
    497 # set table zoom ----
--> 498 driver.execute_script(
    499     "var el = document.getElementsByTagName('table')[0]; "
    500     f"el.style.zoom = '{scale}'; "
    501     "el.parentNode.style.display='none'; "
    502     "el.parentNode.style.display='';"
    503 )
    505 if debug == "zoom":
    506     return _dump_debug_screenshot(driver, path)

File d:\Python_Projects\FOF_CSV_PRACTICE\FOF_PENALTIES\.venv\Lib\site-packages\selenium\webdriver\remote\webdriver.py:528, in WebDriver.execute_script(self, script, *args)
    525 converted_args = list(args)
    526 command = Command.W3C_EXECUTE_SCRIPT
--> 528 return self.execute(command, {"script": script, "args": converted_args})["value"]

File d:\Python_Projects\FOF_CSV_PRACTICE\FOF_PENALTIES\.venv\Lib\site-packages\selenium\webdriver\remote\webdriver.py:429, in WebDriver.execute(self, driver_command, params)
    427 response = self.command_executor.execute(driver_command, params)
    428 if response:
--> 429     self.error_handler.check_response(response)
    430     response["value"] = self._unwrap_value(response.get("value", None))
    431     return response

File d:\Python_Projects\FOF_CSV_PRACTICE\FOF_PENALTIES\.venv\Lib\site-packages\selenium\webdriver\remote\errorhandler.py:232, in ErrorHandler.check_response(self, response)
    230         alert_text = value["alert"].get("text")
    231     raise exception_class(message, screen, stacktrace, alert_text)  # type: ignore[call-arg]  # mypy is not smart enough here
--> 232 raise exception_class(message, screen, stacktrace)

JavascriptException: Message: javascript error: Cannot read properties of undefined (reading 'style')
  (Session info: chrome=132.0.6834.160)
Stacktrace:
	GetHandleVerifier [0x00007FF7937302F5+28725]
	(No symbol) [0x00007FF793692AE0]
	(No symbol) [0x00007FF79352510A]
	(No symbol) [0x00007FF79352BD70]
	(No symbol) [0x00007FF79352EDF8]
	(No symbol) [0x00007FF7935C1460]
	(No symbol) [0x00007FF79359FFAA]
	(No symbol) [0x00007FF7935C0181]
	(No symbol) [0x00007FF79359FD53]
	(No symbol) [0x00007FF79356A0E3]
	(No symbol) [0x00007FF79356B471]
	GetHandleVerifier [0x00007FF793A5F30D+3366989]
	GetHandleVerifier [0x00007FF793A712F0+3440688]
	GetHandleVerifier [0x00007FF793A678FD+3401277]
	GetHandleVerifier [0x00007FF7937FAAAB+858091]
	(No symbol) [0x00007FF79369E74F]
	(No symbol) [0x00007FF79369A304]
	(No symbol) [0x00007FF79369A49D]
	(No symbol) [0x00007FF793688B69]
	BaseThreadInitThunk [0x00007FF81CFF7374+20]
	RtlUserThreadStart [0x00007FF81E51CC91+33]

HansMellman avatar Feb 03 '25 21:02 HansMellman

I've rolled back to version 0.11.0 as that is the version I had working in another project - I can confirm that this error does not occur when attempting to run the same file with that previous version installed.

HansMellman avatar Feb 05 '25 15:02 HansMellman

I am also now getting strange behaviour where it adds palatial whitespace to the underneath of my table - though it only seems to be doing it inconsistently - for certain dataframes (despite the formatting remaining identical as per the code above, just the dataframe input changing. As per the two images below:

Correct image:

Image

Incorrect image rendered with too much white space at the end:

Image Though it's a little hard to tell from the white on white background here on github, this text is directly under the image for clarity.

HansMellman avatar Feb 05 '25 18:02 HansMellman

I can confirm that I am also having this exact same issue. Unfortunately, this is my first time implementing Great Tables in my workflow, and I must say that it has been a battle with the GT.save() function so far. I have eventually managed to get the save working, but I have two outstanding issues: - rendering of "€" symbol (which appears fine when opening the raw html in chrome, but not when using the GT.save() - whitespace rendering below the table as per this thread.

josephbenjamin avatar Feb 07 '25 13:02 josephbenjamin

@HansMellman and @josephbenjamin, thanks so much for reporting this. Could you please try using the latest version, "v0.17.0," to see if the issue is resolved?

jrycw avatar Mar 12 '25 09:03 jrycw

Hi Jerry,

Going through a test now - previous issue was with v0.11 - been a little while since I ran the code - running again now, I am getting this error:

`--------------------------------------------------------------------------- KeyError Traceback (most recent call last) Cell In[33], line 84 1 ( 2 GT(qb) 3 .tab_header( 4 title=md(" 🏈 Analysis by Position Group 🏈 "), ## add small footballs to the title. ## these characters cause issues when saving. 5 subtitle=md("2065 Regular Season") 6 ) 7 .fmt_image( 8 columns='Team', 9 path=analysis_path, 10 file_pattern="{}.png" 11 ) 12 .cols_align( 13 align="center", columns=None 14 ) 15 .cols_label( 16 Team = (" "), 17 Position_Group = (" "), 18 Intelligence = ("Intel"), 19 Performance_Grade = ("Performance"), 20 Current_Overall = ("Current"), 21 Future_Overall = ("Future"), 22 PenaltiesCommitted = ("Penalties"), 23 Pedigree_Percentage = ("Pedigree"), 24 Intelligence_vs_league_avg = ("Int"), 25 PenaltiesCommitted_vs_league_avg = ("Pen"), 26 Performance_Grade_vs_league_avg = ("Perf"), 27 Current_Overall_vs_league_avg = ("Curr"), 28 Future_Overall_vs_league_avg = ("Fut"), 29 Experience_vs_league_avg = ("Exp"), 30 Pedigree_Percentage_vs_league_avg = ("Pedigree") 31 ) 32 .tab_options( 33 container_width = "100%", 34 heading_background_color="#990033", 35 table_border_top_color="#990033", 36 table_font_names="Calibri", 37 table_font_size="20px", 38 ) 39 .tab_style( 40 style=style.fill( 41 color=map_colour_analysis), 42 locations=loc.body("Position_Group") 43 ) 44 .tab_style( 45 style=style.text( 46 color=text_colour_analysis), 47 locations=loc.body("Position_Group") 48 ) 49 .tab_spanner( 50 label=md('Cumulative'), 51 columns=['PenaltiesCommitted', 'Pedigree_Percentage'] 52 ) 53 .tab_spanner( 54 label=md('Group Averages'), 55 columns=['Intelligence', 'Performance_Grade', 'Current_Overall', 'Future_Overall', 'Experience'] 56 ) 57 .tab_spanner( 58 label=md('Versus League Average'), ### MAYBE THE ORDER HERE NEEDS TO BE CHANGED TO HAVE PENALTIES SECOND LAST LIKE THE LEFT HAND COLUMNS? 59 columns=['Intelligence_vs_league_avg', 'Performance_Grade_vs_league_avg', 'Current_Overall_vs_league_avg', 'Future_Overall_vs_league_avg', 'Experience_vs_league_avg','PenaltiesCommitted_vs_league_avg', 'Pedigree_Percentage_vs_league_avg'] 60 ) 61 .fmt_percent(['Intelligence_vs_league_avg', 'PenaltiesCommitted_vs_league_avg', 'Performance_Grade_vs_league_avg', 'Current_Overall_vs_league_avg', 'Future_Overall_vs_league_avg', 'Experience_vs_league_avg', 'Pedigree_Percentage_vs_league_avg'], decimals=1, drop_trailing_zeros=True, scale_values=False) 62 .data_color( 63 columns=['Intelligence_vs_league_avg', 'Performance_Grade_vs_league_avg', 'Current_Overall_vs_league_avg', 'Future_Overall_vs_league_avg', 'Experience_vs_league_avg', 'Pedigree_Percentage_vs_league_avg'], # Target the "Diff" column 64 palette=["#FF0000", "#FFFF00", "#00FF00"], # Red to green gradient 65 domain=None # Automatically inferred from data 66 ) 67 .data_color( 68 columns=['PenaltiesCommitted_vs_league_avg'], 69 palette=["#FF0000", "#FFFF00", "#00FF00"], # Red to green gradient, 70 domain=None, 71 reverse=True 72 ) 73 .tab_style( 74 style=[ 75 style.fill(color="#EDEDED"), 76 #style.text(weight="bold") 77 ], 78 locations=loc.body(columns=['Intelligence', 'Performance_Grade', 'Current_Overall', 'Future_Overall', 'Experience'])) ## Does colouring and bolding actually help? 79 .tab_style( 80 style=[ 81 style.fill(color="#F7F7F7"), 82 ], 83 locations=loc.body(columns=['PenaltiesCommitted', 'Pedigree_Percentage']) ---> 84 )).save("QB_Analysis.png", selector='table', scale=2.0, expand=0, web_driver='chrome', window_size=(6000, 6000), debug_port=None, _debug_dump=None)

File d:\Python_Projects\FOF_CSV_PRACTICE\FOF_PENALTIES.venv\Lib\site-packages\great_tables_export.py:266, in save(self, file, selector, scale, expand, web_driver, window_size, debug_port, _debug_dump) 251 def as_latex(self: GT, use_longtable: bool = False, tbl_pos: str | None = None) -> str: 252 """ 253 Output a GT object as LaTeX 254 255 The as_latex() method outputs a GT object as a LaTeX fragment. This method is useful for when 256 you need to include a table as part of a LaTeX document. The LaTeX fragment contains the table 257 as a string. 258 259 :::{.callout-warning} 260 as_latex() is still experimental. 261 ::: 262 263 Parameters 264 ---------- 265 --> 266 use_longtable 267 An option to use the longtable environment in LaTeX output. This is useful for tables that 268 span multiple pages and don't require precise positioning. 269 tbl_pos 270 The position of the table in the LaTeX output when use_longtable=False. Valid values for 271 positioning include "!t" (top of page), "!b" (bottom of the page), "!h" (here), 272 "!p" (on a separate page), and "!H" (exactly here). If a value is not provided then the 273 table will be placed at the top of the page; if in the Quarto render then the table 274 positioning option will be ignored in favor of any setting within the Quarto rendering 275 environment. 276 277 Returns 278 ------- 279 str 280 A LaTeX fragment that contains the table. 281 282 Limitations 283 ----------- 284 The as_latex() method is still experimental and has some limitations. The following 285 functionality that is supported in HTML output tables is not currently supported in LaTeX 286 output tables: 287 288 - the rendering of the stub and row group labels (via the =rowname_col and =groupname_col 289 args in the GT() class) 290 - the use of the md() helper function to signal conversion of Markdown text 291 - units notation within the cols_labels() and tab_spanner() methods 292 - the fmt_markdown(), fmt_units(), fmt_image(), and fmt_nanoplot() methods 293 - the sub_missing() and sub_zero() methods 294 - most options in the tab_options() method, particularly those that are specific to styling 295 text, borders, or adding fill colors to cells 296 297 As development continues, we will work to expand the capabilities of the as_latex() method to 298 reduce these limitations and more clearly document what is and is not supported. 299 300 Examples 301 -------- 302 Let's use a subset of the gtcars dataset to create a new table. 303 304 {python} 305 from great_tables import GT 306 from great_tables.data import gtcars 307 import polars as pl 308 309 gtcars_mini = ( 310 pl.from_pandas(gtcars) 311 .select(["mfr", "model", "msrp"]) 312 .head(5) 313 ) 314 315 gt_tbl = ( 316 GT(gtcars_mini) 317 .tab_header( 318 title="Data Listing from the gtcars Dataset", 319 subtitle="Only five rows from the dataset are shown here." 320 ) 321 .fmt_currency(columns="msrp") 322 ) 323 324 gt_tbl 325 326 327 Now we can return the table as string of LaTeX code using the as_latex() method. 328 329 {python} 330 gt_tbl.as_latex() 331 332 333 The LaTeX string contains the code just for the table (it's not a complete LaTeX document). 334 This output can be useful for embedding a GT table in an existing LaTeX document. 335 """ 336 built_table = self._build_data(context="latex") 338 latex_table = _render_as_latex(data=built_table, use_longtable=use_longtable, tbl_pos=tbl_pos)

File d:\Python_Projects\FOF_CSV_PRACTICE\FOF_PENALTIES.venv\Lib\site-packages\great_tables_export.py:160, in as_raw_html(self, make_page, all_important) 129 def as_raw_html( 130 self: GT, 131 inline_css: bool = False, 132 make_page: bool = False, 133 all_important: bool = False, 134 ) -> str: 135 """ 136 Get the HTML content of a GT object. 137 138 Get the HTML content from a GT object as a string. By default, the generated HTML will have 139 inlined styles, where CSS styles (that were previously contained in CSS rule sets external to 140 the <table> element are included as style attributes in the HTML table's tags. This option is 141 preferable when using the output HTML table in an emailing context. 142 143 Parameters 144 ---------- 145 gt 146 A GT object. 147 inline_css 148 An option to supply styles to table elements as inlined CSS styles. This is useful when 149 including the table HTML as part of an HTML email message body, since inlined styles are 150 largely supported in email clients over using CSS in a <style> block. 151 make_page 152 An option to wrap the table in a complete HTML page. This is useful when you want to display 153 the table in a web browser. 154 155 Returns 156 ------- 157 str 158 An HTML fragment containing a table. 159 --> 160 Examples: 161 ------ 162 Let's use a subset of the gtcars dataset to create a new table. 163 164 {python} 165 from great_tables import GT, md, style, loc 166 from great_tables.data import gtcars 167 import polars as pl 168 169 gtcars_mini = ( 170 pl.from_pandas(gtcars) 171 .select(["mfr", "model", "msrp"]) 172 .head(5) 173 ) 174 175 gt_tbl = ( 176 GT(gtcars_mini) 177 .tab_header( 178 title=md("Data listing from **gtcars**"), 179 subtitle=md("gtcars is an R dataset") 180 ) 181 .tab_style( 182 style=style.fill(color="LightCyan"), 183 locations=loc.body(columns="mfr") 184 ) 185 .fmt_currency(columns="msrp") 186 .tab_options( 187 heading_background_color="Azure", 188 table_body_hlines_color="Lavender", 189 table_body_hlines_width="2px" 190 ) 191 .opt_horizontal_padding(scale=2) 192 ) 193 194 gt_tbl 195 196 197 Now we can return the table as an HTML string using the as_raw_html() method. 198 199 {python} 200 gt_tbl.as_raw_html() 201 202 203 The HTML string contains the HTML for the table. It has only the table so it's not a complete 204 HTML document but rather an HTML fragment. While this useful for embedding a table in an 205 existing HTML document, you could also use the make_page=True argument to get a complete HTML 206 page with the table contained within. 207 208 {python} 209 gt_tbl.as_raw_html(make_page=True) 210 211 212 Should you want to include all of the CSS styles as inline styles, you can use inline_css=True 213 to get an HTML string with all CSS inlined into the HTML tags. 214 215 {python} 216 gt_tbl.as_raw_html(inline_css=True) 217 218 """ 220 built_table = self._build_data(context="html") 222 table_html = built_table._render_as_html( 223 make_page=make_page, 224 all_important=all_important, 225 )

File d:\Python_Projects\FOF_CSV_PRACTICE\FOF_PENALTIES.venv\Lib\site-packages\great_tables\gt.py:390, in _render_as_html(self, make_page, all_important) 381 else: 382 table_tag_open = f'<table style="{table_defs["table_style"]}" class="gt_table" data-quarto-disable-processing="{quarto_disable_processing}" data-quarto-bootstrap="{quarto_use_bootstrap}">' 384 html_table = f"""{table_tag_open}{table_colgroups} 385 386 {heading_component} 387 {column_labels_component} 388 389 {body_component} --> 390 {source_notes_component} 391 {footnotes_component} 392 393 """ 395 # Obtain the table_id value from the Options (might be set, might be None) 396 table_id = self._options.table_id.value

File d:\Python_Projects\FOF_CSV_PRACTICE\FOF_PENALTIES.venv\Lib\site-packages\great_tables_scss.py:152, in compile_scss(data, id, compress, all_important) 147 # Determine if there are any additional CSS statements 148 has_additional_css = ( 149 additional_css is not None and isinstance(additional_css, list) and len(additional_css) > 0 150 ) --> 152 # Ensure that list items in additional_css are unique and then combine statements while 153 # separating with \n; use an empty string if list is empty or value is None 154 if has_additional_css: 155 additional_css_unique = OrderedSet(additional_css).as_list()

File ~\AppData\Local\Programs\Python\Python311\Lib\string.py:121, in Template.substitute(self, mapping, **kws) 118 self._invalid(mo) 119 raise ValueError('Unrecognized named group in pattern', 120 self.pattern) --> 121 return self.pattern.sub(convert, self.template)

File ~\AppData\Local\Programs\Python\Python311\Lib\string.py:114, in Template.substitute..convert(mo) 112 named = mo.group('named') or mo.group('braced') 113 if named is not None: --> 114 return str(mapping[named]) 115 if mo.group('escaped') is not None: 116 return self.delimiter

KeyError: 'row_striping_background_color'`

If I add 'row_striping_background_color=None' to the tab_options (as I believe is required from here - https://posit-dev.github.io/great-tables/reference/GT.tab_options.html?) then I get the following error instead:

`--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[34], line 32 1 ( 2 GT(qb) 3 .tab_header( 4 title=md(" 🏈 Analysis by Position Group 🏈 "), ## add small footballs to the title. ## these characters cause issues when saving. 5 subtitle=md("2065 Regular Season") 6 ) 7 .fmt_image( 8 columns='Team', 9 path=analysis_path, 10 file_pattern="{}.png" 11 ) 12 .cols_align( 13 align="center", columns=None 14 ) 15 .cols_label( 16 Team = (" "), 17 Position_Group = (" "), 18 Intelligence = ("Intel"), 19 Performance_Grade = ("Performance"), 20 Current_Overall = ("Current"), 21 Future_Overall = ("Future"), 22 PenaltiesCommitted = ("Penalties"), 23 Pedigree_Percentage = ("Pedigree"), 24 Intelligence_vs_league_avg = ("Int"), 25 PenaltiesCommitted_vs_league_avg = ("Pen"), 26 Performance_Grade_vs_league_avg = ("Perf"), 27 Current_Overall_vs_league_avg = ("Curr"), 28 Future_Overall_vs_league_avg = ("Fut"), 29 Experience_vs_league_avg = ("Exp"), 30 Pedigree_Percentage_vs_league_avg = ("Pedigree") 31 ) ---> 32 .tab_options( 33 container_width = "100%", 34 heading_background_color="#990033", 35 table_border_top_color="#990033", 36 table_font_names="Calibri", 37 table_font_size="20px", 38 row_striping_background_color=None 39 ) 40 .tab_style( 41 style=style.fill( 42 color=map_colour_analysis), 43 locations=loc.body("Position_Group") 44 ) 45 .tab_style( 46 style=style.text( 47 color=text_colour_analysis), 48 locations=loc.body("Position_Group") 49 ) 50 .tab_spanner( 51 label=md('Cumulative'), 52 columns=['PenaltiesCommitted', 'Pedigree_Percentage'] 53 ) 54 .tab_spanner( 55 label=md('Group Averages'), 56 columns=['Intelligence', 'Performance_Grade', 'Current_Overall', 'Future_Overall', 'Experience'] 57 ) 58 .tab_spanner( 59 label=md('Versus League Average'), ### MAYBE THE ORDER HERE NEEDS TO BE CHANGED TO HAVE PENALTIES SECOND LAST LIKE THE LEFT HAND COLUMNS? 60 columns=['Intelligence_vs_league_avg', 'Performance_Grade_vs_league_avg', 'Current_Overall_vs_league_avg', 'Future_Overall_vs_league_avg', 'Experience_vs_league_avg','PenaltiesCommitted_vs_league_avg', 'Pedigree_Percentage_vs_league_avg'] 61 ) 62 .fmt_percent(['Intelligence_vs_league_avg', 'PenaltiesCommitted_vs_league_avg', 'Performance_Grade_vs_league_avg', 'Current_Overall_vs_league_avg', 'Future_Overall_vs_league_avg', 'Experience_vs_league_avg', 'Pedigree_Percentage_vs_league_avg'], decimals=1, drop_trailing_zeros=True, scale_values=False) 63 .data_color( 64 columns=['Intelligence_vs_league_avg', 'Performance_Grade_vs_league_avg', 'Current_Overall_vs_league_avg', 'Future_Overall_vs_league_avg', 'Experience_vs_league_avg', 'Pedigree_Percentage_vs_league_avg'], # Target the "Diff" column 65 palette=["#FF0000", "#FFFF00", "#00FF00"], # Red to green gradient 66 domain=None # Automatically inferred from data 67 ) 68 .data_color( 69 columns=['PenaltiesCommitted_vs_league_avg'], 70 palette=["#FF0000", "#FFFF00", "#00FF00"], # Red to green gradient, 71 domain=None, 72 reverse=True 73 ) 74 .tab_style( 75 style=[ 76 style.fill(color="#EDEDED"), 77 #style.text(weight="bold") 78 ], 79 locations=loc.body(columns=['Intelligence', 'Performance_Grade', 'Current_Overall', 'Future_Overall', 'Experience'])) ## Does colouring and bolding actually help? 80 .tab_style( 81 style=[ 82 style.fill(color="#F7F7F7"), 83 ], 84 locations=loc.body(columns=['PenaltiesCommitted', 'Pedigree_Percentage']) 85 )).save("QB_Analysis.png", selector='table', scale=2.0, expand=0, web_driver='chrome', window_size=(6000, 6000), debug_port=None, _debug_dump=None)

TypeError: tab_options() got an unexpected keyword argument 'row_striping_background_color'`

I'll take a look again later but any advice in the meantime on getting around this would be great so I can test the fix

Thanks!

HansMellman avatar Mar 12 '25 10:03 HansMellman

It looks like row_striping_background_color= wasn't specified in GT.tab_options() in the original code. Could you try commenting out this parameter to see if the figure saves as expected?

jrycw avatar Mar 12 '25 11:03 jrycw

It wasn't included in the original code at all, that first error is triggered without the inclusion of the parameter - in the second attempt, I specify the parameter to 'None' and it presents me with that error - so with or without it I am getting errors.

HansMellman avatar Mar 12 '25 11:03 HansMellman

Thanks for the reply. That’s a weird error message, and I can’t reproduce it. Calling GT.tab_options() with the given parameters doesn’t seem to trigger this error using "v0.17.0", for example:

from great_tables import GT
from great_tables.data import exibble

GT(exibble).tab_options(
    container_width="100%",
    heading_background_color="#990033",
    table_border_top_color="#990033",
    table_font_names="Calibri",
    table_font_size="20px",
)

jrycw avatar Mar 12 '25 12:03 jrycw

Okay, so restarting my environment seems to have resolved that issue (the key error) - re ran the test cases for this issue and unfortunately it still persists, however it is inconsistent. I had it generate 6 tables, and 2/6 of them were affected by the extra whitespace at the bottom issue. This is still using the 'chrome' webdriver.

However, when run using the 'firefox' webdriver, all 6 tables were saved to .png without this issue.

HansMellman avatar Mar 12 '25 12:03 HansMellman

Appreciate the information! It looks like the JavascriptException is no longer occurring.

jrycw avatar Mar 12 '25 12:03 jrycw

Hello, I’m also having the same issue. Some pages in my table will randomly have whitespace at the bottom. I’ve tried adjusting the window size and would prefer not to install Firefox on a corporate environment to get a fix, are there any updates?

kazunefei avatar Jul 02 '25 21:07 kazunefei