Excel vba обращение к закрытой книге

Хитрости »

6 Май 2011              261605 просмотров


Как получить данные из закрытой книги?

Достаточно часто появляется вопрос: как извлечь данные из закрытой книги Excel через VBA? Звучит может быть странновато, но это так: вопрос регулярно поднимается на форумах. Собственно, именно в связи с этим и появилась на свет данная статья. В принципе ничего сложного в задаче нет. При этом получить данные можно разными способами, в том числе при помощи функций пользователя(UDF).
Хотя если вдаваться в технические подробности, то получить данные из закрытой книги вообще нельзя. Так или иначе, на уровне системы файл все равно открывается, различие лишь в том как именно и к чему при этом предоставляется доступ. Поэтому переозвучим классическую постановку задачи в более распространенную в жизни: «Как получить данные из книги, не открывая её так, чтобы об этом узнал пользователь»

Попробуем разобраться с некоторыми методами, их плюсами и минусами:

  • Получение данных из закрытой книги при помощи процедуры
  • Получение данных из закрытой книги при помощи UDF
  • Получение данных из закрытой книги при помощи запроса ADO
  • Получение данных из закрытой книги при помощи Power Query
Получение данных из закрытой книги при помощи процедуры VBA
Sub Get_Value_From_Close_Book_Formula()
    Dim sPath As String, sFile As String, sShName As String
    sPath = "C:Documents and Settings" '"
    sFile = "Книга1.xls" '"
    sShName = "Лист1" '"
    Application.DisplayAlerts = 0
    With Range("A1:A100")
        .Formula = "='" & sPath & "[" & sFile & "]" & sShName & "'!" & "A1" '"
        '"A1" - указывается начальная ячейка диапазона, из которого необходимо получить значения
        .Value = .Value
    End With
    Application.DisplayAlerts = 1
End Sub

Данный код работает достаточно медленно, но с его помощью можно «вытащить» из закрытой книги значения сразу нескольких ячеек. Код ниже работает быстрее, но с его помощью можно извлечь значения лишь одной ячейки:

Sub Get_Value_From_Close_Book_Excel4Macro()
    Dim sPath As String, sFile As String, sShName As String
    Dim sAddress As String, vData
    sPath = "C:Documents and Settings" '"
    sFile = "Книга1.xls" '"
    sShName = "Лист1" '"
 
    sAddress = "'" & sPath & "[" & sFile & "]" & sShName & "'!" & Range("A1").Address(ReferenceStyle:=xlR1C1) '"
    vData = ExecuteExcel4Macro(sAddress)
End Sub

Если честно, сам я не очень-то люблю ни один из данных методов, т.к. они совершенно лишены гибкости. С их помощью можно получить исключительно значения ячеек. Форматы, формулы или другие свойства ячеек получить уже не получится. Поэтому я предпочитаю открывать книгу и копировать то, что мне надо. Делаю это, скрывая от пользователя при помощи свойства ScreenUpdating объекта Application.

Sub Get_Value_From_Close_Book()
    Dim sShName As String, sAddress As String, vData
    Dim objCloseBook As Workbook
    'Отключаем обновление экрана
    Application.ScreenUpdating = False
    Set objCloseBook = Workbooks.Open("C:Documents and SettingsКнига1.xls")
    sAddress = "A1:C100" 'или одна ячейка - "A1"
    'получаем значение
    vData = Sheets("Лист1").Range(sAddress).Value
    'Записываем данные на активный лист книги,
    'с которой запустили макрос
    If IsArray(vData) Then
        [A1].Resize(UBound(vData, 1), UBound(vData, 2)).Value = vData
    Else
        [A1] = vData
    End If
    'если надо копировать ячейки с форматами, 
    'то можно использовать стандартные методы копирования вставки
    'objCloseBook.Sheets("Лист1").Range(sAddress).Copy
    '[A1].PasteSpecial xlPasteValues  'вставляем значения
    '[A1].PasteSpecial xlPasteFormats 'вставляем форматы
    'закрываем книгу(из которой получали значения) без сохранения
    objCloseBook.Close False
    'Включаем обновление экрана
    Application.ScreenUpdating = True
End Sub

Есть и более экзотический метод — при помощи GetObject:

Sub Get_Value_From_Close_Book2()
    Dim sShName As String, sAddress As String, vData
    Dim objCloseBook As Object
    'Отключаем обновление экрана
    Application.ScreenUpdating = False
    Set objCloseBook = GetObject("C:Documents and SettingsКнига1.xls")
    sAddress = "A1:C100" 'или одна ячейка - "A1"
    'получаем значение
    vData = objCloseBook.Sheets("Лист1").Range(sAddress).Value
    'Записываем данные на активный лист книги,
    'с которой запустили макрос
    If IsArray(vData) Then
        [A1].Resize(UBound(vData, 1), UBound(vData, 2)).Value = vData
    Else
        [A1] = vData
    End If
    'если надо копировать ячейки с форматами, 
    'то можно использовать стандартные методы копирования вставки
    'objCloseBook.Sheets("Лист1").Range(sAddress).Copy
    '[A1].PasteSpecial xlPasteValues  'вставляем значения
    '[A1].PasteSpecial xlPasteFormats 'вставляем форматы
    'закрываем книгу(из которой получали значения) без сохранения
    objCloseBook.Close False
    'Включаем обновление экрана
    Application.ScreenUpdating = True
End Sub

При таком подходе пользователь разницы не увидит, а действия можно производить с ячейками разные: и сравнение, и отбор по критериям, и фильтровать, и сортировать и т.д. Плюс из книги можно переносить не только значения ячеек, но и форматы, формулы. Но выбирать метод получения значений из закрытых книг вам. Все зависит от ситуации. Все указанные коды работают. Если не работают — то проверьте верно ли указаны все исходные данные(имя книги и расширение, имя листа, путь к папке с книгой).


Получение данных из закрытой книги при помощи UDF

Тот же код, что уже был рассмотрен выше, но оформленный в виде UDF(функции пользователя):

Function Get_Value_From_Close_Book(sWb As String, sShName As String, sAddress As String)
    Dim vData, objCloseBook As Object
    Set objCloseBook = GetObject(sWb)
    'получаем значение
    vData = objCloseBook.Sheets(sShName).Range(sAddress).Value
    objCloseBook.Close False
    Set objCloseBook = Nothing
    'Возвращаем данные в ячейку с функцией
    Get_Value_From_Close_Book = vData
End Function

Синтаксис функции (вызов с листа):
=Get_Value_From_Close_Book(«C:Книга1.xls»;»Лист1″;»B1″)
sWb — полный путь до книги, данные из которой необходимо извлечь («C:Книга1.xls»)
sShName — имя листа в указанной книге, данные из которого необходимо извлечь («Лист1»)
sAddress — адрес ячейки(диапазона) данные которой необходимо получить («B1»)

Чтобы получить массив ячеек(например B1:B10), необходимо выделить необходимое количество ячеек и ввести в них эту функцию, как формулу массива.
Думаю, не надо пояснять, что любой аргумент может быть задан не статичным текстом, а ссылкой на ячейку с этим текстом. Именно в этом и преимущество использования именно функций, а не процедур.


ПОЛУЧЕНИЕ ДАННЫХ ПРИ ПОМОЩИ ЗАПРОСА ADO

Так же есть еще один достаточно экзотический метод получения данных из действительно закрытой книги — через ADO(ActiveX Data Objects). По сути это получение данных через запрос SQL, используя для этого технологию ADO.

'---------------------------------------------------------------------------------------
' Procedure : Extract_Value_ADO
' DateTime  : 02.07.2014 16:47
' Author    : The_Prist(Щербаков Дмитрий)
'             http://www.excel-vba.ru
' Purpose   : Функция получения данных из закрытой книги при помощи ADO
'             в таком виде не может быть использована вызовом с листа
'---------------------------------------------------------------------------------------
Function Extract_Value_ADO(sPath As String, sFileName As String, sShName As String, sRng As String)
    Dim objADO_Con As Object, objRS As Object
    Dim sFullFileName As String, sADORng As String
 
    'проверяем наличие слеша в пути к файлу
    If Right(sPath, 1) <> "" Then sPath = sPath & ""
    'если ячейка только одна - меняем вид адресации на ячейка:ячейка, как того требует ADO
    If Range(sRng).Count = 1 Then
        sADORng = sRng & ":" & sRng
    Else
        sADORng = sRng
    End If
    sFullFileName = sPath & sFileName
    With CreateObject("ADODB.Connection")
        'подключаемся к файлу
        .Open "Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};ReadOnly=1;DBQ=" & sFullFileName & ";"
        'извлекаем записи из указанного диапазона в objRS
        Set objRS = .Execute("select * FROM [" & sShName & "$" & sADORng & "]")
        'выгружаем извлеченные данные на активный лист, начиная с ячейки А1
        Cells(1, 1).CopyFromRecordset objRS
        'Extract_Value_ADO = objRS.Fields(0).Value
    End With
    Set objRS = Nothing
End Function

Вызывать эту функцию следует из другой процедуры или функции. Пример процедуры, для вызова этой функции:

'---------------------------------------------------------------------------------------
' Procedure : Get_Value_From_Close_Book_ADO
' Purpose   : Вызов функции Extract_Value_ADO
'---------------------------------------------------------------------------------------
Sub Get_Value_From_Close_Book_ADO()
    Extract_Value_ADO ThisWorkbook.path, "Книга1.xls", "Лист1", "A1:B25"
End Sub

Для вызова функции Extract_Value_ADO непосредственно с листа(в виде функции UDF) придется несколько изменить приведенный выше код функции, либо извлекать функцией значение только одной ячейки, что будет не очень экономично с точки зрения ресурсов и использование для этого ADO будет слишком неоправданным. Если кому необходимо, то для вызова функции с ячейки листа и возврата значения одной ячейки, необходимо заменить строку:

Cells(1, 1).CopyFromRecordset objRS

на такую:

Extract_Value_ADO = objRS.Fields(0).Value

Синтаксис вызова с листа в таком случае будет следующим:
=Extract_Value_ADO(«C:»; «Книга1.xls»; «Лист1»; «A1»)
Важно: если данные извлекаются только из одной ячейки, то следует указать две ячейки: А1:А2. Это особенность работы с запросами

Если же необходимо извлекать данные диапазона ячеек, то в этом случае можно применить такую функцию:

'---------------------------------------------------------------------------------------
' Procedure : Extract_Value_ADO
' DateTime  : 02.07.2014 16:47
' Author    : The_Prist(Щербаков Дмитрий)
'             http://www.excel-vba.ru
' Purpose   : Функция получения данных из закрытой книги при помощи ADO
'             вызывается с листа как функция массива(если получаем данные с диапазона)
'---------------------------------------------------------------------------------------
Function Extract_Value_ADO_Sh(sPath As String, sFileName As String, sShName As String, sRng As String)
    Dim objADO_Con As Object, objRS As Object
    Dim sFullFileName As String, sADORng As String
    Dim avTmp(), avRes(), li As Long, lr As Long, lc As Long
    'проверяем наличие слеша в пути к файлу
    If Right(sPath, 1) <> "" Then sPath = sPath & ""
    'если ячейка только одна - меняем вид адресации на ячейка:ячейка, как того требует ADO
    If Range(sRng).Count = 1 Then
        sADORng = sRng & ":" & sRng
    Else
        sADORng = sRng
    End If
    sFullFileName = sPath & sFileName
    With CreateObject("ADODB.Connection")
        'подключаемся к файлу
        .Open "Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};ReadOnly=1;DBQ=" & sFullFileName & ";"
        'получаем кол-во строк в запросе
        Set objRS = .Execute("SELECT COUNT(*) FROM [" & sShName & "$" & sADORng & "]")
        li = objRS.Fields(0).Value
        'извлекаем записи из указанного диапазона в objRS
        Set objRS = .Execute("SELECT * FROM [" & sShName & "$" & sADORng & "]")
        'выгружаем извлеченные данные на активный лист, начиная с ячейки А1
        ReDim avRes(1 To li, 1 To objRS.Fields.Count)
        avTmp = objRS.getrows(li, 0)    'получаем массив данных запроса
        For lr = 0 To li - 1    'цикл по строкам
            For lc = 0 To UBound(avTmp, 1) 'цикл по столбцам
                'значения Null не допускаются, поэтому приходится их подменять до выгрузки на лист
                If IsNull(avTmp(lc, lr)) Then
                    avTmp(lc, lr) = Empty
                End If
                avRes(lr + 1, lc + 1) = avTmp(lc, lr)
            Next lc
        Next lr
    End With
 
    Extract_Value_ADO_Sh = avRes
    Set objRS = Nothing
End Function

Синтаксис вызова с листа точно такой же как и в функции выше, только нужно будет выделить необходимое количество ячеек и ввести в них эту функцию, как формулу массива.:
=Extract_Value_ADO_Sh(«C:»; «Книга1.xls»; «Лист1»; «A1:B10»)
sPath — путь к папке с книгой, данные из которой необходимо извлечь («C:»)
sWb — имя книги, включая расширение(.xls в примере), данные из которой необходимо извлечь («Книга1.xls»)
sShName — имя листа в указанной книге, данные из которого необходимо извлечь («Лист1»)
sAddress — адрес ячейки(диапазона) данные которой необходимо получить («A1»)
Важно: если данные извлекаются только из одной строки, то следует все равно указать минимум две строки: А1:B10. Это особенность работы с запросами. При попытке указать только одну строку А1:A10 функция вернет значение ошибки. При этом первая строка воспринимается как заголовки. Т.е. данные должны начинаться как минимум со второй строк(A2), а в A1 — заголовок
Хоть эта функция имеет определенные недостатки — она может быть в разы быстрее предыдущей.


Получение данных из закрытой книги при помощи Power Query

Если еще не работали с надстройкой PowerQuery и не знаете что это такое, то для начала лучше ознакомиться со статьей: Power Query — что такое и почему её необходимо использовать в работе?

Переходим на вкладку Данные(для Excel ниже 2016 вкладка PowerQuery) —Получить данныеИз файлаИз книги
Получить данные из книги Excel
Выбираем нужный лист
Выбрать лист
Если необходимы данные всего листа, то внизу этого окна нажимаем кнопку Загрузить. Все, через пару секунд все данные выбранного листа будут помещены на новый лист текущей книги в умную таблицу.

Но если необходимо отобрать только определенные столбцы и строки — тут придется хитрить. Например, нам необходимо получить данные ячеек C2:D20, но в листе у нас заполнены ячейки A1:H89. А зачем нам лишнее? Самое простое, конечно, это диапазон C2:D20 скопировать на отдельный лист и сделать из него умную таблицу. Далее в запросе выбрать именно эту одну таблицу и все. Но. Не всегда есть такая возможность и поэтому рассмотрим более тернистый путь. Итак, мы подключились к книге. И после выбора листа выбираем не Загрузить, а Преобразовать
Преобразовать данные
Попадаем в редактор запросов PowerQuery и видим там данные нашего листа. Чтобы удалить лишние строки нам придется для начала их пронумеровать, т.к. в PowerQuery нет вменяемой нумерации строк по умолчанию.
Идем на вкладку Добавление столбцаСтолбец индексаНастроить
Настроить столбец Индекса
Начальный индекс ставим 2 (2 потому что первая строка листа у нас стала заголовком, значит первая строка в запросе будет равна 2-ой строке на листе Excel и так нам будет проще потом отбирать)
Инкремент — 1 (это шаг, нам нужно просто пронумеровать строки)
Настроить столбец Индекса
Теперь раскрываем фильтр на добавленном столбце индекса —Числовые фильтры —Между
Фильтр между
Указываем «больше или равно» — 2, «меньше или равно» — 20 (это строки нужного нам диапазона C2:D20).
Условия фильтра
После нажатия Ок останутся только нужные нам строки. А удалить столбцы проще простого: выделяем нужные нам 3-й и 4-ый столбцы(это как C и D на листе Excel, только номерами) -правая кнопка мыши —Удалить другие столбцы.
Удалить другие столбцы
Вуаля!
Осталось выгрузить в нашу книгу: идем на вкладку ГлавнаяЗакрыть и загрузить.
В дальнейшем надо будет просто выделить любую ячейку этой полученной из PowerQuery умной таблицы правой кнопкой мыши и нажать обновить.
Правда, есть нюанс: если вдруг заголовки у нашего файла поменяются — то мы получим ошибку на шаге удаления столбцов. Это происходит потому, что PowerQuery использует абсолютные имена столбцов в запросах. Но это решаемо. Идем на вкладку ГлавнаяРасширенный редактор:
Расширенный редактор
Находим там строку:
#»Removed Other Columns» = Table.SelectColumns(#»Filtered Rows»,{«Товар», «Группа»})
Это и есть наша строка удаления всех столбцов, кроме указанных в фигурных скобках({«Товар», «Группа»}). Как видим, там жестко прописаны имена столбцов и нам надо как-то обратиться к ним через номера, чтобы не привязываться к их именами. Для этого перед этой строкой добавляем еще одну:
ColNames = Table.ColumnNames(#»Filtered Rows»),
этой строкой мы получаем список всех имен столбцов и запоминаем в список ColNames. А далее мы используем этот список для указания нужных номеров:
#»Removed Other Columns» = Table.SelectColumns(#»Filtered Rows»,{ColNames{2}, ColNames{3}})
Только необходимо обращать внимание, что здесь индексация идет с 0. Т.е. если нам нужным были столбцы С(3) и D(4), то мы указываем на 1 меньше: 2 и 3. Если столбцов будет больше — перечисляем через запятые все, которые надо оставить. Зато теперь наш запрос не зависит ни от чего и мы в итоге получаем именно то, что хотим.
И маленькая ложка дегтя: PowerQuery не очень дружелюбен к форматам файлов .xls и .xlsb. Поэтому если нет сильной необходимости использовать именно эти форматы в качестве книг, из которых надо получить данные — лучше их и не использовать.


Статья помогла? Поделись ссылкой с друзьями!

  Плейлист   Видеоуроки


Поиск по меткам



Access
apple watch
Multex
Power Query и Power BI
VBA управление кодами
Бесплатные надстройки
Дата и время
Записки
ИП
Надстройки
Печать
Политика Конфиденциальности
Почта
Программы
Работа с приложениями
Разработка приложений
Росстат
Тренинги и вебинары
Финансовые
Форматирование
Функции Excel
акции MulTEx
ссылки
статистика

Пара цитат:  

  ============================================================­==  

<EM>http://www.programmersforum.ru/showthread.php?s=97d4dcfd4e4aaa13a2146730fef9a4db&t=191322</EM>  

  В VBA не существует метода получения значения из закрытого файла рабочей  
книги. Однако вы можете воспользоваться возможностью управления ссылками на  
файлы, которая предоставляется в Excel. В настоящем разделе описана функция VBA  
(GetValue, показанная ниже), которая получает значение из закрытой книги.  
Эта задача выполняется в результате вызова макроса XLM.  
Код 1  

  Private Function GetValue(path, file, sheet, ref)  
Dim arg As String  
If Right(path, 1) <> «» Then path = path & «»  
If Dir(path & file) = «» Then  
GetValue = «Файл не найден»  
Exit Function  
End If  
arg = «‘» & path & «[» & file & «]» & sheet & «‘!» & _
Range(ref).Range(«A1»).Address(, , xlR1C1)  
GetValue = ExecuteExcel4Macro(arg)  
End Function  

  Функция GetValue имеет четыре аргумента:  
¦ path – путь к закрытому файлу (например, «d:files»);  
¦ file – название рабочей книги (например, «budget.xls»);  
¦ sheet – название рабочего листа (например, «Лист1»);  
¦ ref – ссылка на ячейку (например, «C4»).  
Следующая процедура демонстрирует, как используется функция GetValue.  
В этой процедуре отображается значение ячейки А1 листа Лист1 файла 99Budget.xls  
(папка XLFilesBudget на диске c:.  
Код 1  
Sub TestGetValue()  
p = «c:XLFilesBudget»  
f = «99Budget.xls»  
s = «Лист1»  
a = «A1»  
MsgBox GetValue(p, f, s, a)  
End Sub  

  Ниже приведен еще один пример. Эта процедура считывает 1200 значений  
(100 строк и 12 столбцов) из закрытого файла и помещает эти значения на активный  
рабочий лист.  
Код 1  

  Sub TestGetValue2()  
p = «c:XLFilesBudget»  
f = «99Budget.xls»  
s = «Sheet1»  
Application.ScreenUpdating = False  
For r = 1 To 100  
For c = 1 To 12  
a = Cells(r, c).Address  
Cells(r, c) = GetValue(p, f, s, a)  
Next c  
Next r  
Application.ScreenUpdating = True  
End Sub  

   ============================================================­==  
Вот так можно получить значения из закрытой книги:  

  Dim sFilePath As String, sFileName As String, sSh As String  
Dim sStr As String  
sFilePath = «C:Temp»  
sFileName = «Книга1.xls»  
sSh = «Лист1»  

  With Range(«A1:A100»)  
.Formula = «='» & sFilePath & «[» & sFileName & «]» & sSh & «‘!» & «A1»
.Value = .Value  
End With  

  ‘Вот еще один способ:  
sStr = «‘» & sFilePath & «[» & sFileName & «]» & sSh & «‘!» & Range(«A1»).Address(ReferenceStyle:=xlR1C1)
Range(«A1») = ExecuteExcel4Macro(sStr)  
_______________________

Открытие книги Excel из кода VBA. Проверка существования книги. Создание новой книги, обращение к открытой книге и ее закрытие. Методы Open, Add и Close.

Открытие существующей книги

Существующая книга открывается из кода VBA Excel с помощью метода Open:

Workbooks.Open Filename:=«D:test1.xls»

или

Workbooks.Open («D:test1.xls»)

В кавычках указывается полный путь к открываемому файлу Excel. Если такой файл не существует, произойдет ошибка.

Проверка существования файла

Проверить существование файла можно с помощью функции Dir. Проверка существования книги Excel:

If Dir(«D:test1.xls») = «» Then

    MsgBox «Файл не существует»

Else

    MsgBox «Файл существует»

End If

Или, если файл (книга Excel) существует, можно сразу его открыть:

If Dir(«D:test1.xls») = «» Then

    MsgBox «Файл не существует»

Else

    Workbooks.Open Filename:=«D:test1.xls»

End If

Создание новой книги

Новая рабочая книга Excel создается в VBA с помощью метода Add:

Созданную книгу, если она не будет использоваться как временная, лучше сразу сохранить:

Workbooks.Add

ActiveWorkbook.SaveAs Filename:=«D:test2.xls»

В кавычках указывается полный путь сохраняемого файла Excel, включая присваиваемое имя, в примере — это «test2.xls».

Обращение к открытой книге

Обращение к активной книге:

Обращение к книге с выполняемым кодом:

Обращение к книге по имени:

Workbooks(«test1.xls»)

Workbooks(«test2.xls»)

Обратиться по имени можно только к уже открытой книге, а чтобы из кода VBA Excel книгу открыть, необходимо указать полный путь к файлу.

Открытая рабочая книга закрывается из кода VBA Excel с помощью метода Close:

Workbooks(«test1.xlsx»).Close

Если закрываемая книга редактировалась, а внесенные изменения не были сохранены, тогда при ее закрытии Excel отобразит диалоговое окно с вопросом: Вы хотите сохранить изменения в файле test1.xlsx? Чтобы файл был закрыт без сохранения изменений и вывода диалогового окна, можно воспользоваться параметром метода Close — SaveChanges:

Workbooks(«test1.xlsx»).Close  SaveChanges:=False

или

Workbooks(«test1.xlsx»).Close  (False)

Закрыть книгу Excel из кода VBA с сохранением внесенных изменений можно также с помощью параметра SaveChanges:

Workbooks(«test1.xlsx»).Close  SaveChanges:=True

или

Workbooks(«test1.xlsx»).Close (True)


Фразы для контекстного поиска: открыть книгу, открытие книги, создать книгу, создание книги, закрыть книгу, закрытие книги, открыть файл Excel, открытие файла Excel, существование книги, обратиться к открытой книге.


Функция GetValue предназначена для получения данных из закрытой книги Excel

Использовать такой способ имеет смысл только в том случае, если из большого файла надо получить значения только нескольких ячеек (или одного диапазона ячеек), и при этом точно известно расположение на листе интересующих нас ячеек, и имена листов

Пример использования функции:

Sub ПримерИспользования_GetValue()
    p = "C:Documents and SettingsБухгалтерия" ' папка с файлом
    f = "расход.xls" ' имя файла
    s = "доходы" ' название листа
    a = "D145" ' интересующая нас ячейка
    
    ' выполняем загрузку данных из закрытой книги Excel
    ЗначениеЯчейки = GetValue(p, f, s, a)
 
    Debug.Print ЗначениеЯчейки ' выводим результат в окно Immediate
End Sub

Код функции GetValue:

Function GetValue(path, file, sheet, ref)
    'Функция GetValue получает в качестве параметров:
    ' path – путь к закрытому файлу (например, "d:files");
    ' file – название рабочей книги (например, "budget.xls");
    ' sheet – название рабочего листа (например, "Лист1");
    ' ref – ссылка на ячейку (например, "C4").
    
    If Right(path, 1) <> "" Then path = path & ""
 
    ' проверяем наличие файла по заданному пути
    If Dir(path & file) = "" Then GetValue = "Файл не найден": Exit Function
 
    ' формируем строку запроса
    arg$ = "'" & path & "[" & file & "]" & sheet & "'!" & _
           Range(ref).Range("A1").Address(, , xlR1C1)
 
    ' считываем значение из закрытой книги
    GetValue = ExecuteExcel4Macro(arg$)
 
    ' вместо ошибки возвращаем сообщение об ошибке
    ' к примеру, если лист не найден, или указана несуществующая ячейка
    If IsError(GetValue) Then GetValue = "<ошибка>"
End Function

Ещё один вариант этой функции:

Function GetValue(ByVal filepath$, ByVal SheetName$, ByVal CellAddress$)
    'Функция GetValue получает в качестве параметров:
    ' filepath$ = полный путь к файлу Excel (например, "d:filesbudget.xls");
    ' SheetName$ – название рабочего листа (например, "Лист1");
    ' CellAddress$ – ссылка на ячейку (например, "C4").
    
    On Error Resume Next
    ' проверяем наличие файла по заданному пути
    If Dir(filepath$) = "" Then GetValue = "Файл не найден": Exit Function
 
    Dim arr
    arr = Split(filepath$, "")
    arr(UBound(arr)) = "[" & arr(UBound(arr)) & "]"
    filepath$ = Join(arr, "")
 
    ' формируем строку запроса
    arg$ = "'" & filepath$ & SheetName$ & "'!" & Range(CellAddress$).Range("A1").Address(, , xlR1C1)
 
    ' считываем значение из закрытой книги
    GetValue = ExecuteExcel4Macro(arg$)
 
    ' вместо ошибки возвращаем сообщение об ошибке
    ' к примеру, если лист не найден, или указана несуществующая ячейка
    If IsError(GetValue) Then GetValue = "<ошибка>"
End Function

Genyaa

Ей богу не понимаю смысла подобных ограничений, ну да ладно.

Я пошел чудовищным путем но все же как вариант может кому пригодится: я эту функцию (ExecuteExcel4Macro) запихал во внешнюю dll-библиотеку (с помощью Delphi), потом подключил ее к Ехелю и все заработало. Правда пришлось помучаться с типами переменных, я сам не ахти какой программист но такое ощущение что у Delphi и Excel(VBA) совпадают только Integer и Double. Например при попытке вернуть из библиотеки (созданной в Delphi) значение типа String, Excel без объяснения причин вырубается.

KL

Использовать SUB конечно можно, но:

Попытаюсь вкратце обрисовать суть задачи:

Есть некоторое (неопределенное) количество файлов-источников Excel с абсолютно одинаковой структурой, есть один результирующий файл-приемник с такой-же структурой, но файлы источники содержат в себе сложные теплотехнические расчеты (например за разные периоды), а значения результирующего файла должны собираться (суммированием, среднеарифметическим, средневзвешенным, и т.п.).

Причем подразумевается постояное развитие и видоизменение расчетов.

Какова была моя мысль:

Исходные данные для расчета значения конкретной ячейки — массив адресов исходных файлов, принцип накопления (суммированием, среднеарифметическим, средневзвешенным, и т.п.), ссылка на параметр взвешивания.

Макрос — ФУНКЦИЯ вычисляет собственное местоположение (адрес ячейки) опрашивает ячейки файлов-источников с таким же адресом, рассчитывает их и возвращает нужное значение в ячейку результирующего файла.

Таким образом я могу быстро сформировать сам результирующий файл (банальным протягиванием), легко менять файлы-источники (и их количество), и главное — это может сделать любой пользователь независимо от знаний VBA.

Примечание: Сводные таблицы не подходят в принципе из-за неопределенности источников и относительно сложных алгоритмов определения результирующего значения.

Если существует какое-либо другое направление при решении этой задачи — буду очень признателен.

P.S. Прошу прошения если не смог доступно объяснить.

Понравилась статья? Поделить с друзьями:
  • Excel vba обратиться к ячейке умной таблицы
  • Excel vba обратиться к форме
  • Excel vba метод add
  • Excel vba обратиться к книге по имени
  • Excel vba меню на форме