diff --git a/xlsx/__init__.py b/xlsx/__init__.py index a4ac436..eaf5fa2 100644 --- a/xlsx/__init__.py +++ b/xlsx/__init__.py @@ -7,7 +7,7 @@ import re import zipfile -from xlsx.xldate import xldate_as_tuple +from xlsx.xldate import xldate_as_python from xlsx.formatting import is_date_format_string from xlsx.timemachine import UnicodeMixin @@ -153,9 +153,16 @@ def rowsIter(self): sheetDoc = self.workbook.domzip["xl/worksheets/sheet%d.xml" % self.id] sheetData = sheetDoc.find("{http://schemas.openxmlformats.org/spreadsheetml/2006/main}sheetData") # @type sheetData Element + rowCount = 0 for rowNode in sheetData: rowNum = int(rowNode.get("r")) rowCells = [] + + rowCount += 1 + while rowCount < rowNum: + yield rowCount, [] + rowCount += 1 + for columnNode in rowNode: colType = columnNode.get("t") cellId = columnNode.get("r") @@ -169,14 +176,14 @@ def rowsIter(self): stringIndex = columnNode[0].text data = self.workbook.sharedStrings[int(stringIndex)] #Built in date-formatted fields - elif cellS and re.match("^[\d\.]+$", columnNode[0].text): + elif cellS and columnNode[0].text and re.match("^[\d\.]+$", columnNode[0].text): if int(self.workbook.cellStyles[int(cellS)].get('numFmtId')) in range(14, 22+1): - data = xldate_as_tuple( + data = xldate_as_python( float(columnNode[0].text), datemode=0) elif (self.workbook.cellStyles[int(cellS)].get('numFmtId') in self.workbook.numFmts) \ and is_date_format_string(self.workbook.numFmts[self.workbook.cellStyles[int(cellS)].get('numFmtId')]): - data = xldate_as_tuple( + data = xldate_as_python( float(columnNode[0].text), datemode=0) else: diff --git a/xlsx/xldate.py b/xlsx/xldate.py index ed4efd0..23de093 100644 --- a/xlsx/xldate.py +++ b/xlsx/xldate.py @@ -18,6 +18,7 @@ # Noon on Gregorian 1900-03-01 (day 61 in the 1900-based system) is JDN 2415080.0 # Noon on Gregorian 1904-01-02 (day 1 in the 1904-based system) is JDN 2416482.0 +from datetime import date, datetime from xlsx.timemachine import int_floor_div as ifd _JDN_delta = (2415080 - 61, 2416482 - 1) @@ -53,6 +54,15 @@ class XLDateBadTuple(XLDateError): pass # @throws XLDateBadDatemode datemode arg is neither 0 nor 1 # @throws XLDateError Covers the 4 specific errors + +def xldate_as_python(xldate, datemode): + value = xldate_as_tuple(xldate, datemode) + if any(value[3:]): + return datetime(*value) + else: + return date(*value[:3]) + + def xldate_as_tuple(xldate, datemode): if datemode not in (0, 1): raise XLDateBadDatemode(datemode)