Future Compatibility

Use this trick to support future functionality while still getting your code to compile in older versions of Access.

Future Compatibility

There are several things that annoy me about the default behavior of DoCmd.OpenReport.  To address these annoyances, I built a replacement function that I named PreviewReport().

In this series of articles, I will take you through the evolution of this function as I address each of my frustrations.

Part 5: Missing OpenArgs

The DoCmd.OpenReport function signature changed from Access 2003 to Access 2007.

Access 2003 and earlier

DoCmd.OpenReport(ReportName, View, FilterName, WhereCondition, WindowMode)

Access 2007 and later

DoCmd.OpenReport(ReportName, View, FilterName, WhereCondition, WindowMode, OpenArgs)

As you can see, prior to Access 2007, OpenArgs was not supported as an argument for the OpenReport method.  Including the OpenArgs argument would raise a compile error when run in Access 2003 and earlier.

For several years, I had some applications where I needed to maintain backward compatibility with those earlier versions of Access.  However, I wanted to begin using the OpenArgs parameter in as much of my new development work as possible.

This created a dilemma for me.  My evolving PreviewReport() function lived in my standard Code Library.  As such, I wanted to be able to use it in both old and new applications, without having to change the function in any way.  If I had to tweak the function based on a particular application, then it would no longer be a standard code module.  After all, the key to having a code library that contributes to efficiency is being able to completely replace a module with a newer version and not have to worry about it breaking anything.

So, how can you write code that supports future functionality but still compiles in an older version of Access?

The generic Object to the rescue

The first thing to realize is that DoCmd is actually a method of the Access Application object.  This means that we can set the Application object to a generic Object variable.  

With a generic Object, the VBA compiler won't do any compile-time checking of the properties or methods of the object.

In most cases, this is a bad thing.  (An important concept in defensive programming is to raise errors as early as possible in the design process.  Hence, compile time errors are better than runtime errors because those sorts of errors are easier to discover.)

In this case, though, we can use this behavior to our advantage.

'OpenArgs for reports was added in Access 2007
If CSng(SysCmd(acSysCmdAccessVer)) >= 12 And Len(OpenArgs) > 0 Then  
    'Workaround to allow code to compile in versions of Access prior to 2007
    Dim AccessApp As Object
    Set AccessApp = Application
    AccessApp.DoCmd.OpenReport RptName, acViewPreview, , Where, , OpenArgs
    DoCmd.OpenReport RptName, acViewPreview, , Where
End If

Final note

Admittedly, this particular issue is not really a big deal anymore as Microsoft hasn't supported Access 2003 for many years.  However, the technique itself is valuable, since the Access object model does still change from time to time.


Five down, none to go:

  1. Auto-Print: Opening a report sends it directly to the printer with no on-screen preview
  2. Wrong Data: If you call OpenReport on a report that's already open, Access doesn't apply the new criteria to the report
  3. Unwarranted Errors: When you cancel report opening in the OnNoData event, Access raises an error
  4. Cascading Maximize: If you open a report from a windowed form, maximize the report, then close it, the windowed form from which you opened the report gets maximized
  5. Missing OpenArgs: Prior to Access 2007, OpenArgs was not supported for the OpenReport method

In the final article in this series, I will present the finished versions (with and without vbWatchdog compatibility) of my PreviewReport() function.

Image by Markus Christ from Pixabay

All original code samples by Mike Wolfe are licensed under CC BY 4.0