Обращаюсь к Вам как к экспертам знания vba. Мне необходимо обработать более 1 млрд строк, догадываюсь, что это можно сделать оптимизировать, но знаний не хватает. Если есть такая возможность - помогите, пожалуйста.
Ситуация следующая: У меня есть много текстовых файлов. Каждый из них - лог взвешивания, каждый содержит около 60 000 строк. Я копирую каждый файл на отдельный лист (пример прикреплен). На листе взвешивания отделены пустыми строками друг от друга. Мне необходимо скопировать на отдельный лист (или хотя бы как-то выделить) пропуска машин (в каждом взвешивании это срока со словами "отсканирован пропуск"), вес которых 45 и более тонн (в каждом взвешивании это строка с текстом "зарегистрированный вес") и в которых разница при процедуре взвешивания более 9 тонн (сейчас я это сравниваю формулами, вычитая одну текущую ячейку из следующей, в файле вложении это видно). Проблема в том, что в каждом взвешивании количество строк разное. Сейчас я делаю всё это вручную... примерно 3 месяца нужно, чтобы обработать все логи.
Добрый день, уважаемые форумчане!
Обращаюсь к Вам как к экспертам знания vba. Мне необходимо обработать более 1 млрд строк, догадываюсь, что это можно сделать оптимизировать, но знаний не хватает. Если есть такая возможность - помогите, пожалуйста.
Ситуация следующая: У меня есть много текстовых файлов. Каждый из них - лог взвешивания, каждый содержит около 60 000 строк. Я копирую каждый файл на отдельный лист (пример прикреплен). На листе взвешивания отделены пустыми строками друг от друга. Мне необходимо скопировать на отдельный лист (или хотя бы как-то выделить) пропуска машин (в каждом взвешивании это срока со словами "отсканирован пропуск"), вес которых 45 и более тонн (в каждом взвешивании это строка с текстом "зарегистрированный вес") и в которых разница при процедуре взвешивания более 9 тонн (сейчас я это сравниваю формулами, вычитая одну текущую ячейку из следующей, в файле вложении это видно). Проблема в том, что в каждом взвешивании количество строк разное. Сейчас я делаю всё это вручную... примерно 3 месяца нужно, чтобы обработать все логи.stasprv
Не совсем понятен алгоритм. Как я понял, нужно находить очередную строку, содержащую Текущий вес: и, если она соответствует условиям, выводить на отдельный лист какие-то данные ( строка со словами "отсканирован пропуск" и пустые промежуточные строки не обнаружены). Сразу встаёт вопрос зачем данные из каждого файла копировать на очередной лист. Поиск и выделение нужных данных можно в памяти проделать. Наверное лучше будет, если выложите кусок файла-лога, и объясните что именно нужно вытянуть на лист.
Не совсем понятен алгоритм. Как я понял, нужно находить очередную строку, содержащую Текущий вес: и, если она соответствует условиям, выводить на отдельный лист какие-то данные ( строка со словами "отсканирован пропуск" и пустые промежуточные строки не обнаружены). Сразу встаёт вопрос зачем данные из каждого файла копировать на очередной лист. Поиск и выделение нужных данных можно в памяти проделать. Наверное лучше будет, если выложите кусок файла-лога, и объясните что именно нужно вытянуть на лист. Udik
вот вам барабан яд 41001231307558 wm R419131876897 udik1968@gmail.com
Из строки с пропуском (их почему-то несколько в каждом взвешивании), например 01,08,2016 08:24:32 Отсканирован пропуск "D26,1 959395" в каком виде выделить его значение? Так - "D26,1 959395" Почему строки с текущим весом разделены другими текстовыми строками? Может надо выделить их и перенести в другое место, где уже вычислять разницу?
Из строки с пропуском (их почему-то несколько в каждом взвешивании), например 01,08,2016 08:24:32 Отсканирован пропуск "D26,1 959395" в каком виде выделить его значение? Так - "D26,1 959395" Почему строки с текущим весом разделены другими текстовыми строками? Может надо выделить их и перенести в другое место, где уже вычислять разницу?Kuzmich
Добрый день, K-SerJC. Спасибо, отличный алгоритм получился. Только, как я понял в моем примере нет машин более 45 ny? поэтому он выдает разницу в тех, которые весят меньше. Скопировал данные из лога, где есть такие машины на лист, запустил пакрос... type mismatch. Подскажите, пожалуйста, что я делаю не так? Лог прикрепляю
Добрый день, K-SerJC. Спасибо, отличный алгоритм получился. Только, как я понял в моем примере нет машин более 45 ny? поэтому он выдает разницу в тех, которые весят меньше. Скопировал данные из лога, где есть такие машины на лист, запустил пакрос... type mismatch. Подскажите, пожалуйста, что я делаю не так? Лог прикрепляюstasprv
Наверное лучше будет, если выложите кусок файла-лога, и объясните что именно нужно вытянуть на лист.
Добрый день, Udik. Наверное, я просто не на столько хорошо знаю excel, как Вы, поэтому описываю задачу исходя из своих знаний. Изначально у меня есть текстовые файлы с логами, каждый весит более 1 Гб, я их копирую в xls на несколько листов, т.к. на один лист помещается не более 65 000 строк примерно. Лог прикрепляю
Наверное лучше будет, если выложите кусок файла-лога, и объясните что именно нужно вытянуть на лист.
Добрый день, Udik. Наверное, я просто не на столько хорошо знаю excel, как Вы, поэтому описываю задачу исходя из своих знаний. Изначально у меня есть текстовые файлы с логами, каждый весит более 1 Гб, я их копирую в xls на несколько листов, т.к. на один лист помещается не более 65 000 строк примерно. Лог прикрепляюstasprv
Добрый день, Kuzmich. Данные пропуска можно выделить в любом виде. Вы мне и так значительно облегчите задачу. Конечно, в идеале в виде 959395 (6-7 последних цифр), но это совсем супер.
Добрый день, Kuzmich. Данные пропуска можно выделить в любом виде. Вы мне и так значительно облегчите задачу. Конечно, в идеале в виде 959395 (6-7 последних цифр), но это совсем супер.stasprv
Сообщение отредактировал stasprv - Вторник, 15.11.2016, 21:18
K-SerJC, посмотрел алгоритм более внимательно. Всё-таки он работает немного не правильно. Наверное, я недостаточно понятно написал. Давайте попробую еще раз. Мне необходим номер пропуска машины, у которой при взвешивании соблюдается одновременно два условия: 1. есть скачек по модулю более 9 тн. между любыми интервалами (двумя соседними строчками). Без разницы в плюс или в минус Например: 01,08,2016 03:48:21 Текущий вес: 37,140 01,08,2016 03:48:21 Текущий вес: 36,620 - разница в этом и следующем взвешивании более 9 тн. 01,08,2016 03:48:21 Текущий вес: 26,060
2. и зарегистрированный вес которой более 45 тн. Например: 01,08,2016 03:47:51 Зарегистрированный вес: 61,160 - зарегистрированный вес более 45 тн.
Номер пропуска машины можно взять отсюда: 01,08,2016 03:47:51 Отсканирован пропуск "D26,1 961469" - отсюда необходимо взять номер пропуска
Взвешивания машин друг от друга разделены пустыми строками.
Ваше решение запускать макрос по кнопке и выводить результат вверх листа отличное.
K-SerJC, посмотрел алгоритм более внимательно. Всё-таки он работает немного не правильно. Наверное, я недостаточно понятно написал. Давайте попробую еще раз. Мне необходим номер пропуска машины, у которой при взвешивании соблюдается одновременно два условия: 1. есть скачек по модулю более 9 тн. между любыми интервалами (двумя соседними строчками). Без разницы в плюс или в минус Например: 01,08,2016 03:48:21 Текущий вес: 37,140 01,08,2016 03:48:21 Текущий вес: 36,620 - разница в этом и следующем взвешивании более 9 тн. 01,08,2016 03:48:21 Текущий вес: 26,060
2. и зарегистрированный вес которой более 45 тн. Например: 01,08,2016 03:47:51 Зарегистрированный вес: 61,160 - зарегистрированный вес более 45 тн.
Номер пропуска машины можно взять отсюда: 01,08,2016 03:47:51 Отсканирован пропуск "D26,1 961469" - отсюда необходимо взять номер пропуска
Взвешивания машин друг от друга разделены пустыми строками.
Ваше решение запускать макрос по кнопке и выводить результат вверх листа отличное.stasprv
Сообщение отредактировал stasprv - Вторник, 15.11.2016, 21:16
Вот макрос, который выделяет значение пропуска в столбец F [vba]
Код
Sub Report() Dim FoundPropusk As Range Dim FAdr As String Set FoundPropusk = Columns(1).Find("Отсканирован пропуск ", , xlValues, xlPart) If Not FoundPropusk Is Nothing Then FAdr = FoundPropusk.Address Do Cells(FoundPropusk.Row, 6) = Split(FoundPropusk, "Отсканирован пропуск ")(1) Set FoundPropusk = Columns(1).Find("Отсканирован пропуск ", After:=FoundPropusk) Loop While FoundPropusk.Address <> FAdr End If End Sub
[/vba]
Цитата
Данные пропуска можно выделить в любом виде
Вот макрос, который выделяет значение пропуска в столбец F [vba]
Код
Sub Report() Dim FoundPropusk As Range Dim FAdr As String Set FoundPropusk = Columns(1).Find("Отсканирован пропуск ", , xlValues, xlPart) If Not FoundPropusk Is Nothing Then FAdr = FoundPropusk.Address Do Cells(FoundPropusk.Row, 6) = Split(FoundPropusk, "Отсканирован пропуск ")(1) Set FoundPropusk = Columns(1).Find("Отсканирован пропуск ", After:=FoundPropusk) Loop While FoundPropusk.Address <> FAdr End If End Sub
Взвешивания машин друг от друга разделены пустыми строками.
в принципе не учел только это
тогда уточнение: имеем в начале лист со строками нескольких взвешиваний, которые разделены пробелами, т.е. несколько диапазонов
в каждом отделенном диапазоне участвует только один пропуск, много строк текущий вес и может быть несколько зарегистрированных или только один вес зарегистрирован?
выбираем из диапазона строку отсканирован пропуск, выбираем от туда числовое значение пропуска выводим строки Пропуск две строки между которыми разница >9 строку где зарегистрирован вес >45
и так по всему листу, по каждому диапазону взвешивания. правильно понял?
Взвешивания машин друг от друга разделены пустыми строками.
в принципе не учел только это
тогда уточнение: имеем в начале лист со строками нескольких взвешиваний, которые разделены пробелами, т.е. несколько диапазонов
в каждом отделенном диапазоне участвует только один пропуск, много строк текущий вес и может быть несколько зарегистрированных или только один вес зарегистрирован?
выбираем из диапазона строку отсканирован пропуск, выбираем от туда числовое значение пропуска выводим строки Пропуск две строки между которыми разница >9 строку где зарегистрирован вес >45
и так по всему листу, по каждому диапазону взвешивания. правильно понял?K-SerJC
Sub replacement() Columns("A:A").Select Selection.Replace What:=".", replacement:=",", LookAt:=xlPart, _ SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _ ReplaceFormat:=False End Sub
[/vba] точки в числовых выражениях в экселе зло! исправленный файл вложил.
Sub replacement() Columns("A:A").Select Selection.Replace What:=".", replacement:=",", LookAt:=xlPart, _ SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _ ReplaceFormat:=False End Sub
[/vba] точки в числовых выражениях в экселе зло! исправленный файл вложил.K-SerJC
каждый весит более 1 Гб, я их копирую в xls на несколько листов,
Вот код, который непосредственно файл обрабатывает. Общий алгоритм такой: идет построчное считывание, из строк, содержащих Текущий вес формируется массив весов. Если зарегистрированный вес меньше или равен 45, переходим к следующему взвешиванию. Если больше, проверяем массив на пару с разницей 9. Нашли такую - вносим номер пропуска на лист. [vba]
Код
OOption Explicit
Public Sub processF() Dim str1 As String, strPass As String Dim arr1(1 To 200) As Double Dim curIndex As Byte Dim fileToOpen, arr2 Dim flagMass As Boolean, flgout As Boolean Dim arrStr(1 To 3) As String Dim rowCur As Long, i&
With Application.FileDialog(msoFileDialogFilePicker) .AllowMultiSelect = False .Title = "Выбрать файл" 'заголовок окна диалога .Filters.Clear 'очищаем установленные ранее типы файлов .Filters.Add "Text files", "*.log", 1 'добавляем возможность выбора текстовых log файлов .FilterIndex = 1 'устанавливаем тип файлов по умолчанию .InitialFileName = ThisWorkbook.Path & "\" 'назначаем папку отображения и имя файла по умолчанию .InitialView = msoFileDialogViewDetails 'вид диалогового окна(доступно 9 вариантов)If fileToOpen = False Then Exit Sub If .Show = False Then Exit Sub: If .SelectedItems.Count = 0 Then Exit Sub fileToOpen = .SelectedItems(1) Open fileToOpen For Input As #1 End With Worksheets("out").UsedRange.ClearContents Do Until flgout On Error Resume Next Line Input #1, str1 If EOF(1) Then str1 = "" On Error GoTo 0 If str1 Like arrStr(2) Then arr2 = Split(str1, " ") If Val(arr2(UBound(arr2))) < 45 Then Do Until str1 = "" Or EOF(1) Line Input #1, str1 Loop Erase arr1 curIndex = 0 strPass = "" flagMass = False Else flagMass = True
End If ElseIf str1 Like arrStr(3) Then arr2 = Split(str1, " ") strPass = arr2(UBound(arr2)) strPass = Replace(strPass, Chr(34), "") ElseIf str1 Like arrStr(1) Then curIndex = curIndex + 1 arr2 = Split(str1, " ") arr1(curIndex) = Val(arr2(UBound(arr2))) ElseIf str1 = "" Then If flagMass Then For i = 2 To curIndex If Abs(arr1(i) - arr1(i - 1)) > 9 Then Worksheets("out").Cells(rowCur, 1).Value = strPass rowCur = rowCur + 1 Exit For End If Next i End If Erase arr1 flagMass = False curIndex = 0 strPass = "" If EOF(1) Then flgout = True
каждый весит более 1 Гб, я их копирую в xls на несколько листов,
Вот код, который непосредственно файл обрабатывает. Общий алгоритм такой: идет построчное считывание, из строк, содержащих Текущий вес формируется массив весов. Если зарегистрированный вес меньше или равен 45, переходим к следующему взвешиванию. Если больше, проверяем массив на пару с разницей 9. Нашли такую - вносим номер пропуска на лист. [vba]
Код
OOption Explicit
Public Sub processF() Dim str1 As String, strPass As String Dim arr1(1 To 200) As Double Dim curIndex As Byte Dim fileToOpen, arr2 Dim flagMass As Boolean, flgout As Boolean Dim arrStr(1 To 3) As String Dim rowCur As Long, i&
With Application.FileDialog(msoFileDialogFilePicker) .AllowMultiSelect = False .Title = "Выбрать файл" 'заголовок окна диалога .Filters.Clear 'очищаем установленные ранее типы файлов .Filters.Add "Text files", "*.log", 1 'добавляем возможность выбора текстовых log файлов .FilterIndex = 1 'устанавливаем тип файлов по умолчанию .InitialFileName = ThisWorkbook.Path & "\" 'назначаем папку отображения и имя файла по умолчанию .InitialView = msoFileDialogViewDetails 'вид диалогового окна(доступно 9 вариантов)If fileToOpen = False Then Exit Sub If .Show = False Then Exit Sub: If .SelectedItems.Count = 0 Then Exit Sub fileToOpen = .SelectedItems(1) Open fileToOpen For Input As #1 End With Worksheets("out").UsedRange.ClearContents Do Until flgout On Error Resume Next Line Input #1, str1 If EOF(1) Then str1 = "" On Error GoTo 0 If str1 Like arrStr(2) Then arr2 = Split(str1, " ") If Val(arr2(UBound(arr2))) < 45 Then Do Until str1 = "" Or EOF(1) Line Input #1, str1 Loop Erase arr1 curIndex = 0 strPass = "" flagMass = False Else flagMass = True
End If ElseIf str1 Like arrStr(3) Then arr2 = Split(str1, " ") strPass = arr2(UBound(arr2)) strPass = Replace(strPass, Chr(34), "") ElseIf str1 Like arrStr(1) Then curIndex = curIndex + 1 arr2 = Split(str1, " ") arr1(curIndex) = Val(arr2(UBound(arr2))) ElseIf str1 = "" Then If flagMass Then For i = 2 To curIndex If Abs(arr1(i) - arr1(i - 1)) > 9 Then Worksheets("out").Cells(rowCur, 1).Value = strPass rowCur = rowCur + 1 Exit For End If Next i End If Erase arr1 flagMass = False curIndex = 0 strPass = "" If EOF(1) Then flgout = True
в каждом отделенном диапазоне участвует только один пропуск, много строк текущий вес и может быть несколько зарегистрированных или только один вес зарегистрирован?
Может быть несколько строк в одном взвешивании "Зарегистрирован вес", но они будут идентичны, т.е. зарегистрирован один и тот же вес
в каждом отделенном диапазоне участвует только один пропуск, много строк текущий вес и может быть несколько зарегистрированных или только один вес зарегистрирован?
Может быть несколько строк в одном взвешивании "Зарегистрирован вес", но они будут идентичны, т.е. зарегистрирован один и тот же вес
Вот код, который непосредственно файл обрабатывает.
Спасибо за Ваш труд, но, к сожалению, когда открываю файл и нажимаю на кнопку ничего не происходит. Через разработчик запустил макрос, после выбора файла выдается ошибка "Run-time error: 32809. Application defined or object defined error". Вероятно, я что-то делаю не так?
Вот код, который непосредственно файл обрабатывает.
Спасибо за Ваш труд, но, к сожалению, когда открываю файл и нажимаю на кнопку ничего не происходит. Через разработчик запустил макрос, после выбора файла выдается ошибка "Run-time error: 32809. Application defined or object defined error". Вероятно, я что-то делаю не так?stasprv
проверил, отбирает зарегистрированные >45 и текущие с разницей >9
Наверное, я не совсем понятно написал. Необходимо, чтобы одновременно выполнялись оба условия в одном взвешивании. Машина с весом более 45 тн. и текущее с разницей 9 тн. Было бы отлично, если бы номер пропуска выводился шестизначный (сейчас 5 знаков)
проверил, отбирает зарегистрированные >45 и текущие с разницей >9
Наверное, я не совсем понятно написал. Необходимо, чтобы одновременно выполнялись оба условия в одном взвешивании. Машина с весом более 45 тн. и текущее с разницей 9 тн. Было бы отлично, если бы номер пропуска выводился шестизначный (сейчас 5 знаков)stasprv