簡體   English   中英

通過 VBA 打開 CSV 文件(性能)

[英]Open CSV file via VBA (performance)

顯然,這個問題已經被問過很多次了。 正常程序:

Workbooks.Open (ActiveWorkbook.Path & "\\Test.csv")

不會正確解析 CSV(一個單元格中有很多行)

感謝 Lernkurve,我可以使用他的功能來解決問題: 打開分號分隔的 CSV 文件

Sub ImportCSVFile(filepath As String)
Dim line As String
Dim arrayOfElements
Dim linenumber As Integer
Dim elementnumber As Integer
Dim element As Variant

linenumber = 0
elementnumber = 0

Open filepath For Input As #1 ' Open file for input
    Do While Not EOF(1) ' Loop until end of file
        linenumber = linenumber + 1
        Line Input #1, line
        arrayOfElements = Split(line, ";")

        elementnumber = 0
        For Each element In arrayOfElements
            elementnumber = elementnumber + 1
            Cells(linenumber, elementnumber).Value = element
        Next
    Loop
Close #1 ' Close file.
End Sub

然而,這並不快(我有數千列的文件),我的問題是:

是否有任何本地方法可以通過正確解析在 Excel 中打開 CSV 文件?

Workbooks.Open也可以。

Workbooks.Open ActiveWorkbook.Path & "\\Temp.csv", Local:=True

這是有效的/需要的,因為我在德國使用 Excel,而 excel 確實使用“,”來分隔 .csv 默認情況下,因為我使用英文安裝的 windows。 即使您使用下面的代碼,excel 也會強制使用“,”分隔符。

Workbooks.Open ActiveWorkbook.Path & "\\Test.csv", , , 6, , , , , ";"

Workbooks.Open ActiveWorkbook.Path & "\\Temp.csv", , , 4 +variants of this 不起作用(!)

如果被本地參數阻止,為什么他們甚至有分隔符參數?! 這完全沒有意義。 但現在它起作用了。

此函數讀取 15MB 的 CSV 文件,並在大約 3 秒內將其內容復制到工作表中。 在您的代碼中可能需要花費大量時間的事實是您逐個單元地復制數據而不是一次放置整個內容。

Option Explicit

Public Sub test()

  copyDataFromCsvFileToSheet "C:\temp\test.csv", ",", "Sheet1"

End Sub

Private Sub copyDataFromCsvFileToSheet(parFileName As String, parDelimiter As String, parSheetName As String)

  Dim data As Variant

  data = getDataFromFile(parFileName, parDelimiter)
  If Not isArrayEmpty(data) Then
    With Sheets(parSheetName)
      .Cells.ClearContents
      .Cells(1, 1).Resize(UBound(data, 1), UBound(data, 2)) = data
    End With
  End If

End Sub

Public Function isArrayEmpty(parArray As Variant) As Boolean
'Returns false if not an array or dynamic array that has not been initialised (ReDim) or has been erased (Erase)

  If IsArray(parArray) = False Then isArrayEmpty = True
  On Error Resume Next
  If UBound(parArray) < LBound(parArray) Then isArrayEmpty = True: Exit Function Else: isArrayEmpty = False

End Function

Private Function getDataFromFile(parFileName As String, parDelimiter As String, Optional parExcludeCharacter As String = "") As Variant
'parFileName is supposed to be a delimited file (csv...)
'parDelimiter is the delimiter, "," for example in a comma delimited file
'Returns an empty array if file is empty or can't be opened
'number of columns based on the line with the largest number of columns, not on the first line
'parExcludeCharacter: sometimes csv files have quotes around strings: "XXX" - if parExcludeCharacter = """" then removes the quotes


  Dim locLinesList() As Variant
  Dim locData As Variant
  Dim i As Long
  Dim j As Long
  Dim locNumRows As Long
  Dim locNumCols As Long
  Dim fso As Variant
  Dim ts As Variant
  Const REDIM_STEP = 10000

  Set fso = CreateObject("Scripting.FileSystemObject")

  On Error GoTo error_open_file
  Set ts = fso.OpenTextFile(parFileName)
  On Error GoTo unhandled_error

  'Counts the number of lines and the largest number of columns
  ReDim locLinesList(1 To 1) As Variant
  i = 0
  Do While Not ts.AtEndOfStream
    If i Mod REDIM_STEP = 0 Then
      ReDim Preserve locLinesList(1 To UBound(locLinesList, 1) + REDIM_STEP) As Variant
    End If
    locLinesList(i + 1) = Split(ts.ReadLine, parDelimiter)
    j = UBound(locLinesList(i + 1), 1) 'number of columns
    If locNumCols < j Then locNumCols = j
    i = i + 1
  Loop

  ts.Close

  locNumRows = i

  If locNumRows = 0 Then Exit Function 'Empty file

  ReDim locData(1 To locNumRows, 1 To locNumCols + 1) As Variant

  'Copies the file into an array
  If parExcludeCharacter <> "" Then

    For i = 1 To locNumRows
      For j = 0 To UBound(locLinesList(i), 1)
        If Left(locLinesList(i)(j), 1) = parExcludeCharacter Then
          If Right(locLinesList(i)(j), 1) = parExcludeCharacter Then
            locLinesList(i)(j) = Mid(locLinesList(i)(j), 2, Len(locLinesList(i)(j)) - 2)       'If locTempArray = "", Mid returns ""
          Else
            locLinesList(i)(j) = Right(locLinesList(i)(j), Len(locLinesList(i)(j)) - 1)
          End If
        ElseIf Right(locLinesList(i)(j), 1) = parExcludeCharacter Then
          locLinesList(i)(j) = Left(locLinesList(i)(j), Len(locLinesList(i)(j)) - 1)
        End If
        locData(i, j + 1) = locLinesList(i)(j)
      Next j
    Next i

  Else

    For i = 1 To locNumRows
      For j = 0 To UBound(locLinesList(i), 1)
        locData(i, j + 1) = locLinesList(i)(j)
      Next j
    Next i

  End If

  getDataFromFile = locData

  Exit Function

error_open_file:             'returns empty variant
unhandled_error:             'returns empty variant

End Function

您是否嘗試過導入文本功能

這可能對您有所幫助,也取決於您的CSV文件的格式。

  1. 打開您的 Excel 工作表並轉到菜單Data > Import External Data > Import Data
  2. 選擇您的CSV文件。
  3. 原始數據類型:選擇Fixed width ,然后Next
  4. 它將自動分隔您的columns 然后,您可以在Data preview面板中查看拆分的列。
  5. 然后Finish並查看。

注意:您也可以使用Delimited作為原始數據類型。 在這種情況下,您需要鍵入分隔符。

哼!

我有同樣的問題,我無法在 Excel 中打開 CSV 文件。 我在這個問題中找到了一個對我有用的解決方案Opening a file in excel via Workbooks.OpenText

這個問題幫助我找出了一個適合我的代碼。 代碼看起來或多或少是這樣的:

Private Sub OpenCSVFile(filename as String)
    Dim datasourceFilename As String
    Dim currentPath As String

    datasourceFilename = "\" & filename & ".csv"
    currentPath = ActiveWorkbook.Path

    Workbooks.OpenText Filename:=currentPath & datasourceFilename, _
                       Origin:=xlWindows, _
                       StartRow:=1, _
                       DataType:=xlDelimited, _
                       TextQualifier:=xlDoubleQuote, _
                       ConsecutiveDelimiter:=False, _
                       Tab:=False, _
                       Semicolon:=False, _
                       Comma:=True, _
                       Space:=False, _
                       Other:=False, _
                       FieldInfo:=Array(Array(1, 1), Array(2, 1)), _
                       DecimalSeparator:=".", _
                       ThousandsSeparator:=",", _
                       TrailingMinusNumbers:=True
End Sub

至少,它幫助我了解了可以與Workbooks.OpenText方法一起使用的許多參數。

有時無論設置多少參數,Workbooks.open 的所有解決方案都不起作用。 對我來說,最快的解決方案是更改區域和語言設置中的列表分隔符。 區域窗口/附加設置.../列表分隔符。

如果 csv 未以正確方式打開您可能已將“,”設置為列表分隔符。 只需將其更改為';' 一切都解決了。 當“一切都與你作對”時,這是最簡單的方法:P

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM