Как остановить Excel от повторного открытия книги? - PullRequest
5 голосов
/ 09 октября 2008

У меня есть книга Excel только для чтения, содержащая приложение VBA. Приложение сохраняет любые данные, которые необходимо сохранить в базе данных, и рабочая книга всегда закрывается без сохранения (путем установки ThisWorkbook.Saved = True в BeforeClose).

У меня следующая проблема:

  • Пользователь дважды щелкает книгу в Проводнике Windows, книга открывается.

  • Пользователь дважды щелкает дважды по книге в проводнике Windows.

  • Excel предлагает: «MyWorkbook.xls уже открыт. Повторное открытие приведет к отмене любых внесенных вами изменений. Хотите открыть MyWorkbook.xls?»

  • Если пользователь нажимает «Да», книга открывается повторно без выполнения обработчика события BeforeClose для экземпляра, который уже был открыт .

Это проблема в моем приложении, потому что это означает, что какой-то важный код очистки в обработчике событий BeforeClose не выполняется.

Может кто-нибудь предложить решение VBA для этого. Который может быть:

  • Подавление запроса на повторное открытие книги. Вместо этого молча используйте уже открытый экземпляр.

  • Каким-то образом заставьте BeforeClose или какой-либо другой обработчик событий запускаться в исходном экземпляре до его закрытия, чтобы я мог запустить мой код очистки.

Обновление:

Это Excel 2003.

Я могу избавиться от нежелательного приглашения, установив «ThisWorkbook.Saved = True» в обработчике событий Workbook_SheetChanged (приложение VBA отвечает за сохранение любых данных, которые должны быть сохранены в базе данных, поэтому мне все равно о сохранении изменений в Excel).

Однако это не решает мою проблему: если я сделаю это, то двойной щелчок по Рабочей книге в проводнике автоматически откроет рабочую книгу, но все равно сделает это без вызова обработчиком события «BeforeClose».

Итак, чтобы перефразировать вопрос:

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

Обновление 2

Принимая ответ Б. Киммела - похоже, нет никакого VBA-способа перехватить это событие из рабочей книги.

Решение, которое я буду реализовывать, будет состоять в том, чтобы переместить код приложения в надстройку XLA, которая автоматически загружается (если еще не загружена) при загрузке книги. Надстройка может обрабатывать события Open и BeforeClose и хранить информацию, необходимую для очистки.

Ответы [ 3 ]

2 голосов
/ 10 октября 2008

Человек ... это кажется простым, но трудным. Я поиграл с каждым событием и свойством приложения / рабочей книги, о которых я мог подумать за 7 или около того лет работы с Excel VBA, и я не смог придумать ничего изящного вообще ... Я думаю, что короткий ответ таков: нет действительно короткого элегантного решения этой проблемы (если есть, я бы очень хотел это увидеть). Это плохие новости.

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

Более элегантный способ будет включать переосмысление и рефакторинг ваших методов ... Я думаю, что причина, по которой я никогда не сталкивался с этой проблемой в своей работе, заключается в том, что в конце каждого из моих методов рабочая книга остается в «хорошем» состоянии ... или, другими словами, если есть «очистка», то это делается в конце каждого метода. Если это приводит к значительному снижению производительности, вы можете установить логический флаг и ограничить его запуск в конце каждого из ваших других методов. (т. е. runCleanup = ReturnTrueIfCleanupIsNeeded () If (runCleanup = true), тогда CleanupMethod () End If)

Более грязный способ будет включать превращение всей рабочей книги в своего рода "ad-hoc" мьютекс "
1) копирование всей ( оригинальная ) рабочей книги с событием WorkBookOpen в другую ( temp ) рабочую книгу и использование метода" SaveAs " на temp , чтобы разместить его в отдельном месте.
2) Сохранение пути ( original ).
3) Добавление кода в событие открытия WorkBook, которое проверяет наличие ( temp ) и либо A) Немедленно закрывается и активирует temp или B) Перезаписывает себя с помощью ( temp ), а затем использует SaveAs
4) Поймайте событие, прежде чем пользователь сохранит книгу, и сохраните ее в , , оригинальном местоположении и temp location.
5) В событии WorkBookClose выполните любую необходимую очистку и сохраните temp обратно в исходное местоположение.

Суть всего этого обойти «коллизию», которая возникает, когда вы дважды открываете книгу - по сути, создав рабочую книгу temp при первом открытии и сохранив ее в другом месте (возможно, вы даже можете скрыть файл?) вы гарантируете, что когда пользователь щелкает оригинал, он не сталкивается с данными, с которыми он уже работает в приложении. (Конечно, у него есть свои проблемы / вопросы, такие как «Что если я не знаю, по каким путям у пользователя есть доступ для сохранения временного файла» или «Что если пользователь откроет XLS-файл temp ». ... но именно поэтому я назвал это грязь путь) "

Я знаю, что это много, особенно если вы не привыкли работать с VBA; Если вы хотите, чтобы я опубликовал некоторый код, чтобы помочь вам с любым из этих шагов, оставьте комментарий, и я буду.

Спасибо за интересный вопрос.

2 голосов
/ 09 октября 2008

Вы можете использовать некоторые специальные события приложения для обработки при повторном открытии книги и ручного запуска кода Workbook_Close:

Создайте модуль класса ApplicationController со следующим кодом:

Public WithEvents CApp As Application
Public CurrentWB as Workbook

Private Sub CApp_WorkbookOpen(ByVal wb As Excel.Workbook)


Dim sPathName As String
sPathName = wb.Name
if sPathName = CurrentWB.Name then CallSomeMethod()

End Sub

тогда на вашем событии workbook_load сделайте что-то вроде:

Public controller as new ApplicationController
Private Sub Workbook_Open()
set controller.CApp = Excel.Application
set controller.CurrentWB = ThisWorkbook
End Sub

теперь, когда Excel открывает новую книгу, вы фиксируете событие и запускаете метод безопасности. Вы можете даже предотвратить повторное открытие книги, если хотите.

1 голос
/ 09 марта 2018

Вы также можете отключить запрос:

Это откроет открытый файл без предупреждений .. но учтите, что любые изменения отменяются!

Application.DisplayAlerts = False
Workbooks.Open (sPath)
Application.DisplayAlerts = True

Из Excel Forum

Это решение сработало для моих нужд

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...