Italian esportare dati

Xfood

Expert
Licensed User
ciao a tutti
ho un problema, non riesco ad esportare i dati da un db


allego il codice

'esporta i dati in formato csv
Sub lblExp_Click
lblExp.Enabled = False 'evita click multipli
lblImp.Visible = False
lblExp.Visible= False
'APB1.Visible = True
lblRiepilogo.Text = lblRiepilogo.Text & CRLF & "*** Export: inizio procedura ***"

Dim mlist As List
mlist.Initialize
mlist=DBUtils.ExecuteMemoryTable(DBData.SQL1,"SELECT * FROM anagrafica",Null,0)
Dim su As StringUtils
Log("=========================================")
Log("Export Inizio")

' questa la riga che mi da errore
su.SaveCSV(Starter.rp.GetSafeDirDefaultExternal(""),"archivio.csv","|",mlist)



Log("Export finito")
lblRiepilogo.Text = lblRiepilogo.Text & CRLF & "*** Export: procedura terminata ***"

lblExp.Enabled = True
lblImp.Visible = True
lblExp.Visible= True
End Sub



quando tento di salvarli mi da questo errore


vorrei se possibile salvare questo file nella cartella di default download
Grazie a chi mi dara' una mano
upload_2019-12-22_0-23-40.png
 

udg

Expert
Licensed User
Longtime User
Sicuro che il quarto paramentro di SaveCSV rispetti la definizione?
Table - A List with arrays of strings as items. Each array represents a row. All arrays should be of the same length.

mlist.Initialize - andrebbe eliminato
 

Xfood

Expert
Licensed User
Sicuro che il quarto paramentro di SaveCSV rispetti la definizione?
Table - A List with arrays of strings as items. Each array represents a row. All arrays should be of the same length.

mlist.Initialize - andrebbe eliminato

Grazie per la risposta, oggi appena rientro dopo pranzo provo. (SaveCSV (Dir As String, FileName As String, SeparatorChar As Char, Table As List)
non e' corretto cosi su.SaveCSV(Starter.rp.GetSafeDirDefaultExternal(""),"archivio.csv","|",mlist)
se volessi salvare il dato nella cartella di default DOWNLOAD come faccia ad intercettarla?
ho prese l'esempio di codice da qui:
https://www.b4x.com/android/forum/threads/sqllite-to-csv-and-dbutils.55487/#content

p.s. vorrei finalmente completare il mio primo progetto, sembra un parto, lo lasciato e ripreso mille volte permancanza di tempo.
Grazie mille per il tempo che mi dedicate
 
Last edited:

udg

Expert
Licensed User
Longtime User
Prova il suggerimento di Erel:
Log(File.ReadString(File.DirInternal,"marker_data.csv")) ma riferito a mlist. Un possibile problema potrebbe derivare da dati Null.
Potresti adattare una sintassi tipo:
B4X:
SELECT  ID, NAME, AGE, ADDRESS, SALARY
       FROM COMPANY
       WHERE SALARY IS NOT NULL;
per evitare righe che contengano campi a valore Null oppure definire tutti i campi come NOT NULL e quindi avere una tabella di partenza necessariamente "pulita".

ps: ho controllato e ExecuteMemoryTable ritorna il tipo corretto di dati (list of strings' arrays) per SaveCSV.

pps: https://www.b4x.com/android/forum/t...getsafedirdefaultexternal.110020/#post-686956
 
Last edited:

Xfood

Expert
Licensed User
purtroppo non riesco ad estrarre i dati con SaveCsv()
ho riprovato cosi:
Dim List1 As List
Dim su As StringUtils
List1=DBUtils.ExecuteMemoryTable(DBData.SQL1,"SELECT * FROM anagrafica",Null,0)
su.SaveCSV(File.DirRootExternal, "Download/archivio.csv", ",",List1)
dove sbaglio..????
actsync_lblexp_click (java line: 461)
java.lang.NullPointerException: Attempt to invoke interface method 'int java.lang.CharSequence.length()' on a null object reference
ecc...


per quando riguarda l'accesso alla cartella di default DOWNLOAD ho risolto cosi:
File.DirRootExternal, "Download/archivio.csv"
Sub Activity_Resume
For Each permission As String In Array(rp.PERMISSION_READ_EXTERNAL_STORAGE,rp.PERMISSION_CAMERA,rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
rp.CheckAndRequest(permission)
Wait For Activity_PermissionResult (permission As String, Result As Boolean)
If Result = False Then
ToastMessageShow("No permission!", True)
Activity.Finish
Return
End If
Next
End Sub
il manifest e questo:
AddPermission("android.permission.WRITE_EXTERNAL_STORAGE")
 

udg

Expert
Licensed User
Longtime User
Sono stato poco chiaro. Intendevo dire di provare un log sulle righe ritornate da ExecuteMemoryMap, quindi PRIMA di passare a SaveCSV.
Il mio sospetto è che ci siano valori posti a Null e questi causino problemi con il parser che poi realizza il CSV da salvare.
Se questo fosse il caso, ti basterebbe sostituire i Null con stringa vuota
 

Xfood

Expert
Licensed User
Sono stato poco chiaro. Intendevo dire di provare un log sulle righe ritornate da ExecuteMemoryMap, quindi PRIMA di passare a SaveCSV.
Il mio sospetto è che ci siano valori posti a Null e questi causino problemi con il parser che poi realizza il CSV da salvare.
Se questo fosse il caso, ti basterebbe sostituire i Null con stringa vuota
Grazie, hai un esempio per scorrere la mia list1 e sostituire eventuali risultati null in "" per tutti i campi e tutte le righe?
 

Xfood

Expert
Licensed User
ho provato questo codice:
Dim su As StringUtils
Dim Data As List
Data.Initialize
Dim rs As ResultSet = DBData.SQL1.ExecQuery("SELECT * FROM anagrafica")
Do While rs.NextRow
Dim row(9) As Object
row(0) = rs.GetDouble("id")
row(1) = rs.GetString("codice")
row(2) = rs.GetString("descrizione")
row(3) = rs.GetString("prezzo")
row(4) = rs.GetString("costo")
row(5) = rs.GetString("reparto")
row(6) = rs.GetString("esistenza")
row(7) = rs.GetString("iva")
row(8) = rs.GetString("PzxC")
For i = 0 To 8
If row(i) = Null Then row(i) = ""
Next
Data.Add(row)
Loop
rs.Close
Log("lista processata")
su.SaveCSV(File.DirRootExternal, "Download/archivio.csv", ",",Data)

ma ho sempre questo errore:

lista processata
actsync_lblexp_click (java line: 489)
java.lang.ClassCastException: java.lang.Object[] cannot be cast to java.lang.String[]
at anywheresoftware.b4a.objects.StringUtils.SaveCSV2(StringUtils.java:107)
at anywheresoftware.b4a.objects.StringUtils.SaveCSV(StringUtils.java:100)
at FqGr.EasyScan.actsync._lblexp_click(actsync.java:489)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:196)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:180)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:176)
at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:80)
at android.view.View.performClick(View.java:6256)
at android.view.View$PerformClick.run(View.java:24701)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
 

udg

Expert
Licensed User
Longtime User
Potresti modificare (quindi avere una tua versione) ExecuteMemoryTable. Non ho controllato cosa ritorna GetString2 in caso di valore Null, magari non serve nemmeno
B4X:
Public Sub MyEMT(SQL As SQL, Query As String, StringArgs() As String, Limit As Int) As List
   Dim cur As ResultSet
   If StringArgs = Null Then
       Dim StringArgs(0) As String
   End If
   cur = SQL.ExecQuery2(Query, StringArgs)
   Dim table As List
   table.Initialize
   Do While cur.NextRow
       Dim values(cur.ColumnCount) As String
       For col = 0 To cur.ColumnCount - 1
           values(col) = cur.GetString2(col)
           if ((values(col) = null) or (values(col) ="null")) then values(col) = ""   '<-- unica modifica al codice originale
       Next
       table.Add(values)
       If Limit > 0 And table.Size >= Limit Then Exit
   Loop
   cur.Close
   Return table
End Sub

In alternativa, agendo sul risultato della query e conoscendo il numero di campi attesi, potresti avere qualcosa del genere:
B4X:
Dim List1 As List=DBUtils.ExecuteMemoryTable(DBData.SQL1,"SELECT * FROM anagrafica",Null,0)
for i = 0 to list.size-1
  Dim values(numero di campi ritornati dalla query) As String = list1.get(i)
  For col = 0 To numero di campi ritornati dalla query - 1
       if ((values(col) = null) or (values(col) ="null")) then values(col) = ""  
  Next
Next
 

Xfood

Expert
Licensed User
Potresti modificare (quindi avere una tua versione) ExecuteMemoryTable. Non ho controllato cosa ritorna GetString2 in caso di valore Null, magari non serve nemmeno
B4X:
Public Sub MyEMT(SQL As SQL, Query As String, StringArgs() As String, Limit As Int) As List
   Dim cur As ResultSet
   If StringArgs = Null Then
       Dim StringArgs(0) As String
   End If
   cur = SQL.ExecQuery2(Query, StringArgs)
   Dim table As List
   table.Initialize
   Do While cur.NextRow
       Dim values(cur.ColumnCount) As String
       For col = 0 To cur.ColumnCount - 1
           values(col) = cur.GetString2(col)
           if ((values(col) = null) or (values(col) ="null")) then values(col) = ""   '<-- unica modifica al codice originale
       Next
       table.Add(values)
       If Limit > 0 And table.Size >= Limit Then Exit
   Loop
   cur.Close
   Return table
End Sub

In alternativa, agendo sul risultato della query e conoscendo il numero di campi attesi, potresti avere qualcosa del genere:
B4X:
Dim List1 As List=DBUtils.ExecuteMemoryTable(DBData.SQL1,"SELECT * FROM anagrafica",Null,0)
for i = 0 to list.size-1
  Dim values(numero di campi ritornati dalla query) As String = list1.get(i)
  For col = 0 To numero di campi ritornati dalla query - 1
       if ((values(col) = null) or (values(col) ="null")) then values(col) = "" 
  Next
Next


ottimo funzionaaaaaaa ho utilizzato la prima tua funzione Public Sub MyEMT
grazie sei un Genio
 

udg

Expert
Licensed User
Longtime User
sei un Genio
Per aver aggiunto una riga? pensa a chi ha scritto tutto il resto! :D
 
Top