Archive

Posts Tagged ‘excel’

Excel scroll bar bug

October 7th, 2009

Microsoft Excel 2008 for Mac has an irritating bug where only the active document window has scroll bars. If a second document is open, or even if you only have one document but Excel is not the front-most application then the window has no scroll bars and ignores scroll messages from the mouse. This happens in Excel 12.2.0 (and a couple of earlier revisions behave the same).

Excel scroll bars in inactive window

Excel scroll bars in an inactive window

The correct behaviour is for scroll bars in inactive windows to be drawn in an inactive state and to allow scrolling even when the window is not front-most.

I rather like Excel. I thought it was the least crashy of the assorted junk Microsoft released as Office 4.2 for Mac back in 1993. Fuck me that was a pile of shit.

david ,

Outputting Excel with Django

September 1st, 2009

xlwt is an excellent Python module for generating Microsoft Excel documents (xlrd is its counterpart for consuming Excel documents). I use it in a Django Web application so a visitor can export her data as a spreadsheet.

Django’s documentation includes an example of how to export data in comma-separated values (CSV) format. CSV has the significant advantage of being a standard Python module as well as being a relatively simple and non-vendor specific format. However there are some disadvantages to using CSV:

  1. Values can only be stored as strings or numbers.
  2. Unicode text must be explicitly encoded as UTF-8.
  3. Users are often unfamiliar with the .csv file name extension – “What the hell do I do with this damn you?”

It would be unfriendly of me to expect a user to open a CSV file and then format a column of date strings as proper date values (especially when the user is almost certainly using Excel already). So I choose Excel format over CSV format.

Dates in Excel documents (97/2004 format) are actually stored as numbers. In order to have them appear as dates one must apply a date formatting. You do this by using xlwt.easyxf to create a suitable style instance and then pass that when writing the cell data.

A word of advice: do not instantiate style objects more than once! My initial approach created a new style whenever writing a date/time value. Only once I was testing with more than a few dozen rows did I discover that Excel will grow grumpy and complain about too many fonts being open when trying to display the spreadsheet. The correct approach is to have one instance for each different style and then re-use that instance for the appropriate type of value.

Here is an example that writes all objects of one class to a spreadsheet and sends that file to the client’s browser. You could stuff this in a Django view method.

from datetime import datetime, date
from django.http import HttpResponse
from myproject.myapp.models import MyModel
import xlwt


book = xlwt.Workbook(encoding='utf8')
sheet = book.add_sheet('untitled')

default_style = xlwt.Style.default_style
datetime_style = xlwt.easyxf(num_format_str='dd/mm/yyyy hh:mm')
date_style = xlwt.easyxf(num_format_str='dd/mm/yyyy')

values_list = MyModel.objects.all().values_list()

for row, rowdata in enumerate(values_list):
    for col, val in enumerate(rowdata):
        if isinstance(val, datetime):
            style = datetime_style
        elif isinstance(val, date):
            style = date_style
        else:
            style = default_style

        sheet.write(row, col, val, style=style)

response = HttpResponse(mimetype='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename=example.xls'
book.save(response)
return response

That code works a peach with a 30,000 row / 25 column database, taking about a minute to generate a 13 megabyte file on my lowly iMac G5.

You want to buy me a new Intel iMac, don’t you? Yes, you do.

david ,