LlPrintStart / LlPrintOptionsDialog logic in .NET

I am trying to reqork my programming logic to use .NET interface with databound mode.
My current logic uses the API functions LlPrintStart and LlPrintOptionsDialog to ask the user for a target before the data is actually retrieved.
I would like to keep this logic, i.e. ask the user for the print destination before retrieving the data.
Is there an equivalent e.g. LL.PrintOptionsDialog which would allow prompting the user for options, then get the data and then pass the datasource to LlPrint() ?

The dialogs are called automatically when AutoShowPrintOptions is set to true.

Of course you can also call the dialog yourself via LL.Core.LlPrintOptionsDialog and then set AutoShowPrintOptions to false.

However, it would be advisable if you stick to the standard procedure.

Detailed information on “LlPrintOptionsDialog” can be found in chapter “6.1 Function Reference” of your programmer reference starting on page 241.

Thanks for the reply. My problem is that LlPrint() expects a populated datasource. But I do not want to retrieve the data before asking for the print options.
If I try to use the LlPrintOptionsDialog, then I get the error: “combit.ListLabel24.LL_Printing_Job_Exception: A print function was called, although no print job has been started or the project contains no objects.”.
I tried to add LlPrintStart() but then I get the error: combit.ListLabel24.LL_BadDatabaseStructure_Exception: The database structure that was used for the design does not match the database structure at print time.".
It looks like these functions are not intended for databound mode. Any suggestions?

How did you do that before you revised your programming logic?

When LlPrintStart() is called, a project file must be specified. LlPrintOptionsDialog always refers to a project file, because the P-file is also written…

The “old” logic did indeed use LlPrintStart() with a project file. Then LlPrintOptionsDialog() to prompt for destination etc. Then the data retrieval process started, after which the output was sent to the selected destination. This works, except that I am using DefineVariable() calls to send the data - field-by-field - to L&L which is an expensive operation. This is why I am looking in to the databound mode which allows me to hand over a complete dataset to L&L.

As far as I understand, LlPrint() within the databound model handles the data retrieval from the datasource from within the LlPrint () function. That does not work for me as the data source is an OpenEdge temp-table which is populated on the server, then returned to the client, then passed to L&L. The data retrieval is not a direct database query and also some post-processing might occur on the temp-table after populating it.

I would like to keep this existing logic to avoid having to rewrite the data retrieval logic. So my foreseen logic would be: 1) Ask user for export target and options, 2) retrieve the data, 3) hand the datasource over to L&L to do the processing using LlPrint() without user interaction. Can that be done?

The databinding layer also passes the required information field by field. The API calls typically are very cheap. Given your logic, is there any reason why the export target cannot be selected after starting the print job (i.e. the way it works by default)? Are you aware of our specialized OpenEdge data provider? Information about the data provider can be found in our combit developer blog.

I did some testing using DLL calls (which is what the old method does) and found that these calls are expensive. Also because I need to to a code[age conversion from UFT-8 to UTF-16 with each call.
Yes I did look at the OpenEdge datprovider and are actually using it - but most likely I do not fully understand it sufficiently.

Jos, you could reach out to Thomas Wurl who wrote the OpenEdge provider and see if he can help you. Regarding the thread’s topic: the logic of the print options dialog requires to first open a project file, then call the dialog just like you had it in place before.

If flipping the order to this scheme is a problem we’d need more background on why this is so. If you pass a data provider, we will be as cautious as possible when asking it for data, i.e. no unrequired data should be queried at any time then.

Opening the project file is not a problem, but I guess that that will require sending the database structure using my "old’ logic, i.e. using DefineVariableExt() ?

Not really IIUC - if you attach a DataProvider instance to the component, it can query the data whenever needed. You don’t even have to open the project file yourself, just call the Print() method which does everything automatically in the background. If you need to fine-tune the behavior, you can use the Auto… properties and events at any time.

I get the feeling I am missing some important concept here. I have a data provider configured and if I export what is in the dataset, the output is there. However, LL shows an empty report.

Would be interesting to see what’s in the Debwin4 log in this case. It’s supposed to work exactly that way.

EXCEPTION(WRN: database table ‘’ does not exist)
_ParentDataProvider->OpenTable() FAILED: WRN: database table ‘’ does not exist

Not sure if this is related…

That would mean that the file you’ve designed did use a different or no database structure at all. When using a data provider, this changes the way things are handled. You need to at least open the file in the Designer and assign your table as data source. For a quick check, simply design a new file and see if it works in that case.

If you have many existing project files you could use the object model for a batch conversion. Basically, you need to set the TableID property for the table objects to the name of the required table.

Strange. I can option the project file using databound mode. I use the same project file subsequently for the Print() method. I populate the dataset before calling the Print() method. I almost start thinking that the OpenEdgeDataProvider clears the dataset during the Print() method.

I had a closer look at the design and - as it originates from a non-data-provider-mode - did not have a datasource assigned. After assigning the datasource, it did print the report with data. So one (big) step forward!

It still does not solve my original problem though, as I want the user to specify output destination and options before retrieving the data. Which is why as was looking into LlPrintStart and LlPrintOptionsDialog. These are integrated into the LlPrint() method, but that would require having to retrieve the data beforehand which I would like to avoid.

I think I would like to try setting TableID by code. I am breaking my head on how to do this, though. How do I get to the tableID using Dom?

Here is a small excerpt from our C#-SimpleDom example:

//Add a table into the table container
SubItemTable table = new SubItemTable(container.SubItems);

//Set required source table
table.TableId = comboBoxTable.Text;

//Define zebra pattern for table
table.LineOptions.Data.ZebraPattern.Style = "1";
table.LineOptions.Data.ZebraPattern.Pattern = "1";
table.LineOptions.Data.ZebraPattern.Color = "LL.Scheme.BackgroundColor0";

//Add a new data line including all selected fields
TableLineData tableLineData = new TableLineData(table.Lines.Data);
TableLineHeader tableLineHeader = new TableLineHeader(table.Lines.Header);

The complete source code, and other examples can be found in your LL installation directory in the subfolder \Examples.

As discussed, we will continue the behavior through our support portal. As soon as a possible solution is available, we will publish the findings here for all users.

Hi @Jos_Hennen1, from a chat with Thomas Wurl I seem to understand you’ve found a solution in the meantime. Would be great if you could share it with the others for future reference :slight_smile:

Hi Jochen, sure I want to share this. Apologies for the delay, I have been busy.

Please note that the “.TXT” extension needs to be removed from the attachments!

From: Thomas Wurl
Sent: dinsdag 16 juli 2019 18:54
Subject: OpenEdge Data provider question

Attached is a sample with a different JomalaDatasetServiceAdapter that asks the surrounding procedure to get the data into the dataset.
So you don’t need to pre-fill the dataset and you can do that if you have asks the user for your options like output destination, layout, whatever.
It’s simple – but I agree it’s not easy to understand …

The sequence of events is the following.
• DP:Initialize() – DP reads the schema from the attached service and registers everything for LL.
• Now LL has the schema.
• LL asks for Printer, Layout, whatever.
• LL loads the project file and processes it.
• During this LL asks the DP for data for tables (Filter, Sorting,…)

Codepage conversion from UFT-16 (Memory) to UFT-8 should also happen automatically. The DP creates JSON from datasets via WRITE-JSON and I think this does the conversion – but not sure.
But there are only some places to fix if not.

Hope this helps!

Umpack the zip and use the content together with the jomala folder. Have a look at Jomala/JomalaDatasetSample.p.DatasetSample.lst.txt (27.4 KB) JomalaDatasetSample.p.txt (4.1 KB) JomalaDatasetServiceAdapter.cls.txt (1.7 KB)

2 Likes