Skip to content

Commit b427fc1

Browse files
committed
Updating README and namespacing package name
1 parent f9c3dba commit b427fc1

File tree

3 files changed

+188
-5
lines changed

3 files changed

+188
-5
lines changed

README.md

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
## Spreader
2+
3+
A fast spreadsheet logic library.
4+
5+
[![License](https://img.shields.io/badge/license-BSD-brightgreen.svg)](https://opensource.org/licenses/BSD-3-Clause)
6+
[![pypi](https://img.shields.io/pypi/v/spreader.py)](https://pypi.org/project/spreader.py)
7+
[![Python](https://img.shields.io/badge/Python-3.7-blue.svg)](https://docs.python.org/3/whatsnew/3.7.html)
8+
9+
<!-- References -->
10+
11+
[dynamicformulas]: <https://support.microsoft.com/en-us/office/dynamic-array-formulas-and-spilled-array-behavior-205c6b06-03ba-4151-89a1-87a7eb36e531> (Dynamic Array Formulas)
12+
13+
<!-- End References -->
14+
15+
Spreader is a zero dependency library that implements spreadsheet logic - reading and writing data and formulas into cells, automatic recalculation, copying and moving cells, adding and deleting rows and columns and so on. It does not implement any spreadsheet UI.
16+
It is currently in alpha stage.
17+
18+
## Install
19+
20+
Spreader is a C++ library. In order to install it from source you will need
21+
- Working C++ compiler supporting C++20 standard
22+
- macOS: Xcode 14 or above
23+
- Windows: Visual Studio 2022 or above
24+
- Linux: GCC 11.3 or above
25+
- On Linux you will also need Python development support (the python-dev or python3-dev package in most Linux distributions).
26+
No further external dependencies are required.
27+
28+
You can use pip to install the module
29+
30+
```bash
31+
pip install eg.spreader
32+
```
33+
34+
## Quick start
35+
36+
```python
37+
from eg.spreader import Sheet
38+
...
39+
40+
#Create a new sheet
41+
sheet = Sheet()
42+
#Set a cell to contain plain value. Instead of "A2"
43+
#you can also say Point(x=0, y=1) or just (0, 1) or [0, 1].
44+
#Columns are x and rows y, zero-based
45+
sheet.setValueCell("A2", "Hello ")
46+
sheet.setValueCell("B3", "World!")
47+
#Set a cell to contain formula
48+
sheet.setFormulaCell("A1", "A2 & B3")
49+
#Read calculated formula result
50+
val = s.getValue("A1")
51+
#val is "Hello Wolrd!" here
52+
```
53+
54+
## Limits
55+
56+
Maximum possible size of a sheet is currently 65536 x 2147483648 (e.g. 2<sup>16</sup> x 2<sup>31</sup>) cells.
57+
You can query this value via `Sheet.maxSize` property.
58+
Note that currently, sheets are held entirely in memory (there is no 'offloading' of unused data to some kind of storage).
59+
Thus, depending on how much memory you have available the actual limit on how big a sheet you will be able to create might
60+
be lower than maximum.
61+
62+
There is no hard limit on things like:
63+
- Maximum length of cell's string value
64+
- Maximum number of function arguments (for functions that support variable number of arguments like `SUM`)
65+
- Maximum level of nesting in formulas
66+
or anything else in the library. Instead, those are limited by available memory. In practice such limit is quite a bit larger than
67+
traditional `255` of Excel.
68+
69+
70+
## Cell and Area coordinates
71+
72+
Cell coordinates in the API can be given in the usual "A1", "B2" format. Alternatively, and slightly faster, you can use `Point(x=..., y=...)` objects or `(x, y)` tuples or `[x, y]` lists. In the later case `x` and `y` are zero based so `Point(x=0, y=0)` and `(0, 0)` correspond to "A1".
73+
74+
Similarly area coordinates can be given either as "A1:B2" or as `Rect(Point(x=..., y=...), Size(width=..., height=...))` or as
75+
`(x, y, width, height)` or `[x, y, width, height]`, whichever suits your needs more. As with individual cells, using "A1:B2" format is slightly slower.
76+
77+
## Cell values
78+
79+
Spreader supports the following cell value types: `None` (e.g. blank cell), `bool`, `float`, `str` and instances of its own
80+
`ErrorValue` class (e.g. `Errors.InvalidReference`) that represent the usual spreadsheet #-errors (e.g. `#REF!`).
81+
82+
Numbers contained in a cell are never NaNs and never infinite. Setting a NaN or infinite value cell will result in an `ErrorValue` instead.
83+
84+
Strings you set into a cell via `sheet.setValueCell()` call do not need to be escaped - they are always taken to be literal.
85+
For example `sheet.setValueCell("A1", "=3")` will result in a cell holding literal "=3" value as if you typed `'=3` in Excel
86+
or other spreadsheets.
87+
88+
## Supported formulas
89+
90+
Spreader supports all the operators (e.g. `=`, `+`, `>`, `*` etc.) supported by Excel.
91+
92+
[Dynamic array formulas][dynamicformulas] are fully supported. Therefor there is no need for `ARRAYFORMULA` and it isn't recognized.
93+
94+
The following functions are currently implemented:
95+
<details>
96+
<summary>Expand</summary>
97+
98+
* **A** \
99+
ADDRESS, AVERAGE, AVERAGEA, AVERAGEIF
100+
* **C** \
101+
CEIL, CHOOSE, COLUMN, CONCAT, CONCATENATE, COUNT, COUNTA
102+
* **D** \
103+
DATE, DATEDIF, DAY, DAYS
104+
* **E** \
105+
EDATE, EOMONTH, ERROR.TYPE
106+
* **F** \
107+
FIND, FLOOR
108+
* **H** \
109+
HLOOKUP, HOUR
110+
* **I** \
111+
IF, INDEX, INDIRECT, INT, ISBLANK, ISERR, ISERROR, ISEVEN, ISLOGICAL, ISNA, ISNONTEXT, ISNUMBER, ISODD, ISOWEEKNUM, ISTEXT
112+
* **L** \
113+
LEFT, LEN, LOWER
114+
* **M** \
115+
MATCH, MAX, MAXA, MID, MIN, MINA, MINUTE, MOD, MONTH, MROUND
116+
* **N** \
117+
NOT, NOW
118+
* **O** \
119+
OR
120+
* **R** \
121+
REPLACE, RIGHT, ROUND, ROUNDDOWN, ROUNDUP, ROW
122+
* **S** \
123+
SECOND, SIGN, STDEV, STDEV.P, STDEV.S, STDEVA, STDEVP, STDEVPA, SUBSTITUTE, SUM, SUMIF, SWITCH
124+
* **T** \
125+
TIME, TODAY, TRANSPOSE, TRIM
126+
* **U** \
127+
UPPER
128+
* **V** \
129+
VLOOKUP
130+
* **W** \
131+
WEEKDAY, WEEKNUM
132+
* **X** \
133+
XOR
134+
* **Y** \
135+
YEAR
136+
</details>
137+
138+
## Recalculation
139+
140+
By default sheet recalculation is automatic. You can suspend it using `sheet.suspendRecalc()` and resume it again using
141+
`sheet.resumeRecalc()`. Suspend calls can nest and each is "undone" by a corresponding resume. While suspended you can
142+
manually recalculate a sheet using `sheet.recalculate()`.
143+
144+
## Manipulating sheet size
145+
146+
Similar to how visual spreadsheets behave sheet size (as returned by `sheet.size()`) is dynamic and you don't manipulate
147+
it directly. When you set any cell to a non-null value sheet automatically expands to encompass it if it is outside
148+
the current size. It doesn't automatically contract, however. To reduce size you can use `sheet.deleteColumns()` and
149+
`sheet.deleteRows()` calls. Those, as well as `sheet.insertColumns()` and `sheet.insertRows()` can be used to
150+
delete/insert rows and columns anywhere in the sheet. Just like in visual spreadsheets all the references in formulas
151+
will be automatically adjusted to account for insertion or deletion.
152+
153+
## Copying and moving cells
154+
155+
Normal copying and moving semantics of spreadsheets are also fully supported. You can use:
156+
- `sheet.copyCell()` to copy a single cell to a single cell or area.
157+
- `sheet.copyCells()` (note the plural) to copy an area to another location given by its top left corner
158+
- `sheet.moveCell()` to move a single cell to a new location (also a single cell)
159+
- `sheet.moveCells()` to move a cell area to a new location given by its top left corner
160+
161+
For all these calls the formula references are adjusted in normal spreadsheet fashion.
162+
163+
164+
## Roadmap and missing features
165+
166+
Spreader is currently in alpha - implemented features work and work well but many desirable things are missing.
167+
In particular, it is currently impossible to implement a full, performant spreadsheet UI on top of it. This is
168+
mostly due to lack of things such as change notifications, undo and support of keeping track of cell formatting.
169+
With this in mind the following features are on the roadmap
170+
171+
- Change notifications to enable clients to react to cells changed during recalculation
172+
- Ability to associate abstract formatting information with cells rows and columns. Spreader itself doesn't care
173+
about formatting - it just needs to keep track of it for clients to act upon.
174+
- Support conditional formatting formulas. Similar to above associate opaque format with boolean formulas and tell
175+
the client which one to use.
176+
- Support optional undo. It needs to be optional because it will slow things down and not all clients need it.
177+
- Support more functions in formulas
178+
- Support localized formula input. Currently formula syntax must use US English syntax: `.` as decimal separator, `,` to separate
179+
arguments. Excel allows using `,` and `;` for languages that use comma as decimal separator.
180+
- Serialization/deserialization. Likely in `xlsx` and `json`.
181+
- Maybe: support doing spreadsheet math using decimals rather than doubles.
182+
183+

setup.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
""".splitlines()
3535

3636
setup(
37-
name="spreader",
37+
name="eg.spreader",
3838
version="0.1.dev1",
3939
description="Fast spreadsheet logic library",
4040
long_description=README,
@@ -45,14 +45,14 @@
4545
download_url="http://pypi.python.org/pypi/spreader/",
4646
license="BSD-3-Clause",
4747
package_dir={'':'code/wrappers/python/src'},
48-
packages=['spreader'],
48+
packages=['eg.spreader'],
4949
package_data = {
50-
'spreader': ['py.typed'],
50+
'eg.spreader': ['py.typed'],
5151
},
5252
python_requires=">=3.7",
5353

5454
cmake_source_dir="code",
5555
cmake_args=[
56-
'-DSPR_PYTHON_PACKAGE_DIR=code/wrappers/python/src'
56+
'-DSPR_PYTHON_PACKAGE_DIR=code/wrappers/python/src/eg'
5757
]
5858
)

0 commit comments

Comments
 (0)