在转换XLSX到CSV时保留时间戳

3 投票
1 回答
1722 浏览
提问于 2025-04-18 16:09

我正在尝试把一个文件夹里的所有XLSX文件转换成CSV格式。大部分都没问题,但我遇到了一个关于时间信息的列的问题。这个XLSX文件是由另一个我无法修改的程序生成的。不过,我希望在Excel中查看的时间和转换成CSV后在任何文本编辑器中看到的时间保持一致。

我的代码:

import csv
import xlrd
import os
import fnmatch
import Tkinter, tkFileDialog, tkMessageBox

def main():
    root = Tkinter.Tk()
    root.withdraw()
    print 'Starting .xslx to .csv conversion'
    directory = tkFileDialog.askdirectory()
    for fileName in os.listdir(directory):
        if fnmatch.fnmatch(fileName, '*.xlsx'):
            filePath = os.path.join(directory, fileName)
            saveFile = os.path.splitext(filePath)[0]+".csv"
            savePath = os.path.join(directory, saveFile)
            workbook = xlrd.open_workbook(filePath)
            sheet = workbook.sheet_by_index(0)
            csvOutput = open(savePath, 'wb')
            csvWriter = csv.writer(csvOutput, quoting=csv.QUOTE_ALL)
            for row in xrange(sheet.nrows):
                csvWriter.writerow(sheet.row_values(row))
            csvOutput.close()
    print '.csv conversion complete'

main()

补充一下细节,如果我在Excel中打开一个文件,我在时间列中看到的是:

00:10.3
00:14.2
00:16.1
00:20.0
00:22.0

但是在转换成CSV后,我在同一个位置看到的是:

0.000118981
0.000164005
0.000186227
0.000231597
0.000254861

感谢seanmhanson的回答 https://stackoverflow.com/a/25149562/1858351,我了解到Excel把时间以一天的小数形式存储。虽然我应该更好地学习和使用xlrd,但为了快速解决这个问题,我把这些时间转换成了秒,然后再从秒转换回原来的HH:MM:SS格式。以下是我的(可能不太好)代码,供有需要的人参考:

import csv
import xlrd
import os
import fnmatch
from decimal import Decimal
import Tkinter, tkFileDialog

def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

def seconds_to_hms(seconds):
    input = Decimal(seconds)
    m, s = divmod(input, 60)
    h, m = divmod(m, 60)
    hm = "%02d:%02d:%02.2f" % (h, m, s)
    return hm

def main():
    root = Tkinter.Tk()
    root.withdraw()
    print 'Starting .xslx to .csv conversion'
    directory = tkFileDialog.askdirectory()
    for fileName in os.listdir(directory):
        if fnmatch.fnmatch(fileName, '*.xlsx'):
            filePath = os.path.join(directory, fileName)
            saveFile = os.path.splitext(filePath)[0]+".csv"
            savePath = os.path.join(directory, saveFile)
            workbook = xlrd.open_workbook(filePath)
            sheet = workbook.sheet_by_index(0)
            csvOutput = open(savePath, 'wb')
            csvWriter = csv.writer(csvOutput, quoting=csv.QUOTE_ALL)
            rowData = []
            for rownum in range(sheet.nrows):
                rows = sheet.row_values(rownum)
                for cell in rows:
                    if is_number(cell):
                        seconds = float(cell)*float(86400)
                        hms = seconds_to_hms(seconds)
                        rowData.append((hms))
                    else:
                        rowData.append((cell))
                csvWriter.writerow(rowData)
                rowData = []
            csvOutput.close()
    print '.csv conversion complete'

main()

1 个回答

3

Excel把时间存储成一种浮点数,单位是天。你需要用XLRD来判断一个单元格是不是日期,然后再进行相应的转换。我对XLRD不太熟悉,但你可以试试下面这个方法,如果想保留前面的零,可以调整一下字符串格式:

if cell.ctype == xlrd.XL_CELL_DATE:
    try: 
        cell_tuple = xldate_as_tuple(cell, 0)
        return "{hours}:{minutes}:{seconds}".format(
            hours=cell_tuple[3], minutes=cell_tuple[4], seconds=cell_tuple[5])
    except (any exceptions thrown by xldate_as_tuple):
        //exception handling

XLRD中将日期转换为元组的方法的文档可以在这里找到: https://secure.simplistix.co.uk/svn/xlrd/trunk/xlrd/doc/xlrd.html?p=4966#xldate.xldate_as_tuple-function

如果你想了解类似的问题,可以看看这个问题的回答: Python: xlrd区分日期和浮点数

撰写回答