读取 xls,将所有日期转换为正确格式,-> 写入 csv

Posted

技术标签:

【中文标题】读取 xls,将所有日期转换为正确格式,-> 写入 csv【英文标题】:read xls, convert all dates into proper format, -> write to csv 【发布时间】:2015-02-19 14:50:58 【问题描述】:

我正在读取 excel 文件并将它们写成 csv。几列包含日期,这些日期在 Excel 中格式化为浮点数。在我写入 CSV 之前,所有这些字段都需要转换为正确的日期时间 (dd/mm/YY)。 我发现了一些关于它一般如何工作的好文章,但很难同时在打开的工作表中的所有行上工作。 (Python新手)

代码现在如下所示:

wb = xlrd.open_workbook(args.inname)
    xl_sheet = wb.sheet_by_index(0)
    print args.inname
    print ('Retrieved worksheet: %s' % xl_sheet.name)
    print outname

    # TODO: Convert xldate.datetime from the date fileds to propper datetime

    output = open(outname, 'wb')
    wr = csv.writer(output, quoting=csv.QUOTE_ALL)

    for rownum in xrange(wb.sheet_by_index(0).nrows):
        wr.writerow(wb.sheet_by_index(0).row_values(rownum))

    output.close()

我确定我必须更改“for rownum ....”行,但我正在努力做到这一点。我尝试了几个选项,但都失败了。

谢谢

【问题讨论】:

见***.com/a/311655/2327328 【参考方案1】:

在将其写入文件之前,您需要遍历该行,转换值。您确定它在for rownum 线附近是正确的:

# You need to know which columns are dates before hand
# you can't get this from the "type" of the cell as they 
# are just like any other number

date_cols = [5,16,23]

... # Your existing setup code here #

# write the header row (in response to OP comment)
headerrow = wb.sheet_by_index(0).row_values(0)
wr.writerow(headerrow)

# convert and write the data rows (note range now starts from 1, not 0)
for rownum in xrange(1,wb.sheet_by_index(0).nrows):
    # Get the cell values and then convert the relevant ones before writing
    cell_values = wb.sheet_by_index(0).row_values(rownum)
    for col in date_cols:
        cell_values[col] = excel_time_to_string(cell_values[col])

    wr.writerow(cell_values)

您在 excel_time_to_string() 函数中添加的确切内容取决于您 - @MarkRansom 的答案有一个合理的方法 - 或者您可以使用 xlrd 自己的包版本概述 in this answer.

例如:

def excel_time_to_string(xltimeinput):
    return str(xlrd.xldate.xldate_as_datetime(xltimeinput, wb.datemode))

* 编辑 *

在尝试后响应 cmets 中的帮助请求。这是excel_time_to_string()的更防错版本

def excel_time_to_string(xltimeinput):
    try:
        retVal = xlrd.xldate.xldate_as_datetime(xltimeinput, wb.datemode)
    except ValueError:
        print('You passed in an argument in that can not be translated to a datetime.')
        print('Will return original value and carry on')
        retVal = xltimeinput

    return retVal

【讨论】:

我无法确认这是否有效,因为我偶然发现了我显然需要跳过包含标题的第 1 列的问题。我得到一个“ValueError:int() 的无效文字,基数为 10:'Vertragsbeginn'”错误 是的 - 抱歉 - 应该放入一些内容以跳过第 1 行。这就是您的错误告诉您的内容(尝试转换字符串文字 'Vertragsbeginn' 将不起作用!)。从好的方面来说 - 看起来你的列号是正确的,因为 Vertragsbeginn 可能是一个日期,除非我的德语真的很糟糕。 :) 查看我的更新。注意 - 您可以通过更改 rownum 迭代的范围来设置跳过多行的条件。 太棒了,我自己同时发现了完全相同的代码,很高兴我不会太费劲,因为现在我得到了:ValueError: invalid literal for int() with base 10: ''。我相信这是因为并非所有单元格实际上都包含一个值,即如果尚未定义“合同结束日期”,则单元格为空白 您需要对空白单元格进行if 测试——无论是在for 循环中,还是在您使用的任何excel_time_to_string() 函数中。您可以通过简单的方式(例如if value != '':)执行此操作,或者使用except ValueError: 执行更全面的操作,例如put the translation code in a try-catch block,并让您的代码在无法进行翻译时简单地使用原始值。如果您愿意,我可以将代码放在答案中,但它可能会帮助您更多地了解自己 - 让我知道。 我现在尝试了几种可能的组合,但没有任何运气。正如一两次提到的:我是编程的完全新手(不仅仅是python),因此是一个比作者更好的编辑器:-) 我会很感激一些“额外的”提示。我喜欢自己找到它的想法,这是我一直更喜欢的,同时这个脚本只是一场噩梦。我想你知道我的意思.-) 谢谢【参考方案2】:

从 Excel 到 Python 的转换非常简单:

>>> excel_time = 42054.441953
>>> datetime.datetime(1899,12,30) + datetime.timedelta(days=excel_time)
datetime.datetime(2015, 2, 19, 10, 36, 24, 739200)

或者完全转换成字符串:

def excel_time_to_string(excel_time, fmt='%Y-%m-%d %H:%M:%S'):
    dt = datetime.datetime(1899,12,30) + datetime.timedelta(days=excel_time)
    return dt.strftime(fmt)

>>> excel_time_to_string(42054.441953)
'2015-02-19 10:36:24'
>>> excel_time_to_string(42054.441953, '%d/%m/%y')
'19/02/15'

【讨论】:

@Marc,我知道,这也是我在其他人中发现的,但我正在努力将其纳入上述代码(即在找到的每个日期执行“魔术”在每一行)。如前所述,我是 python 新手。谢谢 @AndreDieball 如xlrd 文档中所述,Excel 日期没有单独的类型,它们只是数字。我给你的例子是如何将浮点数转换为 Python datetime。我已经添加了将其转换为字符串的代码。

以上是关于读取 xls,将所有日期转换为正确格式,-> 写入 csv的主要内容,如果未能解决你的问题,请参考以下文章

如何正确地将数据帧的所有日期时间列转换为 iso 格式

oracle 时间格式转换的问题

如何将字符型数据转化成日期格式

BigInt不会转换为正确的日期格式

如何将所有日期格式转换为日期列的时间戳?

将日期字符串转换为正确的格式