При разработке на платформе 1С:Предприятие 8.3 с использованием управляемых форм программисты часто сталкиваются с загадочной ситуацией: один реквизит формы доступен в коде модуля, а другой — нет, хотя визуально они настроены идентично. Более того, попытка обратиться к стандартным свойствам, таким как Объект, ЭтаФорма или Элементы, приводит к ошибке «Переменная не определена». Проанализируем, почему это происходит и как правильно организовать работу с серверным кодом.
Разберем ситуацию, описанную в теме. У автора есть форма обработки, на которой расположены реквизиты (например, номера колонок). Один реквизит виден, другие — нет. Причина кроется не в «глюках» платформы или кеше, а в использовании директивы компиляции &НаСервереБезКонтекста.
В управляемом приложении 1С разделяет выполнение кода на клиентскую и серверную части. Когда мы вызываем серверную процедуру, платформа должна решить: передавать ли на сервер все данные формы (состояние всех реквизитов, элементов управления, табличных частей) или выполнить «чистый» вызов без лишнего багажа. Рассмотрим подробнее, что происходит при использовании разных директив:
Контекст), упаковывает его (сериализует), передает на сервер, там распаковывает, выполняет код и возвращает измененный контекст обратно на клиент.ЭтаФорма вызывает ошибку компиляции.Проанализируем пример автора: КолонкаНаименование была видна только потому, что она передавалась в процедуру как входящий параметр. Остальные же реквизиты игнорировались компилятором, так как контекст формы в данной процедуре отсутствовал.
Самый простой и быстрый способ решить проблему, если производительность не является критическим фактором, — это изменить директиву компиляции. Рассмотрим, как это сделать:
Вместо использования директивы &НаСервереБезКонтекста укажем обычную &НаСервере. После этого в процедуре станут доступны все реквизиты формы, а также встроенные объекты.
&НаСервере
Процедура ОбработатьДанныеНаСервере()
// Теперь нам доступны все реквизиты напрямую
НомерКолонки = КолонкаКодСтроки;
ТекстНаименования = Объект.Наименование;
Элементы.ГруппаКолонки.Видимость = Ложь;
КонецПроцедуры
Важный момент: Используйте этот метод осознанно. Если на форме есть огромная табличная часть (десятки тысяч строк), каждый такой вызов будет «гонять» эти данные между клиентом и сервером, что может замедлить работу интерфейса.
Если мы хотим следовать принципам Best Practice и не нагружать систему лишними данными, следует оставить &НаСервереБезКонтекста, но передать нужные значения явно. Посмотрим на пример, как это реализовать правильно:
&НаКлиенте
Процедура ВыполнитьДействие()
// Подготавливаем данные для передачи
ПараметрыРасчета = Новый Структура;
ПараметрыРасчета.Вставить("КодСтроки", КолонкаКодСтроки);
ПараметрыРасчета.Вставить("Наименование", КолонкаНаименование);
// Вызываем сервер без передачи всего контекста
Результат = РассчитатьНаСервере(ПараметрыРасчета);
КонецПроцедуры
&НаСервереБезКонтекста
Функция РассчитатьНаСервере(Данные)
// Здесь реквизиты формы недоступны, работаем только с тем, что получили
Возврат Данные.КодСтроки + " " + Данные.Наименование;
КонецФункции
Этот подход предпочтителен в высоконагруженных системах, так как мы передаем только те 10-20 байт, которые действительно нужны серверу, вместо мегабайтов данных всей формы.
Нужно учитывать еще один нюанс: в неконтекстных вызовах недоступен метод РеквизитВЗначение("Объект"). Если вам нужно вызвать метод, написанный в модуле объекта обработки, вам придется использовать либо контекстный вызов &НаСервере, либо считывать объект из базы данных (если это не внешняя обработка, а объект конфигурации) по ссылке.
Проанализируем ситуацию, когда нужно вызвать экспортный метод объекта:
&НаСервере
Процедура ВызватьМетодОбъекта()
// Преобразуем данные формы в реальный объект
ОбъектОбработка = РеквизитВЗначение("Объект");
// Вызываем метод, описанный в модуле объекта
ОбъектОбработка.ВыполнитьСложнуюЛогику();
// Возвращаем изменения обратно в форму
ЗначениеВРеквизит(ОбъектОбработка, "Объект");
КонецПроцедуры
Выясним, какой способ подходит именно вам. Выбор зависит от архитектуры вашей задачи:
&НаСервере. Это упростит код и избавит от необходимости передавать десятки параметров.&НаСервереБезКонтекста и передавайте данные через объект Структура.Объект или Элементы — первым делом проверьте директиву над процедурой. В 99% случаев там будет стоять БезКонтекста.Помните, что чистота кода и производительность идут рука об руку. Понимание того, как платформа 1С управляет данными между клиентом и сервером, позволяет создавать быстрые и стабильные решения.