|
|
|
| Доброво времени суток форумчане!
Извините, данная тема несколько раз обсуждалась на форуме, но возникла небольшая проблема, которую не удается мне решить:
Есть форма, одиночная, во время загрузки базы на ней по ряду параметров и запросов выбираются одна строка из таблицы/запроса (5 текстовых и числовых значений) - нужно эти полученные 5 значений сделать глобальными для всей базы (постоянными для текущего сеанса).
Подскажите как это сделать. | |
|
| |
|
|
|
| При запуске формы попробуй
public a,b,c,d,e as integer
a=me.Поле1
b=me.Поле2
....
Может как-то иначе. | |
|
| |
|
|
|
| Глобальные переменные надо прописывать не в форме, а в модуле. Для этого открыть редактор 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, то можно присваивать им любые значения, хоть строковые, хоть целочисленные, и только для последней из объявленных в списке переменных при попытке загнать в нее строку будет выдана ошибка "несоответствие типов". | |
|
| |
|
|
|
| СПС | |
|
| |
|
|
|
| можно не глобальными - форму скрыть и к ней обращаться Forms!My_Global!Поле1 ,
удобней в плане запросов - которые не воспринимаю глобальные переменные.
п.с. если воспринимаю - раскажите как - буду признателен | |
|
| |
|
|
|
|
| А что бы не забывать обнулять эти переменные, лучше ИХМО передавать значения каждый раз в функцию и там после присвоения их функции - обнулять.
Вообще глобальные - они опасны в этом плане - в плане забыть нульнуть и получится не то значение бродит по программе.... как призрак коммуняки | |
|
| |
|
|
|
| на закритии каждой формы можно обнулять | |
|
| |
|
|
|
|
на закритии каждой формы можно обнулять
|
=============================================
Это не пойдёт - форму иногда открывают, не закрывая ранее открытую форму.
Может быть одновременно открыто несколько форм.
И переменная передаёт значения между несколькими открытыми формами. Так что нужно через функцию. ИХ МА. | |
|
| |
|
|
|
| Правда поговаривают, что глобальные переменные не совсем гуд ибо имеют тенденцию к тому что слетают в самое не подходящее время - более устойчивая альтернатива форма открытая в режиме невидимости | |
|
| |
|
|
|
| или таблица
или свойства базы данных(нужные создать) | |
|
| |
|
|
|
| Верно, глоб. переменные обнуляются в случае необработанной ошибки приложения. Либо писать код без ошибок, либо создать таблицу для хранения переменных.
public function GetCost AS Currency
GetCost = nz(Cost, 0)
'если 0 то извлекаем значение из таблицы
if GetCost = 0 then
GetCost = nz(Dlookup("Cost", "Temp"), 0)
end if
end function
|
| |
|
| |
|
|
|
| Как уже сказано: в текст запроса нельзя включить глобальную переменную, но можно включить глобальную функцию. Глобальная функция как и глоб. переменная прописывается в модуле.
'объявляем глоб. переменную
public Cost as Currency
'объявляем глоб. функцию
public function GetCost as Currency
GetCost = nz(Cost, 0)
end function
|
пример запроса с исп. глоб. функции:
SELECT * FROM Payment WHERE Credit > GetCost()
|
| |
|
| |
|
|
|
| но каждое обращение к функции это есть время - это не кошерно | |
|
| |
|
|
|
| А есть ли альтернатива? Обращение к форме тоже требует времени.
И вообще, если речь идет о блоке электронного наведения ракеты воздух-воздух то да, каждая доля секунды на счету, там в принципе использование языка высокого уровня некошерно, писать надо все на ассемблере. Если речь о простом офис-приложении то есть ли смысл считать доли секунды? | |
|
| |
|
|
|
| ИХ МА лучше всего так, как 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
|
То есть после каждого считывания данных - глоб. переменную - нулим. | |
|
| |
|
|
|
| а если глабальную переменную нужно воткнуть в запрос типа
Select Функция (глобальная, поле1, поле2) as Значение from tabla
- забодается каждый раз глобальную вычислять. | |
|
| |
|
|
|
| Попробуй Котт....
Но скажу заранее - всё очень быстро происходит, потому как запросы работают оч быстро -
не то что 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
|
| |
|
| |
|
|
|
| час я не говорю про конструкцию
WHERE (((PRODUCTS_TBL.FILE_NAME)=FUN_FILES_NAME()))
|
и ежу понятно - один раз вычислили и выполнили запрос.
я про свой пример - там до фига и так вызовов функций (= кол-во записей в запросе), так еще добавится такое же кол-во вызовов на глобальную переменну. | |
|
| |
|
|
|
| Ну что значит забодается? Сколько это в единицах времени на гигагерц процессора? У меня есть небольшая бухпрограмма частной фирмы: десятки и сотни тысяч записей из двух таблиц с 10-20 полями обрабатываются запросом на объединение с условиями, определяемыми глобальными функциями, за доли секунды. Компы с процессором не ниже Core2Duo. База разделенная, 100 мегабитная офисная сеть. Сначала тоже были сомнения насчет тормозов, т.к. вычисления происходят каждый раз с самой первой записи, хранимых промежуточных итогов нет (осознанное требование заказчика). Можно попробовать для интереса в виртуалбоксе с процессором 500 МГц, дополнительно приписав функцию вычисления разницы времени начала и окончания выполнения запроса и вывода на экран, но не думаю, что там будут наблюдаться сильные задержки. А, учитывая российскую тенденцию ставить в офис компы игровой мощности, то такие опыты и вовсе не нужны. | |
|
| |
|
|
|
|
| Глобальные переменные = зло.
:) | |
|
| |
|
|
|
|
|
| Альтернатива глобальным переменным - коллекции
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")
|
Совет из БД Егорова. Автор неизвестен. Я использую. Очень эффективно.
По быстродействию - коллекции очень подходят.
Я их использую даже вместо рекордседов иногда. Выигрыш в разы. | |
|
| |
|
|
|
| Так ведь обращение в запросе опять-таки происходит через глоб. функцию. Получается извлечь значение из коллекции быстрее чем из глоб. переменной? Или выигрыш только по сравнению с рекордсетами? | |
|
| |
|
|
|
| Через коллекцию быстрее. ИМХО. К тому же не надо заботиться о написании фуекции ДЛЯ КАЖДОЙ глоб. переменной! | |
|
| |
|
|
|
| Да, отсутствие необходимости описывать функции для каждой переменной - это хорошо. Подзадолбался их описывать. | |
|
| |
|
|
|
| Нас препод учил, что не надо все подряд объявлять глобальным, чтобы одинаковые названия не перекрывались. И по возможности пользоваться локальными переменными, которые освобождают память при закрытии формы. | |
|
| |
|
|
|
| В общем-то, это верно. Особенно актуально было раньше на слабеньких компах. Сейчас, по-моему не столь актуально. Но злоупотреблять не стоит. К тому же глоб переменные имеют обыкновение "слетать", например, при невыявленных ошибках. | |
|
| |
|
|
|
| Чё та я не понял с объявлением параметров?
' Установка паpаметpов:
' Param "ID", 1000014
' Param "D", Date
Это куда писать надо? | |
|
| |
|
|
|
| Котту
А вот ты мне не давно помогал с запросом
Кол-во за смену: Sum(IIf(Format([DATE_OTK];"mm/dd/yyyy")=Format(FUN_IN_DATE_RPT();"mm/dd/yyyy");1;0))
|
Видишь там обращение к функции FUN_IN_DATE_RPT()
А сама функция к форме обращается и все довольны и без "ЗАДЕРЖЕК".
Надо постепенно уходить от использования глобальных - везде, где гто возможно!
ИХ МА! | |
|
| |
|
|
|
| я грю о том что использовать лучше скрытую форму в место глобальных переменных (ГП) - если это возможно, т.к. использовать ГП в запросе можно только через функцию - а если функция вызывается в поле запроса (не в условии Where) - то возникает N вызовов функций = кол-ву записей в запросе, что в свою очередь ведет к увеличению времени выполнения запроса. | |
|
| |
|
|
|
| Спасибо - понятно!
Но не критично возрастает.....
Не ракеты делаем. | |
|
| |
|
|
|
| Обращение к форме тоже происходит N раз. Тогда вопрос в том, ск. машинных циклов требуется чтобы получить значение из формы и ск. чтобы получить его из функции с операцией присваивания и проверки nz. | |
|
| |
|
|
|
| вопрос - видимо будэ без ответу.... | |
|
| |
|
|
|
|
| Да, показательно. Дай, пожалуйста листинг функции GetTickCount. Хочу на коллекции проверить. | |
|
| |
|
|
|
|
| Спасибо. Слово public тут лишнее, не надо его писать. | |
|
| |
|
|
|
|
| к форме, наверное, путь длинней :) пока найдешь в коллекции форму, пока в ней контрол.......
а тут сразу раз - функция.
прикольно
а как дела обсьтоят с хранением значений в свойствах БД?
быстрее ли? :) | |
|
| |
|
|
|
| А как хранить значения в свойствах БД? | |
|
| |
|
|
|
| проверяет есть ли свойство
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 | |
|
| |
|
|
|
| т.е. можно создать свое свойство в CurrentProject.Properties и туда вогнать свое значение и ее юзать по имени | |
|
| |
|
|
|
| да
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
|
| |
|
| |
|
|
|
| тем - же тестом прогнал с использованием
CurrentProject.Properties.Add "P_1", 10
t1 = GetTickCount()
For i = 1 To 1000000
v = v + CurrentProject.Properties.Item("P_1")
Next
получил -- 7922, меньше чем к форме но значительно дольше чем функция. | |
|
| |
|
|
|
| В модуле проверь
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
|
| |
|
| |
|
|
|
| Чё та я не понял с объявлением параметров?
' Установка паpаметpов:
' Param "ID", 1000014
' Param "D", Date
Понял - это где удобно! - создание через функцию парамеиров.
А это
извлечение паpаметpов:
IDAT = Param "ID"
DAT =Param "D" | |
|
| |
|
|
|
| Извлечение
Param ("ID")
Param ("D")
со скобками | |
|
| |
|
|
|
| Ой да!
Или по названию, или видимо по индексу. | |
|
| |
|
12 Кб. |
|
| Пример | |
|
| |
|
|
|
| спасибо | |
|
| |
|
16 Кб. |
|
| Разность GetTickCount в результате миллиона итераций с извлечением значения через:
коллекцию: 600 мс
функцию: 260 мс | |
|
| |
|
|
|
| прогнал для - форма-другая форма и форма-форма
For i = 1 To 1000000
v = v + Me.PPP ' Forms!fff!PPP
Next
для форма-другая форма - 9516
для форма-форма - 6016
да уж интересно получается - долой обращение к форме | |
|
| |
|
|
|
| Доктор сказал в морг - значит в морг
автор: Lukas (07.09.2011 в 20:35)
Глобальные переменные = зло.
:)
|
| |
|
| |
|
|
18 Кб. |
|
| For i = 1 To 1000000
v = v + DLookup("MyValue", "TempTable")
Next
365047 мс = 6 минут. | |
|
| |
|
|
|
| зависит от задачи, но в больших базах заводить сотни глоб. перем. не есть гуд.
к тому же их надо помнить, написать для каждой ф-ю и т.п.
через коллекцию приятнее но не панацея. ИМХО. | |
|
| |
|
|
|
| Зачем же для каждой функцию заводить
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 | |
|
| |
|
|
|
| А если вот это?
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
|
| |
|
| |