Периодически получать сообщения об ошибках режима прерывания VBA при загрузке элементов управления ленты при запуске PowerPoint - PullRequest
0 голосов
/ 30 января 2019

Я создал надстройку для PowerPoint, которая создает сетку объектов из выбранных объектов.

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

При открытии PowerPoint (с включенной надстройкой) может появиться следующее сообщение об ошибке: «PowerPoint не можетЗапустите эту функцию, потому что в настоящее время у вас есть проект Visual Basic для приложений в режиме прерывания. "

Сообщение повторяется, когда каждый пользовательский элемент управления загружается на ленту (элементы управления постепенно появляются при нажатии кнопки ОК для каждой ошибки),и после запуска PowerPoint элементы управления присутствуют на ленте, но отображаются серым цветом и не активируются при выборе формы.

Ошибка очень трудно найти: она может просто исчезнуть и не-появиться на определенной машине, но затем может присутствовать на другой машине для той же настройки (и exaточно такой же код надстройки).Это может произойти, если эта надстройка загружена сама по себе, или это может произойти, только если она загружена с другими надстройками.

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

Ошибка не отображается, если PowerPoint запускается с открытым документом.Также ошибка может быть видна только тогда, когда PowerPoint настроен на запуск с экрана приветствия, а не с новым документом.

Моя текущая версия офиса: 1812 (офис 365 - рабочий стол), сборка 11126.20196 (но яЯ видел это в других версиях) и Windows 10 версии 1803.

Я пытался:

  • Экспорт всего моего кода в текстовые файлы и импорт его обратно с использованием версииСредство очистки кода Роба Бови, адаптированное для PowerPoint: http://www.tushar -mehta.com / powerpoint / vba_codecleaner / index.htm

  • Попытка заставить сообщения об ошибках появляться впопытайтесь выяснить, каким может быть возможный источник ошибок, но до сих пор не смогли этого сделать:

    • Умышленно вставлять ошибку в любой код, запускаемый при загрузке PowerPoint (например, деление на ноль) приводит к обычным сообщениям об ошибках отладки, а не к сообщениям об ошибках, с которыми у меня возникают проблемы.

    • Введение задержек в Auto_Open, onLoad ивызовы getEnabled, чтобы попытаться получить любой из этих вызовов, которые могут выполняться асинхронно, чтобы перекрываться после предположения , что вызовы Auto_Open и onLoad могут бороться друг с другом : но хотя я могу получить вызовы Auto_Open и onLoad перекрываться, это не привело к повторному появлению сообщений об ошибках .

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

  • Я попытался сравнить реестр(HKCU) для случая, когда PowerPoint находится в режиме перерыва, и когда не видно, может ли это дать подсказку - но не было ничего существенного, что отличалось бы.

XML для надстройки GridMaker выглядит следующим образом (в customUI.xml - я открываю файл pptm в Visual Studio с расширением редактора пакетов Open XML):

<customUI onLoad="GMApplicationEventsModule.gmRibbonUI_onLoad" xmlns="http://schemas.microsoft.com/office/2006/01/customui" xmlns:nsCommtap="CommtapNamespace">
  <ribbon startFromScratch="false">
    <tabs>
      <tab idMso="TabHome">
        <group id="gridMakerGroup" label="Grid Maker">
          <button id="gmMakeGrid"
                  label="Make Into Grid"
                  imageMso="TableInsert"
                  size="normal"
                  onAction="MainModule.makeGrid"
                  getEnabled="GMApplicationEventsModule.gm_GetEnabled" />
        </group>
      </tab>
    </tabs>
  </ribbon>
</customUI>

Модуль GMApplicationEvents выглядит следующим образом:

Option Explicit

Private m_oMyRibbon As IRibbonUI
Private m_boolShapeSelected As Boolean
Private m_oAppEvents As CGMApplicationEvents

Public Function get_m_oMyRibbon() As IRibbonUI
  Set get_m_oMyRibbon = m_oMyRibbon
End Function

Public Sub set_m_boolShapeSelected(value As Boolean)
  m_boolShapeSelected = value
End Sub

Public Function get_m_boolShapeSelected() As Boolean
  get_m_boolShapeSelected = m_boolShapeSelected
End Function

Public Sub gm_GetEnabled(control As IRibbonControl, ByRef returnedVal)
  returnedVal = True
  If control.Id = "gmMakeGrid" Then
    returnedVal = GMApplicationEventsModule.get_m_boolShapeSelected
  End If
End Sub

Public Sub gmRibbonUI_onLoad(Ribbon As IRibbonUI)
  Set m_oMyRibbon = Ribbon
End Sub

Public Sub Auto_Open()
  If m_oAppEvents Is Nothing Then
    Set m_oAppEvents = New CGMApplicationEvents
  End If
  Set m_oAppEvents.App = Application
End Sub

Класс CGMApplicationEvents:

Option Explicit

Public WithEvents App As Application

Private Sub App_WindowSelectionChange(ByVal Sel As Selection)

  If Application.ActiveWindow.Selection.Type <> ppSelectionShapes Then
    GMApplicationEventsModule.set_m_boolShapeSelected False
  Else
    GMApplicationEventsModule.set_m_boolShapeSelected True
  End If

  If Not GMApplicationEventsModule.get_m_oMyRibbon Is Nothing Then
    Dim oRibbon As IRibbonUI
    Set oRibbon = GMApplicationEventsModule.get_m_oMyRibbon
    oRibbon.InvalidateControl "gmMakeGrid"
  End If

End Sub

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

Создание сообщения об ошибке

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

У меня есть одна надстройка - app1-basic (с использованием кода, как описано выше), которая включена.У меня есть второй файл макроса (app2-basic.pptm) ​​(также как описано выше), в который я поместил оператор «Stop» в процедуру onLoad.При закрытом PowerPoint откройте app2-basic.pptm.Во время открытия VBE откроется, и выполнение кода остановится в операторе stop.Теперь закройте PowerPoint (нажав на «X» в частично открытом PowerPoint).Появится сообщение об ошибке.

Появляется сообщение об ошибке, вызванное тем, что PowerPoint пытается вызвать процедуру getEnabled в надстройке, но не может, потому что открываемый макрос перевел ее в режим прерывания.Ведение журнала, кажется, поддерживает это:

Time                    Time tick       VBA Project     Module                  Procedure               Comment

Stop in app2-basic onLoad which is opened as pptm (not add-in), one other add-in enabled (app1-basic)                   
25/02/19 15:17:58:258   158,650,603,696 app1-basic      ApplicationEventsModule Auto_Open               Called
25/02/19 15:17:58:258   158,650,619,479 app1-basic      ApplicationEventsModule Auto_Open               Completed
25/02/19 15:17:59:259   158,653,089,479 app1-basic      ApplicationEventsModule set_m_boolShapeSelected Called
25/02/19 15:17:59:259   158,653,105,936 app1-basic      ApplicationEventsModule get_m_oMyRibbon         Called
25/02/19 15:17:59:259   158,653,421,625 app1-basic      ApplicationEventsModule gmRibbonUI_onLoad       Called.
25/02/19 15:17:59:259   158,653,477,892 app1-basic      ApplicationEventsModule gmRibbonUI_onLoad       Completed
25/02/19 15:17:59:259   158,653,560,560 app2-basic      ApplicationEventsModule gmRibbonUI_onLoad       Called.

Normal open then close - app1 - with no errors                  
25/02/19 15:34:45:245   161,505,047,523 app1-basic      ApplicationEventsModule Auto_Open               Called
25/02/19 15:34:45:245   161,505,061,039 app1-basic      ApplicationEventsModule Auto_Open               Completed
25/02/19 15:34:54:254   161,531,088,269 app1-basic      ApplicationEventsModule gmRibbonUI_onLoad       Called.
25/02/19 15:34:54:254   161,531,110,752 app1-basic      ApplicationEventsModule gmRibbonUI_onLoad       Completed
25/02/19 15:34:54:254   161,531,169,707 app1-basic      ApplicationEventsModule app1_GetEnabled Called: Control.id: app1ShapeSelectedMsg
25/02/19 15:34:54:254   161,531,200,726 app1-basic      ApplicationEventsModule get_m_boolShapeSelected Called
25/02/19 15:34:54:254   161,531,215,706 app1-basic      ApplicationEventsModule app1_GetEnabled         Completed: Control.id: app1ShapeSelectedMsg

Дополнительные комментарии:

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

  • Это похоже, что ошибка, скорее всего, будетвозникающие из-за чего-то еще, кроме надстройки, которая не может быть загружена должным образом из-за ошибки.Также возможно, что ошибка может быть связана с проблемой состояния, в котором PowerPoint открыт, - возможно, из-за проблемы, возникшей при его последнем закрытии.

Код для демонстрацииошибки

Полный код, который время от времени выдает это сообщение об ошибке .

Ответы [ 2 ]

0 голосов
/ 05 мая 2019

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

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

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

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

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

0 голосов
/ 30 января 2019

Я столкнулся с такой же ситуацией только вчера, и из вашего описания мы могли столкнуться с чем-то похожим.

Вы можете получить эту ошибку, когда ссылаетесь, например, на путь текущей презентации или текущий выбор, когда загружается надстройка ... т. Е. Нет открытой презентации и, следовательно, не может быть текущего выбора.

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

Public Sub UberMsg(sMsgString As String, Optional sRoutine As String = "Debug Msg")
    If UberMsg Then
        Call MsgBox(sMsgString, vbOKOnly, sRoutine)
    End If
End Sub

Объявленные как глобальные переменные строка с именем sRoutine и bool с именем UberMsg (установлено в True)

Затем в различных точках моего подпрограммы AutoOpen и подпрограмм, вызываемых из нее:

ThisОднажды в начале процедуры:

sRoutine = "{the current procedure name}"

И скопируйте / вставьте / отредактируйте это перед каждой подозрительной кодовой точкой:

UberMsg "AppInit entry point", sRoutine

Потребовалось всего несколько итераций для сохранения PPAMи повторное тестирование, чтобы найти проблемную область и исправить ее.

Я установлю для логического значения UberMsg значение false и оставлю все это на месте в случае необходимостипотом.

...