Как передать реквизит формы в параметр запроса в 1С 8.3 и правильно заполнить контактную информацию

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке обработок и кастомизации конфигураций на платформе 1С:Предприятие 8.3 начинающие разработчики часто сталкиваются с трудностями при передаче данных между клиентом и сервером. Типичный сценарий: на управляемой форме есть реквизит, значение которого необходимо использовать в качестве параметра запроса в серверной процедуре. Другая частая проблема — корректное сохранение измененных данных обратно в базу данных, особенно когда речь идет о сложных структурах вроде контактной информации.

В этой статье мы подробно разберем, как устроен контекст управляемой формы, как правильно передавать реквизиты в параметры запроса на сервере, а также проанализируем и исправим критические методические ошибки, связанные с ручным формированием XML-структур контактной информации, заменив их на стандартные механизмы Библиотеки стандартных подсистем (БСП).

Понимание контекста управляемой формы в 1С

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

Когда мы объявляем процедуру с директивой &НаСервере, платформа осуществляет контекстный вызов. Это означает, что на сервер передаются все данные управляемой формы. Внутри такой процедуры мы имеем прямой доступ ко всем реквизитам формы по их именам, как если бы они были локальными переменными.

Посмотрим на код автора из первого сообщения темы:


&НаСервере 
Процедура ЗаполнитКИНаСервере() 
    Запрос = Новый Запрос; 
    Запрос.Текст = "..."; 
    Запрос.УстановитьПараметр("Партнер", Партнер); // Обращение к реквизиту формы напрямую
    ...
КонецПроцедуры

Этот код абсолютно работоспособен. Поскольку процедура выполняется в контексте формы (директива &НаСервере), реквизит формы Партнер доступен напрямую. Нам не требуется передавать его с клиента в качестве параметра процедуры.

Альтернативный вариант: явная передача параметров

Рассмотрим ситуацию, когда нам все же требуется передать реквизит формы в качестве параметра. Это становится обязательным, если мы используем директиву &НаСервереБезКонтекста. Внеконтекстные серверные вызовы работают значительно быстрее, так как платформа не гоняет данные всей формы между клиентом и сервером. В этом случае сервер ничего не знает о реквизитах формы, и их нужно передавать явно.

Давайте разберем по шагам, как реализовать явную передачу параметров:

  1. На клиенте при вызове серверного метода мы передаем реквизит формы в качестве аргумента.
  2. На сервере мы принимаем этот аргумент в качестве параметра процедуры и передаем его в запрос.

Посмотрим на пример реализации этого подхода:


&НаКлиенте
Процедура ЗаполнитКИ(Команда)
    // Передаем значение реквизита "Партнер" в серверный метод
    ЗаполнитКИНаСервере(Партнер); 
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ЗаполнитКИНаСервере(Знач ВыбранныйПартнер)
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
    "ВЫБРАТЬ
    |	ПартнерыКонтактнаяИнформация.Представление КАК Представление
    |ИЗ
    |	Справочник.Партнеры.КонтактнаяИнформация КАК ПартнерыКонтактнаяИнформация
    |ГДЕ
    |	ПартнерыКонтактнаяИнформация.Ссылка = &Партнер";
    
    // Устанавливаем параметр запроса, полученный из аргумента процедуры
    Запрос.УстановитьПараметр("Партнер", ВыбранныйПартнер);
    
    РезультатЗапроса = Запрос.Выполнить();
    // Дальнейшая обработка данных...
    
КонецПроцедуры

Использование директивы &НаСервереБезКонтекста является более производительным и считается хорошим тоном в профессиональной разработке на 1С.

Критические ошибки в коде заполнения контактной информации

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

Выясним причины, почему код автора из Сообщения 6 является небезопасным:

1. Ручное формирование XML для поля "ЗначенияПолей"

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

2. Избыточные запросы к СУБД

В цикле обработки результатов запроса автор выполняет метод ПолучитьОбъект(). Запрос и так выполняется по конкретному партнеру, выбранному на форме. Выполнять тяжелый запрос к табличной части КИ, чтобы потом все равно получать объект в цикле — нерационально. Намного быстрее сразу получить объект партнера, обойти его табличную часть в оперативной памяти, внести изменения и записать.

3. Ненадежный парсинг телефонного номера

Использование функции Прав(Представление, 10) для получения номера без кода страны крайне хрупко. Если представление номера заполнено в формате +7 (999) 123-45-67, функция вернет строку со скобками и дефисами, что приведет к записи "мусора" в базу данных. Очистка номера должна выполняться по строгим правилам.

Правильное решение с использованием механизмов БСП

Для работы с контактной информацией в любой современной типовой конфигурации 1С (ERP, КА, УТ, УНФ, БП) предназначен общий модуль УправлениеКонтактнойИнформацией. Он автоматически парсит любые представления телефонов, очищает их от лишних символов и корректно формирует XML и JSON "под капотом".

Проанализируем правильный вариант реализации нашей задачи без написания "велосипедов":


&НаСервере
Процедура ЗаполнитКИНаСервере()
	
	// Проверяем, заполнено ли поле на форме
	Если Не ЗначениеЗаполнено(Партнер) Тогда
		ВызватьИсключение "Не выбран партнер для обработки!";
	КонецЕсли;
	
	// Получаем ссылки на виды и типы контактной информации
	ВидКИ = Справочники.ВидыКонтактнойИнформации.ТелефонПартнера;
	ТипКИ = Перечисления.ТипыКонтактнойИнформации.Телефон; 
	
	// Получаем объект партнера для изменения данных напрямую
	ПартнерОбъект = Партнер.ПолучитьОбъект();
	Модифицирован = Ложь;
	
	// Нам не нужен запрос к БД. Обходим табличную часть контактной информации объекта в памяти
	Для Каждого СтрокаКИ Из ПартнерОбъект.КонтактнаяИнформация Цикл
		
		Если СтрокаКИ.Вид = ВидКИ И СтрокаКИ.Тип = ТипКИ Тогда
			
			ПредставлениеНомера = СтрокаКИ.Представление;
			
			// Нас интересует телефон, у которого заполнено представление, но не разобран номер
			Если ЗначениеЗаполнено(ПредставлениеНомера) 
				И ПустаяСтрока(СтрокаКИ.НомерТелефонаБезКодов) Тогда
				
				// 1. Используем БСП для разбора строкового представления во внутреннюю структуру (JSON/XML)
				// Функция сама определит коды страны, города и очистит номер от форматирования
				СтруктураКИ = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияПоПредставлению(ПредставлениеНомера, ВидКИ);
				
				// 2. Записываем полученную структуру обратно в табличную часть объекта партнера
				// Этот метод БСП гарантирует заполнение всех служебных полей (Значение, ЗначенияПолей, НомерТелефона)
				УправлениеКонтактнойИнформацией.ЗаписатьКонтактнуюИнформацию(ПартнерОбъект, СтруктураКИ, ВидКИ, ТипКИ);
				
				Модифицирован = Истина;
				
			КонецЕсли;
			
		КонецЕсли;
		
	КонецЦикла;
	
	// Записываем объект только при наличии изменений
	Если Модифицирован Тогда
		ПартнерОбъект.Записать();
		Сообщить("Контактная информация партнера успешно обновлена стандартными средствами БСП.");
	Иначе
		Сообщить("Нет данных для обновления контактной информации.");
	КонецЕсли;
	
КонецПроцедуры

Преимущества правильного подхода

Давайте подытожим, почему использование системного модуля БСП предпочтительнее ручной сборки данных:

Используйте встроенные механизмы БСП в своих разработках — это экономит ваше время и гарантирует стабильную работу системы!

← На главную