Path:
strictdoc/backend/excel/import_/excel_sheet_proxy.py
Lines:
94
Non-empty lines:
81
Non-empty lines covered with requirements:
81 / 81 (100.0%)
Functions:
8
Functions covered by requirements:
8 / 8 (100.0%)
1
"""2
@relation(SDOC-SRS-152, scope=file)3
"""4
5
from enum import Enum
6
from typing import List
7
8
import openpyxl
9
import xlrd
10
11
from strictdoc.helpers.auto_described import auto_described
12
from strictdoc.helpers.cast import assert_cast
13
14
15
class ExcelLibType(Enum):
16
XLRD = 1
17
OPENPYXL = 2
18
19
20
@auto_described21
class ExcelSheetProxy:
22
"""
23
An adapter class to open xls(xlrd) or xlsx(openpyxl) with the same interface.24
"""25
26
def __init__(self, file: str):
27
self.file = file
28
if file.endswith(".xlsx"):
29
self.workbook = openpyxl.load_workbook(file)
30
self.sheet = self.workbook.active
31
if self.sheet is None: # pragma: no cover
32
raise RuntimeError(
33
"Couldn't open the first sheet of the workbook"34
)35
self.lib = ExcelLibType.OPENPYXL
36
elif file.endswith(".xls"):
37
self.workbook = xlrd.open_workbook(file, on_demand=True)
38
self.sheet = self.workbook.sheet_by_index(0)
39
self.lib = ExcelLibType.XLRD
40
else: # pragma: no cover
41
raise AssertionError("Unsupported file format")
42
43
@property44
def name(self) -> str:
45
"""
46
Returns the name of the first sheet.47
"""48
if self.lib == ExcelLibType.OPENPYXL:
49
return str(self.sheet.title)
50
elif self.lib == ExcelLibType.XLRD:
51
return str(self.sheet.name)
52
raise AssertionError
53
54
@property55
def ncols(self) -> int:
56
"""
57
The number of columns.58
"""59
if self.lib == ExcelLibType.OPENPYXL:
60
return assert_cast(self.sheet.max_column, int)
61
elif self.lib == ExcelLibType.XLRD:
62
return assert_cast(self.sheet.ncols, int)
63
raise AssertionError
64
65
@property66
def nrows(self) -> int:
67
"""
68
The number of rows.69
"""70
if self.lib == ExcelLibType.OPENPYXL:
71
return assert_cast(self.sheet.max_row, int)
72
elif self.lib == ExcelLibType.XLRD:
73
return assert_cast(self.sheet.nrows, int)
74
raise AssertionError
75
76
def get_cell_value(self, row: int, col: int) -> str:
77
"""
78
Returns the value at row/col as string.79
"""80
if self.lib == ExcelLibType.OPENPYXL:
81
return self.sheet.cell(row=row + 1, column=col + 1).value or ""
82
elif self.lib == ExcelLibType.XLRD:
83
return assert_cast(self.sheet.cell_value(row, col), str)
84
raise AssertionError
85
86
def row_values(self, row: int) -> List[str]:
87
"""
88
Returns a full row as list.89
"""90
if self.lib == ExcelLibType.OPENPYXL:
91
return [(cell.value or "") for cell in self.sheet[row + 1]]
92
elif self.lib == ExcelLibType.XLRD:
93
return assert_cast(self.sheet.row_values(row), list)
94
raise AssertionError