{ "info": { "author": "imjp94", "author_email": "imjp0921@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "License :: OSI Approved :: MIT License", "Topic :: Database", "Topic :: Office/Business :: Financial :: Spreadsheet", "Topic :: Utilities" ], "description": "[![Build Status](https://travis-ci.com/imjp94/cellbase.svg?branch=dev)](https://travis-ci.com/imjp94/cellbase)\n[![Build Status](https://travis-ci.com/imjp94/cellbase.svg?branch=master)](https://travis-ci.com/imjp94/cellbase)\n\n# Cellbase v0.1.2\n\nAbstraction layer for accessing spreadsheet as database, built on top\nof [openpyxl](https://openpyxl.readthedocs.io/en/stable/).\n\n## Usage\n\nRead, write or edit spreadsheet in database like environment, for example:\n\n```python\ncellbase = Cellbase().load('simple.xlsx')\ndao = SimpleDAO(cellbase) # Object inherits from DAO\nentity = Simple(id=1, name='jp') # Object inherits from Entity\n# Basic database operations\ndao.insert(entity)\ndao.query({'row_idx': entity.row_idx})\nentity.name = 'imjp'\ndao.update(entity)\ndao.delete({'row_idx': entity.row_idx})\n# Format cells' font, fill, border, etc...\ndao.format({'row_idx': entity.row_idx},\n fill=PatternFill(fill_type=\"solid\", fgColor=\"00FFFF00\"))\n# Access openpyxl.cell.Cell directly\ndao.traverse(lambda cell: do_something(cell),\n {'row_idx': entity.row_idx}, select=['id'])\ncellbase.save()\n```\n\n## Installing\n\nInstall from pypi:\n\n```console\npip install cellbase\n```\n\n## For Your Information\n\nThere are some rules/concepts being followed by Cellbase,\nnot necessary to know but it is nice to be awared of them.\n\n- Cellbase = Workbook = Database\n- Celltable = Worksheet = Table\n- DAO is the helper to access data from Cellbase\n- Entity is resposible to convert data to/from dict\n- Cellbase named 'load' for reading file instead of 'open' as currently it\n does not open connection/stream to file, which means any changes made\n are not saved or updated until save/save_as is called\n- Implemetation of DAO & Entity are optional\n- 'where' argument in most methods expect dict in format as below:\n ```python\n where = {'col_name_1', value_1, 'col_name_2': value_2}\n ```\n- 'select' argument in traverse & format expect list in format as below:\n ```python\n select = ['col_name_1', 'col_name_2']\n ```\n- 'row_idx' is the actual row index in spreadsheet\n- 'row_idx' starts from 2 as 1st row is taken by header, which means:\n ```python\n dao.query({'row_idx', 1}) # Will raise KeyError\n ```\n- Cellbase doesn't expect input values(dict) consist of 'row_idx' but values\n returned by query() will definitely consist 'row_idx'\n- Cellbase expect variable names declared in first row.\n\n Empty variable will caused whole column to be ignored(column 3).\n\n It doesn't really matter for rows, empty row as row 3 is still a valid\n row.\n\n | var_1 | var_2 | (empty) | var_3 |\n |---------|---------|---------|---------|\n | data | data | data | data |\n | (empty) | (empty) | (empty) | (empty) |\n | data | data | (empty) | data |\n\n## Getting Started\n\nCellbase is made to be easily picked up, you may start right away in python\nconsole or implement DAO & Entity to simplify the codes in your scripts.\n\n```python\nfrom cellbase import Cellbase\n\n# Without specifying filename, it will save as 'cellbase.xlsx' by default\ncellbase = CellBase() \n# Register the format of worksheet to deal with(only for new worksheet)\n# 'Simple' is the worksheet name, while 'id' and 'name' are column names\ncellbase.register({'Simple': ['id', 'name']})\n```\n\n- Without DAO & Entity:\n ```python\n row_idx = cellbase.insert('Simple', {'id': 1, 'name': 'jp'})\n values = cellbase.query('Simple', {'row_idx': row_idx})\n cellbase.update('Simple', {'row_idx': row_idx, 'id': 1, 'name': 'imjp'})\n cellbase.delete('Simple', {'row_idx': row_idx})\n ```\n\n- With DAO & Entity:\n\n First create DAO,\n ```python\n dao = SimpleDAO(cellbase)\n ```\n then do what the last example did,\n\n except saving declaration of table name &\n access data from object inherits Entity\n ```python\n entity = Simple(id=1, name='jp')\n dao.insert(entity)\n dao.query({'row_idx': entity.row_idx})\n entity.name = 'imjp'\n dao.update(entity)\n dao.delete({'row_idx': entity.row_idx})\n ```\n\nFinally, save it to file\n\n```python\ncellbase.save()\n```\n\n## More\n\n### Cellbase load, save, save_as, drop, register\n\nLoad from file\n\n```python\ncellbase.load('filename.xlsx')\n```\n\nSave to filename used in load, otherwise,\ncurrent working directory as 'cellbase.xlsx'\n\n```python\ncellbase.save()\n```\n\nSave as another file, will raise FileExistsError if overwrite is False\n\n```python\ncellbase.save_as('another_filename.xlsx', overwrite=True)\n```\n\nDrop worksheet\n\n```python\ncellbase.drop('worksheet_name')\n# or drop with DAO\ndao.drop()\n```\n\nRegister structure of worksheet to deal with(only required for new worksheet),\notherwise, ValueError will be raised when creating worksheet as Cellbase\ndoesn't know what are the title of worksheet and column names to create.\n\n```python\ncellbase.register({'TABLE_NAME_1': ['COL_NAME_1', 'COL_NAME_2']})\n```\n\n### Example of DAO & Entity\n\nDAO\n\n```python\nfrom cellbase import DAO\n\n\nclass SimpleDAO(DAO):\n # Optional, just to make life easier\n TABLE_NAME = 'Simple'\n COL_ID = 'id'\n COL_NAME = 'name'\n\n def worksheet_name(self):\n return SimpleDAO.TABLE_NAME\n\n def new_entity(self):\n return Simple() # New instance of entity for query to return result\n```\n\nEntity\n\n```python\nfrom cellbase import Entity\n\n\nclass Simple(Entity):\n def __init__(self, id=0, name=\"\"):\n super().__init__() # Declare row_idx\n self.id = id\n self.name = name\n\n def from_dict(self, values):\n super().from_dict(values) # Inherits to handle row_idx\n self.id = values[SimpleDAO.COL_ID]\n self.name = values[SimpleDAO.COL_NAME]\n return self\n\n def to_dict(self):\n values = super().to_dict() # Inherits to handle row_idx\n values[SimpleDAO.COL_ID] = self.id\n values[SimpleDAO.COL_NAME] = self.name\n return values\n```\n\n### Lambda\n\nAfter getting used with Cellbase you might find that simple\nequality search like this is not enough:\n\n```python\ndao.query({'id': 1, 'name': 'imjp'})\n```\n\nFor example, if you need to access all records where name contains 'jp',\nyou might find lambda useful:\n\n```python\ndao.query({'name': lambda value: 'jp' in value})\ndao.update(entity, {'name': lambda value: 'jp' in value})\n\ncellbase.query(worksheet_name, {'name': lambda value: 'jp' in value})\ncellbase.update(worksheet_name, data, {'name': lambda value: 'jp' in value})\n# So as traverse & format...\n```\n\nor find with row_idx\n\n```python\ndao.query({'row_idx': lambda row_idx: 3 <= row_idx <= 9})\ndao.update(entity, {'row_idx': lambda row_idx: 3 <= row_idx <= 9})\n\ncellbase.query(worksheet_name, {'row_idx': lambda row_idx: 3 <= row_idx <= 9})\ncellbase.update(worksheet_name, data, {'row_idx': lambda row_idx: 3 <= row_idx <= 9})\n# So as traverse & format...\n```\n\n### Magic method(Must implement DAO & Entity)\n\n```python\n# Magic method only works with row_idx\ntotal_row_number = len(dao) # __len__\nentity = dao[row_idx] # __getitem__\ndao[row_idx] = entity # __setitem__\ncontains = row_idx in dao # __contains__\ndel dao[row_idx] # __delitem\n\n# Of course it works with lambda/callable too\nentity = dao[lambda row_idx: 3 <= row_idx <= 9] # __getitem__\ncontains = lambda row_idx: 3 <= row_idx <= 9 in dao # __contains__\ndel dao[lambda row_idx: 3 <= row_idx <= 9] # __delitem\n# Exception\n# __setitem__ only support update, insertion will raise warning\nif lambda row_idx: 3 <= row_idx <= 9 in dao:\n dao[lambda row_idx: 3 <= row_idx <= 9] = entity # update\nelse:\n dao[lambda row_idx: 3 <= row_idx <= 9] = entity # no effect at all\n```\n\n### Formatting\n\nOther than setting value, you may format cells as well:\n\n```python\ndao.format(where, select, fill, font, border...)\n# or wrap all formats in CellFormatter\ndao.format(where, select, cell_formatter)\n```\nSee [CellFormatter](cellbase/helper/helper.py), for more information.\n\n### Low Level Access\n\nLow level might be a strong word, but you can have direct access to\ncells(openpyxl.cell.Cell) through traverse:\n\n```python\ndao.traverse(lambda cell: do_something(cell), where, select)\n```\n\n### For more example, checkout [Tests](tests/cellbase_test.py)\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/imjp94/cellbase", "keywords": "spreadsheet excel database query abstraction utility", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "cellbase", "package_url": "https://pypi.org/project/cellbase/", "platform": "", "project_url": "https://pypi.org/project/cellbase/", "project_urls": { "Homepage": "https://github.com/imjp94/cellbase" }, "release_url": "https://pypi.org/project/cellbase/0.1.2/", "requires_dist": [ "openpyxl" ], "requires_python": "", "summary": "Abstraction layer for accessing spreadsheet as database", "version": "0.1.2" }, "last_serial": 4166457, "releases": { "0.1.1": [ { "comment_text": "", "digests": { "md5": "174ef1afbe478b7b2fdae9077b25683d", "sha256": "2211be7a39b08e812fd4ffcb025c8845cc6ecfaab7e95d21df39ef6c554e88f4" }, "downloads": -1, "filename": "cellbase-0.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "174ef1afbe478b7b2fdae9077b25683d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 15454, "upload_time": "2018-08-13T13:31:13", "url": "https://files.pythonhosted.org/packages/b6/1a/0c8c999fff0a1443de52908cceb772c09967b708ab4912046a0cbd7fd430/cellbase-0.1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "176cf79e0029a4ca1c4b220163d6e6bc", "sha256": "7dddee73e72afdea6b4227eb08e479a89b52d9c439d7c43119bc23c6dfebaf7b" }, "downloads": -1, "filename": "cellbase-0.1.1.tar.gz", "has_sig": false, "md5_digest": "176cf79e0029a4ca1c4b220163d6e6bc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12803, "upload_time": "2018-08-13T13:31:15", "url": "https://files.pythonhosted.org/packages/6a/9d/b9f97e6c1e61c5085db4ec2337d5693a62aa234d9ec75cdf9d38c80bec28/cellbase-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "3aa64b6c14eb3fff1ac4fc30e5068db5", "sha256": "329dc28f67919a51a85a65b3f11465ec3ae5e5b0ec42ae023e4208ae439454b2" }, "downloads": -1, "filename": "cellbase-0.1.2-py3-none-any.whl", "has_sig": false, "md5_digest": "3aa64b6c14eb3fff1ac4fc30e5068db5", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 13321, "upload_time": "2018-08-13T18:11:58", "url": "https://files.pythonhosted.org/packages/63/9b/4724b148dc23351053887984ad2097f488debd8be16a78e9b9543e5da176/cellbase-0.1.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "51a6a20d1a7129fdef7b2969d76fa85b", "sha256": "4471de161cdfadc8afbdbda6512df0018959c6cdaec6903b2076f83609f28ac0" }, "downloads": -1, "filename": "cellbase-0.1.2.tar.gz", "has_sig": false, "md5_digest": "51a6a20d1a7129fdef7b2969d76fa85b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11309, "upload_time": "2018-08-13T18:11:59", "url": "https://files.pythonhosted.org/packages/93/24/3a510d0cbb970efb298b4970adec0b276d86d3356e26acb33a74af1d5e15/cellbase-0.1.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "3aa64b6c14eb3fff1ac4fc30e5068db5", "sha256": "329dc28f67919a51a85a65b3f11465ec3ae5e5b0ec42ae023e4208ae439454b2" }, "downloads": -1, "filename": "cellbase-0.1.2-py3-none-any.whl", "has_sig": false, "md5_digest": "3aa64b6c14eb3fff1ac4fc30e5068db5", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 13321, "upload_time": "2018-08-13T18:11:58", "url": "https://files.pythonhosted.org/packages/63/9b/4724b148dc23351053887984ad2097f488debd8be16a78e9b9543e5da176/cellbase-0.1.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "51a6a20d1a7129fdef7b2969d76fa85b", "sha256": "4471de161cdfadc8afbdbda6512df0018959c6cdaec6903b2076f83609f28ac0" }, "downloads": -1, "filename": "cellbase-0.1.2.tar.gz", "has_sig": false, "md5_digest": "51a6a20d1a7129fdef7b2969d76fa85b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11309, "upload_time": "2018-08-13T18:11:59", "url": "https://files.pythonhosted.org/packages/93/24/3a510d0cbb970efb298b4970adec0b276d86d3356e26acb33a74af1d5e15/cellbase-0.1.2.tar.gz" } ] }