Форум поддержки пользователей. LibreOffice, Apache OpenOffice, OpenOffice.org

Форум поддержки пользователей. LibreOffice, Apache OpenOffice, OpenOffice.org

5 Июль 2020, 15:51 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
Новости: Часто задаваемые вопросы по LibreOffice и Apache OpenOffice.org
 
   Начало   Помощь Поиск Войти Регистрация    задать вопрос  
Страниц: 1   Вниз
  Печать  
Автор Тема: Calc: StatusBar  (Прочитано 991 раз)
0 Пользователей и 1 Гость смотрят эту тему.
eeigor
Ubuntu 18.04 LTS
Форумчанин
***
Offline Offline

Пол: Мужской
Сообщений: 100


« Стартовое сообщение: 20 Июнь 2020, 20:58 »

Знатоки, подскажите, как отобразить/скрыть строку состояния в Calc программно.

Код:
Sub DisplayStatusBar(state As Boolean)
Dim document As Object
Dim dispatcher As Object

document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

Dim args1(0) As New com.sun.star.beans.PropertyValue
args1(0).Name = "StatusBarVisible"
args1(0).Value = state

dispatcher.executeDispatch(document, ".uno:StatusBarVisible", "", 0, args1())
End Sub

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

В Excel есть два свойства:
Application.DisplayStatusBar [Boolean]
Application.StatusBar [Variant]
« Последнее редактирование: 20 Июнь 2020, 21:06 от eeigor » Записан
sokol92
Форумчанин
***
Offline Offline

Пол: Мужской
Сообщений: 61


WWW
« Ответ #1: 20 Июнь 2020, 21:23 »

Описано здесь.

Пример использования:

Код:
' Сопоставляет время вызова "родной" функции Basic и функции, вызванной через FunctionAccess
Sub TestFunctionAccessSpeed
  Dim n as Long  ' число вызовов функции  
  Dim i as Long  ' счетчик вызовов
  Dim oIndicator ' индикатор  статуса
  Dim oFA        ' FunctionAccess
  Dim j as Long, s as String, t as Long, d as Double, fm as String, title as String

  n=500000
  fm="#,##0"
  oFA = createUnoService( "com.sun.star.sheet.FunctionAccess" )
  oIndicator=ThisComponent.getCurrentController().frame.createStatusIndicator()  ' создаем индикатор статуса
  
  oIndicator.start("Сравнение скорости вызова функций", n)    ' стартуем индикатор статуса
  s="Число вызовов функций: " & format(n, fm)
  
  For j=1 To 2
    title=IIf(j=1, "Вызов Basic SIN", "Вызов FunctionAccess SIN")
    oIndicator.setText(title)
    oIndicator.setValue(0)
    t=GetSystemTicks()
    For i=1 to n
      If i mod 50000=0 Then
        oIndicator.setvalue(i)
      End If    
      If j=1 Then
        d=sin(i)
      Else
        d=oFA.callFunction("SIN", Array(CDbl(i)))  
      End If  
    Next i  
    s=s & Chr(10) & title & ". Время: " & Format(GetSystemTicks-t, fm)
  Next j  
  
  oIndicator.end()   ' закрываем индикатор статуса
  Msgbox s
End Sub

« Последнее редактирование: 21 Июнь 2020, 15:15 от sokol92 » Записан

Владимир.
sokol92
Форумчанин
***
Offline Offline

Пол: Мужской
Сообщений: 61


WWW
« Ответ #2: 21 Июнь 2020, 15:06 »

Дополнил свой ответ.
Записан

Владимир.
eeigor
Ubuntu 18.04 LTS
Форумчанин
***
Offline Offline

Пол: Мужской
Сообщений: 100


« Ответ #3: 21 Июнь 2020, 18:52 »

Ubuntu Linux 18.04 LTS LibreOffice Calc 6.4.4.2.

sokol92, очень интересное решение. Правда, я спрашивал про StatusBar, но хотел использовать эту панель именно с этой целью: вывести импровизированную строку состояния из символов псевдографики. Но вы угадали мою конечную цель: построить ProgressBar.
Задал значения переменных: n = 5000; m = 500.

Как удалить индикатор?
Скриншот с неудалённым индикатором.

Другой вопрос, чуть не по теме.
Как обновить экран? В Excel для этих целей использовал оператор DoEvents в цикле. А так, ScreenUpdating [Boolean].
Здесь что-то подобное ScreenUpdating False|True:
ThisComponent.lockControllers
ThisComponent.unlockControllers


* Снимок экрана от 2020-06-21 18-46-06.png (54.96 Кб, 828x387 - просмотрено 15 раз.)
« Последнее редактирование: 21 Июнь 2020, 19:31 от eeigor » Записан
sokol92
Форумчанин
***
Offline Offline

Пол: Мужской
Сообщений: 61


WWW
« Ответ #4: 21 Июнь 2020, 20:45 »

"Индикатор" и есть аналог StatusBar, но с расширенными возможностями. Он состоит из двух частей, которыми можно управлять независимо: текста и "прогрессбара".

Если макрос завершается аварийно, то индикатор остается (я не знаю пока, как с этим воевать). При нормальном завершении индикатор удаляется после того, как будет выполнен метод end  и обнулен счетчик ссылок на индикатор (как и другие объекты).

С обновлением экрана, надеюсь, помогут более опытные коллеги.
Записан

Владимир.
eeigor
Ubuntu 18.04 LTS
Форумчанин
***
Offline Offline

Пол: Мужской
Сообщений: 100


« Ответ #5: 21 Июнь 2020, 20:54 »

Я, в своё время работал с Microsoft Access, и там сделано подобным образом.
https://docs.microsoft.com/en-us/office/vba/access/concepts/miscellaneous/use-the-status-bar-progress-meter
acSysCmdRemoveMeter  Remove progress meter

Но всё равно это находка. Спасибо

В отношении метода end() в описании сказано: The instance must be gone by using ref count or disposing. (Экземпляр должен быть удален с помощью...).
Почему "должен быть"? Кто это должен сделать и как?
При нормальном завершении индикатор удаляется после того, как будет выполнен метод end
Сомневаюсь, однако...

UPD
Ну, вот, и ответ. Вы использовали все методы, кроме одного:
Код:
oIndicator.reset()
Он и доделает остальное.
reset()  Clear progress value and description
« Последнее редактирование: 21 Июнь 2020, 21:15 от eeigor » Записан
rami
Гуру
*******
Offline Offline

Пол: Мужской
Сообщений: 2 953


MacBook Pro, LibreOffice и Apache OpenOffice


« Ответ #6: 21 Июнь 2020, 21:19 »

Если макрос завершается аварийно, то индикатор остается (я не знаю пока, как с этим воевать).
Просто нужно выполнить код:
Код:
Sub Main
ThisComponent.CurrentController.StatusIndicator.end()
End Sub


Ну, вот, и ответ. Вы использовали все методы, кроме одного:
Код:
oIndicator.reset()
Он и доделает остальное.
reset()  Clear progress value and description
reset() только сбрасывает значения, но не завершает.
Записан

eeigor
Ubuntu 18.04 LTS
Форумчанин
***
Offline Offline

Пол: Мужской
Сообщений: 100


« Ответ #7: 21 Июнь 2020, 21:21 »

Он состоит из двух частей, которыми можно управлять независимо: текста и "прогрессбара"
На этом форуме, вроде, этой информации нет. Я не нашёл. Есть реализацию через форму (https://forumooo.ru/index.php/topic,3774.0.html). А это очень полезный инструмент.
Записан
eeigor
Ubuntu 18.04 LTS
Форумчанин
***
Offline Offline

Пол: Мужской
Сообщений: 100


« Ответ #8: 21 Июнь 2020, 21:23 »

reset() только сбрасывает значения, но не завершает
Да нет же.
Вот так:
Код:
 oIndicator.end()    ' закрываем индикатор статуса
 oIndicator.reset()  ' clear all
После этого в строке состояния появляется системное сообщение: Лист 1 из 1
Что и требовалось.
« Последнее редактирование: 21 Июнь 2020, 21:26 от eeigor » Записан
rami
Гуру
*******
Offline Offline

Пол: Мужской
Сообщений: 2 953


MacBook Pro, LibreOffice и Apache OpenOffice


« Ответ #9: 21 Июнь 2020, 22:06 »

Я взял макрос из Ответ #1, закомментировал строку кода oIndicator.end()   ' закрываем индикатор статуса, статус индикатор остался незавершённый, затем выполнил предложенный мною макрос и статус индикатор убрался полностью из строки состояния.
Записан

eeigor
Ubuntu 18.04 LTS
Форумчанин
***
Offline Offline

Пол: Мужской
Сообщений: 100


« Ответ #10: 21 Июнь 2020, 23:32 »

Оформлять в виде отдельной процедуры не обязательно, можно прямо здесь:
Код:
  oIndicator = ThisComponent.getCurrentController().frame.createStatusIndicator()
' oIndicator.end()  ' закрываем индикатор статуса
  ThisComponent.CurrentController.StatusIndicator.end()

Работает так же, как и с oIndicator.reset()
Вообще, не очевидная модель объектов:
ThisComponent.CurrentController().frame.createStatusIndicator()
ThisComponent.CurrentController.StatusIndicator.end()

Как будто:
ThisComponent.CurrentController().frame.createStatusIndicator() Is Not ThisComponent.CurrentController.StatusIndicator

Проверил с помощью Xray: в обоих случаях это объект com.sun.star.task.XStatusIndicator
А работает по-разному.

Вот так нормально и понятно (не люблю я эти геттеры и сеттеры):
Код:
' oIndicator = ThisComponent.getCurrentController().frame.createStatusIndicator()  ' создаем индикатор статуса
  oIndicator = ThisComponent.CurrentController().StatusIndicator()

Работает. Зачем нужно было обращение к frame ?
« Последнее редактирование: 22 Июнь 2020, 00:05 от eeigor » Записан
sokol92
Форумчанин
***
Offline Offline

Пол: Мужской
Сообщений: 61


WWW
« Ответ #11: 22 Июнь 2020, 13:54 »

Rami, большое спасибо!
Записан

Владимир.
sokol92
Форумчанин
***
Offline Offline

Пол: Мужской
Сообщений: 61


WWW
« Ответ #12: 24 Июнь 2020, 16:45 »

В версии LO 6.4 появился Infobar, который, в частности, также можно использовать для целей, указанных в данной теме. Пример из #1 расширен:

Код:
' Сопоставляет время вызова "родной" функции Basic и функции, вызванной через FunctionAccess
Sub TestFunctionAccessSpeed
  Dim n as Long   ' число вызовов функции   
  Dim i as Long   ' счетчик вызовов
  Dim oController ' контроллер документа
  Dim oIndicator  ' индикатор  статуса
  Dim oFA         ' FunctionAccess
  Dim j as Long, s as String, t as Long, d as Double, fm as String, title as String, bRed as Boolean

  n=200000
  fm="#,##0"
  oFA = createUnoService( "com.sun.star.sheet.FunctionAccess" )
  oController=ThisComponent.getCurrentController()
 
  oIndicator=oController.StatusIndicator()  ' создаем индикатор статуса
  oController.appendInfobar("MyInfobar", "Выполняется макрос", "Дождитесь завершения работы макроса, иначе можно получить непредсказуемый результат", 3, Array(), True)
  oIndicator.start("Сравнение скорости вызова функций", n)    ' стартуем индикатор статуса
 
  s="Число вызовов функций: " & format(n, fm)
 
  bRed=True
  For j=1 To 2
    title=IIf(j=1, "Вызов Basic SIN", "Вызов FunctionAccess SIN")
    oIndicator.setText(title)
    oIndicator.setValue(0)
    t=GetSystemTicks()
    For i=1 to n
      If i mod 20000=0 Then
        oIndicator.setvalue(i)
        If bRed And j=2 And i/n>=0.7 then
          oController.updateInfobar("MyInfobar", "Макрос скоро завершится", "Дождитесь завершения работы макроса, иначе можно получить непредсказуемый результат", 2)
          bRed=False
        End If 
      End If     
      If j=1 Then
        d=sin(i)
      Else
        d=oFA.callFunction("SIN", Array(CDbl(i))) 
      End If 
    Next i 
    s=s & Chr(10) & title & ". Время: " & Format(GetSystemTicks-t, fm)
  Next J   
 
  oIndicator.end()   ' закрывам индикатор статуса
  oController.removeInfobar("MyInfobar")  ' закрываем инфобар
  Msgbox s
End Sub


Записан

Владимир.
eeigor
Ubuntu 18.04 LTS
Форумчанин
***
Offline Offline

Пол: Мужской
Сообщений: 100


« Ответ #13: 24 Июнь 2020, 23:54 »

Хороший пример. Берём на вооружение.
Записан
Страниц: 1   Вверх
  Печать  
 
Перейти в:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!