Italian Recupero dati da B4XOrderedMap

Xela

Member
Licensed User
Salve a tutti
Da un po' di tempo sto riscontrando problemi con il recupero di dati da una Map. https://www.b4x.com/android/forum/threads/map-collection-the-most-useful-collection.60304/
Come da prassi (mia) ho lasciato "riposare" il problema, di tanto in tanto lo riprendevo in mano pensando che il tempo mi avrebbe "suggerito" la soluzione ma niente. Non riesco a trovare una soluzione.
Ora ho deciso di uscirne...... spero.
Qui allego un piccolo progetto.
Vorrei capire perchè al map.Get(Key) mi viene ritornata sempre l'ultima "riga" della map e non la "riga" richiesta.

M
Y01-Rossi-0
Y02-Bianchi-1
Z01-Verdi-5
Z04-Gialli-0
X03-Viola-0

Map.Get:
Y01
X03-Viola-0
Y02
X03-Viola-0
Z01
X03-Viola-0
Z04
X03-Viola-0
X03
X03-Viola-0

Grazie per ogni vostro suggerimento
 

Attachments

  • TestMap1.zip
    10.1 KB · Views: 141

sirjo66

Well-Known Member
Licensed User
Longtime User
ho aggiornato B4A all'ultima versione
ho scaricato il tuo file Zip
l'ho aperto sul desktop (si è creato la cartella B4A sul desktop)
ho caricato il progetto
premo F5 per mandarlo in esecuzione ma esce questo errore

b4x_error.png
 

Star-Dust

Expert
Licensed User
Longtime User
Sono i comandi commentati che trovi all'inizio della pagina. Lui fa una copia dei dati da una cartella all'altra, cartelle che tu non hai nel tuo PC.

Vedi di eliminare quei comandi e dovrebbe compilarlo
 

LucaMs

Expert
Licensed User
Longtime User
ma esce questo errore
Il motivo è che quello è un progetto B4XPages ed è stato esportato male, usando il modo "classico", ovvero tramite il menu File-Export As Zip (oppure comprimendolo direttamente), mentre si DEVE usare:
B4X:
'Ctrl + click to export as zip: ide://run?File=%B4X%\Zipper.jar&Args=Project.zip
commento che sta nella B4XMainPage.

Per poter lanciare ugualmente un progetto esportato male in quel modo, si può commentare la riga:
B4X:
#CustomBuildAction: folders ready, %WINDIR%\System32\Robocopy.exe,"..\..\Shared Files" "..\Files"
sempre nella B4XMainPage, nella Region Shared Files.


Purtroppo è un errore che fanno molti.
 

LucaMs

Expert
Licensed User
Longtime User
Vorrei capire perchè al map.Get(Key) mi viene ritornata sempre l'ultima "riga" della map e non la "riga" richiesta.
Perché ogni volta cambi i valori di
Dim sRow As PieList
e poi la inserisci nella map ma sRow è sempre lo stesso oggetto; devi creare ogni volta un oggetto diverso di tipo PieList:
B4X:
    Dim sRow0 As PieList
    sRow0.Initialize

    sRow0.sCodPie = "Y01"
    sRow.0sDesPie = "Rossi"
    sRow.0nQta3mn = 0

    MapPie.Put("Y01",sRow0)
    Log(sRow.sCodPie & "-" & sRow.sDesPie & "-" & sRow.nQta3mn)



    Dim sRow1 As PieList
    sRow1.Initialize
    sRow1.sCodPie = "Y02"
    sRow1.sDesPie = "Bianchi"
    sRow1.nQta3mn = 1

    MapPie.Put("Y02",sRow1)
    Log(sRow1.sCodPie & "-" & sRow1.sDesPie & "-" & sRow1.nQta3mn)

(ovviamente non ti conviene farlo come ho scritto direttamente qui, userai un ciclo.


P.S. certo che visto (adesso) che usi Y01, Y02, ovvero inizi con 1, avrei "dovuto" farlo anch'io, per coerenza, ovvero sRow1 e sRow2, anziché sRow0 e sRow1 😁
 
Last edited:

Xela

Member
Licensed User
Grazie LucaMs

Alla fine sei sempre tu che mi dai le dritte migliori. Ho provato e funziona.

Ora ti chiedo:
C'è un modo per "distruggere/uccidere" le molteplici sRow-n che non mi servono più?

Grazie
 

LucaMs

Expert
Licensed User
Longtime User
Grazie LucaMs

Alla fine sei sempre tu che mi dai le dritte migliori. Ho provato e funziona.

Ora ti chiedo:
C'è un modo per "distruggere/uccidere" le molteplici sRow-n che non mi servono più?

Grazie
Puoi provare sparandogli, ma solo se il display non ti serve più 😄.

Gli oggetti che non vengono più utilizzati, per i quali non ci sono variabili che li "puntano" (riferimenti ancora utilizzati) vengono "uccisi" dal S.O. "a tempo debito" (= quando gli pare, quando fa pulizia (garbage collector), quando gli serva spazio).

Non preoccupartene.

Non so se quello fosse solo un esempio; eventualmente forse ti converrebbe leggere quei dati da file (da db sarebbe meglio ancora) per caricare la Map.
 

Xela

Member
Licensed User
Un'altra cosa (non vorrei più sentirmi un "tordo")

'Ctrl + click to export as zip: ide://run?File=%B4X%\Zipper.jar&Args=Project.zip

Come funziona questo commando?

Io sono andato su File e tenendo premuto Ctrl ho premuto su Esporta come Zip.
ma mi sembra di capire che non è questa la giusta procedura.

Ri-grazie
 

LucaMs

Expert
Licensed User
Longtime User
Un'altra cosa (non vorrei più sentirmi un "tordo")



Come funziona questo commando?

Io sono andato su File e tenendo premuto Ctrl ho premuto su Esporta come Zip.
ma mi sembra di capire che non è questa la giusta procedura.

Ri-grazie
Devi tenere premuto CTRL, come hai fatto, ma fare click sul commento stesso.


Ri-grazie
Di niente!
 

Xela

Member
Licensed User
Non so se quello fosse solo un esempio; eventualmente forse ti converrebbe leggere quei dati da file (da db sarebbe meglio ancora) per caricare la Map.

Si era solo un esempio.
I dati me li vado a prendere da un db e, con una serie di query, vado ad alimentare i campi che mi servono nelle type (Row) contenuta nella Map.

In breve: sto cercando di replicare quello che in vbnet ho fatto con un Array di Structure.

E' vero che in VBNet per modificare il valore di un campo uso: Array(i).nomecampo = X. Mentre con Map e Type le cose mi sembrano leggermente + complicate.

Se hai dei suggerimenti..... ben vengano
 

LucaMs

Expert
Licensed User
Longtime User
E' vero che in VBNet per modificare il valore di un campo uso: Array(i).nomecampo = X. Mentre con Map e Type le cose mi sembrano leggermente + complicate.
B4X:
Type typPie(sCodPie As String, sDesPie As String, nQta3mn As Double)


Private Sub FillPiesMap(mapPies As Map)
    Dim RS As ResultSet
    Dim Query As String = "SELECT * FROM Pie"
    RS = mDB.ExecQuery(Query)
    Dim CodPie As String
    Do While RS.NextRow
        CodPie = RS.GetString("CodPie")
        Dim Pie As typPie
        Pie = CreatetypPie(CodPie, RS.GetString("DesPie"), RS.GetDouble("Qta"))
        mapPies.Put(CodPie, Pie)
    Loop
    RS.Close
End Sub

Public Sub CreatetypPie (sCodPie As String, sDesPie As String, nQta3mn As Double) As typPie
    Dim t1 As typPie
    t1.Initialize
    t1.sCodPie = sCodPie
    t1.sDesPie = sDesPie
    t1.nQta3mn = nQta3mn
    Return t1
End Sub
B4X:
Log(mapPies.Get("Y01").As(typPie).sDesPie)



[Tutto non testato, ovviamente]
 
Last edited:

Xela

Member
Licensed User
B4X:
Type typPie(sCodPie As String, sDesPie As String, nQta3mn As Double)


Private Sub FillPiesMap(mapPies As Map)
    Dim RS As ResultSet
    Dim Query As String = "SELECT * FROM Pie"
    RS = mDB.ExecQuery(Query)
    Dim CodPie As String
    Do While RS.NextRow
        CodPie = RS.GetString("CodPie")
        Dim Pie As typPie
        Pie = CreatetypPie(CodPie, RS.GetString("DesPie"), RS.GetDouble("Qta"))
        mapPies.Put(CodPie, Pie)
    Loop
    RS.Close
End Sub

Public Sub CreatetypPie (sCodPie As String, sDesPie As String, nQta3mn As Double) As typPie
    Dim t1 As typPie
    t1.Initialize
    t1.sCodPie = sCodPie
    t1.sDesPie = sDesPie
    t1.nQta3mn = nQta3mn
    Return t1
End Sub

Grazie. Buon suggerimento.

B4X:
Log(mapPies.Get("Y01").As(typPie).sDesPie)

Questa non l'ho capita!!!!!
O almeno a me non funziona il ".As(typPie).sDesPie"

per apportare una modifica a un campo uso questo ciclo:
B4X:
For row = 0 To result.Rows.Size -1
   Dim Record() As Object = result.Rows.Get(row)
   For Each sKeyPie As String In MapPieList.Keys
      If sKeyPie = Record(0) Then 
         Dim sPieRow As PieList
         sPieRow.Initialize
         sPieRow = MapPieList.Get(sKeyPie)
         sPieRow.nQta3mn = Record(1)
         MapPieList.Put(sKeyPie, sPieRow)
      End If
   Next
Next

C'è di meglio?
Grazie
 

LucaMs

Expert
Licensed User
Longtime User
C'è di meglio?
Grazie
Penso di sì; devo guardare meglio (e anche vedere quali oggetti db utilizzi), ma puoi ottenere direttamente l'elemento della Map che vuoi modifcare, senza scorrerla tutta.
Tra non molto lo farò.

Questa non l'ho capita!!!!!
O almeno a me non funziona il ".As(typPie).sDesPie"
E' una novità alla quale anch'io non sono ancora abituato; per questo avevo scritto anche:
[Tutto non testato, ovviamente]
 

LucaMs

Expert
Licensed User
Longtime User
Questa non l'ho capita!!!!!
O almeno a me non funziona il ".As(typPie).sDesPie"
E' una novità alla quale anch'io non sono ancora abituato; per questo avevo scritto anche:
[Tutto non testato, ovviamente]
Veramente a me ha funzionato, ho appena provato (non ho caricato dati da db ma comunque quel .As(typPie)... ha funzionato bene).
 

LucaMs

Expert
Licensed User
Longtime User
Questo è il tuo codice sorgente (ho dovuto scriverlo con quei commenti per come hai scritto la domanda):
B4X:
' per apportare una modifica a un campo uso questo ciclo: 

For row = 0 To result.Rows.Size -1
   Dim Record() As Object = result.Rows.Get(row)
   For Each sKeyPie As String In MapPieList.Keys
      If sKeyPie = Record(0) Then
         Dim sPieRow As PieList
         sPieRow.Initialize
         sPieRow = MapPieList.Get(sKeyPie)
         sPieRow.nQta3mn = Record(1)
         MapPieList.Put(sKeyPie, sPieRow)
      End If
   Next
Next

'C'è di meglio?
'Grazie

Ora, supponendo che tu nell'Array di oggetti Record legga bene da DB i 3 dati (con una Select per i soli record modificati, immagino), non serve che tu scorra tutta la MapPieList, come dicevo.

clsTest:
Sub Class_Globals
    Type typPie(sCodPie As String, sDesPie As String, nQta3mn As Double)
    Private mPies As Map
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
    mPies.Initialize
    FillPiesMapTestNoDB(mPies)
End Sub

Private Sub FillPiesMapTestNoDB(mapPies As Map)
    mapPies.Clear
    
    Dim CodPie As String
    For r = 1 To 10
        CodPie = "CodPie_" & r
        Dim Pie As typPie
        Pie = CreatetypPie(CodPie, "DesPie_" & r, r)
        mapPies.Put(CodPie, Pie)
    Next

    Log("Valori iniziali")   
    Log(mapPies.Get("CodPie_2").As(typPie).sCodPie)
    Log(mapPies.Get("CodPie_2").As(typPie).sDesPie)
    Log(mapPies.Get("CodPie_2").As(typPie).nQta3mn)
    
    Dim Record() As Object = Array As Object("CodPie_2", "DesPie_2", 2)
    Dim CodPie As String = Record(0)
    If mapPies.ContainsKey(CodPie) Then
        Dim Pie As typPie = mapPies.Get(CodPie)
        Pie.nQta3mn = Pie.nQta3mn + 123
    End If
        
    Log("Quantità aggiornata")
    Log(mapPies.Get("CodPie_2").As(typPie).sCodPie)
    Log(mapPies.Get("CodPie_2").As(typPie).sDesPie)
    Log(mapPies.Get("CodPie_2").As(typPie).nQta3mn)
End Sub

Public Sub CreatetypPie (sCodPie As String, sDesPie As String, nQta3mn As Double) As typPie
    Dim t1 As typPie
    t1.Initialize
    t1.sCodPie = sCodPie
    t1.sDesPie = sDesPie
    t1.nQta3mn = nQta3mn
    Return t1
End Sub
 

Xela

Member
Licensed User
B4X:
Dim Record() As Object = Array As Object("CodPie_2", "DesPie_2", 2)
Dim CodPie As String = Record(0)
If mapPies.ContainsKey(CodPie) Then
Dim Pie As typPie = mapPies.Get(CodPie)
Pie.nQta3mn = Pie.nQta3mn + 123
End If
Grazie LucaMS
Questa è la parte più interessante ed è quella che sfrutterò

B4X:
Log("Quantità aggiornata") 
Log(mapPies.Get("CodPie_2").As(typPie).sCodPie) 
Log(mapPies.Get("CodPie_2").As(typPie).sDesPie) 
Log(mapPies.Get("CodPie_2").As(typPie).nQta3mn) End Sub
questa invece proprio non mi va.
il "(mapPies.Get("CodPie_2")." non mi da la possibilità di inserire "As(........"
forse perchè io uso B4XOrderedMap e non Map
o forse perchè mi manca qualcosa.
 
Top