Как прочитать кусками текстовый файл vba
Перейти к содержимому

Как прочитать кусками текстовый файл vba

  • автор:

Как прочитать текстовый файл в VBA

В нынешнее время использование текстовых файлов для обмена данными или хранения данных становится редкостью, но тем не менее, все еще встречается. Приведу два варианта чтения текстового файла из VBA. Каждый способ может быть полезен в своей ситуации.

Способ 1. Открытие (чтение) текстового файла целиком

Можно открыть текстовый файл без учета каких-либо разделителей, сплошным текстом:

Set objExcel = New Excel.Application Set wb = objExcel.Workbooks.Open("имя_файла")

либо, если используются разделители колонок, можно их задействовать:

Открытие текстового файла с разделителем Tab:

Set objExcel = New Excel.Application Set wb = objExcel.Workbooks wb.OpenText Filename:="имя_файла", DataType:=xlDelimited, Tab:=True

Открытие текстового файла с разделителем ; (точка с запятой):

Set objExcel = New Excel.Application Set wb = objExcel.Workbooks wb.OpenText Filename:="имя_файла", DataType:=xlDelimited, Other:=True, OtherChar:=";"

В параметрах можно так же добавить Origin:=xlMSDOS , если текстовый файл в DOS-кодировке.

После открытия файла, его можно пройти как обычные ячейки Excel-кого листа.

Способ 2. Чтение текстового файла построчно

Здесь используется классический вариант чтения как в большинстве языков программирования: открытие файла, цикл чтения построчно, закрытие файла.

f = FreeFile Open "имя_файла" For Input As #f Do While Not EOF(f) Line Input #f, s ' что-нибудь делаем с полученной строкой s Loop Close f

В первой строке определяем число, представляющее следующий номер файла, доступный для использования оператором Open. Затем открываем файл, после чего делаем цикл в котором происходит построчное чтение.

Как прочитать кусками текстовый файл vba

Копирование из текстового файла в заданные ячейки книги

Geart:
Добрый день. Возникла задача копирования заданного числа знаков из известной строчки текстового файла. Возможно ли это реализовать на VBA? Я новичок в этом деле, поэтому если можно объяснять по понятнее. 🙂 Пример тестового файла во вложении.

McConst:
Принципиально это возможно. Вод код, который использует функцию для чтения произвольной строки с определенной длиной начиная от заданной позиции. Если длина не задана, по умолчанию берется длина всей строки. Если позиция в строке не задана, по умолчанию берется позиция первого символа в строке.
Код: (vb)
Public Sub test()
Worksheets(1).Cells(1, 1) = FileToString(File:=»C:/Doosan_report_2013-07-17.txt»)
End Sub

Public Function FileToString(File As String, Optional Row As Long = 1, Optional Position As Long = 1, Optional length As Long = 0) As String
‘Чтение куска текста из файла

Dim text As String ‘Сюда будем читать весь текст из файла
Dim List As Variant ‘Здесь текст будет храниться построчно
Dim oStream

Set oStream = CreateObject(«ADODB.Stream»)
With oStream
.Type = 2 ‘Текстовый файл
.Charset = «utf-8» ‘Кодировка, в которой хранится текст в данном файле
.Open
.LoadFromFile File
text = .ReadText ‘Чтение текста из файла в переменную
.Close
End With
Set oStream = Nothing

List = Split(text, vbCrLf)
‘Если длина не задана, тогда длина будет равна длине строки в файле
If length = 0 Then length = Len(List(Row))
‘проверяем, чтобы заданная в функции длина не превышала длины строки в файле от указанной позиции
If length > (Len(List(Row)) — Position + 1) Then length = Len(List(Row)) — Position + 1
FileToString = Mid(List(Row), Position, length)

Но вообще рекомендую переделать этот код под себя, так как данная функция, чтобы вернуть нужный кусок текста, читает весь файл. Если таких кусков много, а файл большой, она будет каждый раз читать один и тот же файл для разных кусков текста, и это скажется на производительности программы. Данная функция просто пример того, как можно реализовать вашу просьбу.
Ниже прикреплен работающий файл. Потестите, если хотите.

Geart:
Спасибо вам огромное, будем разбираться. )))

kuklp:
Можно проще:
Код: (vb)
Public Sub test()
Dim fName$, mRow&, mLen&, mPos&
fName = «D:\DOKUMENT\EXCEL\Module1.txt»
mRow = 9: mLen = 30: mPos = 10
Worksheets(1).Cells(1, 1) = www(fName, mRow, mPos, mLen)
End Sub

kuklp:
Сейчас только посмотрел файл ТС. Там еще проще можно(макрорекордер):
Код: (vb)
Sub www()
Application.DisplayAlerts = 0
ActiveWorkbook.Sheets.Add
ActiveWorkbook.XmlImport URL:=»H:\Doosan_report_2013-07-17.txt», ImportMap _
:=Nothing, Overwrite:=True, Destination:=Range(«A1»)
Application.DisplayAlerts = -1
End Sub
или:
Sub www1()
Код: (vb)
With ActiveSheet.QueryTables.Add(Connection:= _
«TEXT;H:\Doosan_report_2013-07-17.txt», Destination:=Range(«A1»))
.Name = «Doosan_report_2013-07-17_8»
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = -535
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = False
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
ActiveSheet.UsedRange.Replace vbTab, «», xlPart
End Sub
А там уж выбирай нужную строку 🙂

Чтение нужной строки текствого файла

Чтение нужной строки из файла
С помощью функций Win Api на C написать программу, которая по заданному файлу и слову выводит все.

Чтение нужной строки из файла
Есть файл расположенный в папке с проектом. В нем пока 2 строки, необходимо считать нужную строку.

Построчное чтение из файла до нужной строки
Доброго времени суток. И снова война с текстовым файлом. Суть куска программы: построчное чтение.

Чтение из файла в нужной кодировке
Помогите, пожалуйста. Я делаю считывание из файла при помощи StreamReader и считываю данные.

3480 / 1865 / 389
Регистрация: 13.12.2016
Сообщений: 6,355
Записей в блоге: 5
Ципихович Эндрю, а что мешает ограничить цикл 12-ю и по условию считать данные?
1525 / 494 / 58
Регистрация: 10.04.2009
Сообщений: 8,326
потому, что в цикле я не могу указывать переменные

а = 12 For J = а To а

а с чистого листа если его писать, то легкотня

For J = 12 To 12

es geht mir gut
11267 / 4749 / 1183
Регистрация: 27.07.2011
Сообщений: 11,439

ЦитатаСообщение от Ципихович Эндрю Посмотреть сообщение

строк много
примерно сколько?
1525 / 494 / 58
Регистрация: 10.04.2009
Сообщений: 8,326
es geht mir gut
11267 / 4749 / 1183
Регистрация: 27.07.2011
Сообщений: 11,439

ЦитатаСообщение от Ципихович Эндрю Посмотреть сообщение

Ну миллион, не знаю, потянет ли. Можно попробовать так

1 2 3
Dim a As String, n As Long n = 12 a = Split(CreateObject("Scripting.FileSystemObject").Getfile("C:\Temp\test.txt").OpenasTextStream(1).ReadAll, vbNewLine)(n - 1)

es geht mir gut
11267 / 4749 / 1183
Регистрация: 27.07.2011
Сообщений: 11,439

Проверил на 1 290 000 строк. Строки правда короткие. Отрабатывает за 18 секунд. Не знаю насколько это приемлемо.

es geht mir gut
11267 / 4749 / 1183
Регистрация: 27.07.2011
Сообщений: 11,439
Если в цикле это делать, то вообще 1 секунда. Даже если номер строки 1200000

1 2 3 4 5 6 7 8 9 10 11 12 13
Dim a As String, n As Long, t As Date, k As Long n = 1200000 t = Time Open "C:\Temp\test.txt" For Input As #1 Do While Not EOF(1) Input #1, a k = k + 1 If k = n Then Exit Do Loop Close #1 MsgBox "Время чтения(сек): " & Abs(DateDiff("s", t, Time)) & vbCrLf & "Строка: " & a & vbCrLf & "Номер строки: " & k

3480 / 1865 / 389
Регистрация: 13.12.2016
Сообщений: 6,355
Записей в блоге: 5

ЦитатаСообщение от SoftIce Посмотреть сообщение

Если в цикле это делать, то вообще 1 секунда.
Так и я об этом!
15140 / 6414 / 1730
Регистрация: 24.09.2011
Сообщений: 9,999

Для Split необязательно весь файл считывать. Если известна макс. длина строки, то достаточно считать 12*максДлина.
Можно считывать например 4 кб (типичный размер кластера на диске)

1 2 3 4
Dim myString As String Open "c:\temp\test.txt" For Input As #1 myString = Split(Input(4096, 1), vbNewLine)(11) Close #1

1525 / 494 / 58
Регистрация: 10.04.2009
Сообщений: 8,326

ЦитатаСообщение от Казанский Посмотреть сообщение

Если известна макс. длина строки
строка при записи строки в файл

Print #1, String(89161710, "a")

выдает ошибку
Out of string space
строка

Print #1, String(89161709, "a")

отрабатывается без ошибки
что это за число наибольшей возможной строки в файле 89 млн 161 тысяча 709, почему именно столько?
в разных кодировках текстового файла возможно и больше можно добавить?? хотя и так огромный слой инфы можно поместить))
в коде я добавляю букву а, а если другой знак, количество допустимой строки будет увеличиваться, уменьшаться?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Sub Создать_тестовый_файл() Dim Старт_программы As Date Старт_программы = Time 'создать текстовый файл из 21 474 836 47 строк, дина каждой строки 89161709 Dim J As Long Open "c:\1.txt" For Output As 1 For J = 1 To 2147483647 Print #1, String(89161709, "a") 'Debug.Print J Next J Close 1 MsgBox$ _ "Начато: " & Старт_программы & Chr$(13) & _ "Закончено: " & Time End Sub

но при открытии файла Блокнот++ говорит File open problem
при каких значениях — количество строк, дина строки он будет открываться? спс

Как прочитать кусками текстовый файл vba

Добрый день уважаемые Формучане!
Стала перед мной нетривиальная задача заполнение данных в таблицу из множества текстовых файлов > 1000 шт. Указанные файлы содержат данные о IP адресах и данные о регистраторах доменов. Каждый файл содержит только одни интересующие сведения об интересующем IP адресе. Интересуют только определенные поля: value, handle, startAddress, endAddress, name, country, description, eventDate, label. Помимо интересующих сведений текстовый файл содержит иную не интересующую меня информацию.
Стоит задача извлечь данные с указанных текстовых файлов и заполнить указными сведения таблицу. имеющие аналогичные заголовки: value, handle (которое может повторятся несколько раз в одном текстовом файле мне нужны его все значения поэтому я сделал 4 столба handle_1, handle_2 и тд.), startAddress, endAddress, name, country, description (которое может повторятся несколько раз в одном текстовом файле), eventDate, label.

Я попытался решить самостоятельно данную задачу по средствам Power Query я собрал все текстовые файлы в одну книгу (данные идут в строчку более 30 тыс. строк) после чего начал посредством формул выдергивать из текста интересующие куски информации и подставлять их в таблицу имеющие заголовки value, handle, startAddress, endAddress, name, country, description, eventDate, label. Помимо этого я сделал столбец port43 который указывает мне что после него идут строки следующего текстового файла и так далее… Извлечь данные из строк получилось, однако привести их »Божеский» вид так и не получилось. Пытался структурировать значения, в строки чтоб в конечном итоги перевести в таблицу, однако помимо Каши из значений у меня ничего не вышло.

В конечном итоге хотелось бы получить обычную таблицу в каждой строке которой содержались бы интересующие сведения из текстовый файлов. Буду признателен дельными советами.

Прикрепленные файлы

  • 216.162.47.76.txt (8.71 КБ)
  • пример.xlsx (25.39 КБ)

Пользователь
Сообщений: 290 Регистрация: 23.09.2019
04.01.2020 15:01:15

Нарисуйте пожалуйста таблицу, которую вы видите, то, что должно в итоге получиться. По Вашему запросу не совсем понятно, что именно нужно сделать.

PS Имеется ввиду в экселе

PPS Если вопрос только в том, чтобы каким-то образом в строчки все это записать, я бы поизвращался вот таким способом, и по какому-нибудь критерию выдернул сводную строчку со всеми значениями.

Прикрепленные файлы

  • пример.xlsx (41.72 КБ)

Изменено: lostandleft — 04.01.2020 15:17:13
Пользователь
Сообщений: 2054 Регистрация: 01.07.2018
04.01.2020 17:13:24
Виктор C, попробуйте так в Power Query

let Source = Table.FromColumns(), #"Added Conditional Column" = Table.AddColumn(Source, "gr", each if Text.Contains([Column1], "value") then 1 else if Text.Contains([Column1], "handle") then 2 else if Text.Contains([Column1], "startAddress") then 3 else if Text.Contains([Column1], "endAddress") then 4 else if Text.Contains([Column1], "name") then 5 else if Text.Contains([Column1], "country") then 6 else if Text.Contains([Column1], "description") then 7 else if Text.Contains([Column1], "eventDate") then 8 else if Text.Contains([Column1], "label") then 9 else null), #"Filtered Rows" = Table.SelectRows(#"Added Conditional Column", each [gr] <> null and [gr] <> ""), #"Grouped Rows" = Table.Group(#"Filtered Rows", , >), #"Added Conditional Column2" = Table.AddColumn(#"Grouped Rows", "b", each if [gr] <> 7 and [gr] <> 2 then Table.FirstN([a],1) else [a]), #"Changed Type" = Table.TransformColumns(#"Added Conditional Column2",>), #"Sorted Rows" = Table.Sort(#"Changed Type",>)[[b]], #"Expanded " = Table.ExpandTableColumn(#"Sorted Rows", "b", , ), #"Split Column by Delimiter" = Table.SplitColumn(#"Expanded ", "Column1", Splitter.SplitTextByEachDelimiter(, QuoteStyle.Csv, false), ), #"Merged Columns" = Table.CombineColumns(Table.TransformColumnTypes(#"Split Column by Delimiter", >, "ru-RU"),,Combiner.CombineTextByDelimiter("_", QuoteStyle.None),"Сведено"), #"Added Conditional Column1" = Table.AddColumn(#"Merged Columns", "a", each if Text.End([Column1.2],1)="," then Text.BeforeDelimiter([Column1.2], ",", ) else [Column1.2])[[Сведено],[a]], #"Pivoted Column" = Table.Pivot(#"Added Conditional Column1", List.Distinct(#"Added Conditional Column1"[Сведено]), "Сведено", "a") in #"Pivoted Column"

Изменено: artyrH — 05.01.2020 20:56:16
Сообщений: 22110 Регистрация: 28.12.2016
Excel 2013, 2016
04.01.2020 17:40:03
Я могу ошибатся, но если дать расширение файлам json, то задача в разы упростится.
По вопросам из тем форума, личку не читаю.
Пользователь
Сообщений: 11891 Регистрация: 22.12.2012
Excel 2016, 365
04.01.2020 17:50:01

Цитата
БМВ написал:
но если дать расширение файлам json, то задача в разы упростится.

Привет, Михаил.
Чем упростится? Ну, вот версия для Json хардкодномышкоклацательная

let Source = Json.Document(File.Contents("C:\Path\216.162.47.76.txt")), base = Table.FromRows(, Record.FieldNames(Source)), step1 = Table.SelectColumns(base,), #"Expanded " = Table.ExpandListColumn(step1, "links"), #"Expanded 1" = Table.ExpandListColumn(#"Expanded ", "entities"), #"Expanded 2" = Table.ExpandRecordColumn(#"Expanded 1", "links", , ), #"Expanded 3" = Table.ExpandRecordColumn(#"Expanded 2", "entities", , ), #"Expanded 4" = Table.ExpandListColumn(#"Expanded 3", "links"), #"Expanded 5" = Table.ExpandListColumn(#"Expanded 4", "entities.1"), #"Expanded 6" = Table.ExpandRecordColumn(#"Expanded 5", "links", , ), #"Expanded 7" = Table.ExpandRecordColumn(#"Expanded 6", "entities.1", , ), #"Expanded 8" = Table.ExpandListColumn(#"Expanded 7", "links"), #"Expanded 9" = Table.ExpandListColumn(#"Expanded 8", "entities"), #"Expanded 10" = Table.ExpandRecordColumn(#"Expanded 9", "links", , ), #"Expanded 11" = Table.ExpandRecordColumn(#"Expanded 10", "entities", , ), #"Expanded 12" = Table.ExpandListColumn(#"Expanded 11", "links"), #"Expanded 13" = Table.ExpandRecordColumn(#"Expanded 12", "links", , ) in Table.Distinct(#"Expanded 13")

Основная проблема — как отследить глубину рекурсии? Формально, да можно отслеживать, есть ли на следующем шаге вызова links, entities и уж их разворачивать. Но дело может и затянуться.

Изменено: Андрей VG — 04.01.2020 17:51:22
Пользователь
Сообщений: 2054 Регистрация: 01.07.2018
04.01.2020 17:50:23
БМВ, было бы проще если бы не вложенные списки

= Json.Document(File.Contents("C:\abc\216.162.47.76.txt"))

Пользователь
Сообщений: 11891 Регистрация: 22.12.2012
Excel 2016, 365
04.01.2020 17:53:32

Цитата
artyrH написал:
было бы проще

Артур, было бы проще, если бы ТС снизошёл до представления результата и описания того что нужно извлечь, вдумчиво подойдя, пусть и не к

Цитата
Виктор C написал:
множества текстовых файлов > 1000 шт

но хотя бы случайно выбранному штук 20 количеству. Но не барское это видать дело. Тогда на что форум, если всё сам да сам

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *