0

我编写了一个脚本,可以更改 Excel 工作表中某个日期的值。当我使用 创建一个新的 excel 文件copy时,它会正确复制所有内容,但日期的年份部分除外。例如,它将从 2012 年 4 月 5 日到 2008 年 4 月 5 日。似乎所有日期都可以追溯到四年前。这是代码:

def exceledit():
#open excel sheet                                                           
import xlrd, xlwt, xlutils
import datetime
from xlutils.copy import copy
print 'Opening excel sheet...'
book = xlrd.open_workbook('test.xls', on_demand=True, formatting_info=True)
print 'Creating and editing new excel sheet...'
wbook = copy(book)
print 'Done creating new excel sheet'

sh = book.sheet_by_index(0)
#iterate through dates in excel sheet                                       
for colnum in range(sh.ncols):
    date = sh.cell_value(3, colnum+4)
    #if xlrd finds a date                                                   
    if date:
        #grab date data                                                     
        year, month, day, hour, minute, second =  xlrd.xldate_as_tuple(date\
    , book.datemode)
        #if dates are within the month currently being edited               
        if month == 04:
            #format excel date information to work with parkh dict          
            format =  str(month) + "/" + str(day) + "/" + str(year)        
            print 'Editing ' + format
            #clear cells to eliminate old information                       
            wbook.get_sheet(0).write(6, colnum+6, "")
            wbook.get_sheet(0).write(5, colnum+6, "")
    wbook.get_sheet(0).write(7, colnum+6, "")
            #iterate through hour segments for that day                     
            for x in parkh[format]:
                #if regular hours, insert in "HOURS" row                    
                if x[0] == 'Park Hours':
                    wbook.get_sheet(0).write(6, colnum+6, x[1])
                #if extra magic hours, insert in respective row             
                if x[0] == 'Extra Magic Hours':
                    #insert in morning row                                  
                    if int(x[1][0:1]) in range(2,9):
                        wbook.get_sheet(0).write(5, colnum+6, x[1])
                    #insert in evening row                                  
                    else:
                        wbook.get_sheet(0).write(7, colnum+6, x[1])

        if month == 05:
            break

print 'Done editing. Now saving...'
wbook.save('new.xls')
print 'new.xls saved'

知道为什么它可能会改变年份吗?我还没有看到其他人在其他地方有同样的问题。

4

2 回答 2

1

您显然有一个使用 1904 日期系统的输入 Excel 文件。您的直接问题是xlutils不支持正确复制这些文件。幸运的是,修复是单行的,您甚至可以在完成复制后自己在脚本中进行修复:

wbook = copy(book)
wbook.dates_1904 = book.datemode

这适用于复制日期,因为xlwt支持写入指定正在使用的日期模式的记录。

警告您使用 Worksheet.write() 写入文件的任何新日期值都不会正确写入,因为xlwt不幸的是,在将对象转换为 Excel 魔术浮点数时会忽略该设置dates_1904datetime.datedatetime.datetime

我已经编写并测试了一个替换整个Row.__excel_date_dt方法的修复程序。它将很快提交到新的xlwt存储库github。同时,如果您急需,这里是代码:

def __excel_date_dt(self, date):
    adj = False
    if isinstance(date, dt.date):
        if self.__parent_wb.dates_1904:
            epoch_tuple = (1904, 1, 1)
        else:
            epoch_tuple = (1899, 12, 31)
            adj = True
        if isinstance(date, dt.datetime):
            epoch = dt.datetime(*epoch_tuple)
        else:
            epoch = dt.date(*epoch_tuple)
    else: # it's a datetime.time instance
        epoch = dt.datetime(1900, 1, 1)            
        date = dt.datetime.combine(epoch, date)
    delta = date - epoch
    xldate = delta.days + delta.seconds / 86400.0
    # Add a day for Excel's missing leap day in 1900
    if adj and xldate > 59:
        xldate += 1
    return xldate    

警告试图通过在 Excel 中打开文件来将文件转换为 1900 系统,取消勾选 1904 配置项并保存文件不起作用-日期将超出 4 年。

似乎正常工作的是:

  • 在 Excel 中打开文件,将其另存为XML Spreadsheet 2003 (*.xml)... 这种格式以文本格式记录日期,例如 1999-12-31T23:59:59.999

  • 在文本编辑器中打开 XML 文件,找到这样的行
    <Date1904/>...

  • 在 Excel 中打开更改后的 XML 文件,
    应保留所有数据和格式,唯一的区别应该
    是不再勾选讨厌的 1904 框。然后您可以将其保存为 XLS 文件

于 2012-04-08T12:16:24.770 回答
0

我在 Excel 工作簿中体验过这一点,甚至没有使用 Python。当同一个文件在 Windows 和 Mac 之间传递时,日期可能会发生奇怪的事情尽管这不是典型的)。Excel for Windows 默认使用所谓的“1900”日期系统,而 Excel for Mac 默认使用“1904”日期系统。(这些是各个系统的起始年份。)

尽管 xlrd 文档和源代码强烈建议您坚持使用datemode工作簿中编码的值(就像您所做的那样),但我认为值得尝试明确地给出“其他”模式以xldate_as_tuple查看它是否可以解决您的问题:

year, month, day, hour, minute, second = xlrd.xldate_as_tuple(date,
    1 - book.datemode)

datemode0适用于 1900 模式,1适用于 1904 模式;1 - datemode翻转这个。

顺便说一句,只要在括号表达式中的逗号后换行,就可以不使用反斜杠换行。

于 2012-04-05T22:56:09.803 回答