Android Question Cannot xTableMicro get for 2 columns [SOLVED]

AHilberink

Active Member
Licensed User
Longtime User
Hi,

I use code of Klaus for my table function:
B4X:
'xTableMini CustomView

'This is a mini version of the xTablelite customview which is the lite version of the xTable customview

'Version 0.98 2022.12.18

' these Event lines are useful for a library compilation for the IDE autocompletion
#Event: Touch(X As Int, Y As Int)
' these RaisesSynchronousEvents lines are useful for a library compilation
#RaisesSynchronousEvents: Touch(X As Int, Y As Int)

#DesignerProperty: Key: NumberOfColumns, DisplayName: Number of columns, FieldType: Int, DefaultValue: 3, Description: Number of columns.
#DesignerProperty: Key: RowHeight, DisplayName: Row height, FieldType: Int, DefaultValue: 40, Description: Row height.
#DesignerProperty: Key: LineWidth, DisplayName: LineWidth, FieldType: Int, DefaultValue: 1, MinRange: 1, MaxRange: 10, Description: Line width in dips.
#DesignerProperty: Key: TextSize, DisplayName: Text size, FieldType: Int, DefaultValue: 14, Description: Text size.
#DesignerProperty: Key: TextAlignmentH, DisplayName: TextAlignmentH, FieldType: String, DefaultValue: CENTER, List: LEFT|CENTER|RIGHT, Description: Set the horizontal text horizontal alignment.
#DesignerProperty: Key: TextAlignmentV, DisplayName: TextAlignmentV, FieldType: String, DefaultValue: CENTER, List: TOP|CENTER|BOTTOM, Description: Set the vertical text alignment.
#DesignerProperty: Key: HeaderColor, DisplayName: Header color, FieldType: Color, DefaultValue: 0xFF808080, Description: Header background color.
#DesignerProperty: Key: HeaderTextColor, DisplayName: Header text color, FieldType: Color, DefaultValue: 0xFFFFFFFF, Description: Table background color.
#DesignerProperty: Key: TableColor, DisplayName: Table color, FieldType: Color, DefaultValue: 0xFFD3D3D3, Description: Table background color.
#DesignerProperty: Key:    CellTextColor, DisplayName: Cell text color, FieldType: Color, DefaultValue: 0xFF000000, Description: Table background color.
#DesignerProperty: Key:    Row1Color, DisplayName: Row 1 color, FieldType: Color, DefaultValue: 0xFFFFFFFF, Description: Row1 background color.
#DesignerProperty: Key:    Row2Color, DisplayName: Row 2 color, FieldType: Color, DefaultValue: 0xFF98F5FF, Description: Row2 background color.

Sub Class_Globals
    Private mEventName As String 'ignore
    Private mCallBack As Object 'ignore
    Public mBase As B4XView
    Private xui As XUI 'ignore
    Public Tag As Object
    Public HeaderNames As List
    Public Data As List
    Private mNumberOfColumns, ColumnWidths() As Int
    Public RowHeight, HeaderColor, TableColor, TextColor, HeaderTextColor As Int
    Public TextSize As Float
    Private mAlignmentH As String
    Private mAlignmentV As String
    Private mAlignmentsH() As String
    Private mAlignmentsV() As String
    Private mFont As B4XFont
    Public LineWidth = Max(1, 1dip) As Int
    Public RowColor1, RowColor2 As Int

    Private pnlTable As B4XView

    Private ChrPad = " " As String
End Sub

Public Sub Initialize (Callback As Object, EventName As String)
    mEventName = EventName
    mCallBack = Callback
End Sub

'Base type must be Object
Public Sub DesignerCreateView (Base As Object, Lbl As Label, Props As Map)
    mBase = Base
    Tag = mBase.Tag
    mBase.Tag = Me
    
    mBase.Color = xui.Color_White
    
    'sets the text alignment property
    mAlignmentH = Props.GetDefault("TextAlignmentH", "CENTER")
    mAlignmentV = Props.GetDefault("TextAlignmentV", "CENTER")
    
#If B4A
    LineWidth = DipToCurrent(Props.GetDefault("LineWidth", 1))
#Else
    mLineWidth =Props.GetDefault("LineWidth", 1)
#End If
    
    mNumberOfColumns = Props.GetDefault("NumberOfColumns", 3)
    HeaderColor = xui.PaintOrColorToColor(Props.Get("HeaderColor"))
    TableColor = xui.PaintOrColorToColor(Props.Get("TableColor"))
    HeaderTextColor = xui.PaintOrColorToColor(Props.Get("HeaderTextColor"))
    TextColor = xui.PaintOrColorToColor(Props.Get("CellTextColor"))
    RowColor1 = xui.PaintOrColorToColor(Props.Get("Row1Color"))
    RowColor2 = xui.PaintOrColorToColor(Props.Get("Row2Color"))
    
    TextSize = Props.Get("TextSize")
    
    RowHeight = DipToCurrent(Props.GetDefault("RowHeight", 40dip))

    InitTable
End Sub

Private Sub Base_Resize (Width As Double, Height As Double)
 
End Sub

Private Sub InitTable
    Data.Initialize

    pnlTable = xui.CreatePanel("pnlTable")
    pnlTable.Color = TableColor
    mFont = xui.CreateDefaultFont(TextSize)

    mBase.AddView(pnlTable, 0, 0, mBase.Width, mBase.Height)

    Dim ColumnWidths(mNumberOfColumns) As Int
    Private mAlignmentsV(mNumberOfColumns) As String
    Private mAlignmentsH(mNumberOfColumns) As String
    For i = 0 To mNumberOfColumns - 1
        ColumnWidths(i) = mBase.Width / mNumberOfColumns
        mAlignmentsV(i) = mAlignmentV
        mAlignmentsH(i) = mAlignmentH
    Next

    SetHeader(Array As String("", "", ""))
End Sub

'Clears the table
'Removes all Data and Labels
Public Sub Clear
    pnlTable.RemoveAllViews
    Data.Clear
End Sub

'Adds a row to the table
'Example:<code>Table1.AddRow(Array As String("aaa", "ccc", "ddd", "eee"))</code>
Public Sub AddRow(Values() As String)
    If Values.Length <> mNumberOfColumns Then
        Log("Wrong number of values =" & Values.Length & " col=" & mNumberOfColumns)
        Return
    End If
    Data.Add(Values)
    Dim Row As Int
    Row = Data.Size
    
    Private lbls(mNumberOfColumns) As Label
    Private xlbls(mNumberOfColumns) As B4XView
    For i = 0 To mNumberOfColumns - 1
        lbls(i).Initialize("")
        pnlTable.AddView(lbls(i), pnlTable.GetView(i).Left, Row * RowHeight, pnlTable.GetView(i).Width, RowHeight - LineWidth)
        Private rc(2) As Int
        rc(0) = Row
        rc(1) = i
        xlbls(i) = lbls(i)
        xlbls(i).Tag = rc
        Private rowColor As Int
        Private txtColor As Int
        If Row Mod 2 = 0 Then
            rowColor = RowColor1
            txtColor = TextColor
        Else
            rowColor = RowColor2
            txtColor = TextColor
        End If       
        xlbls(i).Color = rowColor
        xlbls(i).TextColor = txtColor
        xlbls(i).TextSize = TextSize
        xlbls(i).SetTextAlignment(mAlignmentsV(i), mAlignmentsH(i))
        xlbls(i).Text = ChrPad & Values(i) & ChrPad
    Next

    mBase.Height = (Data.Size + 1) * RowHeight
    pnlTable.Height = mBase.Height
End Sub

'Set the headers values
'Example:<code>Table1.SetHeader(Array As String("Col1", "Col2", "Col3"))</code>
Public Sub SetHeader(Values() As String)
    Private col As Int

    pnlTable.RemoveAllViews    'KC
    HeaderNames.Initialize2(Values)

    Private Left = LineWidth As Int
    Private w As Int
    For col = 0 To mNumberOfColumns - 1
        Private lb As Label
        Private lbl As B4XView
        lb.Initialize("")
        lbl = lb
        lbl.SetTextAlignment(mAlignmentsV(col), mAlignmentsH(col))
        lbl.Font = mFont
        lbl.TextSize = TextSize
        lbl.Color = HeaderColor
        lbl.TextColor = HeaderTextColor
        lbl.Text = ChrPad & Values(col) & ChrPad
        lbl.Tag = col
        w = Max(LineWidth, ColumnWidths(col) - LineWidth)

        pnlTable.AddView(lbl, Left, 0, w, RowHeight)

        Left = Left + ColumnWidths(col)
    Next
    
    SetColumnsWidths(ColumnWidths)
End Sub

'Sets the columns widths.
'Example: <code>Table1.SetColumnsWidths(Array As Int(100dip, 30dip, 30dip, 100%x - 160dip))</code>
Public Sub SetColumnsWidths(Widths() As Int)
    Dim col, row As Int
    
    Dim ColumnWidths(Widths.Length) As Int
    For col = 0 To Widths.Length - 1
        ColumnWidths(col) = Widths(col)
    Next
    
    Private v As B4XView
    Private w As Int
    Private Left As Int
    
    Left = LineWidth
        
    For col = 0 To Widths.Length - 1
        v = pnlTable.GetView(col)
        w = Max(2dip, Widths(col) - LineWidth)
        v.Width = w
        v.Left = Left
        If w > 2dip Then
            Left = Left + w + LineWidth
        End If
    Next

    Dim lbls() As B4XView
    For row = 0 To Data.Size -1
        lbls = GetLabels(row)
        For col = 0 To lbls.Length - 1
            lbls(col).SetLayoutAnimated(0, pnlTable.GetView(col).Left, lbls(col).Top, pnlTable.GetView(col).Width, RowHeight - LineWidth)
        Next
    Next
End Sub

'Sets the alignments for the Headers and the Cells
'These must be String Arrays.
'Vertical authorized values are: Top, CENTER, BOTTOM
'Horizontal authorized values are: LEFT, CENTER, RIGHT
Public Sub SetAlignments(Vertical() As String, Horizontal() As String)
    mAlignmentsV = Vertical
    mAlignmentsH = Horizontal
End Sub

Public Sub GetColumnWidths As Int()
    Return ColumnWidths
End Sub

'Loads data from a SQLite database
'SQLite = SQL object
'Query = SQLite query
'SQLite limits REAL numbers converted to Strings like Floats (7 digits) not Doubles
'even 1000000.5 returns 1000000
Public Sub LoadSQLiteDB(SQLite As SQL, Query As String)
    Private col As Int
    Private RSet As ResultSet
    RSet = SQLite.ExecQuery(Query)
    
    If pnlTable.NumberOfViews > 0 Then
        pnlTable.RemoveAllViews
        Data.Clear
    End If
    
    Private Headers(mNumberOfColumns) As String
    For col = 0 To mNumberOfColumns - 1
        Headers(col) = RSet.GetColumnName(col)
    Next
    
    SetHeader(Headers)
    
    RSet = SQLite.ExecQuery(Query)
    Do While RSet.NextRow
        Dim R(mNumberOfColumns), str As String
        For col = 0 To mNumberOfColumns - 1
            str = RSet.GetString2(col)
            If str <> Null Then
                R(col) = str
            Else
                R(col) = ""
            End If
        Next
        AddRow(R)
#If B4J
'        Sleep(0) ' needed to display all entries when the Table is added by code.
#End If
    Loop
    RSet.Close
End Sub

'Gets the Labels of the given row as B4XViews
Public Sub GetLabels(Row As Int) As B4XView()
    Private lbls(mNumberOfColumns) As B4XView
    Private i0 As Int
    
    i0 = (Row + 1) * mNumberOfColumns
    For col = 0 To mNumberOfColumns - 1
        lbls(col) = pnlTable.GetView(i0 + col)
    Next
    Return lbls
End Sub

'Removes the xTableMicro from its parent view
Public Sub RemoveView
    mBase.RemoveViewFromParent
End Sub

'Gets the number of columns
Public Sub getNumberOfColumns As Int
    Return mNumberOfColumns
End Sub

'Sets the number of columns
Public Sub setNumberOfColumns(Number As Int)
    mNumberOfColumns=Number
End Sub

'Gets the number of rowsolumns, read only
Public Sub getNumberOfRows As Int
    Return Data.Size
End Sub

'Gets or sets the width of the xTableMicro of the given cell.
Public Sub getWidth As Int
    Return mBase.Width
End Sub

Public Sub setWidth(Width As Int)
    mBase.Width = Width
    pnlTable.Width = Width
End Sub

'Gets or sets the height of the xTableMicro of the given cell.
Public Sub getHeight As Int
    Return mBase.Width
End Sub

Public Sub setHeight(Height As Int)
    mBase.Height = Height
    pnlTable.Height = Height
End Sub

'Gets the value of the given cell.
Public Sub GetValue(Col As Int, Row As Int) As String
    Dim values() As String
    values = Data.Get(Row)
    Return values(Col)
End Sub

'Returns an array of strings with all the values for a row.
Public Sub GetValues(Row As Int ) As String()
    Dim rowData() As String  = Data.get(Row) ' will throw an excpetion if row is not correct
    Dim tmp(mNumberOfColumns) As String
    For i=0 To mNumberOfColumns-1 ' copy the array
        tmp(i) =  rowData(i)
    Next
    Return tmp
End Sub

Private Sub pnlTable_Touch (Action As Int, X As Float, Y As Float)
    Private iX, iY As Int
    
    iX = X
    iY = Y
    Select Action
        Case pnlTable.TOUCH_ACTION_DOWN
            If xui.SubExists(mCallBack, mEventName & "_Touch", 2) Then
                CallSub3(mCallBack, mEventName & "_Touch", iX, iY)
            End If
    End Select
End Sub

'Sets the xTableMicro visible
Public Sub setVisible(TrueFalse As Boolean)
    mBase.Visible=TrueFalse
End Sub

'Gets the xTableMicro visible
Public Sub getVisible As Boolean
    Return mBase.Visible
End Sub

I cannot get it work for 2 columns.

I added myself:
B4X:
'Sets the number of columns
Public Sub setNumberOfColumns(Number As Int)
    mNumberOfColumns=Number
End Sub

I can set, but still getting:
B4X:
xtablemicro_loadsqlitedb (java line: 482)
java.lang.ArrayIndexOutOfBoundsException: length=2; index=2

Can someone help to get it work with only 2 columns?

Kind regards,
André
 

AHilberink

Active Member
Licensed User
Longtime User
In the original library the NumberOfColumns is read only.
You can set the number in the Designer.

Can you post your projet so I can have a look at it.
Hello Klaus,

Thank you for your reply. The project is big, so I will show the code I need to use:
B4X:
        If(Soort="S") Then
            tblAanvulling1.SetAlignments(Array As String("CENTER", "CENTER"), Array As String("LEFT", "CENTER"))
            tblAanvulling1.LoadSQLiteDB(Main.SQL1,"SELECT Omschrijving, Aantal FROM DumpTabel WHERE OpdrachtID = " & Opdracht)
            tblAanvulling1.Tag = ROWID
            tblAanvulling1.SetColumnsWidths(Array As Int(tblAanvulling1.Width-55dip,55dip))
            If(Activity.Width>=1200) Then
                tblAanvulling1.TextSize=12dip
                tblAanvulling1.SetColumnsWidths(Array As Int(tblAanvulling1.Width-65dip,65dip))
            End If
        Else
            tblAanvulling1.SetAlignments(Array As String("CENTER", "CENTER", "CENTER"), Array As String("LEFT", "LEFT", "CENTER"))
            tblAanvulling1.LoadSQLiteDB(Main.SQL1,"SELECT Actie, Omschrijving, Aantal FROM DumpTabel WHERE OpdrachtID = " & Opdracht)
            tblAanvulling1.Tag = ROWID
            tblAanvulling1.SetColumnsWidths(Array As Int(100dip,tblAanvulling1.Width-155dip,55dip))
            If(Activity.Width>=1200) Then
                tblAanvulling1.TextSize=12dip
                tblAanvulling1.SetColumnsWidths(Array As Int(130dip,tblAanvulling1.Width-195dip,65dip))
            End If
        End If

As you can see on Soort="S" I need 2 columns, else 3. So I cannot set the number at in the Designer.

Is there a way to solve this?

Kind regards,
André
 
Upvote 0

AHilberink

Active Member
Licensed User
Longtime User
Can you test the attached test program.
I modified a bit the xTableMicro.bas file.
Hi Klaus,

Yes. This works fine. Now the number of columns depends on the selected fields of the SQL statement.

THANKS!!

I added also to your functions:
B4X:
'Sets the xTableMicro visible
Public Sub setVisible(TrueFalse As Boolean)
    mBase.Visible=TrueFalse
End Sub

'Gets the xTableMicro visible
Public Sub getVisible As Boolean
    Return mBase.Visible
End Sub

May be handy for others :)
 
Upvote 0
Top