Rambler's Top100
Форум: MS ACCESSVBVBA MS OfficeMS SQL server
Новые сообщения: 0000

Форум: MS ACCESS

Вопросы связанные с MS ACCESS

Обновить визитку
Участники «Online»
Все участники

 
 

Доброго времени суток, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: о наболевшем Глобальные переменные
 
 автор: erzi   (06.09.2011 в 21:50)   личное сообщение
 
 

Доброво времени суток форумчане!
Извините, данная тема несколько раз обсуждалась на форуме, но возникла небольшая проблема, которую не удается мне решить:
Есть форма, одиночная, во время загрузки базы на ней по ряду параметров и запросов выбираются одна строка из таблицы/запроса (5 текстовых и числовых значений) - нужно эти полученные 5 значений сделать глобальными для всей базы (постоянными для текущего сеанса).
Подскажите как это сделать.

  Ответить  
 
 автор: Гоблин   (06.09.2011 в 22:31)   личное сообщение
 
 

При запуске формы попробуй

public a,b,c,d,e as integer
a=me.Поле1
b=me.Поле2
....

Может как-то иначе.

  Ответить  
 
 автор: Stanislav   (07.09.2011 в 05:26)   личное сообщение
 
 

Глобальные переменные надо прописывать не в форме, а в модуле. Для этого открыть редактор visual basic, на списке модулей правой кнопкой: insert - module.

В созданном модуле пишете:

public a as integer
public b as integer
public c as integer


public - означает глобальная.

В форме в обработчике события пишете:

a=целочисленное значение
b=целочисленное значение
c=целочисленное значение


Примечание:
Обязательно следует указывать тип для каждой вновь вводимой переменной, иначе она будет отнесена типу Variant
ПРИМЕР: Правильное объявление переменных:

Dim theName as String 
Dim Cost as Currency,
I as Integer 
Dim MyPicture as Variant

Неправильное объявление переменных:
Dim i, j, k as Integer
Dim Cost, Loss As Currency

Можете проверить: если объявить переменные списком как, например integer, то можно присваивать им любые значения, хоть строковые, хоть целочисленные, и только для последней из объявленных в списке переменных при попытке загнать в нее строку будет выдана ошибка "несоответствие типов".

  Ответить  
 
 автор: Гоблин   (07.09.2011 в 08:22)   личное сообщение
 
 

СПС

  Ответить  
 
 автор: kot_k_k   (07.09.2011 в 08:34)   личное сообщение
 
 

можно не глобальными - форму скрыть и к ней обращаться Forms!My_Global!Поле1 ,
удобней в плане запросов - которые не воспринимаю глобальные переменные.

п.с. если воспринимаю - раскажите как - буду признателен

  Ответить  
 
 автор: snipe   (07.09.2011 в 08:50)   личное сообщение
 
 

Через функцию

  Ответить  
 
 автор: час   (07.09.2011 в 09:02)   личное сообщение
 
 

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

  Ответить  
 
 автор: ddi   (07.09.2011 в 09:05)   личное сообщение
 
 

на закритии каждой формы можно обнулять

  Ответить  
 
 автор: час   (07.09.2011 в 14:43)   личное сообщение
 
 

на закритии каждой формы можно обнулять

=============================================
Это не пойдёт - форму иногда открывают, не закрывая ранее открытую форму.
Может быть одновременно открыто несколько форм.
И переменная передаёт значения между несколькими открытыми формами. Так что нужно через функцию. ИХ МА.

  Ответить  
 
 автор: snipe   (07.09.2011 в 09:07)   личное сообщение
 
 

Правда поговаривают, что глобальные переменные не совсем гуд ибо имеют тенденцию к тому что слетают в самое не подходящее время - более устойчивая альтернатива форма открытая в режиме невидимости

  Ответить  
 
 автор: Силblч   (07.09.2011 в 09:12)   личное сообщение
 
 

или таблица
или свойства базы данных(нужные создать)

  Ответить  
 
 автор: Stanislav   (07.09.2011 в 12:29)   личное сообщение
 
 

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

public function GetCost AS Currency
GetCost = nz(Cost, 0)

'если 0 то извлекаем значение из таблицы
if GetCost = 0 then
GetCost = nz(Dlookup("Cost", "Temp"), 0)
end if
end function

  Ответить  
 
 автор: Stanislav   (07.09.2011 в 12:22)   личное сообщение
 
 

Как уже сказано: в текст запроса нельзя включить глобальную переменную, но можно включить глобальную функцию. Глобальная функция как и глоб. переменная прописывается в модуле.

'объявляем глоб. переменную
public Cost as Currency

'объявляем глоб. функцию
public function GetCost as Currency
GetCost = nz(Cost, 0)
end function

пример запроса с исп. глоб. функции:
SELECT * FROM Payment WHERE Credit > GetCost()

  Ответить  
 
 автор: kot_k_k   (07.09.2011 в 13:18)   личное сообщение
 
 

но каждое обращение к функции это есть время - это не кошерно

  Ответить  
 
 автор: Stanislav   (07.09.2011 в 13:31)   личное сообщение
 
 

А есть ли альтернатива? Обращение к форме тоже требует времени.

И вообще, если речь идет о блоке электронного наведения ракеты воздух-воздух то да, каждая доля секунды на счету, там в принципе использование языка высокого уровня некошерно, писать надо все на ассемблере. Если речь о простом офис-приложении то есть ли смысл считать доли секунды?

  Ответить  
 
 автор: час   (07.09.2011 в 14:36)   личное сообщение
 
 

ИХ МА лучше всего так, как Stanislav советует



Public Cost as Currency
=========================

Public Function GetCost as Currency
GetCost = nz(Cost, 0)
End function 
Это для запросов.

А программе
Public Cost as Currency
=========================

Public Function GetCost as Currency
GetCost = nz(Cost, 0)
Cost=0
End function 

То есть после каждого считывания данных - глоб. переменную - нулим.

  Ответить  
 
 автор: kot_k_k   (07.09.2011 в 15:00)   личное сообщение
 
 

а если глабальную переменную нужно воткнуть в запрос типа

Select Функция (глобальная, поле1, поле2) as Значение from tabla

- забодается каждый раз глобальную вычислять.

  Ответить  
 
 автор: час   (07.09.2011 в 18:27)   личное сообщение
 
 

Попробуй Котт....
Но скажу заранее - всё очень быстро происходит, потому как запросы работают оч быстро -
не то что DAO или ADO.
Я этим давно пользуюся.
И сую в запросы исполняемые в DAO - доступ из визуал басика - всё чики-чикиаккурат быстренько.
Так что даже не сумневайся.
Функции рулят....
Значение поля в запрос - через функцию передать - это прям песня.

тока не так
Select Функция (глобальная, поле1, поле2) as Значение from tabla 

А вот выдрано
PRODUCTS_TBL.DATE_OTK, PRODUCTS_TBL.NAKLADNAYA_NUMBER, PRODUCTS_TBL.FILE_NAME
FROM PRODUCTS_TBL
WHERE (((PRODUCTS_TBL.FILE_NAME)=FUN_FILES_NAME()))


вот и функция пригодилася в условии работает FUN_FILES_NAME()
Функция не маленькая, но работает как часы
Public Function FUN_FILES_NAME() As String
' вспомогательная функция для запроса LIST_ACTUAL_FILE_NAME
FUN_FILES_NAME = Nz(STR_FILE_NAME)
If IsEmpty(STR_FILE_NAME) = True Then
FUN_FILES_NAME = ""
STR_FILE_NAME = "" ' присвоение значения переменной
End If
End Function

  Ответить  
 
 автор: kot_k_k   (08.09.2011 в 08:27)   личное сообщение
 
 

час я не говорю про конструкцию


WHERE (((PRODUCTS_TBL.FILE_NAME)=FUN_FILES_NAME()))



и ежу понятно - один раз вычислили и выполнили запрос.
я про свой пример - там до фига и так вызовов функций (= кол-во записей в запросе), так еще добавится такое же кол-во вызовов на глобальную переменну.

  Ответить  
 
 автор: Stanislav   (08.09.2011 в 08:00)   личное сообщение
 
 

Ну что значит забодается? Сколько это в единицах времени на гигагерц процессора? У меня есть небольшая бухпрограмма частной фирмы: десятки и сотни тысяч записей из двух таблиц с 10-20 полями обрабатываются запросом на объединение с условиями, определяемыми глобальными функциями, за доли секунды. Компы с процессором не ниже Core2Duo. База разделенная, 100 мегабитная офисная сеть. Сначала тоже были сомнения насчет тормозов, т.к. вычисления происходят каждый раз с самой первой записи, хранимых промежуточных итогов нет (осознанное требование заказчика). Можно попробовать для интереса в виртуалбоксе с процессором 500 МГц, дополнительно приписав функцию вычисления разницы времени начала и окончания выполнения запроса и вывода на экран, но не думаю, что там будут наблюдаться сильные задержки. А, учитывая российскую тенденцию ставить в офис компы игровой мощности, то такие опыты и вовсе не нужны.

  Ответить  
 
 автор: Дядя Федор   (08.09.2011 в 09:32)   личное сообщение
 
 

А зачем нулить?

  Ответить  
 
 автор: Lukas   (07.09.2011 в 20:35)   личное сообщение
 
 

Глобальные переменные = зло.
:)

  Ответить  
 
 автор: час   (07.09.2011 в 21:19)   личное сообщение
15 Кб.
 
 

  Ответить  
 
 автор: час   (07.09.2011 в 21:46)   личное сообщение
17 Кб.
 
 

  Ответить  
 
 автор: Дядя Федор   (08.09.2011 в 07:58)   личное сообщение
 
 

Альтернатива глобальным переменным - коллекции


Public Function Param(name As String, Optional Val)
Static ParamCol As New Collection
On Error Resume Next
   Param = Null
   Param = ParamCol(name)
   If IsMissing(Val) Then Exit Function
   ParamCol.Remove name
   If Not IsNull(Val) Then ParamCol.Add Val, name
End Function

'    Установка паpаметpов:
'        Param "ID", 1000014
'        Param "D", Date
'        DoCmd.OpenReport ...
'    Использование в запpосе:
'        SELECT ... WHERE ID=Param("ID") AND Дата<Param("D")
'    Использование в коде:
'        a = param("ID")

Совет из БД Егорова. Автор неизвестен. Я использую. Очень эффективно.
По быстродействию - коллекции очень подходят.
Я их использую даже вместо рекордседов иногда. Выигрыш в разы.

  Ответить  
 
 автор: Stanislav   (08.09.2011 в 08:06)   личное сообщение
 
 

Так ведь обращение в запросе опять-таки происходит через глоб. функцию. Получается извлечь значение из коллекции быстрее чем из глоб. переменной? Или выигрыш только по сравнению с рекордсетами?

  Ответить  
 
 автор: Дядя Федор   (08.09.2011 в 09:29)   личное сообщение
 
 

Через коллекцию быстрее. ИМХО. К тому же не надо заботиться о написании фуекции ДЛЯ КАЖДОЙ глоб. переменной!

  Ответить  
 
 автор: Stanislav   (08.09.2011 в 16:24)   личное сообщение
 
 

Да, отсутствие необходимости описывать функции для каждой переменной - это хорошо. Подзадолбался их описывать.

  Ответить  
 
 автор: Stanislav   (08.09.2011 в 08:15)   личное сообщение
 
 

Нас препод учил, что не надо все подряд объявлять глобальным, чтобы одинаковые названия не перекрывались. И по возможности пользоваться локальными переменными, которые освобождают память при закрытии формы.

  Ответить  
 
 автор: Дядя Федор   (08.09.2011 в 09:32)   личное сообщение
 
 

В общем-то, это верно. Особенно актуально было раньше на слабеньких компах. Сейчас, по-моему не столь актуально. Но злоупотреблять не стоит. К тому же глоб переменные имеют обыкновение "слетать", например, при невыявленных ошибках.

  Ответить  
 
 автор: час   (08.09.2011 в 13:55)   личное сообщение
 
 

Чё та я не понял с объявлением параметров?

' Установка паpаметpов:
' Param "ID", 1000014
' Param "D", Date
Это куда писать надо?

  Ответить  
 
 автор: час   (08.09.2011 в 14:01)   личное сообщение
 
 

Котту
А вот ты мне не давно помогал с запросом

Кол-во за смену: Sum(IIf(Format([DATE_OTK];"mm/dd/yyyy")=Format(FUN_IN_DATE_RPT();"mm/dd/yyyy");1;0))

Видишь там обращение к функции FUN_IN_DATE_RPT()
А сама функция к форме обращается и все довольны и без "ЗАДЕРЖЕК".
Надо постепенно уходить от использования глобальных - везде, где гто возможно!
ИХ МА!

  Ответить  
 
 автор: kot_k_k   (08.09.2011 в 14:34)   личное сообщение
 
 

я грю о том что использовать лучше скрытую форму в место глобальных переменных (ГП) - если это возможно, т.к. использовать ГП в запросе можно только через функцию - а если функция вызывается в поле запроса (не в условии Where) - то возникает N вызовов функций = кол-ву записей в запросе, что в свою очередь ведет к увеличению времени выполнения запроса.

  Ответить  
 
 автор: час   (08.09.2011 в 16:27)   личное сообщение
 
 

Спасибо - понятно!
Но не критично возрастает.....
Не ракеты делаем.

  Ответить  
 
 автор: Stanislav   (08.09.2011 в 16:29)   личное сообщение
 
 

Обращение к форме тоже происходит N раз. Тогда вопрос в том, ск. машинных циклов требуется чтобы получить значение из формы и ск. чтобы получить его из функции с операцией присваивания и проверки nz.

  Ответить  
 
 автор: час   (08.09.2011 в 16:37)   личное сообщение
 
 

вопрос - видимо будэ без ответу....

  Ответить  
 
 автор: kot_k_k   (08.09.2011 в 17:25)   личное сообщение
 
 

вот - экэономическая эксперимента однако!!!

вот сваял 3 функции - время выполнения функции данные GetTickCount - разница начал и окончания цикла.



Function GL_Prov()
    GL_Prov = 1
End Function

Function GL_Prov_2()
    k = GetTickCount
    For i = 1 To 1000000
        ll = 1 + Forms!Global!Plant
    Next
    K2 = GetTickCount
End Function

Function GL_Prov_3()
    k = GetTickCount
    For i = 1 To 1000000
        ll = 1 + GL_Prov
    Next
    K2 = GetTickCount
End Function

Function GL_Prov_4()
    k = GetTickCount
    For i = 1 To 1000000
        ll = 1 + 1
    Next
    K2 = GetTickCount
End Function



1. С обращением к форме - 12109
2. С обращением к функции GL_Prov - 156
3. Просто цикл -16

да уж снимаю шляпу

получается ему стрельнуть функцию проще чем обратиться к форме.

  Ответить  
 
 автор: Stanislav   (09.09.2011 в 06:34)   личное сообщение
 
 

Да, показательно. Дай, пожалуйста листинг функции GetTickCount. Хочу на коллекции проверить.

  Ответить  
 
 автор: kot_k_k   (09.09.2011 в 08:37)   личное сообщение
 
 

Public Declare Function GetTickCount Lib "kernel32" () As Long

  Ответить  
 
 автор: Stanislav   (09.09.2011 в 09:51)   личное сообщение
 
 

Спасибо. Слово public тут лишнее, не надо его писать.

  Ответить  
 
 автор: kot_k_k   (09.09.2011 в 09:53)   личное сообщение
 
 

как слямзил так написал

  Ответить  
 
 автор: Силblч   (09.09.2011 в 09:33)   личное сообщение
 
 

к форме, наверное, путь длинней :) пока найдешь в коллекции форму, пока в ней контрол.......
а тут сразу раз - функция.
прикольно

а как дела обсьтоят с хранением значений в свойствах БД?
быстрее ли? :)

  Ответить  
 
 автор: Stanislav   (09.09.2011 в 10:25)   личное сообщение
 
 

А как хранить значения в свойствах БД?

  Ответить  
 
 автор: Силblч   (09.09.2011 в 10:58)   личное сообщение
 
 

проверяет есть ли свойство

Public Function IsBDProperty(strPNam As String) As Boolean
    Dim lngCount As Long
    Dim i As Long
    IsBDProperty = False
    If Len(Nz(strPNam, "")) = 0 Then Exit Function
    lngCount = CurrentProject.Properties.Count
    For i = 0 To lngCount - 1
        If CurrentProject.Properties.Item(i).Name = strPNam Then
            IsBDProperty = True
            Exit Function
        End If
    Next i
End Function

две други ф-ции - Get и Set

  Ответить  
 
 автор: kot_k_k   (09.09.2011 в 12:06)   личное сообщение
 
 

т.е. можно создать свое свойство в CurrentProject.Properties и туда вогнать свое значение и ее юзать по имени

  Ответить  
 
 автор: Силblч   (09.09.2011 в 12:11)   личное сообщение
 
 

да


Public Function getProp(param$)
    On Error GoTo err123
    If IsBDProperty(param) = True Then getProp = CurrentProject.Properties.Item(param)
    Exit Function
err123:
    MsgBox Error, , "getProp"
    Exit Function
End Function



Public Sub setProp(pn$, pv)
    On Error GoTo err123
    CurrentProject.Properties.Add pn, pv
    Exit Sub
err123:
    MsgBox Error, , "setProp"
    Exit Sub
End Sub

  Ответить  
 
 автор: kot_k_k   (09.09.2011 в 12:39)   личное сообщение
 
 

тем - же тестом прогнал с использованием
CurrentProject.Properties.Add "P_1", 10
t1 = GetTickCount()
For i = 1 To 1000000
v = v + CurrentProject.Properties.Item("P_1")
Next

получил -- 7922, меньше чем к форме но значительно дольше чем функция.

  Ответить  
 
 автор: Дядя Федор   (08.09.2011 в 16:58)   личное сообщение
 
 

В модуле проверь

Public Function Param(name As String, Optional Val)
Static ParamCol As New Collection
On Error Resume Next
   Param = Null
   Param = ParamCol(name)
   If IsMissing(Val) Then Exit Function
   ParamCol.Remove name
   If Not IsNull(Val) Then ParamCol.Add Val, name
End Function 

REM TESTIROVANIE

Private sub tsts
Param "ID", 1000014 'установка
Param "D", Date 
debug.print Param ("ID") 'получение
debug.print Param ("D")
end sub

  Ответить  
 
 автор: час   (08.09.2011 в 18:11)   личное сообщение
 
 

Чё та я не понял с объявлением параметров?

' Установка паpаметpов:
' Param "ID", 1000014
' Param "D", Date

Понял - это где удобно! - создание через функцию парамеиров.
А это
извлечение паpаметpов:
IDAT = Param "ID"
DAT =Param "D"

  Ответить  
 
 автор: Дядя Федор   (09.09.2011 в 07:58)   личное сообщение
 
 

Извлечение
Param ("ID")
Param ("D")
со скобками

  Ответить  
 
 автор: час   (09.09.2011 в 08:24)   личное сообщение
 
 

Ой да!
Или по названию, или видимо по индексу.

  Ответить  
 
 автор: Дядя Федор   (09.09.2011 в 08:59)   личное сообщение
12 Кб.
 
 

Пример

  Ответить  
 
 автор: час   (09.09.2011 в 09:13)   личное сообщение
 
 

спасибо

  Ответить  
 
 автор: Stanislav   (09.09.2011 в 09:26)   личное сообщение
16 Кб.
 
 

Разность GetTickCount в результате миллиона итераций с извлечением значения через:
коллекцию: 600 мс
функцию: 260 мс

  Ответить  
 
 автор: kot_k_k   (09.09.2011 в 09:44)   личное сообщение
 
 

прогнал для - форма-другая форма и форма-форма
For i = 1 To 1000000
v = v + Me.PPP ' Forms!fff!PPP
Next
для форма-другая форма - 9516
для форма-форма - 6016

да уж интересно получается - долой обращение к форме

  Ответить  
 
 автор: snipe   (09.09.2011 в 10:02)   личное сообщение
 
 

Доктор сказал в морг - значит в морг


автор: Lukas (07.09.2011 в 20:35)

Глобальные переменные = зло.
:)

  Ответить  
 
 автор: час   (09.09.2011 в 10:22)   личное сообщение
 
 

Функции, стало быть - наш выбор!
Они и в Африке функции

  Ответить  
 
 автор: Stanislav   (09.09.2011 в 10:24)   личное сообщение
18 Кб.
 
 

For i = 1 To 1000000
v = v + DLookup("MyValue", "TempTable")
Next

365047 мс = 6 минут.

  Ответить  
 
 автор: Дядя Федор   (09.09.2011 в 13:03)   личное сообщение
 
 

зависит от задачи, но в больших базах заводить сотни глоб. перем. не есть гуд.
к тому же их надо помнить, написать для каждой ф-ю и т.п.
через коллекцию приятнее но не панацея. ИМХО.

  Ответить  
 
 автор: snipe   (09.09.2011 в 14:42)   личное сообщение
 
 

Зачем же для каждой функцию заводить

Public asd as Long
Public dfg as String

Public function GlobalX(StrName as String) as Variant 'для примера StrName="asd"
Select Case StrName
Case "asd": GlobalX=asd
Case "dfg": GlobalX=dfg
....
....
End Select
End Function

  Ответить  
 
 автор: час   (09.09.2011 в 13:41)   личное сообщение
 
 

А если вот это?
http://msdatabase.ru/collectionfunctions.htm

Альтернатива DLookUp
 
 
Public Function SqlLookUp(sql)  
Dim ar  
On Error Resume Next  
ar = CurrentProject.connection.Execute(sql).GetRows  
SqlLookUp = ar(0, 0)  
End Function  
 
Вариант 2  
Public Function SqlLookUp(sql)  
On Error Resume Next  
SqlLookUp = CurrentProject.Connection.Execute(sql).Fields(0)  
End Function  
 
Вызов функции из вычисляемого поля:  
= SqlLookUp(" select a + b + c from mytable where id=" & [formID] )  
 
Функция возвратит первое значение (первая строка и первое поле) из набора записей определяемого параметром SQL  

  Ответить  
HiProg.com - Технологии программирования
Rambler's Top100 TopList