Хотите, чтобы 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 короче!

Удачи...