При разработке конфигураций на платформе 1С:Предприятие часто возникает задача автоматизации ввода данных. Одним из наиболее распространенных сценариев является автоматическое формирование стандартного реквизита Наименование на основе других полей объекта (например, дополнительного названия и расшифровки), а также на основе строк его табличной части. Это позволяет минимизировать человеческий фактор, исключить опечатки и поддерживать единый стандарт ведения нормативно-справочной информации (НСИ) в базе данных.
В этой статье мы подробно разберем, как решить эту задачу профессионально. Мы изучим простую конкатенацию строк, определим наиболее подходящие архитектурные места для размещения программного кода, научимся быстро собирать данные из табличных частей без потери производительности системы и рассмотрим важные подводные камни, с которыми сталкиваются разработчики.
Для начала рассмотрим базовый сценарий: у нас есть объект справочника, содержащий стандартный реквизит Наименование, а также два дополнительных реквизита: Название (строка) и Расшифровка (строка). Нам необходимо сделать так, чтобы наименование принимало вид: Название (расшифровка в нижнем регистре).
Для приведения текста расшифровки к нижнему регистру мы используем встроенную функцию платформы НРег. Самый простой вариант слияния строк выглядит следующим образом:
Наименование = Название + " (" + НРег(Расшифровка) + ")";
Этот код отлично решает задачу в лоб, но для его надежной работы в реальной системе необходимо учесть множество нюансов: от пустых значений до места вызова этой процедуры.
Один из самых важных вопросов, возникающих при реализации автозаполнения: на какое событие вешать выполнение данного кода? В профессиональной разработке 1С выделяют два основных подхода.
Подход 1: Заполнение в модуле объекта (Событие ПередЗаписью) — Рекомендуемый метод
Этот подход считается наиболее надежным и правильным с точки зрения архитектуры платформы. Размещение логики в предопределенной процедуре ПередЗаписью модуля объекта гарантирует, что поле Наименование заполнится абсолютно всегда. Это сработает не только при интерактивном сохранении элемента пользователем на форме, но и при программном создании объектов (например, при загрузке данных из внешних файлов Excel, XML, через REST API или в процессе синхронизации данных между базами).
Проанализируем пример кода, который размещается в модуле объекта справочника:
Процедура ПередЗаписью(Отказ)
// Обязательно проверяем, не идет ли загрузка данных из внешних систем.
// При обмене данными автозаполнение обычно отключают, чтобы сохранить оригинальные наименования.
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Проверяем заполненность ключевого поля "Название"
Если ЗначениеЗаполнено(Название) Тогда
// Используем тернарный оператор для обработки пустой расшифровки
ДобавочныйТекст = ?(ЗначениеЗаполнено(Расшифровка), " (" + НРег(Расшифровка) + ")", "");
Наименование = Название + ДобавочныйТекст;
КонецЕсли;
КонецПроцедуры
Подход 2: Интерактивное обновление на форме (Событие ПриИзменении)
Этот вариант необходим для обеспечения качественного пользовательского интерфейса (UX). Если код написан только в модуле объекта, пользователь увидит сформированное наименование только после нажатия кнопки "Записать". До этого момента поле на экране будет оставаться пустым или неактуальным.
Чтобы наименование обновлялось на экране «на лету» при вводе данных в поля Название или Расшифровка, мы привязываем обработчики событий к элементам управления на форме:
&НаКлиенте
Процедура НазваниеПриИзменении(Элемент)
ОбновитьНаименованиеНаФорме();
КонецПроцедуры
&НаКлиенте
Процедура РасшифровкаПриИзменении(Элемент)
ОбновитьНаименованиеНаФорме();
КонецПроцедуры
&НаКлиенте
Процедура ОбновитьНаименованиеНаФорме()
// Формируем строковое значение непосредственно на клиенте для мгновенного отображения
ДобавочныйТекст = ?(ЗначениеЗаполнено(Объект.Расшифровка), " (" + НРег(Объект.Расшифровка) + ")", "");
Объект.Наименование = Объект.Название + ДобавочныйТекст;
КонецПроцедуры
Золотой стандарт разработки: Совмещение обоих подходов. Мы пишем код обновления на форме для визуального удобства пользователя, но обязательно дублируем (или полностью переносим ключевую проверку) в модуль объекта ПередЗаписью для обеспечения железной целостности данных при любых программных манипуляциях.
Теперь разберем более сложную задачу: что делать, если часть наименования должна собираться из строк табличной части (ТЧ) нашего объекта? Напрямую обратиться через точку к реквизитам ТЧ (например, написать Объект.ТабличнаяЧасть.Реквизит) нельзя, поскольку табличная часть — это коллекция строк.
Выясним, какими способами можно быстро и эффективно решить эту задачу.
Если в табличной части хранится перечень текстовых значений (например, список характеристик или комплектующих) и нам нужно просто перечислить их через запятую в наименовании, оптимальным решением в современных версиях 1С:Предприятие 8.3 является использование метода ВыгрузитьКолонку() и функции глобального контекста СтрСоединить(). Это позволяет полностью отказаться от медленных циклов обхода строк.
Рассмотрим пример реализации:
// Шаг 1. Выгружаем все значения из нужной колонки табличной части в массив
МассивЗначений = ТабличнаяЧасть.ВыгрузитьКолонку("Свойство");
// Шаг 2. Объединяем элементы массива в одну строковую переменную, разделяя их запятыми
СтрокаИзТабличнойЧасти = СтрСоединить(МассивЗначений, ", ");
// Шаг 3. Составляем итоговое наименование объекта
Если ЗначениеЗаполнено(СтрокаИзТабличнойЧасти) Тогда
Наименование = Название + " (" + СтрокаИзТабличнойЧасти + ")";
Иначе
Наименование = Название;
КонецЕсли;
Часто на практике в табличной части могут присутствовать пустые строки или повторяющиеся значения. Сваливать их в кучу в наименовании — плохой тон. В таком случае мы применим классический обход коллекции строк с использованием вспомогательного объекта СписокЗначений для фильтрации дубликатов:
СписокУникальных = Новый СписокЗначений;
// Обходим табличную часть построчно
Для Каждого СтрокаТЧ Из ТабличнаяЧасть Цикл
ТекущееЗначение = СтрокаТЧ.Свойство;
// Проверяем заполненность значения и его отсутствие в нашем списке уникальных элементов
Если ЗначениеЗаполнено(ТекущееЗначение)
И СписокУникальных.НайтиПоЗначению(ТекущееЗначение) = Неопределено Тогда
СписокУникальных.Добавить(ТекущееЗначение);
КонецЕсли;
КонецЦикла;
// Получаем массив уникальных значений и объединяем его в строку
МассивУникальных = СписокУникальных.ВыгрузитьЗначения();
СтрокаИзТабличнойЧасти = СтрСоединить(МассивУникальных, ", ");
// Записываем результат
Наименование = Название + ?(ЗначениеЗаполнено(СтрокаИзТабличнойЧасти), " (" + СтрокаИзТабличнойЧасти + ")", "");
Проанализируем ключевые моменты, о которых начинающие разработчики часто забывают, что приводит к критическим ошибкам в рабочей базе данных.
Наименование:
У каждого справочника в метаданных жестко задана максимальная длина наименования (обычно это 25, 50, 100 или 150 символов). Если пользователь введет длинное название, подробную расшифровку, да еще и табличная часть будет содержать много строк, итоговая строка превысит допустимый лимит. При попытке записи система вызовет ошибку или автоматически обрежет строку в случайном месте, сломав скобки.
Лев().
// Динамически получаем максимальную длину наименования из метаданных данного объекта
МаксДлина = Метаданные().ДлинаНаименования;
ИтоговыйТекст = Название + ?(ЗначениеЗаполнено(Расшифровка), " (" + НРег(Расшифровка) + ")", "");
// Безопасно обрезаем строку, если она превышает лимит
Наименование = Лев(ИтоговыйТекст, МаксДлина);
СтрШаблон:
Для повышения читаемости кода и ухода от громоздкого сложения строк через операторы "+" рекомендуется использовать функцию СтрШаблон. Это делает код более изящным и простым в поддержке:
// Пример красивого форматирования строки шаблоном
Наименование = СтрШаблон("%1 (%2)", Название, НРег(Расшифровка));
Наименование в вашей конфигурации теперь рассчитывается и заполняется строго по заданному алгоритму, обязательно заблокируйте его для ручного редактирования пользователем на форме. Для этого найдите элемент формы Наименование и установите его свойство ТолькоПросмотр в значение Истина. Это убережет базу от рассогласования данных, когда пользователь вручную пишет одно, а реквизиты объекта утверждают совершенно другое.
Применяя данные подходы, вы сможете создавать надежные, быстродействующие алгоритмы автоматического заполнения полей, которые значительно упростят работу конечных пользователей программных продуктов 1С.