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
Discord group chat spammer concept.

GC Spammer [Concept] GC-Spammer for https://discord.com/ Warning: This is purely a concept. In the past the script worked, however, Discord ratelimite

Roover 3 Feb 28, 2022
This is a very easy to use tool developed in python that will search for free courses from multiple sites including youtube and enroll in the ones in which it can.

Free-Course-Hunter-and-Enroller This is a very easy to use tool developed in python that will search for free courses from multiple sites including yo

Zain 12 Nov 12, 2022
Código python para automatizar a junção de arquivos CSV's e salva-los em uma pasta final de destino.

merge_csv Código python para automatizar a junção de arquivos CSV's e salva-los em uma pasta final de destino. Esse projeto é usado pra unir alguns ar

Welder Fariles 1 Jan 12, 2022
Posts word definitions on Twitter daily

Word Of The Day bot Post daily word definitions on social media. Twitter account: https://twitter.com/WordOfTheDay_B Introduction The goal of this pro

Lucas Rijllart 1 Jan 08, 2022
Jackrabbit Relay is an API endpoint for stock, forex and cryptocurrency exchanges that accept REST webhooks.

JackrabbitRelay Jackrabbit Relay is an API endpoint for stock, forex and cryptocurrency exchanges that accept REST webhooks. Disclaimer Please note RA

Rose Heart 23 Jan 04, 2023
Multi Account Generator Minecraft/NordVPN/Hulu/Origin And ...

Multi Account Generator Minecraft/NordVPN/Hulu/Origin And ...

76 Jan 01, 2023
A Django-style ORM idea for manipulating Google Datastore entities

No SeiQueLa ORM EM DESENVOLVIMENTO Uma ideia de ORM no estilo do Django para manipular entidades do Google Datastore. Montando seu modelo: from noseiq

Geraldo Castro 16 Nov 01, 2022
An open source, multipurpose, configurable discord bot that does it all

Spacebot - Discord Bot Music, Moderation, Fun, Utilities, Games and Fully Configurable. Overview • Contributing • Self hosting • Documentation (not re

Dhravya Shah 41 Dec 10, 2022
A python script that can send notifications to your phone via SMS text

Discord SMS Notification A python script that help you send text message to your phone one of your desire discord channel have a new message. The proj

2 Apr 25, 2022
An advanced crypto trading bot written in Python

Jesse Jesse is an advanced crypto trading framework which aims to simplify researching and defining trading strategies. Why Jesse? In short, Jesse is

Jesse 4.4k Jan 09, 2023
Offline reverse geocoder in Python using sqlite3

rgeocode Offline reverse geocoder rgeocode accepts a geographic coordinate pair (latitude and longitude) and returns a list containing the name of: A

Venkat 7 Dec 01, 2021
Exchange indicators & Basic functions for Binance API.

binance-ema Exchange indicators & Basic functions for Binance API. This python library has been written to calculate SMA, EMA, MACD etc. functions wit

Emre MENTEŞE 24 Jan 06, 2023
Simple Python Auto Follow Bot

Instagram-Auto-Follow-Bot Description Một IG BOT đơn giản. Tự động follow những người mà bạn muốn cướp follow. Tự động unfollow. Tự động đăng nhập vào

CodingLinhTinh 3 Aug 27, 2022
A python package for fetching informations from GitHub API

Py-GitHub A python package for fetching informations from GitHub API Made with Python3 (C) @FayasNoushad Copyright permission under MIT License Licens

Fayas Noushad 6 Nov 28, 2021
Elkeid HUB - A rule/event processing engine maintained by the Elkeid Team that supports streaming/offline data processing

Elkeid HUB - A rule/event processing engine maintained by the Elkeid Team that supports streaming/offline data processing

Bytedance Inc. 61 Dec 29, 2022
Discord raiding tool. Made in python 3.9

XSpammer Discord raiding tool with 20 features. YT Showcase Requirements/Installation Python 3.7+ [https://python.org] Run setup.bat to install the es

Tiie 6 Oct 24, 2022
VideocompBot - This is TG Video Compress BoT. Prouduct By BINARY Tech 💫

VideocompBot - This is TG Video Compress BoT. Prouduct By BINARY Tech 💫

1 Jan 04, 2022
LavaAPI - A simple library for accepting payments and using the LAVA Wallet

This library was created to simplify the LAVA api provided on the official websi

Vlad Baccara 8 Dec 18, 2022
Netflix Movies and TV Series Downloader Tool including CDM L1 which you guys can Donwload 4K Movies

NFRipper2.0 I could not shared all the code here Because its has lots of files inisde it https://new.gdtot.me/file/86651844 - Downoad File From Here.

Kiran 15 May 06, 2022
Discord bot that shows valorant your daily store by using the Ingame API

Valorant store checker - Discord Bot Discord bot that shows valorant your daily store by using the Ingame API. written using Python and the Pycord lib

STACIA 226 Jan 02, 2023