2017-02-11 3 views
0

Ich habe eine .csv-Datei von meinem Bankkonto exportiert, die derzeit in Excel über Excel importiert wird und dann mit meinem Makro verarbeitet (einige Spalten löschen, Formatänderungen, concat, etc .. nichts besonderes).Excel-Makro zum Wählen, was und wo aus CSV importieren

Die CSV-Datei hat jedoch kein konsistentes Format und es gibt Spalten, die ihre Position ändern (zB Spalte "IBAN" ist manchmal Spalte Nr. 2, manchmal Nr. 5) oder gar nicht vorhanden, was verursacht, dass mein Makro abstürzt.

Was ich brauche, ist ein Code, der zuerst mit der .csv arbeiten würde, überprüfen Sie die .csv für die Spalte "IBAN" und importieren Sie es nach der Prüfung, so würde es immer sagen wir Spalte Nr. 1 und mein Makro würde Spalte Nr. Verarbeiten. 1 ohne Probleme.

Irgendwelche Ideen?

+0

Ich wollte der Suche nach Namen vorschlagen Spaltennummern, um zu bestimmen, aber das ist wahrscheinlich besser gelöst, indem ADO mit der CSV-Datei unter Verwendung einer SQL 'SELECT' Anweisung lesen - auf diese Weise Sie konsistente Daten gehen in haben könnte konsistente Spalten. – YowE3K

+0

YowE3K hast du zufällig irgendwelche Ressourcen, wie man das mit ADO macht? Was den ursprünglichen Beitrag betrifft, würde ich empfehlen, die Methode .Range.Find() zu verwenden, um nach bestimmten Spalten zu suchen und diese Spalten dann in Bereichen zu speichern. Ich werde sehen, ob ich ein Beispiel in einem Bit posten kann. –

+0

@BrandonBarney - Ich könnte ein Beispiel erstellen, aber es wird einfacher sein, wenn ich morgen zur Arbeit komme. (Wir verwenden SQL, um CSV-Dateien bei der Arbeit zu lesen, aber ich muss sehr selten dasselbe zu Hause tun - meine Bank legt keine Spaltenüberschriften in ihre CSV-Dateien!) – YowE3K

Antwort

1

So etwas sollte funktionieren, und ist ziemlich unkompliziert. Sie können auch zusätzliche Argumente mit der Suchfunktion verwenden, um festzulegen, wo Sie suchen:

Public Function GetColumnRange(ByVal sSearch As String, r As Object, rSearchArea As Range) 
If Not rSearchArea.Find(sSearch, , , xlWhole) Is Nothing Then 
    Set r = rSearchArea.Find(sSearch, , , xlWhole) 
    r.Select 
    GetColumnRange = True 
End If 

End Function Public Sub CSV_Reformat() Dim wb Wie Arbeitsmappe Dim ws Wie Arbeitsblatt

Dim arrArgs() As Variant 

Dim cColl As Collection 

Dim rHolder As Object 

Set cColl = New Collection 
arrArgs() = Array("IBAN", "Arg2", "Arg3") 

' Use the code you have to load the .CSV file and to open it 
' Assumes that wb is set to the .CSV file 
' Assumes ws is the first sheet in the .CSV file 

Set wb = ActiveWorkbook ' Replace this with your actual .CSV file 
Set ws = wb.Sheets(1) 

For i = LBound(arrArgs()) To UBound(arrArgs()) 
    If GetColumnRange(arrArgs(i), rHolder, ws.UsedRange) = True Then 
     cColl.Add rHolder 
    End If 
Next 

For i = 1 To cColl.Count 
    Set rHolder = cColl(i) 

    ' Do whatever you need to do with the range here 
    ' For example, you could get the column number: 

    Debug.Print rHolder.Column 
Next 

End Sub 

Ich würde auch empfehlen, ein Array dafür zu verwenden, wenn Ihre CSV-Datei größer ist. Sie können das Array laden Sie sich mit:

Dim arrData() as Variant 
Dim i as Long, Dim j as Long 
Dim lOutput as Long 
Dim bool as Boolean 

' Assumes, as before, that ws is the worksheet we are working in 

arrData() = ws.UsedRange.Value 

Sie können dann ein neues Array für die Ausgabe etwas wie folgt erstellen:

Dim arrOut() as Variant 

redim arrOut(0 to Ubound(arrData()) - 1, 0 to i) 

' Reduce it by one row since we are creating a zero based array. i is the 
' number of columns you want in the output. 

' Then loop over the data array and put the right columns into your output 

For i = 1 to Ubound(arrData(), 2) ' Loop through the headers in your data 
    bool = True 
    Select Case arrData(1, i) 
     Case "IBAN" 
      lOutput = 0 ' Allows you to determine where the data will be put in your array 
     Case "Arg2" 
      lOutput = 1 
     Case "Arg3" 
      lOutput = 2 
     Case Else 
      bool = False 
    End Select 

    If bool = True Then 
     For j = 1 to Ubound(arrData(), 1) 
      arrOut(j - 1, lOutput) = arrData(j, i) 
     Next 
    End If 
Next 

Dies sollte Ihnen ermöglichen, bestimmte Daten aus der CSV-Datei und laden zu wählen es in ein Array. Sie können dann Ihre Daten nach Bedarf auf einen Bereich ausgeben. Zum Beispiel

With wsOutput 
    Set r = .Range("A1").Resize(Ubound(arrOut(), 1) + 1, Ubound(arrOut(), 2) + 1) 
    r.Value = arrOut() 
End With 
0

Der folgende Code verwendet ADODB eine SQL-Abfrage auf der CSV-Datei auszuführen, damit nur die Spalten importieren, die Sie in der gewünschten Reihenfolge, in der Sie sie wünschen.

Sub SQL_Extract() 
    Dim objConnection   As Object 
    Dim objRecordset   As Object 
    Dim CSVFilename    As String 
    Dim CSVFilepath    As String 

    CSVFilename = "myCSVFile.csv"   ' Change to name of your CSV file 
    CSVFilepath = "C:\Temp\DownloadFolder\" ' Change to location of CSV file 

    ' Set up connections & dataset objects 
    Set objConnection = CreateObject("ADODB.Connection") 
    Set objRecordset = CreateObject("ADODB.Recordset")  
    objConnection.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;" & _ 
            "Data Source=" & CSVFilepath & ";" & _ 
            "Extended Properties=""text;HDR=YES;FMT=CSVDelimited"";" 
    objConnection.Open 

    'Create the SQL command to retrieve information 
    'The following assumes that the CSV file contains columns with headings of 
    ' "IBAN", "Transaction Date" and "Amount". (Any other columns in the file 
    ' will be ignored.) 
    sqlCommand = "SELECT [IBAN], " & _ 
       "  [Transaction Date], " & _ 
       "  [Amount] " & _ 
       "FROM [" & CSVFilename & "]" 
    'Execute the query 
    objRecordset.Open sqlCommand, objConnection, 3, 3, 1 

    If Not objRecordset.EOF Then ' Check whether any records were created by the query 
     ' Write out the results of the query 
     ' Change "A2" to top left cell of area where you want results written 
     Range("A2").CopyFromRecordset objRecordset 
    End If 

    objRecordset.Close 
    objConnection.Close 
End Sub 
Verwandte Themen