Хотите, чтобы VBA в excel читал очень большой CSV и создавал выходной файл небольшого подмножества CSV
У меня есть файл csv из 1,2 миллиона записей текста. Буквенно-цифровые поля завертываются в кавычки, даты/времени или числовых полей нет.
Например
"Фред", "Смит", 01/07/1967,2, "7, High Street", "Anytown", "Anycounty", "LS1 7AA"
Я хочу сделать, это написать VBA в Excel (более или менее единственный доступный мне инструмент, который я разумно умею использовать), который читает запись CSV по записи, выполняет проверку (как это происходит на последнее поле, почтовый индекс), а затем выводит небольшое подмножество записей в 1,2 м в новый выходной файл.
Я понимаю, как открыть два файла, прочитать запись, сделать то, что мне нужно сделать с данными и записать их (я просто выведу входную запись с префиксом, обозначающим тип исключения)
Я не знаю, как правильно разбирать CSV в VBA. Я не могу выполнить обычное сканирование текста и искать запятые, поскольку в тексте иногда есть запятые (следовательно, текстовые поля ограничены текстом)
Есть ли фантастическая команда, которая позволила бы мне быстро получить данные из n-го поля в моей записи?
Я хочу, чтобы s_work = field (s_input_record, 5) где 5 - номер поля в моем CSV....
Большое спасибо,
С
Ответы
Ответ 1
Следующий код должен сделать трюк. У меня нет Excel передо мной, поэтому я его не тестировал, но концепция звучит.
Если это заканчивается слишком медленно, мы можем посмотреть способы повышения эффективности.
Sub SelectSomeRecords()
Dim testLine As String
Open inputFileName For Input As #1
Open outputFileName For Output As #2
While Not EOF(1)
Line Input #1, testLine
If RecordIsInteresting(testLine) Then
Print #2, testLine
End If
Wend
Close #1
Close #2
End Sub
Function RecordIsInteresting(recordLine As String) As Boolean
Dim lineItems(1 to 8) As String
GetRecordItems(lineItems(), recordLine)
''// do your custom checking here:
RecordIsInteresting = lineItems(8) = "LS1 7AA"
End Function
Sub GetRecordItems(items() As String, recordLine as String)
Dim finishString as Boolean
Dim itemString as String
Dim itemIndex as Integer
Dim charIndex as Long
Dim inQuote as Boolean
Dim testChar as String
inQuote = False
charIndex = 1
itemIndex = 1
itemString = ""
finishString = False
While charIndex <= Len(recordLine)
testChar = Mid$(recordLine, charIndex, 1)
finishString = False
If inQuote Then
If testChar = Chr$(34) Then
inQuote = False
finishString = True
charIndex = charIndex + 1 ''// ignore the next comma
Else
itemString = itemString + testChar
End If
Else
If testChar = Chr$(34) Then
inQuote = True
ElseIf testChar = "," Then
finishString = True
Else
itemString = itemString + testChar
End If
End If
If finishString Then
items(itemIndex) = itemString
itemString = ""
itemIndex = itemIndex + 1
End If
charIndex = charIndex + 1
Wend
End Sub
Ответ 2
Как насчет VBScript, хотя это также будет работать в Excel:
Set cn = CreateObject("ADODB.Connection")
'Note HDR=Yes, that is, first row contains field names '
'and FMT delimted, ie CSV '
strCon="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\Docs\;" _
& "Extended Properties=""text;HDR=Yes;FMT=Delimited"";"
cn.open strcon
'You would not need delimiters ('') if last field is numeric: '
strSQL="SELECT FieldName1, FieldName2 INTO New.csv FROM Old.csv " _
& " WHERE LastFieldName='SomeTextValue'"
'Creates new csv file
cn.Execute strSQL
Ответ 3
Это напрямую не отвечает на ваш вопрос, но grep
(или один из эквивалентов Windows) действительно будет сиять для этого, например,
grep -e <regex_filter> foo.csv > bar.csv
Ответ 4
Я использовал следующую производную от приведенного выше кода, чтобы успешно открыть произвольный файл csv из VBA в Excel.
Вариант Явный Public cn As Connection
Public Sub DoIt()
Dim strcon As String
Dim strsql As String
Dim rs As Recordset
Установить cn = CreateObject ( "ADODB.Connection" )
strcon = "Provider = Microsoft.Jet.OLEDB.4.0; Источник данных = C:\bin\HomePlanet \;" _
и "Расширенные свойства =" ", HDR = Да; FMT = Разграничено" ";"
cn.Open strcon
strsql = "SELECT * FROM astuname.csv"
Set rs = Новый ADODB.Recordset
rs.Open strsql, cn
DoEvents приостанавливают здесь проверку объектов и свойств rs.Close
End Sub
У rs (recordset) есть набор полей с свойством Count. Каждое поле является свойством типа.
Вы можете ссылаться на поля по порядковому номеру...
Debug.Print rs.Fields(rs.Fields.Count - 1). Тип
Достаточно ли этого?
Если нет, разместите первые несколько строк входного файла, и я оставлю весь путь.
Ответ 5
Посмотрите инструкцию Input #
в справке Excel
Пример использования будет:
Input #fnInput, s_Forename, s_Surname, dt_DOB, i_Something, s_Street, s_Town, s_County, s_Postcode
а затем используйте оператор Write #
для повторной записи записей соответствия
Единственная проблема может заключаться в том, что формат даты на выходе будет выглядеть как # 1967-07-01 #, но этот формат недвусмыслен в отличие от 01/07/1967, который будет представлять 1 июля в Великобритании и 7 января в НАС. Если вам нужно сохранить форматирование даты, выпишите ее как строку:
s_DOB = Format(dt_DOB, "dd/mm/yyyy")
Ответ 6
Все, что вы можете сделать с помощью vba в excel, вы можете делать с помощью vba; плюс намного больше, потому что это база данных, а не электронная таблица. Доступ недоступен для вас?
Намного легче справляться с логическими таблицами, записями и полями, чем с логическими листами, строками и столбцами.
Для ввода, почему "/Data/Import External Data/Text/csv" не работает? Является ли вход не по-настоящему портативным csv?
Ответ 7
Я бы предложил взглянуть на библиотеку Regular Expression (вы должны увидеть ее в "Инструменты... Ссылки" как "Microsoft VBScript Regular Expressions 5.5" или что-то очень похожее.
В этом месте есть образцы как Reg Exp, так и довольно всеобъемлющего символа-символа: http://www.xbeat.net/vbspeed/c_ParseCSV.php. Обратите внимание, что версия Regexp короче!
Удачи...