Skip to content

Commit

Permalink
Add support to GET SUBSCRIPTS with cellrange names
Browse files Browse the repository at this point in the history
  • Loading branch information
enekomartinmartinez committed Jun 29, 2024
1 parent 5d27d61 commit 0dec08c
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 5 deletions.
40 changes: 38 additions & 2 deletions pysd/py_backend/external.py
Original file line number Diff line number Diff line change
Expand Up @@ -1067,9 +1067,45 @@ def get_subscripts_cell(self, row_first, col_first, lastcell):

return data

def get_subscripts_name(self, name):
def get_subscripts_name(self, cellname):
"""Get subscripts from cell range name definition"""
raise NotImplementedError
excel = load_workbook(self.file, read_only=True, data_only=True)
global_cellranges = excel.defined_names
local_cellranges = None
# need to lower the sheetnames as Vensim has no case sensitivity
for sheet in excel.sheetnames:
if sheet.lower() == self.sheet.lower():
local_cellranges = excel[sheet].defined_names
break

if local_cellranges is None:
# Error if it is not able to get the localSheetId
raise ValueError(
self.py_name + "\n"
"The sheet doesn't exist...\n"
+ self._file_sheet
)
try:
# Search for local and global names
cellrange = local_cellranges.get(cellname)\
or global_cellranges.get(cellname)
sheet, cells = next(cellrange.destinations)

assert sheet.lower() == self.sheet.lower()
self.sheet = sheet # case insensitivity in sheet name

# Get the cells where the cellrange is defined
first_cell, last_cell = cells.replace("$", '').split(":")
except (AttributeError, AssertionError):
# key error if the cellrange doesn't exist in the file or sheet
raise AttributeError(
self.py_name + "\n"
f"The cellrange name '{cellname}'\n"
"Doesn't exist in:\n" + self._file_sheet
)
else:
return self.get_subscripts_cell(
*self._split_excel_cell(first_cell), last_cell)

@staticmethod
def _not_nan(value):
Expand Down
Binary file modified tests/data/input.xlsx
Binary file not shown.
115 changes: 112 additions & 3 deletions tests/pytest_types/external/pytest_external.py
Original file line number Diff line number Diff line change
Expand Up @@ -1883,7 +1883,7 @@ def test_subscript_d2(self, _root):
sheet = "No monotonous"
firstcell = "H10"
lastcell = ""
prefix = 'j'
prefix = "j"
expected = ['j3', 'j2', 'j1', 'j6', 'j4', 'j8', 'j-1', 'j3', 'j2']

data = pysd.external.ExtSubscript(file_name=file_name,
Expand All @@ -1895,6 +1895,73 @@ def test_subscript_d2(self, _root):

assert data.subscript == expected

def test_subscript_name_h(self, _root):
"""
ExtSubscript test for horizontal subscripts
"""
import pysd

file_name = "data/input.xlsx"
sheet = "Horizontal missing"
firstcell = "time_missing"
lastcell = "B7"
prefix = "l"
expected = ['l0', 'l1', 'l2', 'l3',
'l5', 'l6', 'l7', 'l8']

data = pysd.external.ExtSubscript(file_name=file_name,
sheet=sheet,
root=_root,
firstcell=firstcell,
lastcell=lastcell,
prefix=prefix)

assert data.subscript == expected

def test_subscript_name_v(self, _root):
"""
ExtSubscript test for vertical subscripts
"""
import pysd

file_name = "data/input.xlsx"
sheet = "Horizontal"
firstcell = "vertical_index"
lastcell = ""
prefix = "p"
expected = ['pA', 'pB', 'pC']

data = pysd.external.ExtSubscript(file_name=file_name,
sheet=sheet,
root=_root,
firstcell=firstcell,
lastcell=lastcell,
prefix=prefix)

assert data.subscript == expected

def test_subscript_name_d(self, _root):
"""
ExtSubscript test for diagonal subscripts
"""
import pysd

file_name = "data/input.xlsx"
sheet = "Horizontal missing"
firstcell = "d_names"
lastcell = None
prefix = ""
expected = ['X', 'A', '0', 'B', '0', 'C', '1']

data = pysd.external.ExtSubscript(file_name=file_name,
sheet=sheet,
root=_root,
firstcell=firstcell,
lastcell=lastcell,
prefix=prefix)

assert data.subscript == expected


class TestWarningsErrors():
"""
Expand Down Expand Up @@ -2008,7 +2075,7 @@ def test_non_existent_cellrange_name_pyxl(self, _root):
final_coords=coords,
py_name=py_name)

error_message = "The cellrange name '.*'\nDoesn't exist in"
error_message = "The cellrange name 'non_exixtent'\nDoesn't exist in"
with pytest.raises(AttributeError, match=error_message):
data.initialize()

Expand All @@ -2032,7 +2099,7 @@ def test_non_existent_cellrange_name_in_sheet_pyxl(self, _root):
final_coords=coords,
py_name=py_name)

error_message = "The cellrange name '.*'\nDoesn't exist in"
error_message = "The cellrange name 'constant'\nDoesn't exist in"
with pytest.raises(AttributeError, match=error_message):
data.initialize()

Expand Down Expand Up @@ -3231,6 +3298,48 @@ def text_openpyxl_str(self, _root):

assert np.isnan(data.data)

def test_subscript_name_non_existent_sheet(self, _root):
"""
ExtSubscript test for diagonal subscripts
"""
import pysd

file_name = "data/input.xlsx"
sheet = "No exit"
firstcell = "d_names"
lastcell = None
prefix = ""

error_message = r"The sheet doesn't exist\.\.\."
with pytest.raises(ValueError, match=error_message):
pysd.external.ExtSubscript(file_name=file_name,
sheet=sheet,
root=_root,
firstcell=firstcell,
lastcell=lastcell,
prefix=prefix)

def test_subscript_name_non_existent_cellrange_name(self, _root):
"""
Test for non-existent cellrange name with openpyxl
"""
import pysd

file_name = "data/input.xlsx"
sheet = "Horizontal"
firstcell = "fake-cell"
lastcell = None
prefix = ""

error_message = "The cellrange name 'fake-cell'\nDoesn't exist in"
with pytest.raises(AttributeError, match=error_message):
pysd.external.ExtSubscript(file_name=file_name,
sheet=sheet,
root=_root,
firstcell=firstcell,
lastcell=lastcell,
prefix=prefix)


class DownwardCompatibility():
"""
Expand Down

0 comments on commit 0dec08c

Please sign in to comment.