Implementing custom event hyperlinks (drilldown) in the XFRX previewer
Setting up custom event hyperlinks
The custom event hyperlinks are defined the same way as normal hyperlinks: you add #UR A HREF= to the label or field comment, followed by “vfpev” as a “protocol”, followed by a FoxPro expression to evaluate.
Example: Hello world
#UR A HREF="vfpev:\\messagebox('Hello world')"
If you add this to a field on your report a “Hello world” messagebox pops up whenever you click on that field.
Please be aware that the text following after HREF= is evaluated during the report execution, at the time the field is about to be rendered. The result is then stored with that particular field and evaluated again when users click on the field. For example, if you need to call your function with a customer ID as a parameter (for example stored in customers.cusID as an integer value), you use something like this:
#UR A HREF="vfpev:\\myfunction("+trans(customers.cusID)+")"
During the report generation the customers.cusID expression is evaluated and the results (e.g. myfunction(1), myfunction(2), etc.) are stored with the individual fields. Myfunction function with the stored parameter is then called when users click on the field.
Enable Custom Hyperlinks for all outputs
XFRX previous versions support custom hyperlinks only in XFRX Preview. But you can change this behavior.
This feature is available since XFRX 18.2.
loSession.SetOtherParams("IncludeCustomHyperlinks",.T.)
Accessing the calling previewer
In case the custom event should result in running a new report, the routine that processes the new report may want to previewer the resulting output in the original previewer, in which the click event occurred. In that case, you can use thisviewer variable as the previewer reference. For example, the following hyperlink definition would be sending the previewer reference as the second parameter of runreport method:
#UR A HREF="vfpev:\\runreport('"+allt(customerid_a)+"',thisviewer)"
Drilldown solution example
(The following example is available in the DrilldownSample subdirectory of the evaluation as well as commercial package).
The sample solution consists of three reports:
- A customer index page followed by a brief list of customers. For each customer there is a list of last three orders, total number of orders and the total turnover:
- When you click on the customer name, a new report with customer details is generated, listing all customer’s orders:
- By clicking on an order number, an order detail report is generated:
Whenever a new report is generated, it is added as a new page to the previewer container:
Here is the full source code:
LPARAMS m.tnReportType, m.tuPar1, m.toViewer SET PATH TO src; xfrxlib; libs; drilldownsample LOCAL m.loSession, m.lnRetval, m.lcPageCaption, m.loPreview IF EMPTY(m.tnReportType) * * no report type was sent - we need to initialize the previewer * and run the 1st report * SET CLASSLIB TO xfrxlib m.loPreview = CREATEOBJECT("frmMPPreviewer") m.tnReportType = 1 m.toViewer = m.loPreview ENDIF * * initialize the XFRX listener * m.loSession=EVALUATE([xfrx("XFRX#LISTENER")]) m.lnRetval = loSession.SetParams(,,,,,,"XFF") IF m.lnRetval = 0 * * now let’s see which report we want to run, select the data * and run the report * DO CASE CASE m.tnReportType = 1 SELECT companyname ; FROM customers ; ORDER BY companyname INTO CURSOR custindex REPORT FORM custindex OBJECT m.loSession Nopageeject SELECT * ; FROM customers INNER JOIN orders ON customers.customerid = orders.customerid ; INNER JOIN orderdetails ON orders.orderid = orderdetails.orderid ; ORDER BY customers.companyname, customers.customerid, orderDate Desc, orders.orderid ; INTO CURSOR custlist REPORT FORM custlist OBJECT m.loSession m.lcPageCaption = "Customers list" CASE m.tnReportType = 2 SELECT * ; FROM customers INNER JOIN orders ON customers.customerid = orders.customerid ; INNER JOIN orderdetails ON orders.orderid = orderdetails.orderid ; ORDER BY customers.companyname, customers.customerid, orders.orderid ; WHERE customers.customerid = m.tuPar1 ; INTO CURSOR custlist REPORT FORM custDet OBJECT m.loSession m.lcPageCaption = "Customers detail ("+ALLTR(m.tuPar1)+")" CASE m.tnReportType = 3 SELECT * ; FROM customers INNER JOIN orders ON customers.customerid = orders.customerid ; INNER JOIN orderdetails ON orders.orderid = orderdetails.orderid ; INNER JOIN products ON products.productid = orderdetails.productid ; ORDER BY customers.companyname, customers.customerid, orders.orderid ; WHERE orders.orderid = m.tuPar1 ; INTO CURSOR custlist REPORT FORM OrdDet OBJECT m.loSession m.lcPageCaption = "Order detail ("+ALLTR(STR(m.tuPar1))+")" ENDCASE ENDIF * * now preview the report * m.toViewer.previewXFF(m.loSession.oxfdocument, m.lcPageCaption) * * show the preview if not yet visible * IF NOT loPreview.Visible * * preview in modal Windows * m.loPreview.Show(1) EENDIF
As you can see, the code is first called without parameters, which automatically runs the first report (customer list). Then the same code is then called (recursively – as the previewer is in modal mode) from the previewer when users click on the custom event with parameters controlling which report should be run, which parameters should be used for the select statement and what should be the caption of the corresponding page in the previewer.
The report fields’ comments are defined as follows:
Report | Field | Comment |
---|---|---|
Customer list | Customer name | #UR A HREF="vfpev:\\runreport(2,'"+allt(customerid_a)+"',thisviewer)" |
Customer detail | Order number | #UR A HREF="vfpev:\\runreport(3,"+allt(str(orderid_a))+",thisviewer)" |