Italian Doppie Virgolette

diresc

Member
Licensed User
Longtime User
Ciao a tutti
Prelevo file .csv da webserver
leggo e li inserisco in list array
poi da list array li inserisco in TABELLA le colonne sono tutti di tipo stringa
il problema è che nel array mi scrivono un valore testo ma tra virgolette es."ricetta1"
nella vista B4XTable1 non visualzza nessun valore(vuoto) come risolvo con replace ma come o?

test:
        For I = 1 To Rows.Length - 1               
                    Dim Values() As String = Regex.Split(",", Rows(I))               
                    Try                                           
                        datax.AddAll(Array(Values))'TUTTI
                    Catch
                        Log(LastException)
                    End Try       
                    ProgressBar1.progress=i /lunghezza*100
                    INDICAZIONE.Text=SERVIZIO.tr17(SERVIZIO.Vx14)& " " &SERVIZIO.tr18(SERVIZIO.Vx14) & " " &  ProgressBar1.progress & " %"           
                    Sleep(0)
                Next
                
                B4XTable1.SetData(datax)
 

sirjo66

Well-Known Member
Licensed User
Longtime User
Nei file CSV, se all'interno di una stringa c'è una virgola, e tu fai Regex.Split(",", Rows(I)) capisci benissimo che quella virgola viene interpretata come un separatore di campo anzichè una virgola dentro nel testo, per cui lo standard CSV prevede che se la stringa contiene una virgola devi racchiuderla tra virgolette.
E se per caso dentro a questa stringa ci dovessere essere le virgolette, si devono raddoppiare
Deduco quindi che a te non è sufficiente utilizzare il Regex.Split(",", Rows(I)) per dividere i vari campi ma devi utilizzare un parser vero e proprio che riesca a decifrare tutto correttamente.
Ce l'avevo da qualche parte, è una regex un po' complicata ma funziona, devo vedere se riesco a trovarla

Nel frattempo dai un occhio qui: https://www.b4x.com/android/forum/threads/b4x-csvparser-csv-parser-and-generator.110901/#content

Edit: prova con queste due:
B4X:
(?:,|\n|^)("(?:(?:"")*[^"]*)*"|[^",\n]*|(?:\n|$))

^(?:([^",]+))?(?=,)|(?<=,)(?:[^",]*)?(?=[,$])|((?<=")[^"(\s*,)][^"]*(?="))|(?<=")(?=")|(?<=,)(?:[^,"])*(?=$)
 
Last edited:

Sagenut

Expert
Licensed User
Longtime User
Prova questo
*** EDIT ***
Eliminato esempio errato per non creare confusione
 
Last edited:

diresc

Member
Licensed User
Longtime User
Ecco il problema intanto grazie per le risposte
quando carico il csv che viene scritto da un plc se i valori sono int ,data, orario tutto ok ma quando alcuni valori sono String il plc mi crea Es. "ricetta 1" & spazi per 255 volte
dunque non visualizzo il dato nella colonna B4XTable1 o fatto una prova a riempire spazi con "w" e mi compare
la stringa letta dal csv pieno di "w" a posto degli spazi
riga csv è composta così:
15601,01/18/2012,02:58:26,"RICETTA A" spazi*255 ,120, 50, 70, 60, 120 , 20,
con Replace(" ", $""$) riesco a cancellare spazi e a visualizzare i dati ma "ricetta A" diventa "ricettaA" che faccio?
 

Sagenut

Expert
Licensed User
Longtime User
Sì, per eliminare le doppie virgolette dovrebbe funzionare, però la questione sollevata da @sirjo66 è interessante e complicata.
Se hai un testo come:

"ciao ciao",
"credimi, è un problema"

lo split con la virgola come separatore, suddividerà anche la seconda riga:

"credimi,
è un problema"
Mi ero perso un pezzo, elimino il consiglio errato.
 

LucaMs

Expert
Licensed User
Longtime User
Questa funziona (pattern generato da ChatGPT):

B4X:
Private Sub Split(Text As String) As List
    Dim lstResult As List
    lstResult.Initialize
 
    Dim Matcher1 As Matcher
    Dim Pattern As String
    Pattern = $"\"([^\"]*?)\"|([^\",]+)"$
    Matcher1 = Regex.Matcher(Pattern, Text)
    Dim Block As String
    Do While Matcher1.Find
        Block = Matcher1.Match.Trim.Replace("""", "")
        lstResult.Add(Block)
    Loop
 
    Return lstResult
End Sub

Per semplicità gli ho fatto restituire una List anziché un array (non esiste il comando Redim, in B4J).
Si può modificare, facendogli prima contare le "occorrenze" e poi dimesionare l'array che dovrebbe restituire (e riempirlo, ovviamente).

(progetto di prova allegato)
 

Attachments

  • Split.zip
    8.6 KB · Views: 85
Last edited:

LucaMs

Expert
Licensed User
Longtime User
Per semplicità gli ho fatto restituire una List anziché un array (non esiste il comando Redim, in B4J).
Si può modificare, facendogli prima contare le "occorrenze" e poi dimesionare l'array che dovrebbe restituire (e riempirlo, ovviamente).
B4X:
Private Sub SplitAsList(Text As String) As List
    Dim lstResult As List
    lstResult.Initialize
    
    Dim Matcher1 As Matcher
    Dim Pattern As String
    Pattern = $"\"([^\"]*?)\"|([^\",]+)"$
    Matcher1 = Regex.Matcher(Pattern, Text)
    Dim Block As String
    Do While Matcher1.Find
        Block = Matcher1.Match.Trim.Replace("""", "")
        lstResult.Add(Block)
    Loop
    
    Return lstResult
End Sub

Private Sub SplitAsArray(Text As String) As String()
    Dim Matcher1 As Matcher
    Dim Pattern As String
    Pattern = $"\"([^\"]*?)\"|([^\",]+)"$

    Dim Block As String
    
    Dim Counter As Int
    Matcher1 = Regex.Matcher(Pattern, Text)
    Do While Matcher1.Find
        Counter = Counter + 1
        Block = Matcher1.Match
    Loop
    Dim Result(Counter) As String

    Matcher1 = Regex.Matcher(Pattern, Text)
    Dim I As Int = 0
    Do While Matcher1.Find
        Block = Matcher1.Match.Trim.Replace("""", "")
        Result(I) = Block
        I = I + 1
    Loop
    
    Return Result
End Sub
 

udg

Expert
Licensed User
Longtime User
Scrivo da smartphone (cellulare potrebbe suonare ambiguo..hehe).
Se vuoi eliminare solo i 255 spazi consecutivi potresti provare a mettere come stringa da cercare una sequenza di 5 spazi o ogni multiplo per cui 255 risulti divisibile.
 

diresc

Member
Licensed User
Longtime User
Ciao LucaMs come dovrei usare le tue funzioni con il mio codice?

For I = 1 To Rows.Length - 1
Dim Values() As String = Regex.Split(",", Rows(I))
Try
datax.AddAll(Array(Values))'TUTTI
Catch
Log(LastException)
End Try
ProgressBar1.progress=i /lunghezza*100
INDICAZIONE.Text=SERVIZIO.tr17(SERVIZIO.Vx14)& " " &SERVIZIO.tr18(SERVIZIO.Vx14) & " " & ProgressBar1.progress & " %"
Sleep(0)
Next

B4XTable1.SetData(datax)
 

diresc

Member
Licensed User
Longtime User
Dimenticavo io uso :
datax.AddAll(Array(Values))
perchè le colonne possono essere da 1 a 30 o di più
 

diresc

Member
Licensed User
Longtime User
Se io scrivessi:
datax.Add(Array(Values(0).trim, Values(1).trim, Values(2).trim,Values(3).Trim, Values(4).Trim, Values(5).Trim, Values(6).Trim, Values(7).Trim))'SINGOLI
funziona ma non sò quante colonne ci sono
 

diresc

Member
Licensed User
Longtime User
è giusto o sbagliato? lui funziona si accettano suggerimenti:
    Dim result As String = Job.GetString
                Dim Rows() As String = Regex.Split(CRLF, result)
                ' Aggiungo le intestazioni alla griglia
                Dim Headers() As String = Regex.Split(",", Rows(0))           
                Dim I As Int
                For I = 0 To Headers.Length - 1               
                    B4XTable1.AddColumn(Headers(I), B4XTable1.COLUMN_TYPE_TEXT)               
                Next
                    ' Aggiungo righe alla griglia   
                For I = 1 To Rows.Length - 1               
                    Dim lstBlocks As List
                    lstBlocks.Initialize               
                    Dim Values() As String = Regex.Split(",", Rows(I))
                    Try 'non mi piace'
                    
                        For ix=0 To  Values.Length-1                   
                            lstBlocks.Add(Values(ix).trim)'elinmino spazi
                        Next
                        
                        datax.Add(lstBlocks)'TUTTI in datax lista                   
                    Catch
                        Log(LastException)
                    End Try           
                    ProgressBar1.progress=i /lunghezza*100
                    INDICAZIONE.Text=SERVIZIO.tr17(SERVIZIO.Vx14)& " " &SERVIZIO.tr18(SERVIZIO.Vx14) & " " &  ProgressBar1.progress & " %"           
                    Sleep(0)
                                    
                Next
                'fine
                'carico il tutto in  B4XTable1

        B4XTable1.SetData(datax)
 

sirjo66

Well-Known Member
Licensed User
Longtime User
ci puoi dare un riga di dati in modo che possiamo fare delle prove ??
 
Top