Android Question Print contents of B4XTable Letter paper in default printer

arana

Member
I have been trying to print a simple list in a letter size page to the default printer, either by converting first to pdf or directly sending from table to printer or
taking snapshot of screen and send it away, I cant seem to understand what I am missing or what I am doing, I already have the table part, just cant send to printer,

for now any method would work to fullfill the schedule :( , I will of course try to make it better but now I have been 2 days trying to no avail.
B4X:
#Region  Project Attributes
    #ApplicationLabel: Shiplists
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

    
#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region
    #FullScreen: False
    #IncludeTitle: True
    
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    Private Done As Button
    Private ShipList As EditText
    Private Tbl1 As B4XTable
    Private xui As XUI
    Dim IME As IME
    Private WebView1 As WebView
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout")
    Tbl1.AddColumn("Item", Tbl1.COLUMN_TYPE_TEXT)
    Tbl1.AddColumn("Qty", Tbl1.COLUMN_TYPE_NUMBERS)
    IME.Initialize("IME")
    IME.HideKeyboard
End Sub

Sub Activity_Resume
    IME.HideKeyboard
End Sub

Sub Activity_Pause (UserClosed As Boolean)
    IME.ShowKeyboard(ShipList)
End Sub


Private Sub Done_Click
    Dim myitems() As String
    Dim l As List
    l.initialize   
    myitems = SplitText(ShipList.text,CRLF)
    'Dim Row() As Object = Array (SplitText(myitems(0),","))
    For n=0 To myitems.length-1
        Dim datoslista() As String
        datoslista = SplitText(myitems(n),",")  'validar si solo queda un elemento, marcara error
        Dim Row() As Object = Array (datoslista(0),datoslista(1))
        'Dim Row() As Object = Array (myitems(0),myitems(1))
        l.Add(Row)
    Next
    Tbl1.SetData(l)

End Sub

Sub SplitText(Text As String,Pattern As String) As String()
   Dim sText() As String
   'sText = Regex.Split(CRLF, Text)
    sText = Regex.Split(Pattern, Text)
   Return sText
End Sub

Private Sub ShipList_EnterPressed
    
    
End Sub

If possible can anyone help me with android printing framework code, it could be html formatting or image output to printer, right now I just want printer to do something. have tried the jfx8 library but that one is apparently for b4j only, I need b4a or a way to call b4j from it.
 

arana

Member
|I saw that one, but couldn't make it work, as well as all the other "see first search result" answers, the problem is those do not provide enough instructions, as to what references to include, or declarations to make.

I get
B4A Version: 10.70
Parsing code. Error
Error parsing program.
Error description: Unknown type: b4xmainpage
Are you missing a library reference?
Error occurred on line: 73 (B4XPages)
Public Sub MainPage As B4XMainPage

I do have XUI, StringUtils checked, I also checked "first result of search", and it does not provide solution to that problem, so I am not closer today that what I was 2 days ago after reading the "first result" help posts.
 
Upvote 0

arana

Member
I dont want to create b4xpages, I was trying to use other code that I got in the search, I already got rid of the b4xpage examples, I just want to make the table data go to the printer by whatever means, but even if I just use the example you provide without any of my code it still does not print anything or gives me any dialog to select printer.


B4X:
#Region  Project Attributes
    #ApplicationLabel: Shiplists
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: Portrait
    #CanInstallToExternalStorage: False
#End Region

    
#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region
    #FullScreen: False
    #IncludeTitle: True
    
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Private rp As RuntimePermissions
    Private xui As XUI
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    Private Root As B4XView 'ignore
    Private xui As XUI 'ignore
    Private Done As Button
    Private ShipList As EditText
    Private Tbl1 As B4XTable
    Dim IME As IME
    Private WebView1 As WebView

End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout")
    Tbl1.AddColumn("Item", Tbl1.COLUMN_TYPE_TEXT)
    Tbl1.AddColumn("Qty", Tbl1.COLUMN_TYPE_NUMBERS)
    IME.Initialize("IME")
    IME.HideKeyboard
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)
    IME.ShowKeyboard(ShipList)
End Sub

Private Sub Done_Click
    Dim myitems() As String
    Dim l As List
    IME.HideKeyboard
    l.initialize
    myitems = SplitText(ShipList.text,CRLF)
    'Dim Row() As Object = Array (SplitText(myitems(0),","))
    For n=0 To myitems.length-1
        Dim datoslista() As String
        datoslista = SplitText(myitems(n),",")  'validar si solo queda un elemento, marcara error
        Dim Row() As Object = Array (datoslista(0),datoslista(1))
        'Dim Row() As Object = Array (myitems(0),myitems(1))
        l.Add(Row)
    Next
    Tbl1.SetData(l)
    rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
    
    MsgboxAsync ("Resultado","")
    Wait For Activity_PermissionResult (Permission As String, Result As Boolean)
    MsgboxAsync (Result,"")
    If Result Then
        PrintPdf
        MsgboxAsync("Hello world", "This is the title")
    End If
    
End Sub


Sub SplitText(Text As String,Pattern As String) As String()
    Dim sText() As String
    'sText = Regex.Split(CRLF, Text)
    sText = Regex.Split(Pattern, Text)
    Return sText
End Sub

Sub PrintPdf
    Dim pdf As PdfDocument
    pdf.Initialize
    pdf.StartPage((611/72) * 300, (765/72) * 300) 'Letter size
    Dim bmp As B4XBitmap = TextToBitmap(200dip, xui.CreateDefaultBoldFont(20), xui.Color_Black, _
     $"s dflkj sdfkls
    dffwje klfj wlkef jwlke fjlwkef jklwe jflkwe jflkwe jflkwe jflkwe jfl
    sdf
    we
    gfkwe lg;kw e;lg wklelg; weg wel;g"$)
    Dim rect As Rect
    rect.Initialize(30, 30, 0, 0)
    rect.Width = bmp.Width / bmp.Scale
    rect.Height = bmp.Height / bmp.Scale
    pdf.Canvas.DrawBitmap(bmp, Null, rect)
    pdf.FinishPage
    Dim out As OutputStream = File.OpenOutput(File.DirRootExternal, "1.pdf", False)
    pdf.WriteToStream(out)
    out.Close
    pdf.Close
    
    'pdf.Canvas.DrawLine(2, 2, 593 , 840, Colors.Blue, 4)
    'pdf.Canvas.DrawText("Hello", 100, 100, Typeface.DEFAULT_BOLD, 30 / GetDeviceLayoutValues.Scale , Colors.Yellow, "CENTER")
    'pdf.FinishPage
    'Dim out As OutputStream = File.OpenOutput(File.DirInternal, "1.pdf", False)
    'pdf.WriteToStream(out)
    'out.Close
    'pdf.Close
End Sub

Sub TextToBitmap (Width As Int, Fnt As B4XFont, Clr As Int, Text As Object) As B4XBitmap
    Dim lbl As Label
    lbl.Initialize("")
    Dim x As B4XView = lbl
    x.Font = Fnt
    x.TextColor = Clr
    x.SetLayoutAnimated(0, 0, 0, Width, 0)
    Dim su As StringUtils
    x.Height = su.MeasureMultilineTextHeight(x, Text)
    x.Text = Text
    Return x.Snapshot
    
End Sub
 
Upvote 0

arana

Member
I have to use multiple lines so I used part from this example

and I got the b4xpages error inserted with it, I now removed it, but still cant make printing work.
this is what I have, I for now am ignoring my data, just want something to print (the generated pdf in your example)
B4X:
#Region  Project Attributes
    #ApplicationLabel: Shiplists
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: Portrait
    #CanInstallToExternalStorage: False
#End Region

    
#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region
    #FullScreen: False
    #IncludeTitle: True
    
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Private rp As RuntimePermissions
    Private xui As XUI
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    Private Root As B4XView 'ignore
    Private xui As XUI 'ignore
    Private Done As Button
    Private ShipList As EditText
    Private Tbl1 As B4XTable
    Dim IME As IME
    Private WebView1 As WebView
    Private printer As Printer

End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout")
    Tbl1.AddColumn("Item", Tbl1.COLUMN_TYPE_TEXT)
    Tbl1.AddColumn("Qty", Tbl1.COLUMN_TYPE_NUMBERS)
    IME.Initialize("IME")
    IME.HideKeyboard
    printer.Initialize("")
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)
    IME.ShowKeyboard(ShipList)
End Sub

Private Sub Done_Click
    Dim myitems() As String
    Dim l As List
    IME.HideKeyboard
    l.initialize
    myitems = SplitText(ShipList.text,CRLF)
    'Dim Row() As Object = Array (SplitText(myitems(0),","))
    For n=0 To myitems.length-1
        Dim datoslista() As String
        datoslista = SplitText(myitems(n),",")  'validar si solo queda un elemento, marcara error
        Dim Row() As Object = Array (datoslista(0),datoslista(1))
        'Dim Row() As Object = Array (myitems(0),myitems(1))
        l.Add(Row)
    Next
    Tbl1.SetData(l)
    rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
    
    MsgboxAsync ("Resultado","")
    Wait For Activity_PermissionResult (Permission As String, Result As Boolean)
    MsgboxAsync (Result,"")
    If Result Then
        PrintPdf
        MsgboxAsync("Hello world", "This is the title")
    End If
    Print
End Sub


Sub SplitText(Text As String,Pattern As String) As String()
    Dim sText() As String
    'sText = Regex.Split(CRLF, Text)
    sText = Regex.Split(Pattern, Text)
    Return sText
End Sub

Sub PrintPdf
    Dim pdf As PdfDocument
    pdf.Initialize
    pdf.StartPage((611/72) * 300, (765/72) * 300) 'Letter size
    Dim bmp As B4XBitmap = TextToBitmap(200dip, xui.CreateDefaultBoldFont(20), xui.Color_Black, _
     $"s dflkj sdfkls
    dffwje klfj wlkef jwlke fjlwkef jklwe jflkwe jflkwe jflkwe jflkwe jfl
    sdf
    we
    gfkwe lg;kw e;lg wklelg; weg wel;g"$)
    Dim rect As Rect
    rect.Initialize(30, 30, 0, 0)
    rect.Width = bmp.Width / bmp.Scale
    rect.Height = bmp.Height / bmp.Scale
    pdf.Canvas.DrawBitmap(bmp, Null, rect)
    pdf.FinishPage
    Dim out As OutputStream = File.OpenOutput(File.DirRootExternal, "1.pdf", False)
    pdf.WriteToStream(out)
    out.Close
    pdf.Close
    
    'pdf.Canvas.DrawLine(2, 2, 593 , 840, Colors.Blue, 4)
    'pdf.Canvas.DrawText("Hello", 100, 100, Typeface.DEFAULT_BOLD, 30 / GetDeviceLayoutValues.Scale , Colors.Yellow, "CENTER")
    'pdf.FinishPage
    'Dim out As OutputStream = File.OpenOutput(File.DirInternal, "1.pdf", False)
    'pdf.WriteToStream(out)
    'out.Close
    'pdf.Close
End Sub

Sub TextToBitmap (Width As Int, Fnt As B4XFont, Clr As Int, Text As Object) As B4XBitmap
    Dim lbl As Label
    lbl.Initialize("")
    Dim x As B4XView = lbl
    x.Font = Fnt
    x.TextColor = Clr
    x.SetLayoutAnimated(0, 0, 0, Width, 0)
    Dim su As StringUtils
    x.Height = su.MeasureMultilineTextHeight(x, Text)
    x.Text = Text
    Return x.Snapshot
    
End Sub

Sub Print
    printer.PrintHtml("job", $"<b>Hello world!!!</b><br/>
<h1>second line</h1>
<img src="${WebViewAssetFile("smiley.png")}"/>"$)
End Sub

Sub WebViewAssetFile (FileName As String) As String
    Dim jo As JavaObject
    jo.InitializeStatic("anywheresoftware.b4a.objects.streams.File")
    If jo.GetField("virtualAssetsFolder") = Null Then
        Return "file:///android_asset/" & FileName.ToLowerCase
    Else
        Return "file://" & File.Combine(jo.GetField("virtualAssetsFolder"), _
  jo.RunMethod("getUnpackedVirtualAssetFile", Array As Object(FileName)))
    End If
End Sub
 
Upvote 0

josejad

Expert
Licensed User
Longtime User
Hi arana:

The problem is that not always there are examples for everything we want to do.
So, the only way is to try little examples for every task, and then try to put it toghether.

It seems you're trying to do something with a B4XTable, in a default project (not a B4XPages project), but you're trying to use B4XPages... (not sure).
We can't try your first code sample just with the code, because we don't know the layout.
It would be better if you upload a small project to test.

Said that:
- Have you tried the code sample in the link Erel has provide? It should work with your printer. Don't worry right now with the table, just try that example
- After that, try to get a image from your table in your code with B4XTable.mBase.Snapshot and try to save it.
- Then, you can try to print that bitmap...
- After that, maybe you can create some code to print the whole table, as you can see, there's no such example... but if you ask the right questions and you get it working, you could share it for the forum¡¡
- Maybe you have checked this post too... just a idea to try the last step
 
Last edited:
Upvote 0

arana

Member
"putting some examples together" ... yes thats what I tried to do, and thats why I endup with b4xpages when I was not trying to., Already removed that part.

" Maybe you have checked this post too... just a idea to try the last step " : that one send you to the same link that Erel Provided, so im just runing in circles, the last link shows how to get data and make table editable, I do not have problem with this, my main problem now is I want to print my data, I did try Erel example, and apparently it creates a pdf, I will then have to take my data into the pdf , I think that will be easier, or just create htmltable and send that to webview, and then snapshot webview and then send to printer, was trying to avoid all that since looking at the examples about printing none of them is doing all that just to be able to print.

right now im getting "java.io.FileNotFoundException: /storage/emulated/0/1.pdf: open failed: EACCES (Permission denied)"
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Nevermind I got it , Thank you both, now i will ask another question regarding printer.printpdf2 (attributes)
Always start a new thread for a new question.

I still cant send to default printer, I want no dialog shown, as this will be an automated process in a production line.
You cannot print with Android built-in print feature without showing this dialog.
 
Upvote 0
Top