0
votes

Importer un fichier CSV séparé par des tabulations, le séparateur de tabulation n'est pas reconnu

J'ai des fichiers csv séparés par des tabulations que je veux transformer en xlsx. Ainsi, chaque csv doit être transformé en xlsx. Le nom de fichier doit être le même. Cependant, les fichiers sont séparés par des tabulations. Par exemple, consultez cette capture d'écran de fichier de test:

ex11

Quand j'exécute mon code (j'ai créé un sous-dossier xlsx avant):

Sub all()

    Dim wb As Workbook
    Dim strFile As String
    Dim strDir As String
    
    strDir = "C:\Users\PC\Desktop\Test\"
    strFile = Dir(strDir & "*.csv")
    
    Do While strFile <> ""
    
    Set wb = Workbooks.Open(Filename:=strDir & strFile, Delimiter:=Chr(9), Local:=False)
    With wb
        .SaveAs Replace(wb.FullName, ".csv", ".xlsx"), 51
        .Close True
    End With
    Set wb = Nothing
    strFile = Dir
    Loop
    
End Sub

cela fonctionne, mais quand je regarde dans le fichier Excel:

ex2

Je peux voir que le séparateur de tabulation n'a pas été détecté. Je pense que mes paramètres locaux sont que le séparateur est un point-virgule et c'est pourquoi il ne fonctionne pas. Maintenant, je voulais définir dataType sur xlDelimited et tab sur True, en changeant la ligne en:

Workbooks.Open FileName:=Spath & sDir, DataType:=xlDelimited, Tab:=True

J'ai aussi essayé

Workbooks.Open (Spath & sDir, DataType:=xlDelimited, Tab:=True)

ou

Workbooks.Open (Spath & sDir), DataType:=xlDelimited, Tab:=True

Mais cela conduit à un message d'erreur. J'ai ensuite essayé une autre approche, où j'ai défini le délimiteur sur Chr (9) (tab) et local sur false:

Sub all()

   Dim sourcepath As String
   Dim sDir As String
   Dim newpath As String
    
    sourcepath = "C:\Users\PC\Desktop\Test\"
    newpath = sourcepath & "xlsx\"
    
    'make sure subfolder xlsx was created before

    sDir = Dir$(sourcepath & "*.csv", vbNormal)
    Do Until Len(sDir) = 0
        Workbooks.Open (sourcepath & sDir)
        With ActiveWorkbook
            .SaveAs Filename:=Replace(Left(.FullName, InStrRev(.FullName, ".")), sourcepath, newpath) & "xlsx", FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
            .Close
        End With
        
        sDir = Dir$
    Loop
End Sub

Cela ne conduit pas à une erreur. Mais lorsque j'ouvre le fichier, il ressemble à:

ex2

Encore une fois même problème, le séparateur de tabulation n'est pas reconnu. Comment puis-je réparer cela?

(Je l'ai aussi essayé avec local: True avec Delimiter: = Chr (9), mais même problème et je l'ai également essayé avec l'ajout de Format: = 6)

Je l'ai essayé de cette façon avec csv car je ne voulais pas faire de même avec l'extension de fichier txt. La raison en est que l'utilisation de csv autorise facilement les caractères de langage spéciaux tels que "ö" et "ü". C'est pourquoi je voulais convertir csv en xlsx et ne pas utiliser la solution de contournement consistant à utiliser txt à la place, car je rencontre alors le problème que lorsque j'essaie de convertir txt en xlsx, certains caractères spéciaux ne sont pas correctement reconnus et j'espère éviter cela problème avec l'utilisation de csv.

Les fichiers csv (ou en fait ce sont tsv, car ils ont l'onglet comme séparateur et non point-virgule) ont des colonnes différentes. Ainsi, un fichier csv pourrait avoir 5 colonnes, les 6 autres et les types de données varient également.

ÉDITER:

En réponse aux EEM, répondez:

Vérifiez ce fichier Test.csv, il ressemble à ceci:

ex4

Séparé par onglet. Pas de point-virgule.

Lorsque j'exécute le code (plus l'ajout de .TextFileDecimalSeparator = "." Au code) et vérifie le fichier xlsx résultant, il ressemble à ceci:

ex2

Les valeurs de la deuxième colonne (Colonne), comme 9987.5 sont correctement transformées en 9987,5. Mais les valeurs de la dernière colonne (ColumnI) sont mal transformées. C'est mon problème maintenant. (Je ne sais pas pourquoi le caractère spécial ne se transforme pas correctement, car dans mes fichiers d'origine, cela fonctionne.)


3 commentaires

Vous devriez pouvoir utiliser la commande du ruban «Texte en colonnes» dans le menu Données pour traiter la feuille de calcul; définissez-le comme délimité et incluez «Tab» comme délimiteur. Enregistrez une macro pour obtenir plus facilement le code VBA requis.


Répondez à la mise à jour pour prendre soin des nouvelles informations sur les données numériques, veuillez tester.


Merci pour votre soutien continu et j'accepterai votre réponse. Cependant, une dernière question: dans les fichiers xlsx résultants, le nom de la feuille de tous les fichiers est "Sheet1". Je voudrais reporter cela du nom de fichier. Pour que le nom de la feuille résultant soit comme le nom de fichier (sans le .xslx). Est-ce possible?


6 Réponses :


1
votes

Avec un fichier délimité qui a une extension csv, les méthodes Excel Open et vba Workbooks.Open et Workbooks.OpenText supposeront toujours que le délimiteur est une virgule, peu importe ce que vous mettez dans l'argument.

  1. Vous pouvez changer l'extension du fichier (par exemple en .txt ), puis la méthode .Open devrait fonctionner.
  2. Vous pouvez le lire dans un objet TextStream et l'analyser ligne par ligne dans VBA
  3. Vous pouvez importer le fichier au lieu d' ouvrir le fichier.
  • Vous pouvez utiliser Power Query pour l'importer.
  • Ou vous pouvez utiliser une variante du code ci-dessous, qui vient d'être généré par l'enregistreur de macros, vous devrez donc le nettoyer et l'adapter un peu à vos spécificités.
With ActiveSheet.QueryTables.Add(Connection:= _
        "TEXT;D:\Users\Ron\Desktop\myFile.csv", Destination:=Range("$A$12"))
        .CommandType = 0
        .Name = "weather_1"
        .FieldNames = True
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .RefreshStyle = xlInsertDeleteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = True
        .RefreshPeriod = 0
        .TextFilePromptOnRefresh = False
        .TextFilePlatform = 437
        .TextFileStartRow = 1
        .TextFileParseType = xlDelimited
        .TextFileTextQualifier = xlTextQualifierDoubleQuote
        .TextFileConsecutiveDelimiter = False
        .TextFileTabDelimiter = True
        .TextFileSemicolonDelimiter = False
        .TextFileCommaDelimiter = False
        .TextFileSpaceDelimiter = False
        .TextFileColumnDataTypes = Array(1, 1, 1, 1)
        .TextFileTrailingMinusNumbers = True
        .Refresh BackgroundQuery:=False
    End With


23 commentaires

Merci pour votre réponse détaillée. Option1 txt n'est pas un moyen pour moi, car je suis confronté à un nouveau problème: les caractères spéciaux UTF-8, comme äö, ne sont donc pas correctement importés. Une question concernant l'option 3, car cela semble être la meilleure solution pour moi: à quoi cela ressemblerait-il, l'importer plutôt que l'ouvrir? Concernant PowerQuery: Je n'ai pas qu'un seul fichier, mais beaucoup. PowerQuery permet-il de le faire pour de nombreux fichiers de manière raisonnable ou dois-je le faire manuellement pour chaque fichier? Ce n'est pas une option pour moi.


Le code vba a l'air bien, mais je pense que mes capacités sont trop limitées pour ajuster dynamiquement des choses comme .TextFileColumnDataTypes. J'ai beaucoup de fichiers différents. Ils n'ont pas les mêmes types de données et ainsi de suite. De plus, la plage n'est pas la même dans chaque fichier.


@BertHobe Je ne comprends pas votre objection concernant les types de données. Vous n'essayez pas de les définir dans votre code existant. Pourquoi devriez-vous avoir besoin de les définir dans ce code?


Eh bien, j'ai pensé à cause de .TextFileColumnDataTypes = Array (1, 1, 1, 1)? Donc, cela indique explicitement le type de données et j'ai pensé que je devais le faire et le spécifier? Mais je ne sais pas, quelle colonne est une chaîne ou un entier ou plus? Donc je ne sais pas comment mettre ça dans ma boucle.


@BertHobe Je suis presque sûr que c'est un argument facultatif.


Et comment le mettre en œuvre lorsque la plage (où se trouvent les données) est différente dans chaque fichier?


@BertHobe Je pensais que vos données étaient dans un fichier?


Mes données sont un fichier. Cependant, j'ai beaucoup de fichiers différents, la plage est toujours différente, donc le nombre de lignes et de colonnes diffère, tout comme le nom de fichier.


Donc mon problème est que je ne sais pas comment mettre cela dans mon code pour le faire fonctionner.


Continuonscette discussion en chat .


J'ai mis à jour ma question et essayé d'implémenter votre code vba.


@BertHobe un aperçu rapide indique que la syntaxe de votre chaîne de connexion est probablement incorrecte. Il semble qu'il y ait au moins un point-virgule manquant.


J'ai essayé "TEXT"; & strFile mais ne fonctionne pas.


@BertHobe Je ne m'attendrais pas à ce que cela fonctionne. Pour moi, il semble que le point-virgule fait partie de la chaîne et non un séparateur.


Ok, je vois votre point. J'ai essayé de le faire fonctionner avec un simple fichier. Mais j'obtiens un message d'erreur. Cela devrait être le même que votre code, mais cela ne fonctionne tout simplement pas.


@BertHobe Essayez d'enregistrer une macro lorsque vous importez le fichier manuellement à partir d'Excel, pour un seul fichier. Cela devrait fournir une syntaxe appropriée.


J'ai déjà essayé cela, mais le résultat était similaire au vôtre et je n'ai pas pu l'implémenter dans mon code.


@BertHobe Est-ce que cela fonctionne pour un seul fichier lorsque vous utilisez cette macro enregistrée?


Le problème avec cela est que le code résultant contient beaucoup de valeurs «codées en dur», comme les noms de colonnes sont déjà inclus. De plus, il ne ressemble pas au vôtre, il diffère, par exemple ActiveSheet.ListObjects.Add est utilisé. Mon VBA est la connaissance ne suffit pas pour l'automatiser.


@BertHobe Cette méthode est sans doute la méthode la plus efficace et la plus facilement personnalisable, mais sa mise en œuvre dans votre environnement semble exiger un niveau de connaissances VBA que vous n'avez pas encore acquis. Et je ne vois aucun nom de colonne codé en dur dans le code généré, donc je ne sais vraiment pas quel est le problème. Si le problème concerne les noms de colonne dans le fichier, vous devez modifier une norme; ou mettez certaines colonnes dans un certain ordre, qui n'a pas été abordé dans votre question initiale. Si autre chose, veuillez m'éclairer.


@BertHobe écrit à l'option n ° 1, si vous utilisez la méthode Workbooks.OpenText (au lieu de la méthode Workbooks.Open ), vous pouvez spécifier une page de codes UTF-8 comme origine, ce qui éliminera l'objection que vous avez faite.


Ma question ici était assez claire, comme je l'ai déjà écrit dans la question initiale qu'ici je veux suivre le chemin avec CSV et non avec TXT. Donc, ici, cette question est de savoir comment importer csv vers xlsx et le faire fonctionner s'il s'agit d'un tsv et non d'un csv. Mes fichiers ne sont pas spéciaux. Si quelqu'un le fait fonctionner pour deux fichiers d'exemple, cela fonctionne pour moi. Cependant, mon problème est que je ne sais pas comment l'implémenter dans ma boucle. L'extrait de code que vous avez publié n'est pas vraiment complet et ne m'aide pas. C'est le problème.


@BertHobe Cela ne répond pas vraiment à ma question. En ce qui concerne la solution de fichier txt, la copie du fichier dans le répertoire TEMP de votre système et la modification du suffixe de type de fichier se font facilement dans VBA (voir Environ (pour déterminer le dossier), Name (pour copier avec un nom modifié, et Kill ( pour supprimer le fichier txt lorsque vous en avez terminé) sont des méthodes que vous pouvez intégrer dans votre boucle DO pour implémenter # 1. Juste une suggestion car vous n'arrivez pas à faire fonctionner la méthode de connexion de données, et je ne comprends pas votre problèmes concernant les "noms de colonnes codés en dur".



0
votes

Le Text to Columns devrait fonctionner pour cela:

Sub all()

   Dim sourcepath As String
   Dim sDir As String
   Dim newpath As String
    
    sourcepath = "C:\Users\snapier\Downloads\Test\"
    newpath = sourcepath & "xlsx\"
    
    'make sure subfolder xlsx was created before

    sDir = Dir$(sourcepath & "*.csv", vbNormal)
    Do Until Len(sDir) = 0
        Workbooks.Open (sourcepath & sDir)
        With ActiveWorkbook.Worksheets(1)
            .UsedRange.TextToColumns Destination:=Range("A1"), DataType:=xlDelimited, _
            TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=True, Tab:=True, _
            Semicolon:=False, Comma:=False, Space:=False, Other:=False
        End With
        With ActiveWorkbook
            .SaveAs Filename:=Replace(Left(.FullName, InStrRev(.FullName, ".")), sourcepath, newpath) & "xlsx", FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
            .Close
        End With
        
        sDir = Dir$
    Loop
End Sub


0 commentaires

3
votes

Comme mentionné par @RonRosenfeld, les fichiers avec l'extension .csv seront ouverts par Excel sous forme de fichier texte avec des délimiteurs de tabulation.

De plus, l'hypothèse suivante n'est pas exacte:

Option1 txt n'est pas un moyen pour moi, car je suis confronté à un nouveau problème que les caractères spéciaux UTF-8, comme äö et ne sont donc pas correctement importés.

La gestion des caractères ou de code page n'a rien à voir avec l'extension des fichiers, mais elle est gérée par le paramètre Origin de la méthode Workbooks.OpenText ou par la propriété TextFilePlatform de l'objet QueryTable .

Par conséquent, à moins que les fichiers ne soient renommés avec une extension différente de csv la [méthode Workbooks.OpenText] ne sera pas efficace.

La solution proposée ci-dessous, utilise l'objet QueryTable et se compose de deux procédures:

  1. Tab_Delimited_UTF8_Files_Save_As_Xlsx
  • Définit le dossier source et cible
  • Crée le dossier xlsx s'il n'est pas présent
  • Obtient tous les fichiers csv dans le dossier source
  1. Open_Csv_As_Tab_Delimited_Then_Save_As_Xls
  • Traitez chaque fichier csv
  • Ajoute un classeur pour contenir la Query Table
  • Importe le fichier csv
  • Supprime la requête
  • Enregistre le fichier sous «xlsx»

EDIT I Ces lignes ont été ajoutées pour assurer la conversion des données numériques:

Sub Open_Csv_As_Tab_Delimited_Then_Save_As_Xls(sWsh As String, sFilenameSrc As String, sFilenameTrg As String)    '@
Dim Wbk As Workbook
    
    Rem Workbook - Add
    Set Wbk = Workbooks.Add
    With Wbk
        
        With .Worksheets(1)

            Rem QueryTable - Add
            With .QueryTables.Add(Connection:="TEXT;" & sFilenameSrc, Destination:=.Cells(1))
                
                Rem QueryTable - Properties
                .SaveData = True
                .TextFileParseType = xlDelimited
                .TextFileDecimalSeparator = "."
                .TextFileThousandsSeparator = ","
                .TextFileConsecutiveDelimiter = False
                .TextFileTabDelimiter = True
                .TextFileTrailingMinusNumbers = True
                .TextFilePlatform = 65001               'Unicode (UTF-8)
                .Refresh BackgroundQuery:=False
                
                Rem QueryTable - Delete
                .Delete
            
            End With
        
            Rem Rename Worksheet    '@
            On Error Resume Next    '@ Ignore error in case the Filename is not valid as Sheetname
            .Name = sWsh            '@
            On Error GoTo 0         '@
        
        End With

        Rem Workbook - Save & Close
        .SaveAs Filename:=sFilenameTrg, FileFormat:=xlOpenXMLWorkbook
        .Close
    
    End With

    End Sub

EDIT II A Quelques modifications pour renommer la feuille de calcul (marquée comme '@)

Testé avec ce fichier csv:

entrez la description de l'image ici

Généré ce fichier `xlsx ':

entrez la description de l'image ici

J'espère qu'il devrait être simple d'ajouter ces procédures à votre projet, faites-moi savoir tout problème ou question que vous pourriez avoir avec les ressources utilisées.

Sub Tab_Delimited_UTF8_Files_Save_As_Xlsx()
Dim sFile As String
Dim sPathSrc As String, sPathTrg As String
Dim sFilenameSrc As String, sFilenameTrg As String
Dim bShts As Byte, exCalc As XlCalculation
    
Rem sPathSrc = "C:\Users\PC\Desktop\Test\"
    sPathTrg = sPathSrc & "xlsx\"
    
    Rem Excel Properties OFF
    With Application
        .EnableEvents = False
        .DisplayAlerts = False
        .ScreenUpdating = False
        exCalc = .Calculation
        .Calculation = xlCalculationManual
        .CalculateBeforeSave = False
        bShts = .SheetsInNewWorkbook
        .SheetsInNewWorkbook = 1
    End With

    Rem Validate Target Folder
    If Len(Dir$(sPathTrg, vbDirectory)) = 0 Then MkDir sPathTrg

    Rem Process Csv Files
    sFile = Dir$(sPathSrc & "*.csv")
    Do Until Len(sFile) = 0
        
        sFilenameSrc = sPathSrc & sFile
        sFile = Left(sFile, -1 + InStrRev(sFile, ".csv"))    '@
        sFilenameTrg = sPathTrg & sFile & ".xlsx"            '@
        
        Call Open_Csv_As_Tab_Delimited_Then_Save_As_Xls(sFile, sFilenameSrc, sFilenameTrg)    '@
        
        sFile = Dir$
    
    Loop

    Rem Excel Properties OFF
    With Application
        .SheetsInNewWorkbook = bShts
        .Calculation = exCalc
        .CalculateBeforeSave = True
        .ScreenUpdating = True
        .DisplayAlerts = True
        .EnableEvents = True
    End With
    
    End Sub

â € ¦

                .TextFileDecimalSeparator = "."
                .TextFileThousandsSeparator = ","


16 commentaires

J'ai copié votre code et ajusté le sPathSrc dans mon dossier (j'ai fait attention à avoir un autre "\" à la fin, donc non seulement ... \ Test mais ... \ Test \. Donc exactement comme le vôtre. Quand je essayez d'exécuter votre code, j'obtiens l'erreur d'exécution 1004 excel ne peut pas accéder à workboox.xlsx et les marques de débogage Set Wbk = Workbooks.Add (Template: = "Workbook"). Quel est le problème ici?


Cela peut avoir à voir avec les paramètres de ma machine, j'ai un classeur personnalisé par défaut, je m'en excuse. Veuillez le changer en Workbooks.Add . Workbooks.Add , essayez de me le faire savoir.


Tout d'abord, un grand merci pour votre soutien continu et votre réponse rapide. Je l'ai essayé et cela fonctionne, cependant, il y a un problème: les fichiers Excel résultants ont le mauvais séparateur décimal. Ainsi, dans les fichiers csv originaux, les numéros sont affichés comme par exemple 9984.5 Dans mon Excel, cela est également montré. Cependant, pour une analyse plus approfondie, j'ai besoin d'Excel pour me montrer un 9985,5 Donc un "," pas un ".". Je ne peux pas modifier cela manuellement dans chaque fichier.


Quel est le séparateur décimal utilisé par Excel?


Les fichiers csv ont "." comme séparateur décimal et votre Excel utilise également ".", les fichiers sont importés avec un ".", mais vous avez besoin que les fichiers csv soient importés avec "," comme séparateur décimal. C'est bien ça?


Non. Mon Excel utilise ",". Donc, dans mon csv, il y a un "." comme séparateur décimal. Oui correct. Lorsque j'ouvre les fichiers xlsx après avoir exécuté votre code, je peux le voir s'afficher avec "." et je peux voir qu'Excel ne reconnaît pas cela comme numérique. J'ai donc besoin d'Excel pour l'afficher avec "," (et le reconnaître comme numérique, mais je suppose que cela se ferait automatiquement). J'ai essayé de définir .TextFileDecimalSeparator.


Quand je l'ai réglé sur "." ça ne change rien. Quand je le mets sur "," alors j'obtiens des résultats corrects pour certaines colonnes, donc 9987,5 est affiché (ce qui est correct), mais d'autres colonnes sont transférées à tort. Cela se produit dans les deux cas ("," ou "." Set): Pour une colonne, il y avait des entrées avant comme 0,000 ou 1000,000. En fait, comme le 9987.5 Cependant, les 1000.000 sont transformés en 1.000.000, ce qui est faux. Je ne sais pas pourquoi cela se produit, comme dans les deux cas, donc 9987,5 et 1 000 000 le "." est le séparateur décimal et il n'y a qu'un seul "." dans les données d'origine (1000.000).


Je ne comprends donc pas pourquoi il change de 1000.000 à 1.000.000. Et comme je l'ai dit, cela arrive peu importe si je règle TextFileDecimalSeparator sur "," ou ".". Je m'attendrais à ce que lorsque je le règle sur "," alors 9987.5 se transforme en 9987,5 et 1.000 se transforme en 1000. Mais 1.000 est transformé en 1.000.000.


Je suppose que cette raison est que dans une colonne, il n'y a que deux chiffres au maximum après le séparateur (9987,5), mais dans l'autre cas, il y en a 3 (1.000) et cela influence cela.


Continuons cette discussion en chat .


Merci pour votre soutien continu et j'accepterai votre réponse. Cependant, une dernière question: dans les fichiers xlsx résultants, le nom de la feuille de tous les fichiers est "Sheet1". Je voudrais reporter cela du nom de fichier. Pour que le nom de la feuille résultant soit comme le nom de fichier (sans le .xslx). Est-ce possible?


Modifier pour renommer la feuille de calcul terminé.


J'ai essayé d'exécuter votre code. Quand je l'exécute, j'obtiens un message d'erreur Erreur d'exécution 7 pas assez d'espace et le débogueur marque la ligne .Refresh BackgroundQuery: = False Cependant, j'ai assez d'espace et quand j'exécute l'ancienne version d'avant la mise à jour avec le fichier / nom de feuille , ça fonctionne encore. Désolé pour ennuyeux.


Cela arrive déjà dans le premier fichier et celui-ci n'est pas vraiment volumineux.


Vous avez raison, c'est ennuyeux. J'ai testé le code (+70 fichiers différents) et il a fonctionné correctement. Néanmoins, j'ai déplacé la feuille de calcul renommée après l'actualisation de la requête. Essayez cette version.


Ça fonctionne maintenant! Merci beaucoup pour votre travail dévoué!



1
votes

À l'aide de l'objet ADODB.Stream, vous pouvez créer une fonction définie par l'utilisateur.

Sub all()

    Dim sourcepath As String
    Dim sDir As String
    Dim newpath As String
    Dim vResult As Variant
    Dim Wb As Workbook
    Dim Fn As String
     sourcepath = "C:\Users\PC\Desktop\Test\"
     newpath = sourcepath & "xlsx\"
     
     'make sure subfolder xlsx was created before
    
     sDir = Dir$(sourcepath & "*.csv", vbNormal)
     Application.ScreenUpdating = False
     Do Until Len(sDir) = 0
         'Workbooks.Open (sourcepath & sDir)
         'use adodb.stream
         vResult = TransToTextWithCsvUTF_8(sourcepath & sDir)
         Fn = Replace(sDir, ".csv", ".xlsx")
         
         Set Wb = Workbooks.Add
         With Wb
            Range("a1").Resize(UBound(vResult, 1) + 1, UBound(vResult, 2) + 1) = vResult
            .SaveAs Filename:=newpath & Fn, FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
            .Close
         End With
         
         sDir = Dir$
     Loop
     Application.ScreenUpdating = True
End Sub

Function TransToTextWithCsvUTF_8(strFn As String) As Variant
    Dim vR() As String
    Dim i As Long, r As Long, j As Integer, c As Integer
    Dim objStream  As Object
    Dim strRead As String
    Dim vSplit, vRow
    Dim s As String
    
    Set objStream = CreateObject("ADODB.Stream")

    With objStream
        .Charset = "utf-8"
        .Open
        .LoadFromFile strFn
         strRead = .ReadText
        .Close
    End With
    
    vSplit = Split(strRead, vbCrLf)
    r = UBound(vSplit)
    c = UBound(Split(vSplit(0), vbTab, , vbTextCompare))
    ReDim vR(0 To r, 0 To c)
    
    For i = 0 To r
        vRow = Split(vSplit(i), vbTab, , vbTextCompare)
        If UBound(vRow) = c Then 'if it is empty line, skip it
            For j = 0 To c
                If IsNumeric(vRow(j)) Then
                    s = Format(vRow(j), "#,##0.000")
                    s = Replace(s, ".", "+")
                    s = Replace(s, ",", ".")
                    s = Replace(s, "+", ",")
                    vR(i, j) = s
                Else
                    vR(i, j) = vRow(j)
                End If
            Next j
        End If
    Next i
    TransToTextWithCsvUTF_8 = vR
    
    Set objStream = Nothing

End Function


9 commentaires

J'ai copié votre code et ajusté le sPathSrc dans mon dossier (j'ai fait attention à avoir un autre "\" à la fin, donc non seulement ... \ Test mais ... \ Test \. Donc exactement comme le vôtre. Quand je essayez d'exécuter votre code, j'obtiens l'index d'erreur d'exécution 9 hors de la zone valide et le débogueur marque vR (i, j) = vRow (j)?


@BertHobe, l'erreur peut s'être produite car le nombre de caractères séparés par des tabulations dans le document texte est différent. Probablement parce qu'il est inférieur à 9 dans la ligne erronée.


Eh bien, chaque document txt peut avoir un nombre différent de colonnes?


@BertHobe, j'ai édité la réponse. S'il y a des lignes vides, sautez-les. If UBound(vRow) = c Then


J'ai copié le code et ajusté le chemin du fichier et créé le sous-dossier xlsx. Ensuite, je lance votre code. Lorsque je l'exécute, il ouvre un fichier et l'enregistre sous xlsx.xlsx. Le fichier suivant est à nouveau essayé d'être enregistré sous ce nom de fichier et on me demande si je veux remplacer le fichier. Cela ne fonctionne pas. J'ai besoin que les noms de fichiers soient là et cela doit fonctionner avec la boucle.


@ BertHobe, je pense que votre code est correct et je ne l'ai pas examiné.


@BertHobe, j'ai édité sub all() .


+1 pour votre soutien continu. Je l'ai essayé et cela fonctionne, mais je rencontre le problème avec le séparateur décimal et mille. Donc, dans mon csv, il y a des nombres comme 9987,5 Ils doivent être convertis en 9987,5. Et les nombres comme 1.000 qui dénotent des pièces ne sont pas correctement transformés, ils sont transformés en 1.000.000. Existe-t-il donc un moyen de définir le séparateur décimal sur "." et mille séparateur à ","? Ou faites-le fonctionner d'une autre manière.


@BertHobe, j'ai édité `Function TransToTextWithCsvUTF_8 () '. Cependant, les milliers et les décimales sont différents pour chaque pays, donc je ne sais pas quel type de pays votre système suit, j'ai donc remplacé les chiffres par des lettres.



-1
votes

Remplacez la ligne Set wb = Workbooks.Open (Filename: = strDir & strFile, Delimiter: = Chr (9), Local: = False) par

Set wb = Workbooks.OpenText(FileName:=strDir & strFile, DataType:=xlDelimited, Tab:=True)

Assurez-vous que c'est .txt afin de pouvoir simplement renommer le fichier .csv avant d'appeler la méthode "OpenText".

Cela force le transfert de données UTF-8: les "ä, ö et Ãœ", etc. seront déplacés vers Excel tels quels.


0 commentaires

1
votes

Cette méthode utilise l'objet du système de fichiers et le flux de texte pour passer de délimité par tabulation à délimité par des virgules. Sélectionnez Microsoft Scripting Runtime dans Outils / Références pour rendre disponible la bibliothèque utilisée. Si le point-virgule ne s'ouvre pas correctement, vous pouvez remplacer le troisième paramètre de la fonction REPLACE dans la ligne fileContents = Replace (fileContents, vbTab, ";") par une virgule et réessayer. Notez que nous créons un fichier .csv avec Set textStreamObj = fileSystemObj.CreateTextFile ("filePath2.csv") , sans écraser notre original.

Option Explicit

Sub changeDelimitedMarker()
    Dim fileSystemObj As Scripting.FileSystemObject
    Dim textStreamObj As Scripting.TextStream
    Dim fileContents As String
    
    Set fileSystemObj = New FileSystemObject
    Set textStreamObj = fileSystemObj.OpenTextFile("filePath1.csv")
    fileContents = textStreamObj.ReadAll
    textStreamObj.Close
    fileContents = Replace(fileContents, vbTab, ",")
    Set textStreamObj = fileSystemObj.CreateTextFile("filePath2.csv")
    textStreamObj.Write fileContents
    textStreamObj.Close
End Sub


3 commentaires

Eh bien, mon objectif est de le faire passer de csv à xlsx. Donc pas filePath2.csv, mais xlsx en conséquence.


Mais merci d'avoir partagé vos pensées, +1


@BertHobe ty pour +1, rappelez-vous qu'un fichier .csv peut être ouvert directement par classeur puis enregistré sous .xlsx