Resolver Hacks contains information and code for doing fun and useful things with Resolver One. This site is created and maintained by Michael Foord, not by Resolver Systems. Please read the disclaimer before using any of the code on this site.
Resolverforge

Contents
Introduction
The power of Resolver One is in how easy it is to use Python libraries within your spreadsheets, and create your own libraries of spreadsheet functions and classes. This does create a problem though, your spreadsheets become dependent on the libraries you are using. You can keep the libraries in the same directory as the spreadsheet, but then you can end up with multiple different versions of libraries stored in several places.
One possible solution is to set the IRONPYTHONPATH so that you can keep all your modules in one place (see the IRONPYTHONPATH article for the full details). This still leaves you with a problem when you send the spreadsheet to other people.
This article is about a module called Resolverforge. It allows you to specify the modules your spreadsheets depend on at the start of your user code. If they aren't available when the spreadsheet loads, then the user will be asked if they want to download them.
This is an early implementation (but it works fine of course!). At the moment it only supports modules that are a single file. Future versions will include a web site that allows users to register modules, it will handle versioning and Python packages that are more than a single module.
Note
Resolverforge is designed to work with Resolver One. It downloads modules on demand from a central repository (which you can specify). None of the code in the Resolverforge module is specific to Resolver One though, it should work with any IronPython code where Windows Forms [1] is available.
The Resolverforge Module and the require Function

You can download the Resolverforge module, along with a 'helloworld' example spreadsheet that uses it:
When you load the spreadsheet for the first time, a message box should appear warning you that the spreadsheet wants to download the helloworld module. If you accept then the module will be downloaded and the import will succeed. From then on the helloworld module can be imported without having to be downloaded.
To use Resolverforge, you need to import the require module. You then call require with the name of the module you need, followed by the normal import statement.
The full code from the 'hello world' example spreadsheet:
require('helloworld')
import helloworld
helloworld.sayhello()
Of course to use require the 'Resolverforge' module must be available to your spreadsheet! (A bit of a chicken and egg situation.) The example works because 'Resolverforge.py' is in the same directory as the spreadsheet. You have two options for locations to put this module where it will be available to all your spreadsheets:
- Put it in your main 'Resolver One' install directory. This will be somewhere like C:\Program Files\Resolver One. Putting a lot of things in this directory is a bad idea, but one module is probably ok.
- Create a directory for your spreadsheet modules. Use the IRONPYTHONPATH environment variable to make modules in this directory available for import by your spreadsheets.
The Module Directory
When you import 'Resolverforge' it checks to see if its directory for storing modules is available. If it isn't then it creates it for you.
By default, this is a directory called '.resolverforge' in your home directory. At my work my home directory is on the network drive, so my Resolverforge directory is H:\.resolverforge. At home, my Resolverforge directory is C:\Documents and Settings\Michael\.resolverforge.
Resolverforge also adds this directory to the module import path (sys.path). This means that if you have already downloaded a module it will be available without having to re-download it. It also means that if you import Resolverforge in your spreadsheets you can keep your own modules in this directory and import them into your spreadsheets.
If you don't like the default location for the Resolverforge directory, then you can change it by setting a 'RESOLVERFORGE' environment variable [2] to point to a different location.
You can force Resolverforge to download the most recent version of a module by deleting it from this directory.
Repositories
Warning
Importing a module will execute the code in the module. Only download and import modules you are sure are safe.
When you import Resolverforge for the first time, it creates a text file in the resolverforge directory called resolverforge.txt.
When you call require and ask for a module that isn't available, Resolverforge will search any repositories in this file (one URL per line) for the specified Python file. The default repository that require searches is a directory on this site: www.resolverhacks.net/resolverforge/.
You can add any URLs (and remove the default one if you want) - including locations on an intranet or the internet. This way you can distribute spreadsheets that depend on your modules, and provide a central location for them to be downloaded from.
Future versions of Resolverforge will include a way of specifying versions (so that it can automatically update out of date modules), and a website allowing users to add new modules to the repository.
Modules
The modules currently available in the Resolver Hacks Repository are:
-
This is the example module used by the Resolverforge example spreadsheet. It fills a block of cells in Sheet1 with 'Hello World' and prints it to the output view.
-
This module provides a cache for storing data between recalculations. It is from the caching article.
-
This module provides a few functions for working with cell ranges. These are taken from the articles on Coloring alternate rows and Easy cell ranges.
-
This module provides functions for working with CSVs. It is taken from the Resolver One documentation page Loading Data from CSV Files.
-
ConfigObj is a module for the easy reading and writing of configuration files. ConfigObj can also be used for persisting data and has an integrated value conversion/validation system. You can read more on the ConfigObj Homepage.
-
This module provides the type conversion and value validation system used by ConfigObj. These features can also be used on their own. You can read more on the validate homepage.
-
cgiutils provides a series of function mainly (but not only) useful for writing Python CGIs. There are also functions for sending emails using the Python standard library, simple templating and performing DNS blacklist lookups. The cgiutils homepage.
-
odict is an ordered dictionary written in pure Python. The odict homepage.
-
pathutils provides functions for working with files, directories and paths. The pathutils homepage.
-
A function for reloading and importing modules, from the Import with reload article.
-
Functions for working with URLs. The urlpath homepage.
The TODO List
There is a lot that can be done to improve the Resolverforge client-side implementation (currently it is just over 100 lines of Python code).
- Add locking.
- 'require' should work on packages not just Python files. (Download a zip file - which could/should include description, docs and tests)
- Extra arguments to require - like version number.
- Proper error messages on failure to import (module not found, couldn't connect etc.)
- Auto-update for new versions.
- Client repository browser and front end for adding repositories.
| [1] | Resolverforge uses the Windows Forms message box to ask the user for permission to download modules. |
| [2] | If you aren't used to setting environment variables, there is a step-by-step guide in my Windows Command Line Programming article. |
Last edited Mon Feb 11 11:07:22 2008.

IronPython in Action