Calc Conditional Format: Duplicate

Автор eeigor, 17 февраля 2022, 08:06

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

eeigor

Путаница возникает сразу, ибо есть 2 константы (используем вторую):
   com.sun.star.sheet.ConditionFormatOperator.DUPLICATE  '=8
   com.sun.star.sheet.ConditionOperator2.DUPLICATE  '=10

Определение условного формата диапазона (ConditionalEntry -> ScTableConditionalFormat) содержит как свойство Operator, так и свойство ConditionOperator.
Вопрос вызван тем, что присвоение константы DUPLICATE срабатывает, если её присвоить свойству Operator, в том время как результат записывается в свойство ConditionOperator, а напрямую не работает, но и ошибки не выдаёт.
Не работает (присвоение не выполняется):
   args(2).Name = "ConditionOperator"
   args(2).Value = com.sun.star.sheet.ConditionOperator2.DUPLICATE  '=10
Работает:
   args(2).Name = "Operator"
   args(2).Value = com.sun.star.sheet.ConditionOperator2.DUPLICATE  '=10

Но мы можем закомментировать строки выше, сначала добавить условный формат (не определённый до конца; получит индекс 0 и имя "Entry0" по умолчанию), а потом доприсвоить недостающее:
   'args(2).Name = "Operator"
   'args(2).Value = com.sun.star.sheet.ConditionOperator2.DUPLICATE  '=10
   oCondFmt.addNew(args)
   oCondFmt(0).ConditionOperator = 10
   Print oCondFmt(0).ConditionOperator  '->10
На сей раз мы записываем значение туда, куда нужно по смыслу: ConditionOperator.

Это так должно быть или это ошибка? И почему существуют 2 константы (столь похожие, но такие разные)?

Demo Code
    Dim oSheet As Object, oRange As Object
   Dim args(2) As New com.sun.star.beans.PropertyValue  'an array of conditional format property values
   Dim oCondFmt As Object  ': oCondFmt = CreateUnoService("com.sun.star.sheet.TableConditionalFormat")
   Dim source As New com.sun.star.table.CellAddress

   <...>
   oCondFmt = oRange.ConditionalFormat

   If oCondFmt.Count = 0 Then
       args(0).Name = "StyleName"
       args(0).Value = "Warning"

       With source: .Sheet = oSheet.RangeAddress.Sheet
           .Column = 0
           .Row = 0
       End With
       args(1).Name = "SourcePosition"
       args(1).Value = source

       args(2).Name = "Operator"  'ConditionOperator
       args(2).Value = com.sun.star.sheet.ConditionOperator2.DUPLICATE  '=10

       oCondFmt.addNew(args)

       'oCondFmt(0).ConditionOperator = 10
       Print oCondFmt(0).ConditionOperator  '->10

       oRange.ConditionalFormat = oCondFmt
   End If

Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

mikekaganski

Это просто история развития условного форматирования.
В момент начального открытия кода условное форматирование было представлено интерфейсом XSheetCondition, который представлял свойство Operator, реализованное с использованием get/set-методов. Это свойство имело тип enum com::sun::star::sheet::ConditionOperator - то есть перечисление. Это, к сожалению, значит, что такое свойство нельзя расширять - набор констант enum, являясь частью API, фиксирован.

В 2011 году была добавлена поддержка условия DUPLICATE, имевшегося в XLSX. Это потребовало расширения интерфейса - и поскольку расширить XSheetCondition нельзя, это делается созданием нового интерфейса: XSheetCondition2. Он включает в себя старый, а также предоставляет новые методы, в т.ч. свойство ConditionOperator, также реализованное посредством get/set. Это свойство на этот раз имеет тип простого целого 32-разрядного числа, а возможные значения - это группа констант ConditionOperator2. Такую группу констант всегда можно дополнить, поскольку они просто перечислены в общем пространстве имён, а не составляют отдельный тип.
А в 2015 было очередное расширение API для поддержки пользовательских выражений (формул), градиентов, наборов значков и т.п. И я не знаю почему, но на этот раз не стали расширять набор констант ConditionOperator2, а ввели новое свойство для сервиса ConditionFormatEntry, реализованное на этот раз с помощью XPropertySet. Вероятно, просто потому, что остальные свойства, нужные для реализации такого функционала, всё равно необходимо было реализовывать через XPropertySet (чтобы иметь возможность запрашивать наличие свойства у конкретного объекта), и для унификации всё сделали через него - а старые get/set*Operator реализовали через конвертацию из нового свойства.

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

eeigor

#2
Михаил, добрый день! Спасибо за развёрнутый ответ и потраченное время. К сожалению, кмк, проделать такую работу могут, увы, не все (если не Вы один на этом форуме).
Даже Ваш ответ мне пришлось перечитать несколько раз, и я ещё вернусь к нему, чтобы пройти по всем предоставленным Вами ссылкам.
Вы правы, конечно... Но будем надеяться, что и мои "исследования" (тут в кавычках) тоже несут какую-то полезную нагрузку (извещают, предостерегают и т. п.). Now I can see farther because I stand on the shoulders of giants.  :)
Спасибо!
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

mikekaganski

Цитата: eeigor от 17 февраля 2022, 09:48проделать такую работу могут, увы, не все

Я был бы рад помочь с конкретными вопросами типа "как найти историю конкретной строки" или "конкретного свойства" - тогда можно было бы вместе пройти по инструментарию, и это было бы не рыбой, но удочкой ;)
С уважением,
Михаил Каганский

eeigor

Да, но правильно поставить вопрос, это значит на 50% решить задачу. Видимо, я отстоял дальше от этого решения.
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

sokol92

Спасибо Игорю за вопрос, а Михаилу за ответ!  :)
Владимир.