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

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

6 Март 2021, 01:47 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
Новости: Здесь можно поблагодарить участников форума Улыбка
 
   Начало   Помощь Поиск Войти Регистрация    задать вопрос  
Страниц: « 1 2 3 »   Вниз
  Печать  
Автор Тема: Выделение определенного слова, состояние ячеек  (Прочитано 1280 раз)
0 Пользователей и 1 Гость смотрят эту тему.
eeigor
Ubuntu 18.04 LTS • LO 7.0.2.2
Форумчанин
***
Offline Offline

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



« Ответ #15: 21 Январь 2021, 23:19 »

Ну, тогда ждём ответы на поставленные здесь вопросы от других участников. Может, я чего-то не нашёл...

кроме InStr() я не знаю, что может его вернуть
И будет ли оно работать с регулярными выражениями?
« Последнее редактирование: 21 Январь 2021, 23:21 от eeigor » Записан
eeigor
Ubuntu 18.04 LTS • LO 7.0.2.2
Форумчанин
***
Offline Offline

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



« Ответ #16: 21 Январь 2021, 23:49 »

Уже теплее... Приглядитесь. Пока не всё понятно, но аналогия с упомянутом выше кодом прослеживается.
И вот с чем надо работать:
 com.sun.star.util.TextSearch Информации почти нет.
 com.sun.star.util.SearchOptions

The .FindFirst finds all cells in the spreadsheet that contain SearchString. If you want to search within the string, then you need com.sun.star.util.TextSearch.
Код:
Sub getMktValue()
  Dim oDoc as Object
  Dim oSheet as Object
  Dim oCell as Object

  oDoc = ThisComponent
  oSheet = oDoc.Sheets.getByName("Income")
  'regex test code'
  oCell = oSheet.getCellByPosition(0, 1)
  stk = oCell.getString()

  oTextSearch = CreateUnoService("com.sun.star.util.TextSearch")
  oOptions = CreateUnoStruct("com.sun.star.util.SearchOptions")
  oOptions.algorithmType = com.sun.star.util.SearchAlgorithms.REGEXP
  oOptions.searchString = "\((.*)\)"
  oTextSearch.setOptions(oOptions)
  oFound = oTextSearch.searchForward(stk, 0, Len(stk))
  sFound = mid(stk, oFound.startOffset(0) + 1, oFound.endOffset(0) - oFound.startOffset(0))
  MsgBox sFound
  sFound = mid(stk, oFound.startOffset(1) + 1, oFound.endOffset(1) - oFound.startOffset(1))
  MsgBox sFound
End Sub

Да, совершенно неожиданно. UNO-сервисы и структуры вместо объектов. И самому хоть с Xray, хоть с MRI никогда не догадаться. Но у меня сейчас уже нет времени. Если кто-то реализует ту самую функцию REGEX_SELECT в первом приближении, поделитесь. Доведём до ума вместе.

https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1util_1_1XTextSearch.html#a8e62cf8b8b7cee9c8d2907cb4aad2fc5
« Последнее редактирование: 22 Январь 2021, 00:09 от eeigor » Записан
eeigor
Ubuntu 18.04 LTS • LO 7.0.2.2
Форумчанин
***
Offline Offline

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



« Ответ #17: 22 Январь 2021, 00:21 »

Function REGEX_SELECT(TextRange, Pattern, Flags) As Integer
Дополнение по поводу третьего параметра Flags...
Ну, не все, может, но есть и полезные. Один: ALL_IGNORE_CASE, то бишь i.

UPD:
Я искал ещё хотя бы флаги типа: m - multiline, g - global. Первый настраивает поиск в многострочном тексте (а такие данные вполне могут быть в ячейке), а второй возвращает все совпадения, иначе - только первое. Тут не нашел. Хотя в формуле листа REGEX значится флаг g.
Собственно говоря, судя по примеру выше, мы идем по тексту ячейки по принципу функции InStr(), но с использованием regex.

UPD2:
Код выше в примере #16 работает отлично. Дело стало за малым.
« Последнее редактирование: 22 Январь 2021, 00:50 от eeigor » Записан
eeigor
Ubuntu 18.04 LTS • LO 7.0.2.2
Форумчанин
***
Offline Offline

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



« Ответ #18: 22 Январь 2021, 01:04 »

Ещё одно подтверждение правильности этого решения:
"Fine. This will often be better than to call REGEX with a FunctionAccess object. You know a way."
Записан
eeigor
Ubuntu 18.04 LTS • LO 7.0.2.2
Форумчанин
***
Offline Offline

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



« Ответ #19: 22 Январь 2021, 11:06 »

И если кто-то пишет REGEX_SELECT, то можно было бы и создать отдельное расширение:

REGEX_MATCH – тут
надо добавить ещё один аргумент на предпоследнюю позицию: что-то типа matchIndex,
где 0 – вся строка (default), 1..n – номер совпадения. Штатная функция этого не делает.

REGEX_SPLIT – для расщепления строки по регэкспу. Возвращает массив.

Чтобы не хуже, чем в Python… Улыбка

UPD:
Соответственно, штатная функция не позволяет проводить замену конкретных вхождений (по индексу/номеру):
REGEX_REPLACE

Но, может, всё это и не так нужно…

« Последнее редактирование: 22 Январь 2021, 13:35 от eeigor » Записан
W1nterdreams
Участник
**
Offline Offline

Сообщений: 20


« Ответ #20: 22 Январь 2021, 11:53 »

Оказывается, всё очень сложно...
Да, мне и правда нужно изменять шрифт не в выделенном тексте, а как бы отслеживать ввод.
Скажем в ячейке текст "всё очень сложно"
Отдельно выделить слово "всё" - красным, слово "очень" синим и слово "сложно" коричневым
В файле 2500 строк и по этим словам планируется отслеживать категорию. В writere это реализовано через простое выделение цветом указанного текста, ячейку целиком выделять - получается слишком пёстро
Записан
eeigor
Ubuntu 18.04 LTS • LO 7.0.2.2
Форумчанин
***
Offline Offline

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



« Ответ #21: 22 Январь 2021, 12:30 »

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

UPD:
Категории отслеживают не по плохо формализованному тексту, а по значениям поля «Категория», где значение – величина атомарная, то бишь неделимая (в крайнем случае – список с разделителями). И тогда всё это будет не нужно!!
Но мы здесь решаем и немножко свои задачи, и вашу по ходу дела…
« Последнее редактирование: 22 Январь 2021, 12:42 от eeigor » Записан
economist
Форумчанин
***
Offline Offline

Сообщений: 1 394


« Ответ #22: 22 Январь 2021, 12:37 »

W1nterdreams - многие хотелки так и не выбиваются в хорошие решения, если идут по порочному кругу недосказанности. Сначала вроде нужно что-то "просто выделить цветом", а потом выясняется что "зеленое" нужно просуммировать и вычесть из "красного" и поставить в отдельном листе, в виде отчета.  

Разбейте вашу строку на части - по столбцам, и вообще - изложите задачу целиком.

Что значит отслеживать? Глазами искать коричневые строки? Спецы по юзабилити вообще называют цвет - врагом точности. Это неспроста, проведены исследования, что лучше.  

Может стоит не цвет, а четкие критерии, словами, в отдельном столбце? В этом случае простая Сводная таблица на отд. листе позволит и отслеживать статусы/состояния/проблемы и будет сама же служить отчетом. Самообновляемым.
Записан

Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...
eeigor
Ubuntu 18.04 LTS • LO 7.0.2.2
Форумчанин
***
Offline Offline

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



« Ответ #23: 22 Январь 2021, 12:51 »

Согласен с @economist. Непонятно вообще, о каких данных идёт речь. И знает ли автор о правилах нормализации данных (хотя бы трёх формах из пяти), и можно ли с имеющимися данными что-то сделать (??).
Сводная таблица – супер, но это требует избыточности в данных (таблица – записи), чего пользователи не любят… А избыточность приводит к ошибкам ввода данных. Это уже вопросы разработки приложений.
Как минимум, надо избавиться от повторяющихся групп (1 форма нормализации)


https://yandex.ru/turbo/ru.wikipedia.org/s/wiki/Нормальная_форма
« Последнее редактирование: 22 Январь 2021, 12:56 от eeigor » Записан
W1nterdreams
Участник
**
Offline Offline

Сообщений: 20


« Ответ #24: 22 Январь 2021, 13:53 »

Извините, если чем изложил задачу не так...
Задача состоит в создании таблицы для учета людей.
И проблема в том, что категорий получается слишком много, это раз, два - часть процесса так или иначе останется в ручном управлении из-за того что она тесно связана с дальнейшей обработкой информации в другом документе writera...оттого, слишком много столбцов, за которыми придется следить вручную так или иначе.
С помощью трёх слов будут отслеживаться вакантные должности, занятые должности и временно замещающие должность.
Я понимаю, что не текстовый редактор, но с учётом того, что до этого момента вся работа велась через writer  и полностью вручную, я хоть как то пытаюсь автоматизировать процесс.
Я понимаю так же, что это форум, и что вы лишь помогаете, при наличии своего времени и желания. И простите мне мою неточность в формулировке проблемы, ещё раз.
Я не знаю, принято или возможно ли на этом форме так делать, но знаю, что чужое время стоит вознаграждения, которое я готов оплатить
Записан
sokol92
Форумчанин
***
Offline Offline

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


WWW
« Ответ #25: 22 Январь 2021, 16:48 »

Можно так. Пример использования в макросе TestRangeTextsColor.

Код:
Option Compatible
' Раскрашивает различными цветами фрагменты текстов в ячейке.
' - oCell ячейка.
' - aTexts массив фрагментов текстов.
' - entireWords Если True, то раскрашивать только целые слова, иначе фрагменты.
' - aColors массив цветов (той же размерности, что aTexts).
' - matchCase False:происводить поиск слов без учета регистра букв, True - с учетом регистра.
'
Sub CellTextsColor(ByVal oCell, ByVal aTexts, ByVal aColors, Optional Byval entireWords as Boolean, Optional ByVal matchCase As Boolean)
  Dim oTextCursor, i As Long, j as Long, j0 as Long, i0 as String, s As String, bFound As Boolean
 
  If IsMissing(matchCase) Then matchCase=False
  If IsMissing(entireWords) Then entireWords=False
 
  oTextCursor=oCell.createTextCursor()
  s=oCell.String
 
  For i=LBound(aTexts) To UBound(aTexts)
    j0=1
    Do While j0<=len(s)
      If matchCase Then
        j=Instr(j0, s, aTexts(i), 0)
      Else
        j=Instr(j0, lcase(s), lcase(aTexts(i)), 0) 
      End If
       
      If j>0 Then
        bFound=True
        If entireWords Then
          If j>1 Then 
            If Ucase(Mid(s, j-1, 1))<>lCase(Mid(s, j-1, 1)) Then bFound=False   ' слева от найденного текста - буква
          End If
          If j+Len(aTexts(i))<=Len(s) Then 
            If Ucase(Mid(s, j+Len(aTexts(i)), 1))<>lCase(Mid(s, j+Len(aTexts(i)), 1)) Then bFound=False   ' справа от найденного текста - буква
          End If
        End If
        If bFound Then
          With oTextCursor
            .gotoStart False
            .goRight j-1 , False 
            .goRight Len(aTexts(i)), True
            .CharColor=aColors(i)
          End With 
        End If
      Else
        Exit Do
      End If
     
      j0=j+Len(aTexts(i))
    Loop
  Next i
End Sub

' Раскрашивает различными цветами фрагменты текстов в диапазоне(диапазонах) ячеек.
' - oRange ячейка или диапазон ячеек
' - aTexts массив фрагментов текстов.
' - entireWords Если True, то раскрашивать только целые слова, иначе фрагменты.
' - aColors массив цветов (той же размерности, что aTexts).
' - matchCase False:происводить поиск слов без учета регистра букв, True - с учетом регистра.
'
Sub RangeTextsColor(ByVal oRange, ByVal aTexts, ByVal aColors, Optional Byval entireWords as Boolean, Optional ByVal matchCase As Boolean)
  Dim oCell
  If IsMissing(matchCase) Then matchCase=False
  If IsMissing(entireWords) Then entireWords=False
 
  If oRange.supportsService("com.sun.star.sheet.SheetCell") Then
    CellTextsColor oRange, aTexts, aColors, entireWords, matchCase
  Else
    For Each oCell In oRange.queryContentCells(com.sun.star.sheet.CellFlags.STRING).getCells
      CellTextsColor oCell, aTexts, aColors, entireWords, matchCase
    Next oCell 
  End If
End Sub

' Раскрашивает в выделенном фрагменте ячеек слова "все", "очень", "сложно".
Sub TestRangeTextsColor
   RangeTextsColor ThisComponent.CurrentSelection, Array("все", "очень", "сложно"), Array(RGB(255, 0, 0), RGB(0, 255, 0), RGB(0, 0, 255)),False
End Sub

« Последнее редактирование: 23 Январь 2021, 16:04 от sokol92 » Записан

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

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



« Ответ #26: 22 Январь 2021, 17:05 »

Узнаю sokol92 уже по стилю.  Улыбка
Кстати ваше решение по заполнению пустых, ранее выделенных произвольных ячеек, мне помогло, и я его использую. Спасибо.
Здесь же замечу одно. Реализован более «процедурный» способ поиска вхождений функцией InStr().
Я «настаивал» на использовании чего-то пошустрее… и нашёл.
Полагаю функция REGEX, диалог «Найти и заменить» с использованием регулярных выражений используют именно его (см. пример выше с TextSearch). Этот объект работает с подстроками, которые находит все сразу, а не в цикле по одной, и позволяет обращаться к ним по индексу.

oFound.startOffset(1)  'это не 1 символ, на который надо сместится (попробуй догадайся!), а номер вхождения (match index), и в примере выше ищется текст, заключённый в скобки, и он выводится в скобках, а затем выводится то, что захвачено в группу и имеет индекс 1. В тексте регэкспа мы бы сослались на эту группу так: \1
« Последнее редактирование: 22 Январь 2021, 17:20 от eeigor » Записан
sokol92
Форумчанин
***
Offline Offline

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


WWW
« Ответ #27: 22 Январь 2021, 17:11 »

Я пользуюсь сервисом TextSearch2. В данном случае Instr вполне достаточно.
Записан

Владимир.
W1nterdreams
Участник
**
Offline Offline

Сообщений: 20


« Ответ #28: 22 Январь 2021, 17:20 »

Спасибо, в принципе, практически всё что нужно он делает.
Можно ли его как нибудь привязать к моменту окончания редактирования ячейки. Я попробовал через привязку к событию это сделать, но там нет такого момента(
Записан
eeigor
Ubuntu 18.04 LTS • LO 7.0.2.2
Форумчанин
***
Offline Offline

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



« Ответ #29: 22 Январь 2021, 17:23 »

Да, можно. Событие листа «Содержание изменено» (или как-то так), щелчок правой кнопкой мыши по ярлыку листа, события… 
« Последнее редактирование: 22 Январь 2021, 17:25 от eeigor » Записан
Страниц: « 1 2 3 »   Вверх
  Печать  
 
Перейти в:  

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