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

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

22 Ноябрь 2017, 08:17 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
Новости: Доступно и просто о работе в офисных пакетах
 
   Начало   Помощь Поиск Войти Регистрация    задать вопрос  
Страниц: 1   Вниз
  Печать  
Автор Тема: [Решено] Программное изменение регистра  (Прочитано 859 раз)
0 Пользователей и 1 Гость смотрят эту тему.
bsi
Новичок
*
Offline Offline

Сообщений: 41


« Стартовое сообщение: 29 Январь 2017, 12:06 »

Привет форумчане. Прошу досказать как переделать код из VBA для LO, если конечно у вас есть свободное время.
Код:
Sub Proper_Case()
   'Первые буквы в верхний регистр
   For Each x In Range("A1:A5")
      x.Value = Application.Proper(x.Value)
   Next
End Sub
и
Код:
Sub Uppercase()
   'Все в верхний регистр
   For Each x In Range("B1:B5")
      x.Value = UCase(x.Value)
   Next
End Sub
.
Всем спасибо.
« Последнее редактирование: 25 Февраль 2017, 17:49 от bsi » Записан
JohnSUN
Капитана в тот день называли на "ты"
Гуру
*******
Offline Offline

Пол: Мужской
Расположение: Киев
Сообщений: 2 359


Помогаю людям и компьютерам понимать друг друга


WWW
« Ответ #1: 29 Январь 2017, 13:14 »

Ну, в этом бэйсике нужно будет написать немного больше:

Код:
Sub ChangeCase(Optional typeCase As String, Optional sRange As String, Optional sheetName As String)
' Изменить регистр в указанном диапазоне
' typeCase - название применяемой функции Calc: "LOWER","UPPER","PROPER"
' (Если очень уж захочется, то можно и "TRIM" или "CLEAN" или любую другую функцию,
' в которой используется только один параметр).  По умолчанию применяется функция "Первые буквы - Заглавные"
' sRange - адрес диапазона для обработки. Если не указан - все ячейки на листе
' sheetName - имя листа для обработки. Если не указано - текущий, активный лист
Dim oFuncAcc As Variant
Dim oSheet As Variant
Dim oRange As Variant
Dim oDataArr As Variant
Dim oData As Variant
Dim i As Long, j As Long
On Error Resume Next ' Ошибки в параметрах могут вызвать ошибки времени выполнения
If IsMissing(typeCase) Then typeCase = "Proper"

If IsMissing(sheetName) Then ' Если имя листа не указано, использовать текущий лист
    oSheet = ThisComponent.getCurrentController().getActiveSheet()
Else ' В противном случае попытаться получить лист по имени
oSheet = ThisComponent.getSheets().getByName(sheetName)
EndIf
' Если листа с указанным именем нет или макрос запущен вообще не из Calc - нечего здесь больше делать
If IsEmpty(oSheet) Or IsNull(oSheet) Then Exit Sub

' Пытаемся получить указанный диапазон ячеек:
If IsMissing(sRange) Then ' Диапазон ячеек указан? Нет.
    oRange = oSheet.createCursor()
    oRange.gotoEndOfUsedArea(True)
    Else ' Какая-то строка есть, попытаемся получить указанные ячейки
    oRange = oSheet.getCellRangeByName(sRange)
    EndIf
If IsEmpty(oRange) Or IsNull(oRange) Then Exit Sub
' Данные из всех этих ячеек считываем во временный массив: 
  oDataArr = oRange.getDataArray()
' Вот так в OOo/AOO/LiO обращаются к встроенным функциям:
oFuncAcc = CreateUNOService("com.sun.star.sheet.FunctionAccess")

' Перебираем все ячейки:
For i = LBound(oDataArr) To UBound(oDataArr) ' Все данные по строкам
oData = oDataArr(i) ' Одна строка
For j = LBound(oData) To UBound(oData) ' По каждой ячейке строки
' If Trim(oData(j)) <> "" Then ' Вызов
oData(j) = oFuncAcc.callFunction(typeCase, Array(oData(j)))
' В случае ошибки при обработке любой из ячеек - исходные данные менять не станем
  If Err <> 0 Then Exit Sub
Next j
oDataArr(i) = oData ' Возвращаем обработанную строку обратно в общий массив
Next i
    oRange.setDataArray(oDataArr) ' Записываем обработанные значения на то же самое место
End Sub

 И теперь - твои две процедуры будут выглядеть так
Код:
Sub Proper_Case()
   'Первые буквы в верхний регистр
    ChangeCase("Proper", "A1:A5")
End Sub

Sub Uppercase()
   'Все в верхний регистр
   ChangeCase("UPPER", "B1:B5")
End Sub
Записан

Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне
bsi
Новичок
*
Offline Offline

Сообщений: 41


« Ответ #2: 29 Январь 2017, 13:36 »

Спасибо вам, как всегда быстрый ответ. Надо разобраться что к чему, а то я только-только начинаю врубаться в LO.
Записан
bsi
Новичок
*
Offline Offline

Сообщений: 41


« Ответ #3: 29 Январь 2017, 16:23 »

Прошу пояснить что я делаю не так. Поместил Ваш код в модуль. На событие листа "Содержимое изменено" ставлю макрос ChangeCase, выдает ошибку " Неверное значение свойства". Файл во вложении. LO 5.2.3.3.

* Изменение регистра.ods (12.61 Кб - загружено 4 раз.)
Записан
JohnSUN
Капитана в тот день называли на "ты"
Гуру
*******
Offline Offline

Пол: Мужской
Расположение: Киев
Сообщений: 2 359


Помогаю людям и компьютерам понимать друг друга


WWW
« Ответ #4: 29 Январь 2017, 17:33 »

У макросов, которые должны обрабатывать события, обычно есть один обязательный параметр - его принято обозначать oEvent As Variant. Через него офис передает в макрос сведения о самом событии. Для события листа "Содержимое изменено" в этом oEvent будет изменившийся диапазон ячеек.
А у ChangeCase три строковых параметра, и ни один из них не подходит под ожидаемый тип Variant.

Просто в твоем первом примере были жестко заданы диапазоны обрабатываемых ячеек - "A1:A5", "B1:B5". Это предполагало, что макрос должен вызываться для всего диапазона, то ли кнопкой, то ли горячей клавишей, то ли через Макрос-Выполнить - вот я и предложил вариант "вообще", который обрабатывал бы заранее известный диапазон ячеек.
Если же ты хочешь обрабатывать ячейки по событию, когда заранее неизвестно для какой из ячеек (или диапазона ячеек) макрос был вызван, то код будет выглядеть немного иначе.
Код:
' Обработать событие листа "Содержимое изменено"
Sub onChange(oEvent As Variant)
Dim oFuncAcc As Variant
Dim i&, j&
oFuncAcc = CreateUNOService("com.sun.star.sheet.FunctionAccess")
If oEvent.ImplementationName = "ScCellObj" Then ' Событие вызвано для одной ячейки
' Адрес этой ячейки oEvent.CellAddress. В какой колонке находится изменившаяся ячейка?
Select Case oEvent.CellAddress.Column
Case 0 ' Колонка A - значение меняем с помощью функции Proper
oEvent.setString(oFuncAcc.callFunction("Proper", Array(oEvent.getString())))
Case 1 ' Колонка B - значение меняем с помощью функции Upper
oEvent.setString(oFuncAcc.callFunction("Upper", Array(oEvent.getString())))
' ... здесь могут быть другие Case для других колонок
Case Else
' Что-то сделать для ячеек из всех остальных колонок. Мы ничего делать не будем
    End Select
Else ' Не одна-единственная ячейка? Значит, целый диапазон. Обработаем каждую ячейку диапазона отдельно
For i = 0 To oEvent.getColumns().getCount()-1
For j = 0 To oEvent.getRows().getCount()-1
onChange(oEvent.getCellByPosition(i, j)) ' То есть вызываем ту же самую обработку события,
' но не для всего диапазона, а для каждой из его ячеек
' Эту часть можно было бы улучшить, если предварительно выбрать из oEvent ячейки,
' которые действительно нужно обрабатывать, чтобы не вызывать процедуру вхолостую
Next j
Next i
EndIf
End Sub
Записан

Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне
bsi
Новичок
*
Offline Offline

Сообщений: 41


« Ответ #5: 29 Январь 2017, 17:41 »

Мир не без добрых людей !  Всё хорошо Огромное спасибо. Все работает.
Записан
bsi
Новичок
*
Offline Offline

Сообщений: 41


« Ответ #6: 30 Январь 2017, 10:38 »

Еще раз спасибо за участие в моей проблеме, но и этот вариант надо править. Необходимо чтобы макрос срабатывал на событие листа, но в определенном диапазоне ячеек. В конкретном случае в В6:В27 и F6:F27. Файл во вложении.

* Документ проба.ods (16.03 Кб - загружено 3 раз.)
« Последнее редактирование: 30 Январь 2017, 12:17 от bsi » Записан
rami
Гуру
*******
Offline Offline

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


MacBook Pro, LibreOffice и Apache OpenOffice


« Ответ #7: 30 Январь 2017, 11:59 »

Необходимо чтобы макрос срабатывал на событие листа, но в определенном диапазоне ячеек. В конкретном случае в В6:В27 и F6:F27.
JohnSUN дал вам развёрнутый ответ для разных вариантов, но под конкретные условия лучше отсечь не используемые варианты. Как вам такой вариант:
Код:
Sub onChange(oEvent As Variant)
Dim oFuncAcc As Variant
oFuncAcc=CreateUNOService("com.sun.star.sheet.FunctionAccess")
If oEvent.ImplementationName = "ScCellObj" Then ' Событие вызвано для одной ячейки
'если номер строки ячейки меньше 5 или больше 26 выходим из процедуры
If oEvent.CellAddress.Row<5 Or oEvent.CellAddress.Row>26 Then Exit Sub
' Адрес этой ячейки oEvent.CellAddress. В какой колонке находится изменившаяся ячейка?
Select Case oEvent.CellAddress.Column
Case 1 ' Колонка B - значение меняем с помощью функции Upper
oEvent.setString(oFuncAcc.callFunction("Upper", Array(oEvent.getString())))
Case 5 ' Колонка F - значение меняем с помощью функции Proper
oEvent.setString(oFuncAcc.callFunction("Proper", Array(oEvent.getString())))
' ... здесь могут быть другие Case для других колонок
   End Select
EndIf
End Sub
Записан

bsi
Новичок
*
Offline Offline

Сообщений: 41


« Ответ #8: 30 Январь 2017, 12:11 »

Цитата:
Как вам такой вариант:
.
Отлично !  Веселый
Записан
Страниц: 1   Вверх
  Печать  
 
Перейти в:  

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