При разработке в среде 1С:Предприятие 8 начинающие программисты часто сталкиваются с ситуацией, когда созданный общий модуль отказывается работать, выдавая ошибку «Переменная не определена». Рассмотрим типичный сценарий: вы создали общий модуль Даты, написали там экспортную функцию для получения текущего времени, но при попытке вызвать её из формы документа система сообщает об ошибке. Разберем детально, почему это происходит, и выясним, как организовать заполнение данных профессионально.
Проанализируем ситуацию: код в модуле формы выполняется на стороне клиента (директива &НаКлиенте), а общий модуль по умолчанию может быть настроен на выполнение только на сервере. В 1С клиентское приложение и сервер — это разные процессы, и клиент «не видит» серверные модули, если для них не установлены специальные разрешения.
Чтобы исправить эту проблему, нам необходимо настроить свойства общего модуля. Рассмотрим по шагам:
Даты.ПриОткрытии (которая выполняется на клиенте), должен быть установлен флаг Клиент (управляемое приложение).Важное замечание: Если у модуля установлен признак Глобальный, то обращение к его методам происходит без указания имени модуля. То есть вместо Даты.ВозвратТекущейДаты() нужно писать просто ВозвратТекущейДаты(). Использование точки при включенном флаге «Глобальный» также приведет к ошибке.
В коде автора используется функция ТекущаяДата(). Проанализируем, почему в многопользовательских системах это может стать проблемой. Рассмотрим пример: сервер 1С находится в Москве (UTC+3), а бухгалтер работает во Владивостоке (UTC+10). Функция ТекущаяДата() вернет время сервера (московское), что будет некорректно для дальневосточного филиала.
Согласно стандартам разработки 1С, рекомендуется использовать функцию ТекущаяДатаСеанса(). Она учитывает часовой пояс, установленный для конкретного пользователя в настройках его сеанса. Это гарантирует, что в документ запишется именно то время, которое видит пользователь на своих часах.
Перейдем к самому важному аспекту — архитектуре. Заполнение реквизитов документа в событии формы ПриОткрытии или ПриСозданииНаСервере считается плохой практикой (так называемым «говнокодом»). Выясним причину:
Если мы прописываем логику в форме, она сработает только тогда, когда пользователь открывает документ интерактивно. Если же документ будет создаваться программно (например, на основании другого документа, через обработку загрузки данных из Excel или через веб-сервис), форма не откроется, код не выполнится, и поле Дата останется пустым.
Рассмотрим правильный подход — использование модуля объекта и процедуры ОбработкаЗаполнения. Этот метод вызывается всегда при создании нового объекта, независимо от того, открывается форма или нет.
Разберем пример кода в модуле объекта:
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
// Проверяем, что это именно новый документ, а не перезаполнение существующего
Если ЭтоНовый() Тогда
// Используем ТекущаяДатаСеанса для учета часового пояса
Дата = ТекущаяДатаСеанса();
КонецЕсли;
КонецПроцедуры
Вызов общего модуля из процедуры ПриОткрытии на клиенте порождает лишний «сетевой прыжок» (round-trip). Это замедляет работу системы, так как компьютер пользователя должен отправить запрос серверу, дождаться ответа и только потом продолжить работу. Проанализируем, как этого избежать.
Если вам все же необходимо донастроить что-то именно в форме, используйте событие ПриСозданииНаСервере. Это событие выполняется один раз при инициализации формы на стороне сервера, и здесь можно обращаться к любым серверным общим модулям без лишних сетевых задержек.
Посмотрим на пример в модуле формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Если документ новый и дата еще не заполнена (например, в ОбработкаЗаполнения)
Если Объект.Ссылка.Пустая() И Объект.Дата = '00010101' Тогда
Объект.Дата = ТекущаяДатаСеанса();
КонецЕсли;
КонецПроцедуры
В современных конфигурациях (таких как УТ 11, ERP, БП 3.0) уже внедрена БСП. Нам не нужно создавать собственные велосипеды для получения даты. Рассмотрим, как это реализовано профессионалами. В БСП существует общий модуль ОбщегоНазначения, который уже имеет все необходимые флаги компиляции.
Вместо создания своего модуля Даты, мы можем вызвать:
ОбщегоНазначения.ТекущаяДатаСеанса()
Подведем итог нашему исследованию. Для того чтобы ваша функция заработала, а код соответствовал стандартам 1С, придерживайтесь следующих правил:
ОбработкаЗаполнения.ТекущаяДатаСеанса() вместо ТекущаяДата(), чтобы избежать проблем с часовыми поясами.ПриОткрытии или НаКлиенте, если это не продиктовано логикой интерфейса.Соблюдение этих простых, но важных правил позволит вам создавать надежные и производительные решения на платформе 1С, которые не «сломаются» при обновлении или изменении способа записи данных.