Python powered spreadsheets

Overview

Marmir is powerful and fun

Marmir takes Python data structures and turns them into spreadsheets.

It is xlwt and google spreadsheets on steroids.

It also supports: input from Django models; taking Psycopg cursors; writing out ascii tables (like psql does); and will soon support HTML tables as output. The goal is to make it easy to generate many types of useful table files with the least amount of configuration.

Marmir melts in your mouth

Installing:

$ pip install Marmir

Talk about simple to use, wow. Marmir is just this:

import datetime
import mm

now = datetime.datetime.now().replace(microsecond=0)

my_data = [ 
    {
        'msg': "My first Row",
        'id': 1,
        'when': now,
    },
    {
        'msg': "My second Row",
        'id': 2,
        'when': now,
    },

]

mm_doc = mm.Document(my_data)
mm_doc.write("example.xls")

Same example above as lists (also node the 'order' argument works in the above as well:

my_headers = ('id', 'msg', 'when')
my_data = (
    (1, "My First Row", now),
    (2, "My Second Row", now)   
)

mm_doc = mm.Document(my_data, order=my_headers)
mm_doc.write("example.xls")

Or you can get fancier:

import datetime
import mm

my_data = [ 
    {
        'msg': "My first Row",
        'id': 1,
        'when': mm.Date(datetime.datetime.now(), "%Y-%m-%dT%H:%M:%S"),
        'homepage': mm.URL("https://github.com/brianray")
    },
    {
        'msg': "My second Row",
        'id': 2,
        'when': datetime.datetime.now(),
        'homepage': mm.URL("http://twitter.com/brianray", "Tweet Me")
    },

]

mm_doc = mm.Document(my_data)
mm_doc.write("example.xls")

# also you can publish to google spreadsheats
mm_doc.write_gdata("Example Spreadsheet", "Username", "Pass")

Now for a little Django (https://www.djangoproject.com/) example:

from yourproject.models import TestModel
from mm.contrib.django.data_model import DjangoDataModel
from mm.contrib.django.grid import DjangoGrid

django_query_set = TestModel.objects.all()
mm_doc = mm.Document(django_query_set, 
              data_model_class=DjangoDataModel, 
              grid_class=DjangoGrid)
mm_doc.write("django_example.xls")

There is a lot more. Check out the Examples.

... Not in your hand

So the primary goals are:

  • make XLS spreadsheets better than xlwt
  • Create Spreadsheets in Google Docs
  • convert python types automagically, date is a date, int is a int, string is a string, ...
  • do stuff you expect like make columns wider to fit, wrap in some cases
  • make stuff pretty colors and easier to read
  • generate directly from Django queries

Some other stuff:

  • do summaries and break out tables
  • add logic and math functions

Marmir is written with love

Brian Ray @brianray wrote Marmir. Brian: is the organizer of ChiPy (http://chipy.org); one of Chicago's Top Tech 25 (according to Crains Oct 2011); been professionally developing software for business for 15 years; and is sick of sub-par Python libraries for creating business spreadsheets.

The name Marmir name from parts of the names Maura and Miranda, the author's girls.

Copyright

Copyright (c) 2013 Brian Ray

Comments
  • object of type 'NoneType' has no len()

    object of type 'NoneType' has no len()

    I got that error when I'm trying to create xls. My code is something like this:

    from mymodel.models import MyList from mm.contrib.django.data_model import DjangoDataModel from mm.contrib.django.grid import DjangoGrid import mm

    thelist = MyList.objects.filter(create_time__range=(start,end)).extra(select={ 'newfield': 'select name from newtable where id=thistable.people_id'}).order_by('-create_time')

    mm_doc = mm.Document(thelist, data_model_class=DjangoDataModel, grid_class=DjangoGrid) mm_doc.write('example.xls')

    I'm using Django 1.4

    The same thing happen when I iterate the queryset and build the list of dict manually.

    opened by lantip 4
  • Doing more with less

    Doing more with less

    Brian; would really love to use this. I had been "rolling my own" Excel output for a Django project before coming across your project. I had been wondering how to incorporate decent formatting to the data and your project seems perfect for that.

    One small (?) issue though. The bulk of data I output from my views is in the form of (a) a list of headers and (b) a "list of lists" for data. This format is perfect for easy conversion to HTML tables, CSV data or Excel files. However your examples are dictionary-based and include header names encapsulated in each "row". Do you see a way to upgrade your project to handle the kind of input I would like to have? Thanks!

    opened by gamesbook 4
  • pip install error

    pip install error

    When I tried to install Marmir with pip it failed. Attached is a screenshot of the error log I received. Note, I haven't had any issues downloading anything else with pip. I also used pip to install another package right after I tried to install this one, and I didn't have any issues.

    error_log

    opened by tetter36 1
  • Proposal to generate files in tests/generated_files subdirectory

    Proposal to generate files in tests/generated_files subdirectory

    The generated XLS files are currently dumped into the project root directory. Can we output those files into tests/generated_files subdirectory instead?

    opened by pebreo 1
  • Proposal to change syntax of how files are opened in test suites

    Proposal to change syntax of how files are opened in test suites

    I propose to change the syntax of all unittests that currently open files like this:

    f = open("foo.xls", "wb")
    f.write(str)
    f.close()
    

    to the more idiomatic:

    with open("foo.xls", "wb") as f:
        f.write(str)
    
    opened by pebreo 1
  • Corrupt file generated using write() method in Windows

    Corrupt file generated using write() method in Windows

    The write() method generates a corrupt file that MS Excel (running in Windows environment) cannot read.

    When opening the file Excel gives the following error:

    "Excel found unreadable content in 'myfile.xls'. Do you want to recover the contents of this workbook?"

    Given the following code:

    my_data = [
                {
                    'msg': "My first Cell",
                    'id': 1,
                    'when': 'now',
                },
                {
                    'msg': "My second Cell",
                    'id': 2,
                    'when': 'now',
                },
    ]
    
    mm_doc = mm.Document(my_data)
    mm_doc.write("myfile.xls") # generates a corrupt file
    
    opened by pebreo 1
  • object of type 'NoneType' has no len()

    object of type 'NoneType' has no len()

    There was already a ticket regarding this issue... It only occurs if I export 2 or more rows at once...

    You can find the model here: https://gist.github.com/SachaMPS/e8448ffede30ed4f204c

    Heres the traceback:

    ERROR:django.request:Internal Server Error: /admin/contact/orderitem/ Traceback (most recent call last): File "/Users/sto/Sites/python.dev/python/stw_project/env/lib/python2.7/site-packages/django/core/handlers/base.py", line 111, in get_response response = callback(request, _callback_args, *_callback_kwargs) File "/Users/sto/Sites/python.dev/python/stw_project/env/lib/python2.7/site-packages/django/contrib/admin/options.py", line 366, in wrapper return self.admin_site.admin_view(view)(_args, *_kwargs) File "/Users/sto/Sites/python.dev/python/stw_project/env/lib/python2.7/site-packages/django/utils/decorators.py", line 91, in _wrapped_view response = view_func(request, _args, *_kwargs) File "/Users/sto/Sites/python.dev/python/stw_project/env/lib/python2.7/site-packages/django/views/decorators/cache.py", line 89, in _wrapped_view_func response = view_func(request, _args, *_kwargs) File "/Users/sto/Sites/python.dev/python/stw_project/env/lib/python2.7/site-packages/django/contrib/admin/sites.py", line 196, in inner return view(request, _args, *_kwargs) File "/Users/sto/Sites/python.dev/python/stw_project/env/lib/python2.7/site-packages/django/utils/decorators.py", line 25, in _wrapper return bound_func(_args, *_kwargs) File "/Users/sto/Sites/python.dev/python/stw_project/env/lib/python2.7/site-packages/django/utils/decorators.py", line 91, in _wrapped_view response = view_func(request, _args, *_kwargs) File "/Users/sto/Sites/python.dev/python/stw_project/env/lib/python2.7/site-packages/django/utils/decorators.py", line 21, in bound_func return func(self, _args2, *_kwargs2) File "/Users/sto/Sites/python.dev/python/stw_project/env/lib/python2.7/site-packages/django/contrib/admin/options.py", line 1153, in changelist_view response = self.response_action(request, queryset=cl.get_query_set(request)) File "/Users/sto/Sites/python.dev/python/stw_project/env/lib/python2.7/site-packages/django/contrib/admin/options.py", line 908, in response_action response = func(self, request, queryset) File "/Users/sto/Sites/python.dev/python/stw_project/project/apps/contact/admin.py", line 63, in export_as_xls data = xlsDoc.writestr() File "/Users/sto/Sites/python.dev/python/stw_project/env/lib/python2.7/site-packages/mm/document_writers.py", line 21, in writestr return self.composer.run(child=child) File "/Users/sto/Sites/python.dev/python/stw_project/env/lib/python2.7/site-packages/mm/composer_xls.py", line 220, in run self.iterate_grid() File "/Users/sto/Sites/python.dev/python/stw_project/env/lib/python2.7/site-packages/mm/composer_base.py", line 26, in iterate_grid self.write_cell(self.row_id, self.col_id, cell) File "/Users/sto/Sites/python.dev/python/stw_project/env/lib/python2.7/site-packages/mm/composer_xls.py", line 165, in write_cell self.done_write_cell(row_id, col_id, cell, value, style) File "/Users/sto/Sites/python.dev/python/stw_project/env/lib/python2.7/site-packages/mm/composer_xls.py", line 176, in done_write_cell new_width = get_string_width_from_style(value, style) File "/Users/sto/Sites/python.dev/python/stw_project/env/lib/python2.7/site-packages/mm/composer_xls.py", line 19, in get_string_width_from_style return int(get_string_width(font_name, point_size, char_string) * 50) File "/Users/sto/Sites/python.dev/python/stw_project/env/lib/python2.7/site-packages/mm/lib/font_data/decorators.py", line 21, in call value = self.func(*args) File "/Users/sto/Sites/python.dev/python/stw_project/env/lib/python2.7/site-packages/mm/lib/font_data/core.py", line 49, in get_string_width str_length = len(char_string) TypeError: object of type 'int' has no len()

    opened by SachaMPS 1
  • Extra Columns test fail

    Extra Columns test fail

    @hodgesds

    ERROR: test_extra_columns (test_extra_columns.TestColumns)

    Traceback (most recent call last): File "/Users/bray/mm/tests/test_extra_columns.py", line 36, in test_extra_columns self.check("test_extra_columns.xls", my_data) File "/Users/bray/mm/tests/test_extra_columns.py", line 45, in check cell_type = xls.get_type(row, col) return self.cell_types[str(worksheet.cell_type(row, colm))] File "/Users/bray/mm/mm_env/lib/python2.7/site-packages/xlrd/sheet.py", line 418, in cell_type return self._cell_types[rowx][colx] IndexError: array index out of range -------------------- >> begin captured logging << --------------------

    opened by brianray 1
  • Rename xlrd.py in test directory to xlrd_helper.py

    Rename xlrd.py in test directory to xlrd_helper.py

    Rename the xlrd.py to avoid the failing of tests

    C:\Users\Tathagata\Documents\GitHub\mm\tests>python gdata_tests.py
    Traceback (most recent call last):
     File "gdata_tests.py", line 6, in <module>
        from xlrd_helper import XLSReader
       ImportError: No module named xlrd_helper
    
    opened by tathagata 1
  • gdata_tests.py fails on Win 7, Python 2.7.2

    gdata_tests.py fails on Win 7, Python 2.7.2

    C:\Users\Tathagata\Documents\GitHub\mm\tests>python gdata_tests.py
    Google Username: C-3PO
    Google password:
    No handlers could be found for logger "mm.composer_xls"
    E
    ======================================================================
    ERROR: test_minimal (__main__.TestGdataSuite)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
     File "gdata_tests.py", line 45, in test_minimal
    password)
     File "C:\Python27\lib\site-packages\marmir-0.1.1-py2.7.egg\mm\document_writers.py", line 60, in write_gdata
    entry = gd_client.Upload(ms, name)
     File "C:\Python27\lib\site-packages\gdata\docs\service.py", line 306, in Upload
    folder_or_uri)
     File "C:\Python27\lib\site-packages\gdata\docs\service.py", line 161, in _UploadFile
    converter=gdata.docs.DocumentListEntryFromString)
     File "C:\Python27\lib\site-packages\gdata\service.py", line 1236, in Post
    media_source=media_source, converter=converter)
     File "C:\Python27\lib\site-packages\gdata\service.py", line 1358, in PostOrPut
    'reason': server_response.reason, 'body': result_body}
    RequestError: {'status': 400, 'body': 'The spreadsheet you are trying to upload is invalid.', 'reason': 'Bad Request'}
    
    ----------------------------------------------------------------------
    Ran 1 test in 11.664s
    
    FAILED (errors=1)
    

    Printing the values of the dict in the doc in line 36

        mm_doc = mm.Document(my_data)
        print mm_doc.__dict__.values()
    
     [<mm.grid_base.GridBase object at 0x0236BB50>, <mm.config_base.ConfigBase object at 0x0236BAD0>, <class 'mm.model_base.DataModel'>, [{'msg': 'My first Cell', 'when': datetime.datetime(2013, 2, 18, 19, 35, 11), 'id': 1}, {'msg': 'My second Cell', 'when': datetime.datetime(2013, 2, 18, 19, 35, 11), 'id': 2}], <mm.model_base.DataModel object at 0x0236BB10>]
    
    opened by tathagata 1
  • Fix Issues #24 and #25

    Fix Issues #24 and #25

    This is my pull request to fix issue #24 and #25.

    Issue #24 was about changing the syntax f = open(..) to with open(..) as f

    Issue #25 was about generating the *.xls files into their own subdirectory tests/generated_files

    A bunch of *_tests.py have been affected but the non-test files that have been affected are:

    document_writers.py
    textwidths.py
    

    All tests have passed as a result of these changes.

    opened by pebreo 0
  • Can it support python 3?

    Can it support python 3?

    It looks not support python3.

    $ pip install marmir
    Collecting marmir Using cached https://files.pythonhosted.org/packages/e4/7d/75d7c821c2a9439ccaad6f70d5cfb8ba3a7d5795b9632f3a9b89a3a40e2e/Marmir-0.1.3.tar.gz Complete output from command python setup.py egg_info: Traceback (most recent call last): File "", line 1, in File "/private/var/folders/n3/hnw9vdn51qzf29grjgmcyr800000gn/T/pip-install-8fun0y3l/marmir/setup.py", line 3, in import mm File "/private/var/folders/n3/hnw9vdn51qzf29grjgmcyr800000gn/T/pip-install-8fun0y3l/marmir/mm/init.py", line 10, in from document_base import * ModuleNotFoundError: No module named 'document_base'

    opened by hh-in-zhuzhou 10
  • catche and warn about more data than headers

    catche and warn about more data than headers

    https://github.com/brianray/mm/blob/master/mm/model_base.py#L125

    Catch the index error and raise a more specific exception. Add a setting to the config called 'INGORE_DATA_MISMATCH'--when True, log a warning instead of failing at this point.

    opened by brianray 0
Releases(mm3)
Owner
Brian Ray
Global Data Science Lead @brianray
Brian Ray
This project, search all entities related to A2P in twilio

Mirror A2P Twilio This project, search all entities related to A2P in twilio (phone numbers, messaging services, campaign, A2P brand information and P

Iván Cárdenas 2 Nov 03, 2022
Robust and blazing fast open-redirect vulnerability scanner with ability of recursevely crawling all of web-forms, entry points, or links with data.

After Golismero project got dead there is no more any up to date open-source tool that can collect links with parametrs and web-forms and then test th

railway zeppelin 34 Aug 25, 2022
With this simple app you can customize your presence in Discord.

Discord Rich Presence This a simple console app which can customize your Discord Presence easily, with only one config file! Setup Go to Discord Devel

Mai 1 Jan 06, 2022
A github actions + python code to extract URLs to code repositories to put into standard form, starting with github

A github actions + python code to extract URLs to code repositories to put into standard form, starting with github ---- NOTE: JUS

Justin Gosses 2 Nov 15, 2021
A Python library for PagerDuty.

Pygerduty Python Library for PagerDuty's REST API and Events API. This library was originally written to support v1 and is currently being updated to

Dropbox 164 Dec 20, 2022
A Telegram bot to extracting text from images. All languages supported.

OCR Bot A Telegram bot to extracting text from images. All languages supported. Deploy to Heroku Local Deploying Clone the repo git clone https://gith

6 Oct 21, 2022
Freqtrade is a free and open source crypto trading bot written in Python.

Freqtrade is a free and open source crypto trading bot written in Python. It is designed to support all major exchanges and be controlled via Telegram. It contains backtesting, plotting and money man

Kazune Takeda 5 Dec 30, 2021
This is a simple unofficial async Api-wrapper for tio.run

Async-Tio This is a simple unofficial async Api-wrapper for tio.run

Tom-the-Bomb 7 Oct 28, 2022
this synchronizes my appearances with my calendar

Josh's Schedule Synchronizer Here's the "problem:" I use a spreadsheet to maintain all my public appearances. I check the spreadsheet as often as poss

Josh Long 2 Oct 18, 2021
Telegram bot which has truecaller and smsbomber features

Truecaller-telegram_bot Add your telegram bot api key in main.py and you are good to go To get a api key Goto telegram and search BotFather From the c

Rudranag 32 Dec 05, 2022
NewpaperNews-API - Json data of the news with python

NewsAPI API Documentation BASE_URL = "https://saurav.tech/NewsAPI/" top_headline

Aryaman Prakash 2 Sep 23, 2022
Tinyman Python SDK

tinyman-py-sdk Tinyman Python SDK Design Goal This SDK is designed for automated interaction with the Tinyman AMM. It will be most useful for develope

Tinyman 113 Dec 30, 2022
A telegram bot to monitor the latest NFT price on BSC.

NFT_Monitor This is a telegram bot for monitoring price and ranking of NFT on Binance Smart Chain. Can fetch latest ranking and price in real time. .P

Niko Pang 10 Oct 09, 2022
Automatically commits and pushes changes from a specified directory to remote repository

autopush a simple python program that checks a directory for updates and automatically commits any updated files (and optionally pushes them) installa

carreb 1 Jan 16, 2022
Video Bot: an Advanced Telegram Bot that's allow you to play Video & Music on Telegram Group Video Chat

Video Bot is an Advanced Telegram Bot that's allow you to play Video & Music on

5 Jan 26, 2022
You can share your Chegg account for answers using this bot with your friends without getting your account blocked/flagged

Chegg-Answer-Bot You can share your Chegg account for answers using this bot with your friends without getting your account blocked/flagged Reuirement

Ammey Saini 27 Dec 24, 2022
RaidBot for WhatsApp

WhatsappRaid Скрипт подготовлен специально для сайта https://pysoc.ru и Ютуб канала PyPro Русский Простой спам бот для WhatsApp на Python3. Работает с

2 May 12, 2022
Auxiliator is telegram bot for basic web-application analysis

Auxiliator Auxiliator is telegram bot for basic web-application analysis What for? Sometimes there is no access to your main PC, where you can scan we

Revoltage 13 Dec 26, 2021
You have 3 files: create mass groups, add mass members, rename all groups (only educational use!)

EDUCATIONAL ONLY! HOW TO INSTALL Edit config.json with your discord account token and the imagepath (if its in the same location as the all_together.p

46 Dec 27, 2022
Easily report Instagram pages and close the page

Program Features - 📌 Delete target post on Instagram. - 📌 Delete Media Target post on Instagram - 📌 Complete deletion of the target account on Inst

hack4lx 11 Nov 25, 2022