IMPORTATION D'UN FICHIER.TXT SERVANT DE MINI BASE DE DONNÉES (SÉPARATEURS ";") D

Cacophrene Messages postés 251 Date d'inscription lundi 29 mars 2004 Statut Membre Dernière intervention 4 mars 2008 - 17 août 2006 à 09:41
jean_marc_n2 Messages postés 170 Date d'inscription jeudi 11 décembre 2003 Statut Membre Dernière intervention 24 janvier 2009 - 20 août 2006 à 09:54
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/39150-importation-d-un-fichier-txt-servant-de-mini-base-de-donnees-separateurs-dans-un-tableau-de-variables

jean_marc_n2 Messages postés 170 Date d'inscription jeudi 11 décembre 2003 Statut Membre Dernière intervention 24 janvier 2009
20 août 2006 à 09:54
=> Inutile d'ajouter une variable pour retourner le nombre de lignes.

Au retour de la fonction, il suffit de faire:

Dim r As Boolean, szErr As String
Dim t() As String
Dim nb_lignes as long, nb_champs as long

r = ImportTxtFile("c:\test.dat", ";", t(), szErr, 1)

' RECUP NOMBRE LIGNES
nb_lignes = Ubound(t(), 1)

Tu peux aussi récupérer le nombre de champs:
nb_champs = Ubound(t(), 2)
gnieark Messages postés 53 Date d'inscription jeudi 17 août 2006 Statut Membre Dernière intervention 22 octobre 2010
20 août 2006 à 00:25
j'ai réussi à intégrer ta fonction dans mon code, ça y est!
gnieark Messages postés 53 Date d'inscription jeudi 17 août 2006 Statut Membre Dernière intervention 22 octobre 2010
19 août 2006 à 23:58
po mal merci.

pour la suite je vais tenter d'intégrer à ta fonction une variable contenant le nombre de lignes du texte.

Si j'y arrive pas j'appellerai à l'aide ;)
jean_marc_n2 Messages postés 170 Date d'inscription jeudi 11 décembre 2003 Statut Membre Dernière intervention 24 janvier 2009
19 août 2006 à 10:50
Hello,

gnieark => Pour préserver ton tableau, il suffit que celui ci soit déclaré ailleurs que dans ta fonction.

VOici un exemple d'amélioration pour ta Sub:
- C'est maintenant une fonction qui retourne un booléen (True si tout va bien, False en cas d'erreur)
- Elle prend en paramètre le nom de fichier, le séparateur à utiliser, le tableau (qui sera alooué dynamiquement), une variable pour mettre le code d'erreur au cas ou (fichier non trouvé par exemple), et en option une variable permettant de commencer à remplir ton tableau à l'indice voulu (en général 0 ou 1).

Private Function ImportTxtFile(ByVal fileName As String, _
ByVal separator As String, _
ByRef tData() As String, _
ByRef errorString As String, _
Optional ByVal baseArray As Integer = 1) As Boolean
Dim f As Integer
Dim tLine() As String
Dim tSplit() As String
Dim buffer As String
Dim nbItem As Long
Dim i As Long, j As Long

On Error GoTo ImportTxtFile_ERR

f = FreeFile()
Open fileName For Binary As #f
buffer = Space$(LOF(f))
Get #f, , buffer
Close #f
tSplit() = Split(buffer, vbCrLf)
nbItem = UBound(Split(tSplit(0), separator)) + baseArray

ReDim tData(UBound(tSplit()) + baseArray, nbItem)

For i = LBound(tSplit()) To UBound(tSplit())
tLine = Split(tSplit(i), separator)
For j = LBound(tLine) To UBound(tLine)
tData(i + baseArray, j + baseArray) = tLine(j)
Next j
Next i
ImportTxtFile = True

ImportTxtFile_END:
Exit Function

ImportTxtFile_ERR:
errorString = Err.Description
Resume ImportTxtFile_END
End Function

Un exemple d'appel:

Private Sub Command2_Click()
Dim r As Boolean, szErr As String
Dim t() As String

r = ImportTxtFile("c:\test.dat", ";", t(), szErr, 1)

End Sub

Avantages:
- Tout est passé en paramètres, plus rien de hard-codé dans la "Sub"
- L'allocation du tableau est dynamique, aussi bien pour les lignes que pour les colonnes: tu peux lire n'importe quel fichier, de n'importe quelle taille, le code est toujours valable
- La lecture en bloc est très rapide
- C'est une vraie fonction, utilisable de façon autonome.

Au final, ça charge un fichier de 20000 lignes avec 7 champs par lignes en 0,4 seconde.

Bonne suite :-)
cs_asimengo Messages postés 280 Date d'inscription jeudi 24 mars 2005 Statut Membre Dernière intervention 18 mars 2009
18 août 2006 à 11:49
@Bouv: Je vais l'uploader dès que possible, mais il faudrait que je le retouche un peu, il s'agissait de ma première source et j'avais encore beaucoup à apprendre en VB.

Au fait vu ton niveau très appréciable pourras-tu me faire des remarques et suggestions pour son amélioration?
bouv Messages postés 1411 Date d'inscription mercredi 6 août 2003 Statut Membre Dernière intervention 3 mars 2019 1
18 août 2006 à 11:26
Asimengo>>Interressant, mais j'aimerai en savoir plus sur la structure du fichier schema.ini
Dommage que ta source ne contienne pas de vrai zip avec un projet exemple.
cs_asimengo Messages postés 280 Date d'inscription jeudi 24 mars 2005 Statut Membre Dernière intervention 18 mars 2009
18 août 2006 à 11:02
@gnieark: Je t'expose ci-dessous l'utilisation de Microsoft Text Driver pour mieux faire ton importation. Tu récupères le fichier dans un recordset et il offre encore plus de possiblités. Ci-dessous un rapide aperçu de la démarche.

Dim Cnx As ADODB.Connection
Dim cmdadodb As ADODB.Command, sCommandText as string
Dim Rst as ADODB.Recordset

'Definition et ouverture de la Connexion
StrCnx = "driver={Microsoft Text Driver (*.txt; *.csv)};DriverId=27" & _
";DBQ=" & App.Path & "\DATA\ASCII" 'DBQ désigne le dossier où se trouve le fichier ASCII
Set Cnx = New ADODB.Connection
With Cnx
.ConnectionString = StrCnx
.Open
End With

'Définition de la commande, elle peut être une requête sur ton fichier Texte.
sCommandText = "[Mon fichier ascii.txt]" 'Ne pas oublier les crochets.
Set cmdadodb = New ADODB.Command
With cmdadodb
.ActiveConnection = Cnx
.CommandType = adCmdUnknown
.CommandText = sCommandText
End With

'Ma variable recordset Rst contiendra tout le fichier Texte que je peux manipuler à ma guise
Set Rst = New ADODB.Recordset
With Rst
.CursorLocation = adUseClient
.CursorType = adOpenDynamic
.LockType = adLockPessimistic
.Open cmdadodb
End With



NB : Le dossier indiqué par DBQ doit contenir un fichier du nom de "schema.ini" qui a la structure de ton fichier texte.
Pour mieux voir ça regarde ma source http://www.vbfrance.com/code.aspx?ID=33090
cs_Didier72 Messages postés 76 Date d'inscription dimanche 10 octobre 2004 Statut Membre Dernière intervention 13 juin 2015
18 août 2006 à 08:33
Hello

Si ela peut apporter un plus

Moi j'utilise cette procédure:

------------------------------------------------------------------
strAdresseFichier = cheminfichier + "fichier.txt"
If (Dir(strAdresseFichier, vbDirectory) <> "") Then
Open strAdresseFichier For Input As #1
While Not EOF(1)
z = z + 1
Line Input #1, strLigne
tabLigne = Split(strLigne, ";")
info1(z) = tabLigne(0)
info2(z) = tabLigne(1)
info3(z) = tabLigne(2)
info4(z) ..... etc Etc
Wend
Close #1
End If

-----------------------------------------------------------------

bye
gnieark Messages postés 53 Date d'inscription jeudi 17 août 2006 Statut Membre Dernière intervention 22 octobre 2010
17 août 2006 à 22:53
merci vos aides sont précieuses. je potasserai tout ça dès demain.

Une petite question: Y'a-t-il une technique pour que le tableau de variable ne se réinitialise pas lorsque le programme s'arrete le temps d'une intervention de l'utilisateur? ou lorsque le programme change de feuille?

merci d'avance!
jean_marc_n2 Messages postés 170 Date d'inscription jeudi 11 décembre 2003 Statut Membre Dernière intervention 24 janvier 2009
17 août 2006 à 21:29
Hello,

Tant qu'à écrire une fonction, autant alors que ce soit "vraiment" une fonction, ce qui n'est pas le cas ici:
- Passer le délimiteur en paramètre
- Passer le tableau en paramètre (on le réallouera dynamiquement)

Note: Il y a une faute de frappe dans le code ci dessus. Il faut bien sur lire:
While NotEOF(iFile) et pas EOF(1)
bouv Messages postés 1411 Date d'inscription mercredi 6 août 2003 Statut Membre Dernière intervention 3 mars 2019 1
17 août 2006 à 15:58
Autre petit conseil,

Utilise un séparateur plus rare que le ';' (par ex '|') ou carément un séparateur perso (ex : '<%S%>').
Car tu risque un jour de te trouver avec un champs qui contient un ';' et toutes tes valeurs seront décalés.

Ce qui donnerait :
DANS TON FICHIER
domaine<%S%>Référence<%S%>Type<%S%>...

Dans ton code :

Private Sub Import(sFileName As String)
Const sDelimiter = "|"
Dim iFile As Integer, i As Integer, iLine As Integer
Dim sLine As String, sTable() As String, sResult(1 To 1000, 1 To 50) As String
'On récupère un numéro de fichier libre
iFile = FreeFile()
'On ouvre le fichier
Open sFileName For Input As #iFile
'On parcour chaque ligne
Do While Not EOF(1)
'On incrémente le n° de ligne
iLine = iLine + 1
'On lit la ligne
Line Input #1, sLine
'On sépare les champs
sTable = Split(sLine, sDelimiter)
'On tri les champs et on les place dans le Tableau sResult
For i = 0 To UBound(sTable)
sResult(iLine, i + 1) = sTable(i)
Next i
Loop
'On ferme le fichier
Close #iFile
End Sub
gnieark Messages postés 53 Date d'inscription jeudi 17 août 2006 Statut Membre Dernière intervention 22 octobre 2010
17 août 2006 à 14:23
je vais suivre tes conseils Cacophrene, merci. préciser à chaque fois le type de variable.

en fait la disposition du fichier texte sera
domaine;Référence;Type;Titre;Emetteur;Version;Visualiser;Imprimer;Importer;Chemin;Destinataires;Int;Ext;Mots clefs;date de mise en application;date de revision

(avec certaines valeurs boolennes, d'autres chaines de caractères d'autres numériques.

Je préfère utiliser les retours à la ligne même si j'alourdis le code, parceque je n'ai pas toujours toutes les informations et il se peut que le nombre d'éléments varie par ligne. De plus en cas de soucis ce sera moins galère pour aller modifier direct dans le fichier .txt
petite précision, ce fichier sera placé dans un repertoire dont je suis le seul (avec mon chef) à avoir l'accès en écriture, les autres l'ont en lecture seulement, c'est pourquoi je ne m'embète pas à sécuriser.

je posterai la suite du code (notemment les fonctions de recherche par critère)
Cacophrene Messages postés 251 Date d'inscription lundi 29 mars 2004 Statut Membre Dernière intervention 4 mars 2008 1
17 août 2006 à 09:44
Décidément ! :-( C'est pas non plus "End Function" mais "End Sub". Ah les étouderies... :-)
Cacophrene Messages postés 251 Date d'inscription lundi 29 mars 2004 Statut Membre Dernière intervention 4 mars 2008 1
17 août 2006 à 09:42
Petite correction : dans ma fonction Import, il ne faut pas lire sFileName As Integer (...!) mais sFileName As String.

Merci d'avance,
Cacophrène
Cacophrene Messages postés 251 Date d'inscription lundi 29 mars 2004 Statut Membre Dernière intervention 4 mars 2008 1
17 août 2006 à 09:41
Salut !

Remplace :

Dim ligne, x As Integer
Dim filename, prout As String

Par :

Dim ligne As Integer (ou As Long si tu veux), x As Integer
Dim filename As String, prout As String

Si le type n'est pas précisé pour chaque variable, toutes celles où celui-ci n'apparaît pas sont considérées par VB comme Variant.

Sinon, tu peux (mais ce n'est pas aussi important que les types... surtout si tu es sûr de n'ouvrir qu'un seul fichier à la fois) utiliser FreeFile au lieu d'un chiffre en dur.

Dernière chose à dire : le découpage en lignes t'est-il utile ? Si c'est le cas, ne tiens pas compte de la suite de mon message. Si, au contraire, les lignes ne sont pas très importantes (c'est-à-dire si tu peux remplacer vbCrLf par un délimiteur), tu peux t'en tirer à moindre coût :

'=========================================================
Private Sub Import(sFileName As Integer)
Dim sData As String, F As Integer, sResult() As String
F = FreeFile()
Open sFileName For Input As #F
sData = Input$(LOF(F), #F)
Close #F
sResult = Split(sData, ";")
End Function
'=========================================================

Voilà tout ! Encore désolé si la fin du message est sans rapport avec ce que tu souhaites faire à partir de la disposition des données dans le fichier texte.

Cordialement,
Cacophrène