B4J Tutorial [ABMaterial]: Sharing the goodness

Mashiane

Expert
Licensed User
Article 1: Generic Excel Importer Class for your ABMUpload component

For my ABMaterial App, I needed a Ms Excel worksheet importer, so I decided to build one.

For this, you will need the Poi libraries, available here..

I have an ABMUpload component in my page, and a combobox to select my template, so when I drop a file there, it gets uploaded to the server and the excel importer code is fired. The ABMCombo is loaded up with the 'Description' column and the 'id' column of my templates table.

My Page_FileUploaded method...

B4X:
Sub Page_FileUploaded(FileName As String, success As Boolean)
    myToastId = myToastId + 1
    If success Then
        page.ShowToast("toast" & myToastId, "toastgreen", "File " & FileName & " uploaded!", 3000)
    Else
        page.ShowToast("toast" & myToastId, "toastred", "File " & FileName & " not uploaded!", 3000)
    End If
    Dim actualFile As String = File.combine(File.DirApp, DownloadFolder & FileName)
    ExcelImportresources(actualFile)
    page.ws.Flush ' IMPORTANT
End Sub
This class assumes that you have a table that stores your template data, i.e. a structure or definition of the stuff you want to import, see figure 1 below:

Figure 1

TemplateTable.png


Usage: Here I want to import Resources to the resources table, from the WB1, starting at row 1 and ending at row 10 of the worksheet. The data should be writtem to the firstname, lastname, dob and jobtitle fields in the table, from column A, B, E and F respectively, but read the column names should they change from the resourcename, surname, dateofbirth, job columns in the templates table.

B4X:
Dim xls As clsExcelmporter
    xls.Initialize("Resources Template","resources","WB1",1,10,True,True)
    xls.SetTemplate("resourcestemplate","wsname","startrow","endrow")
    xls.AddColumn("firstname","resourcename","","A")
    xls.addcolumn("lastname","surname","","B")
    xls.addcolumn("dob","dateofbirth","","E")
    xls.addcolumn("jobtitle","job","","F")
    xls.Build(File.DirApp,"resources.txt")
The output to copy and paste your ABMaterial project will be..

B4X:
Sub ExcelImportresources(xlsFileName As String)
    'get the iym template to use
    Dim cboTemplate As ABMCombo = page.Component("cboTemplate")
    Dim tempID As Int = cboTemplate.GetActiveItemId
    If tempID <= 0 Then
        myToastId = myToastId + 1
        page.ShowToast("toast" & myToastId, "toastred", "The Resources Template should be selected first!", 3000)
        Return
    End If
    If File.Exists("",xlsFileName) = False Then Return
    Dim jsql As SQL = ABMShared.sqlget
    'read the template from file and set the needed properties
    Dim temp As Map = ABMShared.SQLRecordRead(jsql,"resourcestemplate","id",tempID)
    If temp.IsInitialized = False Then
        myToastId = myToastId + 1
        page.ShowToast("toast" & myToastId, "toastred", "The Resources Template could not be read, please correct this!", 3000)
        Return
    End If
    Dim worksheetname As String = temp.GetDefault("wsname","WB1")
    Dim startrow As Long = temp.GetDefault("startrow",1)
    startrow = startrow - 1
Dim endrow As Long = temp.GetDefault("endrow",10)
'start processing the workbook
    Dim wb As PoiWorkbook
    'initialize an existing workbook
    wb.InitializeExisting("",xlsFileName,"")
    'get the worksheet names
    Dim wsl As List = wb.GetSheetNames
    'find the summary work sheet position
    Dim summaryPos As Int = wsl.IndexOf(worksheetname)
    If summaryPos = -1 Then Return
    'get the workbook
    Dim wSheet As PoiSheet = wb.GetSheet(summaryPos)
    Dim rCnt As Long
    Dim Records as List
    Records.initialize
'Get the row positions for the fields
'Get the column names (A-Z) for the fields
Dim resourcenameCol As String = temp.GetDefault("resourcename","A")
Dim surnameCol As String = temp.GetDefault("surname","B")
Dim dateofbirthCol As String = temp.GetDefault("dateofbirth","E")
Dim jobCol As String = temp.GetDefault("job","F")
'Get the column positions (1..n) for the fields
Dim resourcenameColPos As Int = ABMShared.GetColumnPos(resourcenameCol)
Dim surnameColPos As Int = ABMShared.GetColumnPos(surnameCol)
Dim dateofbirthColPos As Int = ABMShared.GetColumnPos(dateofbirthCol)
Dim jobColPos As Int = ABMShared.GetColumnPos(jobCol)
For rowCnt = startrow To endrow
Dim resourcename As String = ABMShared.GetRowCellValue(wSheet,rowCnt, resourcenameCol)
Dim surname As String = ABMShared.GetRowCellValue(wSheet,rowCnt, surnameCol)
Dim dateofbirth As String = ABMShared.GetRowCellValue(wSheet,rowCnt, dateofbirthCol)
Dim job As String = ABMShared.GetRowCellValue(wSheet,rowCnt, jobCol)
'Create map To hold the record To add
Dim record As Map
        record.initialize
record.put("firstname",resourcename)
record.put("lastname",surname)
record.put("dob",dateofbirth)
record.put("jobtitle",job)
Records.Add(record)
        Next
'Add all records to the table
ABMShared.SQLRecordInsertMaps(jSQL,"resources",Records)
    ABMShared.SQLClose(jsql)
    myToastId = myToastId + 1
    page.ShowToast("toast" & myToastId, "toastgreen", "Resources Template data imported successfully!", 3000)
End Sub
The additional methods on my ABMShared...

B4X:
Sub PoiCellReturn(cell As PoiCell) As String
    If cell.IsInitialized = True Then
        Select Case cell.CellType
        Case cell.TYPE_NUMERIC
            Return cell.ValueNumeric
        Case cell.TYPE_STRING
            Return cell.ValueString
        Case cell.TYPE_FORMULA
            Return cell.ValueFormula
        Case cell.TYPE_BLANK
            Return ""
        Case cell.TYPE_BOOLEAN
            Return cell.ValueBoolean
        Case cell.TYPE_ERROR
            Return ""
        Case Else
            Return cell.Value
        End Select
    Else
        Return ""
    End If
End Sub
'return the column position
Sub GetColumnPos(colAlpha As String) As Int
    Select Case colAlpha.tolowercase
    Case "a"
        Return 1
    Case "b"
        Return 2
    Case "c"
        Return 3
    Case "d"
        Return 4
    Case "e"
        Return 5
    Case "f"
        Return 6
    Case "g"
        Return 7
    Case "h"
        Return 8
    Case "i"
        Return 9
    Case "j"
        Return 10
    Case "k"
        Return 11
    Case "l"
        Return 12
    Case "m"
        Return 13
    Case "n"
        Return 14
    Case "o"
        Return 15
    Case "p"
        Return 16
    Case "q"
        Return 17
    Case "r"
        Return 18
    Case "s"
        Return 19
    Case "t"
        Return 20
    Case "u"
        Return 21
    Case "v"
        Return 22
    Case "w"
        Return 23
    Case "x"
        Return 24
    Case "y"
        Return 25
    Case "z"
        Return 26
    Case "aa"
        Return 27
    Case "ab"
        Return 28
    Case "ac"
        Return 29
    Case "ad"
        Return 30
    Case "ae"
        Return 31
    Case "af"
        Return 32
    Case "ag"
        Return 33
    Case "ah"
        Return 34
    Case "ai"
        Return 35
    Case "aj"
        Return 36
    Case "ak"
        Return 37
    Case "al"
        Return 38
    Case "am"
        Return 39
    Case "an"
        Return 40
    Case "ao"
        Return 41
    Case "ap"
        Return 42
    Case "aq"
        Return 43
    Case "ar"
        Return 44
    Case "as"
        Return 45
    Case "at"
        Return 46
    Case "au"
        Return 47
    Case "av"
        Return 48
    Case "aw"
        Return 49
    Case "ax"
        Return 50
    Case "ay"
        Return 51
    Case "az"
        Return 52
    End Select
End Sub
Sub GetRowCellValue(ws As PoiSheet, rowpos As Int, colAlpha As String) As String
    Dim cell As PoiCell = GetPoiCell(ws,rowpos,colAlpha)
    Return PoiCellReturn(cell)
End Sub
Sub GetPoiCell(ws As PoiSheet, rowPos As Int, colAlpha As String) As PoiCell
    Try
        Dim rowP As Int = rowPos - 1
        Dim colP As Int = 0
        If IsNumber(colAlpha) = False Then
            colP = GetColumnPos(colAlpha) - 1
        Else
            colP = colAlpha -1
        End If
        Dim row As PoiRow = ws.GetRow(rowP)
        row.IsInitialized
        Dim cell As PoiCell = row.GetCell(colP)
        cell.IsInitialized
        Return cell
    Catch
        Return Null
    End Try
End Sub
B4X:
Sub GetPoiCellValue(row As PoiRow, colAlpha As String) As String
    Dim cell As PoiCell = GetPoiRowPoiCell(row,colAlpha)
    Return PoiCellReturn(cell)
End Sub
Sub GetPoiRow(ws As PoiSheet, rowPos As Int) As PoiRow
    Try
        Dim rowP As Int = rowPos - 1
        Dim row As PoiRow = ws.GetRow(rowP)
        row.IsInitialized
        Return row
    Catch
        Return Null
    End Try
End Sub
Sub GetPoiRowPoiCell(row As PoiRow, colAlpha As String) As PoiCell
    Try
        Dim colP As Int = 0
        If IsNumber(colAlpha) = False Then
            colP = GetColumnPos(colAlpha) - 1
        Else
            colP = colAlpha -1
        End If
        Dim cell As PoiCell = row.GetCell(colP)
        cell.IsInitialized
        Return cell
    Catch
        Return Null
    End Try
End Sub
Ta: Enjoy...
 

Attachments

Mashiane

Expert
Licensed User
Article 2: Overwriting files uploaded with ABMUpload.

By just tweaking the Handle method of the ABMUploadHandler class, the files that you upload to your server can be overwritten. I had to do this for my app as each time I copied a file it said "Not Uploaded". This was achieved by checking if the file exists and then deleting it.

B4X:
Sub Handle(req As ServletRequest, resp As ServletResponse)
    'get the callback page from the session (multiple modules can use this handler)
    Dim callback As Object = req.GetSession.GetAttribute("abmcallback")
    Dim downloadfolder As String = File.Combine(File.DirApp, req.GetSession.GetAttribute("abmdownloadfolder"))
    Dim MaxSize As Int
    Try
        MaxSize = req.GetSession.GetAttribute("abmmaxsize")
    Catch
        resp.SendError(500, LastException.Message)
        Return
    End Try
    Dim data As Map
    Dim fileName As String
    Dim tmpFileName As String
    Try
        data = req.GetMultipartData(downloadfolder, MaxSize)
        Dim filePart As Part = data.Get("upl")
        If filePart.IsInitialized Then
            fileName =     filePart.SubmittedFilename
            tmpFileName = filePart.TempFile
            If File.Exists(downloadfolder,fileName) = True Then
                File.Delete(downloadfolder,fileName)
            End If
            If ABM.HandleUpload(downloadfolder, tmpFileName, fileName) Then
                If SubExists(callback, "Page_FileUploaded") Then
                    CallSubDelayed3(callback, "Page_FileUploaded", fileName, True)
                End If
            Else
                resp.SendError(500, "Error")
                'If SubExists(callback, "Page_FileUploaded") Then
                '    CallSubDelayed3(callback, "Page_FileUploaded", fileName, False)
                'End If
            End If
        Else ' try image
            Dim filePart As Part = data.Get("imageFromCanvas")
            fileName = filePart.SubmittedFilename
            tmpFileName = filePart.TempFile
            If File.Exists(downloadfolder,fileName) = True Then
                File.Delete(downloadfolder,fileName)
            End If
            If ABM.HandleUpload(downloadfolder, tmpFileName, fileName) Then
                If SubExists(callback, "Page_FileUploaded") Then
                    CallSubDelayed3(callback, "Page_FileUploaded", fileName, True)
                End If
            Else
                If SubExists(callback, "Page_FileUploaded") Then
                    CallSubDelayed3(callback, "Page_FileUploaded", fileName, False)
                End If
            End If
        End If
    Catch
        resp.SendError(500, LastException.Message)
        If SubExists(callback, "Page_FileUploaded") Then
            CallSubDelayed3(callback, "Page_FileUploaded", LastException.Message , False)
        End If
    End Try
End Sub
 

Mashiane

Expert
Licensed User
'Description: extract all elements in a page. Able to view ids and properies and styles etc.
'Tag: loop through page elements...

B4X:
Sub ABMGetElements(page As ABMPage)
    Dim s As String = $"var elems = document.body.getElementsByTagName("*");
    ret=new Array();
    for (var i=0, max=elems.length; i < max; i++) {
     // Do something with the element here
     ret.push(elems[i]);
    }
    console.log(ret);"$
    page.ws.Eval(s,Null)   
End Sub
This writes code to your internet explorer console.
 

Harris

Expert
Licensed User
Article 2: Overwriting files uploaded with ABMUpload.

By just tweaking the Handle method of the ABMUploadHandler class, the files that you upload to your server can be overwritten. I had to do this for my app as each time I copied a file it said "Not Uploaded". This was achieved by checking if the file exists and then deleting it.

B4X:
Sub Handle(req As ServletRequest, resp As ServletResponse)
    'get the callback page from the session (multiple modules can use this handler)
    Dim callback As Object = req.GetSession.GetAttribute("abmcallback")
    Dim downloadfolder As String = File.Combine(File.DirApp, req.GetSession.GetAttribute("abmdownloadfolder"))
    Dim MaxSize As Int
    Try
        MaxSize = req.GetSession.GetAttribute("abmmaxsize")
    Catch
        resp.SendError(500, LastException.Message)
        Return
    End Try
    Dim data As Map
    Dim fileName As String
    Dim tmpFileName As String
    Try
        data = req.GetMultipartData(downloadfolder, MaxSize)
        Dim filePart As Part = data.Get("upl")
        If filePart.IsInitialized Then
            fileName =     filePart.SubmittedFilename
            tmpFileName = filePart.TempFile
            If File.Exists(downloadfolder,fileName) = True Then
                File.Delete(downloadfolder,fileName)
            End If
            If ABM.HandleUpload(downloadfolder, tmpFileName, fileName) Then
                If SubExists(callback, "Page_FileUploaded") Then
                    CallSubDelayed3(callback, "Page_FileUploaded", fileName, True)
                End If
            Else
                resp.SendError(500, "Error")
                'If SubExists(callback, "Page_FileUploaded") Then
                '    CallSubDelayed3(callback, "Page_FileUploaded", fileName, False)
                'End If
            End If
        Else ' try image
            Dim filePart As Part = data.Get("imageFromCanvas")
            fileName = filePart.SubmittedFilename
            tmpFileName = filePart.TempFile
            If File.Exists(downloadfolder,fileName) = True Then
                File.Delete(downloadfolder,fileName)
            End If
            If ABM.HandleUpload(downloadfolder, tmpFileName, fileName) Then
                If SubExists(callback, "Page_FileUploaded") Then
                    CallSubDelayed3(callback, "Page_FileUploaded", fileName, True)
                End If
            Else
                If SubExists(callback, "Page_FileUploaded") Then
                    CallSubDelayed3(callback, "Page_FileUploaded", fileName, False)
                End If
            End If
        End If
    Catch
        resp.SendError(500, LastException.Message)
        If SubExists(callback, "Page_FileUploaded") Then
            CallSubDelayed3(callback, "Page_FileUploaded", LastException.Message , False)
        End If
    End Try
End Sub

That's funny, I tried the same thing - using same code.
If the file exists in the download folder (which I create for each new client) - delete it. Then download the new copy.
It would often give me (File Not Downloaded). I think server still showed file existed prior to deletion completion.
I think a better option would be Alert (msgbox2) - File name already exists - Overwrite? (yes, no)? Delete file, and callback success to add new file.

OR - simply overwrite existing file with no warning (which it won't do currently).
The existing file (name) may be a PDF with a phone number change. In a current session, it won't overwrite.
Create a new session (next day after log out), and it seems to replace existing file just fine?

Thanks
 

Mashiane

Expert
Licensed User
Setting, Getting Text and HTML in ABMaterial components... i.e. JQueryElement

B4X:
'Description, get the text value of a component.
Tag: ABMaterial, getText, JQueryElement
public Sub GetText(page As ABMPage, id As String) As String
    Try
        id = id.tolowercase
        Dim jqe As JQueryElement = page.ws.GetElementById(id)
        Return jqe.GetText.value
    Catch
        Return ""
    End Try
End Sub

'Description: Set the text of a component
'Tag: ABMaterial, text, set, JQueryElement
public Sub SetText(page As ABMPage, id As String, value As String)
    Try
        id = id.tolowercase
        Dim jqe As JQueryElement = page.ws.GetElementById(id)
        jqe.SetText(value)
    Catch
    End Try
End Sub

'Description: Get the html value of a component
'Tag: ABMaterial, JQueryElement, get HTML
public Sub GetHTML(page As ABMPage, id As String) As String
    Try
        id = id.tolowercase
        Dim jqe As JQueryElement = page.ws.GetElementById(id)
        Return jqe.GetHtml.value
    Catch
        Return ""
    End Try
End Sub

'Description: Set the html value of a component
'Tag: ABMaterial, setHTML, jQueryElement
public Sub SetHTML(page As ABMPage, id As String, value As String)
    Try
        id = id.tolowercase
        Dim jqe As JQueryElement = page.ws.GetElementById(id)
        jqe.SetHtml(value)
    Catch
    End Try
End Sub
 

Mashiane

Expert
Licensed User
So I keep misplacing this code... copy files from File.DirAssets to Target folder

B4X:
'Description: Found in the forum
Sub WebViewAssetFile (FileName As String) As String
   #if B4J
    Return File.GetUri(File.DirAssets, FileName)
   #Else If B4A
     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
   #Else If B4i
     Return $"file://${File.Combine(File.DirAssets, FileName)}"$
   #End If
End Sub
B4X:
Description: Copy file from assets folder to target folder
'Tag: File.DirAssets, CopyFile
Public Sub File_CopyFileFromAssets(FileName As String,TargetDir As String) As Boolean
    Dim Inp As InputStream = File.OpenInput(File.DirAssets, FileName)
    Dim outp As OutputStream = File.OpenOutput(TargetDir, FileName, False)
    File.Copy2(Inp, outp)
    outp.Close
    Inp.close
    Return File.Exists(TargetDir,FileName)
End Sub
Usage

B4X:
If WebViewAssetFile("xxx.me") <> "" then
File_CopyFileFromAssets("xxx.me",File.DirApp)
end If
 

Mashiane

Expert
Licensed User
This is a small snippet show add text and an image for KPI on a table...

KPIs.png


Define your theme...

B4X:
MyTheme.AddCellTheme("centercontent")
    MyTheme.Cell("centercontent").align = ABM.CELL_ALIGN_CENTER
    
    MyTheme.AddCellTheme("rightcontent")
    MyTheme.Cell("rightcontent").align = ABM.CELL_ALIGN_RIGHT
These can be put on ABMShared

B4X:
public Sub ABMImageBuild(page As ABMPage,id As String,imgPath As String,opacity As Double,bResponsive As Boolean,bMaterialBoxed As Boolean,sCaption As String, sAlt As String, bCircular As Boolean, bClickable As Boolean,bFixed As String, sWidth As String, sHeight As String) As ABMImage
    Dim img As ABMImage
    img.Initialize(page, id, imgPath & "?" & DateTime.Now, opacity)
    img.IsResponsive = bResponsive
    img.IsMaterialBoxed = bMaterialBoxed
    img.Caption = sCaption
    img.Alt = sAlt
    img.IsCircular = bCircular
    img.IsClickable = bClickable
    If bFixed = "1" Or bFixed = True Then
        img.SetFixedSize(sWidth,sHeight)
    End If
    Return img
End Sub

Sub ABMTextImageRight(page As ABMPage, id As String, text As String, img As String,bFixed As Boolean,iWidth As String,iHeight As String) As ABMContainer
    Dim ItemCont As ABMContainer
    ItemCont.Initialize(page, id, "")
    ItemCont.AddRowsM(1,False,0,0, "").AddCellsOSMP(1,0,0,0,10,10,10,0,0,0,10,"rightcontent").AddCellsOSMP(1,0,0,0,2,2,2,10,0,5,5,"centercontent")
    ItemCont.BuildGrid 'IMPORTANT once you loaded the complete grid AND before you start adding components
    Dim lbl As ABMLabel
    lbl.Initialize(page, id & "lbl", text, ABM.SIZE_PARAGRAPH, False, "")
    ItemCont.Cell(1,1).AddComponent(lbl)
    Dim badge As ABMImage = ABMImageBuild(page,id & "img",img,1,False,False,"","",False,False,bFixed,iWidth,iHeight)
    ItemCont.Cell(1,2).AddComponent(badge)
    Return ItemCont
End Sub
Then when adding rows to your ABMTable , retrieve the contents from the db, on the db I have a URL link to the kpi to use on my RAG scale (Red, Amber, Green)

B4X:
Dim percentageexpenditure As String = resMap.GetDefault("percentageexpenditure", "0")
        Dim budgetimage As String = resMap.GetDefault("budgetimage","../images/gray.png")
        If percentageexpenditure = "" Then
            rCellValues.Add("{NBSP}")
        Else
            '*** Start output format
            percentageexpenditure = ABMShared.percentage(percentageexpenditure)
            Dim abmc As ABMContainer = ABMShared.ABMTextImageRight(page,id,percentageexpenditure,budgetimage,True,32,32)
            '*** End output format
            rCellValues.Add(abmc)
        End If
 

Mashiane

Expert
Licensed User
Description: Creating self referencing AutoComplete text fields.

In my people page, at times the entries will have the same company name, job title or project role. I did not want to create lists for these and thought of having the list of auto complete text fields generated from whatever has been saved on the same table.

When the modal sheet opens, it gets cleared. This also loads the current existing records for the named auto complete text fields in the table. This code snippet shows how I have achieved this easily. I have defined variables for each of the input fields as their source content might change.

B4X:
Sub msgenpeopleClear()
    'Get connection from current pool if MySQL/MSSQL
    Dim jSQL As SQL = ABMShared.SQLGet
    Dim rsTot As Int
    Dim rsCnt As Int
    Dim results As List
    Dim msgenpeople As ABMModalSheet
    msgenpeople = page.ModalSheet("msgenpeople")
    Dim imgprofileimg As ABMImage = msgenpeople.Content.Component("imgprofileimg")
    Dim fileinpprofileupl As ABMFileInput = msgenpeople.Content.Component("fileinpprofileupl")
    Dim txtfullname As ABMInput = msgenpeople.Content.Component("txtfullname")
    Dim txtinstitution As ABMInput = msgenpeople.Content.Component("txtinstitution")
    Dim txtjobtitle As ABMInput = msgenpeople.Content.Component("txtjobtitle")
    Dim txtprojectrole As ABMInput = msgenpeople.Content.Component("txtprojectrole")
    Dim txtemailaddress As ABMInput = msgenpeople.Content.Component("txtemailaddress")
    Dim txtmobilephone As ABMInput = msgenpeople.Content.Component("txtmobilephone")
    imgprofileimg.Source =  "../images/User_96px.png" & "?" & DateTime.Now
    imgprofileimg.Refresh
    fileinpprofileupl.Clear
    fileinpprofileupl.Refresh
    Dim txtfullnameContents As String
    txtfullnameContents = ""
    txtfullname.Text = txtfullnameContents
    txtfullname.Refresh
    Dim txtinstitutionContents As String
    txtinstitutionContents = ""
    txtinstitution.ClearAutoComplete
    results = ABMShared.SQLExecuteMaps(jSQL, "select distinct institution from people order by institution", Null)
    'Loop throught each record read and process it
    rsTot = results.size - 1
    For rsCnt = 0 To rsTot
        'Get each record to process as a map
        Dim resMap As Map = results.get(rsCnt)
        Dim sinstitution As String = resMap.GetDefault("institution","")
        txtinstitution.AddAutoComplete(sinstitution,sinstitution)
    Next
    txtinstitution.Text = txtinstitutionContents
    txtinstitution.Refresh
    Dim txtjobtitleContents As String
    txtjobtitleContents = ""
    txtjobtitle.ClearAutoComplete
    results = ABMShared.SQLExecuteMaps(jSQL, "select distinct jobtitle from people order by jobtitle", Null)
    'Loop throught each record read and process it
    rsTot = results.size - 1
    For rsCnt = 0 To rsTot
        'Get each record to process as a map
        Dim resMap As Map = results.get(rsCnt)
        Dim sjobtitle As String = resMap.GetDefault("jobtitle","")
        txtjobtitle.AddAutoComplete(sjobtitle,sjobtitle)
    Next
    txtjobtitle.Text = txtjobtitleContents
    txtjobtitle.Refresh
    Dim txtprojectroleContents As String
    txtprojectroleContents = ""
    txtprojectrole.ClearAutoComplete
    results = ABMShared.SQLExecuteMaps(jSQL, "select distinct projectrole from people order by projectrole", Null)
    'Loop throught each record read and process it
    rsTot = results.size - 1
    For rsCnt = 0 To rsTot
        'Get each record to process as a map
        Dim resMap As Map = results.get(rsCnt)
        Dim sprojectrole As String = resMap.GetDefault("projectrole","")
        txtprojectrole.AddAutoComplete(sprojectrole,sprojectrole)
    Next
    txtprojectrole.Text = txtprojectroleContents
    txtprojectrole.Refresh
    Dim txtemailaddressContents As String
    txtemailaddressContents = ""
    txtemailaddress.Text = txtemailaddressContents
    txtemailaddress.Refresh
    Dim txtmobilephoneContents As String
    txtmobilephoneContents = ""
    txtmobilephone.Text = txtmobilephoneContents
    txtmobilephone.Refresh
    'Close the connection to the database
    ABMShared.SQLClose(jSQL)
End Sub
 

Mashiane

Expert
Licensed User
Handling different ABMFileInput controls.

13Approval1.png


I have about 5 ABMInput controls, each time one is clicked, I need to determine with one was clicked to upload a file and then upload the file and then update a particular text field.

1. For each ABMInput_Change event, note that these are in the same modal sheet.

B4X:
Sub fileinpimportbusinesscase_Changed(value As String)
    'Save the current active component in case there are multiple components
    ABMShared.SessionStorageSave(page, "fileinput", "fileinpimportbusinesscase")
    Dim msgenprojects As ABMModalSheet
    msgenprojects = page.ModalSheet("msgenprojects")
    Dim fileinpimportbusinesscase As ABMFileInput = msgenprojects.Content.Component("fileinpimportbusinesscase")
    fileinpimportbusinesscase.UploadToServer 'Here the file is uploading
End Sub
B4X:
Sub fileinpimportcommunitylist_Changed(value As String)
    'Save the current active component in case there are multiple components
    ABMShared.SessionStorageSave(page, "fileinput", "fileinpimportcommunitylist")
    Dim msgenprojects As ABMModalSheet
    msgenprojects = page.ModalSheet("msgenprojects")
    Dim fileinpimportcommunitylist As ABMFileInput = msgenprojects.Content.Component("fileinpimportcommunitylist")
    fileinpimportcommunitylist.UploadToServer 'Here the file is uploading
End Sub
B4X:
Sub fileinpimportletterofapproval_Changed(value As String)
    'Save the current active component in case there are multiple components
    ABMShared.SessionStorageSave(page, "fileinput", "fileinpimportletterofapproval")
    Dim msgenprojects As ABMModalSheet
    msgenprojects = page.ModalSheet("msgenprojects")
    Dim fileinpimportletterofapproval As ABMFileInput = msgenprojects.Content.Component("fileinpimportletterofapproval")
    fileinpimportletterofapproval.UploadToServer 'Here the file is uploading
End Sub
B4X:
Sub fileinpimportprojectplan_Changed(value As String)
    'Save the current active component in case there are multiple components
    ABMShared.SessionStorageSave(page, "fileinput", "fileinpimportprojectplan")
    Dim msgenprojects As ABMModalSheet
    msgenprojects = page.ModalSheet("msgenprojects")
    Dim fileinpimportprojectplan As ABMFileInput = msgenprojects.Content.Component("fileinpimportprojectplan")
    fileinpimportprojectplan.UploadToServer 'Here the file is uploading
End Sub
B4X:
Sub fileinpimportrejectionletter_Changed(value As String)
    'Save the current active component in case there are multiple components
    ABMShared.SessionStorageSave(page, "fileinput", "fileinpimportrejectionletter")
    Dim msgenprojects As ABMModalSheet
    msgenprojects = page.ModalSheet("msgenprojects")
    Dim fileinpimportrejectionletter As ABMFileInput = msgenprojects.Content.Component("fileinpimportrejectionletter")
    fileinpimportrejectionletter.UploadToServer 'Here the file is uploading
End Sub
What I do is to save the "fileinput" variable with the component id to the session. Then on Page_FileUpload I read this session variable to determine which control was last used...

B4X:
Sub Page_FileUploaded(FileName As String, success As Boolean)
    If success Then
        ABMShared.Inform(page,"File " & FileName & " uploaded!")
        uploads = uploads + 1
    Else
        ABMShared.Warn(page,"File " & FileName & " not uploaded!")
        page.ws.Flush
        return
    End If
    Dim actualFile As String = File.combine(File.DirApp, DownloadFolder & FileName)
    dim serverFile As String = ServerFolder & filename
    page.ws.Flush ' IMPORTANT
    Dim whichFile As String = ABMShared.SessionStorageRead(page, "fileinput")
    If whichFile = "fileinpimportletterofapproval" Then
        Dim msgenprojects As ABMModalSheet
        msgenprojects = page.ModalSheet("msgenprojects")
        Dim fileinpimportletterofapproval As ABMFileInput = msgenprojects.Content.Component("fileinpimportletterofapproval")
        fileinpimportletterofapproval.Clear
    End If
    If whichFile = "fileinpimportbusinesscase" Then
        Dim msgenprojects As ABMModalSheet
        msgenprojects = page.ModalSheet("msgenprojects")
        Dim fileinpimportbusinesscase As ABMFileInput = msgenprojects.Content.Component("fileinpimportbusinesscase")
        fileinpimportbusinesscase.Clear
    End If
    If whichFile = "fileinpimportprojectplan" Then
        Dim msgenprojects As ABMModalSheet
        msgenprojects = page.ModalSheet("msgenprojects")
        Dim fileinpimportprojectplan As ABMFileInput = msgenprojects.Content.Component("fileinpimportprojectplan")
        fileinpimportprojectplan.Clear
    End If
    If whichFile = "fileinpimportcommunitylist" Then
        Dim msgenprojects As ABMModalSheet
        msgenprojects = page.ModalSheet("msgenprojects")
        Dim fileinpimportcommunitylist As ABMFileInput = msgenprojects.Content.Component("fileinpimportcommunitylist")
        fileinpimportcommunitylist.Clear
    End If
    If whichFile = "fileinpimportrejectionletter" Then
        Dim msgenprojects As ABMModalSheet
        msgenprojects = page.ModalSheet("msgenprojects")
        Dim fileinpimportrejectionletter As ABMFileInput = msgenprojects.Content.Component("fileinpimportrejectionletter")
        fileinpimportrejectionletter.Clear
    End If
End Sub
Now I will just add code to update the respective text controls for each time a file is uploaded. Cool
 

Mashiane

Expert
Licensed User
If you click the ABMInput button and upload the same file, it does not work on subsequent calls.

Calling this method and passing the "initialize" variable name of the control just after you call a .Clear of the control enables this to work..

B4X:
'clear the file input control
Sub FileInputClear(page As ABMPage, id As String)
    Dim xKey As String = $"${id}buttoninput"$
    Dim script As String = $"var ${id}files = document.getElementById('${xKey}');
    ${id}files.value=null;"$
    page.ws.Eval(script, Array As String(xKey))
End Sub
 

Mashiane

Expert
Licensed User
Ola

You probably already have these functions somewhere and I know you will understand what they mean and do... anyway here is my implementation

B4X:
Sub ABMSetBold(value As String) As String
    Dim sb As StringBuilder
    sb.Initialize
    sb.Append("{B}").Append(value).Append("{/B}")
    Return sb.tostring
End Sub

Sub ABMSetItalic(value As String) As String
    Dim sb As StringBuilder
    sb.Initialize
    sb.Append("{I}").Append(value).Append("{/I}")
    Return sb.tostring
End Sub

Sub ABMSetUnderline(value As String) As String
    Dim sb As StringBuilder
    sb.Initialize
    sb.Append("{U}").Append(value).Append("{/U}")
    Return sb.tostring
End Sub

Sub ABMSetSubScript(value As String) As String
    Dim sb As StringBuilder
    sb.Initialize
    sb.Append("{SUB}").Append(value).Append("{/SUB}")
    Return sb.tostring
End Sub

Sub ABMSetSuperScript(value As String) As String
    Dim sb As StringBuilder
    sb.Initialize
    sb.Append("{SUP}").Append(value).Append("{/SUP}")
    Return sb.tostring
End Sub

Sub ABMSetCode(value As String) As String
    Dim sb As StringBuilder
    sb.Initialize
    sb.Append("{CODE}").Append(value).Append("{/CODE}")
    Return sb.tostring
End Sub

Sub ABMSetColor(value As String,HexColor As String) As String
    Dim sb As StringBuilder
    sb.Initialize
    sb.Append($"{C:${HexColor}}${value}{/C}"$)
    Return sb.tostring
End Sub

Sub ABMSetColorIntensity(value As String,Color As String,Intensity As String) As String
    'convert color + intensity to hex
    Dim hexValue As String = ABM.ABMColorToHex(Color, Intensity)
    Dim sb As StringBuilder
    sb.Initialize
    sb.Append($"{C:${hexValue}}${value}{/C}"$)
    Return sb.tostring
End Sub

Sub ABMSetIconColorIntensity(icon As String,Color As String,Intensity As String) As String
    'convert color + intensity to hex
    Dim hexValue As String = ABM.ABMColorToHex(Color, Intensity)
    Dim sb As StringBuilder
    sb.Initialize
    sb.Append($"{IC:${hexValue}}${icon}{/IC}"$)
    Return sb.tostring
End Sub

Sub ABMSetIconColor(icon As String,HexColor As String) As String
    Dim sb As StringBuilder
    sb.Initialize
    sb.Append($"{IC:${HexColor}}${icon}{/IC}"$)
    Return sb.tostring
End Sub

Sub ABMSetStyle(CSS As String) As String
    Dim sb As StringBuilder
    sb.Initialize
    sb.Append("{ST:").Append(CSS).Append("{/ST}")
    Return sb.tostring
End Sub

Hey, check MashCSS on how you can build your css quickly

Sub ABMSetBreak(value) As String
    Dim sb As StringBuilder
    sb.Initialize
    sb.Append(value).Append("{BR}")
    Return sb.tostring
End Sub

Sub ABMSetWideBreak(value) As String
    Dim sb As StringBuilder
    sb.Initialize
    sb.Append(value).Append("{WBR}")
    Return sb.tostring
End Sub

Sub ABMSetSpace(value) As String
    Dim sb As StringBuilder
    sb.Initialize
    sb.Append(value).Append("{NBSP}")
    Return sb.tostring
End Sub

Sub ABMSetHyperLink(Title As String, URL As String) As String
    Dim sb As StringBuilder
    sb.Initialize
    sb.Append($"{AL}${URL}{AT}${Title}{/AL}"$)
    Return sb.tostring
End Sub
 
Top