Открыть файл CSV через VBA (производительность)
Очевидно, этот вопрос задавался много раз. Нормальная процедура:
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
Это, однако, не быстро (у меня есть файлы с тысячами столбцов), и мой вопрос:
Есть ли какой-нибудь родной способ открыть файлы CSV в Excel с правильным разбором?
Ответы
Ответ 1
Workbooks.Open
тоже работает.
Workbooks.Open ActiveWorkbook.Path & "\Temp.csv", Local:=True
это работает/требуется, потому что я использую Excel в Германии, и excel использует "," для разделения .csv по умолчанию, потому что я использую английскую установку окон. даже если вы используете код ниже excel, разделите разделитель ",".
Workbooks.Open ActiveWorkbook.Path & "\Test.csv", , , 6, , , , , ";"
и Workbooks.Open ActiveWorkbook.Path & "\Temp.csv", , , 4
+ варианты этого не работают (!)
почему они даже имеют параметр разделителя, если он заблокирован локальным параметром?! это не имеет никакого смысла. но теперь он работает.
Ответ 2
Эта функция считывает CSV файл размером 15 МБ и копирует его содержимое в лист примерно через 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
Ответ 3
Вы пробовали импортировать текстовую функцию.
Ответ 4
Это может вам помочь, также зависит от того, как формируется ваш файл CSV
.
- Откройте свой лист Excel и перейдите в меню
Data
> Import External Data
> Import Data
.
- Выберите файл
CSV
.
- Исходный тип данных: выберите
Fixed width
, затем Next
.
- Это автоматически разделит ваш
columns
. то вы можете проверить расщепленные столбцы на панели Data preview
.
- Затем
Finish
и посмотрим.
Примечание. Вы также можете перейти с Delimited
в качестве исходного типа данных.
В этом случае вам нужно ввести свой разделительный символ.
НТН!
Ответ 5
У меня такая же проблема, я не могу открыть CSV файл в Excel. Я нашел решение, которое сработало для меня в этом вопросе Открытие файла в excel через 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
.