2

I'm creating and formatting excel files and want to wrap the text in column. I found the method in xlsxwriter which is text_wrap() but when I use this method, Its not working for me. I tried everything but failed.

What I'm doing in my script.

  • reading a csv using pandas
  • creating and saving dataframe into excel file
  • applying text wrap over it.

Script

text_format = workbook.add_format({'text_wrap': True})
worksheet.conditional_format('A1:W{}'.format(len(df)), {'type': 'no_errors',
                                      'format': text_format})

Any help will be appreciated.

Thanks

Hassan Mehmood
  • 1,414
  • 1
  • 14
  • 22

6 Answers6

5

As noted in the XlsxWriter docs, DataFrame formatting cannot be overwritten using set_row(). The easiest way to change the formatting of a DataFrame header is to overwrite the header with individual cell entries, overwriting the value and the format of each cell:

import pandas as pd
import xlsxwriter

df = pd.DataFrame({'this is a very long header that should wrap': ['a2', 'a3', 'a4'],
                   'header2': [1, 2, 3],
                   'header3': [4, 5, 6]})

writer = pd.ExcelWriter('test.xlsx', engine='xlsxwriter')
df.to_excel(writer, sheet_name='Sheet1', startrow=1, header=False)

workbook  = writer.book
worksheet = writer.sheets['Sheet1']
header_format = workbook.add_format({'bold': True, 'text_wrap': True, 'valign': 'top'})

# Overwrite both the value and the format of each header cell
for col_num, value in enumerate(df.columns.values):
    worksheet.write(0, col_num + 1, value, header_format)

workbook.close()

The code above will produce the following:

enter image description here

James Apple
  • 196
  • 1
  • 7
1

I have spent hours troubleshooting this same problem. I have tried the following:

header_format = workbook.add_format({'bold': True, 'text_wrap': True, 'valign': 'top'})

And setting it through its own statement:

header_format.set_text_wrap()

And adding a boolean to the statement:

header_format.set_text_wrap(True)

I thought maybe it was because I was using conditional formatting:

worksheet.conditional_format(0, 0, 0, 21, {'type': 'no_blanks', 'format': header_format})

So I tried it without:

worksheet.set_row(0, 45, testing_format)

I thought that maybe because it was coming before the statement setting column widths below it that perhaps it needed to be at the very end (even though no other format settings exhibit this behavior). That didn't work.

I tried to use one formatting with only text_wrap set and no other formatting and used in no other places. That didn't work.

I tried it with it being the only formatting set for the entire worksheet. That didn't work

I tried updating XlsxWririter to 1.3.7. That didn't work.

At this point I can say with 100% confidence that text wrapping does not work in XlsxWriter 1.3.7 with Python 3.7.4, and Excel for Microsoft 365 MSO 64-bit.

Jason
  • 75
  • 4
  • That is a high level of confidence. :-) Text wrap (or any other alignment properties) isn't supported by Excel for conditional formats. It just ignores it. However, text wrap should work everywhere else with XlsxWriter. Maybe add a small complete working example where you think it doesn't work. – jmcnamara Feb 17 '21 at 20:28
  • unfortunately, I'm a dealing with this same issue, though I'm using libre calc – naftalimich Feb 18 '21 at 18:59
  • re: above https://ask.libreoffice.org/en/question/179550/why-libreoffice-ignore-xlsxwriter-text_wrap-option-where-ms-excel-and-apache-openoffice-do-not/ this is my issue. i haven't tested it but likely it will work on excel – naftalimich Feb 18 '21 at 19:12
1

The reason this doesn't work is that Excel doesn't support text wrapping in a conditional format. From the XlsxWriter docs:

Note: In Excel, a conditional format is superimposed over the existing cell format and not all cell format properties can be modified. Properties that cannot be modified in a conditional format are font name, font size, superscript and subscript, diagonal borders, all alignment properties and all protection properties.

Outside of conditional formatting it should work as expected:

import xlsxwriter

workbook = xlsxwriter.Workbook('test.xlsx')
worksheet = workbook.add_worksheet()

my_format = workbook.add_format({'text_wrap': True})

worksheet.write(0, 0, "hello world, how are you", my_format)

workbook.close()

Output: enter image description here

jmcnamara
  • 38,196
  • 6
  • 90
  • 108
  • Interesting, this does work for me, however I still can't get it to work with even the simplest dataframes. Code below... – Jason Feb 19 '21 at 23:47
1

jmcnamara's example did work, however it will not work for data coming from a pandas dataframe. You can see it does the bold and the valign, but the wrap doesn't work. I also didn't have problem with conditional formatting (as long as it wasn't from a dataframe).

import pandas as pd
import xlsxwriter

df = pd.DataFrame({'this is a very long header that should wrap': ['a2', 'a3', 'a4'],
                   'header2': [1, 2, 3],
                   'header3': [4, 5, 6]})

writer = pd.ExcelWriter('test.xlsx', engine='xlsxwriter')

df.to_excel(writer, "Sheet1", index=False)
worksheet = writer.sheets['Sheet1']

workbook = writer.book

header_format = workbook.add_format({'bold': True, 'text_wrap': True, 'valign': 'top'})


worksheet.set_column(0, 0, 10)
worksheet.write(0, 3, "hello world, how are you")
worksheet.set_row(0, 70, header_format)

workbook.close()

enter image description here

Jason
  • 75
  • 4
  • The reason this happens is explained in the XlsxWriter docs along with a workaround. “Pandas writes the dataframe header with a default cell format. Since it is a cell format it cannot be overridden using set_row()”. See https://xlsxwriter.readthedocs.io/working_with_pandas.html#formatting-of-the-dataframe-headers – jmcnamara Feb 20 '21 at 01:03
1

When I changed from workbook.add_format().set_text_wrap()to workbook.add_format({'text_wrap': True})it worked as expected

rhoerbe
  • 463
  • 1
  • 4
  • 17
0

can not modify the type due to the format of dataframe format prohibition, you can clean the dataframe format in advance, then apply the cell format by set column or set row.

pandas.io.formats.excel.ExcelFormatter.header_style = None

  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 27 '22 at 18:50