Добрый день, я не смог найти решения на вашем форуме, может кто сможет помочь? Задача: есть папка в которой в подпапках(каждая подпапка определенный час дня) лежат файлы CSV с одинаковыми именами. Необходимо свести все файлы для построения статистических графиков для работы. Файл статистики тоже прилагаю. Уж больно муторно 2-3 часа терять для сбора статистики. Если я не правильно обратился направьте, плз.
Добрый день, я не смог найти решения на вашем форуме, может кто сможет помочь? Задача: есть папка в которой в подпапках(каждая подпапка определенный час дня) лежат файлы CSV с одинаковыми именами. Необходимо свести все файлы для построения статистических графиков для работы. Файл статистики тоже прилагаю. Уж больно муторно 2-3 часа терять для сбора статистики. Если я не правильно обратился направьте, плз.Evg72
Я думаю результат получился возможно ущербный (смотря как Вы там что делали) и конечно неоптимальный - файлы нужно читать и анализировать кодом как текст, не открывая их непосредственно Экселем, выводить на лист уже только результат этого анализа. Делать не рвусь - не интересно и пока некогда. Просто подсказываю по моему мнению правильный путь.
Я думаю результат получился возможно ущербный (смотря как Вы там что делали) и конечно неоптимальный - файлы нужно читать и анализировать кодом как текст, не открывая их непосредственно Экселем, выводить на лист уже только результат этого анализа. Делать не рвусь - не интересно и пока некогда. Просто подсказываю по моему мнению правильный путь.Hugo
Ребята, решил оптимизировать код подскажите как: файлы по каждому часу складываются в отдельную папку за день, дни складываются в папку месяца. Для статистики за день хотел сделать цикл от 0 до 23, но как сделать изменения +1 при открытии папки ( "C:\stats\2013\2013-11\2013-11-11\00(типа+1)_00_00\DVN-stats.txt" не знаю.
Ребята, решил оптимизировать код подскажите как: файлы по каждому часу складываются в отдельную папку за день, дни складываются в папку месяца. Для статистики за день хотел сделать цикл от 0 до 23, но как сделать изменения +1 при открытии папки ( "C:\stats\2013\2013-11\2013-11-11\00(типа+1)_00_00\DVN-stats.txt" не знаю.
1. У Вас меняется не только номер в каталоге/папке, но и название файла. Если там нет системы, то просто менять номер в имени каталога мало. 2. Конечно, если эти файлы всегда строго именно такого вида - тогда можно подойти и так... Но я бы делал иначе - собирал словарь с коллекцией (или с привязанным массивом высотой с нужное количество параметров, шириной по количеству файлов или с запасом). Далее кодом открываем все текстовые *-stats.txt в подпапках выбранной папки, читаем построчно, если в строке есть "|" то в словарь ключу из левой части собираем коллекцию значений правой части. Когда все файлы просмотрены - пробегаем по своей вероятно заготовленной форме и по ключам из A выгружаем правее собранные коллекции. Или даже так - сперва по этим ключам делаем словарь с пустыми коллекциями (или массив и словарь с индексами массива), затем уже при просмотре файлов собираем только нужные данные. Если в файлах будет что-то лишнее - не берём.
1. У Вас меняется не только номер в каталоге/папке, но и название файла. Если там нет системы, то просто менять номер в имени каталога мало. 2. Конечно, если эти файлы всегда строго именно такого вида - тогда можно подойти и так... Но я бы делал иначе - собирал словарь с коллекцией (или с привязанным массивом высотой с нужное количество параметров, шириной по количеству файлов или с запасом). Далее кодом открываем все текстовые *-stats.txt в подпапках выбранной папки, читаем построчно, если в строке есть "|" то в словарь ключу из левой части собираем коллекцию значений правой части. Когда все файлы просмотрены - пробегаем по своей вероятно заготовленной форме и по ключам из A выгружаем правее собранные коллекции. Или даже так - сперва по этим ключам делаем словарь с пустыми коллекциями (или массив и словарь с индексами массива), затем уже при просмотре файлов собираем только нужные данные. Если в файлах будет что-то лишнее - не берём.Hugo
Файлы всегда строго такого вида, они внутри похожи как две капли воды за исключением данных. Так как я всего 1 день занимаюсь VBA мне не всё понятно из того что вы написали.
Файлы всегда строго такого вида, они внутри похожи как две капли воды за исключением данных. Так как я всего 1 день занимаюсь VBA мне не всё понятно из того что вы написали.Evg72
Ну понятно что непонятно... Просто чтоб Вы знали, что есть совершенно другой подход, позволяющий избежать ошибок, которые могут быть при Вашем подходе. Но если файлы железно всегда одинаковы по структуре, то в Вашем коде достаточно одного блока Workbooks.OpenText, к которому прикрутить цикл перебора папок/файлов (подменяя путь к открываемому файлу), ну и циклично сдвигать выгрузку результата.
Ну понятно что непонятно... Просто чтоб Вы знали, что есть совершенно другой подход, позволяющий избежать ошибок, которые могут быть при Вашем подходе. Но если файлы железно всегда одинаковы по структуре, то в Вашем коде достаточно одного блока Workbooks.OpenText, к которому прикрутить цикл перебора папок/файлов (подменяя путь к открываемому файлу), ну и циклично сдвигать выгрузку результата.Hugo
с этого места поподробнее... если можно, то на моём коде VBA, покажите. это малая часть того что уже сделано, не хотел загромождать целиком. Но то что я сделал работает, причем захватывает 3 файла с разными именами в одной папке. А так как это не оптимально (хотя и работает) хотел переделать.
с этого места поподробнее... если можно, то на моём коде VBA, покажите. это малая часть того что уже сделано, не хотел загромождать целиком. Но то что я сделал работает, причем захватывает 3 файла с разными именами в одной папке. А так как это не оптимально (хотя и работает) хотел переделать.Evg72
Сообщение отредактировал Evg72 - Четверг, 07.11.2013, 14:48
Sub mac123() ' ' mac123 Макрос ' ' ' Call to test GetFiles function.
Dim dctDict As New Scripting.Dictionary 'создается объект Dictionary Dim varItem As Variant
' Call non recursively, return files into Dictionary object. If GetFiles("D:\TMP\Evg72\", dctDict, True) Then 'заполняется объект Dyctionary: dctDict ' Print items in dictionary. For Each varItem In dctDict If InStr(varItem, "-stats.txt") Then MsgBox varItem Debug.Print varItem End If Next End If ' MsgBox dctDict.Count 'Выводит кол-во файлов в "C:\" End Sub
Function GetFiles(strPath As String, _ dctDict As Scripting.Dictionary, _ Optional blnRecursive As Boolean) As Boolean
' This procedure returns all the files in a directory into ' a Dictionary object. If called recursively, it also returns ' all files in subfolders.
Dim fsoSysObj As Scripting.FileSystemObject Dim fdrFolder As Scripting.Folder Dim fdrSubFolder As Scripting.Folder Dim filFile As Scripting.File
' Return new FileSystemObject. Set fsoSysObj = New FileSystemObject
On Error Resume Next ' Get folder. Set fdrFolder = fsoSysObj.GetFolder(strPath) If Err <> 0 Then ' Incorrect path. GetFiles = False GoTo GetFiles_End End If On Error GoTo 0
' Loop through Files collection, adding to dictionary. For Each filFile In fdrFolder.Files dctDict.Add filFile.Path, filFile.Path 'MsgBox filFile.Path ' Выводит сообщением имя каждого файла, встретившегося в каталоге strPath, т.е. "C:\" Next filFile
' If Recursive flag is true, call recursively. If blnRecursive Then For Each fdrSubFolder In fdrFolder.SubFolders GetFiles fdrSubFolder.Path, dctDict, True Next fdrSubFolder End If
' Return True if no error occurred. GetFiles = True
GetFiles_End: Exit Function End Function
[/vba]
"D:\TMP\Evg72\" замените на свой путь к верхней папке. В референсах проекта подключить библиотеку Microsoft Scripting Runtime. Вместо MsgBox varItem Debug.Print varItem используйте это значение в своём коде импорта данных.
Вот например первое что нашлось, чуть подкрутил:
[vba]
Код
Sub mac123() ' ' mac123 Макрос ' ' ' Call to test GetFiles function.
Dim dctDict As New Scripting.Dictionary 'создается объект Dictionary Dim varItem As Variant
' Call non recursively, return files into Dictionary object. If GetFiles("D:\TMP\Evg72\", dctDict, True) Then 'заполняется объект Dyctionary: dctDict ' Print items in dictionary. For Each varItem In dctDict If InStr(varItem, "-stats.txt") Then MsgBox varItem Debug.Print varItem End If Next End If ' MsgBox dctDict.Count 'Выводит кол-во файлов в "C:\" End Sub
Function GetFiles(strPath As String, _ dctDict As Scripting.Dictionary, _ Optional blnRecursive As Boolean) As Boolean
' This procedure returns all the files in a directory into ' a Dictionary object. If called recursively, it also returns ' all files in subfolders.
Dim fsoSysObj As Scripting.FileSystemObject Dim fdrFolder As Scripting.Folder Dim fdrSubFolder As Scripting.Folder Dim filFile As Scripting.File
' Return new FileSystemObject. Set fsoSysObj = New FileSystemObject
On Error Resume Next ' Get folder. Set fdrFolder = fsoSysObj.GetFolder(strPath) If Err <> 0 Then ' Incorrect path. GetFiles = False GoTo GetFiles_End End If On Error GoTo 0
' Loop through Files collection, adding to dictionary. For Each filFile In fdrFolder.Files dctDict.Add filFile.Path, filFile.Path 'MsgBox filFile.Path ' Выводит сообщением имя каждого файла, встретившегося в каталоге strPath, т.е. "C:\" Next filFile
' If Recursive flag is true, call recursively. If blnRecursive Then For Each fdrSubFolder In fdrFolder.SubFolders GetFiles fdrSubFolder.Path, dctDict, True Next fdrSubFolder End If
' Return True if no error occurred. GetFiles = True
GetFiles_End: Exit Function End Function
[/vba]
"D:\TMP\Evg72\" замените на свой путь к верхней папке. В референсах проекта подключить библиотеку Microsoft Scripting Runtime. Вместо MsgBox varItem Debug.Print varItem используйте это значение в своём коде импорта данных.Hugo
1. Зачем там этот селект? Если выполнять код находясь на этом листе - то ничего select не нужно. 2. Если нужно менять лист, то тоже можно обращаться к любому листу без его "select" - по номеру: [vba]
Код
sheets(2).range("A" & x).Paste
[/vba] или по имени: [vba]
Код
sheets(format(y,"00")).range("A" & x).Paste
[/vba] или Вам вероятно понадобится сдвигаться вправо: [vba]
Код
sheets(format(y,"00")).cells(1,x).Paste
[/vba] Ну а где-то выше по коду соответственно [vba]
Код
x=x+1 y=y+1
[/vba]
1. Зачем там этот селект? Если выполнять код находясь на этом листе - то ничего select не нужно. 2. Если нужно менять лист, то тоже можно обращаться к любому листу без его "select" - по номеру: [vba]
Код
sheets(2).range("A" & x).Paste
[/vba] или по имени: [vba]
Код
sheets(format(y,"00")).range("A" & x).Paste
[/vba] или Вам вероятно понадобится сдвигаться вправо: [vba]
Код
sheets(format(y,"00")).cells(1,x).Paste
[/vba] Ну а где-то выше по коду соответственно [vba]
В цикле решил использовать y -как номер листа, однако почему-то заполняет данными только первый (№6) лист. Я что то не дописал? [vba]
Код
Sub test() Sub test() ' ' test Ìàêðîñ ' ' ' Call to test GetFiles function.
Dim dctDict As New Scripting.Dictionary 'создается объект Dictionary Dim varItem As Variant Dim y
' Call non recursively, return files into Dictionary object. If GetFiles("C:\stats\2013\2013-11\2013-11-11", dctDict, True) Then 'заполняется объект Dyctionary: dctDict ' Print items in dictionary. For Each varItem In dctDict y = 6 If InStr(varItem, "-stats.txt") Then Workbooks.OpenText Filename:= _ varItem _ , Origin:=866, StartRow:=1, DataType:=xlDelimited, TextQualifier:= _ xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, Semicolon:=False, _ Comma:=False, Space:=False, Other:=True, OtherChar:="|", FieldInfo:= _ Array(Array(1, 1), Array(2, 1)), TrailingMinusNumbers:=True Range("A1:B26").Copy ThisWorkbook.Worksheets(y).Range("A1") ActiveWindow.Close Workbooks.OpenText Filename:= _ varItem _ , Origin:=866, StartRow:=1, DataType:=xlDelimited, TextQualifier:= _ xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, Semicolon:=False, _ Comma:=False, Space:=False, Other:=True, OtherChar:="|", FieldInfo:= _ Array(Array(1, 1), Array(2, 1)), TrailingMinusNumbers:=True Range("B3:B26").Copy ThisWorkbook.Worksheets(y).Range("C3") ActiveWindow.Close Workbooks.OpenText Filename:= _ varItem _ , Origin:=866, StartRow:=1, DataType:=xlDelimited, TextQualifier:= _ xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, Semicolon:=False, _ Comma:=False, Space:=False, Other:=True, OtherChar:="|", FieldInfo:= _ Array(Array(1, 1), Array(2, 1)), TrailingMinusNumbers:=True Range("B3:B26").Copy ThisWorkbook.Worksheets(y).Range("D3") ActiveWindow.Close Range("B3:D23").Select Selection.Replace What:=".", Replacement:=",", LookAt:=xlPart, _ SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _ ReplaceFormat:=False y = y + 1 End If Next End If ' MsgBox dctDict.Count 'Выводит кол-во файлов в "C:\" End Sub
[/vba] [moder]Для макросов кнопка тега не "fx", а "#". Исправил. Чтобы не было кракозябр, во время копирования/вставки в VBA и на сайте должен быть одинаковый язык - или и там, и тут вражеский, или нашенский.
[Evg72] учту. А какой шрифт используется здесь?
В цикле решил использовать y -как номер листа, однако почему-то заполняет данными только первый (№6) лист. Я что то не дописал? [vba]
Код
Sub test() Sub test() ' ' test Ìàêðîñ ' ' ' Call to test GetFiles function.
Dim dctDict As New Scripting.Dictionary 'создается объект Dictionary Dim varItem As Variant Dim y
' Call non recursively, return files into Dictionary object. If GetFiles("C:\stats\2013\2013-11\2013-11-11", dctDict, True) Then 'заполняется объект Dyctionary: dctDict ' Print items in dictionary. For Each varItem In dctDict y = 6 If InStr(varItem, "-stats.txt") Then Workbooks.OpenText Filename:= _ varItem _ , Origin:=866, StartRow:=1, DataType:=xlDelimited, TextQualifier:= _ xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, Semicolon:=False, _ Comma:=False, Space:=False, Other:=True, OtherChar:="|", FieldInfo:= _ Array(Array(1, 1), Array(2, 1)), TrailingMinusNumbers:=True Range("A1:B26").Copy ThisWorkbook.Worksheets(y).Range("A1") ActiveWindow.Close Workbooks.OpenText Filename:= _ varItem _ , Origin:=866, StartRow:=1, DataType:=xlDelimited, TextQualifier:= _ xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, Semicolon:=False, _ Comma:=False, Space:=False, Other:=True, OtherChar:="|", FieldInfo:= _ Array(Array(1, 1), Array(2, 1)), TrailingMinusNumbers:=True Range("B3:B26").Copy ThisWorkbook.Worksheets(y).Range("C3") ActiveWindow.Close Workbooks.OpenText Filename:= _ varItem _ , Origin:=866, StartRow:=1, DataType:=xlDelimited, TextQualifier:= _ xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, Semicolon:=False, _ Comma:=False, Space:=False, Other:=True, OtherChar:="|", FieldInfo:= _ Array(Array(1, 1), Array(2, 1)), TrailingMinusNumbers:=True Range("B3:B26").Copy ThisWorkbook.Worksheets(y).Range("D3") ActiveWindow.Close Range("B3:D23").Select Selection.Replace What:=".", Replacement:=",", LookAt:=xlPart, _ SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _ ReplaceFormat:=False y = y + 1 End If Next End If ' MsgBox dctDict.Count 'Выводит кол-во файлов в "C:\" End Sub
[/vba] [moder]Для макросов кнопка тега не "fx", а "#". Исправил. Чтобы не было кракозябр, во время копирования/вставки в VBA и на сайте должен быть одинаковый язык - или и там, и тут вражеский, или нашенский.
[Evg72] учту. А какой шрифт используется здесь?Evg72
Сообщение отредактировал Evg72 - Пятница, 08.11.2013, 12:25
1. Зачем 3 раза открываете один и тот же файл? Всё ведь можно сделать сразу за одно открытие - если нужно скопировать несколько диапазонов, тем более что один и тот же диапазон зачем-то копируете в C3 и D3. 2. Вы берёте очередное имя файла, y = 6, работаете с файлом (3 раза), y = y + 1, затем берёте следующий файл... Вопрос - чему равна переменная y?
1. Зачем 3 раза открываете один и тот же файл? Всё ведь можно сделать сразу за одно открытие - если нужно скопировать несколько диапазонов, тем более что один и тот же диапазон зачем-то копируете в C3 и D3. 2. Вы берёте очередное имя файла, y = 6, работаете с файлом (3 раза), y = y + 1, затем берёте следующий файл... Вопрос - чему равна переменная y? Hugo
1. Зачем 3 раза открываете один и тот же файл? Всё ведь можно сделать сразу за одно открытие - если нужно скопировать несколько диапазонов, тем более что один и тот же диапазон зачем-то копируете в C3 и D3.
1. в одной папке 3- файла: DVN-stats.txt, MMS-stats.txt, MMS2-stats.txt. в первом случае берётся область A1:B26 и вставляется в ячейку A1 листа 6. в файлах ММС и ММС2 берется B3:B26 и вставляется в ячейку С3 и D3 соответственно. 2. во втором случае y=7. или я что то не так прописал?
1. Зачем 3 раза открываете один и тот же файл? Всё ведь можно сделать сразу за одно открытие - если нужно скопировать несколько диапазонов, тем более что один и тот же диапазон зачем-то копируете в C3 и D3.
1. в одной папке 3- файла: DVN-stats.txt, MMS-stats.txt, MMS2-stats.txt. в первом случае берётся область A1:B26 и вставляется в ячейку A1 листа 6. в файлах ММС и ММС2 берется B3:B26 и вставляется в ячейку С3 и D3 соответственно. 2. во втором случае y=7. или я что то не так прописал?Evg72