我大约一年前写了一个python脚本,从那以后一直很好用。它使用来自ArcGIS arcpy 模块的搜索光标将我从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)
所以,当它试图写入excel的时候,我从oracle数据库中提取了一个特定的值:
sheet.Cells(excelrow,excelcol).Value = rowItem
所以,我打印出rowItem的值和类型,返回:
此时脚本已写入大约一百行日期值,因此这个值似乎非常特别。我不认为excel喜欢那一年的那一年。 1193.excel对datetime.datetime值的年份有限制吗?我无法看到它,但它是唯一真正想到的东西。
我知道这个值是错误的,因为我们对该特定数据库的记录不应超过~1890左右。改变价值需要花费更多的时间和精力(我为政府工作而不拥有数据库,因此我没有权利改变它)而且,我担心我会遇到更多的这些错误,所以我宁愿处理它们,然后改变它们。
这是一个更完整的脚本,我很快写下来测试它:
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
我试图转换为字符串:
str(rowItem)
但是这会带来一大堆新问题(其他值上的unicode错误等),所以我想解决这个问题。谁能看到可能导致此错误的是什么?
谢谢!
答案 0 :(得分:4)
正如您所怀疑的那样,问题是这一年。我用以下代码证实了这一点:
>>> 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的日期表示不能早于1/0/1900
。它表示日期的方式实际上是一个数字,因此早于1990年的日期将需要为负数。 Excel无法处理此问题,并为您提供错误消息。
如果您无法更改从数据源获取的日期,那么问题就变成了您希望如何处理它。有几种可能的选择,我建议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)
不幸的是,你不能直接捕获错误,所以你需要使用一个裸except
,但是这将花费800年到任何无法写入的日期。