win32com有问题使用python写date值

我大约一年前写了一个python脚本,从那以后一直工作得很好。 它使用ArcGIS arcpy模块中的search光标将我从oracle数据库中提取的一些值写入excel spreasheet,然后使用win32com写入excel spreasheet

最近,我经历了一个错误,我认为我已经确定了这个问题。 错误如下:

sheet.Cells(excelrow,excelcol).Value = rowItem File "E:\sw_nt\Python27\ArcGIS10.1\lib\site-packages\win32com\client\__init__.py", line 474, in __setattr__ self._oleobj_.Invoke(*(args + (value,) + defArgs)) com_error: (-2147352567, 'Exception occurred.', (0, None, None, None, 0, -2146827284), None) 

所以,它挂在写一个特殊的价值,我从Oracle数据库拉当它试图写入excel的行:

 sheet.Cells(excelrow,excelcol).Value = rowItem 

所以,我打印出rowItem的值和types,它返回:

  • 值= 12/05/1193
  • 键入= datetime.datetime

这个脚本已经写了大约一百行左右的date值,所以这个值似乎是非常特殊的。 我不认为excel喜欢当年的那一年。 1193. excel是否对datetime.datetime值有一定的限制? 我看不到它,但它是唯一真正想到的东西。

我知道这个值是错误的,因为我们对这个特定数据库的logging不能超过1890年左右。 要改变这个价值需要花费更多的时间和精力(我为政府工作,不拥有数据库,所以我没有权利改变它)。另外,我恐怕会遇到更多的这些错误,所以我宁愿处理他们,然后改变他们。

下面是我写的一个更完整的脚本来testing它:

 import arcpy, win32com.client # Set a variable to an empty excel instance excel = win32com.client.Dispatch("Excel.Application") excel.Visible = True # Initialize a workbook within excel book = excel.Workbooks.Add() # Set first sheet in book and rename it for the report sheet = book.Worksheets(1) sheet.Columns(1).ColumnWidth = 30 x = r"path_to_Database" excelrow = 1 for row in arcpy.SearchCursor(x): sheet.Cells(excelrow,1).Value = row.WORK_START_DATE excelrow +=1 

我试图转换为string:

 str(rowItem) 

但是,这带来了一大堆新问题(在其他值unicode错误等),所以我想解决这个例子。 任何人都可以看到是什么可能导致这个错误?

谢谢!

问题是,正如你正确地怀疑的那样,这一年。 我用下面的代码证实了这一点:

 >>> d = datetime.datetime(1193, 12, 5) >>> sheet.Cells(1,1).Value = d Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Python27\lib\site-packages\win32com\client\__init__.py", line 474, in __setattr__ self._oleobj_.Invoke(*(args + (value,) + defArgs)) pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, None, None, None, 0, -2146827284), None) >>> d = datetime.datetime(1993, 12, 5) >>> sheet.Cells(1,1).Value = d >>> 

原因可能是因为Excel的date表示不能早于1/0/1900 。 它代表date的方式实际上是一个数字,所以早于1990年的date就需要是负数。 Excel不能处理这个,并给你一个错误消息。

如果你不能改变你从数据源得到的date,那么问题就变成了你想如何处理它。 有几个潜在的select,我build议try...except

 try: sheet.Cells(excelrow, 1).Value = row.WORK_START_DATE except: datetime.datetime(row.WORK_START_DATE.year + 800, row.WORK_START_DATE.month, row.WORK_START_DATE.day) 

不幸的是,你不能直接捕捉错误,所以你需要使用一个裸机,但是这会在任何不能写入的date上扔800年。