Visual Report Writer and The Web (IV)
by
, 28-Apr-2013 at 10:39 AM (11758 Views)
In this fourth blog the Customer List is the topic. Ehh, a customer list, isn't that too simple for a demo and a blog? Yes and no. A customer list running on the Web Order Customer table is in fact a simple report but as you discover below we have added a couple of features to make the report and integration more attractive. To see the here discussed report in action you should navigate to the live demo website (European Server, USA server). You are also advised to read the three previous blogs (1: The Solution, 2: Invoices Report, 3: The Cleanup).
The Report
The report is named Simple Customer List but contains a couple of enhancements to make it more attractive. The report contains two functions. One function is named PageNumber which simply return the text "Page:" combined with the special field {&Page Number}. Besides the fact that you can easily combine a static text and a variable it can be seen as simple. The second function is named StateName which shows the usage of ELFs. ELF is the abbreviation of Extended Library Function. With Visual Report Writer you can make use of functions written in a DLL (Dynamic Link Library) to perform special operations that are not in the product itself. The functions should return a value and in this case it returns the name of the customer state by finding a row in the codemast table of the workspace. This ELF is named CodeDescription and is delivered with the product in a DLL named CodeMast.Dll. The function code itself is:
The first parameter of this function call is a path to the codemast table. The codemast table maybe converted to SQL and then the value of the report parameter named CodeMastPath should point to an INT file. In this demo website the table is in the embedded DataFlex database format and thus points to a codemast.dat file on disk. With the usage of the parameter field it is possible to control the location of the table at integration level in a similar way as pbAutoLocateDFFiles operates.Code:return CodeDescription({?CodeMastPath},"STATES",{Customer.State})
Last but not least; a report should look nice, should be attractive. In this report we added a blue bar behind the column captions and the bar has a rounding in its corners. For the upcoming revision 3.0 we can add gradients to such an object to make it even more attractive.
The Integration
At report integration level we decided to add a couple of features available in and through the DataFlex 17.1 Web Application Framework.
First, the selection criteria and the results are separated from eachother to make more space for both of them and to show that it can be done. The selection criteria can be set on the first cWebTabPage object and the results are shown in an iFrame control on the second tab-page. The selections tab-page is divided into two panels to keep the controls reasonable in width on wider devices. The width of an input control enlarges if the width of the view enlarges and the piWidth of the cWebView object is not set to a specific width.
The first control on the tab-page is a cWebCombo control which is data-aware and automatically pulls the states from the codemast table via the DD validation table connection. The only change made in regards to this control is the cancellation of the field_defaults setting in the customer data dictionary object. Normally the state Florida is specified as a default state and to avoid the report by default only shows the customers of one state this is blanked out. You can still - and it is the purpose of having the cWebCombo - a state to limit the data found and presented. In the OnInitializeReport event of the cVRWReport object this is covered as:
The second control on the tab-page is a cWebForm control, not data-aware and "just" an input field. If the user enters a value here the rows from the table are filtered on including this value in the name column. In coding this is done as follows:Code:WebGet psValue of oCustomerStateForm to sCustomerState If (sCustomerState <> "") Begin Send AddFilter C_USEMAINVRWREPORTID "{Customer.State}" C_VRWEqual sCustomerState End
Usage of functions inside a psFilterFunction adds power to the system BUT slows down the selection. Visual Report Writer currently (still on the wishlist) does not attempt to offload selection criteria if a function is used inside a psFilterFunction instruction. Offload means adding the selection criteria to the WHERE clause in an ODBC database report and jump-into index in a DataFlex embedded database data-source report. Note that selection criteria in a psFilterFunction where no functions are used can be offloaded to speed up the selection process. For an ODBC based report you can check if the selection criteria are offloaded by viewing the SQL statement created, available from the report designer tool as well as from integration level (ReportQuery function of cVRWReport).Code:WebGet psValue of oNameContains to sNameContains If (sNameContains <> "") Begin Get GetChecked of oContainsCaseInSensitive to bCaseInSensitive Move (SFormat ("return Instr({Customer.Name},'%1',1,%2)", sNameContains, bCaseInSensitive)) to sFilterFunction Set psFilterFunction C_USEMAINVRWREPORTID to sFilterFunction End
The next control is again a cWebCombo control but not data-aware this time and its values are hard coded in the OnFill event of the control. The control allows you to limit the number of found customers by looking at the customer.status column. The following code is used to pass the user' choice to the report selection criteria.
The next control is a horizontal line to serve both the purpose of creating some distance between the combo and the sliders (the next big thing) and having "just" a separator line. The object is instantiated from the cWebHorizontalLine class.Code:WebGet psValue of oCustomerStatus to sStatus If (sStatus <> '-') Begin Send AddFilter C_USEMAINVRWREPORTID "{Customer.Status}" C_VRWEqual sStatus End
The next three controls are sliders (cWebSlider). The user can set the selection range for balance, purchase or credit limits to a upper and lower boundary value. The checkbox on the right hand side of the slider needs to be used to make the value active. This is done because the slider's ranges are set to a smaller range than the full set, just to show it can be done.Code:Object oSpacerLine is a cWebHorizontalLineEnd_Object
How code is behind the slider controls? First the object itself:
You can create this by drag-and-drop from the class palette and setting properties as pbShowRange, pbShowValue and pbRanged.Code:Object oPurchasesSlider is a cWebSlider Set piColumnSpan to 6 Set psLabel to "Purchases Range:" Set peLabelAlign to alignRight Set pbShowRange to True Set pbShowValue to True Set pbRanged to True End_Object
The OnLoad event is used to find the current highest and lowest values for the columns balance, credit limit and purchases. Because the credit limit and purchase columns are not part of an index we added two indexes to the customer data file to make the process of finding the highest and lowest value easier and faster. The OnLoad event of one of the sliders is:
The code above sets the mimimum and maximum values of the sliders (piMinValue and piMaxValue) but also sets a "current" range which is 10% of the maximum minus the minimum value plus the minimum or the maximum, moving the range a little off the upper and lower values.Code:Procedure OnLoad Integer iMinValue iMaxValue iFrom iTo Forward Send OnLoad Clear Customer Find Gt Customer by 3 Move Customer.Balance to iMinValue Clear Customer Find Lt Customer by 3 Move Customer.Balance to iMaxValue Move (iMinValue + (iMaxValue - iMinValue / 10)) to iFrom Move (iMaxValue - (iMaxValue - iMinValue / 10)) to iTo Set piMinValue to iMinValue Set piFrom to iFrom Set piMaxValue to iMaxValue Set piTo to iTo End_Procedure
The slider control can show labels spread over the slider and this is done in the event OnFillLabels.
Three labels are added at 5, 50 and 95% of the minimum and maximum values.Code:Procedure OnFillLabels Integer iMinValue iMaxValue iLow iMedium iHigh Get piMinValue to iMinValue Get piMaxValue to iMaxValue Move (iMaxValue - iMinValue * 0.05) to iLow Move (iMaxValue - iMinValue * 0.50) to iMedium Move (iMaxValue - iMinValue * 0.95) to iHigh Send AddLabel iLow "Low" Send AddLabel iMedium "Medium" Send AddLabel iHigh "High" End_Procedure
The ranges are - if made active via the checkbox - added to the selection criteria via the following code (again inside OnInitializeReport)
In the report description above is mentioned that the report uses codemast.dll to return the name of the state. For this the path to the codemast table needed to be given and it was done via a parameter named CodeMastPath. The parameter is set in a method of its own (started from OnInitializeReport). In the following code the report is queried for the parameter ID of the named parameter CodeMastPath which is then used to set the path.Code:Get GetChecked of oUseBalanceFiltering to bUseValue If (bUseValue) Begin WebGet piFrom of oBalanceSlider to iFrom WebGet piTo of oBalanceSlider to iTo Send AddFilter C_USEMAINVRWREPORTID "{Customer.Balance}" C_VRWGreaterThanOrEqual iFrom Send AddFilter C_USEMAINVRWREPORTID "{Customer.Balance}" C_VRWLessThanOrEqual iTo End
For deployment it is important to make sure the DLL can be loaded. In the web site this means the codemast.dll has to be copied to the same folder where webapp.exe is stored.Code:Procedure SetParameters Integer iParameter String sCodeMastPath Get ParameterIdByName C_USEMAINVRWREPORTID 'CodeMastPath' to iParameter Get_File_Path "CodeMast.Dat" to sCodeMastPath Set psParameterValue C_USEMAINVRWREPORTID iParameter to sCodeMastPath End_Procedure
The report generation is done in a routine named GenerateReport which is started by the RunReport button in the commandbar used in the cWebView.
The main difference between this code and the GenerateReport discussed in Invoices Report Blog is the instruction to switch to the results tab-page. The Send Show is responsible for switching tab-pages.Code:Procedure GenerateReport String sReportId sFile sUrl VRWPDFExportOptions PDFExportOptions Boolean bCanceled Get OpenReport to sReportId If (sReportId <> "") Begin Get DefaultPDFExportOptions to PDFExportOptions Set pPDFExportOptions to PDFExportOptions Get ReportCacheFileName ".pdf" to sFile If (sFile <> "") Begin Send ExportReport C_vrwPDF sFile Get pbCanceled to bCanceled If (not (bCanceled)) Begin Get DownloadURL of ghoWebResourceManager sFile to sUrl If (sUrl <> "") Begin Send Show of oResultsTabPage WebSet psUrl of oViewer to sUrl End End End Send CloseReport sReportId End End_Procedure
We hope that this blog - and the upcoming blogs - help you to create a very succesful business level web application using the 17.1 Web Framework and the Data Access Report Writer.