Package: numbers-parser
numbers-parsernumbers-parseris a Python module for parsingApple Numbers.numbersfiles. It supports Numbers files
generated by Numbers version 10.3, and up with the latest tested version being 13.2
(current as of September 2023).It supports and is tested against Python versions from 3.8 onwards. It is not compatible
with earlier versions of Python.Installationpython3-mpipinstallnumbers-parserA pre-requisite for this package ispython-snappywhich will be installed by Python automatically, but python-snappy also requires that the binary
libraries for snappy compression are present.The most straightforward way to install the binary dependencies is to useHomebrewand source Python from Homebrew rather than from macOS as described
in thepython-snappy github:For Intel Macs:brewinstallsnappypython3CPPFLAGS="-I/usr/local/include -L/usr/local/lib"\python3-mpipinstallpython-snappyFor Apple Silicon Macs:brewinstallsnappypython3CPPFLAGS="-I/opt/homebrew/include -L/opt/homebrew/lib"\python3-mpipinstallpython-snappyFor Linux (your package manager may be different):sudoapt-get-yinstalllibsnappy-devOn Windows, you will need to either arrange for snappy to be found for VSC++ or you can install python
binary libraries compiled byChristoph Gohlke. You must select the correct python
version for your installation. For example for python 3.11:pip install python_snappy-0.6.1-cp311-cp311-win_amd64.whlQuick StartReading documents:>>>fromnumbers_parserimportDocument>>>doc=Document("mydoc.numbers")>>>sheets=doc.sheets>>>tables=sheets[0].tables>>>rows=tables[0].rows()Sheets and tables are iterables that can be indexed using either an
integer index or using the name of the sheet/table:>>>doc.sheets[0].name'Sheet 1'>>>doc.sheets["Sheet 1"].name'Sheet 1'>>>doc.sheets[0].tables[0].name'Table 1'>>>doc.sheets[0].tables["Table 1"].name'Table 1'Tableobjects have arowsmethod which contains a nested list
with an entry for each row of the table. Each row is itself a list of
the column values.>>>data=sheets["Sheet 1"].tables["Table 1"].rows()>>>data[0][0]<numbers_parser.cell.EmptyCellobjectat0x1022b5710>>>>data[1][0]<numbers_parser.cell.TextCellobjectat0x101eb6790>>>>data[1][0].value'Debit'Cell DataCells are objects with a common base class ofCell. All cell types
have a propertyvaluewhich returns the contents of the cell as a
python datatype.numbers-parserusespenduluminstead of python’s builtin
types. Available cell types are:Cell typevalue typeAdditional propertiesNumberCellfloatTextCellstrRichTextCellstrSeeRich textEmptyCellNoneBoolCellboolDateCellpendulum.datetimeDurationCellpendulum.durationErrorCellNoneMergedCellNoneSeeMerged cellsCell references can be either zero-offset row/column integers or an
Excel/Numbers A1 notation. Where cell values are notNonethe
propertyformatted_valuereturns the cell value as astras
displayed in Numbers. Cells that have no values in a table are
represented asEmptyCelland cells containing evaluation errors of
any kindErrorCell.>>>table.cell(1,0)<numbers_parser.cell.TextCellobjectat0x1019ade50>>>>table.cell(1,0).value'Debit'>>>table.cell("B2")<numbers_parser.cell.NumberCellobjectat0x103a99790>>>>table.cell("B2").value1234.5>>>table.cell("B2").formatted_value'£1,234.50'Pandas SupportSince the return value ofrows()is a list of lists, you can pass
this directly to pandas. Assuming you have a Numbers table with a single
header which contains the names of the pandas series you want to create
you can construct a pandas dataframe using:importpandasaspddoc=Document("simple.numbers")sheets=doc.sheetstables=sheets[0].tablesdata=tables[0].rows(values_only=True)df=pd.DataFrame(data[1:],columns=data[0])Writing Numbers DocumentsWhilst support for writing numbers files has been stable since version
3.4.0, you are highly recommended not to overwrite working Numbers files
and instead save data to a new file.Cell values are written usingTable.write()andnumbers-parserwill automatically create empty rows and columns
for any cell references that are out of range of the current table.doc=Document("write.numbers")sheets=doc.sheetstables=sheets[0].tablestable=tables[0]table.write(1,1,"This is new text")table.write("B7",datetime(2020,12,25))doc.save("new-sheet.numbers")Additional tables and worksheets can be added to aDocumentbefore saving usingDocument.add_sheet()andSheet.add_table()respectively:doc=Document()doc.add_sheet("New Sheet","New Table")sheet=doc.sheets["New Sheet"]table=sheet.tables["New Table"]table.write(1,1,1000)table.write(1,2,2000)table.write(1,3,3000)doc.save("sheet.numbers")Stylesnumbers_parsercurrently only supports paragraph styles and cell
styles. The following styles are supported:font attributes: bold, italic, underline, strikethroughfont selection and sizetext foreground colorhorizontal and vertical alignmentcell background colorcell background imagescell indents (first line, left, right, and text inset)Numbers conflates style attributes that can be stored in paragraph
styles (the style menu in the text panel) with the settings that are
available on the Style tab of the Text panel. Some attributes in Numbers
are not applied to new cells when a style is applied.To keep the API simple,numbers-parserpacks all styling into a singleStyleobject. When a document is saved, the attributes
not stored in a paragraph style are applied to each cell that includes it.Styles are read from cells using theCell.styleproperty and you can
add new styles withDocument.add_style.red_text=doc.add_style(name="Red Text",font_name="Lucida Grande",font_color=RGB(230,25,25),font_size=14.0,bold=True,italic=True,alignment=Alignment("right","top"),)table.write("B2","Red",style=red_text)table.set_cell_style("C2",red_text)Cell Data FormattingNumbers has two different cell formatting types: data formats and custom
formats.Data formats are presented in Numbers in the Cell tab of the Format pane
and are applied to individual cells. Like Numbers,numbers-parserscaches formatting information that is identical across multiple cells.
You do not need to take any action for this to happen; this is handled
internally by the package. Changing a data format for cell has no impact
on any other cells.Cell formats are changed usingTable.set_cell_formatting():table.set_cell_formatting("C1","date",date_time_format="EEEE, d MMMM yyyy")table.set_cell_formatting(0,4,"number",decimal_places=3,negative_style=NegativeNumberStyle.RED)Custom formats are shared across a Document and can be applied to
multiple cells in multiple tables. Editing a custom format changes the
appearance of data in all cells that share that format. You must first
add a custom format to the document usingDocument.add_custom_format()before assigning it to cells usingTable.set_cell_formatting():long_date=doc.add_custom_format(name="Long Date",type="date",date_time_format="EEEE, d MMMM yyyy")table.set_cell_formatting("C1","custom",format=long_date)A limited number of currencies are formatted using symbolic notation
rather than an ISO code. These are defined innumbers_parser.currenciesand match the ones chosen by Numbers. For
example, US dollars are referred to asUS$whereas Euros and British
Pounds are referred to using their symbols of€and£respectively.Bordersnumbers-parsersupports reading and writing cell borders, though the
interface for each differs. Individual cells can have each of their four
borders tested, but when drawing new borders, these are set for the
table to allow for drawing borders across multiple cells. Setting the
border of merged cells is not possible unless the edge of the cells is
at the end of the merged region.Borders are represented using theBorderclass
that can be initialized with line width, color and line style. The
current state of a cell border is read using theCell.borderproperty
andTable.set_cell_border()sets the border for a cell edge or a range of cells.APIFor more examples and details of all available classes and methods,
see thefull API docs.Command-line scriptsWhen installed fromPyPI,
a command-like scriptcat-numbersis installed in Python’s scripts
folder. This script dumps Numbers spreadsheets into Excel-compatible CSV
format, iterating through all the spreadsheets passed on the
command-line.usage: cat-numbers [-h] [-T | -S | -b] [-V] [--formulas] [--formatting]
                  [-s SHEET] [-t TABLE] [--debug]
                  [document ...]

Export data from Apple Numbers spreadsheet tables

positional arguments:
  document              Document(s) to export

options:
  -h, --help            show this help message and exit
  -T, --list-tables     List the names of tables and exit
  -S, --list-sheets     List the names of sheets and exit
  -b, --brief           Don't prefix data rows with name of sheet/table
                        (default: false)
  -V, --version
  --formulas            Dump formulas instead of formula results
  --formatting          Dump formatted cells (durations) as they appear
                        in Numbers
  -s SHEET, --sheet SHEET
                        Names of sheet(s) to include in export
  -t TABLE, --table TABLE
                        Names of table(s) to include in export
  --debug               Enable debug loggingNote:--formattingwill return different capitalization for 12-hour
times due to differences between Numbers’ representation of these dates
anddatetime.strftime. Numbers in English locales displays 12-hour
times with ‘am’ and ‘pm’, butdatetime.strftimeon macOS at least
cannot return lower-case versions of AM/PM.LimitationsCurrent known limitations ofnumbers-parserare:Formulas cannot be written to a documentTable styles that allow new tables to adopt a style across the whole
table are not planned.Creating cells of typeBulletedTextCellis not supportedNew tables are inserted with a fixed offset below the last table in a
worksheet which does not take into account title or caption sizeNew sheets insert tables with formats copied from the first table in
the previous sheet rather than default table formatsDue to a limitation in Python’sZipFile, Python
versions older than 3.11 do not support image filenames with UTF-8
characters (seeissue
69).Cell.style.bg_imagereturnsNonefor such files and issues aRuntimeWarning.Pivot tables are unsupported, but re-saving a document is believed to work. Saving a document with a pivot table issues a UnsupportedWarning.LicenseAll code in this repository is licensed under theMIT License.