Домашняя страница Undo Do New Save Карта сайта Обратная связь Поиск по форуму
МИР MS EXCEL - Гость.xls

Вход

Регистрация

Напомнить пароль

 

= Мир MS Excel/Кнопка на ленте активная по условию - Мир MS Excel

Старая форма входа
  • Страница 1 из 1
  • 1
Модератор форума: китин, _Boroda_  
Мир MS Excel » Вопросы и решения » Вопросы по VBA » Кнопка на ленте активная по условию (Макросы/Sub)
Кнопка на ленте активная по условию
user0 Дата: Вторник, 01.08.2017, 09:39 | Сообщение № 1
Группа: Проверенные
Ранг: Форумчанин
Сообщений: 152
Репутация: 8 ±
Замечаний: 0% ±

Excel 2013, 2016
Доброго времени,

Сделал вкладку MyTab с парой кнопок на ленте. Идея в том чтобы по умолчанию кнопка Stop была неактивной и становилась активной (доступной для нажатия) после запуска процесса назначеного на кнопку Start. В целом все довольно просто и работает.
Но почему-то перестает работать когда добавляешь вызов другой процедуры после активации кнопки, например StatusBarProgress - кнопка Stop активируется только после завершения процедуры StatusBarProgress.

Подскажите, пожалуйста, где проблема:

xml (customUI14)
[vba]
Код
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="RibbonOnLoad">
  <ribbon>
    <tabs>
      <tab id="T1" label="MyTab" insertBeforeMso="TabHome">
        <group id="G1" label="buttons">
          <button id="G1B1" imageMso="NavDrillDown" label="Start" tag="btnStart" size="large" onAction="btnStart"/>
          <button id="G1B2" imageMso="CancelRequest" label="Stop" tag="btnStopTag" size="large" getEnabled="GetEnabledMacro" onAction="btnStop"/>
        </group>
      </tab>
    </tabs>
  </ribbon>
</customUI>
[/vba]
[vba]
Код
Option Explicit

Public myRib As IRibbonUI
Public myTag As String
Public btnStopPressed As Boolean

'ribbon
Sub RibbonOnLoad(ribbon As IRibbonUI)
    Set myRib = ribbon
End Sub

Sub GetEnabledMacro(control As IRibbonControl, ByRef Enabled)
    If myTag = "Enable" Then
        Enabled = True
    Else
        If control.Tag Like myTag Then
            Enabled = True
        Else
            Enabled = False
        End If
    End If
End Sub

Sub RefreshRibbon(Tag As String)
    myTag = Tag
    If myRib Is Nothing Then
        MsgBox "Error, Save/Restart your workbook"
    Else
        myRib.Invalidate
    End If
End Sub

'buttons
Sub btnStart(control As IRibbonControl)
    Call RefreshRibbon(Tag:="btnStopTag")
    Call StatusBarProgress
End Sub

Sub btnStop(control As IRibbonControl)
    btnStopPressed = True
    Call RefreshRibbon(Tag:="")
End Sub

'routine
Sub StatusBarProgress()
    Dim iTask As Long
    Dim TotalTasks As Long
    Dim secondsPerTask As Integer
    Dim TimeStart As Double

    secondsPerTask = 0.1
    TotalTasks = 3000
    TimeStart = Now

    For iTask = 1 To TotalTasks
        DoEvents
        If btnStopPressed Then GoTo myEnd

        Application.StatusBar = iTask & " of " & TotalTasks & " " & Format(iTask / TotalTasks, "0.0%") & _
        "   EndOn: " & Format(Now + (TotalTasks - iTask) * secondsPerTask / 86400, "YYYY-MM-DD hh:mm:ss") & _
        "   Remaining: " & Format(Now - TimeStart, "hh:mm:ss") & " of " & Format(TotalTasks * secondsPerTask / 86400, "hh:mm:ss")

    Next iTask

myEnd:
    Application.StatusBar = False
    btnStopPressed = False
    Call RefreshRibbon(Tag:="")
End Sub
[/vba]

ps. к теме не относится, но если вдруг кому интересно - как обойти проблему losing the state of the global IRibbonUI ribbon object.
К сообщению приложен файл: q2.xlsm (23.4 Kb)


Сообщение отредактировал user0 - Вторник, 01.08.2017, 14:39
 
Ответить
СообщениеДоброго времени,

Сделал вкладку MyTab с парой кнопок на ленте. Идея в том чтобы по умолчанию кнопка Stop была неактивной и становилась активной (доступной для нажатия) после запуска процесса назначеного на кнопку Start. В целом все довольно просто и работает.
Но почему-то перестает работать когда добавляешь вызов другой процедуры после активации кнопки, например StatusBarProgress - кнопка Stop активируется только после завершения процедуры StatusBarProgress.

Подскажите, пожалуйста, где проблема:

xml (customUI14)
[vba]
Код
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="RibbonOnLoad">
  <ribbon>
    <tabs>
      <tab id="T1" label="MyTab" insertBeforeMso="TabHome">
        <group id="G1" label="buttons">
          <button id="G1B1" imageMso="NavDrillDown" label="Start" tag="btnStart" size="large" onAction="btnStart"/>
          <button id="G1B2" imageMso="CancelRequest" label="Stop" tag="btnStopTag" size="large" getEnabled="GetEnabledMacro" onAction="btnStop"/>
        </group>
      </tab>
    </tabs>
  </ribbon>
</customUI>
[/vba]
[vba]
Код
Option Explicit

Public myRib As IRibbonUI
Public myTag As String
Public btnStopPressed As Boolean

'ribbon
Sub RibbonOnLoad(ribbon As IRibbonUI)
    Set myRib = ribbon
End Sub

Sub GetEnabledMacro(control As IRibbonControl, ByRef Enabled)
    If myTag = "Enable" Then
        Enabled = True
    Else
        If control.Tag Like myTag Then
            Enabled = True
        Else
            Enabled = False
        End If
    End If
End Sub

Sub RefreshRibbon(Tag As String)
    myTag = Tag
    If myRib Is Nothing Then
        MsgBox "Error, Save/Restart your workbook"
    Else
        myRib.Invalidate
    End If
End Sub

'buttons
Sub btnStart(control As IRibbonControl)
    Call RefreshRibbon(Tag:="btnStopTag")
    Call StatusBarProgress
End Sub

Sub btnStop(control As IRibbonControl)
    btnStopPressed = True
    Call RefreshRibbon(Tag:="")
End Sub

'routine
Sub StatusBarProgress()
    Dim iTask As Long
    Dim TotalTasks As Long
    Dim secondsPerTask As Integer
    Dim TimeStart As Double

    secondsPerTask = 0.1
    TotalTasks = 3000
    TimeStart = Now

    For iTask = 1 To TotalTasks
        DoEvents
        If btnStopPressed Then GoTo myEnd

        Application.StatusBar = iTask & " of " & TotalTasks & " " & Format(iTask / TotalTasks, "0.0%") & _
        "   EndOn: " & Format(Now + (TotalTasks - iTask) * secondsPerTask / 86400, "YYYY-MM-DD hh:mm:ss") & _
        "   Remaining: " & Format(Now - TimeStart, "hh:mm:ss") & " of " & Format(TotalTasks * secondsPerTask / 86400, "hh:mm:ss")

    Next iTask

myEnd:
    Application.StatusBar = False
    btnStopPressed = False
    Call RefreshRibbon(Tag:="")
End Sub
[/vba]

ps. к теме не относится, но если вдруг кому интересно - как обойти проблему losing the state of the global IRibbonUI ribbon object.

Автор - user0
Дата добавления - 01.08.2017 в 09:39
Саня Дата: Вторник, 01.08.2017, 21:50 | Сообщение № 2
Группа: Друзья
Ранг: Ветеран
Сообщений: 1068
Репутация: 560 ±
Замечаний: 0% ±

XL 2016
[vba]
Код
Sub btnStart(control As IRibbonControl)
    Call RefreshRibbon(Tag:="btnStopTag")
    'Call StatusBarProgress
    Application.OnTime Now, "StatusBarProgress"
End Sub
[/vba]

нет никакого разумного объяснения этому. yes

просто, процедура, вызвавшая инвалидейт ленты, пока не завершит свое выполнение, не будет делать тот самый инвалидейт.

гипотезы оставлю при себе :p


Сообщение отредактировал Саня - Вторник, 01.08.2017, 22:04
 
Ответить
Сообщение[vba]
Код
Sub btnStart(control As IRibbonControl)
    Call RefreshRibbon(Tag:="btnStopTag")
    'Call StatusBarProgress
    Application.OnTime Now, "StatusBarProgress"
End Sub
[/vba]

нет никакого разумного объяснения этому. yes

просто, процедура, вызвавшая инвалидейт ленты, пока не завершит свое выполнение, не будет делать тот самый инвалидейт.

гипотезы оставлю при себе :p

Автор - Саня
Дата добавления - 01.08.2017 в 21:50
user0 Дата: Среда, 02.08.2017, 04:30 | Сообщение № 3
Группа: Проверенные
Ранг: Форумчанин
Сообщений: 152
Репутация: 8 ±
Замечаний: 0% ±

Excel 2013, 2016
Спасибо за разделение моей боли :D

Но даже так оно все равно работает как-то нестабильно:
1) первый раз, после добавления кода - заработало (единоразово, см п2), но после сохранения и открытия файла перестало работать.
2) после успешной остановки кнопкой Stop и последующего повторного запуска Start, кнопка стоп уже не активируется..

Возможно есть еще идеи ?)

ps. офтоп, аргументы в процедуру в OnTime, внезапно, передаются неочевидным способом.


Сообщение отредактировал user0 - Среда, 02.08.2017, 05:42
 
Ответить
СообщениеСпасибо за разделение моей боли :D

Но даже так оно все равно работает как-то нестабильно:
1) первый раз, после добавления кода - заработало (единоразово, см п2), но после сохранения и открытия файла перестало работать.
2) после успешной остановки кнопкой Stop и последующего повторного запуска Start, кнопка стоп уже не активируется..

Возможно есть еще идеи ?)

ps. офтоп, аргументы в процедуру в OnTime, внезапно, передаются неочевидным способом.

Автор - user0
Дата добавления - 02.08.2017 в 04:30
user0 Дата: Четверг, 03.08.2017, 15:26 | Сообщение № 4
Группа: Проверенные
Ранг: Форумчанин
Сообщений: 152
Репутация: 8 ±
Замечаний: 0% ±

Excel 2013, 2016
Вроде разобрался.
Такое нестабильное поведение возникает если открыт редактора vba и там выбран лист или модуль и тп. Если редактор потом закрыть, все работает как прежде.

Еще один вопрос, подскажите, пожалуйста, как запустить инвалидейт ленты, если бы код из StatusBarProgress не был бы отдельной процедурой, а был вставлен в btnStart, сразу после RefreshRibbon?
 
Ответить
СообщениеВроде разобрался.
Такое нестабильное поведение возникает если открыт редактора vba и там выбран лист или модуль и тп. Если редактор потом закрыть, все работает как прежде.

Еще один вопрос, подскажите, пожалуйста, как запустить инвалидейт ленты, если бы код из StatusBarProgress не был бы отдельной процедурой, а был вставлен в btnStart, сразу после RefreshRibbon?

Автор - user0
Дата добавления - 03.08.2017 в 15:26
Мир MS Excel » Вопросы и решения » Вопросы по VBA » Кнопка на ленте активная по условию (Макросы/Sub)
  • Страница 1 из 1
  • 1
Поиск:

Яндекс.Метрика Яндекс цитирования
© 2010-2024 · Дизайн: MichaelCH · Хостинг от uCoz · При использовании материалов сайта, ссылка на www.excelworld.ru обязательна!