Переменные уровня модуля и статические переменные не сохраняют значения

Автор eeigor, 8 марта 2022, 16:45

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

eeigor

В версии LO 7.3 почему-то не работает это всё... Что-то случилось? Просьба посмотреть у себя.

1) Использование переменной уровня модуля (Dim nCount%) не работает: с каждым запуском некоторой функции, добавляющей 1 к счётчику, переменная nCount заново инициализируется нулём и всегда равна 1.

2) Статическая переменная. В примере ниже счётчик тоже не растёт (всегда равен 42).

Sub ExampleStatic()
Dim i As Integer, nResult As Integer
For i = 0 To 2
nResult = InitVar()
Next
MsgBox nResult, 0, "Ответ"
End Sub

' Функция для инициализации статической переменной
Function InitVar() As Integer
Static nInit As Integer
Const MINIMUM As Integer = 40  'минимальное значение, возвращаемое этой функцией
if nInit = 0 Then  'проверка инициализации
nInit = MINIMUM
Else
nInit = nInit + 1
End If
InitVar = nInit
End Function


Version: 7.3.1.3 / LibreOffice Community
Build ID: eead5aec017556e2cdbf9dfff06537ec58969b73
CPU threads: 8; OS: Linux 5.4; UI render: default; VCL: gtk3
Locale: ru-RU (ru_RU.UTF-8); UI: en-US
Calc: threaded

Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

sokol92

Добрый день! У меня в Вашем примере функция ExampleStatic выдает 42, что верно.
Владимир.

eeigor

Добрый день!
Для первого вызова - да.
А потом:
Static nInit As Integer
nInit = nInit + 1

Счётчик должен прирастать.
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

sokol92

LO Basic отличен от VBA. Ваш вопрос подробнейшим образом описан в разделе 3.7 книги А.Питоньяка OOME_4_0.odt.

Если Вы хотите, чтобы значения переменных не "сбрасывались" после завершения работы макроса, то используйте описание Global.
Владимир.

eeigor

Посмотрю. Странно, конечно. Забыл-таки
Но статика не работает...
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

mikekaganski

Цитата: eeigor от  8 марта 2022, 18:21Но статика не работает...

Цитата: Andrew Pitonyak3.7.1 Local variables defined in a subroutine or function
...
Use the keyword Static to change a variable's creation and destruction times to the calling macro's start and finish times, respectively. Although the variable is visible only in the routine containing the variable, the variable is initialized once when the macro starts running, and the variable's values are retained through multiple calls to the same routine. In other words, you start with no macro running. The first time that a subroutine or function that contains a static variable is called, the static variables contain initial values based on their types. The static variables retain their values between calls as long as the macro as a whole did not stop running.
С уважением,
Михаил Каганский

eeigor

Владимир, Михаил, спасибо. Я всё понял. Ранее сталкивался с этим. Но вот опять "посчитал" такую ситуацию нелогичной и как будто забыл, что знал. Но в VBA с этим вопросом гораздо удобнее. Пример в стартовом сообщении работает, стало быть, правильно. Вот таким, я бы сказал "извращённым", способом надо использовать статические переменные в LO Basic. Увы.
Толку в операторе Static мало.
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

sokol92

Цитата: eeigor от  8 марта 2022, 18:56Толку в операторе Static мало.
Мы используем оператор Static в такого рода констукциях:
Option Compatible

' lang:ru
' Возвращает объект FunctionAccess.
Function oFA
  Static o
  If IsEmpty(o) Then
    o = createUnoService( "com.sun.star.sheet.FunctionAccess" )
  End If 
  oFA=o
End Function

Это может дать при многократном вызове этой функции в течение работы макроса ускорение в 10-ки раз.
Можно для подобных конструкций использовать и Global, однако, как пишет А.Питоньяк, Global переменные отовсюду видны (что может быть неудобно) и в ряде случаев тоже "сбрасываются".
Владимир.

eeigor

Владимир, так если, то всё здорово.
Однако, как понял, между вызовами значение статической переменной в LO Basic не сохраняется.
Ваш пример - это так, как в VBA. Или же сохраняется, если вашу функцию вызывает в цикле работающий внешний макрос. Тогда да.

Edit: Впрочем, достаточно создать обычную объектную переменную в вызывающем макросе и передать ее по ссылке (default is ByRef) в вызываемый, и необходимость в статической переменной, как в Вашем примере, отпадает.
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

sokol92

В LO Basic есть важное понятие "Моменты начала и окончания (работы) вызываемого макроса" (выделенное в цитате Михаила жирным шрифтом). Я выше привел пример для случая, когда Вы стартуете макрос, который от начала до окончания работы производит многократный вызов одной и той же функции. По завершению работы макроса все переменные уровня модуля (не Global) и Static "сбрасываются".
В VBA такие переменные "сбрасываются" только при сбросе (остановке) проекта.
Владимир.

eeigor

Цитата: sokol92 от  8 марта 2022, 20:40Моменты начала и окончания (работы) вызываемого макроса
В цитате Михаила "calling macro's start and finish times" - это вызывающий макрос.

Спасибо. Я со всем этим так или иначе сталкивался. Однако было не лишним ещё раз повторить этот материал.
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community