Открыта или закрыта книга Excel? Проверяем с помощью кода VBA по краткому или полному имени файла, используя объектную переменную, цикл или оператор Open.
Проверка по краткому имени
Способ проверки по краткому имени, открыта ли рабочая книга, позволяет определить состояние проверяемой книги в том же экземпляре приложения Excel, в котором открыта книга с проверяющим кодом.
Использование объектной переменной
Вариант пользовательской функция VBA Excel, предназначенной для проверки, открыта или закрыта рабочая книга, путем определения результата присвоения ссылки на нее объектной переменной. Присвоение состоялось (BookOpenClosed = True) – книга открыта, произошла ошибка и присвоение не состоялось (BookOpenClosed = False) – книга закрыта.
Function BookOpenClosed(wbName As String) As Boolean Dim myBook As Workbook On Error Resume Next Set myBook = Workbooks(wbName) BookOpenClosed = Not myBook Is Nothing End Function |
Аргумент функции:
- wbName – краткое имя проверяемой рабочей книги.
Перебор открытых книг циклом
Этот вариант функции BookOpenClosed перебирает с помощью цикла все открытые книги Excel и проверяет их краткие имена на совпадение с кратким именем проверяемой книги. Совпадение найдено (BookOpenClosed = True) – книга открыта, совпадение не найдено (BookOpenClosed = False) – книга закрыта.
Function BookOpenClosed(wbName As String) As Boolean Dim myBook As Workbook For Each myBook In Workbooks If myBook.Name = wbName Then BookOpenClosed = True Exit For End If Next End Function |
В коллекцию Workbooks входят и скрытые книги, в том числе Личная книга макросов, и книга с функцией.
Проверка по полному имени
Проверка по полному имени с помощью оператора Open позволяет узнать, открыта ли рабочая книга каким-либо другим процессом: текущим экземпляром Excel, в котором открыта книга с проверяющим кодом, другим экземпляром Excel или сторонним приложением.
Function BookOpenClosed(wbFullName As String) As Boolean Dim ff As Integer ff = FreeFile On Error Resume Next Open wbFullName For Random Access Read Write Lock Read Write As #ff Close #ff BookOpenClosed = (Err.Number <> 0) End Function |
Аргумент функции:
- wbFullName – полное имя проверяемой рабочей книги.
Эта функция открывает с помощью оператора Open файл проверяемой книги с разрешением чтения и записи (параметр access) и запретом чтения и записи, если этот файл уже открыт другим процессом (параметр lock).
Если файл уже открыт другим процессом, а указанный тип доступа (параметр access) не разрешен (параметр lock), операция открытия завершится с ошибкой, а выражение (Err.Number <> 0) возвратит значение True.
Примеры проверки состояния книги
По краткому имени
Sub Primer1() If BookOpenClosed(«Книга1.xlsx») Then MsgBox «Книга открыта» Else MsgBox «Книга закрыта» End If End Sub |
По полному имени
Sub Primer2() If BookOpenClosed(«C:Папка1Папка2Папка3Книга1.xlsx») Then MsgBox «Книга открыта» Else MsgBox «Книга закрыта» End If End Sub |
Владимир Пользователь Сообщений: 8196 |
Здравствуйте. «..Сладку ягоду рвали вместе, горьку ягоду я одна.» |
Ёк-Мок Пользователь Сообщений: 1775 |
«on error resume next»? Удивление есть начало познания © Surprise me! |
Казанский Пользователь Сообщений: 8839 |
#3 14.04.2015 10:20:18 1 способ
2 способ
Если книга не открыта, она будет открыта, но в невидимом режиме, и лучше сделать ее видимой. Изменено: Казанский — 14.04.2015 10:23:31 |
||||
Юрий М Модератор Сообщений: 60575 Контакты см. в профиле |
|
Владимир Пользователь Сообщений: 8196 |
#5 14.04.2015 11:06:36 Вроде ошибка исчезла, но теперь копирование на Лист «Шате-М» не происходит.
«..Сладку ягоду рвали вместе, горьку ягоду я одна.» |
|
The_Prist Пользователь Сообщений: 14182 Профессиональная разработка приложений для MS Office |
#6 14.04.2015 11:20:22
Либо Open, либо GetObject Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы… |
||
Владимир Пользователь Сообщений: 8196 |
Спасибо большое. Заработало. «..Сладку ягоду рвали вместе, горьку ягоду я одна.» |
Hugo Пользователь Сообщений: 23251 |
Бывает GetObject() барахлит… Вдруг и неожиданно на файлах, которые (другие оттуда же) ранее открывались без проблем. |
Юрий М Модератор Сообщений: 60575 Контакты см. в профиле |
Тоже с этим сталкивался. Теперь всегда делаю через Workbooks.Open |
Владимир Пользователь Сообщений: 8196 |
Нет, при открытом файле «F:ЛогистикаКнига.XLSM» всё-таки не работает, при закрытом полный порядок. «..Сладку ягоду рвали вместе, горьку ягоду я одна.» |
The_Prist Пользователь Сообщений: 14182 Профессиональная разработка приложений для MS Office |
#11 14.04.2015 12:23:45 Как проверить открыта ли книга?
Берете оттуда функцию IsBookOpen. Далее:
и потом уже к Wb обращаетесь. Все должно работать. Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы… |
||
Андрей VG Пользователь Сообщений: 11878 Excel 2016, 365 |
#12 14.04.2015 13:13:32 Доброе время суток
|
||
Владимир Пользователь Сообщений: 8196 |
#13 14.04.2015 13:37:27 IsBookOpen всё время артачится — ошибку выдаёт, чем только не обзывал — Boolean, Srting, Workbook, Name
Изменено: Владимир — 14.04.2015 13:38:20 «..Сладку ягоду рвали вместе, горьку ягоду я одна.» |
||
Андрей VG Пользователь Сообщений: 11878 Excel 2016, 365 |
#14 14.04.2015 13:49:00 Владимир, немного не так
|
||
RAN Пользователь Сообщений: 7091 |
Никак не пойму, зачем в данном случае огород с IsFileOpen? |
Владимир Пользователь Сообщений: 8196 |
Андрей, теперь на IsFileOpen ругается. Да как же их объявить? «..Сладку ягоду рвали вместе, горьку ягоду я одна.» |
Андрей VG Пользователь Сообщений: 11878 Excel 2016, 365 |
#17 14.04.2015 14:00:17 RAN, А если файл открыт в другом экземпляре Excel?
с моими проверочными данными |
||
Владимир Пользователь Сообщений: 8196 |
Открываю с web_a исходный файл, параллельно открыт файл «Книга.xlsm» куда копируются данные. Запускаю макрос и происходит выделение «IsFileOpen».. «..Сладку ягоду рвали вместе, горьку ягоду я одна.» |
RAN Пользователь Сообщений: 7091 |
#19 14.04.2015 14:20:02
А если на другом компьютере? |
||
Hugo Пользователь Сообщений: 23251 |
Ещё вариант — перебрать все открытые книги и у каждой проверить полный путь (совпадает ли с нужным) — так не спутаете книги, если у них одинаковые названия, но лежат в разных папках (и открыта например ненужная). |
Владимир Пользователь Сообщений: 8196 |
Да это в примере он называется просто Книга, а в реальности — Что пора заказать. Этот файл у меня постоянно открыт, т.к. он является основным рабочим. Поэтому его специально закрывать, чтоб скопировать туда данные будет очень неудобно. «..Сладку ягоду рвали вместе, горьку ягоду я одна.» |
Hugo Пользователь Сообщений: 23251 |
Вообще-то у меня нет никакой ошибки в первоначальном коде (и ранее помню не было ошибок). Проверьте путь. |
RAN Пользователь Сообщений: 7091 |
#23 14.04.2015 14:46:33
Код из #3 как раз именно для этого случая. |
||
Hugo Пользователь Сообщений: 23251 |
Да, там не ошибка выскакивает, а предупреждение, что если есть несохранённые изменения, то они будут потеряны при переоткрытии файла. Если же его только смотрели (или сохранились) — то всё происходит молча. |
Владимир Пользователь Сообщений: 8196 |
А там на строке With Sheets(«Шате-М») спотыкается. «..Сладку ягоду рвали вместе, горьку ягоду я одна.» |
Hugo Пользователь Сообщений: 23251 |
Где там? |
RAN Пользователь Сообщений: 7091 |
#27 14.04.2015 15:00:09
или
) |
||||
Владимир Пользователь Сообщений: 8196 |
Андрей, точно. Вот где собакин порылся. Приставку забыл. Спасибо. Теперь с открытой книгой тоже работает. «..Сладку ягоду рвали вместе, горьку ягоду я одна.» |
Владимир Пользователь Сообщений: 8196 |
#29 19.02.2016 11:49:11 Алексей, спасибо. «..Сладку ягоду рвали вместе, горьку ягоду я одна.» |
Проверка файла на активность при открытии |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
Хитрости »
4 Май 2011 93403 просмотров
Как проверить открыта ли книга?
Собственно суть темы отражена в названии. Как при выполнении кода из VBA узнать перед обращением к книге открыта она или нет? Ведь если книга закрыта, то обращение к ней вызовет ошибку, а если открывать без проверки — то это может повлечь за собой утерю данных, если предварительно эта книга не была сохранена. Ни один ни второй вариант, естественно, не устраивают. Я покажу два способа проверки через функции. Если функция вернет True — книга открыта, если False — закрыта. Для проверки функций используем проверочную процедуру Check_Open_Book:
Sub Check_Open_Book() If IsBookOpen("Книга1.xls") Then MsgBox "Книга открыта", vbInformation, "Сообщение" Else MsgBox "Книга закрыта", vbInformation, "Сообщение" 'открываем книгу Workbooks.Open "C:Книга1.xls" End If End Sub
Данная процедура вызывает функцию IsBookOpen, передавая ей в качестве параметра имя книги, «открытость» которой мы хотим проверить. Я приведу несколько вариантов самой функции IsBookOpen. Во всех вариантах действует один и тот же принцип: код любого из вариантов функции IsBookOpen необходимо скопировать и вставить в стандартный модуль. Модуль должен быть внутри той книги, в кодах которой планируется проверять открыта ли книга. Только тогда IsBookOpen будет доступна для вызова из любого кода этой же книги.
Если вдруг в момент выполнения на строке If IsBookOpen(«Книга1.xls») Then появится ошибка «Sub or function not defined» — значит функция IsBookOpen либо не была скопирована в стандартный модуль, либо она вообще не в стандартном модуле, а в модуле листа, формы или книги.
Вариант 1:
Function IsBookOpen(wbName As String) As Boolean Dim wbBook As Workbook For Each wbBook In Workbooks If wbBook.Name <> ThisWorkbook.Name Then If Windows(wbBook.Name).Visible Then If wbBook.Name = wbName Then IsBookOpen = True: Exit For End If End If Next wbBook End Function
Функция просматривает все открытые книги и если находит среди них книгу с указанным именем, то функция возвращает True. Есть небольшая особенность — функция исключает скрытые книги(это либо надстройки, либо PERSONAL.XLS). Так же из просмотра исключена та книга, в которой расположен сам код. Если Вам нужно проверить наличие книги независимо от её видимости, то необходимо просто заменить блок
If Windows(wbBook.Name).Visible Then If wbBook.Name = wbName Then IsBookOpen = True: Exit For End If
на одну строку(просто убрать лишнее условие проверки)
If wbBook.Name = wbName Then IsBookOpen = True: Exit For
Либо можно использовать
Вариант 2:
Function IsBookOpen(wbName As String) As Boolean Dim wbBook As Workbook: On Error Resume Next Set wbBook = Workbooks(wbName) IsBookOpen = Not wbBook Is Nothing End Function
Данный способ обращается к любой открытой книге, даже если она скрыта как PERSONAL.XLS или надстройка. Однако у данной функции есть недостаток — используется оператор On Error и если в настройках VBA(Tools —Options -вкладка General) установлено Break on All Errors — то этот код не сработает, если книга не открыта — получим ошибку. В то время как Вариант1 с циклом по всем открытым книгам сработает без ошибок.
Вариант 3:
По просьбам читателей решил добавить код, который проверяет открыта ли книга независимо от её месторасположения и используемого приложения Excel. Книга может быть открыта другим пользователем (если книга на сервере), в другом экземпляре Excel или в этом же экземпляре Excel.
Function IsBookOpen(wbFullName As String) As Boolean Dim iFF As Integer, retval As Boolean iFF = FreeFile On Error Resume Next Open wbFullName For Random Access Read Write Lock Read Write As #iFF retval = (Err.Number <> 0) Close #iFF IsBookOpen = retval End Function
Функция несколько отличается от приведенных выше — передается в неё не только имя книги, а полный путь к книге, включая имя и расширение:
Sub Test() MsgBox "Файл 'Книга1'" & IIf(IsBookOpen("C:Книга1.xls"), " уже открыт", " не занят") End Sub
Или более близкий к жизненной ситуации вариант: надо открыть книгу, внести в книгу изменения, сохранить и закрыть. Если книга кем-то уже открыта — получим ошибку на этапе сохранения или запрос на этапе открытия. Поэтому сначала проверяем доступность книги и если она доступна — вносим изменения и сохраняем.
Sub Test() Dim sWBFullName As String Dim wb As Workbook 'полный путь к проверяемой книге sWBFullName = "C:DocumentsКнига1.xls" 'если книга кем-то открыта - пропускаем обработку этой книги 'книга закрыта - вносим изменения, сохраняем, закрываем If IsBookOpen(sWBFullName) = False Then Set wb = Application.Workbooks.Open(sWBFullName) 'изменяем значение ячейки "A1" на первом листе книги wb.Sheets(1).Range("A1").Value = "www.excel-vba.ru" ws.Close True End If End Sub
При использовании функции IsBookOpen так же надо учитывать, что она может посчитать книгу открытой не только если она реально кем-то открыта, а если к ней просто нет доступа(например, заблокирован доступ со стороны администратора и т.п.).
Также см.:
Как получить данные из закрытой книги?
Как узнать существует ли лист в книге?
Как узнать существует ли модуль в книге
Статья помогла? Поделись ссылкой с друзьями!
Видеоуроки
Поиск по меткам
Access
apple watch
Multex
Power Query и Power BI
VBA управление кодами
Бесплатные надстройки
Дата и время
Записки
ИП
Надстройки
Печать
Политика Конфиденциальности
Почта
Программы
Работа с приложениями
Разработка приложений
Росстат
Тренинги и вебинары
Финансовые
Форматирование
Функции Excel
акции MulTEx
ссылки
статистика
Имеется макрос, который получает значения из закрытой книги (формально он ее открывает, используя Workbooks.open()
, отключает ивенты/алерты Application.ScreenUpdating = False, Application.DisplayAlerts = False, Application.EnableEvents = False
, считывает то, что нужно, и книгу закрывает).
Книга находится на сервере, поэтому с ней могут работать другие пользователи. При выполнении моего макроса все экземпляры книги, открытые другими пользователями, закрываются. Я поставила проверку, чтобы книга не закрывалась, если была открыта до выполнения макроса, но это все равно не работает — книга закрывается, а затем открывается в Read-only режиме, изменения соответственно не сохраняются, если какой-то пользователь их вносил.
Вопрос в следующем — можно ли как-то заставить макрос открыть второй экземпляр этой книги, считать необходимые данные и закрыть его, чтобы никак не трогать экземпляры, открытые до этого?
I am trying to read data from another spreadsheet in the same folder as my currently opened workbook, whenever I run this code I get the error file already open. Is there something wrong with my syntax or anything that might stop this from happening?
Here is the code.
Sub ReadFile()
Infile = ThisWorkbook.Path & "smallDataset.csv"
Open Infile For Input As #1
Input #1, a, b
Close #1
Debug.Print (a & " " & b)
End Sub
Thanks.
asked Dec 27, 2017 at 0:48
3
Try the following code to make sure there is no file open with handle #1
Sub ReadFile()
InFile = ThisWorkbook.Path & "smallDataset.csv"
Close #1
Open InFile For Input As #1
Input #1, a, b
Close #1
Debug.Print (a & " " & b)
End Sub
Or you use Freefile to get the next number
Sub ReadFile
FileNumber = FreeFile
InFile = ThisWorkbook.Path & "smallDataset.csv"
Open InFile For Input As FileNumber
Input #FileNumber, a, b
Close #FileNumber
Debug.Print (a & " " & b)
End Sub
answered Dec 27, 2017 at 8:54
StoraxStorax
10.8k3 gold badges15 silver badges33 bronze badges
I am also experiencing the errors which you have, these are the probable causes of the said error.
1) The CSV
is open along with the Excel
file
2) Your code has memory leaks
To resolve number 1
- Try running the VBA code when the CSV is not opened
To resolve number 2
- Try to use close the
CSV
object after you have written your data inside it.
I’m not sure about your full code, but please check if you have something like Excel.Close
or Excel.Quit
.
answered Dec 27, 2017 at 1:54
Mr.JMr.J
4101 gold badge11 silver badges30 bronze badges
На чтение 3 мин. Просмотров 4.3k.
Что делает макрос: При автоматическом открытии книги, необходимо учитывать, что может произойти при попытке открытия книги, которая уже открыта. Обычно Excel пытается открыть файл еще раз, с предупреждением, что любые несохраненные изменения будут потеряны. В VBA есть хороший инструмент, которые знает, как определить открыта ли книга, прежде чем пытаться открыть его снова.
Содержание
- Как макрос работает
- Код макроса
- Как работает этот код
- Код макроса
- Как использовать
Как макрос работает
Первое, что надо заметить, что это функция, а не процедура Sub. Мы проверяем файл, чтобы увидеть, назначен ли он переменной объекта. Только открытые книги могут быть присвоены переменной объекта. Когда мы пытаемся назначить закрытую книгу для переменной, возникает ошибка. Так что, если данная книга может быть назначена, книга открыта, если возникает ошибка, книга закрыта.
Код макроса
Function FileIsOpenTest(TargetWorkbook As String) As Boolean 'Шаг 1: Объявить переменные Dim TestBook As Workbook 'Шаг 2: проверка на ошибки On Error Resume Next 'Шаг 3: Попробуйте проверить книгу Set TestBook = Workbooks(TargetWorkbook) 'Шаг 4: Если ошибки не произошло, книга уже открыта If Err.Number = 0 Then FileIsOpenTest = True Else FileIsOpenTest = False End If End Function
Как работает этот код
- Первое, что макрос делает – указывает переменную строку, содержащую имя файла, который выбирает пользователь. TestBook это имя переменной строки.
- В шаге 2, мы проверяем Excel на ошибки. В случае ошибки, возобновить код. Без этой строки код остановится при возникновении ошибки. Опять же, мы проводим тестирование данного файла, чтобы увидеть, назначен ли он переменной объекта. Поэтому, если данная книга может быть назначена, она открыта, если возникает ошибка, она закрыта. Если возникла ошибка, нам нужно знать код.
- На шаге 3, присваиваем книге переменную объекта TestBook. Сама строка переменной называется TargetWorkbook. TargetWorkbook передает функции в объявлении функции (см. первую строку кода). Данная функция устраняет необходимость жесткого кодирования имени книги, что позволяет нам передать его в качестве переменной.
- На шаге 4, проверяем, произошла ли ошибка. Если ошибки не произошло, книга открыта, поэтому мы устанавливаем FileIsOpenTest в True. Если произошла ошибка, это означает, что книга не открыта. В этом случае мы устанавливаем FileIsOpenTest значение false.
Это функция может быть использована для оценки любого файла, который передаст к нему, через его TargetWorkbook аргумент. Мы будем использовать затем эту функцию в макросе. Следующий макрос показывает, как реализовать эту функцию. Здесь мы используем одни и те же макросы, которые вы видели в предыдущем разделе, «Как открыть конкретную книгу, определенную пользователем», но на этот раз, мы создаем новую функцию FileIsOpenTest, чтобы убедиться, что пользователь не может открыть уже открытый файл.
Код макроса
Sub MacroOtkritaLiKniga() 'Шаг 1: Определить переменную строки. Dim FName As Variant Dim FNFileOnly As String 'Шаг 2: Метод GetOpenFilename активизирует диалоговое окно. FName = Application.GetOpenFilename( _ FileFilter:="Excel Workbooks,*.xl*", _ Title:="Выберите книгу, которую нужно открыть", _ MultiSelect:=False) 'Шаг 3: Откройте файл, если он еще не открыт. If FName <> False Then FNFileOnly = StrReverse(Left(StrReverse(FName), _ InStr(StrReverse(FName), "") - 1)) If FileIsOpenTest(FNFileOnly) = True Then MsgBox "Данный файл уже открыт" Else Workbooks.Open Filename:=FName End If End If End Sub
Как использовать
Чтобы реализовать этот макрос, вы можете скопировать и вставить в обе части кода в стандартном модуле:
- Активировать визуальный элемент базовый редактор, нажав клавиши Alt+F11 на клавиатуре.
- Щелкните правой кнопкой мыши имя проекта или рабочей книги в окне проекта.
- Выбрать Вставку Модуля➜.
- Введите или вставьте код в созданный модуль.
- При необходимости можно назначить макрос для кнопки
Привет!
Вот столкнулся с проблемой (для меня очень серьезной):
Есть программа, которая хранит свои данные в файле xls. Есть пользователи, кторые работаю в данной прграмме, но имеют плохие нервы. Поэтому, когда они запускают программу, если сразу не появилось окно, то они начинают тыкать на ярлык запуска снова и снова. В результате появляется большое количество открытого одного и того же файла. Причем открывается этот файл только для чтения.
Программа не может сохранить данные.
Пытался сдеать следующее: когда программа запускается, то она ищет некий файл «запуск.txt», который сама же и создает при запуске. Т.е. если файл существует, то программа не запускается. При закрытии программы файл удаляется.
Но это не решило проблему, т.к. у некоторых пользователей все равно иногда открывается файл, в котором хранятся данные только для чтения. Либо они особо «одаренные», либо у меня и вправду руки не оттуда растут.
Я думаю, что можно сделать проверку, если файл открыт только для чтения (несколько раз), то программа выводит пользователю сообщение об ошибке и рекомендует перезагрузить компьютер.
Может еще есть какие соображения? И как проверить, что файл уже открыт? Спасибо.