SPLIT mots en plusieurs parties encadrés par des doubles quotes

cs_PeD Messages postés 63 Date d'inscription vendredi 25 janvier 2002 Statut Membre Dernière intervention 13 avril 2013 - 17 août 2012 à 20:40
 Utilisateur anonyme - 26 sept. 2012 à 19:51
Bonsoir,

Pas beaucoup d'espoir d'avoir une solution ( fonction - bout de code ) toute faite, mais sait on jamais; un petit malin ....


Je n'ai pas de problème pour isoler chaque mot dans un tableau avec split quand la chaine de caractère est celle ci :

01 PARIS FRANCE EUROPE
02 BRUXELLES BELGIQUE EUROPE


mais quand une ligne contient ceci
03 "BUENOS AIRES" ARGENTINE "AMERIQUE DU SUD"

idéalement le mot(1) est 03, le mot(2) "BUENOS AIRES", le mot(3) ARGENTINE et le
mot(4) "AMERIQUE DU SUD"
ce que ne retourne évidemment pas la fonction SPLIT

Ce genre de données est généré par exemple par des exports de MYSQL.

Ai je un autre moyen ( fonction ) pour arriver à mettre dans mon tableau ces mots logiques? ou dois je travailler en test caractère par caractère, ce qui se fera, je le crains fort,
au détriment de la performance.

Qu'en pensez vous?

Merci Pierre

Pierre

30 réponses

ucfoutu Messages postés 18038 Date d'inscription lundi 7 décembre 2009 Statut Modérateur Dernière intervention 11 avril 2018 211
17 août 2012 à 21:27
Bonjour,
la question qui me vient d'emblée et naturellement à l'esprit est celle-ci :
Par quel code ce tableau a-t-il été rempli (et à partir de quoi) ?


________________________
Réponse exacte ? => "REPONSE ACCEPTEE" pour faciliter les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement vous dire ce qu'elle contient. Je n'interviendrai qu'en cas de nécessité de développ
0
cs_PeD Messages postés 63 Date d'inscription vendredi 25 janvier 2002 Statut Membre Dernière intervention 13 avril 2013
17 août 2012 à 21:41
Le fichier reçu résulte de "export record set to an external file" du résultat d'une query dans le MySQL Workbench.
En clair, les rows de "Select * FROM CITY".

Note : mais je ne suis pas sûr que j'ai répondu à la question, car je récupère un fichier .txt avec des lignes et non un réel tableau.
C'est le code après le SPLIT qui met en tableau dans mon application.
Du genre
MotCnt = SPLIT(zone," ")
For i = 0 to MoCnt
mot(i) = ....
next


Ai je répondu?


Pierre
0
ucfoutu Messages postés 18038 Date d'inscription lundi 7 décembre 2009 Statut Modérateur Dernière intervention 11 avril 2018 211
17 août 2012 à 21:55
car je récupère un fichier .txt avec des lignes et non un réel tableau

Reviens lorsque tu sauras exposer avec clarté et précision (tous les tenants et aboutissants). Entre ton premier message et le second, il y a un fossé que je regrette.
________________________
Réponse exacte ? => "REPONSE ACCEPTEE" pour faciliter les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement vous dire ce qu'elle contient. Je n'interviendrai qu'en cas de nécessité de développ
0
cs_PeD Messages postés 63 Date d'inscription vendredi 25 janvier 2002 Statut Membre Dernière intervention 13 avril 2013
17 août 2012 à 23:54
Ouais bon. Je simplifie.
Cela me paraissait clair, mais bon, j'accepte.

On oublie MySQl.
J'ai un fichier .txt qui contient les lignes
01 PARIS FRANCE EUROPE
02 BRUXELLES BELGIQUE EUROPE
03 "BUENOS AIRES" ARGENTINE "AMERIQUE DU SUD"

Je veux mettre en tableau les mots de chaque ligne, puis traiter ( ce traitement est ici hors de propos ).

Donc à chaque lecture de ligne, je mets en tableau les mots avec SPLIT.
Pour ligne 1 , j'aurai mot(1) = 01,
mot(2) PARIS, mot(3) FRANCE, mot(4) = EUROPE.

Mais pour la ligne 03, je voudrais que "BUENOS AIRES" soit mis dans mot(2), or avec SPLIT cela ne sera pas le cas. Il mettra dans mot(2) "BUENOS et dans mot(3) AIRES", dans mot(4) = ARGENTINE.

Or je veux que les mots de même rang contiennent le même type d'info : mot(1) = sequence , mot(2) la ville, mot(3) le pays, mot(4) le continent.


Je me relis : je trouvais que j'avais mieux expliqué avant. Snif.

Pardon, donc.

Pierre


Pierre
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_titicar Messages postés 181 Date d'inscription jeudi 30 mai 2002 Statut Membre Dernière intervention 19 août 2012
17 août 2012 à 23:59
Il existe sans doute plusieurs moyens. Un simple serait de remplacer tes séparateurs (un espace) par au autre caractère tant qu'ils ne se trouvent pas entre des guillemets, mais ça implique l'appel d'une fonction à écrire.

titicar
0
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
18 août 2012 à 00:01
Salut

Split n'a jamais renvoyé de chiffre, mais un tableau de chaines.
Ton code n'est pas correct.

Ton petit problème m'a titillé, et j'aime ça.
Voilà donc le fruit de mon travail.
    Dim Data1       As String
    Dim Data2       As String
    Dim aMots()     As String
    Dim aMots2()    As String
    Dim bInWord     As Boolean
    Dim sTemp       As String
    Dim lIndex      As Long
    Dim r           As Long
    Dim t           As Long
    
    Data1 = "01 PARIS FRANCE EUROPE"
    Data2 = "03 ""BUENOS AIRES"" ARGENTINE ""AMERIQUE DU SUD"""
    
    aMots = Split(Data1, " ")   ' Ici, change Data1 / Data2
    ' Visu avant
    For r = 0 To UBound(aMots)
        Debug.Print r, aMots(r)
    Next r
    Debug.Print "--------------------------------------------------------"

    ReDim aMots2(0 To UBound(aMots))
    lIndex = -1
    sTemp = ""
    If UBound(aMots) > 4 Then
        bInWord = False
        For r = 0 To UBound(aMots)
            If Left$(aMots(r), 1) = """" Then
                ' Si la chaine commence par "
                sTemp = Mid$(aMots(r), 2)
                bInWord = True
            ElseIf Right$(aMots(r), 1) = """" Then
                ' Si la chaine se termine par "
                sTemp = sTemp & " " & Left$(aMots(r), Len(aMots(r)) - 1)
                bInWord = False
            Else
                If bInWord Then
                    ' Si on est dans un "mot"
                    sTemp = sTemp & " " & aMots(r)
                Else
                    sTemp = aMots(r)
                End If
            End If
            ' Mémo or not mémo
            If bInWord Then
                ' Si on est dans un "mot"
                ' On ne fait rien, on attend la fin du "mot"
            Else
                ' " non trouvé ou fin de zone ou mot normal
                lIndex = lIndex + 1
                aMots2(lIndex) = sTemp
                sTemp = ""
            End If
        Next r
        ' Redimensionne le tableau 2 qui doit être plus petit, maintenant
        ReDim Preserve aMots2(0 To lIndex)
    Else
        ' Ligne normale sans "
        aMots2 = aMots
    End If
    ' Visu après
    For r = 0 To UBound(aMots2)
        Debug.Print r, aMots2(r)
    Next r
    Debug.Print "--------------------------------------------------------"

En ce moment, je ne programme plus beaucoup et ça m'a fait plaisir de replonger dedans.

Vala
Jack, MVP VB
NB : Je ne répondrai pas aux messages privés

Le savoir est la seule matière qui s'accroit quand on la partage (Socrate)
0
cs_PeD Messages postés 63 Date d'inscription vendredi 25 janvier 2002 Statut Membre Dernière intervention 13 avril 2013
18 août 2012 à 00:28
Merci.

A titicar : j'ai pensé à cela aussi, mais j'ai peur de la performance. Je pourrais avoir un fichier avec 1 million ou davantage de lignes, ou une largeur de ligne importante.
Ce que j'ai donné n'est qu'un exemple pour les besoins de l'exercice.
Je reçois ces fichiers et ne suis pas maître de leur grandeur.

A Jack : j'essaie demain.

Et vous reviendrai.

La bonne nuit.

Pierre
0
Utilisateur anonyme
18 août 2012 à 00:49
Bonsoir,

Si c'est bien du .NET, tu peux faire comme ceci (MaChaine étant l'expression à splitter) :
Dim MonTableau() As String = MaChaine.Split(New String() {Convert.ToChar(34)}, StringSplitOptions.RemoveEmptyEntries)
0
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
18 août 2012 à 02:49
Ah oui, petit détail qui 'avait échappé : Mon code est du VB6/VBA.
A transcrire sous .Net sera simple.

Mais si la solution proposée par Banana est efficace, quel gain !

(5 min plus tard)
Je viens de faire l'essai de la syntaxe proposée par Banana.
En fait, c'est un Split sur les ", ce qui n'est pas correct :
- Si pas de " dans la chaine : Renvoie une seule donnée = la chaine entière
- Si des " : Renvoie bien un tableau de chaque item
- Mais si des " juste pour le nom de la ville, on aura que 3 items, les 2 derniers n'étant pas découpés
0
ucfoutu Messages postés 18038 Date d'inscription lundi 7 décembre 2009 Statut Modérateur Dernière intervention 11 avril 2018 211
18 août 2012 à 08:15
Au risque d'être lourd, je vais en ce qui me concerne remettre en cause l'écriture du fichier elle-même. Cela évitera le bricolage envisagé !
Mais si l'on tient à un tel bricolage, alors === >>
soit toto la chaîbne à traiter
- ajouter un espace devant et derrière toto
- remplacer ensuite chr(32) + chr(34) par "/"
- remplacer dans le résultat Chr(34) & Chr(32) par "/"
"splitter" sur "/"

________________________
Réponse exacte ? => "REPONSE ACCEPTEE" pour faciliter les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement vous dire ce qu'elle contient. Je n'interviendrai qu'en cas de nécessité de développ
0
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
18 août 2012 à 13:06
Rappel des données :
01 PARIS FRANCE EUROPE
02 BRUXELLES BELGIQUE EUROPE
03 "BUENOS AIRES" ARGENTINE "AMERIQUE DU SUD"

J'en ajoute une 4ème tout aussi particulière :
04 "AIX EN PROVENCE" FRANCE EUROPE

Dans ton raisonnement, ucfoutu, les lignes 01 02 ou 04 ne seront pas correctement traitées, puisque :
- 01 et 02 : ne renferment pas de ", donc pas de /
- 04 : FRANCE et EUROPE ne seront pas correctement séparées puisque pas de / non plus entre elles.

Oui oui, casse tête.
0
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
18 août 2012 à 13:09
Si l'on doit modifier l'exportation (Excel ?) des données, il suffirait :
- De remplacer le séparateur entre données "espace" par un autre symbole non rencontré dans les données, Tabulation par exemple
- De supprimer les éventuels " à l'intérieur des données
0
Utilisateur anonyme
18 août 2012 à 13:13
Bonjour jack

C'est vrai que je n'avais pas approfondi mes test comme il se doit.
Merci pour ta remarque

Une expression régulière serait efficace également. Reste à la construire ...

Un bonjour à ucfoutu en passant
0
cs_PeD Messages postés 63 Date d'inscription vendredi 25 janvier 2002 Statut Membre Dernière intervention 13 avril 2013
18 août 2012 à 14:46
Bonjour à tous.

Je suis occupé à tester, spécialement le code inventif e Jack.

Pour info : l'export, comme dit dans ma question originale, est un export de MYSQL ( à partir du workbench et que je ne contrôle donc pas ).

Pour info : je ne l'ai vu que plus tard ( car visuellement il n'y a pas de différence ) mais les caractères entre les mots sont des hexa 09 et non des blancs. Sauf dans les "mots" composés comme "BUENOS AIRES". Il s'agit d'un espace entre BUENOS et AIRES.

Encore merci.

Pierre
0
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
18 août 2012 à 22:44
Ah bah alors rien de plus simple, il suffit de Spliter avec les tabulations (hexa ou décimal, 9 = Tabulation):
    Dim Data1       As String
    Dim Data2       As String
    Dim aMots()     As String
    Dim r           As Long
    
    Data1 = "01" & vbTab & "PARIS" & vbTab & "FRANCE" & vbTab & "EUROPE"
    Data2 = "03" & vbTab & """BUENOS AIRES""" & vbTab & "ARGENTINE" & vbTab & """AMERIQUE DU SUD"""
    
    aMots = Split(Data1, vbTab)   ' Ici, change Data1 / Data2

    ' Epuration des "
    For r = 0 To UBound(aMots)
        aMots(r) = Replace(aMots(r), Chr$(34), vbNullString)
    Next r
0
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
18 août 2012 à 22:49
Pardon, c'est encore du VB6, mais la transcription en .Net ne pose pas difficulté.
0
rebixav Messages postés 130 Date d'inscription dimanche 16 décembre 2007 Statut Membre Dernière intervention 28 janvier 2013
19 août 2012 à 08:56
je crois que j'ai quelque chose pour toi (attention c'est un vieux code que je n'utilise plus, en tout cas il prenais plusieurs choix de split à faire : espace, "-", " : ", un peu ce que l'on veut :


Public Function SPLIT2(ByVal Texte$, Optional ByVal separateur$ " ", Optional ByVal long_max_de_la_ligne% 0, _
Optional ByVal separateur2$ "", Optional ByVal separateur3$ "", _
Optional ByVal separateur4$ "", Optional ByVal separateur5$ "") As Variant
'split2 fait la même cose que split
'dim montableau$()
'montableau$=split2("xavier dumont")
'montableau$(0)="xavier"
'montableau$(1)="dumont"
'mais aussi prendre en compte une taille de ligne exemple :
'montableau$=split2("xavier dumont"," ",16)
'montableau$(0)="xavier dumont" car sa taille ne depasse pas 16 caractere !
'trés pratique pour couper des phrases sans couper les mots !
'PS : si long_max_de_la_ligne%=0 then split2 est utilisé comme split !
'PS : le nombre de ligne ne dépasseras pas 5000 !
'PS : si un mots fait à lui tout seul plus de 16 caractere alors ce mot sera seul,
'mais ajouter quand même !
'Vous pouvez aussi dans cette version de SPLIT2, mettre jusqu'à 5 caractère de recherche à dilimiter !

' BUGgggggggggggggggggggggggggggggggggggggg
' essayer SPLIT2(".386", " ", 200, vbTab)
'



Dim split_tableau$()
If Texte$ "" Then ReDim split_tableau$(0): split_tableau$(0) "": SPLIT2 = split_tableau$(): Exit Function
If separateur2$ "" Then split_tableau$ Split(Texte$, separateur$)

If long_max_de_la_ligne% = 0 Then

If separateur2$ = "" Then
SPLIT2 = split_tableau$()
Else
'--------------------------- délimitation manuel ------------------------------------
ReDim split_tableau$(5000) ' nombre de ligne max, vous pouvez le changer !
i2% 1: n% -1
For i% = 1 To Len(Texte$)
a$ = Mid$(Texte$, i%, 1)
Select Case a$
Case separateur$, separateur2$, separateur3$, separateur4$, separateur5$
' xxx xx+xxxx '<< séparation de " " et "+"
a$ = Mid$(Texte$, i2%, i% - i2%)
If a$ <> "" Then n% n% + 1: split_tableau$(n%) a$
i2% = i% + 1
End Select
Next i%
If i2% <i% Then n% n% + 1: split_tableau$(n%) = Mid$(Texte$, i2%, i% - i2%)
ReDim Preserve split_tableau$(n%)
SPLIT2 = split_tableau$()
'------------------------------------------------------------------------------------
End If

Else

ReDim split2_tableau$(5000) ' nombre de ligne max, vous pouvez le changer !
For i% = 0 To UBound(split_tableau$)
If Len(split2_tableau$(j%)) + Len(split_tableau$(j%)) > long_max_de_la_ligne% Then
If split2_tableau$(j%) <> "" Then j% = j% + 1
End If
If split2_tableau$(j%) = "" Then
split2_tableau$(j%) = split_tableau$(i%)
Else
split2_tableau$(j%) = split2_tableau$(j%) + " " + split_tableau$(i%)
End If
Next i%
ReDim Preserve split2_tableau$(j%)
SPLIT2 = split2_tableau$()

End If

Erase split_tableau$
Erase split2_tableau$


' 'Function split a 1 ou 2 niveaux
' '1- a un niveau lorsque PosN2 = 0
' '2- a 2 niveaux lorque PosN2 >= 1
'
' 'ex :
' 'si chaine = "a1$b1#a2$b2#a3$b3"
' 'spameliore(chaine,1,1) rend "a1"
' 'spameliore(chaine,1,0) rend "a1$b1"
' 'spameliore(chaine,2,2) rend "b2"
'
'
' public Function SpAmeliore(Chaine As String, PosN1 As Integer, PosN2 As Integer)
' Dim DataP1
' Dim Tableau1() As String
' Tableau1() = Split(Chaine, "#", -1)
' DataP1 = Tableau1(PosN1 - 1)
' If PosN2 0 Then SpAmeliore DataP1: Exit Function
' Dim Tableau2() As String
' Tableau2() = Split(DataP1, "$", -1)
' SpAmeliore = Tableau2(PosN2 - 1)
' End Function

'MsgBox "prog pas finie"


End Function


essaye et dit moi ce que tu en pense !

Au faite si la performance du code te gene, tu peut en faire un module exe aprés et demander a ton prog.exe "chaine1,chaine2,..." sous la commande Shell

maintenant je fait des module .bas, .frm .exe et .asm(assembleur)

en tout cas ta solution me paraiut pas complexe, aprés ces la puissance qui joue !

la première fois que j'ai vue ta question et :
01 PARIS FRANCE EUROPE
02 BRUXELLES BELGIQUE EUROPE
03 "BUENOS AIRES" ARGENTINE "AMERIQUE DU SUD"

je me suis dit pourquoi SPLIT, il n'as qu'à le faire à la main caractere par caractere, et faire lui même les tableau bref comme jack

dit moi si c'est cela !??
0
cs_PeD Messages postés 63 Date d'inscription vendredi 25 janvier 2002 Statut Membre Dernière intervention 13 avril 2013
19 août 2012 à 10:28
A Rebixav.

Merci. Je vais essayer..... mais laissez moi un peu de temps.

Pierre
0
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
19 août 2012 à 13:44
Du temps ?
Tu rigoles !
Aller, et que ça saute !
0
cs_PeD Messages postés 63 Date d'inscription vendredi 25 janvier 2002 Statut Membre Dernière intervention 13 avril 2013
19 août 2012 à 15:23
Je vais m'exiler sur MARS là où les journées sont de 25 heures.

Et non !! je bosse, bosse et rebosse et de plus je l'assure, cela me passionne et je prends mon pied ........... depuis 42 ans dans cette P... de formidable informatique.
Et j'ai bien dit "informatique".

Pierre
0
Rejoignez-nous