ipysheet icon indicating copy to clipboard operation
ipysheet copied to clipboard

Would be good to have a get_cell(i, j) method to Sheet

Open oscar6echo opened this issue 7 years ago • 9 comments

This would be convenient as not all cells need be remembered to retrieve their value.

Maybe something as simple that ?

def get_cell(sheet, i, j):
    for cell in sheet.cells:
        if cell.row == i and cell.column == j:
            return cell

oscar6echo avatar Jan 21 '18 23:01 oscar6echo

Sound good, or maybe even do:

sheet[0,1].value = 3

What if it does not exist? Create it or throw an exception? I'd say you have to create it first.

maartenbreddels avatar Jan 22 '18 14:01 maartenbreddels

Yes, I like your version better.
I guess it should throw an error if the cell does not exist.
Agree that creation should be handled separately.

oscar6echo avatar Jan 22 '18 14:01 oscar6echo

I think we should also think about 'named' cells, so it's easy to refer to them by name, e.g.:

cell = ipysheet.cell(0, 0, value=4, name='interest')
....
assert cell is sheet['interest']

There is already a bit of support for this, since cells could be created at the frontend, and have a 'name'.

maartenbreddels avatar Jan 22 '18 15:01 maartenbreddels

Yes indeed.
Actually I did it manually in the ipysheet-demo.
Undoubtedly this will be a frequent use case.

oscar6echo avatar Jan 22 '18 16:01 oscar6echo

What are the reasons for throwing if the cell doesn't exist?

I feel like __getitem__ should return None if the cell does not exist yet, and __setitem__ should simply create it. I might be wrong though. I've never really been a user of Excel or table sheets libraries in general so I suppose my feelings could be wrong :P

martinRenou avatar Feb 07 '19 11:02 martinRenou

I feel like __getitem__ should return None

I think that's not very Pythonic, I would say, implement https://docs.python.org/3/library/collections.abc.html#collections.abc.MutableMapping (I don't think we can inherit from it btw, gives issues here). But for this behaviour you probably want to implement get (https://github.com/python/cpython/blob/3.7/Lib/_collections_abc.py#L641)

We could have setitem create a cell on the fly, that could be useful.

maartenbreddels avatar Feb 07 '19 12:02 maartenbreddels

Maybe it should return None if the indices are in bounds concerning the sheet size? And throw if it's out of bounds?

martinRenou avatar Feb 07 '19 12:02 martinRenou

I think always in Python obj[key] should throw a KeyError, and obj[index'] should throw an IndexError when key/index is not found.

maartenbreddels avatar Feb 07 '19 13:02 maartenbreddels

Because cells are sometimes actually cell ranges, I'm thinking about this implementation:

def __getitem__(self, item):
    cell = None
    row, column = item
    
    for c in self.cells:
        if c.row_start <= row <= c.row_end and c.column_start <= column <= c.column_end:
            cell = c

    if cell is None:
        raise IndexError('no cell was previously created for (row, index) = (%s, %s)'.format(row, column))

    return cell

It would allow getting access to cell ranges, and return the last added cell if some cells are overlapping. But the following would not make sense in the case of a cell range:

sheet[0, 1].value = 3

So my implementation could be confusing for users.

The current implementation is:

def __getitem__(self, item):
    row, column = item
    for cell in self.cells:
        if cell.row_start == row and cell.column_start == column \
           and cell.row_end == row and cell.column_end == column:
            return cell
    raise IndexError('no cell was previously created for (row, index) = (%s, %s)'.format(row, column))

martinRenou avatar Mar 12 '19 16:03 martinRenou