B4A Library [Class] TableView - Supports tables of any size

An improved version of this class is available here: http://www.b4x.com/forum/additional...icial-updates/30649-class-flexible-table.html


The Table class allows you to show tables of any sizes. The views (labels) are reused to avoid creating many views.

With the help of StringUtils the table can be loaded and saved to a CSV file. It shouldn't be difficult to show SQL tables using DBUtils.ExecuteMemoryTable.

SS-2012-07-04_10.38.01.png


Follow the attached example to see how the class is used. To add it to your own project you need to add the class module to your project and add a reference to StringUtils library.

RemoveRow code is available here: http://www.b4x.com/forum/showpost.php?p=146795&postcount=147

V1.10 uploaded. New method: SetColumnsWidths. Allows you to manually set the width of each column
V1.11 uploaded. Fixes a bug with grey stripes appearing.
 

Attachments

  • Table.zip
    14.9 KB · Views: 7,945
Last edited:

Smee

Well-Known Member
Licensed User
Longtime User
You need to call:
B4X:
tblOrders.AddToActivity(pan, ...)

Thanks Erel,

I was sure i had tried that earlier. I must have done it in conjunction with another error:sign0137:
 

Smee

Well-Known Member
Licensed User
Longtime User
i created a small test app which works fine but then i was creating another one that uses the same code in the class but i am getting funny results.

It seems when i click on a row it changes the entire contents of the row to the same as the last row. I do not have any subs which can do this so it is happening in the class itself

B4X:
Private Sub Cell_Click
   Dim rc As RowCol
   Dim l As Label
   l = Sender
   rc = l.Tag
'   SelectRow(rc.Row)
   SelectRow(rc)
   If SubExists(Callback, Event & "_CellClick") Then
      CallSub3(Callback, Event & "_CellClick", rc.Col, rc.Row)
   End If
End Sub
if i put a return after this line

rc = l.Tag

then it does not happen

it happens here
SelectRow(rc)

or more specifically in the sub routines that are called in that sub.

Private Sub ShowRow


UPDATE:

B4X:
Private Sub ShowRow(row As Int)
    If visibleRows.ContainsKey(row) Then Return
    'Log("ShowRow: " & row)
    Dim lbls() As Label
    Dim values() As String
   Dim values2() As String
   
    lbls = GetLabels(row)
   values = Data.get(row)
   
   For x=0 To Data.Size-1
      values2 = Data.get(x)
   Next

i changed the sub to put the for next loop in. It seems that when the table is loaded all the values are correct but when a row is touched all the values in the data list is the same. i.e it is all the same as the last row. How can this be?
 
Last edited:

melamoud

Active Member
Licensed User
Longtime User
Are you sure it change the table data or just present the new line over the old one?

Easy to check if you print the table line.
I'm asking because it make sense its just presentation issue if so you might want to check that in both projects the container panel/activity has the same height - it might be a bug in the table anyway but will help with the diagnostics
 

Smee

Well-Known Member
Licensed User
Longtime User
Have you modified the class code?

Can you upload the problematic project?

thanks Erel

here it is

No i actually copied and pasted the class code in case i had made an accidentel change
 

Attachments

  • test3.zip
    260 KB · Views: 318
Last edited:

Smee

Well-Known Member
Licensed User
Longtime User
I have found the source of the error but i am unsure how to fix it

B4X:
Dim TableMap(4) As String
For x = 0 To Cursor.RowCount-1
   Cursor.Position = x
   For i = 0 To Cursor.ColumnCount-1
      TableMap(i)=Cursor.GetString2(i)
   Next
   tblOrders.AddRow(TableMap)
Next

Puts the correct values in BUT it causes the error

comment out the .addrow and instead

B4X:
'tblOrders.AddRow(Array As String("a","b","c","d"))
'tblOrders.AddRow(Array As String("e","f","g","h"))
'tblOrders.AddRow(Array As String("i","j","k","l"))
'tblOrders.AddRow(Array As String("m","n","o","p"))
'tblOrders.AddRow(Array As String("q","r","s","t"))

works fine. rows do not change

So it is how i am adding the string to the row which causes the problem. but if i use

B4X:
tblOrders.AddRow(Array As String((TableMap))

The code executes but i do not get any values. How to overcome it?

i have tried this
Dim TableMap() As String
For i = 0 To Cursor.ColumnCount-1
TableMap=Cursor.GetString2(i)
Next
BUT i get an error at getstring
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
You are using the same array again and again.

Change your code to:
B4X:
Sub PopulateGrid

Dim Cursor As Cursor

tblOrders.ClearAll

SQL.ExecNonQuery("DELETE FROM Orders WHERE Qty=0")

Cursor = SQL.ExecQuery("SELECT * FROM Orders")
For x = 0 To Cursor.RowCount-1
   Cursor.Position = x
   Dim TableMap(4) As String
   For i = 0 To Cursor.ColumnCount-1
      TableMap(i)=Cursor.GetString2(i)
   Next
   tblOrders.AddRow(TableMap)
Next                  

End Sub
 

Smee

Well-Known Member
Licensed User
Longtime User
Inelegant Solution

here it is

B4X:
   tblOrders.AddRow(Array As String(TableMap(0),TableMap(1),TableMap(2),TableMap(3)))

Can i do it without knowing the number of columns in advance?
 

Smee

Well-Known Member
Licensed User
Longtime User
Why don't you take the code I posted? It will work fine. You can change 4 to Cursor.ColumnCount.

Oh CRAP!!!

I posted without seeing your solution. Thanks Erel. Far better than mine as per usual
 

enrico

Active Member
Licensed User
Longtime User
Does this example work only with "," as csv fileld separator ?
What if I have ";" ?
 

klaus

Expert
Licensed User
Longtime User
You can either:
- Replace in the Table class in lines 348, 354 and 380 the comma "," by the semicolon ";".

or

- Modify
Public Sub LoadTableFromCSV(Dir As String, Filename As String, HeadersExist As Boolean)
to
Public Sub LoadTableFromCSV(Dir As String, Filename As String, HeadersExist As Boolean, SepChar As String)
and the two lines
List1 = StringUtils1.LoadCSV2(Dir, Filename, ",", headers)
List1 = StringUtils1.LoadCSV(Dir, Filename, ",")

to
List1 = StringUtils1.LoadCSV2(Dir, Filename, SepChar, headers)
List1 = StringUtils1.LoadCSV(Dir, Filename, SepChar)


And the calling line, for example, from
Table2.LoadTableFromCSV(File.DirAssets, "citylist.csv", True)
to
Table2.LoadTableFromCSV(File.DirAssets, "citylist.csv", True, ";")

And
Public Sub SaveTableToCSV(Dir As String, Filename As String)
to
Public Sub SaveTableToCSV(Dir As String, Filename As String, SepChar As String)
and
StringUtils1.SaveCSV2(Dir, Filename, ",", Data, headers)
to
StringUtils1.SaveCSV2(Dir, Filename, SepChar, Data, headers)
and the calling routine, for example, from
Table2.LoadTableFromCSV(File.DirAssets, "citylist.csv", True)
to
Table2.LoadTableFromCSV(File.DirAssets, "citylist.csv", True, ";")

Best regards.
 

enrico

Active Member
Licensed User
Longtime User
Filter

Thanks.
Can I filter the csv table according the value of a selected cell (How ?) or is it possible only with sqlite table ?
 

Smee

Well-Known Member
Licensed User
Longtime User
this is the code i use

For x = 0 To Cursor.RowCount-1
Cursor.Position = x
Dim TableMap(Cursor.ColumnCount) As String
For i = 0 To Cursor.ColumnCount-1
TableMap(i)=Cursor.GetString2(i)
Next
tblOrders.AddRow(TableMap)
Next
Cursor.Close
 

enrico

Active Member
Licensed User
Longtime User
Sorry but I would need a more complete code, because I get various errors trying to modify and clean it to use SQLite.
Can anybody post a zip ? Thanks
 

enrico

Active Member
Licensed User
Longtime User
I've done it, even if I see it much slower than with csv table.
But now I have problems with buttons.
I put some buttons in a panel and strangely clicks don't work.
Table_CellClick and Table_HeaderClick are working but those Button_Click seems insensitive. I can't understand why.
 
Top