0

I have a dataframe, In that if the value is starting with letter "A" i'm styling it in red color, now i need to send it as html table in mail but when i execute it its coming without that styling, below is the code i tried please help. please check the image for df style

import os
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import pandas as pd

def color_failed(values):
    if values.startswith("A"):
        color="Red"
    else:
        color="yellow"

    return 'color: %s' % color

def test_mail():
    try:
        server=smtplib.SMTP()
        d={"One":["Abhi","Shek"],"two":["Arjun","Echo"],"three":["Virat","Gandalf"],"four":["Emma","Amma"]}
        df=pd.DataFrame(d)
        df.style.applymap(color_failed)
 
        msg = MIMEMultipart()
        msg['Subject'] = "Testing"
        msg['From'] = mail_id
        msg['To']=mail_id
        html = """\
                    <html>
                        <head>Test Email
                        <style>
                        </style>
                        </head>
                            <body>
                                {0}
                            </body>
                    </html>
                """.format(df.to_html())

        email_body = MIMEText(html, 'html')
        msg.attach(email_body)

        server.sendmail(mail_id, mail_id, msg.as_string())

enter image description here

3
  • Have you checked this thread? Commented Oct 14, 2022 at 12:07
  • i just saw that now, i believe that in that thread they are editing the header background colour, say i had a similar line line of replace for code for <td> element, the style would be effective for whole table right?,,, i have df in which "Abhi" "Amma" and "Arjun" are in red colour, i want to maintain the same style of font color in the html as well Commented Oct 14, 2022 at 12:32
  • df.to_html() always gives HTML without styles. You may add some parameters in to_html(....) - but this need to read documentation for to_html(). But for more complex table you may have to format it on your own (using for-loops to work with every row and column separatelly). Commented Oct 14, 2022 at 17:09

1 Answer 1

0

EDIT:

I found you can assign styled dataframe to variable and use .to_html() on this dataframe.

def color_failed(values):
    if values.startswith("A"):
        color = "red"
    else:
        color = "yellow"

    return f'color: {color}'

df_styled = df.style.applymap(color_failed)

print(df_styled.to_html())       # display HTML

df_styled.to_html('index.html')  # save in file

OLD ANSWER:

df.to_html() always gives HTML without styles.

You may add some parameters in to_html(....) to change something. See doc for to_html().

You may use formatters to convert value into <div style="color: red">value</div>. It may need escape=False to put it as HTML in table.

def color_failed(value):
    if value.startswith("A"):
        color = "red"
    else:
        color = "yellow"

    return f'<div style="color: {color}">{value}</div>'

df.to_html(formatters=[color_failed, color_failed, color_failed, color_failed], escape=False)

Every column need own formatter so I repeated it 4 times in list.

Because email is not important in this problem so I skip it and I save data in file index.html and I use webbrowser to show it automatically in browser.

import pandas as pd

def color_failed(value):
    if value.startswith("A"):
        color = "red"
    else:
        color = "yellow"

    return f'<div style="color: {color}">{value}</div>'

data = {
    "one": ["Abhi", "Shek"],
    "two": ["Arjun", "Echo"],
    "three": ["Virat", "Gandalf"],
    "four": ["Emma", "Amma"]
}

df = pd.DataFrame(data)

print(df.to_html(formatters=[color_failed, color_failed, color_failed, color_failed], escape=False))

# --- show in web browser ---

df.to_html('index.html', formatters=[color_failed, color_failed, color_failed, color_failed], escape=False)

import webbrowser
webbrowser.open('index.html')

Result:

<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>one</th>
      <th>two</th>
      <th>three</th>
      <th>four</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td><div style="color: red">Abhi</div></td>
      <td><div style="color: red">Arjun</div></td>
      <td><div style="color: yellow">Virat</div></td>
      <td><div style="color: yellow">Emma</div></td>
    </tr>
    <tr>
      <th>1</th>
      <td><div style="color: yellow">Shek</div></td>
      <td><div style="color: yellow">Echo</div></td>
      <td><div style="color: yellow">Gandalf</div></td>
      <td><div style="color: red">Amma</div></td>
    </tr>
  </tbody>
</table>

enter image description here


For more complex table you may have to format it on your own (using for-loops to work with every row and column separatelly).

Sign up to request clarification or add additional context in comments.

1 Comment

i tried the old answer part and it worked as expected thanks a lot @furas

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.