B4J Question Tableview select multiple rows

raphipps2002

Active Member
Licensed User
Longtime User
Is it possible to select multiple rows on a tableview then scroll through the the table identifying those rows selected.
;)
 

Daestrum

Expert
Licensed User
Longtime User
yes - see this example (needs javaobject library)

B4X:
Dim jo As JavaObject = TableView1
Dim sm As JavaObject
   sm = jo.RunMethod("getSelectionModel",Null)
Dim sm1 As JavaObject
   sm1.InitializeStatic("javafx.scene.control.SelectionMode")
   sm.RunMethod("setSelectionMode",Array(sm1.GetField("MULTIPLE")))
' the following 3 lines ONLY work in release mode and will select rows 1, 2 and 5
sm.RunMethod("select",Array(1)) ' select row 1
sm.RunMethod("select",Array(2)) ' select row 2
sm.RunMethod("select",Array(5)) ' select row 5
' to add rows from mouse click use ctrl+click otherwise selection is reset

' get selected rows from table as list
Dim l As List
l.Initialize
   l.AddAll(sm.RunMethodJO("getSelectedItems",Null))

' display the data in the rows
Dim ss As String = ""
For Each o() As Object In l
   For Each o1 In o
      If ss="" Then
         ss = o1
      Else
         ss = ss & "-" & o1
      End If
   Next
Log(ss)
ss=""
Next
...
 
Last edited:
Upvote 0

raphipps2002

Active Member
Licensed User
Longtime User
ok thanks....I have included this in my code but cant get it to work. When you say 'only works in release mode' what does this mean? How do i set and what do it set to make release mode? on my form the user selects from two datepickers; from and to. jo1 and jo2.

1) Scrolling from row 1 to the end of table, looking for column(1) which is a date column. If date is between A and B I want to select it
2) I wasnt sure if tblCB.selectrow = i might interfere with the code you gave me, so i created a list of all rows within the date range then
3) for each j finds the row number and then your code - jo.RunMethodJO("getSelectionModel",Null).RunMethod("select",Array(j))
4: Display the data in the rows only shows last row

But all it does is highlight the last row :(


B4X:
Try
        Dim jo1 As JavaObject = dtprangeFrom
        Dim jo2 As JavaObject = dtpRangeTo
        Dim sDate1 As String = jo1.RunMethod("getValue", Null)
        Dim dDate1 As Long = DateTime.DateParse(sDate1)
        Dim sDate2 As String = jo2.RunMethod("getValue", Null)
        Dim dDate2 As Long = DateTime.DateParse(sDate2)
    Catch
        msg.Show("Select date range","Date range error")
        Log(LastException)   
        Return
    End Try
   
        Log("Period from " & DateTime.Date(dDate1) & " to " & DateTime.Date(dDate2))
       
    'select row
    Dim jo As JavaObject = tblCB
    Dim sm As JavaObject
    sm = jo.RunMethod("getSelectionModel",Null)
    Dim sm1 As JavaObject
    sm1.InitializeStatic("javafx.scene.control.SelectionMode")
    sm.RunMethod("setSelectionMode",Array(sm1.GetField("MULTIPLE")))

   
    Dim Li As List
    Li.Initialize()
   
   
    For i = 1 To tblCB.Items.Size-1
       
        Log("row selected is " & i)
        tblCB.SelectedRow = i
        Dim row() As Object = tblCB.SelectedRowValues
        Dim DT As Long = DateTime.DateParse(row(1))
   
        Log("Transaction selected is " & row(0) & " " & row(1))
        If DT >= dDate1 And DT <=dDate2 Then
            'Now select the actual row
            Li.Add(i)   
            Log(i & " is in date range" & DateTime.Date(DT))
        End If   
    Next
   
    For Each j In Li
        Log("selecting item row " & j)
        jo.RunMethodJO("getSelectionModel",Null).RunMethod("select",Array(j))
    Next
           
    'Get selected rows from the table as list
    Dim l As List
    l.Initialize
    l.AddAll(sm.RunMethodJO("getSelectedItems",Null))
   
    'Display the data in the rows
     Dim ss As String = ""
    For Each o() As Object In l
        For Each o1 In o
            If ss = "" Then
                ss=01
            Else
                ss = ss & "-" & o1
            End If       
        Next
        Log(ss)
        ss = ""
    Next





:)
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
Release mode as in compiled and run.
Normally you use B4J in debug mode (the box above edit window normally says Debug) you have to select release for the select rows to work.
I have no idea as to why, as setting them from js works even in debug mode.
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
If you ctrl+click on the tableview, does it select multiple rows ?
 
Upvote 0

raphipps2002

Active Member
Licensed User
Longtime User
Yes it does....but for some reason it has started to work. I am sure its something to do with dateformat...further investigation need...but I getting somewhere

thanks!
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
Good :)
I can show you the equivalent code using nashorrn js, much easier to read and it can filter and select in one go

(when I say easier, I mean for me, but maybe not for others :) )
 
Last edited:
Upvote 0

raphipps2002

Active Member
Licensed User
Longtime User
yes please! Its strange you know because sometimes it works then I close app re-complie and it doesnt work! very odd! But it is working as I want thanks very much
 
Upvote 0

raphipps2002

Active Member
Licensed User
Longtime User
Well....the code seems to be working better...but one thing....why is it that the last item in the tables always ends up 'visually' highlighting the last row. But not actually selecting it as far as the code is concerned. How can I stop this?

:)
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
I am not sure, it doesn't happen when I use js version to select rows
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
the js version
B4X:
' in globals
Dim nash As jInvokeNashorn    ' in libraries under jscriptengine
Dim scr As String

The actual code
B4X:
scr = $"
   load("fx:base.js")
   load("fx:controls.js")
   load("fx:graphics.js")

function selectRows(table,from,to){
   table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE)
   for each(i in table.items){
       if (i[0] >= from && i[0] <= to){ //compare col 0 to value
          table.getSelectionModel().select(i)
       }
    }
}

function selectedPrint(table){
   table.getSelectionModel().getSelectedItems().forEach(function(aa){print(aa[0],"-",aa[1])})
}

function getSelected(table){
   return table.getSelectionModel().getSelectedItems()
}
"$

nash.InitInvocable(scr)
nash.Invoke("selectRows",Array(TableView1,3,6))
nash.Invoke("selectedPrint",Array(TableView1))
Log(nash.Invoke("getSelected",Array(TableView1)))
 
Last edited:
Upvote 0

raphipps2002

Active Member
Licensed User
Longtime User
Ok so I tried the code But nothing is selected. My table is called tblCB. I played with the function row numbers currently 1 to 6...but nothing selected

When I manually selected rows using ctrl-click, the log did reveal the rows selected. But in the log I had this which i have seen before and have a feeling its not correct

In my table col 0 is either I and E

and col 1 is a date

LOG

I - 2015-11-05
[[Ljava.lang.Object;@1d9e25bd]
E - 2015-12-02
[[Ljava.lang.Object;@27c8edb1]

Code

B4X:
scr = $"
   load("fx:base.js")
   load("fx:controls.js")
   load("fx:graphics.js")

    function selectRows(table,from,to){
       table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE)
       for each(i in table.items){
           if (i[0] >= from && i[0] <= to){ //compare col 0 to value
              table.getSelectionModel().select(i)
           }
        }
    }

    function selectedPrint(table){
       table.getSelectionModel().getSelectedItems().forEach(function(aa){print(aa[0],"-",aa[1])})
    }

    function getSelected(table){
       return table.getSelectionModel().getSelectedItems()
    }
    "$

    nash.InitInvocable(scr)

    nash.Invoke("selectRows",Array(tblCB,1,6))
   
    nash.Invoke("selectedPrint",Array(tblCB))

    Log(nash.Invoke("getSelected",Array(tblCB)))
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
in this line
nash.Invoke("selectRows",Array(tblCB,1,6))
the 1 and 6 are the limits
ie the col.value is compared to the 2 values, it must be between 1 and 6 in this case

this line chooses which column you are comparing
if (i[0] >= from && i[0] <= to)
In this case its column 0

It looks like you need col 1 which would be i[1]

if column holds a string which is a date, you could pass the date range to the function in place of the 1 and 6
ie
nash.Invoke("selectRows",Array(tblCB,startdate,enddate))
or
nash.Invoke("selectRows",Array(tblCB,"2015-01-01","2015-06-06"))

or replace
B4X:
function selectRows(table,from,to){
    table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE)
    for each(i in table.items){
       if (i[0] >= from && i[0] <= to){ //compare col 0 to value
          table.getSelectionModel().select(i)
       }
    }
}
with
B4X:
function selectRows(table,col,from,to){
    table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE)
    for each(i in table.items){
       if (i[col] >= from && i[col] <= to){ //compare col.value to limits
          table.getSelectionModel().select(i)
       }
    }
}
and call with
nash.Invoke("selectRows",Array(tblCB,1,"2015-01-01","2015-06-06"))
and you can specify the column to compare in the call ( the 1 as second parameter)

this code
B4X:
function selectedPrint(table){
    table.getSelectionModel().getSelectedItems().forEach(function(aa){print(aa[0],"-",aa[1])})
}
simply prints out col 0 value "-" col 1 value
again the aa[0] and aa[1] specify the columns to print (col 0 and col 1 in this case)

The last routine getSelected(table) simply returns a list containing all of the selected rows (each item is an object containing the entire row)
 
Last edited:
Upvote 0

raphipps2002

Active Member
Licensed User
Longtime User
Ahh I see. Silly me! Ok I get it. But in my table column 1 shows a date. ie. 2015-11-01. So, I need to convert that column value to a tick value datetime.dateparse("2015-11-01") = tickvalue. Then compare this with the datepicker's value selected by user again converted to a tick. pickerfrom to pickerto

I presume therefore that as my date column is col 1 i need this

B4X:
function selectRows(table,from,to){
   table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE)
   for each(i in table.items){
       if (i[1] >= from && i[1] <= to){ //compare col 0 to value
          table.getSelectionModel().select(i)
       }
    }
}


B4X:
    nash.InitInvocable(scr)

    Try
        Dim jo1 As JavaObject = dtprangeFrom
        Dim jo2 As JavaObject = dtpRangeTo
        Dim sDate1 As String = jo1.RunMethod("getValue", Null)
        Dim dDate1 As Long = DateTime.DateParse(sDate1)
        Dim sDate2 As String = jo2.RunMethod("getValue", Null)
        Dim dDate2 As Long = DateTime.DateParse(sDate2)
   
    Catch
        msg.Show("Select date range","Date range error")
        Log(LastException)   
        Return
   
    End Try

    nash.Invoke("selectRows",Array(tblCB,dDate1,dDate2))
   
    nash.Invoke("selectedPrint",Array(tblCB))

    Log(nash.Invoke("getSelected",Array(tblCB)))
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
What data type is col 1? do you just put a date field into it or a string?
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
I would just convert the datepicker output to a string and use that to compare. (not used datepicker much but suspect the value can be like 2015/2/21)

Also you could change the if line in selectRows(table...) to
if (i[1] >= (from<to?from:to) && i[1] <= (to>from?to:from))

Then, if the dates are put in wrong instead of from, to they go in as to , from
the above line will still select the correct rows as it will use the earliest date as 'from' and the later date as 'to'.
 
Last edited:
Upvote 0

raphipps2002

Active Member
Licensed User
Longtime User
Thanks for the tutorial! :)

Can I ask...how do you DESELECT and item?

Select
jo.RunMethodJO("getSelectionModel",Null).RunMethod("select",Array(j))

DESelect
jo.RunMethodJO("getSelectionModel",Null).RunMethod("DEselect",Array(j))????

:)
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
jo.RunMethodJO("getSelectionModel",Null).RunMethod("clearSelection",Array(j))
 
Upvote 0
Top