О создании диалога методом CreateUnoDialog

Автор juceser, 26 марта 2025, 21:55

0 Пользователи и 1 гость просматривают эту тему.

juceser

Добрый вечер,

Необходимо вывести форму диалога в LibreOffice.
Форма создана, на листе кнопка.
Аналогично Excel метод Show не работает.
Попытка отобразить форму макросом типа рекомендуемого -

DialogLibraries.LoadLibrary("Standard")
oDialogTab = CreateUnoDialog(DialogLibraries.Standard.Dialog1)
    REM Получим модель диалога.
oDialogTabModel = oDialogTab.Model
    oDialogTabModel.Title = _
    "Табулирование функций. Пример диалога"

вызывает сбой на операторе CreateUnoDialog - функция или процедура не обнаружена.

Не работает и обходной вариант -


    With GlobalScope.BasicLibraries
      If Not .IsLibraryLoaded("Tools") Then .LoadLibrary("Tools")
    End With
    oDialogTab = Tools.ModuleControls.LoadDialog("Standard","Dialog1")

В последнем случае в списке модулей появляются служебные модули, в том числе и Tools, в нем можно найти и функцию LoadDialog и в нем обращение CreateUnoDialog -

Function LoadDialog(Libname as String, DialogName as String, Optional oLibContainer)
Dim oLib as Object
Dim oLibDialog as Object
Dim oRuntimeDialog as Object
    If IsMissing(oLibContainer ) then
        oLibContainer = DialogLibraries
    End If
    oLibContainer.LoadLibrary(LibName)
    oLib = oLibContainer.GetByName(Libname)
    oLibDialog = oLib.GetByName(DialogName)
    oRuntimeDialog = CreateUnoDialog(oLibDialog)
    LoadDialog() = oRuntimeDialog
End Function
Эти функции лежат уже, видимо, в библиотеке Standard, функции которой мне в конструкторе не видны.

Хотелось бы понять каким образом просто выполнить вызов формы по макросу кнопки на листе.
Метод с диалогами по непонятным причинам не работает.
Во втором варианте -

With GlobalScope.BasicLibraries
      If Not .IsLibraryLoaded("Tools") Then .LoadLibrary("Tools")
    End With
    oDialogTab = Tools.ModuleControls.LoadDialog("Standard","Dialog1")

он сыпется на последней строке - не понимает аргументы LoadDialog.

В Excel я бы плюнул на всю эту дребедень с библиотеками и привязанным к кнопке макросом вызвал бы одну
команду Форма.Show и в свойстве Activate формы инициализировал ее свойства, затащив обращением к листу
stA = Activesheet.Range("A1").Value нужные мне в форме значения и присвоив их к нужным полям формы Me.TBox.Value=stA . Далее обрабатывал бы саму форму.

Я не понимаю почему в VBA LibreOffice ничего из этого не работает и, более того, не работают даже методы, которые по всем хелпам должны работать вроде этого CreateUnoDialog - LoadDialog.

Кстати в Excel вся эта "интересная" хрень с диалогами тоже не работает, но там она в хелпах и не фигурирует вроде нигде.

Windows 10 и LibreOffice Calc Version: 24.8.0.3 (X86_64) / LibreOffice Community
Build ID: 0bdf1299c94fe897b119f97f3c613e9dca6be583
CPU threads: 12; OS: Windows 10 X86_64 (10.0 build 19045); UI render: Skia/Raster; VCL: win
Locale: ru-RU (ru_RU); UI: ru-RU
Calc: threaded

Может кто-то подскажет как просто открыть окно формы и обращение к листу и запись данных листа в форму?

Привет импортозамещению.

Спасибо.
   

bigor

juceser простейший вариант ваших хотелок в файле
Поддержать наш форум можно здесь

juceser

Спасибо. Как ни странно, заработало.
Полностью удалил весь дальнейший код и оставил только ваш (он же мой).
По сути Вы добавили только чтение из ячейки.
И он прошел. Почему ранее не проходил не понятно.

Смотрю дальше - добавляю задание умолчаний на форму и столкнулся с ошибкой -

Ошибка времени выполнения Basic.
Свойство или метод не найдены: Value.

на строках -

oNumericXnModel = oDialogTab.GetControl("NumericXn")
NumericXnModel.Value = -1.7

Здесь NumericXn поле ввода в форме.

Ваш вариант -


oDialogTab.Model.NumericXn.value = ThisComponent.Sheets(1).getCellbyPosition(8,2).value



Также не работает.

Очевидно же свойство Value быть должно у поля ввода. Дело в типе данных? Непонятно.

Файл приложу.

mikekaganski

Цитата: juceser от 27 марта 2025, 09:26Очевидно же свойство Value быть должно у поля ввода

Очевидно кому и с чего? Программирование по наитию - это лотерея.
У Вас объект UnoControlEdit. Даже если играть в "угадай поддерживаемые свойства", у него может быть свойство текст (или строка), но никак не "Value" (которое чаще всего значит "числовое значение"). Да, бывают фреймворки с расширенным толкованием термина Value - ну так знакомство с одним из них не означает "очевидно же, что в каком-то другом (любом) случае будет так же" ;)

А лучше всё же пользоваться окном Watch и изучать, что это за объект, с которым Вы работаете.
С уважением,
Михаил Каганский

bigor

Цитата: juceser от 27 марта 2025, 09:26По сути Вы добавили только чтение из ячейки
запуск диалога, и числовое поле. У вас же похоже текстовые поля и получать они хотят текст, а не значения.
Поддержать наш форум можно здесь

juceser

Я работаю с таким предложенным фрагментом кода и он заявлен как работающий.

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

Вот я и разбираюсь.

Изначально вообще окно диалога не создавалось.

Сейчас заработало. Я не пойму даже почему оно не работало, все операторы открытия окна остались те же.

Теперь заткнулись на присвоении значения боксу.

В ответе выше мне прислали код который реально работает у меня -

Sub Main
DialogLibraries.LoadLibrary("Standard")
oDialogTab = CreateUnoDialog(DialogLibraries.Standard.Dialog1)
    REM Получим модель диалога.
oDialogTabModel = oDialogTab.Model
    oDialogTabModel.Title = _
    "Табулирование функций. Пример диалога"
   
    oDialogTab.Model.NumbFild1.value=ThisComponent.Sheets(0).getCellbyPosition(0,0).value
    oDialogTab.execute
End Sub

Там файл приложен и здесь есть свойство Value.

У меня у бокса другое имя, обращаюсь к другой ячейке на другом листе и вуаля - код уже не работает -

oDialogTab.Model.NumericXn.value = ThisComponent.Sheets(1).getCellbyPosition(8,2).value

Как так? Свойство Value, отличается имя бокса и ячейка.

А теперь сам код примера ниже. Файл еще раз приложу.


REM Глобальные переменные
Dim oSheet As Object 'Лист Табулирование
Dim oDialogTab As Object
REM Переключатели. Функции
Dim oOptYModel As Object
Dim oOptGModel As Object
Dim oOptZModel As Object
REM Флажки. Операторы цикла
Dim oCheckDoLoopWhModel As Object
Dim oCheckDoLoopUnModel As Object
Dim oCheckDoWhLoopModel As Object
Dim oCheckDoUnLoopModel As Object
Dim oCheckWhileWendModel As Object
Dim oCheckForNextModel As Object
REM Поля ввода. Исходные данные
Dim oNumericXnModel As Object
Dim oNumericXkModel As Object
Dim oNumericDxModel As Object
REM Флажки. Агрегирующие функции
Dim oCheckSumModel As Object
Dim oCheckPrModel As Object
Dim oCheckMinModel As Object
Dim oCheckMaxModel As Object

REM Инициализация и запуск диалога
Sub StartDialogTab
    REM Загрузим библиотеку и диалог.
   

    DialogLibraries.LoadLibrary("Standard")
    oDialogTab = CreateUnoDialog(DialogLibraries.Standard.Dialog1)
REM Получим модель диалога.
    oDialogTabModel = oDialogTab.Model
oDialogTabModel.Title = _
"Табулирование функций. Пример диалога"
REM Флажки для операторов цикла
    oCheckDoLoopWhModel = oDialogTab.GetControl("CheckDoLoopWh")
    oCheckDoLoopUnModel = oDialogTab.GetControl("CheckDoLoopUn")
    oCheckDoWhLoopModel = oDialogTab.GetControl("CheckDoWhLoop")
    oCheckDoUnLoopModel = oDialogTab.GetControl("CheckDoUnLoop")
    oCheckWhileWendModel = oDialogTab.GetControl("CheckWhileWend")
    oCheckForNextModel = oDialogTab.GetControl("CheckForNext")
REM По умолчанию выбран цикл Do...Loop While.
    oCheckDoLoopWhModel.State = 1
REM Переключатели для функций   
    oOptYModel = oDialogTab.GetControl("OptY")
    oOptGModel = oDialogTab.GetControl("OptG")
    oOptZModel = oDialogTab.GetControl("OptZ")   
REM По умолчанию выбрана функция y(x).
    oOptYModel.State = True
   
REM Поля ввода начальных значений, которым
REM присваиваются значения по умолчанию.   
    oNumericXnModel = oDialogTab.GetControl("NumericXn")
    oNumericXnModel.Value = -1.7
    oNumericXkModel = oDialogTab.GetControl("NumericXk")
    oNumericXkModel.Value = 1.9
    oNumericDxModel = oDialogTab.GetControl("NumericDx")
    oNumericDxModel.Value = 0.2
   
REM Флажки для агрегирующих функций
  oCheckSumModel = oDialogTab.GetControl("CheckSum")
  oCheckPrModel = oDialogTab.GetControl("CheckPr")
  oCheckMinModel = oDialogTab.GetControl("CheckMin")
  oCheckMaxModel = oDialogTab.GetControl("CheckMax")
REM По умолчанию флажки не установлены.
  oCheckSumModel.State = 0
  oCheckPrModel.State = 0
  oCheckMinModel.State = 0
    oCheckMaxModel.State = 0
REM Лист Табулирование, на который выводим результат.
    oSheet = ThisComponent.Sheets(4)
     
REM Запустим диалог.
    oDialogTab.Execute()
End Sub

REM Оператор цикла Do...Loop While. Табулирование функции
Function DoLoopWhile(xn as Double, xk as Double, dx as Double)
REM Номер текущей строки
Dim iRow as Integer
REM Текущее значение x
Dim x as Double
REM Выведем исходные данные на лист Табулирование.
oSheet.getCellRangeByName("D1").setValue(xn)
oSheet.getCellRangeByName("F1").setValue(xk)
oSheet.getCellRangeByName("H1").setValue(dx)
REM Вычисляем в цикле на отрезке [xn, xk] с шагом dx
REM значения выбранной функции,
REM в зависимости от переключателя.
REM Результат выводим на лист Табулирование,
REM начиная с третьей строки.
x = xn
iRow = 3
Do
  oSheet.getCellRangeByName("A" & iRow).setValue(x)
  If oOptYModel.State Then _
  oSheet.getCellRangeByName("B" & iRow).setValue(y(x))
  If oOptGModel.State Then _
  oSheet.getCellRangeByName("B" & iRow).setValue(g(x))
  If oOptZModel.State Then _
  oSheet.getCellRangeByName("B" & iRow).setValue(z(x))
  x = x + dx
  iRow = iRow + 1
Loop While x <= xk
REM Возвращаем номер последней заполненной строки
REM для вычисления в дальнейшем агрегирующих функций
DoLoopWhile = iRow - 1
End Function

REM Нажатие кнопки Вычислить в диалоге
Sub OKClick
Dim iRow as Integer
Dim oRange 'Диапазон значений
Dim sCol as String
    Dim xn as Double, xk as Double, dx as Double
    xn = oNumericXnModel.Value
    xk = oNumericXkModel.Value
    dx = oNumericDxModel.Value
   
REM В ячейку A1 выведем имя вычислямой функции.
    oRange = oSheet.getCellRangeByName("A1")
    If oOptYModel.State Then oRange.String = "Функция y(x)"
    If oOptGModel.State Then oRange.String = "Функция g(x)"
    If oOptZModel.State Then oRange.String = "Функция z(x)"
REM Если ни один из операторов цикла не выбран,
REM выдадим сообщение об ошибке и выйдем из OKClick.
    If  oCheckDoLoopWhModel.State = 0 and _
        oCheckDoLoopUnModel.State = 0 and _
        oCheckDoWhLoopModel.State = 0 and _
        oCheckDoUnLoopModel.State = 0 and _
        oCheckWhileWendModel.State = 0 and _
        oCheckForNextModel.State = 0 Then
         MsgBox "Выберите оператор цикла", _
          MB_ICONEXCLAMATION, "Ошибка"
         Exit Sub
    End If
REM Вызываем функцию табулирования для каждого
REM из выбранных операторов цикла.
REM Сохраняем номер последней заполненной строки
REM в таблице и номер заполненного столбца
    If oCheckDoLoopWhModel.State = 1 Then
       iRow = DoLoopWhile (xn, xk, dx)
       sCol = "B"
    End If
REM Удалим формулы из ячеек для результатов агрегирующих функций 
oSheet.getCellRangeByName("I2:I5").clearContents( _
   com.sun.star.sheet.CellFlags.FORMULA )
REM Вычисляем агрегирующие функции в зависимости
REM от установленных флажков.
REM Результат выводим как формулу в ячейки столбца "I".
    If oCheckSumModel.State = 1 Then _
       oSheet.getCellRangeByName("I2").Formula = _
        "=Sum(" & sCol & "3:" & sCol & iRow & ")"
    If oCheckPrModel.State = 1 Then _
       oSheet.getCellRangeByName("I3").Formula = _
        "=Product(" & sCol & "3:" & sCol & iRow & ")"
    If oCheckMinModel.State = 1 Then _
       oSheet.getCellRangeByName("I4").Formula = _
       "=Min(" & sCol & "3:" & sCol & iRow & ")"
    If oCheckMaxModel.State = 1 Then _
       oSheet.getCellRangeByName("I5").Formula = _
       "=Max(" & sCol & "3:" & sCol & iRow & ")" 
   
End Sub
REM Нажатие кнопки Выход в диалоге
Sub ExitClick
REM Закрываем диалог.
oDialogTab.endExecute()
End Sub


juceser

Цитата: bigor от 27 марта 2025, 11:06
Цитата: juceser от 27 марта 2025, 09:26По сути Вы добавили только чтение из ячейки
запуск диалога, и числовое поле. У вас же похоже текстовые поля и получать они хотят текст, а не значения.


Все верно. Диалог запустился и значение притянулось. Текстовые и цифровые боксы тут разные элементы, хоть внешне выглядят одинаково. Значение вытянулось.

juceser

Вы будете смеяться, но снова грабли.   ;D
Только что мы задали значения переменных и успешно в предыдущей процедуре при старте формы -

    oNumericXnModel = oDialogTab.GetControl("NumericXn")
    oNumericXnModel.Value = -1.7
    oNumericXkModel = oDialogTab.GetControl("NumericXk")
    oNumericXkModel.Value = 1.9
    oNumericDxModel = oDialogTab.GetControl("NumericDx")
    oNumericDxModel.Value = 0.2

и вот уже при нажатии на кнопку Вычислить все сразу же вылетает на присвоении  xn-

Sub OKClick
Dim iRow as Integer
Dim oRange 'Диапазон значений
Dim sCol as String
    Dim xn as Double, xk as Double, dx as Double
    xn = oNumericXnModel.Value
    xk = oNumericXkModel.Value
    dx = oNumericDxModel.Value

Ошибка -

Ошибка времени выполнения Basic.
Объектная переменная не установлена.

При том что переменная oNumericXnModel установлена глобальной.

REM Глобальные переменные
Dim oSheet As Object 'Лист Табулирование
Dim oDialogTab As Object
REM Переключатели. Функции
Dim oOptYModel As Object
Dim oOptGModel As Object
Dim oOptZModel As Object
REM Флажки. Операторы цикла
Dim oCheckDoLoopWhModel As Object
Dim oCheckDoLoopUnModel As Object
Dim oCheckDoWhLoopModel As Object
Dim oCheckDoUnLoopModel As Object
Dim oCheckWhileWendModel As Object
Dim oCheckForNextModel As Object
REM Поля ввода. Исходные данные
Dim oNumericXnModel As Object
Dim oNumericXkModel As Object
Dim oNumericDxModel As Object


juceser

Нужно заново инициализировать диалог в функции обработки кнопки этого диалога?
Проблема типом данных опять?

mikekaganski

Цитата: juceser от 27 марта 2025, 11:46При том что переменная oNumericXnModel установлена глобальной.

REM Глобальные переменные
...
Dim oNumericXnModel As Object
Dim oNumericXkModel As Object
Dim oNumericDxModel As Object

Нет, Вы не установили oNumericXnModel глобальной - Вы только написали такой комментарий. Глобальной переменная задаётся с помощью ключевого слова Global. Дополнительно см. здесь.

А это какой предмет?
С уважением,
Михаил Каганский

bigor

Цитата: juceser от 27 марта 2025, 11:46переменная oNumericXnModel установлена глобальной.
это потому, что
Цитата: juceser от 27 марта 2025, 11:46REM Глобальные переменные
написано :)

Поддержать наш форум можно здесь

juceser

Установил везде

REM Глобальные переменные
Global oSheet As Object 'Лист Табулирование
Global oDialogTab As Object
REM Переключатели. Функции
Global oOptYModel As Object
Global oOptGModel As Object
Global oOptZModel As Object
REM Флажки. Операторы цикла
Global oCheckDoLoopWhModel As Object
Global oCheckDoLoopUnModel As Object
Global oCheckDoWhLoopModel As Object
Global oCheckDoUnLoopModel As Object
Global oCheckWhileWendModel As Object
Global oCheckForNextModel As Object
REM Поля ввода. Исходные данные
Global oNumericXnModel As Object
Global oNumericXkModel As Object
Global oNumericDxModel As Object
REM Флажки. Агрегирующие функции
Global oCheckSumModel As Object
Global oCheckPrModel As Object
Global oCheckMinModel As Object
Global oCheckMaxModel As Object

Это абсолютно ни на что не повлияло. Та же ошибка.

Кстати, в хелпе сказано -

The variable is only valid in this module.

Dim VarName As TYPENAME

В данном случае все процедуры находятся в одном модуле.
Следовательно, надо понимать, что все переменные, объявленные в общей секции являются глобальными для этого модуля. Или это не так?
Понятно, что переменные, объявленные в процедуре, действуют только в этой процедуре.
Но, в любом случае, это ничего не дало.

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

Информатика, галопом по Европам. VBA, Python, БД.




sokol92

ЦитироватьАккомпаниатор, вспомнив о жене и близких, отказывается от неравной борьбы и ретируется, а на его место садится более выносливый человек.
:)

1. Скачал файл из сообщения #11. Нажимаю кнопку "Табулирование", затем "Вычислить". Ошибки нет.

2. Вы напрасно используете версию LibreOffice 24.8.0 . Эта версия предназначена для энтузиастов, которые вылавливают ошибки в программе. Обновите на текущую, у меня сейчас 24.8.5.

3. При таком количестве переменных опция Option Explicit становится обязательной.  :)
Владимир.

juceser

Объявил опцию. Потребовалось дообъявить переменную - oDialogTabModel .

После этого возникла та же ошибка в функции кнопки Вычислить.
Установил с сайта последнюю стабильную версию -

Version: 25.2.1.2 (X86_64) / LibreOffice Community
Build ID: d3abf4aee5fd705e4a92bba33a32f40bc4e56f49
CPU threads: 12; OS: Windows 10 X86_64 (10.0 build 19045); UI render: Skia/Raster; VCL: win
Locale: ru-RU (ru_RU); UI: ru-RU
Calc: threaded

Ничего не изменилось, та же ошибка.




Option Explicit

REM Глобальные переменные
Global oSheet As Object 'Лист Табулирование
Global oDialogTab As Object
Global oDialogTabModel As Object
REM Переключатели. Функции
Global oOptYModel As Object
Global oOptGModel As Object
Global oOptZModel As Object
REM Флажки. Операторы цикла
Global oCheckDoLoopWhModel As Object
Global oCheckDoLoopUnModel As Object
Global oCheckDoWhLoopModel As Object
Global oCheckDoUnLoopModel As Object
Global oCheckWhileWendModel As Object
Global oCheckForNextModel As Object
REM Поля ввода. Исходные данные
Global oNumericXnModel As Object
Global oNumericXkModel As Object
Global oNumericDxModel As Object
REM Флажки. Агрегирующие функции
Global oCheckSumModel As Object
Global oCheckPrModel As Object
Global oCheckMinModel As Object
Global oCheckMaxModel As Object

bigor

Цитата: sokol92 от 27 марта 2025, 14:23Ошибки нет.
ошибки тоже не было, но оказывается макрос не выполняется, переписал имя в свойствах кнопки, начал выполняться и вываливаться в ошибку. У вас нигде не прописан oSheet, прописал - теперь ругается на  oCheckForNextModel.State, кстати даже если в первом макросе проверять, то ругается тоже
Поддержать наш форум можно здесь