diff --git a/HISTORY.md b/HISTORY.md index aaccbb0..58de623 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -9,6 +9,7 @@ ### Bugfixes - Fixed a crash when exporting an empty string with the ReST format (#368) +- Error cells from imported .xls files contain now the error string (#202) ## 0.14.0 (2019-10-19) diff --git a/src/tablib/formats/_xls.py b/src/tablib/formats/_xls.py index 3fc94af..0533476 100644 --- a/src/tablib/formats/_xls.py +++ b/src/tablib/formats/_xls.py @@ -76,7 +76,10 @@ def import_set(dset, in_stream, headers=True): if (i == 0) and (headers): dset.headers = sheet.row_values(0) else: - dset.append(sheet.row_values(i)) + dset.append([ + val if typ != xlrd.XL_CELL_ERROR else xlrd.error_text_from_code[val] + for val, typ in zip(sheet.row_values(i), sheet.row_types(i)) + ]) def import_book(dbook, in_stream, headers=True): diff --git a/tests/files/errors.xls b/tests/files/errors.xls new file mode 100644 index 0000000..0869337 Binary files /dev/null and b/tests/files/errors.xls differ diff --git a/tests/test_tablib.py b/tests/test_tablib.py index 00b8214..695d13d 100755 --- a/tests/test_tablib.py +++ b/tests/test_tablib.py @@ -6,6 +6,8 @@ import doctest import json import pickle import unittest +from collections import OrderedDict +from pathlib import Path from uuid import uuid4 import tablib @@ -887,17 +889,34 @@ class TSVTests(BaseTestCase): self.assertEqual(tsv, self.founders.tsv) +class XLSTests(BaseTestCase): + def test_xls_format_detect(self): + """Test the XLS format detection.""" + in_stream = self.founders.xls + self.assertEqual(detect_format(in_stream), 'xls') + + def test_xls_import_with_errors(self): + """Errors from imported files are kept as errors.""" + xls_source = Path(__file__).parent / 'files' / 'errors.xls' + with xls_source.open('rb') as fh: + data = tablib.Dataset().load(fh.read()) + self.assertEqual( + data.dict[0], + OrderedDict([ + ('div by 0', '#DIV/0!'), + ('name unknown', '#NAME?'), + ('not available (formula)', '#N/A'), + ('not available (static)', '#N/A') + ]) + ) + + class XLSXTests(BaseTestCase): def test_xlsx_format_detect(self): """Test the XLSX format detection.""" in_stream = self.founders.xlsx self.assertEqual(detect_format(in_stream), 'xlsx') - def test_xls_format_detect(self): - """Test the XLS format detection.""" - in_stream = self.founders.xls - self.assertEqual(detect_format(in_stream), 'xls') - def test_xlsx_import_set(self): date_time = datetime.datetime(2019, 10, 4, 12, 30, 8) data.append(('string', '004', 42, 21.55, date_time))