读取 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的主要内容,如果未能解决你的问题,请参考以下文章