Как запустить событие макросом

Автор Kadet, 7 августа 2021, 11:16

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

Kadet

Добрый день!
Небольшой вопрос, но пока не могу разобраться. Подскажите, пожалуйста.

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

Как можно запустить это событие этого поля изменяя данные поля макросом?
Методов Modifi или IsModified у этого поля нет.

eeigor

#1
Вероятно, если вы макросом изменяетесь состояние поля, то вы и в состоянии «тут же на месте» самостоятельно вызвать требуемый макрос/событие (о котором пишите). А в иных случаях он будет запускаться автоматически.
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

Kadet

#2
Стал бы я взывать к общественности, если дело было в простом вызове макроса?!

Всё дело в oEvent, который должен зайти в этот макрос и который должен содержать данные именно этого поля: Имя, Значение, цепочка Parent.
А так как этот макрос повешен на многие поля, некоторые из которых даже одноимённые, то и oEvent у них будет разный.

Попробуйте тест. При изменении макросом событие не срабатывает.

economist

Одноименных полей лучше избегать. Данные поля: Имя, Значение, цепочка Parent - можно прочитать опять же, внешним макросом. В библиотеки Tools есть готовые макросы:

GetControlModel
GetControlView
GetControlShape

Они ищут по имени объект в любом из трех представлений Model, View, Controller.

Есть запасной путь для запуска макросов событий без самих событий - Listner, но он сложнее и делает систему тормознее.
Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...

sokol92

Подобный вопрос несколько дней назад обсуждался здесь.
Резюме: добавить связанную ячейку (Linked cell) к элементу управления и установить слушатель  XModifyListener на эту ячейку. Указанный слушатель "поймает" и изменения значения ячейки, внесенные макросом.
Владимир.

Kadet

Цитата: economist от  7 августа 2021, 13:50Одноименных полей лучше избегать.
Иногда это весьма удобно.

Т.е., предлагаете собрать oEvent из подручных материалов. Не представляю как.

mikekaganski

Цитата: Kadet от  7 августа 2021, 13:34Всё дело в oEvent, который должен зайти в этот макрос и который должен содержать данные именно этого поля: Имя, Значение, цепочка Parent.
А так как этот макрос повешен на многие поля, некоторые из которых даже одноимённые, то и oEvent у них будет разный.

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

Kadet

#7
Цитата: sokol92 от  7 августа 2021, 14:11Резюме: добавить связанную ячейку (Linked cell) к элементу управления и установить слушатель
Не вариант. Использую calc как демку, для простоты.

На самом деле поля, которые нужно менять, являются частью БД, а изменение полей ведётся посредством диалогового окна.

Есть подозрения, что за всю эту кухню могут отвечать следующие методы полей:
SbxVOID entryChanged ( SbxOBJECT )
SbxVOID entryRangeInserted ( SbxOBJECT )
SbxVOID entryRangeRemoved ( SbxOBJECT )
SbxVOID allEntriesChanged ( SbxOBJECT )
SbxVOID setListEntrySource ( SbxOBJECT )
SbxOBJECT getListEntrySource ( void )

В особенности, весьма похож первый метод - entryChanged , но он требует аргумента, типа - com.sun.star.form.binding.ListEntryEvent. Что за объект и как его получить пока не разобрался.

Kadet

#8
Цитата: mikekaganski от  7 августа 2021, 14:16Да не делается так. Ваш обработчик события должен брать событие, вытаскивать из него сведения, и вызывать отдельный метод, который уже принимает эти данные как отдельные аргументы. А когда нужно, вызываете тот же метод с отдельными аргументами, а не пытаетесь сформировать событие.
Пробовал. НО...

Как бы, так понятней и проще?

Есть несколько субформ в форме БД. Многие поля в этих субформах - перехлёстываются. Именно эти поля имеют одинаковое имя, потому что должны иметь одинаковые значения (поэтому и удобно использовать одноимённые поля). Макрос, который я копаю, вылавливает изменения в подобных полях, и по имени (которое одинаковое в разных субформах) устанавливает ВСЕМ подобным полям, во всех субформах одинаковое значение. Ну, так же делает много всякой всячены, типа открывает и закрывает доступы к другим, связанным полям.

Именно для этих целей удобно использовать oEvent, потому что не известно из какой формы и какого поля будет вызван макрос.

Так же oEvent используется для получения значения передаваемого из этого поля другим полям. И свести из к одной одинаковой переменной, которая "после обработки" будет передаваться макросу не получается, потому что макрос меняет и чекбоксы, значение которых boolean, и числовые поля, и даже списки.

Не представляю. как всё это можно свести к одной переменной, которую нужно передавать макросу.

В общем oEvent в этом случает наиболее удобен, так как закрывает все эти дыры.

Kadet

Тогда проще просто написать дубляжный кусок этого макроса, который можно будет использовать при вызове его извне, а не по событию поля. Это всё усложняет, но если другого пути нет, то... придётся.

Kadet

#10
В общем, долго объяснять. Легче показать.

Допустим есть поле-чекбокс "cbВорота1". Оно параллелится сразу в трёх субформах и во всех трёх должно иметь одинаковое значение, вне зависимости от того в какой из субформ происходили манипуляции с ним. При изменении этого поля в ЛЮБОЙ из трёх субформ, происходит следующее.
Sub SetParam(oEvent)
Dim oForms, oForm, sName
'******************************************
oForms = oEvent.Source.getModel().getParent().getParent()
sName = oEvent.Source.getModel().Name
'******************************************
Select Case sName
Case "cbВорота1"
oForm = oForms.getByName("ТОРЕЦ")
oForm.getByName("cbВорота1").State = oEvent.Source.State
oForm = oForms.getByName("ВОРОТА")
oForm.getByName("cbВорота1").State = oEvent.Source.State
oForm = oForms.getByName("ОБЩИЕ")
oForm.getByName("cbВорота1").State = oEvent.Source.State
End Select
End Sub


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

Для списков, текстовых полей, цифровых код немного отличается, потому как у них нет метода - oEvent.Source.State.

Вот почему это для меня очень удобно использовать oEvent. И не хочу это сильно менять.

Kadet

Не правильно аргументировал. Передать переменной можно всё, что угодно. Проблемы возникают при получении значений в эту переменную. Ведь в разных типах полей по-разному берутся их значения. Всё равно проверку на тип поля с перечислением всех возможных вариантов сделать не проще, чем замутить с дублирующим макросом.

Kadet

#12
Решил проблему по принципу mikekaganski. Однако передаю не сведения как аргументы, а всё сработавшее поле как объект целиком.
Пришлось вклинить между срабатывающим полем и исполняемым макросом ещё один макрос, который получает из oEvent объект поля и передаёт его исполняемому макросу. А там уже идёт обработка всех необходимых значений из самого поля.
Sub SetParam(oEvent)
SetEnabled(oEvent.Source.getModel())
End Sub

Sub SetEnabled(Odj as Object)
Dim oForms, oForm, sName, funType$
sName = Odj.Name
Select Case sName
...
...
...
End Sub


А когда вызываю макрос из диалогового окна тоже передаю объект нужного поля напрямую исполняемому макросу.

Всё, это, конечно хорошо, но как-то мне не понятно. Если есть какой-то метод, который может вызываться при ручной обработке поля, то должна же быть возможность управления этим методом программно. Ведь не Святой же Дух управляет этими событиями, а какие-то подпрограммы. "Ежели один человек построил, другой завсегда разобрать может". (к/ф "Формула Любви")
И я просто убеждён, что эти механизмы есть, управлять событиями программно, только ещё до них не докопались.