When using Jupyter, I noticed that newline characters were being displayed as raw instead of actual newlines. This issue seemed to be specific to Linux.
To fix this problem, I simply performed a text replace to eliminate all the \n
characters, which resolved the formatting error.
In addition, running the code directly in Python rather than through Jupyter provided the correct output from the beginning.
As an update, I decided to manage my HTML styling separately from pandas.
It appears that there is a compatibility concern between Microsoft Outlook (desktop) and the rendering of certain elements, although it displays correctly in Outlook365 and standalone HTML in Chrome.
Specifically, when attempting to highlight a row based on a single cell content, some cells weren't consistently highlighted in Outlook, causing an unintended effect where table borders didn't display properly.
Furthermore, there was one problematic cell even outside of Outlook, where the style attribute wasn't being created for unknown reasons.
After facing these challenges, I switched to using Beautiful Soup for adding HTML styling. Although I had no prior experience with Beautiful Soup, I managed to implement the solution within 20 minutes following hours of unsuccessful attempts with Pandas.
html_table = df.to_html(index=False, classes='table table-bordered')
soup = BeautifulSoup(html_table,'html.parser')
rows = soup.find("table", border=1).find("tbody").find_all("tr")
for row in rows:
last_col = row.find_all("td")[-1]
if last_col.get_text() != '':
row.attrs['style'] = 'background-color: yellow'
html_body += str(soup)
Initially hesitant about introducing another library, the ease of implementation with Beautiful Soup convinced me otherwise.
A modified approach, tailored for Outlook compatibility after thorough testing:
df = pd.DataFrame(np.random.randn(5, 4), columns=['a', 'b', 'c', 'd'])
html_table = df.to_html(classes='table table-bordered')
soup = BeautifulSoup(html_table,'html.parser')
table = soup.find("table", border=1)
elements = table.find_all(["td", "th"])
for e in elements:
e.attrs['style'] = 'border: 2px solid lightgrey;'
table.attrs['style'] = 'border-collapse: collapse; padding: 5px;'
html_body += str(soup)