34

I'm trying to change the text alignment to the center of 2 merged cells. I've found some answers that didn't work for my case:

currentCell = ws.cell('A1')
currentCell.style.alignment.horizontal = 'center' #TypeError: cannot set horizontal attribute
#or
currentCell.style.alignment.vertical = Alignment.HORIZONTAL_CENTER #AttributeError: type object 'Alignment' has no attribute 'HORIZONTAL_CENTER'

both didn't work, is there any other way to do it?

rleir
  • 791
  • 1
  • 7
  • 19
Pythonizer
  • 1,080
  • 4
  • 15
  • 25

6 Answers6

67

yes, there is a way to do this with openpyxl:

from openpyxl.styles import Alignment

currentCell = ws.cell('A1') #or currentCell = ws['A1']
currentCell.alignment = Alignment(horizontal='center')

hope this will help you

samsemilia7
  • 758
  • 1
  • 8
  • 10
12

This is what finally worked for me with the latest version from PIP (2.2.5)

    # center all cells
    for col in w_sheet.columns:
        for cell in col:
            # openpyxl styles aren't mutable,
            # so you have to create a copy of the style, modify the copy, then set it back
            alignment_obj = cell.alignment.copy(horizontal='center', vertical='center')
            cell.alignment = alignment_obj

Update:

As of openpyxl version 2.4.0 (~2016) the .copy() method is deprecated for StyleProxy objects.

Try changing the last two lines to:

from copy import copy
alignment_obj = copy(cell.alignment)
alignment_obj.horizontal = 'center'
alignment_obj.vertical = 'center'
cell.alignment = alignment_obj
johnDanger
  • 1,990
  • 16
  • 22
nmz787
  • 1,960
  • 1
  • 21
  • 35
5

None of the other solutions worked for me, since my solution requires openpyxl, and at least in 2.1.5 cell.alignment can't be set directly.

from openpyxl.styles import Style, Alignment

cell = ws.cell('A1')
cell.style = cell.style.copy(alignment=Alignment(horizontal='center')) 

The above copies the current style and replaces the alignment. You can also create a whole new style - with any values not specified taking the default values from https://openpyxl.readthedocs.org/en/latest/styles.html

cell.style = Style(alignment=Alignment(horizontal='center'),font=Font(bold=True))

# or - a tidier way

vals = {'alignment':Alignment(horizontal='center'),
        'font':Font(bold=True),
       }
new_style = Style(**vals)
cell.style = new_style
mhorne
  • 243
  • 3
  • 10
  • 2
    The `Style` class is no longer used; you assign to the individual style elements directly. For this example, you would assign `cell.font = Font(bold=True)` and `cell.alignment = Alignment(horizontal='center')` and (not in the example) `cell.fill = PatternFill(fgColor='33489F', fill_type='solid')` – hlongmore Jun 22 '18 at 02:09
  • @hlongmore Is it possible to assign to all cells within a column at once? – AsheKetchum Jul 18 '18 at 18:36
  • 1
    @AsheKetchum That's a good question; one I would have to figure out myself. If I find that you can, I'll update or add a new comment. – hlongmore Jul 18 '18 at 23:01
2

I found the following code to be a pretty simple way to format every cell in your worksheet:

tot_rows = ws.max_row #get max row number
tot_cols = ws.max_column #get max column number

cols = range(1,tot_cols) #turns previous variables into iterables
rows = range(1,tot_rows) 

for c in cols:
    for r in rows:
        ws.cell(row=r, column=c).alignment = Alignment(horizontal='center', vertical='center')
1

its my first time posting anything here. So i found a way to align text using openpyxl, Alignment

i=3
while i < 253:
    cellc = ws.cell(row=i, column= 3)
    cellc.alignment = Alignment(horizontal="right")
    i+=1

I set i to be the start point then the len of my column

-2

You can achieve this by using Python XlsxWriter library.

import xlsxwriter

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

cell_format = workbook.add_format({'align': 'center'})

worksheet.merge_range('A1:B1', "")
worksheet.write_rich_string('A1','Example', cell_format)

workbook.close()

Here i have merged cells A1, B1 and added a cell format parameter which includes the align parameter assigned as center.

enter image description here

Tanveer Alam
  • 5,185
  • 4
  • 22
  • 43
  • 7
    Question title is «Hor[i]zontal text alignment in **openpyxl**», emphasis is mine. Please consider that my remark doesn't imply neither that you haven't answered part of the OP question, nor that the OP couldn't decide to switch to a different library and approve your answer. – gboffi Oct 31 '14 at 10:19
  • @gboffi I had worked on xlsxwriter which has great features for xls writing that's why i suggested this. Plus as it is mentioned as merging two cells and align it horizontal center which i achieved by this. So OP can think about switching library if nothing else works. – Tanveer Alam Oct 31 '14 at 10:25
  • 2
    In this case I think you have to use xlsxwriter as we don't support styles for merged cells in Openpyxl because the specification doesn't define how it should be handled. – Charlie Clark Oct 31 '14 at 19:21
  • 1
    @Tanveer: The use of `write_rich_string()` isn't required. You can get the same effect as follows: `worksheet.merge_range('A1:B1', "Example", cell_format)`. – jmcnamara Nov 01 '14 at 00:55
  • 2
    @Charlie: I'm not sure if it is specified but in practice the style for a merged range is applied to the string/number/formula in the first cell of the range and then to blank cells for the rest of the range. I implemented the Openpyxl merge cell handling in Pandas like that (via the Openpyxl API). XlsxWriter just does the same thing internally. – jmcnamara Nov 01 '14 at 01:03
  • 1
    @jmcnamara yeah, I've seen a bit of what Excel does. I see a problem with the created cells in a read/write situation: what about any values in such cells and how do you handle more complicated formatting such as borders? We have a couple of bugs related to this https://bitbucket.org/openpyxl/openpyxl/issue/348 Using the blank cell approach you can even apply completely different formatting to the cells which shows how much a hack it really is. :-( I'll submit a "defect report" to the ECMA for clarification. – Charlie Clark Nov 01 '14 at 12:25