HOWTO: Storing Report Definitions in a Database

The following article describes what to do if you want to store report definitions in a database rather than in a file.

Using the .NET Component

Version 22 and Higher

Starting with version 22 of List & Label, we provide a programming interface that uses a virtual file system - called Repository - that is fully stream-based. It also supports the usage of dependencies of a project file like drilldown reports, any file-based objects like image objects or PDF objects, project includes etc. and it is recommended to use it - especially when using List & Label in web applications. See more details in the article Using the Repository Mode within the .NET Help.

Version 16 and higher

Starting with version 16 of List & Label you can alternatively use stream objects for the methods ‘.Design()’ and ‘.Print()’ to use report definitions. During design time the menu items ‘File > New’, ‘File > Open’ and ‘File > Save As’ are automatically disabled. Therefore, no additional calls to ProhibitAction are required. And if you are using the DOM API, you can also use stream objects. This feature eliminates the need to cache report definitions from the database to the file system. For more information and limitations, see the .NET Help on [Store Project Files in a Database] (Store Project Files in a Database). Note: this will not handle any dependencies, just the project file itself.

Use with other components or native APIs

Basically, List & Label always uses a file to read or write the report information. This report filename is passed to the corresponding methods responsible for invoking the designer to create/modify reports and to the methods responsible for performing the printing. Two examples are LlDefineLayout() and LlPrintWithBoxStart().

So, if we want to retrieve a report definition from a database, we’ll have to create a temporary file where we store the report information (read from a BLOB or MEMO field).

This means that your application must first offer all available reports in a list and let the end user choose which one they want to modify. Let’s call this dialog “report selection dialog”. After that, your application will create a temporary file with the selected report content.

Now we need to prevent the Designer from displaying this temporary file name in its title bar (which would not only be annoying, but also look rather unprofessional). This can be achieved by 'OR’ing the project type parameter of LlDefineLayout() with LL_NONAMEINTITLE.

Additionally, we need to prevent the end user from using the Open, New and Save As menu items, as this would cause the design results not to be saved to our temporary file.

This can be done by hiding the menu items with LlDesignerProhibitAction() before starting the designer:

...
// hide/disable menu items
::LlDesignerProhibitAction(hJob, 524);
::LlDesignerProhibitAction(hJob, 519);
::LlDesignerProhibitAction(hJob, 515);

// start/open the Designer
LlDefineLayout(
				hJob, 
				hWnd, 
				L"Designer", 
				LL_PROJECT_LIST | LL_NONAMEINTITLE , 
				szTempFile
				);
...

When the Designer is closed, all we have to do is collect the temporary file, transfer its contents to our database, and then delete the file. That’s it.

You could also allow the creation of new reports:

  • The “Report Selection Dialog” gets an additional item “New Report” in its list. When selected, your application will create a temporary, non-existent filename (without creating the file itself) and use the code shown above.
  • If you want end users to be able to create new reports using existing ones as templates, you could add a “New Report from Template…” item.

Note: The Designer automatically stores the filename of the last saved report file in the registry key HKEY_CURRENT_USER\Software\combit\cmbtll<modulename>\LastFile (where is the module name of your application). This can be useful if you want to allow end users to ‘save as’, but you want to edit the file afterwards.

IDKBTE000593 KBTE000593
.