News combit Dev Blog

dsListLabel - Simplified Xbase++ Integration

Posted: Friday, February 24, 2017 | 2 comment(s)
 
Years ago I started developing a class to simplify the integration of List & Label into Xbase++ which I used for all my client's apps. The range of functionality grew with every new task. By now it supports real data preview which is handled in a separate thread.

As we also offer Addon Libraries for Xbase++ developers (XClass++, AdsClass++, VisualDBU,...) it did not take long until users asked me to share my ideas and code and provide a common class to everyone. Xbase++ developers are used to a high level language and do not really want to deal with API calls.

After consulting with the List & Label team, we decided to share this class and provide it free to everyone. The main approach is to implement sophisticated methods which completely hide the List & Label API. This class will meet most of the demands for everyday reports. It provides callback slots to call all List & Label API functions which are not already wrapped by methods. So there is no limit of individual configuration possibilities.

This is the basic code for creating a report:

FUNCTION Print(oDlg)     // oDlg is calling dialog 
  LOCAL oListLabel 
  LOCAL nError 
 
  oListLabel := dsListLabel():New( oDlg) 
 
  // some error handling
  if oListLabel:Status() == XBP_STAT_FAILURE 
    Msgbox("Cannot load List & Label:"+;
		var2char(oListLabel:Getlasterror())) 
    RETURN false 
  endif 
 
  // report file is searched in :DefaultPath or current directory 
  oListLabel:Report := "order.lst" 
 
  // current workarea is printed in a do-while loop 
  // filter or scopes are respected 
  oListLabel:Connect() 
 
  // register table to be visible in designer and provide data to print 
  oListLabel:DataSetField() 
 
  nError := oListLabel:Print() 
 
  if nError <> 0              // some error handling 
     Msgbox(oListLabel:GetLastMessage(), "Error: "+;
			var2char(oListLabel:GetLastError())) 
  endif 
  oListLabel:Close() 
RETURN nError == 0 

Basic configuration can be set once in the main function like main() and is stored in class members.
dsListLabel():LicensingInfo(<your personal List & Label license>)
dsListLabel():DefaultPath(".\ListLabel")

Little by little this sample can be extended. For example, it is very easy to export the report into a PDF document:
// open export file afterwards, default = .f. 
oListLabel:Showexport := .t. 
 
// instead of :print() 
nError   := oListLabel:SaveAsPdf("c:\tmp\myfile.pdf" )

And sending the report by email is also quite simple:
cCC      := "cc@ds-datasoft.de" 
cBCC     := "bcc@ds-datasoft.de" 
cSubject := "Hello World" 
cBody    := memoread("MailBody.txt")       // for example
 
// instead of :print() 
nError   := oListLabel:SendAsMail(.f., "info@ds-datasoft.de", cCC, cBCC,;
			cSubject, cBody )

So far this looks pretty good. In the next step we will add a report container to support relational data structures, typically used for master-detail printing:
// register tables for designer 
oListLabel:DataSetField(select("Order"), "Order") 
oListLabel:DataSetField(select("OrderItem"), "OrderItem")

// register tables for report container 
// 2nd parameter: symbol name must be identical with 2nd parameter of 
// DataSetField! (case-sensitiv!) 
oListLabel:AddTable("Order", "Order") 
oListLabel:AddTable("OrderItem", "OrderItem") 
 
// register relationen 
// 1st + 2nd parameter: symbol name must be identical with 2nd parameter of 
// DataSetField! 
oListLabel:AddTableRelation("OrderItem", "Order", "Order Items") 

// Codeblock when table changes in report container 
oListLabel:TableChange := {|o,l,c,p| _TableChange(o,l,c,p)} 
 
nError := oListLabel:Print()

Additionally I have added two more features:

  • A callback slot when printing from preview (e.g. to set a print flag)
    // callback, printing
    oListLabel:Callback :=	{|nE,nId,oListLabel|myFunction(nE,nId,oListLabel)}
  • Real data preview in the Designer. To implement this feature a thread is started, the registered tables are moved to the workspace of this thread and the data is passed to List & Label. When finished, the tables are released and moved back to the original workspace.
    // enable once in main()
    dsListLabel:DefaultDesignerPreview(.t.)
    
    That’s it! Once this feature is enabled and you switch to the preview in the Designer you get a preview with real data. All the work is done in the background. This feature requires also to install the OT4XB package from Pablo Botella Navarro which can be downloaded from www.xbwin.com.


The dsListLabel package includes DLLs for List & Label 22 and Visual Xbase++ 2.0. As the source code is also shipped, DLLs for different versions can be created by demand. The component dsListLabel will be included in the next List & Label 22 installation. Or you can download it directly from our website.




Author: Marcus Herz
Partner at DS-Datasoft

Marcus Herz has specialized in Xbase++ development and has created addon libraries from the very beginning of Xbase++. He realizes individual and specific industry solutions and other data-based projects.



+1 800 256 3608 (toll-free North America only)