Repository: SDXorg/pysd (language: python)

Issue:
Error reading Vensim model (parsimonious.exceptions.IncompleteParseError)
Hello,

I am not able to read a relatively complex Vensim model with eight model views. 

I tried two ways and neither worked.

1. Read the model with the default arguments:

model = pysd.read_vensim('C:\\Users\\...path...\\model.mdl')
*** TypeError: cannot unpack non-iterable NoneType object

2. Read the model with split_views = True

model = pysd.read_vensim('C:\\Users\\...path...\\model.mdl', split_views=True)
*** parsimonious.exceptions.IncompleteParseError: Rule 'line' matched in its entirety, but it didn't consume all the text. The non-matching portion of the text begins with '|14|BU|0-0-128' (line 1, column 71).

In case 2, the text '|14|BU|0-0-128' raising the error is located toward the end of the mdl file (in text view), having to do with the sketch information generated automatically by Vensim. In particular, the line is in a block related to the eighth and last view:
...
10,73,simulator mode,194,665,68,11,8,131,0,18,-1,0,0,0,-1--1--1,0-0-0,|14|BU|0-0-128
12,74,105057302,192,632,80,20,3,60,0,0,0,0,0,0
simulator mode,0,1,1
30,75,f1303_17 - Copy0027.bmp,370,641,79,29,8,3,0,0,-1,0,0,0
12,76,34931712,812,203,221,110,3,188,0,0,1,0,0,0
...

Thanks for any advice.


Discussion / hints:
Hi @mak63-dev,

Thanks for reporting this error.

Can you please try using either underline or bold font, but not both, and let us know if this solves the problem?

Thank you
Hi @mak63-dev 

Now the issue with `split_views` should be solved thanks to @rogersamso's contribution. But I am not sure about the first one. Could you test again with the last version in the master branch, please?
Hi Roger & Eneko,

Pulled the latest version from git and retried. Indeed now it no longer crashes with split_views where it was crashing before.

But with or without split_views it is now giving me the first error:


  File C:\miniconda3\Lib\site-packages\pysd\builders\python\subscripts.py:60 in subscripts
    self._subscripts[sub.name] = ExtSubscript(

  File C:\miniconda3\Lib\site-packages\pysd\py_backend\external.py:1022 in __init__
    row_last, col_last = self._split_excel_cell(lastcell)

TypeError: cannot unpack non-iterable NoneType object


I wonder if, as a workaround, I could edit the model in text mode and remove all the graphics related code that's generated automatically by Vensim toward the end, then load the bare model without the graphics. Would this work?

Thanks for any help.
Hi @mak63-dev,

The issue you have now does not seem to be related with the Vensim sketch. It looks like the issue is caused by the use of GET DIRECT SUBSCRIPT or GET XLS SUBSCRIPT in your model.

This function has the following signature `GET DIRECT SUBSCRIPT('file','tab',firstcell,'lastcell', 'prefix')`, and the error seems to be complaining about not being able to read the `lastcell` argument correctly.

Before anything else, please verify all uses of these functions in your model, and see if the arguments are pointing to the right Excel cell.

If you don't spot any potential issue, we can investigate further.

Thanks!
Hi Roger.

The model runs without problems in Vensim. There are no broken links to files or issues with reading the data.

Thanks
Hi @mak63-dev,

Unfortunately, the fact that the model runs in Vensim is actually not a guarantee. Vensim is quite flexible and non-opinionated, which can occasionally allow for certain bugs to arise.

Can you share a small sample of your code, or a toy model, where the stated functions are used, so that we can try to pinpoint where the error might originate?

Thanks
Thanks again Roger,

Sure, I use GET DIRECT SUBSCRIPT quite a bit, not using GET XLS SUBSCRIPT at all.

Here are all the instances in my model where I call this function. I hope it helps:
********************************************************
	.subscripts
********************************************************~
	|

store:
	GET DIRECT SUBSCRIPT( 'C:\\...\\cum_store.csv'\
		,'cum_store', 'a2', 'a', 's')
	~	Dmnl
	~	stores
	|
gitem:
	GET DIRECT SUBSCRIPT( 'C:\\...\\s_data.csv'\
		 , 's_data', 'a2', 'a', 'i')
	~	Dmnl
	~	all the product family items
	|
item:
	GET DIRECT SUBSCRIPT( 'C:\\...\\sales_17.csv'\
		,'sales_17', 'b1', '1', 'i')
	~	Dmnl
	~	active items in the current store
	|
fitem:
	GET DIRECT SUBSCRIPT( 'C:\\...\\pred_sales_17.csv'\
		,'pred_sales_17', 'b1', '1', 'i')
	~	Dmnl
	~	items carried by the currently simulated store with adequate data for a \
		forecast
	|

ditem:
	GET DIRECT SUBSCRIPT( 'C:\\...\\d_item_indices.csv'\
		,'d_item_indices', 'a1', '1', 'i')
	~	Dmnl
	~	all items with identical basic features requiring an additional \
		'other' feature
	|
fixed d item:
	GET DIRECT SUBSCRIPT( 'C:\\...\\d_item_indices.csv'\
		,'d_item_indices', 'a2', '2', 'i')
	~	Dmnl
	~	all items with identical basic features requiring an additional 'other' \
		feature
		          to differentiate
	|

free d item:
	GET DIRECT SUBSCRIPT( 'C:\\...\\d_items.csv'\
		,'d_items', 'b1', '1', 'i')
	~	Dmnl
	~	all items with identical basic features requiring an additional 'other' \
		feature
		          to differentiate
	|

brand:
	GET DIRECT SUBSCRIPT( 'C:\\...\\s_brands.csv'\
		,  's_brands', 'a1', 'a', 'b')
	~	Dmnl
	~		|

day of week:
	GET DIRECT SUBSCRIPT( 'C:\\...\\sales_dow_full.csv'\
		,'sales_dow_full', 'b1', '1', 'w')
	~	Dmnl
	~	day ow week index: 0 = Monday, 6 = Sunday
	|
single holiday:
	GET DIRECT SUBSCRIPT( 'C:\\...\\single_holidays.csv'\
		,  'single_holidays', 'a1', '', 'h')
	~	Dmnl
	~	single holiday id's
	|
double holiday:
	GET DIRECT SUBSCRIPT( 'C:\\...\\multi_holidays.csv'\
		,  'multi_holidays', 'a1', '1', 'h')
	~	Dmnl
	~	double holiday id's
	|

s p:
	GET DIRECT SUBSCRIPT( 'C:\\...\\s inputs\\s_p.csv'\
		,  's_p', 'a1', '', 'p')
	~	Dmnl
	~	   s p id's
	|
d p:
	GET DIRECT SUBSCRIPT( 'C:\\...\\m_p.csv'\
		,  'm_p', 'a1', '1', 'p')
	~	Dmnl
	~	   d p id's
	|




These are all. I hope it helps.
	



Looks like these might be the problems:

```
s p:
GET DIRECT SUBSCRIPT( 'C:\...\s inputs\s_p.csv'
, 's_p', 'a1', '', 'p')
~ Dmnl
~ s p id's
|

single holiday:
GET DIRECT SUBSCRIPT( 'C:\...\single_holidays.csv'
, 'single_holidays', 'a1', '', 'h')
~ Dmnl
~ single holiday id's
|
```


What is the problem with them? Do I need to specify the last cell instead of letting the default option with '' ?

> What is the problem with them? Do I need to specify the last cell instead of letting the default option with '' ?

Can you check if that fixes your problem?
I think the current implementation needs last_cell to be a full cell (letter + number), but Vensim also supports using only a letter or a number as last_cell and will read all the rows/columns starting from first_cell. It also supports only quotes to get everything to the right and below. Could check if we can give support for that easily. But in the case of the no info provided, we need to know how Vensim reads the subscripts (if column by column or row per row), could you send an example of how the subscripts in

```
s p:
GET DIRECT SUBSCRIPT( 'C:\...\s inputs\s_p.csv'
, 's_p', 'a1', '', 'p')
~ Dmnl
~ s p id's
|
```

are defined in the file, and how are they shown in Vensim?


In the example above, it would start from a1 and read horizontally in that row everything to the right.
Changing the model to check if it will run with the last cell specified
ok, as a quick check, I tried instead of using an empty quote for last cell to pass only a number (which basically says only read everything else in this row/column). This didn't work either.

So, if indeed both a letter and number are needed for the last cell, then all my uses in the model cause problems because I don't specify a last cell. Generally, it is often the case one needs to read an entire row, or column, and only occasionally read partly up to a certain cell. So it would be really helpful to support the 'defaults'. Also, often the files get modified and you don't want to have to change everything in the model.

Does it seem plausible that you might support this? Or I should be going through the files carefully to specify the last cell?
Further to this discussion, the Vensim manual explains clearly the convention here:

https://www.vensim.com/documentation/fn_get_direct_subscript.html
Hi, it should be easy to fix, I will try to do it this weekend
@mak63-dev could you please test with the version in #447 branch [update_extsubscript](https://github.com/SDXorg/pysd/tree/update_extsubscript)? This should solve the error with the subscripts reading.
Hi Eneko,

Thanks for taking the time to look into this.
Got the version from [update_extsubscript](https://github.com/SDXorg/pysd/tree/update_extsubscript) and tried with the updated code but I'm still getting the error:

  File C:\miniconda3\Lib\site-packages\pysd\pysd.py:155 in read_vensim
    py_model_file = ModelBuilder(abs_model).build_model()

  File C:\miniconda3\Lib\site-packages\pysd\builders\python\python_model_builder.py:42 in __init__
    SectionBuilder(section)

  File C:\miniconda3\Lib\site-packages\pysd\builders\python\python_model_builder.py:86 in __init__
    self.subscripts = SubscriptManager(

  File C:\miniconda3\Lib\site-packages\pysd\builders\python\subscripts.py:30 in __init__
    self.subscripts = abstract_subscripts

  File C:\miniconda3\Lib\site-packages\pysd\builders\python\subscripts.py:60 in subscripts
    self._subscripts[sub.name] = ExtSubscript(

  File C:\miniconda3\Lib\site-packages\pysd\py_backend\external.py:1022 in __init__
    row_last, col_last = self._split_excel_cell(lastcell)

TypeError: cannot unpack non-iterable NoneType object
Hi, for the error message seems that you are still running the version in `master` branch. Can you reinstall please? Note that two branches have the same version value, so some installers may not update. You may need to remove and install pysd again.
I uninstalled pysd, deleted the cloned repository and tried creating a new repository using github directly from

https://github.com/SDXorg/pysd/tree/update_extsubscript

I get an error message: "The repository does not seem to exist anymore. You may not have access, or it may have been deleted or renamed". Not sure why I'm getting this error, I can navigate to the URL via a browser.
I guess you are using GitHub Desktop, right? I cannot give support in that case as I have never used it.

But I guess you can clone https://github.com/SDXorg/pysd.git as usual and change the branch later somehow.  
I am not getting this to work. Switched to the right branch, rebuilt the library and still getting the same error. Can't tell from the version number either because it shows as 3.14.0
Maybe I'll wait until there is a proper commit to the master branch and then retry.
ok, I've made some 'progress'. I was able to build the library with the fix using the command

pip install git+https://github.com/SDXorg/pysd.git@update_extsubscript

Now I'm still getting an error, but its different. The new error is shown below:




  File C:\miniconda3\Lib\site-packages\pysd\pysd.py:155 in read_vensim
    py_model_file = ModelBuilder(abs_model).build_model()

  File C:\miniconda3\Lib\site-packages\pysd\builders\python\python_model_builder.py:42 in __init__
    SectionBuilder(section)

  File C:\miniconda3\Lib\site-packages\pysd\builders\python\python_model_builder.py:86 in __init__
    self.subscripts = SubscriptManager(

  File C:\miniconda3\Lib\site-packages\pysd\builders\python\subscripts.py:30 in __init__
    self.subscripts = abstract_subscripts

  File C:\miniconda3\Lib\site-packages\pysd\builders\python\subscripts.py:60 in subscripts
    self._subscripts[sub.name] = ExtSubscript(

  File C:\miniconda3\Lib\site-packages\pysd\py_backend\external.py:1023 in __init__
    subs = self.get_subscripts_cell(*split, lastcell)

  File C:\miniconda3\Lib\site-packages\pysd\py_backend\external.py:1057 in get_subscripts_cell
    data = pd.read_excel(

  File C:\miniconda3\Lib\site-packages\pandas\io\excel\_base.py:495 in read_excel
    io = ExcelFile(

  File C:\miniconda3\Lib\site-packages\pandas\io\excel\_base.py:1554 in __init__
    raise ValueError(

ValueError: Excel file format cannot be determined, you must specify an engine manually.
From the new errors, it looks like it's following a different sequence of function calls from before. Looks like it's trying to read an Excel file, whereas I am reading from a csv file...

Hi @mak63-dev 

I guess this is because your data is saved in `.csv` files.  If you do not have many of them, I recommend saving them as `.xls` or `.xlsx` files (and modifying the extension in the model). We currently don't support `.csv` files. I will be happy to add this support, but I may need much more time for it as it requires more testing and changing several things...
In any case, could you send an example of how your csv files are structured? I guess there are "single sheet" Excel files like, right? This would be useful to add support in the future
These are just generic ASCII files, like .txt files, with ',' separated fields (by default, or another delimiter if specified). They can be edited with any basic editor. For example, one of the subscripts in my model is

store:
GET DIRECT SUBSCRIPT( 'C:\...\cum_store.csv'
,'cum_store', 'a2', 'a', 's')
~ Dmnl
~ stores
|

and reads from a file that looks like below. The subscripts are read starting from a2 (the 0 under "store") and getting the entire rest of the column under "store"), so 0-36


store,sales,adj_demand,bln_demand,size,n_days
0,6882,6926.420891567252,5015.6241406813415,512610,1211
1,5152,5160.775240436563,3620.2224737404,344840,1211
2,10838,10935.854344420462,7418.75802080286,805095,1211
3,6144,6161.564397713924,4450.346809633231,461225,1210
4,3153,3157.246272382307,2505.6622639073153,224960,1210
5,7819,7827.275171393158,5858.803039091432,570555,1211
6,5147,5164.496326477711,3889.9110242162537,388890,1211
7,4270,4306.668807448917,3137.2245902833915,323000,1211
8,47,47.0,46.0,3220,23
9,2970,2987.6939192640207,2296.8029860273123,193595,1211
10,5092,5119.097781151385,3900.3549331543672,375855,1211
11,5481,5512.913215397109,3813.8797142453946,371420,1210
12,4260,4286.062469994591,3006.924140532463,296500,1211
13,7503,7521.613500453263,5354.54701040083,566745,1211
14,10741,10766.295464706822,7353.605591648074,718795,1211
15,9061,9105.655948747913,6298.244583340483,571185,1210
16,9166,9203.157634202667,6393.674736244693,603140,1211
17,4479,4479.097421736181,3458.046274138154,331845,1211
18,5478,5491.207385277128,4224.6919690112045,392475,1211
19,8772,8838.110820235639,6319.1057183255425,608790,1210
20,13502,13572.465658191284,9072.192451323506,940315,1211
21,7903,7927.488437386526,6035.300649347015,582340,1210
22,7275,7278.746759903979,5564.349337512386,517255,1211
23,8934,9003.209435190709,6485.4212763507485,630475,1211
24,11675,11708.48900788761,8205.882381217156,828680,1211
25,11199,11258.543534549684,7317.246797948742,722830,1211
26,6381,6421.164575818191,4593.035333592501,413230,1208
27,6065,6083.048459392475,4473.617360500059,413700,1211
28,8327,8374.455856338538,6037.90658134379,602455,1210
29,10037,10089.84025806295,7174.530543597178,678245,1211
30,5476,5493.474310183651,4158.94716915358,398455,1210
31,4818,4832.1704019372855,3590.267199013336,328960,1210
32,4358,4365.361536294854,3290.0887718982176,291365,1210
33,10285,10298.694127629757,7130.69191298495,748805,1211
34,10781,10800.077107968893,7365.527864461407,763030,1211
35,1393,1393.8571428559237,1155.7603009780075,74480,1210
36,3,3.0,3.0,210,4
I think I could try to implement them, both for subscripts and data, but it will take more time to release as testing will take time. But from the current implementation of GET functions should be easy to give support to this kind of files
right - it's also the corresponding methods for data :)

I have merged the updates in the `master`. I will develop the support for `csv` and `tab` files in a new branch during this week.
@mak63-dev could I use that data for testing?
sure, go ahead!
:)

Could you also try to export your file to a tab-separated file (.tab) and try the same example above in Vensim, but with the .tab? and the same with a .txt separated by whitespaces?

The model I'm testing uses many csv files and I'd have to change all of them to test. Let me build a test model that just reads subscripts and data from a csv file and will test with that. Probably tomorrow
Yes, that would be very useful so we can directly add to our testing suite. Sorry for asking you for that but I don't have access to Vensim anymore :S

Fix patch:
diff --git a/docs/tables/get_functions.tab b/docs/tables/get_functions.tab
index 996f490b..3cb138e8 100644
--- a/docs/tables/get_functions.tab
+++ b/docs/tables/get_functions.tab
@@ -1,9 +1,9 @@
 Vensim	Vensim example	Xmile	Xmile example	Abstract Syntax	Python Translation	Vensim comments	Xmile comments	Python comments
-GET XLS DATA	"GET XLS DATA('file', 'sheet', 'time_row_or_col', 'cell')"			"GetDataStructure('file', 'sheet', 'time_row_or_col', 'cell')"	pysd.external.ExtData(...)
-GET DIRECT DATA	"GET DIRECT DATA('file', 'sheet', 'time_row_or_col', 'cell')"			"GetDataStructure('file', 'sheet', 'time_row_or_col', 'cell')"	pysd.external.ExtData(...)
-GET XLS LOOKUPS	"GET XLS LOOKUPS('file', 'sheet', 'x_row_or_col', 'cell')"			"GetLookupsStructure('file', 'sheet', 'x_row_or_col', 'cell')"	pysd.external.ExtLookup(...)
-GET DIRECT LOOKUPS	"GET DIRECT LOOKUPS('file', 'sheet', 'x_row_or_col', 'cell')"			"GetLookupsStructure('file', 'sheet', 'x_row_or_col', 'cell')"	pysd.external.ExtLookup(...)
-GET XLS CONSTANTS	"GET XLS CONSTANTS('file', 'sheet', 'cell')"			"GetConstantsStructure('file', 'sheet', 'cell')"	pysd.external.ExtConstant(...)
-GET DIRECT CONSTANTS	"GET DIRECT CONSTANTS('file', 'sheet', 'cell')"			"GetConstantsStructure('file', 'sheet', 'cell')"	pysd.external.ExtConstant(...)
-GET XLS SUBSCRIPT	"GET XLS SUBSCRIPT('file', 'sheet', 'first_cell', 'last_cell', 'prefix')"				pysd.external.ExtSubscript(...)
-GET DIRECT SUBSCRIPT	"GET DIRECT SUBSCRIPT('file', 'sheet', 'first_cell', 'last_cell', 'prefix')"				pysd.external.ExtSubscript(...)
+GET XLS DATA	"GET XLS DATA('file', 'tab', 'time_row_or_col', 'cell')"			"GetDataStructure('file', 'tab', 'time_row_or_col', 'cell')"	pysd.external.ExtData(...)
+GET DIRECT DATA	"GET DIRECT DATA('file', 'tab', 'time_row_or_col', 'cell')"			"GetDataStructure('file', 'tab', 'time_row_or_col', 'cell')"	pysd.external.ExtData(...)
+GET XLS LOOKUPS	"GET XLS LOOKUPS('file', 'tab', 'x_row_or_col', 'cell')"			"GetLookupsStructure('file', 'tab', 'x_row_or_col', 'cell')"	pysd.external.ExtLookup(...)
+GET DIRECT LOOKUPS	"GET DIRECT LOOKUPS('file', 'tab', 'x_row_or_col', 'cell')"			"GetLookupsStructure('file', 'tab', 'x_row_or_col', 'cell')"	pysd.external.ExtLookup(...)
+GET XLS CONSTANTS	"GET XLS CONSTANTS('file', 'tab', 'cell')"			"GetConstantsStructure('file', 'tab', 'cell')"	pysd.external.ExtConstant(...)
+GET DIRECT CONSTANTS	"GET DIRECT CONSTANTS('file', 'tab', 'cell')"			"GetConstantsStructure('file', 'tab', 'cell')"	pysd.external.ExtConstant(...)
+GET XLS SUBSCRIPT	"GET XLS SUBSCRIPT('file', 'tab', 'first_cell', 'last_cell', 'prefix')"				pysd.external.ExtSubscript(...)
+GET DIRECT SUBSCRIPT	"GET DIRECT SUBSCRIPT('file', 'tab', 'first_cell', 'last_cell', 'prefix')"				pysd.external.ExtSubscript(...)
diff --git a/docs/whats_new.rst b/docs/whats_new.rst
index b61cf367..4a431a19 100644
--- a/docs/whats_new.rst
+++ b/docs/whats_new.rst
@@ -1,6 +1,6 @@
 What's New
 ==========
-v3.14.1 (2024/07/XX)
+v3.14.1 (2024/07/18)
 --------------------
 New Features
 ~~~~~~~~~~~~
@@ -15,8 +15,11 @@ Bug fixes
 ~~~~~~~~~
 - Support for :py:mod:`numpy` 2. (`@enekomartinmartinez <https://github.com/enekomartinmartinez>`_)
 - Allow multiple font styles in var names (:issue:`443`). (`@rogersamso <https://github.com/rogersamso>`_)
-- Allow Vensims GET DIRECT/XLS SUBSCRIPT when lastcell is not a cell value  (:issue:`443`). (`@enekomartinmartinez <https://github.com/enekomartinmartinez>`_)
-- Allow Vensims GET DIRECT/XLS SUBSCRIPT defined with cell range names  (:issue:`261`). (`@enekomartinmartinez <https://github.com/enekomartinmartinez>`_)
+- Allow Vensims GET DIRECT/XLS SUBSCRIPT when lastcell is not a cell value (:issue:`443`). (`@enekomartinmartinez <https://github.com/enekomartinmartinez>`_)
+- Allow Vensims GET DIRECT/XLS SUBSCRIPT defined with cell range names (:issue:`261`). (`@enekomartinmartinez <https://github.com/enekomartinmartinez>`_)
+- Translate filenames as raw :py:class:`str` to made them work properly for Windows paths (:issue:`443`). (`@enekomartinmartinez <https://github.com/enekomartinmartinez>`_)
+- Improve support for reading :py:class:`pysd.py_backend.external.External` from all the spreadsheet files includying those types from open software ('.odf', '.ods', '.odt'). (`@enekomartinmartinez <https://github.com/enekomartinmartinez>`_)
+- Improve support for reading :py:class:`pysd.py_backend.external.External` from CSV, TAB and any other kind of text file. (`@enekomartinmartinez <https://github.com/enekomartinmartinez>`_)
 
 Documentation
 ~~~~~~~~~~~~~
@@ -28,6 +31,10 @@ Internal Changes
 ~~~~~~~~~~~~~~~~
 - Fix CI tests. (`@rogersamso <https://github.com/rogersamso>`_)
 - Run CI coverage only on ubuntu and lowest Python. (`@enekomartinmartinez <https://github.com/enekomartinmartinez>`_)
+- Rename 'sheet' by 'tab' in :py:class:`pysd.py_backend.external.External` and related functions and classes to follow Vensim's nomenclature. (`@enekomartinmartinez <https://github.com/enekomartinmartinez>`_)
+- Add error message when no subscripts are read from :py:class:`pysd.py_backend.external.ExtSubscript` during the model building. (`@enekomartinmartinez <https://github.com/enekomartinmartinez>`_)
+- Add error message when a :py:class:`pysd.py_backend.external.External` cell/firstcell is interpreted as cellrange name but the input file is not a spreadsheet. (`@enekomartinmartinez <https://github.com/enekomartinmartinez>`_)
+- Improve parsing of quoted arguments in the vensim translator for external lookups and external subscripts. (`@enekomartinmartinez <https://github.com/enekomartinmartinez>`_)
 
 v3.14.0 (2024/04/24)
 --------------------
diff --git a/pysd/builders/python/python_expressions_builder.py b/pysd/builders/python/python_expressions_builder.py
index b207d3b9..1d685a51 100644
--- a/pysd/builders/python/python_expressions_builder.py
+++ b/pysd/builders/python/python_expressions_builder.py
@@ -891,7 +891,7 @@ def build(self, arguments: dict) -> Union[BuildAST, None]:
         """
         self.component.type = "Lookup"
         self.component.subtype = "External"
-        arguments["params"] = "'%s', '%s', '%s', '%s'" % (
+        arguments["params"] = "r'%s', '%s', '%s', '%s'" % (
             self.file, self.tab, self.x_row_or_col, self.cell
         )
         final_subs, arguments["subscripts"] =\
@@ -966,7 +966,7 @@ def build(self, arguments: dict) -> Union[BuildAST, None]:
         """
         self.component.type = "Data"
         self.component.subtype = "External"
-        arguments["params"] = "'%s', '%s', '%s', '%s'" % (
+        arguments["params"] = "r'%s', '%s', '%s', '%s'" % (
             self.file, self.tab, self.time_row_or_col, self.cell
         )
         final_subs, arguments["subscripts"] =\
@@ -1041,7 +1041,7 @@ def build(self, arguments: dict) -> Union[BuildAST, None]:
         """
         self.component.type = "Constant"
         self.component.subtype = "External"
-        arguments["params"] = "'%s', '%s', '%s'" % (
+        arguments["params"] = "r'%s', '%s', '%s'" % (
             self.file, self.tab, self.cell
         )
         final_subs, arguments["subscripts"] =\
diff --git a/pysd/builders/python/subscripts.py b/pysd/builders/python/subscripts.py
index 1ba8b4b2..51f0b321 100644
--- a/pysd/builders/python/subscripts.py
+++ b/pysd/builders/python/subscripts.py
@@ -59,11 +59,16 @@ def subscripts(self, abstract_subscripts: List[AbstractSubscriptRange]):
                 # subscript from file
                 self._subscripts[sub.name] = ExtSubscript(
                     file_name=sub.subscripts["file"],
-                    sheet=sub.subscripts["tab"],
+                    tab=sub.subscripts["tab"],
                     firstcell=sub.subscripts["firstcell"],
                     lastcell=sub.subscripts["lastcell"],
                     prefix=sub.subscripts["prefix"],
                     root=self._root).subscript
+
+                if not self._subscripts[sub.name]:
+                    raise ValueError(
+                        f"Subscript range '{sub.name}' empty:\n\t"
+                        + str(sub.subscripts))
             else:
                 raise ValueError(
                     f"Invalid definition of subscript '{sub.name}':\n\t"
diff --git a/pysd/py_backend/external.py b/pysd/py_backend/external.py
index 35e4ffae..5401d5f6 100644
--- a/pysd/py_backend/external.py
+++ b/pysd/py_backend/external.py
@@ -6,15 +6,22 @@
 
 import re
 import warnings
-import pandas as pd
+
+from openpyxl import load_workbook
+from openpyxl.utils.exceptions import InvalidFileException
+
 import numpy as np
 import xarray as xr
-from openpyxl import load_workbook
+import pandas as pd
+
 from . import utils
 from .data import Data
 from .lookups import Lookups
 
 
+_SPREADSHEET_EXTS = {'.xls', '.xlsx', '.xlsm', '.xlsb', '.odf', '.ods', '.odt'}
+
+
 class Excels():
     """
     Class to save the read Excel files and thus avoid double reading
@@ -22,19 +29,35 @@ class Excels():
     _Excels, _Excels_opyxl = {}, {}
 
     @classmethod
-    def read(cls, file_name, sheet_name):
+    def read(cls, file_name, tab):
         """
         Read the Excel file or return the previously read one
         """
-        if file_name.joinpath(sheet_name) in cls._Excels:
-            return cls._Excels[file_name.joinpath(sheet_name)]
+        if file_name.joinpath(tab) in cls._Excels:
+            return cls._Excels[file_name.joinpath(tab)]
         else:
+            # get the function to read the data based on its extension
+            read_kwargs = {}
+            ext = file_name.suffix.lower()
+            if ext in _SPREADSHEET_EXTS:
+                read_func = pd.read_excel
+                read_kwargs['sheet_name'] = tab
+            elif ext == '.csv':
+                read_func = pd.read_csv
+                if tab and not tab[0].isalnum():
+                    read_kwargs['sep'] = tab
+            else:
+                read_func = pd.read_table
+                if tab and not tab[0].isalnum():
+                    read_kwargs['sep'] = tab
+            # read the data
             excel = np.array([
                 pd.to_numeric(ex, errors='coerce')
                 for ex in
-                pd.read_excel(file_name, sheet_name, header=None).values
+                read_func(file_name, header=None, **read_kwargs).values
                 ])
-            cls._Excels[file_name.joinpath(sheet_name)] = excel
+            # save data for future retrievals
+            cls._Excels[file_name.joinpath(tab)] = excel
             return excel
 
     @classmethod
@@ -78,8 +101,9 @@ class External(object):
         fail, but it may be used to check the quality of the data.
     file: str
         File name from which the data is read.
-    sheet: str
-        Sheet name from which the data is read.
+    tab: str
+        Tab name from which the data is read. If file type is not a
+        spreadsheet this will be used as a separator.
 
     """
     missing = "warning"
@@ -87,7 +111,7 @@ class External(object):
     def __init__(self, py_name):
         self.py_name = py_name
         self.file = None
-        self.sheet = None
+        self.tab = None
 
     def __str__(self):
         return self.py_name
@@ -109,34 +133,27 @@ def _get_data_from_file(self, rows, cols):
             depending on the shape of the requested data
 
         """
-        ext = self.file.suffix.lower()
-        if ext in ['.xls', '.xlsx', '.xlsm']:
-            # read data
-            data = Excels.read(
-                self.file,
-                self.sheet)[rows[0]:rows[1], cols[0]:cols[1]].copy()
+        # read data
+        data = Excels.read(
+            self.file,
+            self.tab)[rows[0]:rows[1], cols[0]:cols[1]].copy()
 
-            shape = data.shape
+        shape = data.shape
 
-            # empty cells
-            if shape[0] == 0 or shape[1] == 0:
-                raise ValueError(
-                    self.py_name + "\n"
-                    "The cells are empty.\n"
-                    + self._file_sheet
-                )
-
-            # if it is a single row remove its dimension
-            if shape[1] == 1:
-                data = data[:, 0]
-            if shape[0] == 1:
-                data = data[0]
-            return data
+        # empty cells
+        if shape[0] == 0 or shape[1] == 0:
+            raise ValueError(
+                self.py_name + "\n"
+                "The cells are empty.\n"
+                + self._file_sheet
+            )
 
-        raise NotImplementedError(
-            self.py_name + "\n"
-            f"The files with extension {ext} are not implemented"
-        )
+        # if it is a single row remove its dimension
+        if shape[1] == 1:
+            data = data[:, 0]
+        if shape[0] == 1:
+            data = data[0]
+        return data
 
     def _get_data_from_file_opyxl(self, cellname):
         """
@@ -156,13 +173,23 @@ def _get_data_from_file_opyxl(self, cellname):
 
         """
         # read data
-        excel = Excels.read_opyxl(self.file)
+        try:
+            excel = Excels.read_opyxl(self.file)
+        except InvalidFileException:
+            raise ValueError(
+                self.py_name + "\n"
+                f"Cannot read the file '{self.file}'...\n"
+                f"It could happen that cell='{cellname}' was "
+                "read as a cell range name due to a wrong "
+                "definition of cell value"
+            )
+
         # Get global and local cellrange names
         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():
+            if sheet.lower() == self.tab.lower():
                 local_cellranges = excel[sheet].defined_names
                 break
 
@@ -179,8 +206,8 @@ def _get_data_from_file_opyxl(self, 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
+            assert sheet.lower() == self.tab.lower()
+            self.tab = sheet  # case insensitivity in sheet name
 
             # Get the cells where the cellrange is defined
             cells = re.split(r":|\$", cells)
@@ -573,7 +600,7 @@ def _file_sheet(self):
         Returns file and sheet name in a string
         """
         return "\tFile name:\t'{}'\n".format(self.file)\
-               + "\tSheet name:\t'{}'\n".format(self.sheet)
+               + "\tSheet name:\t'{}'\n".format(self.tab)
 
     @staticmethod
     def _col_to_num(col):
@@ -704,11 +731,11 @@ class ExtData(External, Data):
     Class for Vensim GET XLS DATA/GET DIRECT DATA
     """
 
-    def __init__(self, file_name, sheet, time_row_or_col, cell,
+    def __init__(self, file_name, tab, time_row_or_col, cell,
                  interp, coords, root, final_coords, py_name):
         super().__init__(py_name)
         self.files = [file_name]
-        self.sheets = [sheet]
+        self.tabs = [tab]
         self.time_row_or_cols = [time_row_or_col]
         self.cells = [cell]
         self.coordss = [coords]
@@ -725,13 +752,12 @@ def __init__(self, file_name, sheet, time_row_or_col, cell,
                              + "'raw', 'interpolate', "
                              + "'look_forward' or 'hold_backward'")
 
-    def add(self, file_name, sheet, time_row_or_col, cell,
-            interp, coords):
+    def add(self, file_name, tab, time_row_or_col, cell, interp, coords):
         """
         Add information to retrieve new dimension in an already declared object
         """
         self.files.append(file_name)
-        self.sheets.append(sheet)
+        self.tabs.append(tab)
         self.time_row_or_cols.append(time_row_or_col)
         self.cells.append(cell)
         self.coordss.append(coords)
@@ -753,9 +779,9 @@ def initialize(self):
         """
         if not self.coordss[0]:
             # Just load one value (no add)
-            for self.file, self.sheet, self.x_row_or_col, \
+            for self.file, self.tab, self.x_row_or_col, \
                 self.cell, self.coords\
-                in zip(self.files, self.sheets, self.time_row_or_cols,
+                in zip(self.files, self.tabs, self.time_row_or_cols,
                        self.cells, self.coordss):
                 self.data = self._initialize_data("data")
         else:
@@ -763,9 +789,9 @@ def initialize(self):
             self.data = xr.DataArray(
                 np.nan, self.final_coords, list(self.final_coords))
 
-            for self.file, self.sheet, self.x_row_or_col, \
+            for self.file, self.tab, self.x_row_or_col, \
                 self.cell, self.coords\
-                in zip(self.files, self.sheets, self.time_row_or_cols,
+                in zip(self.files, self.tabs, self.time_row_or_cols,
                        self.cells, self.coordss):
                 values = self._initialize_data("data")
 
@@ -789,11 +815,11 @@ class ExtLookup(External, Lookups):
     Class for Vensim GET XLS LOOKUPS/GET DIRECT LOOKUPS
     """
 
-    def __init__(self, file_name, sheet, x_row_or_col, cell, coords,
+    def __init__(self, file_name, tab, x_row_or_col, cell, coords,
                  root, final_coords, py_name):
         super().__init__(py_name)
         self.files = [file_name]
-        self.sheets = [sheet]
+        self.tabs = [tab]
         self.x_row_or_cols = [x_row_or_col]
         self.cells = [cell]
         self.coordss = [coords]
@@ -802,12 +828,12 @@ def __init__(self, file_name, sheet, x_row_or_col, cell, coords,
         self.interp = "interpolate"
         self.is_float = not bool(coords)
 
-    def add(self, file_name, sheet, x_row_or_col, cell, coords):
+    def add(self, file_name, tab, x_row_or_col, cell, coords):
         """
         Add information to retrieve new dimension in an already declared object
         """
         self.files.append(file_name)
-        self.sheets.append(sheet)
+        self.tabs.append(tab)
         self.x_row_or_cols.append(x_row_or_col)
         self.cells.append(cell)
         self.coordss.append(coords)
@@ -822,9 +848,9 @@ def initialize(self):
         """
         if not self.coordss[0]:
             # Just loag one value (no add)
-            for self.file, self.sheet, self.x_row_or_col, \
+            for self.file, self.tab, self.x_row_or_col, \
                 self.cell, self.coords\
-                in zip(self.files, self.sheets, self.x_row_or_cols,
+                in zip(self.files, self.tabs, self.x_row_or_cols,
                        self.cells, self.coordss):
                 self.data = self._initialize_data("lookup")
         else:
@@ -832,9 +858,9 @@ def initialize(self):
             self.data = xr.DataArray(
                 np.nan, self.final_coords, list(self.final_coords))
 
-            for self.file, self.sheet, self.x_row_or_col, \
+            for self.file, self.tab, self.x_row_or_col, \
                 self.cell, self.coords\
-                in zip(self.files, self.sheets, self.x_row_or_cols,
+                in zip(self.files, self.tabs, self.x_row_or_cols,
                        self.cells, self.coordss):
                 values = self._initialize_data("lookup")
 
@@ -854,11 +880,11 @@ class ExtConstant(External):
     Class for Vensim GET XLS CONSTANTS/GET DIRECT CONSTANTS
     """
 
-    def __init__(self, file_name, sheet, cell, coords,
+    def __init__(self, file_name, tab, cell, coords,
                  root, final_coords, py_name):
         super().__init__(py_name)
         self.files = [file_name]
-        self.sheets = [sheet]
+        self.tabs = [tab]
         self.transposes = [
             cell[-1] == '*' and np.prod(utils.compute_shape(coords)) > 1]
         self.cells = [cell.strip('*')]
@@ -866,12 +892,12 @@ def __init__(self, file_name, sheet, cell, coords,
         self.root = root
         self.final_coords = final_coords
 
-    def add(self, file_name, sheet, cell, coords):
+    def add(self, file_name, tab, cell, coords):
         """
         Add information to retrieve new dimension in an already declared object
         """
         self.files.append(file_name)
-        self.sheets.append(sheet)
+        self.tabs.append(tab)
         self.transposes.append(
             cell[-1] == '*' and np.prod(utils.compute_shape(coords)) > 1)
         self.cells.append(cell.strip('*'))
@@ -887,8 +913,8 @@ def initialize(self):
         """
         if not self.coordss[0]:
             # Just loag one value (no add)
-            for self.file, self.sheet, self.transpose, self.cell, self.coords\
-                in zip(self.files, self.sheets, self.transposes,
+            for self.file, self.tab, self.transpose, self.cell, self.coords\
+                in zip(self.files, self.tabs, self.transposes,
                        self.cells, self.coordss):
                 self.data = self._initialize()
         else:
@@ -897,8 +923,8 @@ def initialize(self):
             self.data = xr.DataArray(
                 np.nan, self.final_coords, list(self.final_coords))
 
-            for self.file, self.sheet, self.transpose, self.cell, self.coords\
-                in zip(self.files, self.sheets, self.transposes,
+            for self.file, self.tab, self.transpose, self.cell, self.coords\
+                in zip(self.files, self.tabs, self.transposes,
                        self.cells, self.coordss):
                 self.data.loc[self.coords] = self._initialize().values
 
@@ -1012,10 +1038,10 @@ class ExtSubscript(External):
     Class for Vensim GET XLS SUBSCRIPT/GET DIRECT SUBSCRIPT
     """
 
-    def __init__(self, file_name, sheet, firstcell, lastcell, prefix, root):
+    def __init__(self, file_name, tab, firstcell, lastcell, prefix, root):
         super().__init__("Hardcoded external subscript")
         self.file = file_name
-        self.sheet = sheet
+        self.tab = tab
         self.prefix = prefix
         self._resolve_file(root=root)
         split = self._split_excel_cell(firstcell)
@@ -1054,10 +1080,26 @@ def get_subscripts_cell(self, row_first, col_first, lastcell):
         if col_last is not None:
             read_kwargs['usecols'] = np.arange(col_first, col_last+1)
 
-        data = pd.read_excel(
-            self.file, self.sheet,
-            skiprows=row_first-1,
+        # get the function to read the data based on its extension
+        ext = self.file.suffix.lower()
+        if ext in _SPREADSHEET_EXTS:
+            read_func = pd.read_excel
+            read_kwargs['sheet_name'] = self.tab
+        elif ext == '.csv':
+            read_func = pd.read_csv
+            if self.tab and not self.tab[0].isalnum():
+                read_kwargs['sep'] = self.tab
+        else:
+            read_func = pd.read_table
+            if self.tab and not self.tab[0].isalnum():
+                read_kwargs['sep'] = self.tab
+
+        # read the data
+        data = read_func(
+            self.file,
+            skiprows=row_first,
             dtype=object,
+            header=None,
             **read_kwargs
             ).values
 
@@ -1069,12 +1111,21 @@ def get_subscripts_cell(self, row_first, col_first, lastcell):
 
     def get_subscripts_name(self, cellname):
         """Get subscripts from cell range name definition"""
-        excel = load_workbook(self.file, read_only=True, data_only=True)
+        try:
+            excel = load_workbook(self.file, read_only=True, data_only=True)
+        except InvalidFileException:
+            raise ValueError(
+                self.py_name + "\n"
+                f"Cannot read the file '{self.file}'...\n"
+                f"It could happen that firstcell='{cellname}' was "
+                "read as a cell range name due to a wrong definition "
+                "of cell value"
+            )
         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():
+            if sheet.lower() == self.tab.lower():
                 local_cellranges = excel[sheet].defined_names
                 break
 
@@ -1091,8 +1142,8 @@ def get_subscripts_name(self, 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
+            assert sheet.lower() == self.tab.lower()
+            self.tab = sheet  # case insensitivity in sheet name
 
             # Get the cells where the cellrange is defined
             first_cell, last_cell = cells.replace("$", '').split(":")
diff --git a/pysd/py_backend/model.py b/pysd/py_backend/model.py
index 2db13ad7..dcce0090 100644
--- a/pysd/py_backend/model.py
+++ b/pysd/py_backend/model.py
@@ -544,7 +544,6 @@ def initialize_external_data(self, externals=None):
         except ValueError:  # pragma: no cover
             raise ModuleNotFoundError("No module named 'netCDF4'")
 
-
         for ext in self._external_elements:
             if ext.py_name in ds.data_vars.keys():
                 # Initialize external from nc file
@@ -753,7 +752,7 @@ def __include_for_serialization(self, ext, py_name_clean, data, metadata,
             for col in self._doc.columns
         }
         var_meta["files"] = ";".join(ext.files)
-        var_meta["sheets"] = ";".join(ext.sheets)
+        var_meta["tabs"] = ";".join(ext.tabs)
         var_meta["cells"] = ";".join(ext.cells)
         # TODO: add also time_row_or_cols
 
diff --git a/pysd/translators/structures/abstract_expressions.py b/pysd/translators/structures/abstract_expressions.py
index 07e02dec..5af36388 100644
--- a/pysd/translators/structures/abstract_expressions.py
+++ b/pysd/translators/structures/abstract_expressions.py
@@ -558,7 +558,8 @@ class GetLookupsStructure(AbstractSyntax):
     file: str
         The file path where the data is.
     tab: str
-        The sheetname where the data is.
+        Tab name from which the data is read. If file type is not a
+        spreadsheet this will be used as a separator.
     x_row_or_col: str
         The pointer to the cell or cellrange name that defines the
         interpolation series data.
@@ -587,7 +588,8 @@ class GetDataStructure(AbstractSyntax):
     file: str
         The file path where the data is.
     tab: str
-        The sheetname where the data is.
+        Tab name from which the data is read. If file type is not a
+        spreadsheet this will be used as a separator.
     time_row_or_col: str
         The pointer to the cell or cellrange name that defines the
         interpolation time series data.
@@ -616,7 +618,8 @@ class GetConstantsStructure(AbstractSyntax):
     file: str
         The file path where the data is.
     tab: str
-        The sheetname where the data is.
+        Tab name from which the data is read. If file type is not a
+        spreadsheet this will be used as a separator.
     cell: str
         The pointer to the cell or the cellrange name that defines the data.
 
diff --git a/pysd/translators/vensim/parsing_grammars/lookups.peg b/pysd/translators/vensim/parsing_grammars/lookups.peg
index c4a731b8..1088337f 100644
--- a/pysd/translators/vensim/parsing_grammars/lookups.peg
+++ b/pysd/translators/vensim/parsing_grammars/lookups.peg
@@ -2,6 +2,4 @@
 
 lookup = _ "(" _ (regularLookup / excelLookup) _ ")"
 regularLookup = limits? _ ( "(" _ number _ "," _ number _ ")" _ ","? _ )+
-excelLookup = ~"GET( |_)(XLS|DIRECT)( |_)LOOKUPS"I _ "(" (args _ ","? _)+ ")"
-
-args = ~r"[^,()]*"
+excelLookup = ~"GET( |_)(XLS|DIRECT)( |_)LOOKUPS"I _ "(" _ (string _ ","? _)+ ")"
diff --git a/pysd/translators/vensim/vensim_element.py b/pysd/translators/vensim/vensim_element.py
index a67a7e7d..e135328f 100644
--- a/pysd/translators/vensim/vensim_element.py
+++ b/pysd/translators/vensim/vensim_element.py
@@ -124,6 +124,7 @@ def __init__(self, ast):
         self.subscripts = []
         self.subscripts_except = []
         self.subscripts_except_groups = []
+        self.qargs = []
         self.name = None
         self.expression = None
         self.keyword = None
@@ -166,14 +167,17 @@ def visit_keyword(self, n, vc):
         self.keyword = n.text.strip()[1:-1].lower().replace(" ", "_")
 
     def visit_imported_subscript(self, n, vc):
-        self.subscripts = {
-            arg_name: argument.strip().strip("'")
-            for arg_name, argument
-            in zip(
-                ("file", "tab", "firstcell", "lastcell", "prefix"),
-                vc[4].split(",")
-            )
-        }
+        self.subscripts = dict(
+            file=self.qargs[0],
+            tab=self.qargs[1],
+            firstcell=self.qargs[2],
+            lastcell=self.qargs[3],
+            prefix=self.qargs[4]
+        )
+
+    def visit_string(self, n, vc):
+        self.qargs.append(vc[1])
+        return vc[1]
 
     def visit_subscript_copy(self, n, vc):
         self.component = SubscriptRange(self.name, vc[4].strip())
@@ -635,6 +639,7 @@ class LookupsVisitor(parsimonious.NodeVisitor):
     """Visit the elements of a lookups to get the AST"""
     def __init__(self, ast):
         self.translation = None
+        self.qargs = []
         self.visit(ast)
 
     def visit_limits(self, n, vc):
@@ -658,15 +663,17 @@ def visit_regularLookup(self, n, vc):
         )
 
     def visit_excelLookup(self, n, vc):
-        arglist = vc[3].split(",")
-
         self.translation = structures["get_xls_lookups"](
-            file=eval(arglist[0]),
-            tab=eval(arglist[1]),
-            x_row_or_col=eval(arglist[2]),
-            cell=eval(arglist[3])
+            file=self.qargs[0],
+            tab=self.qargs[1],
+            x_row_or_col=self.qargs[2],
+            cell=self.qargs[3]
         )
 
+    def visit_string(self, n, vc):
+        self.qargs.append(vc[1])
+        return vc[1]
+
     def generic_visit(self, n, vc):
         return "".join(filter(None, vc)) or n.text
 


Test patch:
diff --git a/tests/data/input.csv b/tests/data/input.csv
new file mode 100644
index 00000000..878f2727
--- /dev/null
+++ b/tests/data/input.csv
@@ -0,0 +1,5 @@
+,1,2,3,4,5,6,7,8,9,10,,
+A,0,0,1,1,-1,-1,0,0,,,
+B,0,1,1,-1,-1,0,0,0,,,
+C,1,1,-1,-1,0,0,0,0,,,
+,,,,,,,,,,,,
diff --git a/tests/data/input.tab b/tests/data/input.tab
new file mode 100644
index 00000000..4b0e48c8
--- /dev/null
+++ b/tests/data/input.tab
@@ -0,0 +1,5 @@
+	1	2	3	4	5	6	7	8	9	10		
+A	0	0	1	1	-1	-1	0	0			
+B	0	1	1	-1	-1	0	0	0			
+C	1	1	-1	-1	0	0	0	0			
+												
diff --git a/tests/data/input.txt b/tests/data/input.txt
new file mode 100644
index 00000000..317d2cc7
--- /dev/null
+++ b/tests/data/input.txt
@@ -0,0 +1,5 @@
+=1=2=3=4=5=6=7=8=9=10==
+A=0=0=1=1=-1=-1=0=0===
+B=0=1=1=-1=-1=0=0=0===
+C=1=1=-1=-1=0=0=0=0===
+============
diff --git a/tests/data/input2.csv b/tests/data/input2.csv
new file mode 100644
index 00000000..43448bec
--- /dev/null
+++ b/tests/data/input2.csv
@@ -0,0 +1,5 @@
+;1;2;3;4;5;6;7;8;9;10;;
+A;0;0;1;1;-1;-1;0;0;;;
+B;0;1;1;-1;-1;0;0;0;;;
+C;1;1;-1;-1;0;0;0;0;;;
+;;;;;;;;;;;;
diff --git a/tests/data/not_implemented_file.ods b/tests/data/not_implemented_file.ods
deleted file mode 100644
index a56eb466..00000000
Binary files a/tests/data/not_implemented_file.ods and /dev/null differ
diff --git a/tests/pytest_builders/pytest_python.py b/tests/pytest_builders/pytest_python.py
index 67890d5a..f23cb86e 100644
--- a/tests/pytest_builders/pytest_python.py
+++ b/tests/pytest_builders/pytest_python.py
@@ -190,19 +190,32 @@ def test_referencebuilder_subscripts_nowarning(self, component,
 
 class TestSubscriptManager:
     @pytest.mark.parametrize(
-        "arguments,raise_type,error_message",
+        "asrs,raise_type,error_message",
         [
             (  # invalid definition
-                [[AbstractSubscriptRange("my subs", 5, [])], Path("here")],
+                [AbstractSubscriptRange("my subs", 5, [])],
                 ValueError,
                 "Invalid definition of subscript 'my subs':\n\t5"
             ),
+            (  # empty range exts
+                [AbstractSubscriptRange("my subs", dict(
+                    file="data/input.csv",
+                    tab="",
+                    firstcell="A5",
+                    lastcell="5",
+                    prefix="sr"
+                    ), [])],
+                ValueError,
+                "Subscript range 'my subs' empty:\n\t"
+                "{'file': 'data/input.csv', 'tab': '', "
+                "'firstcell': 'A5', 'lastcell': '5', 'prefix': 'sr'}"
+            ),
         ],
-        ids=["invalid definition"]
+        ids=["invalid definition", "empty range exts"]
     )
-    def test_invalid_subscripts(self, arguments, raise_type, error_message):
+    def test_invalid_subscripts(self, asrs, raise_type, error_message, _root):
         with pytest.raises(raise_type, match=error_message):
-            SubscriptManager(*arguments)
+            SubscriptManager(asrs, _root)
 
 
 class TestNamespaceManager:
diff --git a/tests/pytest_pysd/pytest_serialize_externals.py b/tests/pytest_pysd/pytest_serialize_externals.py
index 33f45d77..639ae6aa 100644
--- a/tests/pytest_pysd/pytest_serialize_externals.py
+++ b/tests/pytest_pysd/pytest_serialize_externals.py
@@ -50,7 +50,7 @@ def test_serialize_externals_file_content(self, tmp_path, model):
         assert "description" in ds.attrs.keys()
         assert all(map(
             lambda x: x in ds.data_vars["_ext_data_data_forward"].attrs.keys(),
-            ["Py Name", "sheets", "files"]))
+            ["Py Name", "tabs", "files"]))
 
     @pytest.mark.parametrize(
         "model_path,include,exclude",
diff --git a/tests/pytest_types/external/pytest_external.py b/tests/pytest_types/external/pytest_external.py
index e5296531..1f699e7b 100644
--- a/tests/pytest_types/external/pytest_external.py
+++ b/tests/pytest_types/external/pytest_external.py
@@ -275,7 +275,7 @@ def test_read_empty_cells_openpyxl(self, _root):
 
         ext = External("external")
         ext.file = "data/input.xlsx"
-        ext.sheet = "Horizontal missing"
+        ext.tab = "Horizontal missing"
         ext._resolve_file(root=_root)
 
         error_message = r"external\nThe cells are empty\.\n"\
@@ -294,7 +294,7 @@ def test_read_empty_cells_pandas(self, _root):
 
         ext = External("external")
         ext.file = "data/input.xlsx"
-        ext.sheet = "Horizontal missing"
+        ext.tab = "Horizontal missing"
         ext._resolve_file(root=_root)
 
         error_message = r"external\nThe cells are empty\.\n"
@@ -339,7 +339,7 @@ def test_data_interp_h1d_1(self, _root):
         py_name = "test_data_interp_h1d_1"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -372,7 +372,7 @@ def test_data_interp_hn1d_1(self, _root):
         py_name = "test_data_interp_h1d_1"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -402,7 +402,7 @@ def test_data_interp_h1d(self, _root, _exp):
         py_name = "test_data_interp_h1d"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -432,7 +432,7 @@ def test_data_interp_v1d(self, _root, _exp):
         py_name = "test_data_interp_v1d"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -462,7 +462,7 @@ def test_data_interp_hn1d(self, _root, _exp):
         py_name = "test_data_interp_h1nd"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -492,7 +492,7 @@ def test_data_interp_vn1d(self, _root, _exp):
         py_name = "test_data_interp_vn1d"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -522,7 +522,7 @@ def test_data_forward_h1d(self, _root, _exp):
         py_name = "test_data_forward_h1d"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -552,7 +552,7 @@ def test_data_forward_v1d(self, _root, _exp):
         py_name = "test_data_forward_v1d"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -582,7 +582,7 @@ def test_data_forward_hn1d(self, _root, _exp):
         py_name = "test_data_forward_hn1d"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -612,7 +612,7 @@ def test_data_forward_vn1d(self, _root, _exp):
         py_name = "test_data_forward_vn1d"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -642,7 +642,7 @@ def test_data_backward_h1d(self, _root, _exp):
         py_name = "test_data_backward_h1d"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -672,7 +672,7 @@ def test_data_backward_v1d(self, _root, _exp):
         py_name = "test_data_backward_v1d"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -702,7 +702,7 @@ def test_data_backward_hn1d(self, _root, _exp):
         py_name = "test_data_backward_hn1d"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -732,7 +732,7 @@ def test_data_backward_vn1d(self, _root, _exp):
         py_name = "test_data_backward_vn1d"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -762,7 +762,7 @@ def test_data_interp_vn2d(self, _root, _exp):
         py_name = "test_data_interp_vn2d"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -791,7 +791,7 @@ def test_data_forward_hn2d(self, _root, _exp):
         py_name = "test_data_forward_hn2d"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -820,7 +820,7 @@ def test_data_backward_v2d(self, _root, _exp):
         py_name = "test_data_backward_v2d"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -853,7 +853,7 @@ def test_data_interp_h3d(self, _root, _exp):
         py_name = "test_data_interp_h3d"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell_1,
@@ -863,7 +863,7 @@ def test_data_interp_h3d(self, _root, _exp):
                                      py_name=py_name)
 
         data.add(file_name=file_name,
-                 sheet=sheet,
+                 tab=sheet,
                  time_row_or_col=time_row_or_col,
                  cell=cell_2,
                  coords=coords_2,
@@ -893,7 +893,7 @@ def test_data_forward_v3d(self, _root, _exp):
         py_name = "test_data_forward_v3d"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell_1,
@@ -903,7 +903,7 @@ def test_data_forward_v3d(self, _root, _exp):
                                      py_name=py_name)
 
         data.add(file_name=file_name,
-                 sheet=sheet,
+                 tab=sheet,
                  time_row_or_col=time_row_or_col,
                  cell=cell_2,
                  coords=coords_2,
@@ -933,7 +933,7 @@ def test_data_backward_hn3d(self, _root, _exp):
         py_name = "test_data_backward_hn3d"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell_1,
@@ -943,7 +943,7 @@ def test_data_backward_hn3d(self, _root, _exp):
                                      py_name=py_name)
 
         data.add(file_name=file_name,
-                 sheet=sheet,
+                 tab=sheet,
                  time_row_or_col=time_row_or_col,
                  cell=cell_2,
                  coords=coords_2,
@@ -970,7 +970,7 @@ def test_data_raw_h1d(self, _root, _exp):
         py_name = "test_data_forward_h1d"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -1013,7 +1013,7 @@ def test_lookup_h1d(self, _root, _exp):
         py_name = "test_lookup_h1d"
 
         data = pysd.external.ExtLookup(file_name=file_name,
-                                       sheet=sheet,
+                                       tab=sheet,
                                        x_row_or_col=x_row_or_col,
                                        root=_root,
                                        cell=cell,
@@ -1041,7 +1041,7 @@ def test_lookup_v1d(self, _root, _exp):
         py_name = "test_lookup_v1d"
 
         data = pysd.external.ExtLookup(file_name=file_name,
-                                       sheet=sheet,
+                                       tab=sheet,
                                        x_row_or_col=x_row_or_col,
                                        root=_root,
                                        cell=cell,
@@ -1069,7 +1069,7 @@ def test_lookup_hn1d(self, _root, _exp):
         py_name = "test_lookup_h1nd"
 
         data = pysd.external.ExtLookup(file_name=file_name,
-                                       sheet=sheet,
+                                       tab=sheet,
                                        x_row_or_col=x_row_or_col,
                                        root=_root,
                                        cell=cell,
@@ -1097,7 +1097,7 @@ def test_lookup_vn1d(self, _root, _exp):
         py_name = "test_lookup_vn1d"
 
         data = pysd.external.ExtLookup(file_name=file_name,
-                                       sheet=sheet,
+                                       tab=sheet,
                                        x_row_or_col=x_row_or_col,
                                        root=_root,
                                        cell=cell,
@@ -1125,7 +1125,7 @@ def test_lookup_h2d(self, _root, _exp):
         py_name = "test_lookup_h2d"
 
         data = pysd.external.ExtLookup(file_name=file_name,
-                                       sheet=sheet,
+                                       tab=sheet,
                                        x_row_or_col=x_row_or_col,
                                        root=_root,
                                        cell=cell,
@@ -1156,7 +1156,7 @@ def test_lookup_vn3d(self, _root, _exp):
         py_name = "test_lookup_vn3d"
 
         data = pysd.external.ExtLookup(file_name=file_name,
-                                       sheet=sheet,
+                                       tab=sheet,
                                        x_row_or_col=x_row_or_col,
                                        root=_root,
                                        cell=cell_1,
@@ -1165,7 +1165,7 @@ def test_lookup_vn3d(self, _root, _exp):
                                        py_name=py_name)
 
         data.add(file_name=file_name,
-                 sheet=sheet,
+                 tab=sheet,
                  x_row_or_col=x_row_or_col,
                  cell=cell_2,
                  coords=coords_2)
@@ -1194,7 +1194,7 @@ def test_lookup_vn3d_shape0(self, _root, _exp):
         py_name = "test_lookup_vn3d_shape0"
 
         data = pysd.external.ExtLookup(file_name=file_name,
-                                       sheet=sheet,
+                                       tab=sheet,
                                        x_row_or_col=x_row_or_col,
                                        root=_root,
                                        cell=cell_1,
@@ -1203,7 +1203,7 @@ def test_lookup_vn3d_shape0(self, _root, _exp):
                                        py_name=py_name)
 
         data.add(file_name=file_name,
-                 sheet=sheet,
+                 tab=sheet,
                  x_row_or_col=x_row_or_col,
                  cell=cell_2,
                  coords=coords_2)
@@ -1230,7 +1230,7 @@ def test_lookup_vn2d_xarray(self, _root):
         py_name = "test_lookup_vn2d_xarray"
 
         data = pysd.external.ExtLookup(file_name=file_name,
-                                       sheet=sheet,
+                                       tab=sheet,
                                        x_row_or_col=x_row_or_col,
                                        root=_root,
                                        cell=cell_1,
@@ -1293,7 +1293,7 @@ def test_lookup_vn3d_xarray(self, _root):
         py_name = "test_lookup_vn3d_xarray"
 
         data = pysd.external.ExtLookup(file_name=file_name,
-                                       sheet=sheet,
+                                       tab=sheet,
                                        x_row_or_col=x_row_or_col,
                                        root=_root,
                                        cell=cell_1,
@@ -1302,7 +1302,7 @@ def test_lookup_vn3d_xarray(self, _root):
                                        py_name=py_name)
 
         data.add(file_name=file_name,
-                 sheet=sheet,
+                 tab=sheet,
                  x_row_or_col=x_row_or_col,
                  cell=cell_2,
                  coords=coords_2)
@@ -1364,7 +1364,7 @@ def test_constant_0d(self, _root):
         py_name = "test_constant_0d"
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell,
                                          coords=coords,
@@ -1372,7 +1372,7 @@ def test_constant_0d(self, _root):
                                          py_name=py_name)
 
         data2 = pysd.external.ExtConstant(file_name=file_name,
-                                          sheet=sheet,
+                                          tab=sheet,
                                           root=_root,
                                           cell=cell2,
                                           coords=coords,
@@ -1398,7 +1398,7 @@ def test_constant_n0d(self, _root):
         py_name = "test_constant_0d"
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell,
                                          coords=coords,
@@ -1406,7 +1406,7 @@ def test_constant_n0d(self, _root):
                                          py_name=py_name)
 
         data2 = pysd.external.ExtConstant(file_name=file_name,
-                                          sheet=sheet,
+                                          tab=sheet,
                                           root=_root,
                                           cell=cell2,
                                           coords=coords,
@@ -1431,7 +1431,7 @@ def test_constant_h1d(self, _root, _exp):
         py_name = "test_constant_h1d"
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell,
                                          coords=coords,
@@ -1454,7 +1454,7 @@ def test_constant_v1d(self, _root, _exp):
         py_name = "test_constant_v1d"
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell,
                                          coords=coords,
@@ -1477,7 +1477,7 @@ def test_constant_hn1d(self, _root, _exp):
         py_name = "test_constant_hn1d"
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell,
                                          coords=coords,
@@ -1500,7 +1500,7 @@ def test_constant_vn1d(self, _root, _exp):
         py_name = "test_constant_vn1d"
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell,
                                          coords=coords,
@@ -1523,7 +1523,7 @@ def test_constant_h2d(self, _root, _exp):
         py_name = "test_constant_h2d"
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell,
                                          coords=coords,
@@ -1546,7 +1546,7 @@ def test_constant_v2d(self, _root, _exp):
         py_name = "test_constant_v2d"
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell,
                                          coords=coords,
@@ -1569,7 +1569,7 @@ def test_constant_hn2d(self, _root, _exp):
         py_name = "test_constant_hn2d"
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell,
                                          coords=coords,
@@ -1592,7 +1592,7 @@ def test_constant_vn2d(self, _root, _exp):
         py_name = "test_constant_vn2d"
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell,
                                          coords=coords,
@@ -1624,7 +1624,7 @@ def test_constant_h3d(self, _root, _exp):
         py_name = "test_constant_h3d"
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell,
                                          coords=coords,
@@ -1632,7 +1632,7 @@ def test_constant_h3d(self, _root, _exp):
                                          py_name=py_name)
 
         data.add(file_name=file_name,
-                 sheet=sheet,
+                 tab=sheet,
                  cell=cell2,
                  coords=coords2)
 
@@ -1662,7 +1662,7 @@ def test_constant_v3d(self, _root, _exp):
         py_name = "test_constant_v3d"
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell,
                                          coords=coords,
@@ -1670,7 +1670,7 @@ def test_constant_v3d(self, _root, _exp):
                                          py_name=py_name)
 
         data.add(file_name=file_name,
-                 sheet=sheet,
+                 tab=sheet,
                  cell=cell2,
                  coords=coords2)
 
@@ -1700,7 +1700,7 @@ def test_constant_hn3d(self, _root, _exp):
         py_name = "test_constant_hn3d"
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell,
                                          coords=coords,
@@ -1708,7 +1708,7 @@ def test_constant_hn3d(self, _root, _exp):
                                          py_name=py_name)
 
         data.add(file_name=file_name,
-                 sheet=sheet,
+                 tab=sheet,
                  cell=cell2,
                  coords=coords2)
 
@@ -1738,7 +1738,7 @@ def test_constant_vn3d(self, _root, _exp):
         py_name = "test_constant_vn2d"
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell,
                                          coords=coords,
@@ -1746,7 +1746,7 @@ def test_constant_vn3d(self, _root, _exp):
                                          py_name=py_name)
 
         data.add(file_name=file_name,
-                 sheet=sheet,
+                 tab=sheet,
                  cell=cell2,
                  coords=coords2)
 
@@ -1754,6 +1754,189 @@ def test_constant_vn3d(self, _root, _exp):
 
         assert data().equals(_exp.constant_3d)
 
+    def test_constant_h1d_csv(self, _root, _exp):
+        """
+        ExtConstant test for horizontal 1d data
+        """
+        import pysd
+
+        file_name = "data/input.csv"
+        sheet = ""
+        cell = "B2"
+        coords = {'val': [0, 1, 2, 3, 5, 6, 7, 8]}
+        py_name = "test_constant_h1d_csv"
+
+        data = pysd.external.ExtConstant(file_name=file_name,
+                                         tab=sheet,
+                                         root=_root,
+                                         cell=cell,
+                                         coords=coords,
+                                         final_coords=coords,
+                                         py_name=py_name)
+        data.initialize()
+
+        assert data().equals(_exp.constant_1d)
+
+    def test_constant_h2d_csv(self, _root, _exp):
+        """
+        ExtConstant test for horizontal 2d data
+        """
+        import pysd
+
+        file_name = "data/input.csv"
+        sheet = ","
+        cell = "B2"
+        coords = {'ABC': ['A', 'B', 'C'], 'val': [0, 1, 2, 3, 5, 6, 7, 8]}
+        py_name = "test_constant_h2d_csv"
+
+        data = pysd.external.ExtConstant(file_name=file_name,
+                                         tab=sheet,
+                                         root=_root,
+                                         cell=cell,
+                                         coords=coords,
+                                         final_coords=coords,
+                                         py_name=py_name)
+        data.initialize()
+
+        assert data().equals(_exp.constant_2d)
+
+    def test_constant_v2d_csv(self, _root, _exp):
+        """
+        ExtConstant test for vertical 2d data
+        """
+        import pysd
+
+        file_name = "data/input.csv"
+        sheet = "vertical"
+        cell = "B2*"
+        coords = {'val': [0, 1, 2, 3, 5, 6, 7, 8], 'ABC': ['A', 'B', 'C']}
+        py_name = "test_constant_v2d_csv"
+
+        data = pysd.external.ExtConstant(file_name=file_name,
+                                         tab=sheet,
+                                         root=_root,
+                                         cell=cell,
+                                         coords=coords,
+                                         final_coords=coords,
+                                         py_name=py_name)
+        data.initialize()
+
+        assert data().equals(_exp.constant_2d.transpose())
+
+    def test_constant_v2d_csv2(self, _root, _exp):
+        """
+        ExtConstant test for vertical 2d data
+        """
+        import pysd
+
+        file_name = "data/input2.csv"
+        sheet = ";"
+        cell = "B2*"
+        coords = {'val': [0, 1, 2, 3, 5, 6, 7, 8], 'ABC': ['A', 'B', 'C']}
+        py_name = "test_constant_v2d_csv2"
+
+        data = pysd.external.ExtConstant(file_name=file_name,
+                                         tab=sheet,
+                                         root=_root,
+                                         cell=cell,
+                                         coords=coords,
+                                         final_coords=coords,
+                                         py_name=py_name)
+        data.initialize()
+
+        assert data().equals(_exp.constant_2d.transpose())
+
+    def test_constant_h1d_tab(self, _root, _exp):
+        """
+        ExtConstant test for horizontal 1d data
+        """
+        import pysd
+
+        file_name = "data/input.tab"
+        sheet = ""
+        cell = "B2"
+        coords = {'val': [0, 1, 2, 3, 5, 6, 7, 8]}
+        py_name = "test_constant_h1d_tab"
+
+        data = pysd.external.ExtConstant(file_name=file_name,
+                                         tab=sheet,
+                                         root=_root,
+                                         cell=cell,
+                                         coords=coords,
+                                         final_coords=coords,
+                                         py_name=py_name)
+        data.initialize()
+
+        assert data().equals(_exp.constant_1d)
+
+    def test_constant_h2d_tab(self, _root, _exp):
+        """
+        ExtConstant test for horizontal 2d data
+        """
+        import pysd
+
+        file_name = "data/input.tab"
+        sheet = "\t"
+        cell = "B2"
+        coords = {'ABC': ['A', 'B', 'C'], 'val': [0, 1, 2, 3, 5, 6, 7, 8]}
+        py_name = "test_constant_h2d_tab"
+
+        data = pysd.external.ExtConstant(file_name=file_name,
+                                         tab=sheet,
+                                         root=_root,
+                                         cell=cell,
+                                         coords=coords,
+                                         final_coords=coords,
+                                         py_name=py_name)
+        data.initialize()
+
+        assert data().equals(_exp.constant_2d)
+
+    def test_constant_v2d_tab(self, _root, _exp):
+        """
+        ExtConstant test for vertical 2d data
+        """
+        import pysd
+
+        file_name = "data/input.tab"
+        sheet = "vertical"
+        cell = "B2*"
+        coords = {'val': [0, 1, 2, 3, 5, 6, 7, 8], 'ABC': ['A', 'B', 'C']}
+        py_name = "test_constant_v2d_tab"
+
+        data = pysd.external.ExtConstant(file_name=file_name,
+                                         tab=sheet,
+                                         root=_root,
+                                         cell=cell,
+                                         coords=coords,
+                                         final_coords=coords,
+                                         py_name=py_name)
+        data.initialize()
+
+        assert data().equals(_exp.constant_2d.transpose())
+
+    def test_constant_v2d_txt(self, _root, _exp):
+        """
+        ExtConstant test for vertical 2d data
+        """
+        import pysd
+
+        file_name = "data/input.txt"
+        sheet = "="
+        cell = "B2*"
+        coords = {'val': [0, 1, 2, 3, 5, 6, 7, 8], 'ABC': ['A', 'B', 'C']}
+        py_name = "test_constant_v2d_txt"
+
+        data = pysd.external.ExtConstant(file_name=file_name,
+                                         tab=sheet,
+                                         root=_root,
+                                         cell=cell,
+                                         coords=coords,
+                                         final_coords=coords,
+                                         py_name=py_name)
+        data.initialize()
+
+        assert data().equals(_exp.constant_2d.transpose())
 
 class TestSubscript():
     """
@@ -1776,7 +1959,7 @@ def test_subscript_h(self, _root):
                     'val5', 'val6', 'val7', 'val8']
 
         data = pysd.external.ExtSubscript(file_name=file_name,
-                                          sheet=sheet,
+                                          tab=sheet,
                                           root=_root,
                                           firstcell=firstcell,
                                           lastcell=lastcell,
@@ -1799,7 +1982,76 @@ def test_subscript_h2(self, _root):
                     'v5', 'v6', 'v7', 'v8']
 
         data = pysd.external.ExtSubscript(file_name=file_name,
-                                          sheet=sheet,
+                                          tab=sheet,
+                                          root=_root,
+                                          firstcell=firstcell,
+                                          lastcell=lastcell,
+                                          prefix=prefix)
+
+        assert data.subscript == expected
+
+    def test_subscript_h_csv(self, _root):
+        """
+        ExtSubscript test for horizontal subscripts
+        """
+        import pysd
+
+        file_name = "data/input.csv"
+        sheet = ""
+        firstcell = "A1"
+        lastcell = "1"
+        prefix = 'h'
+        expected = ['h1', 'h2', 'h3', 'h4', 'h5',
+                    'h6', 'h7', 'h8', 'h9', 'h10']
+
+        data = pysd.external.ExtSubscript(file_name=file_name,
+                                          tab=sheet,
+                                          root=_root,
+                                          firstcell=firstcell,
+                                          lastcell=lastcell,
+                                          prefix=prefix)
+
+        assert data.subscript == expected
+
+    def test_subscript_h_tab(self, _root):
+        """
+        ExtSubscript test for horizontal subscripts
+        """
+        import pysd
+
+        file_name = "data/input.tab"
+        sheet = ""
+        firstcell = "B1"
+        lastcell = "1"
+        prefix = 'h'
+        expected = ['h1', 'h2', 'h3', 'h4', 'h5',
+                    'h6', 'h7', 'h8', 'h9', 'h10']
+
+        data = pysd.external.ExtSubscript(file_name=file_name,
+                                          tab=sheet,
+                                          root=_root,
+                                          firstcell=firstcell,
+                                          lastcell=lastcell,
+                                          prefix=prefix)
+
+        assert data.subscript == expected
+
+    def test_subscript_h_txt(self, _root):
+        """
+        ExtSubscript test for horizontal subscripts
+        """
+        import pysd
+
+        file_name = "data/input.txt"
+        sheet = "="
+        firstcell = "B1"
+        lastcell = "1"
+        prefix = 'h'
+        expected = ['h1', 'h2', 'h3', 'h4', 'h5',
+                    'h6', 'h7', 'h8', 'h9', 'h10']
+
+        data = pysd.external.ExtSubscript(file_name=file_name,
+                                          tab=sheet,
                                           root=_root,
                                           firstcell=firstcell,
                                           lastcell=lastcell,
@@ -1821,7 +2073,7 @@ def test_subscript_v(self, _root):
         expected = ['A', 'B', 'C']
 
         data = pysd.external.ExtSubscript(file_name=file_name,
-                                          sheet=sheet,
+                                          tab=sheet,
                                           root=_root,
                                           firstcell=firstcell,
                                           lastcell=lastcell,
@@ -1843,7 +2095,73 @@ def test_subscript_v2(self, _root):
         expected = ['A', 'B', 'C', '4', '5']
 
         data = pysd.external.ExtSubscript(file_name=file_name,
-                                          sheet=sheet,
+                                          tab=sheet,
+                                          root=_root,
+                                          firstcell=firstcell,
+                                          lastcell=lastcell,
+                                          prefix=prefix)
+
+        assert data.subscript == expected
+
+    def test_subscript_v_csv(self, _root):
+        """
+        ExtSubscript test for vertical subscripts
+        """
+        import pysd
+
+        file_name = "data/input.csv"
+        sheet = ","
+        firstcell = "A2"
+        lastcell = "A"
+        prefix = 'v'
+        expected = ['vA', 'vB', 'vC']
+
+        data = pysd.external.ExtSubscript(file_name=file_name,
+                                          tab=sheet,
+                                          root=_root,
+                                          firstcell=firstcell,
+                                          lastcell=lastcell,
+                                          prefix=prefix)
+
+        assert data.subscript == expected
+
+    def test_subscript_v_tab(self, _root):
+        """
+        ExtSubscript test for vertical subscripts
+        """
+        import pysd
+
+        file_name = "data/input.tab"
+        sheet = "\t"
+        firstcell = "A1"
+        lastcell = "A"
+        prefix = 'v'
+        expected = ['vA', 'vB', 'vC']
+
+        data = pysd.external.ExtSubscript(file_name=file_name,
+                                          tab=sheet,
+                                          root=_root,
+                                          firstcell=firstcell,
+                                          lastcell=lastcell,
+                                          prefix=prefix)
+
+        assert data.subscript == expected
+
+    def test_subscript_v_ncsv(self, _root):
+        """
+        ExtSubscript test for vertical subscripts
+        """
+        import pysd
+
+        file_name = "data/input2.csv"
+        sheet = ";"
+        firstcell = "A1"
+        lastcell = "A"
+        prefix = 'v'
+        expected = ['vA', 'vB', 'vC']
+
+        data = pysd.external.ExtSubscript(file_name=file_name,
+                                          tab=sheet,
                                           root=_root,
                                           firstcell=firstcell,
                                           lastcell=lastcell,
@@ -1865,7 +2183,7 @@ def test_subscript_d(self, _root):
         expected = ['X', 'A', 'B', 'C', 'Y', 'A', 'B', 'C']
 
         data = pysd.external.ExtSubscript(file_name=file_name,
-                                          sheet=sheet,
+                                          tab=sheet,
                                           root=_root,
                                           firstcell=firstcell,
                                           lastcell=lastcell,
@@ -1887,7 +2205,51 @@ def test_subscript_d2(self, _root):
         expected = ['j3', 'j2', 'j1', 'j6', 'j4', 'j8', 'j-1', 'j3', 'j2']
 
         data = pysd.external.ExtSubscript(file_name=file_name,
-                                          sheet=sheet,
+                                          tab=sheet,
+                                          root=_root,
+                                          firstcell=firstcell,
+                                          lastcell=lastcell,
+                                          prefix=prefix)
+
+        assert data.subscript == expected
+
+    def test_subscript_d_csv(self, _root):
+        """
+        ExtSubscript test for diagonal subscripts
+        """
+        import pysd
+
+        file_name = "data/input.csv"
+        sheet = "123 name"
+        firstcell = "B1"
+        lastcell = "C2"
+        prefix = 'd'
+        expected = ['d1', 'd2', 'd0', 'd0']
+
+        data = pysd.external.ExtSubscript(file_name=file_name,
+                                          tab=sheet,
+                                          root=_root,
+                                          firstcell=firstcell,
+                                          lastcell=lastcell,
+                                          prefix=prefix)
+
+        assert data.subscript == expected
+
+    def test_subscript_d_tab(self, _root):
+        """
+        ExtSubscript test for diagonal subscripts
+        """
+        import pysd
+
+        file_name = "data/input.tab"
+        sheet = "sheet name!"
+        firstcell = "B1"
+        lastcell = "C2"
+        prefix = 'd'
+        expected = ['d1', 'd2', 'd0', 'd0']
+
+        data = pysd.external.ExtSubscript(file_name=file_name,
+                                          tab=sheet,
                                           root=_root,
                                           firstcell=firstcell,
                                           lastcell=lastcell,
@@ -1910,7 +2272,7 @@ def test_subscript_name_h(self, _root):
                     'l5', 'l6', 'l7', 'l8']
 
         data = pysd.external.ExtSubscript(file_name=file_name,
-                                          sheet=sheet,
+                                          tab=sheet,
                                           root=_root,
                                           firstcell=firstcell,
                                           lastcell=lastcell,
@@ -1932,7 +2294,7 @@ def test_subscript_name_v(self, _root):
         expected = ['pA', 'pB', 'pC']
 
         data = pysd.external.ExtSubscript(file_name=file_name,
-                                          sheet=sheet,
+                                          tab=sheet,
                                           root=_root,
                                           firstcell=firstcell,
                                           lastcell=lastcell,
@@ -1954,7 +2316,7 @@ def test_subscript_name_d(self, _root):
         expected = ['X', 'A', '0', 'B', '0', 'C', '1']
 
         data = pysd.external.ExtSubscript(file_name=file_name,
-                                          sheet=sheet,
+                                          tab=sheet,
                                           root=_root,
                                           firstcell=firstcell,
                                           lastcell=lastcell,
@@ -1968,34 +2330,6 @@ class TestWarningsErrors():
     Test for the warnings and errors of External and its subclasses
     """
 
-    def test_not_implemented_file(self, _root):
-        """
-        Test for not implemented file
-        """
-        import pysd
-
-        file_name = "data/not_implemented_file.ods"
-        sheet = "Horizontal"
-        time_row_or_col = "4"
-        cell = "C5"
-        coords = {}
-        interp = None
-        py_name = "test_not_implemented_file"
-
-        data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
-                                     time_row_or_col=time_row_or_col,
-                                     root=_root,
-                                     cell=cell,
-                                     coords=coords,
-                                     interp=interp,
-                                     final_coords=coords,
-                                     py_name=py_name)
-
-        error_message = r"The files with extension .ods are not implemented"
-        with pytest.raises(NotImplementedError, match=error_message):
-            data.initialize()
-
     def test_non_existent_file(self, _root):
         """
         Test for non-existent file
@@ -2011,7 +2345,7 @@ def test_non_existent_file(self, _root):
         py_name = "test_non_existent_file"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -2038,7 +2372,7 @@ def test_non_existent_sheet_pyxl(self, _root):
         py_name = "test_non_existent_sheet_pyxl"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -2066,7 +2400,7 @@ def test_non_existent_cellrange_name_pyxl(self, _root):
         py_name = "test_non_existent_cellrange_name_pyxl"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -2092,7 +2426,7 @@ def test_non_existent_cellrange_name_in_sheet_pyxl(self, _root):
         py_name = "est_non_existent_cellrange_name_in_sheet_pyxl"
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell,
                                          coords=coords,
@@ -2123,7 +2457,7 @@ def test_data_interp_h1dm_row(self, _root):
         pysd.external.External.missing = "warning"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -2161,7 +2495,7 @@ def test_data_interp_h1dm_row2(self, _root):
         pysd.external.External.missing = "warning"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -2201,7 +2535,7 @@ def test_data_interp_h1dm(self, _root, _exp):
         pysd.external.External.missing = "warning"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -2237,7 +2571,7 @@ def test_data_interp_h1dm_ignore(self, _root, _exp):
         pysd.external.External.missing = "ignore"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -2272,7 +2606,7 @@ def test_data_interp_h1dm_raise(self, _root):
         pysd.external.External.missing = "raise"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -2303,7 +2637,7 @@ def test_data_interp_v1dm(self, _root, _exp):
         pysd.external.External.missing = "warning"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -2339,7 +2673,7 @@ def test_data_interp_v1dm_ignore(self, _root, _exp):
         pysd.external.External.missing = "ignore"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -2374,7 +2708,7 @@ def test_data_interp_v1dm_raise(self, _root):
         pysd.external.External.missing = "raise"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -2405,7 +2739,7 @@ def test_data_interp_hn1dm(self, _root, _exp):
         pysd.external.External.missing = "warning"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -2441,7 +2775,7 @@ def test_data_interp_hn1dm_ignore(self, _root, _exp):
         pysd.external.External.missing = "ignore"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -2476,7 +2810,7 @@ def test_data_interp_hn1dm_raise(self, _root):
         pysd.external.External.missing = "raise"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -2510,7 +2844,7 @@ def test_data_interp_hn3dmd(self, _root, _exp):
         pysd.external.External.missing = "warning"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell_1,
@@ -2520,7 +2854,7 @@ def test_data_interp_hn3dmd(self, _root, _exp):
                                      py_name=py_name)
 
         data.add(file_name=file_name,
-                 sheet=sheet,
+                 tab=sheet,
                  time_row_or_col=time_row_or_col,
                  cell=cell_2,
                  interp=interp,
@@ -2556,7 +2890,7 @@ def test_data_interp_hn3dmd_raw(self, _root):
         pysd.external.External.missing = "warning"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell_1,
@@ -2566,7 +2900,7 @@ def test_data_interp_hn3dmd_raw(self, _root):
                                      py_name=py_name)
 
         data.add(file_name=file_name,
-                 sheet=sheet,
+                 tab=sheet,
                  time_row_or_col=time_row_or_col,
                  cell=cell_2,
                  interp=interp,
@@ -2594,7 +2928,7 @@ def test_lookup_hn3dmd_raise(self, _root):
         pysd.external.External.missing = "raise"
 
         data = pysd.external.ExtLookup(file_name=file_name,
-                                       sheet=sheet,
+                                       tab=sheet,
                                        x_row_or_col=x_row_or_col,
                                        root=_root,
                                        cell=cell_1,
@@ -2603,7 +2937,7 @@ def test_lookup_hn3dmd_raise(self, _root):
                                        py_name=py_name)
 
         data.add(file_name=file_name,
-                 sheet=sheet,
+                 tab=sheet,
                  x_row_or_col=x_row_or_col,
                  cell=cell_2,
                  coords=coords_2)
@@ -2631,7 +2965,7 @@ def test_lookup_hn3dmd_ignore(self, _root, _exp):
         pysd.external.External.missing = "ignore"
 
         data = pysd.external.ExtLookup(file_name=file_name,
-                                       sheet=sheet,
+                                       tab=sheet,
                                        x_row_or_col=x_row_or_col,
                                        root=_root,
                                        cell=cell_1,
@@ -2640,7 +2974,7 @@ def test_lookup_hn3dmd_ignore(self, _root, _exp):
                                        py_name=py_name)
 
         data.add(file_name=file_name,
-                 sheet=sheet,
+                 tab=sheet,
                  x_row_or_col=x_row_or_col,
                  cell=cell_2,
                  coords=coords_2)
@@ -2674,7 +3008,7 @@ def test_constant_h3dm(self, _root):
         pysd.external.External.missing = "warning"
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell_1,
                                          coords=coords_1,
@@ -2682,7 +3016,7 @@ def test_constant_h3dm(self, _root):
                                          py_name=py_name)
 
         data.add(file_name=file_name,
-                 sheet=sheet,
+                 tab=sheet,
                  cell=cell_2,
                  coords=coords_2)
 
@@ -2710,7 +3044,7 @@ def test_constant_h3dm_ignore(self, _root):
         pysd.external.External.missing = "ignore"
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell_1,
                                          coords=coords_1,
@@ -2718,7 +3052,7 @@ def test_constant_h3dm_ignore(self, _root):
                                          py_name=py_name)
 
         data.add(file_name=file_name,
-                 sheet=sheet,
+                 tab=sheet,
                  cell=cell_2,
                  coords=coords_2)
 
@@ -2744,7 +3078,7 @@ def test_constant_h3dm_raise(self, _root):
         pysd.external.External.missing = "raise"
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell_1,
                                          coords=coords_1,
@@ -2752,7 +3086,7 @@ def test_constant_h3dm_raise(self, _root):
                                          py_name=py_name)
 
         data.add(file_name=file_name,
-                 sheet=sheet,
+                 tab=sheet,
                  cell=cell_2,
                  coords=coords_2)
 
@@ -2781,7 +3115,7 @@ def test_constant_hn3dm_raise(self, _root):
         pysd.external.External.missing = "raise"
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell_1,
                                          coords=coords_1,
@@ -2789,7 +3123,7 @@ def test_constant_hn3dm_raise(self, _root):
                                          py_name=py_name)
 
         data.add(file_name=file_name,
-                 sheet=sheet,
+                 tab=sheet,
                  cell=cell_2,
                  coords=coords_2)
 
@@ -2812,7 +3146,7 @@ def test_data_interp_h1d0(self, _root):
         py_name = "test_data_interp_h1d0"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -2840,7 +3174,7 @@ def test_data_interp_v1d0(self, _root):
         py_name = "test_data_interp_v1d0"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -2870,7 +3204,7 @@ def test_data_interp_hn1d0(self, _root):
         pysd.external.External.missing = "warning"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -2899,7 +3233,7 @@ def test_data_interp_hn1dt(self, _root):
         py_name = "test_data_interp_h1dt"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -2928,7 +3262,7 @@ def test_data_interp_hns(self, _root):
         py_name = "test_data_interp_hns"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -2957,7 +3291,7 @@ def test_data_interp_vnss(self, _root):
         py_name = "test_data_interp_vnss"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -2987,7 +3321,7 @@ def test_data_interp_hnnwd(self, _root):
         py_name = "test_data_interp_hnnwd"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -3014,7 +3348,7 @@ def test_data_raw_hnnm(self, _root):
         py_name = "test_data_interp_hnnm"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -3037,7 +3371,7 @@ def test_data_raw_hnnm(self, _root):
         py_name = "test_data_interp_hnnnm2"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -3074,7 +3408,7 @@ def test_data_h3d_interpnv(self, _root):
             r"'raw', 'interpolate', 'look_forward' or 'hold_backward'"
         with pytest.raises(ValueError, match=error_message):
             pysd.external.ExtData(file_name=file_name,
-                                  sheet=sheet,
+                                  tab=sheet,
                                   time_row_or_col=time_row_or_col,
                                   root=_root,
                                   cell=cell,
@@ -3102,7 +3436,7 @@ def test_data_h3d_interp(self, _root):
         py_name = "test_data_h3d_interp"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell_1,
@@ -3115,7 +3449,7 @@ def test_data_h3d_interp(self, _root):
             "previously defined one"
         with pytest.raises(ValueError, match=error_message):
             data.add(file_name=file_name,
-                     sheet=sheet,
+                     tab=sheet,
                      time_row_or_col=time_row_or_col,
                      cell=cell_2,
                      coords=coords_2,
@@ -3139,7 +3473,7 @@ def test_data_h3d_add(self, _root):
         py_name = "test_data_h3d_add"
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell_1,
@@ -3151,7 +3485,7 @@ def test_data_h3d_add(self, _root):
         error_message = "Error matching dimensions with previous data"
         with pytest.raises(ValueError, match=error_message):
             data.add(file_name=file_name,
-                     sheet=sheet,
+                     tab=sheet,
                      time_row_or_col=time_row_or_col,
                      cell=cell_2,
                      coords=coords_2,
@@ -3174,7 +3508,7 @@ def test_lookup_h3d_add(self, _root):
         py_name = "test_lookup_h3d_add"
 
         data = pysd.external.ExtLookup(file_name=file_name,
-                                       sheet=sheet,
+                                       tab=sheet,
                                        x_row_or_col=x_row_or_col,
                                        root=_root,
                                        cell=cell_1,
@@ -3185,7 +3519,7 @@ def test_lookup_h3d_add(self, _root):
         error_message = "Error matching dimensions with previous data"
         with pytest.raises(ValueError, match=error_message):
             data.add(file_name=file_name,
-                     sheet=sheet,
+                     tab=sheet,
                      x_row_or_col=x_row_or_col,
                      cell=cell_2,
                      coords=coords_2)
@@ -3211,7 +3545,7 @@ def test_constant_h3d_add(self, _root):
         py_name = "test_constant_h3d_add"
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell,
                                          coords=coords,
@@ -3221,7 +3555,7 @@ def test_constant_h3d_add(self, _root):
         error_message = "Error matching dimensions with previous data"
         with pytest.raises(ValueError, match=error_message):
             data.add(file_name=file_name,
-                     sheet=sheet,
+                     tab=sheet,
                      cell=cell2,
                      coords=coords2)
 
@@ -3239,7 +3573,7 @@ def test_constant_hns(self, _root):
         py_name = "test_constant_hns"
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell,
                                          coords=coords,
@@ -3266,7 +3600,7 @@ def text_openpyxl_str(self, _root):
         py_name = "test_openpyxl_str"
 
         data = pysd.external.ExtLookup(file_name=file_name,
-                                       sheet=sheet,
+                                       tab=sheet,
                                        x_row_or_col=x_row_or_col,
                                        root=_root,
                                        cell=cell,
@@ -3287,7 +3621,7 @@ def text_openpyxl_str(self, _root):
         sheet = "caSE anD NON V"  # test case insensitivity
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell,
                                          coords=coords,
@@ -3313,7 +3647,7 @@ def test_subscript_name_non_existent_sheet(self, _root):
         error_message = r"The sheet doesn't exist\.\.\."
         with pytest.raises(ValueError, match=error_message):
             pysd.external.ExtSubscript(file_name=file_name,
-                                       sheet=sheet,
+                                       tab=sheet,
                                        root=_root,
                                        firstcell=firstcell,
                                        lastcell=lastcell,
@@ -3334,7 +3668,56 @@ def test_subscript_name_non_existent_cellrange_name(self, _root):
         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,
+                                       tab=sheet,
+                                       root=_root,
+                                       firstcell=firstcell,
+                                       lastcell=lastcell,
+                                       prefix=prefix)
+
+    def test_name_in_tab(self, _root):
+        """
+        Test for cellrange input in cell for non spreadsheet file
+        """
+        import pysd
+
+        file_name = "data/input.csv"
+        sheet = ""
+        cell = "data"
+        coords = {}
+        py_name = "test_name_in_tab"
+
+        data = pysd.external.ExtConstant(file_name=file_name,
+                                         tab=sheet,
+                                         root=_root,
+                                         cell=cell,
+                                         coords=coords,
+                                         final_coords=coords,
+                                         py_name=py_name)
+
+        error_message = r"Cannot read the file '.*'...\n"\
+            "It could happen that cell='data' was read as a "\
+            "cell range name due to a wrong definition of cell value"
+        with pytest.raises(ValueError, match=error_message):
+            data.initialize()
+
+    def test_subscript_name_in_csv(self, _root):
+        """
+        Test for cellrange input in cell for non spreadsheet file
+        """
+        import pysd
+
+        file_name = "data/input.csv"
+        sheet = ""
+        firstcell = "fake-cell"
+        lastcell = ""
+        prefix = ""
+
+        error_message = r"Cannot read the file '.*'...\n"\
+            "It could happen that firstcell='fake-cell' was read as a "\
+            "cell range name due to a wrong definition of cell value"
+        with pytest.raises(ValueError, match=error_message):
+            pysd.external.ExtSubscript(file_name=file_name,
+                                       tab=sheet,
                                        root=_root,
                                        firstcell=firstcell,
                                        lastcell=lastcell,
@@ -3379,7 +3762,7 @@ def test_constant_hn3dm_keep(self, _root):
             ['XY', 'ABC', 'val'])
 
         data = pysd.external.ExtConstant(file_name=file_name,
-                                         sheet=sheet,
+                                         tab=sheet,
                                          root=_root,
                                          cell=cell_1,
                                          coords=coords_1,
@@ -3387,7 +3770,7 @@ def test_constant_hn3dm_keep(self, _root):
                                          py_name=py_name)
 
         data.add(file_name=file_name,
-                 sheet=sheet,
+                 tab=sheet,
                  cell=cell_2,
                  coords=coords_2)
 
@@ -3435,7 +3818,7 @@ def test_lookup_hn3dmd_keep(self, _root):
             ['lookup_dim', 'XY', 'ABC'])
 
         data = pysd.external.ExtLookup(file_name=file_name,
-                                       sheet=sheet,
+                                       tab=sheet,
                                        x_row_or_col=x_row_or_col,
                                        root=_root,
                                        cell=cell_1,
@@ -3444,7 +3827,7 @@ def test_lookup_hn3dmd_keep(self, _root):
                                        py_name=py_name)
 
         data.add(file_name=file_name,
-                 sheet=sheet,
+                 tab=sheet,
                  x_row_or_col=x_row_or_col,
                  cell=cell_2,
                  coords=coords_2)
@@ -3476,7 +3859,7 @@ def test_data_interp_v1dm_keep(self, _root):
             ['time'])
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -3512,7 +3895,7 @@ def test_data_interp_hnnm_keep(self, _root):
             ['time'])
 
         data = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -3541,7 +3924,7 @@ def test_lookup_data_attr(self, _root):
         py_name = "test_data_interp_hnnm"
 
         datD = pysd.external.ExtData(file_name=file_name,
-                                     sheet=sheet,
+                                     tab=sheet,
                                      time_row_or_col=time_row_or_col,
                                      root=_root,
                                      cell=cell,
@@ -3551,7 +3934,7 @@ def test_lookup_data_attr(self, _root):
                                      py_name=py_name)
 
         datL = pysd.external.ExtLookup(file_name=file_name,
-                                       sheet=sheet,
+                                       tab=sheet,
                                        x_row_or_col=time_row_or_col,
                                        root=_root,
                                        cell=cell,