Android Question Get variable value by string of name

hung

Active Member
Licensed User
Longtime User
Here is what I want
B4X:
Sub Process_Globals
    Private gs_appver As String = "2312xx"
    Private gs_appname As String = "App name"
End sub

Sub Showall()
    ToastMessageShow(varval("gs_appver"), True)
    ToastMessageShow(varval("gs_appname"), True)
End sub

Is there a function in B4x similar as "varval()"?
 

ilan

Expert
Licensed User
Longtime User

1703958362529.png


:oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops:
 
Upvote 0

aeric

Expert
Licensed User
Longtime User
Of course such function doesn't exist in B4A or else you can already use it.

With B4XPages, I can create the function.

Note: Only valid for String variables.

B4X:
Sub Class_Globals
    Private Root As B4XView
    'Private xui As XUI
    Private varmaps As Map
    Private gs_appver As String = "2312xx"       'ignore
    Private gs_appname As String = "App name"    'ignore
End Sub

Public Sub Initialize
'    B4XPages.GetManager.LogEvents = True
    varmaps.Initialize
End Sub

Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
    GenerateVarMaps
End Sub

Sub ShowAll
    ToastMessageShow(varval("gs_appver"), True)
    ToastMessageShow(varval("gs_appname"), True)
End Sub

Private Sub varval (key As String) As String
    Return varmaps.Get(key)
End Sub

Private Sub GenerateVarMaps
    Dim strMe As String = Me
    Dim Fields() As String = Regex.Split2(",", Regex.MULTILINE, strMe.SubString2(1, strMe.Length-1))
    
    For Each Field As String In Fields
        Dim ExcludeList As List = Array("b4xcollections", "b4xpages", "main", "root", "starter", "xui")
        If Field.Contains("=") Then
            Dim KeyValue() As String = Regex.Split("=", Field)
            KeyValue(0) = KeyValue(0).Trim
            KeyValue(1) = KeyValue(1).Trim
            If ExcludeList.IndexOf(KeyValue(0)) < 0 Then
                varmaps.Put(KeyValue(0), KeyValue(1))
            End If
        End If
    Next
End Sub

Private Sub Button1_Click
    ShowAll
End Sub
 

Attachments

  • Var.zip
    12.6 KB · Views: 22
Upvote 0

aeric

Expert
Licensed User
Longtime User
From below similar threads,
This one may work for Int variables and Default template.

 
Upvote 0

ilan

Expert
Licensed User
Longtime User
Of course such function doesn't exist in B4A or else you can already use it.

With B4XPages, I can create the function.

Note: Only valid for String variables.

B4X:
Sub Class_Globals
    Private Root As B4XView
    'Private xui As XUI
    Private varmaps As Map
    Private gs_appver As String = "2312xx"       'ignore
    Private gs_appname As String = "App name"    'ignore
End Sub

Public Sub Initialize
'    B4XPages.GetManager.LogEvents = True
    varmaps.Initialize
End Sub

Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
    GenerateVarMaps
End Sub

Sub ShowAll
    ToastMessageShow(varval("gs_appver"), True)
    ToastMessageShow(varval("gs_appname"), True)
End Sub

Private Sub varval (key As String) As String
    Return varmaps.Get(key)
End Sub

Private Sub GenerateVarMaps
    Dim strMe As String = Me
    Dim Fields() As String = Regex.Split2(",", Regex.MULTILINE, strMe.SubString2(1, strMe.Length-1))
   
    For Each Field As String In Fields
        Dim ExcludeList As List = Array("b4xcollections", "b4xpages", "main", "root", "starter", "xui")
        If Field.Contains("=") Then
            Dim KeyValue() As String = Regex.Split("=", Field)
            KeyValue(0) = KeyValue(0).Trim
            KeyValue(1) = KeyValue(1).Trim
            If ExcludeList.IndexOf(KeyValue(0)) < 0 Then
                varmaps.Put(KeyValue(0), KeyValue(1))
            End If
        End If
    Next
End Sub

Private Sub Button1_Click
    ShowAll
End Sub
But why?
Why not just work with variables?
 
Upvote 0

aeric

Expert
Licensed User
Longtime User
If you want to work with B4X or non-UI just manually add all variables into a Map. 😅

B4X:
Sub Process_Globals
    Private varmaps As Map
    Private gs_appver As String = "2312xx"
    Private gs_appname As String = "App name"
    Private gs_appbuild As Float = 2.5
End Sub

Sub AppStart (Args() As String)
    varmaps.Initialize
    varmaps.Put("gs_appver", gs_appver)
    varmaps.Put("gs_appname", gs_appname)
    varmaps.Put("gs_appbuild", gs_appbuild)
    
    Log(VarVal("gs_appver"))
    Log(VarVal("gs_appname"))
    Log(VarVal("gs_appbuild"))
End Sub


Sub VarVal (Key As String) As Object
    Return varmaps.Get(Key)
End Sub
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
@aeric
Your solution works also with other simple types: Int Float Double Boolean etc.
A very interesting trick. How did you discover it?

@ilan
Perhaps the OP is working on some kind of scripting and wants to ask the user to enter a variable name.
Then use that string to retrieve the value.

@LucaMs (4 more posts to 30,000. You can do it before 2024!)
I believe you liked the solution in the link referenced in #5 above.
https://www.b4x.com/android/forum/t...he-name-of-a-variable-array.58197/post-366504
 
Last edited:
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
You can also use CallSub(Me, "GET_" & varname) to convert a string to a value
B4X:
Sub GET_gs_appname As String
    Return gs_appname
End Sub
 
Upvote 0

hung

Active Member
Licensed User
Longtime User
Of course such function doesn't exist in B4A or else you can already use it.

With B4XPages, I can create the function.

Note: Only valid for String variables.

B4X:
Sub Class_Globals
    Private Root As B4XView
    'Private xui As XUI
    Private varmaps As Map
    Private gs_appver As String = "2312xx"       'ignore
    Private gs_appname As String = "App name"    'ignore
End Sub

Public Sub Initialize
'    B4XPages.GetManager.LogEvents = True
    varmaps.Initialize
End Sub

Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
    GenerateVarMaps
End Sub

Sub ShowAll
    ToastMessageShow(varval("gs_appver"), True)
    ToastMessageShow(varval("gs_appname"), True)
End Sub

Private Sub varval (key As String) As String
    Return varmaps.Get(key)
End Sub

Private Sub GenerateVarMaps
    Dim strMe As String = Me
    Dim Fields() As String = Regex.Split2(",", Regex.MULTILINE, strMe.SubString2(1, strMe.Length-1))
   
    For Each Field As String In Fields
        Dim ExcludeList As List = Array("b4xcollections", "b4xpages", "main", "root", "starter", "xui")
        If Field.Contains("=") Then
            Dim KeyValue() As String = Regex.Split("=", Field)
            KeyValue(0) = KeyValue(0).Trim
            KeyValue(1) = KeyValue(1).Trim
            If ExcludeList.IndexOf(KeyValue(0)) < 0 Then
                varmaps.Put(KeyValue(0), KeyValue(1))
            End If
        End If
    Next
End Sub

Private Sub Button1_Click
    ShowAll
End Sub
This works for sure. But unfortunately changing all variables into map means rewrite everything. So need other solutions.
 
Upvote 0

hung

Active Member
Licensed User
Longtime User
You can also use CallSub(Me, "GET_" & varname) to convert a string to a value
B4X:
Sub GET_gs_appname As String
    Return gs_appname
End Sub
This is close but that refers to putting a lot of Select Case into a lot of functions.
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
why don't you use the variable directly?

B4X:
Sub Process_Globals
    Private gs_appver As String = "2312xx"
    Private gs_appname As String = "App name"
End sub

Sub Showall()
    ToastMessageShow(gs_appver, True)
    ToastMessageShow(gs_appname, True)
End sub
 
Upvote 0

aeric

Expert
Licensed User
Longtime User
changing all variables into map means rewrite everything

I don't understand why you said so.

What are required:
1. Add the GenerateVarMaps sub into your B4XPage
2. Declare varmaps as Map
3. Access it

If you mean you need to convert your B4A app (Default template) to using B4XPages, then there are indeed some works.
 
Upvote 0

hung

Active Member
Licensed User
Longtime User
Thank you all for the responses, especially @aeric.

Here is the use case.

I have an app with webview allowing javascript interface CallSub. The app has many variables for different purposes. I want to allow the webpage (somewhere in internet) loaded inside the webview ( webview.loadurl() ) to callback via javascript interface to get the variable value then submit webpage hence to webserver.

If we write one function for a variable that will mean many callback functions that increases apk size a lot. Or I could use one callback function with many Select Case to return variable values by something like case "gs_appver" return gs_appver. But it is inflexible and every time when we need one more variable, both app and webpage need to update program.

or, considering the app as a client browser, the online webpage as the url somewhere in internet. The idea is to allow webpage get value of any variables stored inside the app. The app is not going to change for next one to two years but our webpage could change at any minutes to get what we want.
 
Upvote 0

aeric

Expert
Licensed User
Longtime User
Thank you all for the responses, especially @aeric.

Here is the use case.

I have an app with webview allowing javascript interface CallSub. The app has many variables for different purposes. I want to allow the webpage (somewhere in internet) loaded inside the webview ( webview.loadurl() ) to callback via javascript interface to get the variable value then submit webpage hence to webserver.

If we write one function for a variable that will mean many callback functions that increases apk size a lot. Or I could use one callback function with many Select Case to return variable values by something like case "gs_appver" return gs_appver. But it is inflexible and every time when we need one more variable, both app and webpage need to update program.

or, considering the app as a client browser, the online webpage as the url somewhere in internet. The idea is to allow webpage get value of any variables stored inside the app. The app is not going to change for next one to two years but our webpage could change at any minutes to get what we want.
Maybe there is a better way to rewrite the Select Case.
 
Upvote 0

hung

Active Member
Licensed User
Longtime User
@aeric
Your solution works also with other simple types: Int Float Double Boolean etc.
A very interesting trick. How did you discover it?

@ilan
Perhaps the OP is working on some kind of scripting and wants to ask the user to enter a variable name.
Then use that string to retrieve the value.

@LucaMs (4 more posts to 30,000. You can do it before 2024!)
I believe you liked the solution in the link referenced in #5 above.
https://www.b4x.com/android/forum/t...he-name-of-a-variable-array.58197/post-366504

JordiCP's reply on #8 might be solution for me. I will try that out. Thank you, William.
 
Upvote 0

hung

Active Member
Licensed User
Longtime User

JordiCP's reply on #8 might be solution for me. I will try that out. Thank you, William.
Excellent! This works well. Thank you all for the insight. And to JordiCP who might not know this yet.
In b4x,
B4X:
...
wve.addJavascriptInterface(wv_home, "b4xcallback")
wv_home.Loadurl("....abc.html")
...
' get system variables, e.g. gs_appver
Sub getsysvar(argvar As String) As String
    Dim rslt As String
    Dim jo As JavaObject
    jo.InitializeContext
    jo = jo.InitializeNewInstance(Application.PackageName & ".main",Null)
    rslt = jo.GetField("_" & argvar)
    Return rslt
End Sub

In abc.html
B4X:
<button onclick="document.getElementById('idfld').value=b4xcallback.CallSub('getsysvar', false, 'gs_appver');">Get Appver</button>
<button onclick="document.getElementById('idfld').value=b4xcallback.CallSub('getsysvar', false, 'str_hellothere');">Get Hello There</button>
 
Upvote 0
Top