Работа с LibreOffice, как с Com-объектом

Автор Борис_С, 22 октября 2021, 17:15

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

mikekaganski

Цитата: Борис_С от  1 декабря 2021, 14:25Попробовал использовать метод getTypes и получил такой результат

Хм. Возможно, Вам нужно разобраться с основами используемого языка.
Эта строчка должны была выглядеть как-то так:
unoidl.com.sun.star.lang.XTypeProvider xTypeProvider = (unoidl.com.sun.star.lang.XTypeProvider)xCell;
unoidl.com.sun.star.uno.Type[] types = xTypeProvider.getTypes();
С уважением,
Михаил Каганский

Борис_С

Спасибо. С этим разобрался. Кстати, список типов получается так:

unoidl.com.sun.star.lang.XTypeProvider xTypeProvider =
         (unoidl.com.sun.star.lang.XTypeProvider)xCell;
System.Type[] types = xTypeProvider.getTypes();


Теперь другая проблема. Дошел до цикла получения гиперссылок:

oParEnum = oCell.getText().createEnumeration()
Do While oParEnum.hasMoreElements ()
    oElement = oParEnum.nextElement()
    If oElement.TextPortionType = "TextField" Then
       ...
    End If
Loop


У меня он выглядит так:

                    unoidl.com.sun.star.container.XEnumeration oParEnum = gText.createEnumeration();
                    while (oParEnum.hasMoreElements())
                    {
                            uno.Any oElement = oParEnum.nextElement();
                            unoidl.com.sun.star.lang.XTypeProvider xTypeProvider =
                                (unoidl.com.sun.star.lang.XTypeProvider)oElement;
                            System.Type[] types = xTypeProvider.getTypes();
                            //unoidl.com.sun.star.text.XText oElement1 =
                            //    (unoidl.com.sun.star.text.XText)oElement;
                            //if ((unoidl.com.sun.star.text.TextPortion)oElement.)
                    }


В API написано, что свойство TextPortionType можно получить только из интерфейса com::sun::star::text::TextPortion
у меня unoidl.com.sun.star.text.TextPortion. С# говорит, что такого интерфейса нет.
Попробовал получить список допустимых интерфейсов для объекта oElement.
С# говорит, что uno.Any не может быть преобразован в unoidl.com.sun.star.lang.XTypeProvider

mikekaganski

Ага. Тут Вы видите особенность, что в Basic uno.Any воспринимается как переменная типа Variant - и пользователю не требуется "доставать" оттуда значение, чтобы его использовать. В C++ потребовалось бы что-то типа

com.sun.star.lang.XTypeProvider xTypeProvider;
if (oElement >>= xTypeProvider)
{
    ...
}


Надо посмотреть в примерах, как с Any работают в C#. Смогу глянуть попозже.
С уважением,
Михаил Каганский

mikekaganski

Цитата: Борис_С от  1 декабря 2021, 16:55
У меня он выглядит так:

                    unoidl.com.sun.star.container.XEnumeration oParEnum = gText.createEnumeration();
                    while (oParEnum.hasMoreElements())
                    {
                            uno.Any oElement = oParEnum.nextElement();
                            unoidl.com.sun.star.lang.XTypeProvider xTypeProvider =
                                (unoidl.com.sun.star.lang.XTypeProvider)oElement;
                            System.Type[] types = xTypeProvider.getTypes();
                            //unoidl.com.sun.star.text.XText oElement1 =
                            //    (unoidl.com.sun.star.text.XText)oElement;
                            //if ((unoidl.com.sun.star.text.TextPortion)oElement.)
                    }


Попробуйте изменить его на такой манер (добавлено .Value):


                    unoidl.com.sun.star.container.XEnumeration oParEnum = gText.createEnumeration();
                    while (oParEnum.hasMoreElements())
                    {
                            uno.Any oElement = oParEnum.nextElement();
                            unoidl.com.sun.star.lang.XTypeProvider xTypeProvider =
                                (unoidl.com.sun.star.lang.XTypeProvider)oElement.Value;
                            System.Type[] types = xTypeProvider.getTypes();
                            //unoidl.com.sun.star.text.XText oElement1 =
                            //    (unoidl.com.sun.star.text.XText)oElement;
                            //if ((unoidl.com.sun.star.text.TextPortion)oElement.)
                    }
С уважением,
Михаил Каганский

Борис_С

Изменил. Теперь можно посмотреть доступные интерфейсы для oElement.Value,
но я по-прежнему не понимаю, как получить свойство TextPortionType объекта oElement

sokol92

MRI рисует такую конструкцию (конструкции Using опущены):
XTextRange xTextRange = (XTextRange) oElement.Value;
XPropertySet xPropSet = (XPropertySet)xTextRange;
String sTextPortionType = (String) xPropSet.getPropertyValue("TextPortionType").Value;

Владимир.

mikekaganski

Вообще MRI - чудесный инструмент. В ЛО появился встроенный инструмент для интроспекции, но у него ещё много недоработок (вот, например, две мои хотелки), так что MRI ещё долго будет незаменим.
С уважением,
Михаил Каганский

Борис_С

Написал такой код:

while (oParEnum.hasMoreElements())
{
     uno.Any oElement = oParEnum.nextElement();
     unoidl.com.sun.star.text.XTextRange xTextRange =
                 (unoidl.com.sun.star.text.XTextRange)oElement.Value;
     unoidl.com.sun.star.beans.XPropertySet xPropSet1 =
                 (unoidl.com.sun.star.beans.XPropertySet)xTextRange;
     String sTextPortionType =
                (String)xPropSet1.getPropertyValue("TextPortionType").Value;
}


На операторе

      String sTextPortionType =
                (String)xPropSet1.getPropertyValue("TextPortionType").Value;

возникает исключение Message = ""

sokol92

Пройдите этот путь вместе с MRI. Использование Using сокращает код и уменьшает число возможных опечаток.
Владимир.

sokol92

Михаил, а @Hanya отказался включить свое расширение в основной пакет, или ему никто не предлагал (если этот вопрос не выходит за рамки допустимого)?
Владимир.

mikekaganski

Владимир: я как-то предлагал ему хотя бы стать владельцем соответствующей страницы расширения, которую кто-то (не он) создал и забросил, и там непонятно какие не совместимые ни с чем версии. Но я не получил от него никакого отклика.
С уважением,
Михаил Каганский

sokol92

#26
Михаил, спасибо за ответ! Последний проект на Github Hanya изменял 29 дней назад, так что теоретические шансы на контакты остаются.

В модуле CSharp.py (дата изменения 19.11.2015) из расширения MRI есть строки, помеченные комментарием ToDo, так что, возможно, этот модуль до конца не доделан. Я сам не пишу программы на C#.
Владимир.

Борис_С

Владимир, я установил расширение MRI. Оно должно появиться в меню? Если да, то где и под каким названием?

Борис_С

Цитата: mikekaganski от  1 декабря 2021, 17:11Надо посмотреть в примерах, как с Any работают в C#. Смогу глянуть попозже.
Михаил, может вы подскажете, где можно посмотреть примеры работы С# с OpenOffice.

sokol92

#29
Для расширения MRI устанавливается библиотека Basic MRILib, подключив которую Вы можете вызывать макрос Mri c соответствующим параметром (параметр по умолчанию StarDesktop).

Мне показался более удобным другой способ вызова. Я записал в библиотеку Standard из MyMacros... следующую функцию:

Sub Mri(ByVal Optional MriTargetObject)
 On Error GoTo ErrHandler  
 If IsMissing( MriTargetObject ) Then MriTargetObject = StarDesktop
 CreateUnoService("mytools.Mri").inspect(MriTargetObject)
 Exit Sub
ErrHandler:
 Msgbox "Error: " & Error
End Sub


Плюс этого подхода - для вызова MRI не требуется никаких предварительных действий.
Чаще всего приходится начинать инспекцию с текущего документа, так что такой макрос
Sub CallMri
 Mri ThisComponent
End Sub


можно поместить в Standard и повесить на любую удобную горячую клавишу.

О работе с MRI см. ранее указанное видео.
Владимир.