Заблокировать работу с документом на время работы макроса

Автор ForumOOo (бот), 30 ноября 2016, 20:33

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

ForumOOo (бот)

Компонент: Basic
Версия продукта: 5.x
Сборка:
ОС:

Доброе время суток! Заблокировать работу с документом на время работы макроса. Как такое осуществить?
Cacl, LibreOffice Basic<br/><br/>--<br/>Подпись: Alex

JohnSUN

#1
Совсем недавно было в очередной раз
myDoc = ThisComponent
myDoc.lockControllers()
myDoc.addActionLock()
' --- modify your cells here ---
myDoc.removeActionLock()
myDoc.unlockControllers()
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

Alex16

#2
Цитата: JohnSUN от 30 ноября 2016, 18:45Совсем недавно было в очередной раз
Да это-то никуда от меня не делось. Но между этими строками, в момент когда код выполняется в месте, где строчка ' --- modify your cells here ---
мы(пользователь) можем менять значения в ячейках, ну и как бы полноценно работать в calk'е)

Хотелось бы, что б как-то было "заметно", что идет какая-то работа.... ну и что б пользователь своими шаловливыми руками ничего не делал в это время с документом.

JohnSUN

#3
Цитата: Alex16 от  1 декабря 2016, 09:01
Хотелось бы, что б как-то было "заметно", что идет какая-то работа.... ну и что б пользователь своими шаловливыми руками ничего не делал в это время с документом.
Две задачи - два решения
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

Alex16

#4
Цитата: JohnSUN от  1 декабря 2016, 09:51Две задачи - два решения
Интересные решения! Спасибо. Но для моего уровня пока сложновато(
И я не понял откуда вызывается LongWorkMacro2. И вот эта строка - "InitProgBar(1, 0, "") : HideProgBar", что это за двоеточие??

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

JohnSUN

#5
Цитата: Alex16 от  1 декабря 2016, 14:13
И я не понял откуда вызывается LongWorkMacro2.
Событие на кнопке уже в диалоговом окне
Цитата: Alex16 от  1 декабря 2016, 14:13
И вот эта строка - "InitProgBar(1, 0, "") : HideProgBar", что это за двоеточие??
Продолжение оператора, обычный синтаксис бэйсика - вообще-то это две строки кода, но поскольку они логически представляют единое целое ("Инициализировать прогресс-бар И скрыть его"), то есть смысл записать два действия в одну строку. Это позволит потом переносить оба оператора одной строкой вверх-вниз по коду и они не разорвутся, не потеряются. Для этого ставят двоеточие впритык к закончившемуся оператору и в той же строке через пробел пишут следующий. И так сколько нужно раз...
Цитата: Alex16 от  1 декабря 2016, 14:13
Но у меня появилось такое решение... Или это нельзя?
Можно, всё можно. Запрограммировать можно вообще всё что угодно. Но в случае, когда вычисления длятся настолько долго, что пользователь может успеть не только шевельнуть мышкой, но и даже изменить значения каких-то ячеек, лучше озаботиться не отображением прогресса, а оптимизацией алгоритма - очень многие программы начинают работать в десятки раз быстрее, если их переписать правильно
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

Alex16

#6
Цитата: JohnSUN от  1 декабря 2016, 13:31Событие на кнопке уже в диалоговом окне
Семён Семёныч... :) Как я мог об этом даже не подумать (
Цитата: JohnSUN от  1 декабря 2016, 13:31обычный синтаксис бэйсика
Тоже ведь знал об этом, но бэйсиком занимался почти 20 лет назад (потом перешел на делфи) ....забыл(
Цитата: JohnSUN от  1 декабря 2016, 13:31Можно, всё можно. Запрограммировать можно вообще всё что угодно.
Здесь я даже и не сомневаюсь)
Цитата: JohnSUN от  1 декабря 2016, 13:31лучше озаботиться не отображением прогресса, а оптимизацией алгоритма
Согласен на 100% В связи с этим, где-то тут не далеко, на днях и на этом форуме я где-то наткнулся на твой кому-то ответ, но в нем было только схемотично типа "на время работы макроса отключить протоколирование UnDo" - отсюда вопрос: Как это сделать? :)
UnDo - я так понял возврат-отмена действий. Я заметил, что после работы моих макросов очень много там записей, а они в общем-то не нужны, более того - вредны!

Alex16

Собс-но вон он этот "долгоиграющий" макрос:
Sub InsertSumsFormulsDATA(CountUsr%)
Dim N%, U%, C%, R%, ColumnSums%, MAX_ITERAC%
Dim oStatusIndicator As Variant
MAX_ITERAC = EndColRow - StartColRow
oStatusIndicator = ThisComponent.getCurrentController().getFrame().createStatusIndicator()
oStatusIndicator.start("Подготовка к работе...", MAX_ITERAC)
ColumnSums = CountUsr * ColumnCount
For N = StartColRow to EndColRow
  R = N - StartColRow + 1
  For C = 0 to ColumnCount - 1
    If CountUsr = 1 then
  Formuls = "=SUM(" & ColumnNumberToString(C) & R & ")"
    Else
      Formuls = "=SUM(" & ColumnNumberToString(C) & R
  For U = 1 to CountUsr - 2
Formuls = Formuls & ";" & ColumnNumberToString(U * ColumnCount + C) & R
  Next U
  Formuls = Formuls & ";" & ColumnNumberToString(U * ColumnCount + C) & R & ")"
    End IF
  shtData.GetCellByPosition(ColumnSums + C, N - StartColRow).Formula = Formuls
  Next C
  oStatusIndicator.setValue(N)
  oStatusIndicator.setText("Обработка услуги: " & N)
Next N
shtSystem.getCellByPosition(6,0).Value = 1
oStatusIndicator.end()
End Sub


StartColRow = 13
EndColRow = 187
ColumnCount = 10
CountUsr = 29

rami

#8
Цитата: Alex16 от  1 декабря 2016, 12:13Только нужно бы еще запретить закрытие окна. Или это нельзя?
Это просто, НО в этом случае закрыть окно можно будет только макросом, а не вручную. А если произойдёт какой-нибудь сбой в макросе, придётся "убивать" офис.

Alex16

Цитата: Alex16 от  1 декабря 2016, 13:46UnDo" - отсюда вопрос: Как это сделать?
Нашел:
   Thisreport.isUndoEnabled=False
   InsertSumsFormulsDATA(29)
   Thisreport.isUndoEnabled=True
Если это - это. то на скорость оно как-то не повлияло(

Alex16

Цитата: rami от  1 декабря 2016, 14:31Это просто, НО в этом случае закрыть окно можно будет только макросом, а не вручную. А если произойдёт какой-нибудь сбой в макросе, придётся "убивать" офис.
Понял, а тут нет конструкций типа try finally end?

JohnSUN

#11
Цитата: Alex16 от  1 декабря 2016, 15:55
Собс-но вон он этот "долгоиграющий" макрос:
И ты считаешь, что он не сможет работать быстрее?
Ну, попробуй, например, так:
Sub InsertSumsFormulsDATA(CountUsr%)
Dim N%, U%, C%, R%, ColumnSums%, MAX_ITERAC%, a%
Dim oStatusIndicator As Variant
MAX_ITERAC = EndColRow - StartColRow
oStatusIndicator = ThisComponent.getCurrentController().getFrame().createStatusIndicator()
oStatusIndicator.start("Подготовка к работе...", MAX_ITERAC)
ColumnSums = CountUsr * ColumnCount
oStartCell = shtData.getCellByPosition(ColumnSums, StartColRow)
If CountUsr = 1 Then
oStartCell.Formula = "=A1"
Else
Formuls = "=SUM(" & ColumnNumberToString(C) & "1"
For U = 1 to CountUsr - 1
Formuls = Formuls & ";" & ColumnNumberToString(U * ColumnCount + C) & "1"
Next U
Formuls = Formuls &  ")"
oStartCell.Formula = Formuls
EndIf
shtData.getCellRangeByPosition(ColumnSums, StartColRow, ColumnSums+ColumnCount, StartColRow).fillAuto(com.sun.star.sheet.FillDirection.TO_RIGHT, 1)
shtData.getCellRangeByPosition(ColumnSums, StartColRow, ColumnSums+ColumnCount, EndColRow).fillAuto(com.sun.star.sheet.FillDirection.TO_BOTTOM, 1)
shtSystem.getCellByPosition(6,0).Value = 1
oStatusIndicator.end() ' И зачем он был нужен?
End Sub

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

Alex16

Цитата: JohnSUN от  1 декабря 2016, 15:20Ну, попробуй, например, так:
Хитро ;). Раб день кончается, завтра попробую.
Но уже вижу:
Цитата: JohnSUN от  1 декабря 2016, 15:20oStatusIndicator.end()   ' И зачем он был нужен?
:)

Alex16

#13
Цитата: JohnSUN от  1 декабря 2016, 15:20не сможет работать быстрее?
Ну, попробуй, например, так:
Респект! Работает моментально. Чуть-чуть не те диапазоны, но немного подправил, и все отлично.
Вот уж действительно индикатор не нужен. Спасибо огромное!
Sub InsertSumsFormulsDATA(CountUsr%)
Dim U%, ColumnSums%
Dim oStartCell
ColumnSums = CountUsr * ColumnCount
oStartCell = shtData.getCellByPosition(ColumnSums, 0)
If CountUsr = 1 Then
oStartCell.Formula = "=A1"
Else
Formuls = "=SUM(A1"
For U = 1 to CountUsr - 1
Formuls = Formuls & ";" & ColumnNumberToString(U * ColumnCount) & "1"
Next U
Formuls = Formuls &  ")"
oStartCell.Formula = Formuls
EndIf
shtData.getCellRangeByPosition(ColumnSums, 0, ColumnSums+ColumnCount-1, 0).fillAuto(com.sun.star.sheet.FillDirection.TO_RIGHT, 1)
shtData.getCellRangeByPosition(ColumnSums, 0, ColumnSums+ColumnCount-1, EndColRow - StartColRow).fillAuto(com.sun.star.sheet.FillDirection.TO_BOTTOM, 1)
End Sub

Alex16

Даже еще проще получилось:
Sub InsertSumsFormulsDATA(CountUsr%)
Dim U%, ColumnSums%, oStartCell
ColumnSums = CountUsr * ColumnCount
oStartCell = shtData.getCellByPosition(ColumnSums, 0)
Formuls = "=SUM(A1"
For U = 1 to CountUsr - 1
Formuls = Formuls & ";" & ColumnNumberToString(U * ColumnCount) & "1"
Next U
Formuls = Formuls &  ")"
oStartCell.Formula = Formuls
shtData.getCellRangeByPosition(ColumnSums, 0, ColumnSums+ColumnCount-1, 0).fillAuto(com.sun.star.sheet.FillDirection.TO_RIGHT, 1)
shtData.getCellRangeByPosition(ColumnSums, 0, ColumnSums+ColumnCount-1, EndColRow - StartColRow).fillAuto(com.sun.star.sheet.FillDirection.TO_BOTTOM, 1)
End Sub