Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to format cell with datetime object of the form 'yyyy-mm-dd hh:mm:ss' in Excel using openpyxl

So, given:

dttm = datetime.datetime.strptime("2014-06-23 13:56:30", "%Y-%m-%d %H:%M:%S")
ws['A1'] = dttm

The result in excel is that the correct date-time is written to the cell (you can see it where you'd input formulas). BUT, the cell display format is only MM/DD/YYYY.

I need the cell to display like "6/23/2014 13:56" instead of just "6/23/2014".

How can I explicitly format the cell to accomplish this?

Thanks!

Edit

@alecxe This solution works and is exactly what I asked for. I would like to be able to save styles like the solution by @Woodham. Unfortunately it raises a typeError (see comment). Any suggestions?

like image 214
MothraDactyl Avatar asked Jun 23 '14 16:06

MothraDactyl


5 Answers

The simplest way to format a cell is using .number_format = "format" as in:

value = datetime.datetime.strptime("2014-06-23 13:56:30", "%Y-%m-%d %H:%M:%S")
cell = ws['A1']
cell.value = value
cell.number_format = 'YYYY MMM DD'

This is tested in openpyxl (2.2.2)

like image 199
Scott Roberts Avatar answered Oct 12 '22 21:10

Scott Roberts


from openpyxl import load_workbook
from openpyxl.styles import NamedStyle

xlsx_file = args.xlsx_file.name

# openning:
wb = load_workbook(filename = xlsx_file)


# create date style:
date_style = NamedStyle(name='date_style', number_format='DD.MM.YYYY HH:MM:MM')

# apply the style to the column H of the default sheet:
ws = wb.active
for row in ws[2:ws.max_row]:  # skip the header
    cell = row[7]             # column H
    cell.style = date_style

# saving:
wb.save(xlsx_file)

Edit: the above works for me, but somehow does not work on my coleagues machine. Converting the cell to string fixed that:

import datetime

from openpyxl import load_workbook
from openpyxl.styles import Alignment

xlsx_file = 'file.xlsx'

date_format = '%Y-%b-%d'

# openning:
wb = load_workbook(filename = xlsx_file)

# we also center align that column:
alignment = Alignment(horizontal='center')

# apply python date format to column H of the default sheet, and convert the column to Excel text:
ws = wb.active
for row in ws[2:ws.max_row]:        # skip the header
    cell = row[7]   # column H
    if isinstance(cell.value, datetime.datetime):
        cell.value = cell.value.strftime(date_format)
        cell.alignment = alignment

# saving:
wb.save(xlsx_file)

The same wrapped in a script:

#!/usr/bin/env python3

import argparse
import datetime

from openpyxl import load_workbook
from openpyxl.styles import Alignment


# ==============
## parsing args:

desc="""

Applies python date format to a given column of the xlsx file (default sheet) and converts the column to a Excel text format.

Dependencies:
pip3 install --user --upgrade openpyxl
"""

parser = argparse.ArgumentParser(description=desc, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('--version', action='version', version='%(prog)s 0.01')

parser.add_argument('-f', '--file',
                    help = "xlsx file",
                    dest = 'xlsx_file',
                    type = argparse.FileType('r'),
                    )

parser.add_argument('-c', '--column',
                    help = "column (starting from A) (default to %(default)s)",
                    dest = 'column',
                    type = str,
                    default = "A",
                    )

parser.add_argument('-d', '--date-format',
                    help = "date format to use, e.g. %%d.%%m.%%Y (default to %(default)s)",
                    dest = 'date_format',
                    type = str,
                    default = '%Y-%b-%d',
                    )

args = parser.parse_args()


# =========
## program:

xlsx_file = args.xlsx_file.name

column_number = sum(
    [ ord(char) - 97 + i*26  for i,char in enumerate(
        list( args.column.lower() )
        ) ]
)

# openning:
wb = load_workbook(filename = xlsx_file)

# we also center align that column:
alignment = Alignment(horizontal='center')

# apply python date format to a given column of the default sheet, and convert the column to Excel text:
ws = wb.active
for row in ws[2:ws.max_row]:        # skip the header
    cell = row[column_number]
    if isinstance(cell.value, datetime.datetime):
        cell.value = cell.value.strftime(args.date_format)
        cell.alignment = alignment

# saving:
wb.save(xlsx_file)
like image 26
Adobe Avatar answered Oct 12 '22 13:10

Adobe


For openpyxl 2.4.5 you'll no longer have access to NumberFormat and Style and will have to use NamedStyle. Here's some sample usage:

from openpyxl.styles import NamedStyle

date_style = NamedStyle(name='datetime', number_format='DD/MM/YYYY HH:MM:MM')
ws['A1'].style = date_style

Alternatively with the new NamedStyle class, you can set the style by the string name once NamedStyle has been instantiated:

from openpyxl.styles import NamedStyle

NamedStyle(name='custom_datetime', number_format='DD/MM/YYYY HH:MM:MM')
ws['A1'].style = 'custom_datetime'

Documentation here: https://openpyxl.readthedocs.io/en/stable/styles.html

like image 18
quetzaluz Avatar answered Oct 12 '22 20:10

quetzaluz


For openpyxl 2.3.4 the NumberFormat cannot be imported, but this code works to set the style:

from openpyxl.styles import Style

…
date_style = Style(number_format="DD/MM/YYYY HH:MM:MM")
ws['A1'].style = date_style
like image 1
Peconia Avatar answered Oct 12 '22 20:10

Peconia


I believe you will need to set a openpyxl.styles.Style on the cell(s) that you want to format.

Looking at the documentation here, something like this should work:

dttm = datetime.datetime.strptime("2014-06-23 13:56:30", "%Y-%m-%d %H:%M:%S")
s = Style(number_format=NumberFormat('dd-mm-yyyy h:mm:ss'))

ws['A1'] = dttm
ws['A1'].styles = s

Update: Style class is no longer used, for the solution refer to this answer.

like image 1
Woodham Avatar answered Oct 12 '22 21:10

Woodham