2

I use StyleFrame to export from pandas to Excel.

Cells are formatted to 'wrap text' and 'shrink to fit' by default. (How) can I change these settings?

The API documentation describes that the utils module contains the most widely used values for styling elements and that is possible to directly use a value that is not present in the utils module as long as Excel recognises it.

What do I need to specify for Excel in this case? Of how/where can I find out what Excel expects? Many thanks in advance!

Examples of what I have tried:

This code works perfect:

sf.apply_column_style(cols_to_style=['A'], styler_obj=Styler(bg_color=utils.colors.blue))

But my problem is that I do not know what to change to switch off the text wrapping and shrink to fit options:

sf.apply_column_style(cols_to_style=['A'], styler_obj=Styler(text_control=wrap_text.none))        
NameError: name 'wrap_text' is not defined

sf.apply_column_style(cols_to_style=['A'], styler_obj=Styler(text_control=utils.wrap_text.none)) 
AttributeError: module 'StyleFrame.utils' has no attribute 'wrap_text'

sf.apply_column_style(cols_to_style=['A'], styler_obj=Styler(utils.wrap_text.none)) 
AttributeError: module 'StyleFrame.utils' has no attribute 'wrap_text'

sf.apply_column_style(cols_to_style=['A'], styler_obj=Styler(wrap_text=False))        
TypeError: __init__() got an unexpected keyword argument 'wrap_text'
Wouter
  • 1,296
  • 2
  • 14
  • 32

2 Answers2

3

As of version 1.3 it is possible to pass wrap_text and shrink_to_fit directly to Styler, for example no_wrap_text_style = Styler(wrap_text=False)

DeepSpace
  • 78,697
  • 11
  • 109
  • 154
2

The bad news is that you can't do it nicely in the current version.

The good news is that you can monkey patch it for now, and I'll expose an API for it in the next version.

from openpyxl.styles import (PatternFill, Style, Color, Border,
                             Side, Font, Alignment, Protection)
from StyleFrame import StyleFrame, Styler, utils

def my_create_style(self):
    side = Side(border_style=self.border_type, color=utils.colors.black)
    border = Border(left=side, right=side, top=side, bottom=side)
    return Style(font=Font(name=self.font, size=self.font_size, color=Color(self.font_color),
                           bold=self.bold, underline=self.underline),
                 fill=PatternFill(patternType='solid', fgColor=self.bg_color),
                 alignment=Alignment(horizontal='center', vertical='center',
                                     wrap_text=False,  # use True/False as needed
                                     shrink_to_fit=False,  # use True/False as needed
                                     indent=0),
                 border=border,
                 number_format=self.number_format,
                 protection=Protection(locked=self.protection))

Styler.create_style = my_create_style

# rest of code

Just keep in mind that this will change the behavior of all Styler objects. If you want finer control you can monkey patch individual Styler instances, but it will require a bit more creativity:

from functools import partial
# ... and rest of imports from above example

# same code as above

a_style = Styler(bg_color=utils.colors.blue)

# this needs to be done BEFORE applying
a_style.create_style = partial(my_create_style, a_style)
sf.apply_column_style(cols_to_style=['A'], styler_obj=a_style)
DeepSpace
  • 78,697
  • 11
  • 109
  • 154
  • Many thanks for the extensive answer as well as the StyleFrame solution itself of course, it is a great help!!! – Wouter Dec 13 '17 at 15:43