Доброго времени суток, уважаемые форумчане! Можно ли в макросе реализовать получение данных из файла txt в лист книги при совпадении имени файла! Т.е. есть книга excel - на Листе 1 есть таблица - нужно путем указания или выделения выделить несколько ячеек по столбцу А и произвести поиск в txt файле - при совпадении - взять значение - которое в txt после / и записать в лист напротив совпавшего значения в столбце О. Прикладываю образец файлов. Заранее спасибо за ответ!
Доброго времени суток, уважаемые форумчане! Можно ли в макросе реализовать получение данных из файла txt в лист книги при совпадении имени файла! Т.е. есть книга excel - на Листе 1 есть таблица - нужно путем указания или выделения выделить несколько ячеек по столбцу А и произвести поиск в txt файле - при совпадении - взять значение - которое в txt после / и записать в лист напротив совпавшего значения в столбце О. Прикладываю образец файлов. Заранее спасибо за ответ!Ed_Vard
При запуске макроса 1. Читаем текстовый файл построчно, занося в Dictionary номер до слэша и в Item то, что после. Вопрос - файл всегда постоянный или нужно выбирать в диалоге? 2. Перебираем выделенные ячейки, каждое значение ищем в словаре, и (если нашлось) извлекаем из Item содержимое, помещаем в ячейку, используя Offset. Вопрос - строк в Экселе много? Если много, то быстрее брать диапазон в массив, перебирать его, результат грузить в другой параллельный массив, который потом выгрузить на лист. Будет быстро при любом разумном количестве записей (при неразумном будет, но не быстро ).
Ну и главный вопрос - действительно 2011 0 010 990 нужно помещать всё в одну ячейку столбца O? Может быть нужно разбить по ячейкам?
Пока код такой - выделить ячейки в А, запустить:
Code
Option Explicit
Sub ImportData() Dim s$, x, cc As Range s = Application.GetOpenFilename("Текстовые файлы (*.txt),*.txt,Все файлы (*.*),*.*") If s = "False" Then Exit Sub With CreateObject("Scripting.dictionary") .CompareMode = 1 'TextCompare Open s For Input As #1 Do Until EOF(1) Line Input #1, s If InStr(s, "/") Then x = Split(s, "/")(0) If x <> "" Then .Item(x) = Split(s, "/")(1) End If Loop Reset
For Each cc In Selection.Cells If .exists(cc.Value) Then cc.Offset(, 14) = .Item(cc.Value) Next End With End Sub
Можно. Алгоритм примерно такой, но есть вопросы:
При запуске макроса 1. Читаем текстовый файл построчно, занося в Dictionary номер до слэша и в Item то, что после. Вопрос - файл всегда постоянный или нужно выбирать в диалоге? 2. Перебираем выделенные ячейки, каждое значение ищем в словаре, и (если нашлось) извлекаем из Item содержимое, помещаем в ячейку, используя Offset. Вопрос - строк в Экселе много? Если много, то быстрее брать диапазон в массив, перебирать его, результат грузить в другой параллельный массив, который потом выгрузить на лист. Будет быстро при любом разумном количестве записей (при неразумном будет, но не быстро ).
Ну и главный вопрос - действительно 2011 0 010 990 нужно помещать всё в одну ячейку столбца O? Может быть нужно разбить по ячейкам?
Пока код такой - выделить ячейки в А, запустить:
Code
Option Explicit
Sub ImportData() Dim s$, x, cc As Range s = Application.GetOpenFilename("Текстовые файлы (*.txt),*.txt,Все файлы (*.*),*.*") If s = "False" Then Exit Sub With CreateObject("Scripting.dictionary") .CompareMode = 1 'TextCompare Open s For Input As #1 Do Until EOF(1) Line Input #1, s If InStr(s, "/") Then x = Split(s, "/")(0) If x <> "" Then .Item(x) = Split(s, "/")(1) End If Loop Reset
For Each cc In Selection.Cells If .exists(cc.Value) Then cc.Offset(, 14) = .Item(cc.Value) Next End With End Sub
Hugo, спасибо за отклик! по поводу вопросов: 1. Да - файл один и тот же, и находиться постоянно в одном и томже каталоге - в него постоянно дописываються строки по результату работы другой программы. 2. Но данный момент - пордка 25 000 строк - но за раз они все не обрабатываються - т.е. нужно указать - с какой по какую ячейку нужно обрабатывать. 3. 2011 0 010 990 - да - именно так и нужно записывать в ячейку - желательно убрать пробелы между цифрами.
Hugo, спасибо за отклик! по поводу вопросов: 1. Да - файл один и тот же, и находиться постоянно в одном и томже каталоге - в него постоянно дописываються строки по результату работы другой программы. 2. Но данный момент - пордка 25 000 строк - но за раз они все не обрабатываються - т.е. нужно указать - с какой по какую ячейку нужно обрабатывать. 3. 2011 0 010 990 - да - именно так и нужно записывать в ячейку - желательно убрать пробелы между цифрами.Ed_Vard
Да - именно так - как нужно - единственное - можно указать путь на определенную папку с определенным именем файла - чтоб не выскакивало окно выбора файла и чтоб небыло пробелов между цирами!
Quote (Hugo)
Пока код такой - выделить ячейки в А, запустить:
Да - именно так - как нужно - единственное - можно указать путь на определенную папку с определенным именем файла - чтоб не выскакивало окно выбора файла и чтоб небыло пробелов между цирами!Ed_Vard
Sub ImportData() Dim s$, x, cc As Range With CreateObject("Scripting.dictionary") .CompareMode = 1 'TextCompare Open "C:\temp\loaded.txt" For Input As #1 Do Until EOF(1) Line Input #1, s If InStr(s, "/") Then x = Split(s, "/")(0) If x <> "" Then .Item(x) = Replace(Split(s, "/")(1), " ", "") End If Loop Reset
For Each cc In Selection.Cells If .exists(cc.Value) Then cc.Offset(, 14) = .Item(cc.Value) Next End With End Sub
Можно добавить запрос про ячейки, например в инпутбокс нужно записать 25/5600, и будут обработаны эти ячейки. Ну и, если обрабатываете много строк - тысячу-другую, то есть смысл перевести обработку на массивы.
P.S. Хотя эту задачу можно сделать и без макросов - импортировать текст на другой лист, разбив на столбцы по "/", и затем подтянуть с помощью ВПР(), заменить формулы на значения, заменой по столбцу заменить пробелы на ничего.
Ну это уже мелочи:
Code
Option Explicit
Sub ImportData() Dim s$, x, cc As Range With CreateObject("Scripting.dictionary") .CompareMode = 1 'TextCompare Open "C:\temp\loaded.txt" For Input As #1 Do Until EOF(1) Line Input #1, s If InStr(s, "/") Then x = Split(s, "/")(0) If x <> "" Then .Item(x) = Replace(Split(s, "/")(1), " ", "") End If Loop Reset
For Each cc In Selection.Cells If .exists(cc.Value) Then cc.Offset(, 14) = .Item(cc.Value) Next End With End Sub
Можно добавить запрос про ячейки, например в инпутбокс нужно записать 25/5600, и будут обработаны эти ячейки. Ну и, если обрабатываете много строк - тысячу-другую, то есть смысл перевести обработку на массивы.
P.S. Хотя эту задачу можно сделать и без макросов - импортировать текст на другой лист, разбив на столбцы по "/", и затем подтянуть с помощью ВПР(), заменить формулы на значения, заменой по столбцу заменить пробелы на ничего.Hugo
Можно добавить запрос про ячейки, например в инпутбокс нужно записать 25/5600, и будут обработаны эти ячейки.
Если это не сложно - то было бы неплохо! Максимально за один раз - около 1500 строк - так что в принципе - как Вы сделали - очень хорошо справляеться! Вариант с открытием и через ВПР делал - очень долго получаеться - пока откроешь, разделишь - а на листе есть другие формулы - довольно тормознуто получаеться! А так - все очень хорошо получилось - именно то - что нужно!
Quote (Hugo)
Можно добавить запрос про ячейки, например в инпутбокс нужно записать 25/5600, и будут обработаны эти ячейки.
Если это не сложно - то было бы неплохо! Максимально за один раз - около 1500 строк - так что в принципе - как Вы сделали - очень хорошо справляеться! Вариант с открытием и через ВПР делал - очень долго получаеться - пока откроешь, разделишь - а на листе есть другие формулы - довольно тормознуто получаеться! А так - все очень хорошо получилось - именно то - что нужно!Ed_Vard
Sub ImportData() Dim s$, x, cc As Range, diap$ Dim n&, m&, calc_status
diap = InputBox("Запрос строк", "Введите данные вида n/m") If diap = "" Then Exit Sub n = Split(diap, "/")(0) m = Split(diap, "/")(1)
With Application .EnableEvents = False .ScreenUpdating = False calc_status = .Calculation .Calculation = xlCalculationManual End With
With CreateObject("Scripting.dictionary") .CompareMode = 1 'TextCompare Open "C:\temp\Ed_Vard\2\loaded.txt" For Input As #1 Do Until EOF(1) Line Input #1, s If InStr(s, "/") Then x = Split(s, "/")(0) If x <> "" Then .Item(x) = Replace(Split(s, "/")(1), " ", "") End If Loop Reset
For Each cc In Range(Cells(n, 1), Cells(m, 1)) If .exists(cc.Value) Then cc.Offset(, 14) = .Item(cc.Value) Next End With
With Application .Calculation = calc_status .EnableEvents = True .ScreenUpdating = True End With
End Sub
Ещё добавил отключение событий, пересчёта и обновление экрана на время процесса.
Тоже мелочь:
Code
Option Explicit
Sub ImportData() Dim s$, x, cc As Range, diap$ Dim n&, m&, calc_status
diap = InputBox("Запрос строк", "Введите данные вида n/m") If diap = "" Then Exit Sub n = Split(diap, "/")(0) m = Split(diap, "/")(1)
With Application .EnableEvents = False .ScreenUpdating = False calc_status = .Calculation .Calculation = xlCalculationManual End With
With CreateObject("Scripting.dictionary") .CompareMode = 1 'TextCompare Open "C:\temp\Ed_Vard\2\loaded.txt" For Input As #1 Do Until EOF(1) Line Input #1, s If InStr(s, "/") Then x = Split(s, "/")(0) If x <> "" Then .Item(x) = Replace(Split(s, "/")(1), " ", "") End If Loop Reset
For Each cc In Range(Cells(n, 1), Cells(m, 1)) If .exists(cc.Value) Then cc.Offset(, 14) = .Item(cc.Value) Next End With
With Application .Calculation = calc_status .EnableEvents = True .ScreenUpdating = True End With
End Sub
Ещё добавил отключение событий, пересчёта и обновление экрана на время процесса.Hugo
Ещё добавил отключение событий, пересчёта и обновление экрана на время процесса.
Спасибо большое - все отлично работает! А можно ли рядом в ячейки столбца Р вставлять текущую дату - когда происходит вставка значений в столбец О ?
Quote (Hugo)
Ещё добавил отключение событий, пересчёта и обновление экрана на время процесса.
Спасибо большое - все отлично работает! А можно ли рядом в ячейки столбца Р вставлять текущую дату - когда происходит вставка значений в столбец О ?Ed_Vard
Hugo, Доброго времени суток! Очень нужна помощь - почемуто не записались все значения в в лог файл! Единственная возможность получить эти значения из rtf файла - что он из себя представляет - во вложении - приложил только один! Такой файл формируеться на каждый файл в столбце А и "обзываеться" именем файла и в конце добавляеться rtf. Внутри этого файла мне нужно взять то - что находиться в четвертой строке между Входящий номер: и запятой! Этих файлов великое множество в определенной папке - руками смотреть просто не реально! Можно это как то реализовать по аналогии с вашим предудущим вариантом? Заранее спасибо за ответ!
Hugo, Доброго времени суток! Очень нужна помощь - почемуто не записались все значения в в лог файл! Единственная возможность получить эти значения из rtf файла - что он из себя представляет - во вложении - приложил только один! Такой файл формируеться на каждый файл в столбце А и "обзываеться" именем файла и в конце добавляеться rtf. Внутри этого файла мне нужно взять то - что находиться в четвертой строке между Входящий номер: и запятой! Этих файлов великое множество в определенной папке - руками смотреть просто не реально! Можно это как то реализовать по аналогии с вашим предудущим вариантом? Заранее спасибо за ответ!Ed_Vard
По аналогии вероятно не получится. Разве что эти цифры всегда в 65-ой строке начиная с 85-ой позиции находятся, если как текстовый файл открывать. Иначе тут наверное надо Ворд привлекать и его методами искать данные, я с Вордом мало работал...
По аналогии вероятно не получится. Разве что эти цифры всегда в 65-ой строке начиная с 85-ой позиции находятся, если как текстовый файл открывать. Иначе тут наверное надо Ворд привлекать и его методами искать данные, я с Вордом мало работал...Hugo
По аналогии вероятно не получится. Разве что эти цифры всегда в 65-ой строке начиная с 85-ой позиции находятся, если как текстовый файл открывать.
А почему в 65 строке и 85 позиции? И возможно ли его открыть как txt?
Вот на planetaexcel нашел код - но как его применить в моем случае - не пойму
Code
Sub OpenRtfAndPasteToSheets() Dim wd As Object Dim ns As Worksheet
On Error Resume Next 'запустим Ворд Set wd = GetObject("", "Word.Application") If Err.Number <> 0 Then Err.Clear Set wd = CreateObject("Word.Application") If Err.Number <> 0 Then Exit Sub End If
On Error GoTo BAD
Do 'получим имя очередного файла f = Application.GetOpenFilename("Файлы RTF, *.rtf,Все файлы, *.*") If TypeName(f) = "Boolean" Then Exit Do 'если Отмена - выход 'откроем выбранный очередной файл Set wdd = wd.Documents.Open(f) ' wd.Visible = True 'скопируем содержимое документа t = wdd.Content.Copy 'создадим лист для этого документа Set ns = ActiveWorkbook.Worksheets.Add 'вставим скопированное в новый лист ns.Paste Destination:=ns.Cells(1, 1) 'немного выравним вид ns.Cells.WrapText = False ns.Columns.AutoFit ns.Rows.AutoFit wdd.Close Loop wd.Quit Set wd = Nothing Exit Sub BAD: MsgBox Err.Description On Error Resume Next wd.Quit Set wd = Nothing End End Sub
Quote (Hugo)
По аналогии вероятно не получится. Разве что эти цифры всегда в 65-ой строке начиная с 85-ой позиции находятся, если как текстовый файл открывать.
А почему в 65 строке и 85 позиции? И возможно ли его открыть как txt?
Вот на planetaexcel нашел код - но как его применить в моем случае - не пойму
Code
Sub OpenRtfAndPasteToSheets() Dim wd As Object Dim ns As Worksheet
On Error Resume Next 'запустим Ворд Set wd = GetObject("", "Word.Application") If Err.Number <> 0 Then Err.Clear Set wd = CreateObject("Word.Application") If Err.Number <> 0 Then Exit Sub End If
On Error GoTo BAD
Do 'получим имя очередного файла f = Application.GetOpenFilename("Файлы RTF, *.rtf,Все файлы, *.*") If TypeName(f) = "Boolean" Then Exit Do 'если Отмена - выход 'откроем выбранный очередной файл Set wdd = wd.Documents.Open(f) ' wd.Visible = True 'скопируем содержимое документа t = wdd.Content.Copy 'создадим лист для этого документа Set ns = ActiveWorkbook.Worksheets.Add 'вставим скопированное в новый лист ns.Paste Destination:=ns.Cells(1, 1) 'немного выравним вид ns.Cells.WrapText = False ns.Columns.AutoFit ns.Rows.AutoFit wdd.Close Loop wd.Quit Set wd = Nothing Exit Sub BAD: MsgBox Err.Description On Error Resume Next wd.Quit Set wd = Nothing End End Sub
В 65 строке и 85 позиции - это если блокнотом файл открывать. А этот код можно так приспособить - вот в месиджбоксе нужные данные, правда на запятую не ориентировался, только на "Входящий номер: ". Если длина нужных данных может плавать - нужно доделывать. Воспользовался объектом DataObject, входящий в состав "Microsoft Forms 2.0 Object Library" - нужно подключить эту библиотеку. Простой способ - добавить в проект форму, которую потом сразу можно удалить. Куда потом выводить этот test - другой вопрос.
Code
Sub OpenRtfAndPasteToSheets() Dim wd As Object Dim ns As Worksheet
On Error Resume Next 'запустим Ворд Set wd = GetObject("", "Word.Application") If Err.Number <> 0 Then Err.Clear Set wd = CreateObject("Word.Application") If Err.Number <> 0 Then Exit Sub End If
On Error GoTo BAD
'получим имя очередного файла f = Application.GetOpenFilename("Файлы RTF, *.rtf,Все файлы, *.*") If TypeName(f) = "Boolean" Then End 'если Отмена - выход 'откроем выбранный файл Set wdd = wd.Documents.Open(f) ' wd.Visible = True 'скопируем содержимое документа t = wdd.Content.Copy Dim MyData As DataObject Set MyData = New DataObject MyData.GetFromClipboard test = MyData.GetText(1) test = Mid(test, InStr(test, "Входящий номер: ") + 16, 14) MsgBox test wd.Quit Set wd = Nothing Exit Sub BAD: MsgBox Err.Description On Error Resume Next wd.Quit Set wd = Nothing End End Sub
В 65 строке и 85 позиции - это если блокнотом файл открывать. А этот код можно так приспособить - вот в месиджбоксе нужные данные, правда на запятую не ориентировался, только на "Входящий номер: ". Если длина нужных данных может плавать - нужно доделывать. Воспользовался объектом DataObject, входящий в состав "Microsoft Forms 2.0 Object Library" - нужно подключить эту библиотеку. Простой способ - добавить в проект форму, которую потом сразу можно удалить. Куда потом выводить этот test - другой вопрос.
Code
Sub OpenRtfAndPasteToSheets() Dim wd As Object Dim ns As Worksheet
On Error Resume Next 'запустим Ворд Set wd = GetObject("", "Word.Application") If Err.Number <> 0 Then Err.Clear Set wd = CreateObject("Word.Application") If Err.Number <> 0 Then Exit Sub End If
On Error GoTo BAD
'получим имя очередного файла f = Application.GetOpenFilename("Файлы RTF, *.rtf,Все файлы, *.*") If TypeName(f) = "Boolean" Then End 'если Отмена - выход 'откроем выбранный файл Set wdd = wd.Documents.Open(f) ' wd.Visible = True 'скопируем содержимое документа t = wdd.Content.Copy Dim MyData As DataObject Set MyData = New DataObject MyData.GetFromClipboard test = MyData.GetText(1) test = Mid(test, InStr(test, "Входящий номер: ") + 16, 14) MsgBox test wd.Quit Set wd = Nothing Exit Sub BAD: MsgBox Err.Description On Error Resume Next wd.Quit Set wd = Nothing End End Sub