Обратиться к закрытой книге excel

Хитрости »

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


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

Достаточно часто появляется вопрос: как извлечь данные из закрытой книги 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
ссылки
статистика

Открытие книги 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, существование книги, обратиться к открытой книге.


 

woodbox

Пользователь

Сообщений: 11
Регистрация: 08.02.2013

Товарищи, есть вопросик.
Каким образом сделать работающую ссылку на ячейку в книге которая закрыта?
Ссылка формируется через ДВССЫЛ(СЦЕПИТЬ(…
Спасибо заранее!

Прикрепленные файлы

  • Пример.xls (14.5 КБ)

Изменено: woodbox13.02.2013 19:22:09

 

The_Prist

Пользователь

Сообщений: 14182
Регистрация: 15.09.2012

Профессиональная разработка приложений для MS Office

Через ДВССЫЛ никак.
Делайте ссылку обычными ссылками. Либо через VBA. Иначе никак.

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

в конце статьи есть функция для получения данных из закрытой книги.

Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы…

 

Nic70y

Пользователь

Сообщений: 3289
Регистрация: 22.12.2012

Win7 MSO 2013

:D

 

woodbox

Пользователь

Сообщений: 11
Регистрация: 08.02.2013

Огромное спасибо, но есть один момент) данные появляются только в 1-й ячейке диапазона.
Если в каждую ячейку зайти и нажать Enter то данные появляются.
Посему вопрос, как отправить Enter сразу диапазону ячеек?

 

woodbox

Пользователь

Сообщений: 11
Регистрация: 08.02.2013

#5

14.02.2013 17:25:10

Нашел пользовательскую функцию типа

Код
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
    'Возвращаем данные в ячейку с функцией
    If IsArray(vData) Then
        Get_Value_From_Close_Book = vData
    Else
        Get_Value_From_Close_Book = vData
    End If
End F unction

Но при выполнении в файле невозможно нормально выделить ни одной ячейки( видимо переходит в какой то режим. Подскажите пожалуйста как исправить эту функцию.

 

The_Prist

Пользователь

Сообщений: 14182
Регистрация: 15.09.2012

Профессиональная разработка приложений для MS Office

«Нашел» сильно сказано. Скорее сходили по моей ссылке и оттуда взяли, т.к. в своем сообщении я точную карту обрисовал, как найти.
Исправить никак нельзя. Либо Вы получаете данные из закрытой книги, либо ничего у Вас не тормозит. Одно из двух.

Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы…

 

woodbox

Пользователь

Сообщений: 11
Регистрация: 08.02.2013

Дело не в том что тормозит) а в том что режим выделения становится каким то другим, т.е. ячейку нельзя выделить как обычно. Функция отрабатывает очень быстро, спасибо Вам за наводку на нее) но тут думаю дело может быть в чем то другом, может excel не возвращается в привычный режим после отработки функции. Не могу понять в чем дело

 

Максим

Пользователь

Сообщений: 268
Регистрация: 31.12.2012

подскажите пожалуйста почему указанная выше пользовательская функция скрыто открывает книгу с данными, но не закрывает её потом?

 

ikki

Пользователь

Сообщений: 9709
Регистрация: 22.12.2012

удалил сообщение

Изменено: ikki03.08.2014 07:26:13

фрилансер Excel, VBA — контакты в профиле
«Совершенствоваться не обязательно. Выживание — дело добровольное.» Э.Деминг

 

Максим

Пользователь

Сообщений: 268
Регистрация: 31.12.2012

У меня задача схожая с задачей

woodbox

-а. А именно

функцией листа

получать значение конкретной ячейки из закрытой книги. Должна быть возможность автоматически, по условию изменять путь к файлу. Изучив вышенаписанное удалось получить функцию, которая возвращает путь к ячейке. Возможно ли преобразовать полученный путь в его значение? (только в рамках функции листа, а не макросом)
Можно делать руками — копируем ячейку с результатом вычисления функции, специальная вставка вставить значение, F2, ENTER, но это совсем не то что хотелось бы!
Подскажите пожалуйста существует ли способ заставить функцию возвращать значение, а не путь.

спасибо.

 

Максим

Пользователь

Сообщений: 268
Регистрация: 31.12.2012

#11

04.08.2014 01:08:34

и вот ещё. Есть способ решить задачу с помощью ADO. Макрос, который это делает я нашёл, но переделать его пользовательскую функцию не могу.

Код
Function извлечение(path, file, sheet, ref)
Set cn = CreateObject("ADODB.Connection")
path = ThisWorkbook.path & "" & path
If Right(path, 1) <> "" Then path = path & ""
t = path & file
cn.Open "Provider='Microsoft.Jet.OLEDB.4.0';Data Source='" & t & "';Extended Properties='Excel 8.0;HDR=No;IMEX=1';"
Set rs1 = cn.Execute("select * from [" & sheet & ref & ":" & ref & "]") 

дальше в макросе было так:

Код
Cells(5, 5).CopyFromRecordset rs1

как это правильно написать в функции я не знаю.

Код
End Function

вообще возможно такое сделать в функции листа?

спасибо!

Изменено: Максим04.08.2014 01:24:27
(оформил код тегом)

 

Юрий М

Модератор

Сообщений: 60585
Регистрация: 14.09.2012

Контакты см. в профиле

Максим, код следует оформлять тегом. Привыкайте.

 

B.Key

Пользователь

Сообщений: 633
Регистрация: 26.02.2014

#13

04.08.2014 01:34:35

Cells(5, 5).CopyFromRecordset rs1

Код
извлечение=rs1.fields(0).value

хотя это полное извращение дергать ADO recordset, и использовать его как функцию
Хотя разовые применения вполне допустимы.

 

Максим

Пользователь

Сообщений: 268
Регистрация: 31.12.2012

ооуеее!

B.Key

спасибо вам! наконец-то у меня хоть что-то заработало! :)

да, везде на форумах пишут что применение ADO для извлечения данных из закрытой книги это вроде как изврат, но ничего другого, применимого к функции листа, я не нашёл

 

B.Key

Пользователь

Сообщений: 633
Регистрация: 26.02.2014

Это не изврат, а вполне нормальное решение и довольно скоростное. Просто использовать его его надо с умом :))

 

Максим Зеленский

Пользователь

Сообщений: 4646
Регистрация: 11.06.2014

Microsoft MVP

#16

04.08.2014 01:47:24

Цитата
B.Key пишет: хотя это полное извращение
Цитата
B.Key пишет: Это не изврат, а вполне нормальное решение

я так и не понял…   :D

F1 творит чудеса

 

B.Key

Пользователь

Сообщений: 633
Регистрация: 26.02.2014

#17

04.08.2014 10:18:14

Получение значения одной ячейки с помощью ADO это изврат, а использовать ADO для других целей (не буду уточнять) вполне хорошее решение.

Скрытый текст

 

The_Prist

Пользователь

Сообщений: 14182
Регистрация: 15.09.2012

Профессиональная разработка приложений для MS Office

#18

04.08.2014 11:09:50

Цитата
Максим пишет:
почему указанная выше пользовательская функция скрыто открывает книгу с данными, но не закрывает её потом

Функция закрывает книгу 100%. За это отвечает строка:

Код
objCloseBook.Close False

Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы…

 

ikki

Пользователь

Сообщений: 9709
Регистрация: 22.12.2012

Дима, в моём сообщении #9 об этом и говорилось.
просто на основе кода.
потом я его проверил.
для файлов *.xls, открываемых из Excel 2010 это почему-то не так.
файла нет в списке открытых, тем не менее при повторном пересчете функции или при ручном открытии файла Excel действительно почему-то выдает сообщение о том, что файл уже открыт.
поэтому я и откорректировал своё сообщение.

причина мне непонятна.
возможно — режим совместимости для файлов *.xls, возможно — какие-то особенности GetObject
думаю, GetObject имеет смысл заменить на Workbooks.Open

Изменено: ikki04.08.2014 11:37:30

фрилансер Excel, VBA — контакты в профиле
«Совершенствоваться не обязательно. Выживание — дело добровольное.» Э.Деминг

 

The_Prist

Пользователь

Сообщений: 14182
Регистрация: 15.09.2012

Профессиональная разработка приложений для MS Office

#20

04.08.2014 11:38:18

Что-то мне подсказывает, что эта строка:

Код
Set rs1 = cn.Execute("select * from [" & sheet & ref & ":" & ref & "]")

выбьет в ошибку. Символа одного не хватает:

Код
Set rs1 = cn.Execute("select * from [" & sheet & "$" & ref & ":" & ref & "]")

Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы…

 

Максим

Пользователь

Сообщений: 268
Регистрация: 31.12.2012

я решил что «$», как указатель «абсолютности» тут ни к чему и убрал его. Возможно я ошибаюсь и этот символ тут для другого было нужен, но без него работает.

тут я ошибался. $ нужен

Изменено: Максим04.08.2014 16:09:31
(исправил и убрал не корректный пример )

 

The_Prist

Пользователь

Сообщений: 14182
Регистрация: 15.09.2012

Профессиональная разработка приложений для MS Office

#22

04.08.2014 15:12:50

Я может чего не так понял, но в приложенном файле строка выглядит так:

Код
Set rs1 = cn.Execute("select * from [Лист1$a1:a1]")

т.е. знак $ присутствует. Попробуйте теперь его из этой строки убрать и заново пересчитать функцию.

Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы…

 

Максим

Пользователь

Сообщений: 268
Регистрация: 31.12.2012

#23

04.08.2014 16:06:20

ой! и правда. прошу прощения. я был уверен что у меня эта строка в функции «закомменчена». Действительно, Ваша правда — без $ не работает. спасибо за подсказку!

Прикрепленные файлы

  • ссылка на закрытую книгу.rar (17.67 КБ)

Как сослаться или связать значение в закрытом / закрытом файле книги Excel?

Обычно, когда вы ссылаетесь на значение ячейки из другой книги, вам нужно сначала открыть книгу. Как насчет прямой ссылки на значение ячейки из закрытой книги? В этой статье будут показаны методы ссылки на значение ячейки из определенного листа неоткрытого файла книги.

Контрольное значение из закрытого / закрытого файла Excel с формулой
Вставьте все данные определенного рабочего листа из неоткрытого/закрытого файла Excel с помощью Kutools for Excel


Контрольное значение из закрытого / закрытого файла Excel с формулой

Предположим, что ваша закрытая книга с именем test находится по пути E: Excel file на вашем компьютере, и вы хотите ссылаться на значение ячейки A2 из Sheet2 этой закрытой книги. Пожалуйста, сделайте следующее.

1. Выберите пустую ячейку, чтобы разместить значение ячейки, на которую указывает ссылка, введите формулу в панель формул и нажмите кнопку Enter ключ. Смотрите скриншот:

=INDEX(‘E:Excel file[test.xlsx]Sheet2’!A:A,2,1)

Заметки:

1). В формуле E: файл Excel — это полный путь к неоткрытой книге, тест.xlsx — это имя книги, Sheet2 — это имя листа, которое содержит значение ячейки, из которой вам нужно ссылаться, а A: A, 2,1 означает, что ячейка A2 будет указана в закрытой книге. Вы можете изменить их в зависимости от ваших потребностей.

2). Если вы хотите вручную выбрать лист для ссылки, примените формулу ниже. После применения формулы a Выбрать лист появится диалоговое окно, выберите рабочий лист и нажмите кнопку ОК. Тогда сразу же будет ссылка на определенное значение ячейки этого рабочего листа.

=INDEX(‘E:Excel file[test.xlsx]sheetname’!A:A,2,1)


Вставьте все данные определенного рабочего листа из неоткрытого/закрытого файла Excel с помощью Kutools for Excel

Если вы хотите вставить все содержимое листа из закрытого файла Excel, здесь я рекомендую вам Вставить файл в курсор полезности Kutools for Excel. Чтобы это сделать, выполните следующие действия.

1. Выберите пустую ячейку, с которой должен начинаться указанный рабочий лист, затем щелкните Кутулс Плюс > Импорт Экспорт > Вставить файл в курсор

2. в Вставить файл в курсор диалогового окна, нажмите Приложения кнопку.

3. в Выберите файл для вставки в позицию курсора ячейки диалоговом окне найдите и выберите закрытую книгу, на которую хотите сослаться, а затем нажмите Откройте кнопка. Смотрите скриншот:

4. Теперь он возвращается к вставке. Файл в курсоре диалоговом окне вы можете выбрать любой из Только значение (без формул) и Не передавать форматирование нужные вам параметры, а затем щелкните OK кнопка. В следующем всплывающем окне Выберите рабочий лист диалоговом окне, укажите рабочий лист и щелкните значок OK кнопка. Смотрите скриншот:

Теперь все содержимое выбранного рабочего листа указанной неоткрытой книги ссылается на текущий рабочий лист.

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

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


Статьи по теме:

  • Как ссылаться на формат и значение из другой ячейки в Excel?
  • Как ссылаться на рабочий лист по номеру индекса вместо имени в Excel?
  • Как удалить все ссылки на формулы, но сохранить значения в ячейках в Excel?
  • Как сохранить постоянную ссылку на ячейку формулы в Excel?
  • Как указать имя вкладки в ячейке в Excel?

Лучшие инструменты для работы в офисе

Kutools for Excel Решит большинство ваших проблем и повысит вашу производительность на 80%

  • Снова использовать: Быстро вставить сложные формулы, диаграммы и все, что вы использовали раньше; Зашифровать ячейки с паролем; Создать список рассылки и отправлять электронные письма …
  • Бар Супер Формулы (легко редактировать несколько строк текста и формул); Макет для чтения (легко читать и редактировать большое количество ячеек); Вставить в отфильтрованный диапазон
  • Объединить ячейки / строки / столбцы без потери данных; Разделить содержимое ячеек; Объединить повторяющиеся строки / столбцы… Предотвращение дублирования ячеек; Сравнить диапазоны
  • Выберите Дубликат или Уникальный Ряды; Выбрать пустые строки (все ячейки пустые); Супер находка и нечеткая находка во многих рабочих тетрадях; Случайный выбор …
  • Точная копия Несколько ячеек без изменения ссылки на формулу; Автоматическое создание ссылок на несколько листов; Вставить пули, Флажки и многое другое …
  • Извлечь текст, Добавить текст, Удалить по позиции, Удалить пробел; Создание и печать промежуточных итогов по страницам; Преобразование содержимого ячеек в комментарии
  • Суперфильтр (сохранять и применять схемы фильтров к другим листам); Расширенная сортировка по месяцам / неделям / дням, периодичности и др .; Специальный фильтр жирным, курсивом …
  • Комбинируйте книги и рабочие листы; Объединить таблицы на основе ключевых столбцов; Разделить данные на несколько листов; Пакетное преобразование xls, xlsx и PDF
  • Более 300 мощных функций. Поддерживает Office/Excel 2007-2021 и 365. Поддерживает все языки. Простое развертывание на вашем предприятии или в организации. Полнофункциональная 30-дневная бесплатная пробная версия. 60-дневная гарантия возврата денег.

вкладка kte 201905


Вкладка Office: интерфейс с вкладками в Office и упрощение работы

  • Включение редактирования и чтения с вкладками в Word, Excel, PowerPoint, Издатель, доступ, Visio и проект.
  • Открывайте и создавайте несколько документов на новых вкладках одного окна, а не в новых окнах.
  • Повышает вашу продуктивность на 50% и сокращает количество щелчков мышью на сотни каждый день!

офисный дно

Fedogor, так вряд ли получится, потому что здесь еще есть предыстория.

Есть папка. В ней много подпапок. Во всех этих подпапках лежат .xls файлы одного шаблона. И эти файлы добавляются, точно так же, как и папки. И когда-то на этом форуме один очень добрый человек помог мне написать макрос, который находит все эти файлы.

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

Суть в том, чтоб из многих файлов, которые добавляются и обновляются, создать небольшую базу данных. К примеру, в каждом таком файле в одной определённой ячейке есть имя клиента, во второй количество купленного товара и в третьей цена товара. И эти данные из файлов по разным клиентам нужно свести в одну табличку в отдельной книге.

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

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
Dim N_com%, Folders_Com() As String
 
Sub Quest()
    Dim i%
    Const Folder$ = "X:Test"
    N_com = 0
    Call Subfolders2_in(Folder)
    For i = 1 To N_com
    Filename = Dir(Folders_Com(i) & "*.xls")
    Do While Filename <> ""
    Range("A1").End(xlDown).Offset(1, 0).Value = Folders_Com(i) & Filename
    Filename = Dir
   Loop
Next i
End Sub
 
Sub Subfolders2_in(Folder$)
    Dim Folders() As String
    Dim N%, i%
    Dim fs, f, f1, fc, s
    
    Set fs = CreateObject("Scripting.FileSystemObject")
    Set f = fs.GetFolder(Folder)
    Set fc = f.SubFolders
    
    N = 0
    On Error Resume Next
    For Each f1 In fc
      N = N + 1
      ReDim Preserve Folders(1 To N) As String
      Folders(N) = Folder & "" & f1.Name & ""
      
      N_com = N_com + 1
      ReDim Preserve Folders_Com(1 To N_com) As String
      Folders_Com(N_com) = Folders(N)
   Next f1
      If N = 0 Then Exit Sub
End Sub

Понравилась статья? Поделить с друзьями:
  • Обратить строку в excel
  • Обратится к листу excel vba
  • Обрамления для документов word
  • Обрамление ячеек таблицы word
  • Обрамление ячеек в excel это