How to format bot 'send_message' output so it aligns like a table?
Asked Answered
E

2

6

I'm trying to create a simple Telegram Bot using the python-telegram-bot library, but i can't align a dictionary with the default "{0:<20} {1}".format(key, value) idea.

Let me give u an example:

Mapy = {
    "one": "1",
    "two": "2",
    "three": "3",
    "four": "4",
    "five": "5",
    "six": "6",
    "seven": "7",
    "eight": "8"
}

tmpstring = ""

for key, value in Mapy.items():
    tmpstring = tmpstring + "{0:<20} {1}".format(key, value) + "\n"

print(tmpstring)
context.bot.send_message(chat_id=update.message.chat_id, text=tmpstring)

the printed finish looks like this:

one                  1
two                  2
three                3
four                 4
five                 5
six                  6
seven                7
eight                8

as expected nicely aligned, but the message in Telegram looks like this:

enter image description here

So my question is: How can i align the chat message so it looks like the printed output?

Elaelaborate answered 7/5, 2019 at 20:59 Comment(0)
F
20

Use Markdowns (V2) 'pre-formatted fixed-width code block' to preserve the alignment. [Docs]

Wrap the wonderfully aligned table in a code-block using 3 back-ticks (```)

```
one          1
two          2
three        3
```

Send your message with the parse_mode option set to: MarkDown (V2)

Ferneferneau answered 8/5, 2019 at 11:45 Comment(3)
perfect, thanks, wrapping the String in "```" and using parse_mode="Markdown" in the send_message fixed my problem.Elaelaborate
@Elaelaborate Perfect! Keep in mind that the end users screen resolution decides if the table will show normal. I used to send some 3 column tables via Telegram. Smaller phones required landscape mode to see the table. I had te most trouble with iPhones users who could not see them, telegram wrapped the message, even in landscape!!Ferneferneau
When wrapping into ``` you can't add links into the text, like [one]('link.com/') because it will show up like a piece of code?Undertone
H
2

You can also use PrettyTable to build the layout instead of using spaces inside your code. The nice thing about this is you never have to worry about the spacing if you add more items to your response data that have variable widths.

This is also helpful when pulling in text from a data source such as an API, database, list, etc. (even taking it a step farther, if you are storing your users in a database, they could set their locale, and then you can convert it before sending: i.e 9,000.00 vs 9.000,00 etc.

Static Text Example:

    from prettytable import PrettyTable

    table = PrettyTable()
    table.field_names = ['Item', 'Price']
    table.add_row(['ham', '$3.99')
    table.add_row(['egg', '$2.99')
    table.add_row(['spam', 'Free!')
    
    response = '```\n{}```'.format(table.get_string())
    update.message.reply_text(response, parse_mode='Markdown')

Output:

+------+------------------+
| Item |      Price       |
+------+------------------+
| ham  |      $3.99       |
| egg  |      $2.99       |
| spam | Free Today Only! |
+------+------------------+

List Example:

    items = [
        ['ham', '$3.99'],
        ['egg', '$2.99'],
        ['spam', 'Free Today Only!']
    ]

    table = PrettyTable()
    table.field_names = ['Item', 'Price']
    for item in items:
        table.add_row(item)
    response = '```\n{}```'.format(table.get_string())
    update.message.reply_text(response, parse_mode='Markdown')

The table alignment can be set to r, l, c (Right, Left, or Center)

table.align = "r"

More info: https://pypi.org/project/prettytable/

Repository: https://github.com/jazzband/prettytable

Hammertoe answered 6/7, 2023 at 15:24 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.