【问题标题】:csv module writes time as decimalcsv 模块将时间写入十进制
【发布时间】:2012-11-02 01:45:52
【问题描述】:

我遇到了一个问题,我在 .xls 文件中有一些数据(下面的示例)。

  A            B           C         D         E        F
John Smith     8:00AM      9:00AM    10:00AM    5:00PM  8.00

当我使用 Python CSV 模块将其写入 csv 时,结果为

John,Smith,0.333333333,0.375,0.416666667,0.708333333,0.333333333

现在有趣的部分是,如果我手动将 xls 文件保存为 MSDOS csv,我会得到所需的输出

John,Smith,8:00 AM,9:00 AM,10:00 AM,5:00 PM,8:00

这是我正在运行的函数。它有点混乱,所以我提前道歉。

def csv_gen(filepath, saveto):
    for files in glob.glob("*.xls"):
        shutil.copy(filepath + "\\" + files, saveto)
        with xlrd.open_workbook(files) as wb:
            sh = wb.sheet_by_index(0)
            newfile = saveto + files[:-4] + '.csv'
            now = datetime.datetime.now()
            dates = now.strftime("%m-%d-%Y")
            filestart = [saveto + files]
            time = [dates]
            with open(newfile, 'wb') as f:
                c = csv.writer(f,delimiter=',')
                list =  range(sh.nrows)
                last = range(sh.nrows)[-1]
                list.remove(0)
                list.remove(3)
                list.remove(2)
                list.remove(1)
                list.remove(last)
                #Iterate through data and show values of the rows
                for r in list:
                    lines = sh.row_values(r)
                    del lines[:4]
                    stuff = lines + filestart + time
                    #Remove blanks so csv doesnt have uneeded data
                    if lines[0] is '':
                        del stuff[:]
                    #Write to csv file with new data
                    if any(field.strip() for field in stuff):
                        c.writerow(stuff)
            shutil.move(newfile, mergeloc)

我不明白为什么会这样。我已经尝试将方言标志添加到 csv 编写器为“excel”,但输出仍然相同。

更新:

如果我将文档保存为 csv,那么workBook.SaveAs(test.csv, 24) 编码 24 用于 MSDOS。我得到了所需的

输出
John,Smith,8:00 AM,9:00 AM,10:00 AM,5:00 PM,8:00

但是当 csv 模块抓取它并删除一些空白行并在最后删除一些东西时,它会写出这些行,这就是我再次得到小数的时候

John,Smith,0.333333333,0.375,0.416666667,0.708333333,0.333333333

csv 模块的目的是修改行和删除空白行。

更新

 for r in list: 
     cells = sh.row_values(r) 
     csv_row = cells[0] for col_value in cells[1:]:
         csv_row.append(datetime.time(*xlrd.xldate_as_tuple(col_value, 0)[3:])) 

添加了 row_values 以仅返回单元格的值,而不是 xldata:0.33333。然后添加一个 * 以使传递成为位置参数。

【问题讨论】:

  • 请不要使用list作为变量名。这很令人困惑......
  • 对,我正在使用 xls 并转换为 csv 文件。他们使用它来跟踪个人的时间,然后我通过 csv 文件导入数据,因为我需要一个分隔文件
  • 我尝试这样做:import datetime; now = datetime.datetime.now(); dates = now.strftime("%m-%d-%Y"); time = [dates]; print time 我得到['11-13-2012'] 这是您期望的时间吗?
  • 抱歉,now = datetime.datetime.now() dates = now.strftime("%m-%d-%Y") 用于稍后在代码中附加另一列日期。
  • 如果您在lines = sh.row_values(r) 之后立即调用print lines,它会输出什么?你从sh.cell_type(0,1) 得到什么,或者你的第一个数据行的索引是什么,很难告诉你从工作表的开头删除一些行?

标签: python excel csv xlrd


【解决方案1】:

在我看来,csv 模块中的问题不是问题,读取 .xls 文件时似乎出了点问题。

根据 Excel 工作表中的xlrd docs 日期是一团糟

Excel 电子表格中的日期

实际上,没有这样的事情。你所拥有的是浮点数 数字和虔诚的希望。 Excel 日期有几个问题:

我使用您在其中提供的内容的新 .xls 文件进行了快速测试。 Python 读取文件没有问题,虽然我的机器上没有 Excel,但我在 LibreOffice 中制作了文件并将其保存为 .xls。即便如此,这些字段在 python 端还是以 unicode 字符串的形式出现。

您应该能够使用 xlrd.xldate_as_tuple(xldate, datemode) (link) 将浮点数转换为 python 日期元组。正在做

print xlrd.xldate_as_tuple(0.333333333,0)

打印出来

(0, 0, 0, 8, 0, 0)

更新

因此,您可能需要类似以下内容,更改遍历行的 for 循环

...
for r_idx in list:
    cells = sh.row(r)
    csv_row = [cells[0]] # the first row value should be ok as just a string
    for col_value in cells[1:]:
        # add the date time column values to the converted csv row
        csv_row.append( datetime.time(xlrd.xldate_as_tuple(col_value, 0)[3:]) )
    ...

【讨论】:

  • 嗯,所以我按照你的建议去做,然后停下来思考。如果我将文档保存为 csv,那么 workBook.SaveAs(test.csv, 24) 编码适用于 MSDOS。所以当我检查我有我想要的输出时。现在,当 csv 模块抓取它并删除一些空白行并在最后删除一些内容时,它会将行写出,这就是我再次获得小数的时候。
  • @thedemon 好吧,这可能应该在原始问题中出现。也许您应该编辑问题以包含thought
  • 好吧,我做了上面的事情 this-a1 = sh.cell_value(rowx=4, colx=6) a1_as_datetime = datetime.time(*xlrd.xldate_as_tuple(a1, 0)[3:] ) 在打印时我得到 08:00:00 这很好并且可以工作,但我对 python 还是有点陌生​​。迭代数据并更改单元格以获得我想要的结果的最佳方法是什么?
  • 感谢 sn-p 我可以看到它是如何工作的。但是,我确实做了一些更改,并希望分享以供将来参考和访问者使用。对于列表中的 r:单元格 = sh.row_values(r) csv_row = cells[0] 对于单元格中的 col_value[1:]:csv_row.append(datetime.time(*xlrd.xldate_as_tuple(col_value, 0)[3:]) ) 添加 row_values 以仅返回单元格的值,而不是 xldata:0.33333。然后添加一个 * 以使传递成为位置参数。
  • @thedemon 您应该将更改作为您问题的更新。没有人会在评论中找到它们。
猜你喜欢
  • 1970-01-01
  • 2017-02-24
  • 2014-03-16
  • 2018-09-10
  • 2014-02-11
  • 2018-05-30
  • 2011-12-22
  • 1970-01-01
  • 2012-04-10
相关资源
最近更新 更多