B4J Question ABMaterial . . . . ABMReport

BigBoss123

Member
Licensed User
Longtime User
I'm struggling to get the ABMReport work correctly.

The code to recreated the report is as follows
B4X:
Sub msbtn4_clicked(Target As String)
    
    myReport.Initialize("myReport", Me, page, ID, ReportCSS, "")
'    'Log("entering Btn4")
    page.CloseModalSheet("fixedsheet")

    tblTrans.Visibility= False
    Report_Build(page, "myReport")
    ' refresh the page
    page.Refresh
    page.FinishedLoading
    ' restoring the navigation bar position
    page.RestoreNavigationBarPosition
    tbl1.clear
    Loadpallets(1)
End Sub

Sub Report_Build(InternalPage As ABMPage, InternalID As String)
    Dim bar As String
    Dim date1 As String
    Dim cat As String
    Dim doc As String
    Dim beg As String
    Dim bal As String
    
    ABMShared.ConnectNavigationBar(page)
    
    ' the report header
    Dim ReportHeader As ABMContainer = myReport.Header.InitializeAsContainer(page, "reportheader", "", ABM.PRINT_PAGEBREAK_INSIDE_AVOID)
    ReportHeader.AddRows(1,False, "border").AddCells12(1,"")
    ReportHeader.AddRows(1,False, "").AddCellsOS(1,0,0,0,9,9,9,"").AddCellsOSMP(1,0,0,0,3,3,3,20,0,0,0,"right")
    ReportHeader.AddRows(1,False, "").AddCellsOS(1,0,0,0,7,7,7,"").AddCellsOS(1,0,0,0,5,5,5,"")
    ReportHeader.BuildGrid
    
    ReportHeader.CellR(0,1).AddComponent(BuildLabel(InternalPage, "repTitle",  "{B} Transactions {/B}", ABM.SIZE_H4, "center", True, ABM.VISIBILITY_ALL))

    ' the report body
    Dim Body As ABMReport
    Body.Initialize("Body", Me, InternalPage, InternalID & "body", "", ABM.PRINT_PAGEBREAK_INSIDE_AVOID)
    ' header of the body
    Body.Header.InitializeAsTexts(Array As String("Row", "Barcode", "Date", "Category  ", "Document",  "Beginning", "Current"), Array As Int(5,10,10,30,25,10,10), Array As String("repheader","repheaderright","repheaderright","repheaderright","repheaderright","repheaderright","repheaderright"), "")
        
    '
    For x = 0 To RSList.Size -1

        Dim tblF As Map = RSList.Get(x)
        bar = tblF.Get("barcode")
        date1 = tblF.Get("dbdate")
        cat =  tblF.Get("category")
        If     tblF.Get("document1") = Null Then
            doc = "N/A"
        Else
            doc =  tblF.Get("document1")
        End If
        beg =  tblF.Get("dbquantity")
        bal =  tblF.Get("dbvalue")

        ' create a text block
        Dim block As ABMReportBlock
        block.InitializeAsTexts(Array As String(x, bar, date1, cat, doc, beg, bal), Array As Int(5,10,10,30,25,10,10), Array As String("repbody","repbodyright","repbodyright","repbodyright", "repbodyright","repbodyright","repbodyright"), "")
        Body.AddBodyBlock(block)
        
    Next
    
    myReport.AddBodySubReport(Body)
    page.refresh
    
End Sub

the app is shown in the following screenshots but when I hit the 'print' button nothing happens.

Any help here would most appreciated.

thanks
 

Attachments

  • Search1.PNG
    Search1.PNG
    42.1 KB · Views: 197
  • Search2.PNG
    Search2.PNG
    50.8 KB · Views: 192
  • Search3.PNG
    Search3.PNG
    113 KB · Views: 195

alwaysbusy

Expert
Licensed User
Longtime User
You have to look at ABMReport as just another ABMComponent.

First, take a look at the Report example in the ABMaterial zip you downloaded.

Basically, what you do is create a new Class (e.g. Report01) where you design the report object (see above example). Then on your page, dim your report, add it to the page (it becomes the 'print preview'):
B4X:
Dim myReport As Report01

' temporary hide the row so the user doesn't sees the report being build
page.Row(2).Visibility = ABM.VISIBILITY_HIDE_ALL
page.Row(2).Refresh

' remove any previously build report
page.Cell(2,1).RemoveAllComponents
page.Cell(2,1).Refresh

' make a new report
myReport.Initialize(page, "myReport")

' Add the report to the page
page.Cell(2,1).AddComponent(myReport.Report)
' refresh so ABM automatically runs Report_Build()
page.Row(2).Refresh

' make the row containing the report visible again
page.Row(2).Visibility = ABM.VISIBILITY_ALL
page.Row(2).Refresh

You can then use Page.PrintPage, which will open the browsers print dialog. It will print every component on the page where .isPrintable is not set to false.

I recently found another way to print a certain div only that may be of some use.
You can add this code in e.g. your print button. It temporary opens a new window with only the report in it and opens up the dialog.
B4X:
' you have to find out what the exact ID is of the the report if it is in a container. Is always lowercase! (in the browser, press F12 - Elements to find it)
Dim TagID as String = "#myreport"

Dim Script As String = $"            
            var divContents = $("${TagID}").html();
            var a = window.open('', '', 'height=500, width=700'); 
            a.document.write('<html>'); 
            a.document.write('<body onafterprint="self.close()">'); 
            a.document.write('<div style="width: 100%;height: 100%;text-align:center;">');
            a.document.write(divContents); 
            a.document.write('</div>');
            a.document.write('</body></html>'); 
            a.document.close();
            a.print();
            "$        
            
Page.ws.eval(Script, Null)
Page.ws.Flush

Alwaysbusy
 
Upvote 0

BigBoss123

Member
Licensed User
Longtime User
Thanks every so much. I had hoped not to create a separate class for each report, but OK I see now how it works.
Will also try the div version as well.
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
I had hoped not to create a separate class for each report
You don't actually have to if you make some generic report. For a client that needed hundreds of reports I wrote one. I can not share it as the code belongs to the client, but here is the general principle.

The generic report has some 'Row Types' defined in Report_Build. For example type 100 = a single text line, type 101 = a single line bold font size 28px, 201 is two text each 50% wide, type 300 is 3 barcodes next to each other, type 500 = 3 images next to each other, etc...

Each report has a json file that has a number of insert SQL queries that fill a temporary table. Each row consists of one of the above row types and the values such a row needs.
B4X:
'type,value1,value2,value3,value4...
101,This is the Title,,,...
201,detail A cell1,cell2,,...
201,detail B cell1,cell2,,...
201,detail C cell1,cell2,,...

In Report_Build, a select SQL query loads all those lines and values from this temporary table for the report. A Select Case than builds the report.
B4X:
Select Case RowType
case 100
     Make and add an ABMReportBlock type 100
case 101
     Make and add an ABMReportBlock type 101
case 201
..
End Select

So to make a new report now, all I have to do is make a new json definition of it without having to write any code.

Alwaysbusy
 
Upvote 0
Top