B4A Library [Class] Flexible Table

Eric McDonald

Member
Licensed User
With the amount of pages there are on this thread, I have no idea if this has been asked yet but,

is there a way to select a row then select it again to be able to deselect it (pretty much just removing the color of the selected row)?

Also, is there a way to change the color of the selected row?
 

klaus

Expert
Licensed User
Longtime User
is there a way to select a row then select it again to be able to deselect it
Directly no, but you can use a workaround:
Define a Global variable SelectedRow = -1 As Int
And use the CellClick event like this:
B4X:
Sub Table2_CellClick(col As Int, row As Int)
    If SelectedRow >= 0 And SelectedRow = row Then
        Table2.clearSelection 'this removes the selection and removes the selected row color
        SelectedRow = -1
    Else
        SelectedRow = row
    End If
End Sub

Also, is there a way to change the color of the selected row?
Yes, you have the SelectedRowColor and SelectedCellColor properties which can be defined in the Designer or in the code.

I have seen that there are no SelectedRowTextColor and SelectedCellTextColor properties.
I will add these today and I will also add a property, ZeroSelections, allowing to have no selection.
 

klaus

Expert
Licensed User
Longtime User
The Table class has been updated to version 3.04.
- Added SelectedRowTextColor and SlectedCellTextColor properties
- Added ZeroSelections property, True > when a selected row is pressed it will be unselected False > it remains selected.
 
Last edited:

AnandGupta

Expert
Licensed User
Longtime User
The Table clas has been updated to version 3.04.
I think the #1 post is not updated with latest version.
Or I am looking at wrong place.

Regards,

Anand
 

AnandGupta

Expert
Licensed User
Longtime User
Sorry, I was sure that I did it, but after your post I saw that I removed the previous version without uploading the new version!?
Thanks got it, but updates text is still due, I think.



Regards,

Anand
 

RB Smissaert

Well-Known Member
Licensed User
Longtime User
Sorry, I was sure that I did it, but after your post I saw that I removed the previous version without uploading the new version!?

Just had a look at the latest version and noticed it still uses the old selection sort.
I found this to be quite slow and changed it with the SortType method on a list.
This is indeed a lot faster and I posted about this and I think you were going to look into it
and maybe incorporate it. This is a long time ago. How is the situation regarding this?

RBS
 

RB Smissaert

Well-Known Member
Licensed User
Longtime User
This is the relevant code as I have it now, may have changed since that thread.

B4X:
Public Sub SortTableNum(col As Int, bAscending As Boolean)

    Dim i As Long
    Dim lUB As Long
    Dim DataSorted As List
    Dim strColumnDataType As String

    GetVisibleRows (SV.VerticalScrollPosition)


    'strColumnDataTypes is set in LoadSQLDB4
    '---------------------------------------
    strColumnDataType = strColumnDataTypes(col)

    lUB = Data.Size - 1

    DataSorted.Initialize

    If bMap Then
        If col = 0 Then
            If strColumnDataType = "I" Then
                If iAlteredRowColour <> -1 Then
                    For i = 0 To lUB
                        DataSorted.Add (setSortPairLong(i, CInt(SortResultMap.GetKeyAt(i)), arrAlteredRowColour(i)))
                    Next
                Else
                    For i = 0 To lUB
                        DataSorted.Add (setSortPairLong(i, CInt(SortResultMap.GetKeyAt(i)), False))
                    Next
                End If
                DataSorted.SortType("lLong", bAscending)    '<< this will do the sort
            Else
                If iAlteredRowColour <> -1 Then
                    For i = 0 To lUB
                        DataSorted.Add (setSortPairDouble(i, SortResultMap.GetKeyAt(i), arrAlteredRowColour(i)))
                    Next
                Else
                    For i = 0 To lUB
                        DataSorted.Add (setSortPairDouble(i, SortResultMap.GetKeyAt(i), False))
                    Next
                End If
                'this will take a bit less than half of the total time of SortTableNum
                '---------------------------------------------------------------------
                DataSorted.SortType("dDouble", bAscending)    '<< this will do the sort
            End If
        Else    'If col = 0
            If strColumnDataType = "I" Then
                If iAlteredRowColour <> -1 Then
                    For i = 0 To lUB
                        DataSorted.Add (setSortPairLong(i, CInt(SortResultMap.GetValueAt(i)), arrAlteredRowColour(i)))
                    Next
                Else
                    For i = 0 To lUB
                        DataSorted.Add (setSortPairLong(i, CInt(SortResultMap.GetValueAt(i)), False))
                    Next
                End If
                DataSorted.SortType("lLong", bAscending)    '<< this will do the sort
            Else
                If iAlteredRowColour <> -1 Then
                    For i = 0 To lUB
                        DataSorted.Add (setSortPairDouble(i, SortResultMap.GetValueAt(i), arrAlteredRowColour(i)))
                    Next
                Else
                    For i = 0 To lUB
                        DataSorted.Add (setSortPairDouble(i, SortResultMap.GetValueAt(i), False))
                    Next
                End If
                'this will take a bit less than half of the total time of SortTableNum
                '---------------------------------------------------------------------
                DataSorted.SortType("dDouble", bAscending)    '<< this will do the sort
            End If
        End If    'If col = 0
    Else
        If strColumnDataType = "I" Then
            If iAlteredRowColour <> -1 Then
                For i = 0 To lUB
                    SortResultSet.Position = i
                    DataSorted.Add (setSortPairLong(i, SortResultSet.GetInt2(col), arrAlteredRowColour(i)))
                Next
            Else
                For i = 0 To lUB
                    SortResultSet.Position = i
                    DataSorted.Add (setSortPairLong(i, SortResultSet.GetInt2(col), False))
                Next
            End If
            DataSorted.SortType("lLong", bAscending)    '<< this will do the sort
        Else
            If iAlteredRowColour <> -1 Then
                For i = 0 To lUB
                    SortResultSet.Position = i
                    DataSorted.Add (setSortPairDouble(i, SortResultSet.GetDouble2(col), arrAlteredRowColour(i)))
                Next
            Else
                For i = 0 To lUB
                    SortResultSet.Position = i
                    DataSorted.Add (setSortPairDouble(i, SortResultSet.GetDouble2(col), False))
                Next
            End If
            'this will take a bit less than half of the total time of SortTableNum
            '---------------------------------------------------------------------
            DataSorted.SortType("dDouble", bAscending)    '<< this will do the sort
        End If
    End If

    SelectedRows.Clear

    debug_counter = 0

    If strColumnDataType = "I" Then
        If iAlteredRowColour <> -1 Then
            For i = 0 To lUB
                Dim tL As SortLong = DataSorted.Get(i)
                'DataTemp is populated in LoadSQLDB4 or LoadSQLiteDBFromMap,
                'so keep using the same original Data list with different sorts
                '--------------------------------------------------------------
                Data.Set(i, DataTemp.Get(tL.IDX))
                SetRowColour(i, tL.bColouredRow, False)
            Next
        Else
            For i = 0 To lUB
                Dim tL As SortLong = DataSorted.Get(i)
                'DataTemp is populated in LoadSQLDB4 or LoadSQLiteDBFromMap,
                'so keep using the same original Data list with different sorts
                '--------------------------------------------------------------
                Data.Set(i, DataTemp.Get(tL.IDX))
            Next
        End If
    Else
        If iAlteredRowColour <> -1 Then
            'will be column type real - "R"
            For i = 0 To lUB
                Dim tD As SortDouble = DataSorted.Get(i)
                'DataTemp is populated in LoadSQLDB4 or LoadSQLiteDBFromMap,
                'so keep using the same original Data list with different sorts
                '--------------------------------------------------------------
                Data.Set(i, DataTemp.Get(tD.IDX))
                SetRowColour(i, tD.bColouredRow, False)
            Next
        Else
            'will be column type real - "R"
            For i = 0 To lUB
                Dim tD As SortDouble = DataSorted.Get(i)
                'DataTemp is populated in LoadSQLDB4 or LoadSQLiteDBFromMap,
                'so keep using the same original Data list with different sorts
                '--------------------------------------------------------------
                Data.Set(i, DataTemp.Get(tD.IDX))
            Next
        End If
    End If

    RefreshTable

End Sub

Public Sub SortTable(col As Int, bAscending As Boolean)

    Dim i As Long
    Dim lUB As Long
    Dim DataSorted As List

    GetVisibleRows (SV.VerticalScrollPosition)

    lUB = Data.Size - 1

    If bMap Then
        If col = 0 Then
            DataSorted.Initialize
            If arrDateColumns(col) = True Then
                If iAlteredRowColour <> -1 Then
                    For i = 0 To SortResultMap.Size - 1
                        DataSorted.Add (setSortPairLong(i, CLng(SortResultMap.GetKeyAt(i)), arrAlteredRowColour(i)))
                    Next
                Else
                    For i = 0 To SortResultMap.Size - 1
                        DataSorted.Add (setSortPairLong(i, CLng(SortResultMap.GetKeyAt(i)), False))
                    Next
                End If
                DataSorted.SortType("lLong", bAscending)
            Else    'If arrDateColumns(col) = True
                If iAlteredRowColour <> -1 Then
                    For i = 0 To SortResultMap.Size - 1
                        DataSorted.Add (setSortPairString(i, ClearStringNull(SortResultMap.GetKeyAt(i), ""), arrAlteredRowColour(i)))
                    Next
                Else
                    For i = 0 To SortResultMap.Size - 1
                        DataSorted.Add (setSortPairString(i, ClearStringNull(SortResultMap.GetKeyAt(i), ""), False))
                    Next
                End If
                DataSorted.SortType("strString", bAscending)
            End If    'If arrDateColumns(col) = True
        Else    'If col = 0
            DataSorted.Initialize
            If arrDateColumns(col) = True Then
                If iAlteredRowColour <> -1 Then
                    For i = 0 To SortResultMap.Size - 1
                        DataSorted.Add (setSortPairLong(i, CLng(SortResultMap.GetValueAt(i)), arrAlteredRowColour(i)))
                    Next
                Else
                    For i = 0 To SortResultMap.Size - 1
                        DataSorted.Add (setSortPairLong(i, CLng(SortResultMap.GetValueAt(i)), False))
                    Next
                End If
                DataSorted.SortType("lLong", bAscending)
            Else    'If arrDateColumns(col) = True
                If iAlteredRowColour <> -1 Then
                    For i = 0 To SortResultMap.Size - 1
                        DataSorted.Add (setSortPairString(i, ClearStringNull(SortResultMap.GetValueAt(i), ""), arrAlteredRowColour(i)))
                    Next
                Else
                    For i = 0 To SortResultMap.Size - 1
                        DataSorted.Add (setSortPairString(i, ClearStringNull(SortResultMap.GetValueAt(i), ""), False))
                    Next
                End If
                DataSorted.SortType("strString", bAscending)
            End If    'If arrDateColumns(col) = True

        End If    'If col = 0
    Else    'If bMap
        DataSorted.Initialize
        If arrDateColumns(col) = True Then
            If iAlteredRowColour <> -1 Then
                For i = 0 To SortResultSet.RowCount - 1
                    SortResultSet.Position = i
                    DataSorted.Add (setSortPairLong(i, SortResultSet.GetLong2(col), arrAlteredRowColour(i)))
                Next
            Else
                For i = 0 To SortResultSet.RowCount - 1
                    SortResultSet.Position = i
                    DataSorted.Add (setSortPairLong(i, SortResultSet.GetLong2(col), False))
                Next
            End If
            DataSorted.SortType("lLong", bAscending)
        Else
            If iAlteredRowColour <> -1 Then
                For i = 0 To SortResultSet.RowCount - 1
                    SortResultSet.Position = i
                    DataSorted.Add (setSortPairString(i, ClearStringNull(SortResultSet.GetString2(col), ""), arrAlteredRowColour(i)))
                    'General.RunLog("SortTable, setSortPairString, arrAlteredRowColour(" & i & "): " & arrAlteredRowColour(i))
                Next
            Else
                For i = 0 To SortResultSet.RowCount - 1
                    SortResultSet.Position = i
                    DataSorted.Add (setSortPairString(i, ClearStringNull(SortResultSet.GetString2(col), ""), False))
                Next
            End If
            DataSorted.SortType("strString", bAscending)
        End If
    End If    'If bMap

    SelectedRows.Clear
    debug_counter = 0

    If arrDateColumns(col) = True Then
        If iAlteredRowColour <> -1 Then
            For i = 0 To lUB
                Dim tL As SortLong = DataSorted.Get(i)
                'DataTemp is populated in LoadSQLDB4 or LoadSQLiteDBFromMap,
                'so keep using the same original Data list with different sorts
                '--------------------------------------------------------------
                Data.Set(i, DataTemp.Get(tL.IDX))
                SetRowColour(i, tL.bColouredRow, False)
            Next
        Else
            For i = 0 To lUB
                Dim tL As SortLong = DataSorted.Get(i)
                'DataTemp is populated in LoadSQLDB4 or LoadSQLiteDBFromMap,
                'so keep using the same original Data list with different sorts
                '--------------------------------------------------------------
                Data.Set(i, DataTemp.Get(tL.IDX))
            Next
        End If
    Else    'If arrDateColumns(col) = True
        If iAlteredRowColour <> -1 Then
            For i = 0 To lUB
                Dim tDS As SortString = DataSorted.Get(i)
                'DataTemp is populated in LoadSQLDB4 or LoadSQLiteDBFromMap,
                'so keep using the same original Data list with different sorts
                '--------------------------------------------------------------
                Data.Set(i, DataTemp.Get(tDS.IDX))
                SetRowColour(i, tDS.bColouredRow, False)
            Next
        Else
            For i = 0 To lUB
                Dim tDS As SortString = DataSorted.Get(i)
                'DataTemp is populated in LoadSQLDB4 or LoadSQLiteDBFromMap,
                'so keep using the same original Data list with different sorts
                '--------------------------------------------------------------
                Data.Set(i, DataTemp.Get(tDS.IDX))
            Next
        End If
    End If    'If arrDateColumns(col) = True

    RefreshTable

End Sub

Sub setSortPairString(lIDX As Long, strValue As String, bColouredRow As Boolean) As SortString

    Dim tSS As SortString

    tSS.Initialize
    tSS.IDX = lIDX
    tSS.strString = strValue
    tSS.bColouredRow = bColouredRow
    Return tSS

End Sub

Sub setSortPairLong(lIDX As Long, lValue As Long, bColouredRow As Boolean) As SortLong

    Dim tL As SortLong

    tL.Initialize
    tL.IDX = lIDX
    tL.lLong = lValue
    tL.bColouredRow = bColouredRow
    Return tL

End Sub

Sub setSortPairDouble(lIDX As Long, dValue As Double, bColouredRow As Boolean) As SortDouble

    Dim tD As SortDouble

    tD.Initialize
    tD.IDX = lIDX
    tD.dDouble = dValue
    tD.bColouredRow = bColouredRow
    Return tD

End Sub

Public Sub SetSortCursor(oRS As ResultSet)
    bMap = False
    SortResultSet = oRS
End Sub

Public Sub SetSortMap(oMap As Map)
    bMap = True
    SortResultMap = oMap
End Sub

Sub Class_Globals

    Public bMap As Boolean
    Public SortResultSet As ResultSet
    Public SortResultMap As Map

    Type SortString(IDX As Long, _
                     strString As String, _
                     bColouredRow As Boolean)
    Type SortLong(IDX As Long, _
                   lLong As Long, _
                   bColouredRow As Boolean)
    Type SortDouble(IDX As Long, _
                     dDouble As Double, _
                     bColouredRow As Boolean)
                     bColouredRow As Boolean)

    Private DataTemp As List

Public Sub LoadSQLiteDB(RS1 As ResultSet, _
                         AutomaticWidths As Boolean, _
                         ColumnNames() As String, _
                         ColumnDataTypes() As String, _
                         MaxColumnWidths() As Int, _
                         ColWidths() As Int)
    
    'towards the end of LoadSQLiteDB
    SetSortCursor (RS1)
    DataTemp.Initialize
    For i = 0 To lRows - 1
        DataTemp.Add (Data.Get(i))
    Next

Will see if I can find that thread now.

RBS
 

Eric McDonald

Member
Licensed User
Not sure if this has been asked yet but I haven't been able to find it anywhere on this forums or google.

But is there a way to take a table and save it as a CSV file then be able to take a different table and save it into the same CSV file under the existing rows?

I appreciate any help.
 

klaus

Expert
Licensed User
Longtime User
Yes!
There are two methods:
SaveTableToCSV(Dir As String, Filename As String)
SaveTableToCSV2(Dir As String, Filename As String, SeparatorChar As String)

You could have found it on your own.
In the IDE, type the name of the Table object and a dot, like in the example Table1.

The inline help shows all the methods and properties for the Table object.
 

Eric McDonald

Member
Licensed User
I have tried that method but what I am trying to do is explained with the comments in the code below
B4X:
    If File.Exists(File.DirRootExternal,"CSV_Test.csv") = True Then
        'Take the data from the existing CSV file and store it somewhere
        'Add that data to a new CSV file
        'The below row will take that saved data from the old CSV file and take the data
        'from the new table and add it to a new CSV file
        register.SaveTableToCSV(File.DirRootExternal,"CSV_Test.csv")
    Else
        register.SaveTableToCSV(File.DirRootExternal,"CSV_Test.csv")
    End If

Just trying to find something that will do what I'm trying to do in my code, not necessarily go the route of checking if the file already exists.
 

klaus

Expert
Licensed User
Longtime User
Sorry, I hadn't read your post deeply enough.
It is not possible, in the current version, to append the table content to an existing *.csv file.
The SaveTableToCSV routines are based on the StringUtils library which doesn't allow to append data.
To append data you need to write your own routine.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User

Eric McDonald

Member
Licensed User
Is there a relatively possible way to be able to take the values (As Strings) from the table and have that text be auto-filled into an existing Edit Text?
I.e. An edit selected feature when a button is pressed, an existing edit text control will be filled with the specified value from the table.

Going along with this feature to actually make it work, is there a way to check if a certain row is selected using Register_CellClick as a way to take the values from that specific row?
 

klaus

Expert
Licensed User
Longtime User
You can use the Table_CellClick(col As Int, row As Int) event which returns the selected row and column.
You have the Value = Table.GetValue(col, row) method which returns the value of the cell with the given row and column index.
You can define two variables to save the row and col values and or save the content with the method above.

You have Table.SelectedRows, the list of the selected row indexes without the selected column indexes.
Table.SelectedRows.Size returns the number of selected rows. If you set Table.MultiSelect = True you can select several rows.
Table.SelectedRows.Get(0) returns the index of the first selected row and Table.SelectedRows.Get(1) the next one and so on.
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…