Convert SpreadSheets to CSV files with Python and pyuno, Part 2

 in

Using the SSConverter class that we developed last week, which used the OORunner class from the week before that, this week we'll create a Python function that allows us to use spreadsheets as if they were CSV files by converting them on the fly.

Unlike the previous two pieces of code this piece doesn't use any new features of pyuno. It's actually quite simple: the function takes the name of a file that can be either a spreadsheet file or a CSV file:

  • If the name refers to a spreadsheet file then the corresponding CSV file is checked, if it does not exist it is created. If it does exist, then it is checked to make sure that it's newer than the spreadsheet file, if not it's re-created.
  • If the name refers to a CSV file then it's again checked to make sure it's newer than the spreadsheet file and it's re-created if the spreadsheet is newer.

In either case the name of the CSV file is returned. Usage is simple:

csvfile = check_csv_file(ifile)

If run directly the test code runs which accepts any number of command line arguments. The test code calls the function on each command line argument.

When run on a spreadsheet when there is no CSV file it creates the CSV file and returns its name:

$ python check_csv_file.py jj.xls
Creating jj.csv from jj.xls
Input name jj.xls, output name jj.csv

When run on the same spreadsheet again it simply returns the CSV file name since the CSV file already exists and is newer than the spreadsheet:

$ python check_csv_file.py jj.xls
Input name jj.xls, output name jj.csv

When run on the CSV file it returns the CSV file name:

$ python check_csv_file.py jj.csv
Input name jj.csv, output name jj.csv

When run on the CSV file after the spreadsheet has been modified it re-creates the CSV file and returns its name:

$ touch jj.xls
$ python check_csv_file.py jj.csv
Recreating jj.csv from jj.xls
Input name jj.csv, output name jj.csv

The source code for the function follows:

import os
import re
import sys
import csv


def check_csv_file(csvfile):
    """
    Make sure the CSV file exists.
    If it does not exist, try to create it from an XLS or ODS file.
    The passed name can refer to an XLS file or an ODS file.
    The return value will be the name of a CSV file.
    """
    def find_csv(csvf):
        """ Check to see if the CSV file exists. """
        fname, ext = os.path.splitext(csvf)
        ext        = ext.lower()
        if   ext == '.txt':
            f = '%s.%s' % (fname, 'TXT')
            if os.path.exists(f):
                csvf = f
            else:
                csvf = '%s.%s' % (fname, 'txt')

        elif ext != '.csv':
            f = '%s.%s' % (fname, 'CSV')
            if os.path.exists(f):
                csvf = f
            else:
                csvf = '%s.%s' % (fname, 'csv')

        return csvf

    def find_sheet(ssvf):
        """ Check to see if the spread sheet file exists. """
        sheetf = None
        fname  = os.path.splitext(ssvf)[0]
        for ext in ('xls', 'XLS', 'ods', 'ODS'):
            f = '%s.%s' % (fname, ext)
            if os.path.exists(f):
                sheetf = f
                break

        return sheetf

    def convert_sheet(sheetf, csvf):
        """ Convert spreadsheet to a CSV file. """
        import ooutils
        from ssconverter import SSConverter
        try:
            converter = SSConverter()
            converter.convert(sheetf, csvf)
        except Exception, e:
            sys.stderr.write("ERROR: %s\n" % e.message)
            sys.exit(1)

    # Find the spreadsheet file that corresponds to the CSV file
    csvfile   = find_csv(csvfile)
    sheetfile = find_sheet(csvfile)

    if sheetfile:
        # If CSV does not exist try to create it.
        if not os.path.exists(csvfile):
            sys.stderr.write("Creating %s from %s\n" % (csvfile, sheetfile))
            convert_sheet(sheetfile, csvfile)
        else:
            # If spreadsheet is newer the CSV file, re-create it.
            if os.stat(csvfile).st_mtime < os.stat(sheetfile).st_mtime:
                sys.stderr.write("Recreating %s from %s\n" % (csvfile, sheetfile))
                convert_sheet(sheetfile, csvfile)


    if not os.path.exists(csvfile):
        sys.stderr.write('File not found: %s\n' % csvfile)
        sys.exit(1)

    return csvfile


if __name__ == "__main__":
    for f in sys.argv[1:]:
        f2 = check_csv_file(f)
        print "Input name %s, output name %s" % (f, f2)
______________________

Mitch Frazier is an Associate Editor for Linux Journal.

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Converting from a multi-sheet file

I giron's picture

Hi.

Thanks for the tip and the utilities. I tested them with OpenOffice.org 2.04 and Python 2.4.4 running under Debian Etch and they work ok.

Nevertheless, only the first sheet in the Excel file gets converted. Is it possible to extract the rest of the sheets?

Regards.

Rev 2

Mitch Frazier's picture

I'll work on that. If you haven't seen something in a week or two, leave me another reminder comment. :)

Mitch Frazier is an Associate Editor for Linux Journal.

White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState