Форум программистов, компьютерный форум, киберфорум
VBA
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/8: Рейтинг темы: голосов - 8, средняя оценка - 5.00
0 / 0 / 0
Регистрация: 08.06.2015
Сообщений: 10
1

Отчет по множеству файлов

08.06.2015, 13:53. Показов 1487. Ответов 16
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте.
Помогите пожалуйста с макросом...
Необходимо следующее: Есть таблица, в нее нужно заполнить данные исходя из номеров в столбце например A1, там будут указанны номера 001, 002, 003 и тд. Исходя из первой ячейки должны заполняться следующие ячейки в строке сканируя определенный каталог на диске, с вложенными подпапками с названием таким же как первая ячейка. Ячейки которые должны заполняться всегда одинаковые, данные разные...
Например. В строке А325 ставлю номер 325, макрос находит файл с названием 325.xls в подпапках каталога "работа" и берет данные из нужных ячеек к примеру F55, H83, A5 (всегда статичны) и тд, и вставляет их в соответсвующие ячейки B1, C1, D2... и тд.
Заранее спасибо.
Вложения
Тип файла: rar Пример_112.rar (36.7 Кб, 12 просмотров)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
08.06.2015, 13:53
Ответы с готовыми решениями:

Отчет (по датам) на основе данных из других файлов Excel
Здравствуйте, коллеги! Решение вопроса сам не нашел. Прошу по возможности помочь. Есть около 150...

Собрать с разных листов из плоских файлов в один отчет
Ребята привет,нужно консолидировать реестры с разных листов в один сводный отчет в отдельном листе....

Сканер директорий и файлов pdf, который генерировал бы удобный отчет
нужно сделать сканер директорий и файлов pdf, который генерировал бы удобный отчет пример состоит...

Обход заданной директории и вывод всех её файлов и папок в файл-отчет
Написать функцию, которая делает обход заданной директории и выводит все её файлы и папки и...

16
466 / 123 / 61
Регистрация: 04.03.2015
Сообщений: 325
08.06.2015, 21:45 2
Какое количество файлов будет обрабатываться за раз? Действительно около 600?

Добавлено через 1 минуту
И во всех ли листы с данными называются одинаково?
0
0 / 0 / 0
Регистрация: 08.06.2015
Сообщений: 10
08.06.2015, 21:50  [ТС] 3
Предполагается около 1000 файлов, возможно больше, обрабатывать нужно не чаще раза в месяц.
Листы везде называются одинаково.
0
466 / 123 / 61
Регистрация: 04.03.2015
Сообщений: 325
09.06.2015, 00:35 4
Вот черновой вариант.
Насчет скорости сказать ничего не могу. Просто нету такого количества файлов.
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
Dim FSO As Object
Dim FAdr As String
Const MnDir As String = "C:\Пример_112\"
Sub test()
    Dim con As Object, rst As Object, cell As Range
    Set FSO = CreateObject("Scripting.FileSystemObject")
    Set con = CreateObject("ADODB.Connection")
    Set rst = CreateObject("ADODB.Recordset")
    For Each cell In Range("A1:A" & Sheets(1).Cells(Sheets(1).Rows.Count, 1).End(xlUp).Row)
        SearchFile MnDir, Int(cell.Value) & ".xlsx"
        If FAdr <> "" Then
            con.Open ("Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" & FAdr & "; Extended Properties=""Excel 12.0;HDR=No;IMEX=1""")
            rst.Open ("SELECT * From [Лист1$F54:F54]"), con
            cell.Offset(, 1).Value = rst.Fields("F1")
            rst.Close
        
            rst.Open ("SELECT * From [Лист1$H83:H83]"), con
            cell.Offset(, 2).Value = rst.Fields("F1")
            rst.Close
        
            rst.Open ("SELECT * From [Лист1$A5:A5]"), con
            cell.Offset(, 3).Value = rst.Fields("F1")
            rst.Close
        
            FAdr = ""
            con.Close
        End If
    Next cell
    Set FSO = Nothing
    Set rst = Nothing
    Set con = Nothing
End Sub
 
Sub SearchFile(dirname As String, FName As String)
    Dim nm
    For Each nm In FSO.GetFolder(dirname).SubFolders
        If FSO.FileExists(nm.Path & "\" & FName) Then
            FAdr = nm.Path & "\" & FName
            Exit For
        End If
        SearchFile nm.Path, FName
    Next nm
End Sub
Добавлено через 2 часа 19 минут
Второй вариант. Более быстрый.
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Dim FCol As New Collection
Dim FSO As Object
Dim FAdr As String
Const MnDir As String = "C:\Пример_112\"
Sub test()
    Dim con As Object, rst As Object, i As Integer, Mas()
    Set FSO = CreateObject("Scripting.FileSystemObject")
    Set FCol = Nothing
    Col (MnDir)
    Set con = CreateObject("ADODB.Connection")
    Set rst = CreateObject("ADODB.Recordset")
    Mas = Range("A1:D" & Sheets(1).Cells(Sheets(1).Rows.Count, 1).End(xlUp).Row).Value
    For i = LBound(Mas, 1) To UBound(Mas, 1)
        On Error Resume Next
        FAdr = FCol(Int(Mas(i, 1)) & ".xlsx")
        If Err = 0 Then
            con.Open ("Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" & FAdr & "; Extended Properties=""Excel 12.0;HDR=No;IMEX=1""")
            rst.Open ("SELECT * From [Лист1$F54:F54]"), con
            Mas(i, 2) = rst.Fields("F1")
            rst.Close
            rst.Open ("SELECT * From [Лист1$H83:H83]"), con
            Mas(i, 3) = rst.Fields("F1")
            rst.Close
            rst.Open ("SELECT * From [Лист1$A5:A5]"), con
            Mas(i, 4) = rst.Fields("F1")
            rst.Close
            con.Close
          Else
            Err = 0
        End If
    Next i
    Range("A1:D" & Sheets(1).Cells(Sheets(1).Rows.Count, 1).End(xlUp).Row).Value = Mas
    Set FCol = Nothing
    Set FSO = Nothing
    Set rst = Nothing
    Set con = Nothing
End Sub
 
Sub Col(dirname As String)
    Dim nm, fil
    For Each nm In FSO.GetFolder(dirname).SubFolders
        For Each fil In nm.Files
            FCol.Add nm.Path & "\" & fil.Name, fil.Name
        Next fil
        Col nm.Path
    Next nm
End Sub
Сгенерировал у себя 1000 файлов в разных поддиректориях.
Первый вариант работает 57-58 секунд, второй 40-41 секунду.

Может кто-то предложит еще варианты оптимизации.
1
0 / 0 / 0
Регистрация: 08.06.2015
Сообщений: 10
09.06.2015, 00:40  [ТС] 5
спасибо за макросы, буду тестить, 17 секунд не так уж и много, отчеты не так часто нужно делать, но экономия времени большая. На другом форуме предложили следующий вариант...
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
Private Declare Function SearchTreeForFile _
        Lib "imagehlp.dll" ( _
        ByVal RootPath As String, _
        ByVal InputPathName As String, _
        ByVal OutputPathBuffer As String) As Long
 
Private Sub Test()
    With Application
         .ScreenUpdating = False
         .DisplayAlerts = False
         .Calculation = xlManual
    End With
   
    Dim iSource As Range, iCell As Range
    Dim iPath$, iFileName1$, iFileName2$, iAddress$, iCount%
    
    iPath = ThisWorkbook.Path 'Можно указать 'родительскую' папку самостоятельно
    
    With ThisWorkbook.Worksheets(1)
         Set iSource = .Range(.Cells(1, "A"), .Cells(1, "A").End(xlDown))
    End With
         
    For Each iCell In iSource
        iFileName1 = iCell & ".xlsx": iFileName2 = Space(255)
        
        If SearchTreeForFile(iPath, iFileName1, iFileName2) <> 0 Then
        
           iFileName2 = Application.Trim(iFileName2)
           iFileName2 = Replace(iFileName2, iFileName1, "[" & iFileName1 & "]", , , vbTextCompare)
           
           For iCount = 1 To 3
               iAddress = Choose(iCount, "F54", "H83", "A5")
               With iCell.Offset(, iCount)
                    .Formula = "='" & iFileName2 & "Лист1'!" & iAddress
                    .Value = .Value
                    'Возможно имеет смысл заменять формулы на значения, либо
                    'сразу в трёх ячейках строки, либо вообще во 'всём' диапазоне
               End With
           Next
           
        Else
           iCell.Offset(, 1).Resize(, 3) = CVErr(xlErrNA) '#Н/Д
        End If
    Next
   
    With Application
         .Calculation = xlAutomatic
         .DisplayAlerts = True
         .ScreenUpdating = True
    End With
End Sub
0
0 / 0 / 0
Регистрация: 08.06.2015
Сообщений: 10
10.06.2015, 23:19  [ТС] 6
Пробовал тестировать, в папке где вся база файлов, возникает ошибка в строчке:
Visual Basic
1
 FCol.Add nm.Path & "\" & fil.Name, fil.Name
Наверное что то с именами файлов не так?
0
466 / 123 / 61
Регистрация: 04.03.2015
Сообщений: 325
10.06.2015, 23:52 7
Цитата Сообщение от Zidane_ Посмотреть сообщение
возникает ошибка в строчке:
FCol.Add nm.Path & "\" & fil.Name, fil.Name
Скорее всего существуют файлы с одинаковыми именами в разных папках.

Добавлено через 3 минуты
Можно добавить
Visual Basic
1
On Error Resume Next
перед 43 строкой.
Тогда будет обрабатываться первый найденный файл. Остальные макрос проигнорирует.
1
0 / 0 / 0
Регистрация: 08.06.2015
Сообщений: 10
11.06.2015, 01:04  [ТС] 8
проверял названия файлов которые макрос должен обработать (xls), совпадений не нашел...
Названия файлов других форматов могут совпадать в разных папках
0
0 / 0 / 0
Регистрация: 08.06.2015
Сообщений: 10
17.06.2015, 10:27  [ТС] 9
Помогите пожалуйста с еще одним макросом..
Нужен перенос строки с 1 на 2 лист, после заполнения нужной ячейки в этой строке... в файле столбец E.
Но нужно что бы на 2 листе заполнение шло не в последнюю пустую строку, а по порядковому номеру в столбце А, где заполнены порядковые номера...
Вложения
Тип файла: xlsx Книга1.xlsx (9.4 Кб, 7 просмотров)
0
466 / 123 / 61
Регистрация: 04.03.2015
Сообщений: 325
17.06.2015, 15:58 10
Вообще то нужно новую тему было создать.
Вот код вставить нужно в модуль первого листа.
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim c As Range, i As Integer
    If Not Intersect(Target, Range("E1:E" & Sheets(1).Cells(Sheets(1).Rows.Count, 5).End(xlUp).Row)) Is Nothing Then
        For Each c In Intersect(Target, Sheets(1).Range("E1:E" & Sheets(1).Cells(Sheets(1).Rows.Count, 5).End(xlUp).Row))
            If IsNumeric(Cells(c.Row, 1).Value) Then
                With Sheets(2)
                    For i = 2 To .Cells(.Rows.Count, 1).End(xlUp).Row
                        If .Cells(i, 1).Value >= Sheets(1).Cells(c.Row, 1).Value Then Exit For
                    Next i
                    .Rows(i & ":" & i).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
                    .Range("A" & i & ":E" & i).Value = Sheets(1).Range("A" & c.Row & ":E" & c.Row).Value
                End With
            End If
        Next c
    End If
End Sub
0
0 / 0 / 0
Регистрация: 08.06.2015
Сообщений: 10
17.06.2015, 22:42  [ТС] 11
Спасибо, Все работает.
Но при изменении данных в 1 листе, во втором остается по старому, можно сделать обновление?
И при изменении в Колонке Е, добавляется новая строка, можно сделать что бы строчка так же обновлялась?
0
466 / 123 / 61
Регистрация: 04.03.2015
Сообщений: 325
18.06.2015, 02:34 12
Цитата Сообщение от Zidane_ Посмотреть сообщение
Но при изменении данных в 1 листе, во втором остается по старому, можно сделать обновление?
И при изменении в Колонке Е, добавляется новая строка, можно сделать что бы строчка так же обновлялась?
Забыл удаление старых данных сделать. Вот обновленный код.
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim c As Range, i As Integer, temp As String
    If Not Intersect(Target, Range("E1:E" & Sheets(1).Cells(Sheets(1).Rows.Count, 5).End(xlUp).Row)) Is Nothing Then
        For Each c In Intersect(Target, Sheets(1).Range("E1:E" & Sheets(1).Cells(Sheets(1).Rows.Count, 5).End(xlUp).Row))
            If IsNumeric(Cells(c.Row, 1).Value) Then
                With Sheets(2)
                    For i = 2 To .Cells(.Rows.Count, 1).End(xlUp).Row
                        If .Cells(i, 1).Value >= Sheets(1).Cells(c.Row, 1).Value Then Exit For
                    Next i
                    .Rows(i & ":" & i).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
                    .Range("A" & i & ":E" & i).Value = Sheets(1).Range("A" & c.Row & ":E" & c.Row).Value
                    temp = temp & "," & c.Row & ":" & c.Row
                End With
            End If
        Next c
        Sheets(1).Range(Mid(temp, 2, Len(temp) - 1)).Delete Shift:=xlUp
    End If
End Sub
Добавлено через 18 минут
Если нужно, чтоб данные на первом листе не удалялись, то вот еще вариант.
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim c As Range, i As Integer, temp As String
    If Not Intersect(Target, Range("E1:E" & Sheets(1).Cells(Sheets(1).Rows.Count, 5).End(xlUp).Row)) Is Nothing Then
        For Each c In Intersect(Target, Sheets(1).Range("E1:E" & Sheets(1).Cells(Sheets(1).Rows.Count, 5).End(xlUp).Row))
            If IsNumeric(Cells(c.Row, 1).Value) Then
                With Sheets(2)
                    For i = 2 To .Cells(.Rows.Count, 1).End(xlUp).Row
                        If .Cells(i, 1).Value >= Sheets(1).Cells(c.Row, 1).Value Then Exit For
                    Next i
                    If .Cells(i, 1).Value = Sheets(1).Cells(c.Row, 1).Value Then _
                    .Rows(i & ":" & i).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
                    .Range("A" & i & ":E" & i).Value = Sheets(1).Range("A" & c.Row & ":E" & c.Row).Value
                End With
            End If
        Next c
    End If
End Sub
0
0 / 0 / 0
Регистрация: 08.06.2015
Сообщений: 10
18.06.2015, 08:23  [ТС] 13
Цитата Сообщение от Vovchikvsb Посмотреть сообщение
Если нужно, чтоб данные на первом листе не удалялись, то вот еще вариант.
второй вариант тоже самое что и самый первый... наверное что то не то скопировалось....
С удалением данных на 1 листе не подходит... данные должны оставаться..
0
466 / 123 / 61
Регистрация: 04.03.2015
Сообщений: 325
18.06.2015, 12:38 14
Цитата Сообщение от Zidane_ Посмотреть сообщение
наверное что то не то скопировалось
В 10 строчке = с <> напутал.
Вот правильный вариант.
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim c As Range, i As Integer, temp As String
    If Not Intersect(Target, Range("E1:E" & Sheets(1).Cells(Sheets(1).Rows.Count, 5).End(xlUp).Row)) Is Nothing Then
        For Each c In Intersect(Target, Sheets(1).Range("E1:E" & Sheets(1).Cells(Sheets(1).Rows.Count, 5).End(xlUp).Row))
            If IsNumeric(Cells(c.Row, 1).Value) Then
                With Sheets(2)
                    For i = 2 To .Cells(.Rows.Count, 1).End(xlUp).Row
                        If .Cells(i, 1).Value >= Sheets(1).Cells(c.Row, 1).Value Then Exit For
                    Next i
                    If .Cells(i, 1).Value <> Sheets(1).Cells(c.Row, 1).Value Then _
                    .Rows(i & ":" & i).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
                    .Range("A" & i & ":E" & i).Value = Sheets(1).Range("A" & c.Row & ":E" & c.Row).Value
                End With
            End If
        Next c
    End If
End Sub
0
0 / 0 / 0
Регистрация: 08.06.2015
Сообщений: 10
18.06.2015, 14:47  [ТС] 15
Благодарю, теперь как надо..
А можно сделать так что бы все значения на 2 листе обновлялись, при запуске макроса?
0
0 / 0 / 0
Регистрация: 08.06.2015
Сообщений: 10
19.06.2015, 22:57  [ТС] 16
Цитата Сообщение от Vovchikvsb Посмотреть сообщение
В 10 строчке = с <> напутал.
Вот правильный вариант.
Или же значения обновлялись при редактировании ячеек из столбцов B, С, D
0
466 / 123 / 61
Регистрация: 04.03.2015
Сообщений: 325
20.06.2015, 08:54 17
Цитата Сообщение от Zidane_ Посмотреть сообщение
Или же значения обновлялись при редактировании ячеек из столбцов B, С, D
В строках 3 и 4 поменяйте E1 на B1.
0
20.06.2015, 08:54
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
20.06.2015, 08:54
Помогаю со студенческими работами здесь

На чем написать сканер директорий и файлов pdf, который генерировал бы удобный отчет
нужно сделать сканер директорий и файлов pdf, который генерировал бы удобный отчет пример состоит...

Резервное копирование файлов полное, инкрементные и отчет на почту о том, что все успешно
Всем привет. Нужна программа Резервное копирование файлов полное, Инкрементные и отчет на почту о...

Отчет СКД. Вывод нескольких таблиц в отчет из разных запросов.
Привет, коллеги! Возникла необходимость в одном отчете видеть 2 таблички: одну по продажам, другую...

Как отчет из построителя отчетов сохранить во внешний отчет?
В консоли построителя отчетов(ИР), получается сам очень аккуратный отчет , но сохраняется и...

Как открыть отчёт с указанным значением параметра, который используется в запросе на котором строится отчёт?
Есть запрос, по нему построен отчёт: SELECT Товар.Артикул, ., Товар.Наименование, ., .,...

Отчет РАУЗ переделать в отчет с партионным учетом
Возможно ли типовой отчет построенный на РАУЗ переделать так, чтобы он работал в партионном учете?...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru