Lists the new features, improvements, and fixes for each release of AFC. Note that the former name of AFC was SEJ (Spreadsheet Engine for Java). You may also want to look at:
- All public APIs taking a
Stringargument where they really should take a
Filehave been dropped.
- The internal implementation of
Engineis no longer a subclass of
ClassLoader. We warned you not to rely on this.
- During constant folding, AFC now caches values for cells it has already computed. This can speed up compilation times of certain sheets dramatically.
- Fixed parsing multisheet ranges in .xls files (issue 21).
- Fixed processing of HLOOKUP and VLOOKUP fourth parameter (issue 24).
- Fixed inferring type of IF and ExpressionNodeForSwitch (issue 25).
- Fixed parsing .ods files with lots of trailing empty rows (issue 26).
- Fixed a bug in rewriter/annotator interplay (issue 27).
- AFC can now compile engines which can log intermediate values during a computation.
MDETERM()is now supported.
- Upgraded to ASM 3.1.
- Upgraded to Ant 1.7.1.
- Upgraded to Checkstyle 5.0.
- Cell name case is preserved when compiling to readable code.
EngineLoader.Config.parentClassLoaderis set to
- Fixed compatibility issues with OpenOffice.org Calc 3.0.
- Fixed loading saved engines when AFC classes are loaded not by system classloader.
- Fixed getting named ranges defined in the spreadsheet after defining an additional range name.
- Fixed generating identifiers when compiling to readable code.
- Fixed incorrect
Row.getRowIndex()return value when parsing ODF spreadsheets.
- Scripts now have UNIX executable file permisson in the build tools package.
- AFC can now load and save spreadsheets in the Microsoft Office Open XML
.xlsx(MS Excel 2007) format.
- Fixed parsing off-sheet ranges.
- Fixed parsing sheet names with hyphens and quotes.
- Fixed displaying cell references in A1 format with more that 2 letters.
- Fixed parsing percents on JDK 6 with de_CH locale.
- Sheet names are displayed in cell and range names in error messages.
- AFC can now save spreadsheets in the OpenDocument
- Added new
- AFC now supports OpenOffice.org Calc computation mode.
Spreadsheet.getCellA1(String)is now able to return cells from all sheets, not only the first.
- Fixed parsing formulas without the
oooc:prefix in OpenDocument spreadsheets. Such spreadsheets are saved by KOffice.
- Fixed parsing OpenDocument spreadsheets with broken references.
- OpenDocument spreadsheet loader now pays attention to
INDEX()now does better range checking on 2-dimensional indexes, handles omitted indices better when set to constant 0, and can deal with bound column-index values for lookups into vertical vectors and vice versa.
- Builds and tests properly on JDK 6.
- Source .zip no longer contains .hg folder.
- Fixed parsing quotes in string literals.
- Fixed and improved site.
- Shared formula parsing fixes for JExcelAPI.
- Improved system tests.
- You can no longer bind to input methods throwing checked exceptions. (We may re-enable this later when AFC checks that all output methods declare all of those checked exceptions.)
- AFC no longer rounds final results to the precision specified in cell formats. If you want rounded results, use the
ROUND()function. This only affects newly compiled engines.
- AFC no longer treats errors conditions like
#NUM!as zero. Instead, it signals an error.
contains(Cell)method was removed from
Range, because the
contains(Range)method can be used instead.
Spreadsheet.RangeNameDefinitioninterfaces were removed. The
getDefinedName(String)method was removed from the
Spreadsheetinterface. Its functionality is now provided by the
getDefinedNames()method which now returns
- AFC can now load spreadsheets in the OpenDocument
.odsformat (as written, for example, by OpenOffice.org Calc).
COVAR()is now supported.
COUNTIF()are now supported.
ZTEST()are now supported.
VARA()are now supported.
SIGN()are now supported.
VDB()is now supported
DGET()are now supported.
CLEAN()is now supported
FIXED()are now supported
DSUM()et al. now handle date/time strings.
- You can now tell AFC to compile to more readable code when decompiled.
DAYS360()is now supported.
TIMEVALUE()are now supported
- We now support binding unboxed numeric types as inputs (
int, etc.) to string-valued cells.
MATCH()is now supported for string comparisons.
- When creating cell names from row titles, AFC now filters out typical illegal characters (spaces, for instance).
- A few convenience variants of
defineInputCellet al. make it easier to bind cells to methods. You no longer have to construct the
CallFrameobjects yourself, except for advanced binding.
- The folding support (used to implement
SUMetc.) has been rewritten completely. It can now handle multiple parallel vectors, multiple aggregators, and has much more streamlined code in the implementation.
- We now verify the spreadsheet model loaded from our test spreadsheets against an external description (.yaml files). This ensures that test sheet changes are reflected in a diffable format.
- The reference test sheets now have columns that check whether the expected and actual values truly match (in Excel). These columns are verified during reference tests (formulas and values).
- You can set
build.propertiesto make reference tests silently update the .yaml files in-place. More streamlined when you detect changes using
hg statlater on anyway.
- The method
bindAllByName()no longer throws an exception if cell remain unbound. Use
bindAllByName()if you want this behaviour back.
SUMSQ()is now supported.
RANK()are now supported.
- By name binding now supports binding only cells with a given input and output prefix.
- You can query the named cells still unbound to warn users about potential automatic by-name binding problems.
- Changed the names of the runtimes to
Runtime..._v2and removed deprecated features.
Your engines won’t run anymore. Recompile.
- Changed the names of the predefined scaled
- Changed the way internal caching is controlled.
- Changed the API for manual value conversions using a given locale. Now uses a
MathContextnow supported. Older scaled
BigDecimalno longer recommended and may be phased out in the future.
STDEVP()are now supported.
COUNTA()is now supported.
T()are now supported.
ISNUMBER()are now supported.
ROUNDUP()are now supported.
VLOOKUP()are now supported.
- You can optionally configure symbols (such as the decimal separator, the grouping separator, and so on) needed to format numbers.
- Added option to load cell values of all cells, even computed ones, into the internal spreadsheet model. This is mainly useful to write automated tests (see
- Documented different way of computing date/time differences in AFC/Excel and Java in Date Tutorial.
- Computations involving repeating sections no longer need to implement
- Improved the way
- Number to string conversions now all use the configured runtime locale. This means they are no longer computed at compile-time, even if constant
- You can now bind parameters of input methods to computed cells.
- Upgraded to ASM 3.0.
- The hacking docs have been updated to reflect the new project layout.
TODAY()functions now return the same value for the same computation. This value can be reset when output class implements
- New build target
- Pass a root pointer instead of the environment to subengines. This is in preparation for having the root engine contain things like the current computation’s value of
- The packages have been renamed. The prefix
org.formulacompiler.. Old compiled engines are not compatible with this release!
- The central API has changed.
sej.SEJhas been split up into
org.formulacompiler.compiler.FormulaCompilerand, derived from this,
- The folder layout has changed. The code is now split up into a separate component per .jar file (despite the earlier reasons for not splitting the project up into modules). The components live in the
components/folder and each has its own
build/folder. This shows clearly which AFC .jars need which supporting external .jars.
- Date functions:
YEAR()are now supported.
- Conversion functions:
VALUE()is now partially supported, parsing dates and currency is not supported yet.
- You can optionally configure an explicit locale and time zone for engine factories. Great for server applications with users all over the world.
- You can make AFC treat Excel constant date/times as time-zone adjusted global times.
- You can pass pure times properly to a computation.
- You can pass dates as unboxed milliseconds since 1970 to a computation.
- Reorganized build targets to make
- Cited examples now serve as tripwires in the documentation.
- Mathematical functions:
TRUNC()are now supported.
- Financial functions:
RATE()are now supported.
- String functions:
TRIM()are now supported.
- For the
^operator, as for the new
POWER()function, invocations with non-integer exponents are converted to
- Moved from hardwired service implementor constructors (in, for example, the class
SEJ) to dynamically configured implementors. This mimics Java 6’s
java.util.ServiceLoader, but also works on Java 5. For details, see the discussion in the dev journal and also the reasons for not splitting the project up into modules.
- Updated build script so the bootstrap dummy implementations for code that gets generated later on is no longer necessary.
- Macker dependency checking rules are now generated from a central component description in YAML using Ruby. This description is also used to generate a graph of the allowed component dependencies.
- The build now runs dot and the Ruby scripts to regenerate graphics and config files.
INDEX()no longer generates a backing constant array if there are no constants.
- Replaced the JFlex/CUP-based parser with one generated by JavaCC to work around a parser limit.
- Added support for decompilation of generated engines.
- SEJ generates the
InnerClassattribute needed for proper decompilation and required by the JVM spec when a factory or computation is based on a public static inner class.
- Function reference now links to decompiled engines for example formulas.
- Tutorial topics now contain decompiled engines to better show what SEJ does behind the scenes.
- Dropped support for
- Renamed internal rewrite functions
- Dropped support for automatically aggregating outer sibling sections. You need to use an outer cell which aggregates the sibling section explicitly. This will probably be enabled more fully again later on.
IRR()are now supported (not yet over dynamic sections, though).
DMAX()are now supported.
_FOLD_ARRAY()added to internal rewriting language.
_DFOLD()to the internal expression AST, but not the rewriting language. This is because rewriting a database fold like
DSUM()is too complex for a simple rewrite. The rewriting is done in a specialized Java class.
- The constant folder now uses the template methods in
sej.internal.templatesto evaluate templated operators and functions. This got rid of a lot of redundant code, and it ensures that newly added templates automatically get constant folding support.
- Cleaned up the implementation of
BigDecimalexponentiation now fails with an internal
ArithmeticException“Rounding necessary” if the exponent is not an integer.
sej.util.Newwhich provides generic static getters to leverage Java 5 type inference (as suggested by Josh Bloch in his new slides on “Effective Java Reloaded”).
- Checked whether the engine format needs to be more robust for the future. It’s OK already.
- Added a breakdown of missing spreadsheet functions.
- Added documentation of internal rewrite functions.
- Documented how to add an array computation.
- A few entries in the developer’s journal.
- Added support for naive string comparisons. By naive I mean that they do not handle the fancy code-page stuff in Excel yet. It’s basically
- Redid the developer’s journal so it indexes automatically. Added two entries.
- Dropped support for JRE 1.4. This could be re-enabled with some effort, if anyone really needs it.
- Dropped support for
- First version of hacking docs.
- Generation of byte-code compiler methods from plain Java template methods to implement low-level functions.
- Expression rewriting to implement high-level functions.
LETfor rewriting of aggregators.
COMBIN()are now supported.
- Added generic test harness which allows me to fairly quickly debug users’s sheets.
SpreadsheetBuilder.newCell()added for creating blank cells.
- A number of automated tests compare generated .jar files against baseline versions to detect unwanted changes.
- Documentation source now in the project in Rextile format. Used to be in a custom format and only resulting HTML files were versioned in the project.
- Build script greatly streamlined and documented. Made it properly configurable/portable.
- Added download for build tools package to the main page.
- Source distribution now includes Eclipse project setup with custom Java formatting rules and all.
- Added internal logging package for structured (indented) debug log output.
- Temporary build artefacts now get written to
- Constant folding support for
- Eliminated redundant definitions of A1- and R1C1-style expression scanners.
- Excel spreadsheet saver now properly formats dates and booleans (added tests, too). Fixed issue with columns widths and default fonts not being copied from the template properly.
- Code coverage ant targets no longer run the caching speed test as the speed varies too much when coverage tracking is enabled.
- Use of
_FOLDfixes a number of bugs with aggregation over nested sections.
SEARCHwith wildcards had bugs.
- Support for writing initial spreadsheets added.
- SEJ now supports multiple sheets in an Excel workbook and resolves references across sheets properly.
- The interface
Spreadsheet.Cellnow gives access to the formula text using
- Call chaining for spreadsheet builder methods (they return
- SEJ now automatically converts numeric values to strings when a
String-valued output method is bound to a numeric cell.
- Much improved (and tested) error reporting. Error messages should now contain all information for users to be able to pinpoint the source of a problem in their original spreadsheet.
- Code coverage analysis added using cobertura and emma. Use
ant emmato run them, then check
build/coverage/coverage.htmlfor the results.
MATCHnow properly handles type arguments other than 1, 0, and -1.
- Much improved Excel function tests, used as base for reference docs.
- Improved error messages should give clearer indication of the source of a problem.
BigDecimalengines now return all values with proper scale.
- Boolean values are treated as numbers in constant folder, too.
- Enabled proper constant folding for
ORwhen they are aggregators.
- Documented and tested the use of a derived output class providing default implementations with a factory method returning a superclass.
- Implemented repeating sections with outputs.
- Improved structure of tutorial index.
- Allow setting of a custom parent class loader for compiled and loaded engines.
- Updated to JExcelAPI version 2.6.0, released on April 27, 2006.
- Updated to Retrotranslator version 1.0.7, released on July 4, 2006.
- The Ant build script now runs the tutorial tests for both the current JRE and JRE 1.4. They fell through so far because their class names do not end in
Testfor easier citability.
- As a consequence of the above, I have fixed the automatic type conversions so that they run on JRE 1.4 (which lacks, for instance,
static Byte valueOf(byte)in class
- Also as a consequence of the above, unscaled
BigDecimaldivision is no longer supported on JRE 1.4.
- Give a clearer error message when an outer cell references an inner cell of a section without aggregating it.
- The sample spreadsheets in the documentation are now cited from the real spreadsheet files used in the automated tests (using JCite again). This ensures their correctness and improves the formatting.
- The function
MATCHis supported again. However, the last argument (the match type) must be constant, and the second argument (the match range) cannot reference a repeating section yet.
- The function
INDEXis now supported for one- and two-dimensional lookup. However, the range argument cannot reference a repeating section yet.
- Implemented input-only repeating sections.
ORare not yet supported as aggregators on them, though.
- Implemented support for Excel functions
COUNTdoes not yet handle empty cells properly – this is because SEJ generally does not.)
- Documented, tested and completed the handling of the full set of allowed input method parameters.
- Refactored the binding tutorial into more separate pages.
- Added support for defining and referencing ranges to the
- Added some missing
breakstatements discovered by Eclipse’s new check (should not ever trigger anyway, but still…)
- Unbound output parameter combinations now throw
IllegalArgumentExceptionwhen there is now default implementation of the output method.
- Parametrized output methods are supported now. The interactive demo thus runs again, but does not yet look good because there are some info methods missing on the spreadsheet interface.
- SEJ now ships the new
sej-doc.jarwhich contain, respectively, the entire source code and documentation for SEJ. Not included are the examples and test cases. These two .jar files make attaching source and docs in modern IDEs very easy.
- Clarified behaviour differences between Excel and SEJ with respect to
nullinput values. See tutorial on type conversions.
NOT, and comparisons outside of the test of an
- Fixed parsing of cell/range names containing dots (
.) in the R1C1-style parser. Added unit test for parsing names (only had a system test before which did not test the R1C1 parser).
- SEJ should now accept all valid cell and range names according to Excel’s online help. In particular, Excel names may now contain dots (
.) and do no longer have to start with an underscore or at least two alphabetic characters.
- Type conversion is now documented.
- All exceptions are now called
- Can call static input methods.
- Removed the superfluous
Engine*.jarfiles from the binary distribution.
- Can use non-static local classes as inputs again.
- The new
EngineBuildersupports the most typical use-case out of the box. The
SpreadsheetNameCreatorgive more fine-grained control over this. This use-case is used to provide the motivation for using SEJ in the tutorial.
- Separated the concept of a computation engine (collection of computation classes) from the concept of a computation factory. Engine is now the thing being loaded and saved. Factory creates now computation instances. The factory can be forced to implement an application-specific interface or base class, which makes SEJ even more non-intrusive on application code (see use-case above).
- SEJ now converts between its internal numeric type and basically all numeric Java types in the input and output method result types. To support this, scaled
longvalues in the interface must now be annotated with
ScaledLong. (While already tested fairly rigorously, the full documentation for this feature is still missing.)
- Saved engines are now normal .jar files, which can be inspected like any other .jar file. The generated classes are normal .class entries in the .jar file.
- I have reorganized the packages. Everything internal is now in
sej.internal. Everything need for the loading and running of compiled engines is in
sej.internal.bytecode.runtime. The compile-time public API is in
- I have rigorously trimmed the API again. Every non-trivial entity is now represented by an interface in the API, not a class. The central class
sej.SEJprovides factory methods for all of these.
- The fairly monolithic low-level interface
sej.Compilerhas been broken up to reflect the processing chain:
sej.SpreadsheetCompiler. Most of these components have a consistent instantiation protocol with a factory method in
sej.SEJand a configuration class called
XY.Configwhich supplies parameters to new instances. This is in preparation of being able to expose the internal computation model as a lightweight alternative to the spreadsheet model.
- New base error class,
sej.runtime.SEJError, from which all others are derived. Better separation of errors into
- You can now generate engines that support internal caching of inputs, outputs and multiply referenced intermediate values.
BigDecimalnumeric type now generates vastly more efficient constant values. They are preconstructed in
private static final BigDecimalfields, using
BigDecimal.valueOf( long, int )wherever possible.
- Implemented scaled
sej.NumericTypenow has support routines for value conversions.
sej.runtimeis a new package holding the runtime support classes. They used to be in
- Added automated tests for serialization and deserialization of engines, as well as the use of the runtime-only jar for deserialization.
- Removed ASM dependency from the base
- Removed general expression interpreter support. Introduced special constant folder support instead (much faster).
- Exponentiation (
A1^A2) and taking a percentage (
A1%) now work when applied to input cells. Added this to the test suite.
- SEJ ships with two new .jars,
sej-runtime-jre1.4.jar, which have been converted from Java 5 to Java 1.4 by Retrotranslator. Use these .jars if you plan to deploy SEJ on the JRE 1.4. All unit tests are now run automatically using both the JDK 1.5 and a JRE 1.4 during builds to ensure compatibility.
- I dropped
Engine.Computation. You no longer have to subclass this thing when defining an output type. As a consequence, you can now define an output as an interface instead of a class.
- I moved the
Compiler. That way, compiled engines don’t need the interface to the compiler, making
sej-runtime.jara little smaller still.
- SEJ accepts
booleaninput values and can return both
- Moved all test and sample data to folders named
org/formulacompilerfor better compatibility with the source layout at Abacus.
- I fixed the contents of the distribution packages so the documentation style-sheets are included.
- The run-time .jar now works (that is, contains all the required stuff).
This minor release changes the name
Compiler.Section. Since we are no longer binding by name, the term NameSpace is no longer appropriate.
Compiler.getRootNameSpace() has been shortened to
This is the first release with the new API based on binding cells to native types. The interpreter has been dropped and replaced by a byte code compiler producing very fast code.