Skip to main content

Convert between various formats (YAML, JSON, XLSX, ODS, CSV) to Markdown Tables

Project description

madato

Rust CI workflow Python CI workflow Rust Version Rust Version

madato is a library and command line tool for working tabular data, and Markdown


  1. madato (library) - this library, which reads YAML, CSV, JSON, XLSX/ODS and writes Markdown
  2. madato (cli) - providing a helpful command line tool of the above
  3. The full library is available as a python module, or a rust library.

The tools is primarly centered around getting tabular data (spreadsheets, CSVs) into Markdown.

Usage

CLI

Download from https://github.com/inosion/madato/releases

Rust

The library, if you need spreadsheet support, then add the spreadsheets feature.

madato = { version = "0", features = ["spreadsheets"] }

Python

pip install madato

Details

When generating the output:

  • Filter the Rows using basic Regex over Key/Value pairs
  • Limit the columns to named headings
  • Re-order the columns, or repeat them using the same column feature
  • Only generate a table for a named "sheet" (applicable for the XLS/ODS formats)

Madato is:

  • Command Line Tool (Windows, Mac, Linux) - good for CI/CD preprocessing
  • Rust Library - Good for integration into Rust Markdown tooling
  • Node JS WASM API - To be used later for Atom and VSCode Extensions

Madato expects that every column has a heading row. That is, the first row are headings/column names. If a cell in that first row is blank, it will create NULL0..NULLn entries as required.

Example CLI usage

  • Extract the 3rd Sheet sheet from an MS Excel Document
08:39 $ madato table --type xlsx test/sample_multi_sheet.xlsx --sheetname "3rd Sheet"
|col1|col2| col3 |col4 |                         col5                          |NULL5|
|----|----|------|-----|-------------------------------------------------------|-----|
| 1  |that| are  |wider|  value ‘aaa’ is in the next cell, but has no heading  | aaa |
|than|the |header| row |       (open the spreadsheet to see what I mean)       |     |
  • Extract and reorder just 3 Columns
08:42 $ madato table --type xlsx test/sample_multi_sheet.xlsx --sheetname "3rd Sheet" -c col2 -c col3 -c NULL5
|col2| col3 |NULL5|
|----|------|-----|
|that| are  | aaa |
|the |header|     |
  • Pull from the second_sheet sheet
  • Only extract Heading 4 column
  • Use a Filter, where Heading 4 values must only have a letter or number.
08:48 $ madato table --type xlsx test/sample_multi_sheet.xlsx --sheetname second_sheet -c "Heading 4" -f 'Heading 4=[a-zA-Z0-9]'
|        Heading 4         |
|--------------------------|
|         << empty         |
|*Some Bolding in Markdown*|
|   `escaped value` foo    |
|           0.22           |
|         #DIV/0!          |
|  “This cell has quotes”  |
|       😕 ← Emoticon       |
  • Filtering on a Column, ensuring that a "+" is there in Trend Column
09:00 $ madato table --type xlsx test/sample_multi_sheet.xlsx --sheetname Sheet1 -c Rank -c Language -c Trend -f "Trend=\+"
|                         Rank                         |  Language  |Trend |
|------------------------------------------------------|------------|------|
|                          1                           |   Python   |+5.5 %|
|                          3                           | Javascript |+0.2 %|
|                          7                           |     R      |+0.0 %|
|                          12                          | TypeScript |+0.3 %|
|                          16                          |   Kotlin   |+0.5 %|
|                          17                          |     Go     |+0.3 %|
|                          20                          |    Rust    |+0.0 %|

Internals

madato uses:

  • calamine for reading XLS and ODS sheets
  • wasm bindings to created JS API versions of the Rust API
  • regex for filtering, and serde for serialisation.
  • PyO3 and Maturin for Python Support

Tips

  • I have found that copying the "table" I want from a website: HTML, to a spreadsheet, then through madato gives an excellent Markdown table of the original.

Python

pip install madato

# py
from IPython.display import display, Markdown
import madato
display(Markdown(madato.spreadsheet_to_md("../test/Financial Sample.xlsx")
print(madato.spreadsheet_to_md(str(my_sample_spreadsheet)))

More Commandline

Sheet List

You can list the "sheets" of an XLS*, ODS file with

$ madato sheetlist test/sample_multi_sheet.xlsx 
Sheet1
second_sheet
3rd Sheet

YAML to Markdown

Madato reads a "YAML" file, in the same way it can a Spreadsheet. This is useful for "keeping" tabular data in your source repository, and perhaps not the XLS.

madato table -t yaml test/www-sample/test.yml

|col3| col4  |  data1  |       data2        |
|----|-------|---------|--------------------|
|100 |gar gar|somevalue|someother value here|
|190x|       |  that   |        nice        |
|100 | ta da |  this   |someother value here|

Please see the test/www-sample/test.yml file for the expected layout of this file

Excel/ODS to YAML

Changing the output from default "Markdown (MD)" to "YAML", you get a Markdown file of the Spreadsheet.

madato table -t xlsx test/sample_multi_sheet.xslx.xlsx -s Sheet1 -o yaml
---
- Rank: "1"
  Change: ""
  Language: Python
  Share: "23.59 %"
  Trend: "+5.5 %"
- Rank: "2"
  Change: ""
  Language: Java
  Share: "22.4 %"
  Trend: "-0.5 %"
- Rank: "3"
  Change: ""
  Language: Javascript
  Share: "8.49 %"
...

If you omit the sheet name, it will dump all sheets into an order map of array of maps.

Features

  • [x] Reads a formatted YAML string and renders a Markdown Table
  • [x] Can take an optional list of column headings, and only display those from the table (filtering out other columns present)
  • [X] Native Binary Command Line (windows, linux, osx)
  • [X] Read an XLSX file and produce a Markdown Table
  • [X] Read an ODS file and produce a Markdown Table
  • [X] Read a CSV
  • [X] Published as a Python Module
  • [ ] TSV, PSV (etc) file and produce a Markdown Table
  • [ ] Support Nested Structures in the YAML input
  • [ ] Read a Markdown File, and select the "table" and turn it back into YAML

Future Goals

Known Issues

License

Serde is licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Serde by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

madato-0.7.0.tar.gz (82.9 kB view hashes)

Uploaded Source

Built Distributions

madato-0.7.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

madato-0.7.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.9 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ s390x

madato-0.7.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.7 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ppc64le

madato-0.7.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARMv7l

madato-0.7.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARM64

madato-0.7.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl (1.7 MB view hashes)

Uploaded PyPy manylinux: glibc 2.5+ i686

madato-0.7.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

madato-0.7.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.9 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ s390x

madato-0.7.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.7 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ppc64le

madato-0.7.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARMv7l

madato-0.7.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARM64

madato-0.7.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl (1.7 MB view hashes)

Uploaded PyPy manylinux: glibc 2.5+ i686

madato-0.7.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

madato-0.7.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.9 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ s390x

madato-0.7.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.7 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ppc64le

madato-0.7.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARMv7l

madato-0.7.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARM64

madato-0.7.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl (1.7 MB view hashes)

Uploaded PyPy manylinux: glibc 2.5+ i686

madato-0.7.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

madato-0.7.0-pp37-pypy37_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.9 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ s390x

madato-0.7.0-pp37-pypy37_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.7 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ppc64le

madato-0.7.0-pp37-pypy37_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARMv7l

madato-0.7.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ ARM64

madato-0.7.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl (1.7 MB view hashes)

Uploaded PyPy manylinux: glibc 2.5+ i686

madato-0.7.0-cp312-none-win_amd64.whl (673.2 kB view hashes)

Uploaded CPython 3.12 Windows x86-64

madato-0.7.0-cp312-none-win32.whl (658.3 kB view hashes)

Uploaded CPython 3.12 Windows x86

madato-0.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ x86-64

madato-0.7.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.8 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ s390x

madato-0.7.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.7 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ppc64le

madato-0.7.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.6 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ARMv7l

madato-0.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.6 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ARM64

madato-0.7.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl (1.7 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.5+ i686

madato-0.7.0-cp312-cp312-macosx_11_0_arm64.whl (802.0 kB view hashes)

Uploaded CPython 3.12 macOS 11.0+ ARM64

madato-0.7.0-cp312-cp312-macosx_10_12_x86_64.whl (817.8 kB view hashes)

Uploaded CPython 3.12 macOS 10.12+ x86-64

madato-0.7.0-cp311-none-win_amd64.whl (673.2 kB view hashes)

Uploaded CPython 3.11 Windows x86-64

madato-0.7.0-cp311-none-win32.whl (658.8 kB view hashes)

Uploaded CPython 3.11 Windows x86

madato-0.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

madato-0.7.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.8 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ s390x

madato-0.7.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.7 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ppc64le

madato-0.7.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.6 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ARMv7l

madato-0.7.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.6 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ARM64

madato-0.7.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl (1.7 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.5+ i686

madato-0.7.0-cp311-cp311-macosx_11_0_arm64.whl (803.3 kB view hashes)

Uploaded CPython 3.11 macOS 11.0+ ARM64

madato-0.7.0-cp311-cp311-macosx_10_12_x86_64.whl (820.4 kB view hashes)

Uploaded CPython 3.11 macOS 10.12+ x86-64

madato-0.7.0-cp310-none-win_amd64.whl (673.3 kB view hashes)

Uploaded CPython 3.10 Windows x86-64

madato-0.7.0-cp310-none-win32.whl (658.6 kB view hashes)

Uploaded CPython 3.10 Windows x86

madato-0.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

madato-0.7.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.9 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ s390x

madato-0.7.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.7 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ppc64le

madato-0.7.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.6 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ARMv7l

madato-0.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.6 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ARM64

madato-0.7.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl (1.7 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.5+ i686

madato-0.7.0-cp310-cp310-macosx_11_0_arm64.whl (803.0 kB view hashes)

Uploaded CPython 3.10 macOS 11.0+ ARM64

madato-0.7.0-cp310-cp310-macosx_10_12_x86_64.whl (820.5 kB view hashes)

Uploaded CPython 3.10 macOS 10.12+ x86-64

madato-0.7.0-cp39-none-win_amd64.whl (673.2 kB view hashes)

Uploaded CPython 3.9 Windows x86-64

madato-0.7.0-cp39-none-win32.whl (659.1 kB view hashes)

Uploaded CPython 3.9 Windows x86

madato-0.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

madato-0.7.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.9 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ s390x

madato-0.7.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.7 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ppc64le

madato-0.7.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.6 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARMv7l

madato-0.7.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.6 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARM64

madato-0.7.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl (1.7 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.5+ i686

madato-0.7.0-cp39-cp39-macosx_11_0_arm64.whl (803.1 kB view hashes)

Uploaded CPython 3.9 macOS 11.0+ ARM64

madato-0.7.0-cp39-cp39-macosx_10_12_x86_64.whl (820.5 kB view hashes)

Uploaded CPython 3.9 macOS 10.12+ x86-64

madato-0.7.0-cp38-none-win_amd64.whl (673.0 kB view hashes)

Uploaded CPython 3.8 Windows x86-64

madato-0.7.0-cp38-none-win32.whl (659.9 kB view hashes)

Uploaded CPython 3.8 Windows x86

madato-0.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

madato-0.7.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.9 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ s390x

madato-0.7.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.7 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ppc64le

madato-0.7.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.6 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARMv7l

madato-0.7.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.6 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARM64

madato-0.7.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl (1.7 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.5+ i686

madato-0.7.0-cp37-none-win_amd64.whl (673.0 kB view hashes)

Uploaded CPython 3.7 Windows x86-64

madato-0.7.0-cp37-none-win32.whl (659.8 kB view hashes)

Uploaded CPython 3.7 Windows x86

madato-0.7.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.17+ x86-64

madato-0.7.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl (1.9 MB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.17+ s390x

madato-0.7.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (1.7 MB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.17+ ppc64le

madato-0.7.0-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.6 MB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.17+ ARMv7l

madato-0.7.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.6 MB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.17+ ARM64

madato-0.7.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl (1.7 MB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.5+ i686

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page