dgorissen / pycel

A library for compiling excel spreadsheets to python code & visualizing them as a graph
GNU General Public License v3.0
565 stars 147 forks source link

support for set_value and evaluate with defined names #153

Open codinguncut opened 1 year ago

codinguncut commented 1 year ago

As far as I can tell it is not possible to use "defined names" in the set_value and evaluate methods.

excel = ExcelCompiler(filename='simple.xlsx')
excel.evaluate('together')
Traceback (most recent call last):
  File "C:\Users\sinea\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\pycel\excelcompiler.py", line 851, in _evaluate_non_iterative
    address = AddressRange.create(address)
  File "C:\Users\sinea\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\pycel\excelutil.py", line 343, in create
    addr_tuple, sheetname = range_boundaries(
  File "C:\Users\sinea\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\pycel\excelutil.py", line 752, in range_boundaries
    raise ValueError(f"{address} is not a valid coordinate or range")
ValueError: together is not a valid coordinate or range

It would be nice if this could be supported natively.

Possible workaround below, unless I have completely missed the point. Also, the documentation for AddressCell and AddressRange is a bit weird in requiring to pass in a _Cell when it appears that what needs to be passed in is an ExcelCompiler, since _Cell has no attribute .excel.defined_names

   class PycelWrapper(ExcelCompiler):
        def __init__(self, *args, **kwargs):
            self.compiler = ExcelCompiler(*args, **kwargs)

        def evaluate(self, address, *args, **kwargs):
            range = AddressRange.create(address, *args, cell=self, **kwargs)
            return self.compiler.evaluate(range, *args, **kwargs)

        def set_value(self, address, *args, **kwargs):
            cell = AddressCell.create(address, *args, cell=self, **kwargs)
            return self.compiler.set_value(cell, *args, **kwargs)

        def __getattr__(self, name):
            return getattr(self.compiler, name)