Профессиональные приемы работы в Microsoft Excel

Обмен опытом => Microsoft Excel => Тема начата: Виктория Зуева от 25.06.2009, 12:17

Название: "Сборка" данных в новую книгу из файлов в папке без открытия исходных
Отправлено: Виктория Зуева от 25.06.2009, 12:17
Пример:
Есть две папки - "1квартал" и "2квартал" на диске D:\Отчеты2009.
Папки содержат файлы Excel - ежемесячные отчеты от отделов (в каждой папке около 70 штук). Имена файлов в папках одинаковые (Отдел 1.xls, Отдел 2.xls и т.д.) 
Файлы имеют похожую структуру - на 1-м (единственном) листе таблица, шапка таблицы у всех одинаковая (в 3-й строке), а вот строка итогов "прыгает" в зависимости от содержимого от 15 до 60 строки
( в D:\Отчеты2009\1квартал\Отдел 1.xls   итоговая строка - 25,
а в D:\Отчеты2009\2квартал\Отдел 1.xls   итоговая строка - 53).

В папке "1квартал" был создан файл Excel - Отчет 1квартал.xls , в который "ручками" были вставлены в ячейки строк  ссылки - на ячейки других книг папки "1квартал",  т.е. на соответствующие итоговые значения из файлов отчетов по отделам.
Например, ссылка в файле "Отчет 1квартал.xls" выглядит следующим образом (при закрытом файле Отдел 1.xls):
='D:\Отчеты2009\1квартал\[Отдел 1.xls]Лист1'!$D$25

Проблемы и вопросы:
Пока файл "Отчет 1квартал.xls" лежит в папке D:\Отчеты2009\1квартал\, все связи нормально работают. Если папка "1 квартал" со всем содержимым перемещается на другой диск, связи в  файле "Отчет 1квартал.xls" приходится отключать... иначе =#Н/Д.
1) Можно ли макросом определять текущее местонахождение отчетного файла на диске и менять в нем адреса ссылок на исходные файлы с тем же именем, но из текущей папки?
2) Что-бы придумать, чтоб для папки "2квартал" в файл "Отчет 2квартал.xls" итоговые данные по отделам "собирать" не ручками?

Название: Re: Изменение в ссылках пути к текущей папке с файлом книги
Отправлено: boa от 25.06.2009, 14:51
начну с конца :)
Цитата: Виктория Зуева от 25.06.2009, 12:17
2) Что-бы придумать, чтоб для папки "2квартал" в файл "Отчет 2квартал.xls" итоговые данные по отделам "собирать" не ручками?

в итоговой строке в одной и той же колонке я бы написал одинаковый для всех файлов текст  типа "Общий итог"
тогда поиск номера итоговой стоки можно сделать так:
    Do: iRow = iRow + 1
    Loop Until Cells(iRow, [номер столбца]) = "Общий итог"

на выходе  iRow будет = номеру искомой строки
Название: Re: Изменение в ссылках пути к текущей папке с файлом книги
Отправлено: Виктория Зуева от 25.06.2009, 15:25
Ячейка с текстом "Итого по отделу" присутствует во 2 столбце почти внизу каждого "Отчета". Ниже еще есть непустые строки. Я вот про ВПР думала по этому поводу.
А вот что делать с этим iRow? Его в модуль "отдела" или "отчета" прикручивать?  ???
Название: Re: Изменение в ссылках пути к текущей папке с файлом книги
Отправлено: boa от 25.06.2009, 15:43
это в модуль отчета для сбора инфы с разных файлов


Sub Reports()
Dim File  As Variant
Dim UserFile  As Variant
Dim iRow As Integer
Dim iRowRep As Integer
Dim i As Integer
Dim j As Integer


File = Array(file1, file2, file3, file4, file5, file6, file7, file8, file9, "и т.д.")
iRowRep = 5

    For i = LBound(File) To UBound(File)

        UserFile = File(i) & ".xls"
'можно сформировать имя файла и по другому
'    For i = 1 To [последний отдел]
'        UserFile = "Отдел " & i & ".xls"
'    Next i

        With Workbooks(UserFile).Sheets(1)
iRow = 0 'или следующая после "шапки"
            Do: iRow = iRow + 1
            Loop Until .Cells(iRow, 2) = "Итого по отделу"
       
           
            For j = 1 To [последний столбец]
                Cells(iRowRep, j) = .Cells(iRow, j)
            Next j
   
        End With
        iRowRep = iRowRep + 1
    Next i

End Sub



P.S. Если будут сложности,  - выложите файлы-образцы
Название: Re: Изменение в ссылках пути к текущей папке с файлом книги
Отправлено: _Boroda_ от 26.06.2009, 04:13
Я такие вещи делаю неизменяемым файлом без макросов, который после автозаполнения сохраняю в нужную папку.
Файл "Отчет" в папке "Отчеты2009". Он един для всех кварталов.
Порядок действий:
1) открыть все файлы в папке "nквартал" (n - номер квартала),
2) открыть файл "Отчет",
3) закрыть все файлы папки "nквартал".
В файле "Отчет" останутся все данные за квартал n.
Пункты 1 и 2 можно поменять местами.
Если случайно открыты файлы из разных папок (например 1квартал - отдел 1 и 2квартал - отдел 2), то в ячейке А1 - красная ругань, если все файлы из одной папки, то в А1 - № квартала.
Работает для 100 файлов, но можно увеличить.
ВПР в строке 5 нужно подогнать под родные файлы "отдел m" (вместо 2 поставить номер своего столбца с данными и изменить массив для поиска).
Название: Re: Изменение в ссылках пути к текущей папке с файлом книги
Отправлено: boa от 28.06.2009, 13:45
Виктория, посмотрите, это то?
Название: Re: Изменение в ссылках пути к текущей папке с файлом книги
Отправлено: Виктория Зуева от 02.07.2009, 16:45
Boroda, спасибо за ваш пример - взяла себе в "копилку идей"! Но хочется сделать через макрос.
Вариант boa подошел в этом случае куда лучше. +1
Одно НО - оба варианта требуют открытия исходных файлов.
Может, есть вариант без открытия исходников решить задачу, или с поочередным открытием штук по 10-15-20?
Название: Re: Изменение в ссылках пути к текущей папке с файлом книги
Отправлено: boa от 02.07.2009, 17:00
Цитата: Виктория Зуева от 02.07.2009, 16:45
Может, есть вариант без открытия исходников решить задачу, или с поочередным открытием штук по 10-15-20?

без открытия не знаю :(, а с поочередным открытием можно. Здесь (https://forum.msexcel.ru/microsoft_excel/vytaskivanie_iz_papki_faylov_excel_obedinenie_ih_v_odin_s_dob_imeni_fayla-t860.0.html) смотрели?
Название: Re: "Сборка" данных в новую книгу из файлов в папке без открытия исходных
Отправлено: Виктория Зуева от 06.07.2009, 00:46
Вот накопала ссылок на английском, но, думаю, знающим термины VBA будет понятно.

Ресурсы про извлечение данных из файлов Excel:
http://www.mrexcel.com/forum/showthread.php?t=140187
Есть пример кода и ссылка - в ответе:
http://www.rondebruin.nl/tips.htm
Оттуда взято:
http://www.rondebruin.nl/copy3.htm
Там есть под заголовком Example workbook пример кода в файле.

Еще ресурс
Retrieving Data From Closed Excel Files Through A Macro:
http://www.bigresource.com/VB-Retrieving-Data-from-closed-Excel-Files-through-a-macro--W0fr1vyP.html#

И видео - может, не совсем в тему...
http://www.youtube.com/watch?v=pFgwa9nQTU0

Может, из этой кучи идей можно что-либо накопать по моему вопросу?
А именно - выборка данных из закрытых книг в файл-отчет (если он лежит в той же папке, что и исходные).


Название: Re: "Сборка" данных в новую книгу из файлов в папке без открытия исходных
Отправлено: zhal от 08.07.2009, 11:20
А вы можете еще раз уточнить, Вы частично решили для себя задачу ии нет?
Вот способ скрыть от пользовательских глаз открываемые макросом Excel-книги.
Основной смысл - это создание в макросе нового Excel приложения и изменение его свойста visible в false
Что не понятно - разъясню ;)

Sub

Sub OpenFiles()

Set myWb = ThisWorkbook ' Текущая книга, из которой запускаем макрос
Dim NewApp As New Excel.Application 'Новое Excel приложение, которое будет не видимым
Dim OpenBook As Workbook ' Открываемая не видимая книга
Dim FileDir As String 'Директория, в которой лежат открываемые файлы
Dim FileMask As String ' Маска фалов, которые открываем
Dim OpenFileName As String ' Наименование файла в директории

' Задаем директорию, в которой лежат файлы. Если она равна директории текущей книги,
' то можно задать FileDir = myWb.Path
FileDir = "c:\0\local_cc"
' Задаем маску файлов
FileMask = "*.xls"

NewApp.Visible = False ' Собственно делаем невидимым приложение, в котором будем открывать книги

' корректировка переменной с директорией, если та не содержит косую черту в конце
If Right(FileDir, 1) <> "\" Then
   FileDir = FileDir & "\"
End If

'Считываем наименование первого файла в папке
OpenFileName = Dir(FileDir & FileMask)
Do While OpenFileName <> "" ' Считываем наименования фалов в директории
   If FileDir & OpenFileName <> myWb.FullName Then ' Исключаем случай повторного открытия Главной книги
      NewApp.Workbooks.Open FileName:=FileDir & OpenFileName ' Открываем книгу
      Set OpenBook = NewApp.ActiveWorkbook ' Запоминаем ссылку на открытую книгу
      myWb.Activate ' Делаем Активной Главную книгу
     
      ' Делаем то, что нам нужно. К Главной книге обращаемся как к myWb, к открытой для считывания как к OpenBook
      Debug.Print OpenFileName ' Для отладки. Выводит имена открываемых файлов в immediate окно VBA. В Рабочем варианте закомментировать
     
     
      OpenBook.Close ' Закончили обработку текущей книги. Закрывам книгу
   End If
   OpenFileName = Dir ' Считываем наименование следующего файла в директории
Loop

NewApp.Quit 'закрываем не видимое приложение

End Sub

Название: Re: "Сборка" данных в новую книгу из файлов в папке без открытия исходных
Отправлено: boa от 08.07.2009, 18:44
Виктория, вот файл, который будет работать с закрытыми книгами
Он их сам откроет и сам закроет. Время работы макроса, конечно, сильно возрастает, но думаю Вы сами сделаете для себя выбор.

P.S. Извините, что заставил себя ждать. Некогда было "голову поднять"
P.P.S. За ссылки спасибо, интересны, но опять же, работают по принципу "Открыл файл-Прочитал инфу-Закрыл". Нашел по Вашим ссылкам интересную инфу  Copy a range from closed workbooks (ADO)
(http://www.rondebruin.nl/ado.htm), но разбираться пока не нашлось времени. Возможно, после изучения данного метода смогу модернизировать Ваш код.
Название: Re: "Сборка" данных в новую книгу из файлов в папке без открытия исходных
Отправлено: zhal от 09.07.2009, 14:43
Цитата: boa от 08.07.2009, 18:44
... вот файл, который будет работать с закрытыми книгами
Он их сам откроет и сам закроет.

Макрос работать будет ;), но ...
Открывая книги, делает их доступными для глаза и для внешнего вмешательства.
ИМХО в случае длительных запросов просто нельзя будет на компе заниматься другими делами. Если Excel-книга будет постоянно терять фокус, выполнение макроса может вылетать с ошибками.
ИМХО все-таки нужно открывать книги (из которых считываются данные) в новом невидимом application:


Sub ...
...
Dim NewApp As New Excel.Application 'Новое Excel приложение, которое будет не видимым
...
NewApp.Visible = False ' Собственно делаем невидимым приложение, в котором будем открывать книги
...
NewApp.Workbooks.Open FileName:=FileDir & OpenFileName ' Открываем книгу
...
NewApp.quit
End Sub


Относительно ADO. Это всего лишь способ доступа к данным. Он позволяет работать с таблицами Excel как с таблицами базы данных, с помощью SQL-запросов. ИМХО здесь не уместен, поскольку не требуется фильтровать строки и преобразовывать значения. Перебирать строки из Recordset придется точно также, как перебираются строки Excel-таблицы.
Название: Re: "Сборка" данных в новую книгу из файлов в папке без открытия исходных
Отправлено: boa от 09.07.2009, 15:59
Цитата: zhal от 09.07.2009, 14:43
Открывая книги, делает их доступными для глаза и для внешнего вмешательства.
zhal, вот рабочая версия. Распакуйте архив во временную папку. Попробуйте во время выполнения макроса посмотреть или что-либо изменить в иных файлах кроме Отчета.

Цитата: zhal от 09.07.2009, 14:43ИМХО все-таки нужно открывать книги (из которых считываются данные) в новом невидимом application:
Возможно ИМХО изменится ;)

P.S. Только не надо хитрить и расставлять точки остановки макроса :)
Название: Re: "Сборка" данных в новую книгу из файлов в папке без открытия исходных
Отправлено: boa от 09.07.2009, 16:48
Цитата: zhal от 09.07.2009, 14:43
ИМХО все-таки нужно открывать книги (из которых считываются данные) в новом невидимом application:
Надо отдать должное открытие в скрытом окне достаточно действенный способ sm_clap +1 и может быть использован во многих ситуациях...
Название: Re: "Сборка" данных в новую книгу из файлов в папке без открытия исходных
Отправлено: Виктория Зуева от 14.07.2009, 23:26
Спасибо за предложенное решение!
"Прикручиваю" к своим корявым данным. Еще бы с форматом отчета потом справиться... Есть еще
вопрос -
если еще из файла Отдела в Отчет надо "вытащить" значение именованной ячейки (имя - kod_otd), которую добавили в заголовок, то как это сделать?
Ячейка - в 3-й строке.
Название: Re: "Сборка" данных в новую книгу из файлов в папке без открытия исходных
Отправлено: boa от 15.07.2009, 00:14
Цитата: Виктория Зуева от 14.07.2009, 23:26
Еще бы с форматом отчета потом справиться...
воспользуйтесь макрорекодером, а потом в созданном макросе, как говорят скульпторы, уберите лишнее :)

Цитата: Виктория Зуева от 14.07.2009, 23:26
...из файла Отдела в Отчет надо "вытащить" значение именованной ячейки (имя - kod_otd), которую добавили в заголовок, то как это сделать?
после строки
               Rezultat(i, 1) = Left(FileOtdel, Len(FileOtdel) - 4) 'обрезаем расширение названия файла
добавьте
               On Error Resume Next
               Rezultat(i, 1) = .Range("kod_otd") & " " & Left(FileOtdel, Len(FileOtdel) - 4)
Название: Re: "Сборка" данных в новую книгу из файлов в папке без открытия исходных
Отправлено: Виктория Зуева от 15.07.2009, 11:33
Ругается Excel на строчку в макросе:

ReDim Rezultat(1 To i, 1 To 4)  'посчитав, создаем массив в который потом занесем все данные

Я поняла, что если код отдела надо в отдельную ячейку, то в массиве Rezultat надо увеличить размерность до (1 To i, 1 To 5) и далее с результатами справлюсь (я надеюсь  :) ).
И еще - в каждый отчет от отдела добавлен титульный лист с реквизитными данными по отделу, на нем же будет ячейка с именем kod_otd (Лист 1, имя листа "Титул"), а сама таблица теперь будет на листе 2 "Отчет".
Надо ли изменить следующую строку?
With Workbooks(FileOtdel).Sheets(1)
(я так понимаю, что надо...но как?)
Название: Re: "Сборка" данных в новую книгу из файлов в папке без открытия исходных
Отправлено: boa от 15.07.2009, 19:23
Цитата: Виктория Зуева от 15.07.2009, 11:33
Ругается Excel на строчку в макросе:
ReDim Rezultat(1 To i, 1 To 4)  'посчитав, создаем массив в который потом занесем все данные
Я поняла, что если код отдела надо в отдельную ячейку, то в массиве Rezultat надо увеличить размерность до (1 To i, 1 To 5) и далее с результатами справлюсь (я надеюсь  :) ).
поняли правильно, но в прошлом примере, что бы не изменять размерность, я код отдела объединил с именем файла, хотя если у Вас есть реестр "код/название отдела", то тогда, конечно, лучше в отдельную ячейку, а потом, сопоставив, вывести красивое ИМЯ ОТДЕЛА.
Цитата: Виктория Зуева от 15.07.2009, 11:33
И еще - в каждый отчет от отдела добавлен титульный лист с реквизитными данными по отделу, на нем же будет ячейка с именем kod_otd (Лист 1, имя листа "Титул"), а сама таблица теперь будет на листе 2 "Отчет".
Надо ли изменить следующую строку?
With Workbooks(FileOtdel).Sheets(1)
(я так понимаю, что надо...но как?)
Да, и очень просто :)
With Workbooks(FileOtdel).Sheets("Отчет")
либо
With Workbooks(FileOtdel).Sheets("Титул")
соответственно.

на всяк.случ. прикрепляю архив
Название: Re: "Сборка" данных в новую книгу из файлов в папке без открытия исходных
Отправлено: Виктория Зуева от 17.07.2009, 16:32
Проблема!!!
В последнем макросе - newApplication в невидимом режиме открывается,
Dim newApp As New Excel.Application 'Новое Excel приложение
newApp.Visible = False

в него по очереди файлы загружаются, файлы "выгружаются" (т.е. закрываются),
newApp.Workbooks(FileOtdel).Close 'когда мы с файла "выжали все соки" - закрываем его
а вот для приложения команды закрытия нет... оно так и остается висеть, невидимое... ЧТО ДЕЛАТЬ?
Куда и что дописать?  ???
А то макрос три раза запустила - и 3 Excel-a "скрытые" повисли в памяти.
Название: Re: "Сборка" данных в новую книгу из файлов в папке без открытия исходных
Отправлено: Виктория Зуева от 17.07.2009, 20:15
Эврика!
Нашла!!!

NewApp.Quit
после 2-го Loop надо вставить...
Закрыть чтобы "невидимое приложение"...
Название: Re: "Сборка" данных в новую книгу из файлов в папке без открытия исходных
Отправлено: boa от 18.07.2009, 01:02
Да воздастся ищущему :)
Название: Re: "Сборка" данных в новую книгу из файлов в папке без открытия исходных
Отправлено: Виктория Зуева от 21.07.2009, 23:03
Как в этом коде отключить автопересчет для newApp? (привожу часть кода)
Dim newApp As New Excel.Application 'Новое приложение в невидимиом режиме
newApp.Visible = False

TimeStart = GetTickCount
Application.ScreenUpdating = 0 'Отключаем автообновление
Application.Calculation = xlManual
Application.EnableCancelKey = xlDisabled    ' Запрет прерывания макроса

v_Path = ThisWorkbook.Path & "\"
FileOtdel = Dir(v_Path)
v_Mask = "XLS"

i = 0
   Do While FileOtdel <> ""
       If UCase(Right(FileOtdel, 3)) = v_Mask Then
           i = i + 1 ' здесь мы посчитаем сколько у нас файлов, соответствующих маске, в папке
       End If
       FileOtdel = Dir
   Loop

ReDim Rezultat(1 To i, 1 To 9) 'посчитав, создаем массив, в который потом занесем все данные

FileOtdel = Dir(v_Path)
i = 1
   Do While FileOtdel <> "" ' Запускаем цикл до тех пор пока в папке есть интересующие нас файлы
       If UCase(Right(FileOtdel, 3)) = v_Mask Then
'           MsgBox (v_iFileName)
       
       If Not FileOtdel = ThisWorkbook.Name Then
           newApp.Workbooks.Open Filename:=v_Path & FileOtdel 'открываем найденный файл

           With newApp.Workbooks(FileOtdel)
Название: Re: "Сборка" данных в новую книгу из файлов в папке без открытия исходных
Отправлено: Виктория Зуева от 21.07.2009, 23:05
А то для каждого файла из папки "вываливается" запрос:
Название: Re: "Сборка" данных в новую книгу из файлов в папке без открытия исходных
Отправлено: boa от 22.07.2009, 00:04
newApp.DisplayAlerts = False 'Отключаем окна диалогов скрытого Excel