1с где можно хранить переменную
Область применения: управляемое приложение, мобильное приложение, обычное приложение.
1. В большинстве случаев, вместо переменных программных модулей следует использовать более подходящие средства разработки платформы 1С:Предприятие . Поскольку область видимости (использования) таких переменных сложно контролировать, то они зачастую становятся источником трудновоспроизводимых ошибок.
Примеры некорректного использования и исключений из этого правила приведены далее. Рекомендации по оформлению переменных в коде программных модулей см. в статье Структура модуля.
2. Неоправданные примеры использования переменных в модулях объектов (справочников, документов, наборов записей, обработок, отчетов и пр.).
2.1. Для передачи параметров между обработчиками подписок на события и в обработчики событий модуля объекта из внешнего кода рекомендуется использовать свойство объекта ДополнительныеСвойства . Например, неправильно:
Перем КонвертацияФайлов Экспорт;
Если КонвертацияФайлов Тогда
.
// вызывающий код
ФайлОбъект.КонвертацияФайлов = Истина;
ФайлОбъект.Записать();
Если ДополнительныеСвойства.Свойство("КонвертацияФайлов") Тогда
.
// вызывающий код
ФайлОбъект.ДополнительныеСвойства.Вставить("КонвертацияФайлов", Истина);
ФайлОбъект.Записать();
В то же время, для передачи внутренних параметров между обработчиками событий модуля объекта целесообразно использовать неэкспортные переменные модуля объекта, которые недоступны из внешнего кода.
Например:
Перем ПредыдущееЗначениеОрганизации; // значение реквизита "Организация" до записи объекта в базу
Процедура ПередЗаписью(Отказ)
ПредыдущееЗначениеОрганизации = . ; // с помощью запроса выясняем значение до записи объекта в базу
КонецПроцедуры
Процедура ПриЗаписи(Отказ)
Если ПредыдущееЗначениеРеквизита <> Организация Тогда
// отрабатываем изменение значения реквизита при записи
.
КонецЕсли;
2.2. Для обработки кодов возврата (ошибок) в логике программного модуля рекомендуется использовать строковые константы.
Например, неправильно:
Перем НетОшибок,
Ошибка_ОбработкиПроверкиЗаполнения, // возникает, если обработка проверки заполнения вернула отказ
Ошибка_ЗаписиОбъекта, // возникает, если во время записи объекта возникло исключение
Ошибка_БлокировкиОбъекта, // возникает, при попытке блокировки объекта
Процедура ВыполнитьПерерасчет()
.
Результат = ОбработатьДокументы(. );
Если Результат = Ошибка_ЗаписиОбъекта Тогда
.
ИначеЕсли Результат = Ошибка_БлокировкиОбъекта Тогда
.
ИначеЕсли .
НетОшибок = 1;
Ошибка_ОбработкиПроверкиЗаполнения = 2;
Ошибка_ЗаписиОбъекта = 3;
Ошибка_БлокировкиОбъекта = 4;
Процедура ВыполнитьПерерасчет()
.
Результат = ОбработатьДокументы(. );
Если Результат = "ОшибкаЗаписиОбъекта" Тогда
.
ИначеЕсли Результат = "ОшибкаБлокировкиОбъекта" Тогда
.
ИначеЕсли .
2.3. Для кеширования долго-вычисляемых и часто-используемых значений в процедурах и функциях рекомендуется применять модули с повторным использованием возвращаемых значений на время вызова сервера.
Исключение из этого правила составляют случаи, когда по соображениям безопасности возвращать результат вычисления в экспортной функции недопустимо. В этом случае они размещаются в локальной переменной модуля.
3. Неоправданные примеры использования переменных в модулях форм.
3.1. Для кеширования долго-вычисляемых и часто-используемых значений в процедурах и функциях рекомендуется применять модули с повторным использованием возвращаемых значений.
При этом не следует кешировать статическую и легко вычисляемую информацию. В частности, не следует кешировать в клиентских переменных модуля формы значения предопределенных элементов и перечислений. Для их получения на клиенте предназначен метод ПредопределенноеЗначение .
3.2. Для хранения и передачи промежуточных результатов вычислений между разными процедурами и функциями формы следует использовать
- Параметры процедур и функций – для передачи результатов по цепочке вызовов дочерних процедур и функций в контексте одного вызова.
- Реквизиты формы – если требуется сохранять промежуточные результаты между разными вызовами с клиента. (Следует иметь в виду, что значения серверных переменных модуля формы не сохраняются между вызовами с клиента.)
Исключение из этого правила составляют случаи использования клиентских переменных формы для хранения промежуточных результатов в обработчиках ожидания формы, в обработчиках внешних событий и в клиентских обработчиках событий элементов формы.
Например:
4. Переменные управляемого и обычного приложения следует использовать для хранения «клиентских параметров сеанса». Подробнее см. статью Использование параметров сеанса.
Программирование системы
24.08.2018 08:06
10313
Во встроенном языке программирования 1С используются переменные. Имена переменных должны начинаться с английского или русского символа, или подчеркивания. Нельзя чтобы наименование переменной начиналось с цифры. Не рекомендуется именовать переменные зарезервированными синтаксическими конструкциями. Имена переменных должны носить осмысленный характер. Это улучшает читабельность программного кода. Что в последующем увеличивает скорость разработки или доработки приложения. При объявлении переменных не требуется указывать тип значения, как это делается во многих других языках программирования. Тип значения определяется автоматически системой.
Локальные переменные
Локальные переменные определяются внутри процедур или функций. Перед ними необязательно писать ключевое слово "Перем". Область доступности таких переменных ограничена границами своей процедуры или функции. То есть, к такой переменной нельзя обратиться в другой процедуре или функции или из глобального контекста.
Глобальные переменные
Во многих языках программирования предусмотрено создание глобальных переменных. Во встроенном языке 1С, так же есть возможность создавать глобальные переменные. Такие переменные доступны во всех процедурах и функциях модуля в котором они определены. В языке программирования 1С глобальные переменные могут быть определены в любых модулях (объектов, форм, и т.д) кроме общих модулей. Глобальные переменные задаются в самом верху модуля, перед определением всех процедур и функций. Перед именем переменной пишется ключевое слово "Перем". Значение указывать нельзя. Значение глобальной переменной можно задать в процедурах, функциях модуля или в конце модуля после всех процедур и функций.
Экспортные переменные
Глобальную переменную можно сделать экспортной, указав ключевое слово "Экспорт". Например, если экспортная переменная создаётся в модуле объекта справочника, то к ней можно обратиться через объект этого справочника, СправочникОбъект.ИмяПеременной.
В модуле управляемого приложения в процедуре ПриНачалеРаботыСистемы создаю переменную типа список значений и заполняю.
Объявляю переменную как экспорт.
Каким образом обратиться к этой переменной из общих модулей, модулей менеджеров документов, модулях форм?
Yandex |
---|
Возможно, вас также заинтересует |
Kikoz |
---|
Ответ № 1 |
К таким переменным можно обратиться только из клиентских функций и процедур.
Перед описанием переменной обязательно должна быть указана директива компиляции (&НаКлиенте илиНаСервере).
Если используется директива компиляцииНаКлиенте, то такая переменная будет существовать с момента создания формы до момента ее закрытия. Причем только в клиентской части формы. Из серверных процедур формы она доступна не будет.
(с) Максим Радченко, 1С.
А можно создать одну переменнуюНаСервере для получения ее в серверных процедура, а другую, такую жеНа клиенте для клиентских?
Тип: ХранилищаНастроекМенеджер.
Предназначено для доступа к хранилищам настроек, которые созданы в конфигурации.
Сервер, толстый клиент, внешнее соединение.
а то кто-то тут торгует синтакс-помощником.
выглядит, как будто к тонкому клиенту не подходит:
Сервер, толстый клиент, внешнее соединение.
(14) не абсолютно все, а только те, про которые идет разговор. ожидается последовательный вызов клиентской функции, поведение которой зависит от значения констант, изменение констант на ходу при этом не планируется, то есть нужно закэшировать их на клиенте.
(16) какое еще общее решение? смотря какая у тебя задача. если клиент, значит есть форма, значит можно хранить в реквизитах формы. а вообще 1С не рекомендует кэшировать константы в повторно используемых значениях.
(15) там константы и так кешируются на уровне платформы, зачем вам их по второму разу кешировать? Вы хотите странного.
(19) разве можно получить значение константы на клиенте? если нет, значит константа кэшируется на сервере, а зачем она мне там, если мне на клиенте надо?
(20) С методической точки зрения, даже параметры сеанса, о которых ты начал тут говорить, для кэширования использовать не правильно ;)
вроде как константу получают так:
если даже она у меня сама закэшируется на сервере, то вызов сервера от этого не исчезнет.
кстати, почему-то так не заработало:
(23) у тебя же есть форма? добавляешь реквизит на форме, например, ВалютаУпрУчета. ПриСозданииНаСервере пишешь ВалютаУпрУчета = Константы.ВалютаУпрУчета.Получить(); и потом используй в своей форме сколько хочешь ВалютаУпрУчета, без вызова сервера.
(24) поддержу. Так столько всего передается с сервера, что специально что-то делать не имеет смысла.
(10) Переменные упр. модуля в Web-клиенте не доступны.
(26) > Переменные упр. модуля в Web-клиенте не доступны.
Хм, вряд ли это так.
(28) Не в курсе, а что там с внешней обработкой?
"Экспортируемые переменные, процедуры или функции модуля управляемого приложения (у которых в заголовке указано ключевое слово Экспорт) будут доступны (рис. 3.5):
Не понял нравственных метаний присутствующих в ветке.
Давайте, рассказывайте мне, кто обидел.
Я приду на помощь.
(33) Так понять нас не мудрено.
По "заветам партии" хотим все считать на сервере, а где переменные хранить не знаем. Всяких таблиц, списков значений и структур хотим создать, да побольше. Да только так создать, чтобы не пришлось их с клиента гонять.
Еще, хотелось бы, перемещение рисунков по табличному документу организовать на клиенте, а не лезть на сервер
Храните на Клиенте:
(36) то есть, в итоге, создаем общий модуль с повторным использованием и вставляем функцию получения константы? а если нужно хранить какие-то данные которые на сервере вообще ни к чему (ну типа предыдущих координат мыши)?
(37) Если тебе на клиенте нужно сохранить значение, то просто в модуле формы можно завести переменную как в (35).
А вот значение серверной переменной постоянно так хранить не получится.
При возврате с сервера на клиента ей настанет каюк. При вызове сервера с клиента тебе придется передавать клиентские данные или через параметры функции, временноехранилище или через форму. Как то так.
(39) ВременноеХранилище - это же файл?
Получу я адрес в хранилище. Теперь его нужно хранить.
Было бы шикарно объявить переменную, вроде
И пусть платформа сама гоняет ее по своим хранилищам.
Доступно и всерьез!
(40) размести темпы и "временные" папки юзера 1с на рамдрайве (tmpfs в линупсе - самый простой вариант), будь мужиком!
Но как так!? Ведь глобальные переменные модуля формы существуют всё время, пока живёт форма. Какой костыль нужно поставить в этот раз, чтоб можно было пользовать переменную, вполне законно, объявленную ранее? Или сейчас в 2018 это уже нельзя делать?
(1) Объявление переменной модуля идет первой строкой модуля?
Если сохранить не взирая на ошибку компилятора, в режиме предприятия ошибка возникает?
Опечатки исключаются?
Переменная объявлена, но её значение не определено, т.е даже не равно Неопределено.
Довольно много кодил на управляемых формах, и не могу припомнить случаев, когда мне нужно было иметь значение ТОЛЬКО на клиенте. Обычно все "только клиентские" переменные это либо реквизит формы (который отображается на форме), либо передаются в параметрах функций и процедур. В каких случаях требуются только клиентские переменные, приведите пример?
Локальное кэширование, например. Хранение каких-то связанных данных, нужных в интерактиве, без запихивания их в реквизиты формы, чтобы облегчить контекст формы и клиент-серверные вызовы. Работа с оборудованием с клиента.
(27)При работе с другой базой через ком-соединение, хранить это ком-соединение можно только в клиентской переменной модуля, в реквизиты формы вы его не засунете. Вы конечно можете каждый раз создавать новое ком-соединение при выполнении клиентской команды, но это варварство.
(29) Странный аргумент. Намного выгоднее работать с другой базой через COM-соединение на сервере. Куча профита. Одна точка подключения, нет ограничений на окружение клиента (хоть веб), нет лишних клиент-серверных вызовов и других ограничений клиента. А чтобы подключение не пересоздавалось постоянно - получать его через модуль с повторным использованием возвращаемых значений.
(31) Если на сервере можно сохранить соединение после серверного вызова, то конечно, - так было бы удобнее, но я не смог это проделать. Дайте, пожалуйста, минимальный пример.
А чтобы подключение не пересоздавалось постоянно - получать его через модуль с повторным использованием возвращаемых значений.
В общем модуле со свойством "Повторное использование возвращаемых значений" установленным в "На время сеанса" создаешь функцию, которая создает и возвращает соединение. В параметры функции лучше всего передавать собственно параметры подключения или ссылку на элемент справочника, который их содержит (т.к. возвращаемые значения кэшируются для комбинаций параметров).
В результате при первом обращении к этой функции соединение будет создано, а при повторных вызовах функция будет возвращать ранее созданное соединение. Иногда соединение может "потеряться", в этом случае функция просто повторно создаст соединение. Варианты на потеряться (из справки):
- после долгого неиспользования (более 5 минут);
- при нехватке оперативной памяти в рабочем процессе сервера;
- при перезапуске рабочего процесса;
- при переключении клиента на другой рабочий процесс
ЗЫ. Встречал даже "хаки" для "удержания" больших ТЗ на сервере таким макаром, с "дерганьем" каждые несколько минут, чтобы не ушло из кэша. Но это выглядит грязным приемом, ведь все-таки это чистой воды механизм кэширования. Использовать его для хранения состояния потенциально чревато. Ну а для кэширования соединений подходит идеально.
(33) Спасибо. Жаль, этот метод не подойдет в общем случае для внешней обработки.
Хотя, наверно, можно создать универсальную функцию в таком модуле, параметром которой будет текст кода, выполняемого на сервере.
А без этого костыля никак? Мне бы логику разработчиков этого чуда понять! Вот, вроде бы есть возможность переменную объявить, но вроде и нет такой возможности(
P.S.: Я так подозреваю, что дело тут в препроцессоре и надобно с директивами поиграться.
Во встроенном языке программирования 1С используются переменные. Имена переменных должны начинаться с английского или русского символа, или подчеркивания. Нельзя чтобы наименование переменной начиналось с цифры. Не рекомендуется именовать переменные зарезервированными синтаксическими конструкциями. Имена переменных должны носить осмысленный характер. Это улучшает читабельность программного кода. Что в последующем увеличивает скорость разработки или доработки приложения. При объявлении переменных не требуется указывать тип значения, как это делается во многих других языках программирования. Тип значения определяется автоматически системой.
Локальные переменные
Локальные переменные определяются внутри процедур или функций. Перед ними необязательно писать ключевое слово "Перем". Область доступности таких переменных ограничена границами своей процедуры или функции. То есть, к такой переменной нельзя обратиться в другой процедуре или функции или из глобального контекста.
Глобальные переменные
Во многих языках программирования предусмотрено создание глобальных переменных. Во встроенном языке 1С, так же есть возможность создавать глобальные переменные. Такие переменные доступны во всех процедурах и функциях модуля в котором они определены. В языке программирования 1С глобальные переменные могут быть определены в любых модулях (объектов, форм, и т.д) кроме общих модулей. Глобальные переменные задаются в самом верху модуля, перед определением всех процедур и функций. Перед именем переменной пишется ключевое слово "Перем". Значение указывать нельзя. Значение глобальной переменной можно задать в процедурах, функциях модуля или в конце модуля после всех процедур и функций.
Экспортные переменные
Глобальную переменную можно сделать экспортной, указав ключевое слово "Экспорт". Например, если экспортная переменная создаётся в модуле объекта справочника, то к ней можно обратиться через объект этого справочника, СправочникОбъект.ИмяПеременной.
Комментарии (0)
Платформа 8.2 простым штатным способом позволяет реализовывать глобальные переменые на сервере. Достигается это использованием модулей с признаком "Повторное использование возвращаемых значений" установленным в значение "На время сеанса". Установка данного признака заставляет систему помнить все возвращаемые значения. Как сказано в СП:
Если для общего модуля установлено значение "На время вызова" или "На время сеанса", то возвращаемые значения экспортных функций повторно используются в разрезе входных значений их параметров.
Для сброса значений необходимо вызвать функцию:
Таким образом задача решается без всяких извращений.
Для демонстрации приложена конфигурация, с одной единственной обработкой, со следующим текстом:
Модуль "Тест" (Сервер, Вызов сервера):
И модуль "Переменные" (Сервер, Повторное использование возвращаемых значений=На время сеанса):
Ложка дегтя - все что написано выше - неправильно. Везде, где написано "сеанс" надо читать "20 минут после последнего обращения" :(
И вообще - не все по факту так, как написано. Вскоре будут изменения.
Специальные предложения
Сохранение соответствия "ключевые параметры"->"возвращаемое значение" и возможность обращения к нему - это конечно корошо и не только для возврата соответствия, как в примере (вызов непараметризируемой функции), т.к. здесь придется еще позиционироваться на элементе соответствия. Если параметр у функции один - строка - идентификатор переменной, то и получается нечто вроде функции возвращавшей значение параметра сенса в 8.1. А можно и многомерить (составной ключ - значение)
Остается вопрос - сколько вот таких запоминаний может быть в рамках сеанса, и будет ли все это корошо чиститься по завершении сеанса. ;)
(5) данный пример максимально наглядно показывает, что возможно сохранение ссылки на объект. Что за объект - это уже не важно.
Количество сохраняемых объектов платформа не ограничивает.
Чиститься будет, если не будет циклических ссылок
(7) Я бы сказал, что данный пример показывает возможность сохранения соответствия в рамках сеанса и обращения к нему в первую очередь. А что запихано в соответствие - да что угодно, благо там нет ограничения на типы хранимых в соотв. объектов. ;)
(9) почему соответствие? это может быть структура, ТЗ, ВК, .
смысл в том, что хранится именно ссылка, а не копия объекта
(10) в примере то именно соответствие :) Для меня соответствие - это не ссылка. Это агрегатный объект/тип:) А хранить наверное можно все, что может возвращать подобная функция с указанными свойствами, либо агрегатный объект/тип, ею возващаемый.
(11) соответствие для демонстрации выбрано только потому, что в нем проще хранить уникальные значения (дату).
А агрегантный объект может быть либо ссылкой (как в данном примере) либо копией (в типовых 8.1 можно посмотреть функцию глПолучитьЗначениеПеременной(. ) - название может быть несколько не такое)
Я бы еще заголовок темы поменял. Ну как-то не совсем он коррелирует с описанием. Например, из первого предложения темы - "Реализация глобальных переменных и обращение к ним на сервере 8.2". :D
Если быть еще более точным, то читать надо не реже чем каждые 6 минут и даже в этом случае через 20 минут после вычислени все равно "умрет". А может и раньше если не повезет и серверу станет мало памяти.
Возможность очень интересная, но очень неуниверсальная :-( т.к. нет возможности явно управлять временем жизни кеша.
(22) да, да, да.
на момент публикации еще небыло столь подробных комментариев от 1С, а сечас уже есть. и в связи с этим данный механизм уже не столь красив как казалось.
Спасибо! Отлично работает.
Внимание! В 8.3 не работает способ с использованием ПараметрСеанса, описанный тут: http://infostart.ru/public/62410/ , выдаёт ошибку "Переданное значение не может быть помещено во временное хранилище".
Из документации:
Сохраненные значения удаляются:
Если свойство установлено в значение На время вызова:
● на стороне сервера – при возврате управления с сервера;
● на стороне клиента – при завершении работы процедуры или функции встроенного языка верхнего уровня (вызванной системой из интерфейса, а не из другой процедуры или функции встроенного языка);
Если свойство общего модуля установлено в значение На время сеанса:
● на стороне сервера – при окончании сеанса;
● на стороне клиента – при закрытии клиентского приложения.
Сохраненные значения будут удалены:
● на сервере, в толстом клиенте, во внешнем соединении, в тонком клиенте и в веб-клиенте с обычной скоростью соединения – через 20 минут после вычисления сохраняемого значения или через 6 минут после последнего использования;
● в тонком клиенте и веб-клиенте с низкой скоростью соединения – через 20 минут после вычисления сохраняемого значения;
● при нехватке оперативной памяти в рабочем процессе сервера;
● при перезапуске рабочего процесса;
● при переключении клиента на другой рабочий процесс.
После удаления значений вызов экспортируемой функции выполняется как при первом вызове.
А нельзя ли ТАК правильно написать программный код, где "КЕШируемый" вызов будет получать данные только один раз( а не крутить вызовы в теле модуля)? И управление КЕШом всё-таки связать с видимостью ПЕРЕМЕННЫХ? Если пользователь "ушёл с модуля" - почистился КЕШ переменных значений модуля.
Вообще, как бы желательно, САМОМУ (программно) чистить КЕШ НЕ НУЖНЫХ значений(по типу деструктора).
И ещё. Если в общем модуле с повторным использованием выбран "на время сеанса", то чем ЭТО в принципе отличается от использовании параметров сеанса? Это я про "мусор" как в конфигурации, так и в головах
Для решения каких-то задач этот механизм наверняка нужен, удобен и хорош, но никакого отношения к "глобальным переменным на сервере" он не имеет, зачем писать такие вводящие в заблуждения названия статьям? Это "сохранение значения на сервере на время сеанса", а не глобальная переменная.
Переменная - это то, что можно изменить. Собственно, огромный кусок потребностей в глобальных переменных - это чтение-изменение её в разных местах. Есть у меня, например, глобальный счётчик, есть в разных местах процедуры, которые этот счётчик читают, а потом накручивают. Как это можно реализовать в данном механизме? Подозреваю, что как-то можно нахимичить с ОбновитьПовторноИспользуемыеЗначения(), но эти значения, собсна, для того и кэшировались, чтобы их как можно меньше дёргать, а так, получается, для каждого изменения нужно весь кэш сбрасывать (а его может быть очень много) для одной переменной.
Читайте также: