Глобальная переменная

Автор Alex16, 22 ноября 2016, 15:32

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

Alex16

Доброе время суток всем! Подскажите как сделать глобальную(для модуля) переменную?
Сделал так:
Объявление:
    Option Explicit
    Public LastUserID%

Использование:
Sub LoadRep(N as Integer)

  print LastUserID
..........
LastUserID = N
..........
  print LastUserID

End Sub


LoadRep вызывается по смене списка (ЛистБокс)
В сообщениях всегда первым показывается "0", вторым выбранный Номер Итема в списке.
Такое ощущение как будто LastUserID не глобальная....

Alex16

Я так понял, что я не правильно объявляю переменную:
Public LastUserID%

Если закомментировать, то все работает как надо, ну т.е. переменная сохраняет свое значение:
REM  *****  BASIC  *****
' Option Explicit
'    Public LastUserID%
   
Sub LoadRep(N as Integer)

  print LastUserID

LastUserID = N

  print LastUserID

End Sub

Sub Test
    LoadRep(RND*50)
End Sub

но мне нужен Option Explicit

rami

#2
Если правильно понял, то так:
REM  *****  BASIC  *****
Option Explicit
 
Sub LoadRep(N as Integer)
 print LastUserID

LastUserID = N

 print LastUserID

End Sub

Sub Test
Static LastUserID%        'переменная объявляется здесь, видна во всех макросах модуля и сохраняет значение до следующего изменения
   LoadRep(RND*50)
End Sub


Ошибся, переменную LastUserID% нужно объявлять как Global вне макроса, а не как Static :(

Alex16

Цитата: rami от 22 ноября 2016, 15:03Если правильно понял, то так:
Ну в общем-то да, результат - что нужно. Просто как-то неожиданно :) Глобальная переменная объявляется внутри подпрограммы.

rami

#4
Цитата: Alex16 от 22 ноября 2016, 17:13
Цитата: rami от 22 ноября 2016, 15:03Если правильно понял, то так:
Ну в общем-то да, результат - что нужно. Просто как-то неожиданно :) Глобальная переменная объявляется внутри подпрограммы.
А она не глобальная. Она видна во всех библиотеках и модулях только текущего документа.

Alex16

#5
Цитата: rami от 22 ноября 2016, 15:19А она не глобальная.
Как это не глобальная??? Она ж доступна из всех макросов модуля...
Глобальная для текущего документа :)

rami

Цитата: Alex16 от 22 ноября 2016, 15:26Как это не глобальная??? Она ж доступна из всех макросов модуля...
Глобальная, не глобальная — лишь бы здорова была ;D ;D ;D  Не будем ругаться за терминологию.

Переменная Static должна объявляться в процедуре, должна же она чем-то отличаться от Global и других.

Alex16

Цитата: rami от 22 ноября 2016, 15:44Не будем ругаться за терминологию.
Я даже не посмею этого сделать здесь :) Более того, отдельное и большущее Вам и всем на этом форуме - Спасибище! :)
Но в догонку у меня вопрос. Помимо этой переменной у меня еще есть такие:
В начале модуля:
' Option Explicit
'    Public shtSystem as Object

Затем в процедуре, которая вызывается при открытии данного документа:

shtSystem = ThisComponent.Sheets(0)

Ну и далее в разных процедурах использую переменную shtSystem. И вроде таких глюков, как с LastUserID - нет.
Отсюда вопрос - а правильно ли я делаю и не наступлю ли на более тяжелые грабли?

rami

Цитата: Alex16 от 22 ноября 2016, 18:42Ну и далее в разных процедурах использую переменную shtSystem. И вроде таких глюков, как с LastUserID - нет.
Отсюда вопрос - а правильно ли я делаю и не наступлю ли на более тяжелые грабли?
А какие глюки были с LastUserID ??? Есть разные требования к переменным и разные способы их объявления. Естественно, нужно подбирать правильный тип и способ объявления каждой переменной. Если после завершения макроса нужно запоминать значение переменной для последующего использования — выбираем Static, если не нужно — другую в зависимости от условий видимости переменной.

По возможности нужно избегать объявление переменной в модуле (вне процедуры), так ка это может привести к неожиданным и нежелательным эффектам (нашествие Чужих ^-^ ^-^ ^-^ — переменных из других библиотек или модулей). Объявлять переменную в модуле нужно только если она должна быть видна в разных макросах.

Alex16

#9
Цитата: rami от 22 ноября 2016, 20:56По возможности нужно избегать объявление переменной в модуле (вне процедуры)
т.е. так:




       Option Explicit
       Public shtSystem as Object, shtReport as Object.....


Sub MainInit
shtSystem = ThisComponent.Sheets(0)
shtReport = ThisComponent.Sheets(1)
shtData   = ThisComponent.Sheets(2)
...........
End Sub


ну и далее в разных Sub, Function - обращаемся к ним.
лучше так не делать?

У меня вопрос, наверное уже, не про видимость и место объявления, а про время жизни переменной.
Получается объявить их можно в начале модуля, а инициализировать в каждой Sub, Function. Хотя уже и смысл в объявлении вне процедур - теряется.

Alex16

Что-то не пойму, что случилось, но сегодня перестал работать этот пример:
REM  *****  BASIC  *****
Option Explicit
 
Sub LoadRep(N as Integer)
 print LastUserID   <<< Ошибка времени выполнения BASIC. Переменная не определена.

LastUserID = N

 print LastUserID

End Sub

Sub Test
Static LastUserID%        'переменная объявляется здесь, видна во всех макросах модуля и сохраняет значение до следующего изменения
   LoadRep(RND*50)
End Sub

Если курсор поставить в sub Test и нажать F5 то ошибка.
(В момент эксперимента в либре открыт только новый документ Calc и весь модуль с макросами в этом сообщении.)

rami

Вот и я попал в засаду :( : сначала переменная LastUserID% была объявлена как Global, а она сохраняется до закрытия офиса — именно её действие я по ошибке принял за Static. Сама Static, как я и сказал раньше не глобальная, а локальная переменная и действует до полного завершения макроса. Пример от Питоньяка:
Sub ExampleStatic
  ExampleStaticWorker()
  ExampleStaticWorker()
End Sub

Sub ExampleStaticWorker
  Static iStatic1 As Integer
  Dim iNonStatic As Integer
  iNonStatic = iNonStatic + 1
  iStatic1 = iStatic1 + 1
Msgbox "iNonStatic = " & iNonStatic & CHR$(10) & "iStatic1 = " & iStatic1
End Sub


То поведение переменной, о котором писали вчера, относится к Global, а не Static. Это хороший пример как нужно быть осторожным с переменными объявленными в модуле вне макросов.

Alex16

Так. Меня радует, что вопрос с засадой разъяснился, хоть и не в мою пользу)
Тогда получается мой вопрос переменной не решить? Мне нужно что бы в переменной (глобальной) сохранялось значение, выбранного последним в списке элемента.
У меня конечно же созрел коварный план. Сохранять не в переменную, а в "секретную" ячейку какого-нибудь "специального" листа... Но как-то это не камильфо.... не по программистски)))

mikekaganski

С уважением,
Михаил Каганский

JohnSUN

Цитата: Alex16 от 23 ноября 2016, 13:28
как-то это не камильфо.... не по программистски)))
Нормально-нормально! Программисты тоже бывают разные (индусы, например). Главное, чтобы решение работало и выполняло поставленную задачу. А как именно это сделано - уже не так уж и важно. "Не важно, как идёт процесс. Главное - как это выглядит со стороны" (с) один из Законов Мерфи
Секретная ячейка - только один из возможных вариантов. Есть еще куча мест, где это значение можно спрятать - пользовательские свойства документа, именованный диапазон, внешний текстовый файл (.ini), системный реестр... А можно просто каждый раз заглядывать в тот же самый ListBox и читать его значение. Любое из этих решений может быть реализовано и, скорее всего, будет работать годами.
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне