В практике разработки на платформе 1С часто возникает ситуация, когда типовой функционал требует строгой аналитики (например, ссылки на справочник Склады), а конечный пользователь хочет «гибкости экселя» — возможности вписать название склада текстом прямо в документ. Проблема заключается в том, что изменение типа реквизита на составной (Ссылка + Строка) влечет за собой перекрестные изменения в регистрах, отчетах и механизмах обмена данными. Разберем подробно, как решить эту задачу, сохранив чистоту архитектуры и удовлетворив требования пользователя.
Рассмотрим классический пример: документ «Списание товаров». В нем есть реквизит Склад с типом СправочникСсылка.Склады. Нам необходимо сделать так, чтобы пользователь мог вводить произвольный текст, который будет сохраняться, но при этом сам реквизит Склад в метаданных оставался ссылочным. Проанализируем, почему это сложно: 1С жестко контролирует типы данных, и попытка записать строку в поле ссылки приведет к ошибке или очистке поля.
Основные подходы к решению:
Этот метод считается наиболее элегантным с точки зрения пользовательского интерфейса. Мы не меняем структуру хранения данных в основном реквизите, но создаем для пользователя иллюзию «умного поля».
Рассмотрим алгоритм реализации по шагам:
СкладНаименованиеСтрока с типом Строка (100). Он будет реально хранить текст в базе.СкладДляФормы с составным типом: СправочникСсылка.Склады и Строка.СкладДляФормы на месте стандартного поля склада.Теперь проанализируем программную логику в модуле формы. Нам нужно обеспечить связку при открытии и сохранении документа.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Если ссылка на склад заполнена, показываем её, иначе — текст
Если ЗначениеЗаполнено(Объект.Склад) Тогда
СкладДляФормы = Объект.Склад;
Иначе
СкладДляФормы = Объект.СкладНаименованиеСтрока;
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
// Распределяем данные из виртуального поля в реальные реквизиты
Если ТипЗнч(СкладДляФормы) = Тип("Строка") Тогда
ТекущийОбъект.СкладНаименованиеСтрока = СкладДляФормы;
// Чтобы не ломать логику проведения, можно очистить ссылку
// или заполнить её «Складом по умолчанию»
ТекущийОбъект.Склад = Справочники.Склады.ПустаяСсылка();
Иначе
ТекущийОбъект.Склад = СкладДляФормы;
ТекущийОбъект.СкладНаименованиеСтрока = "";
КонецЕсли;
КонецПроцедуры
Этот способ позволяет пользователю писать что угодно, сохраняя при этом возможность выбора из справочника. Однако стоит помнить, что типовые отчеты по-прежнему будут видеть пустой склад, если пользователь ввел текст.
Если задача пользователя — просто видеть правильное название в печатной форме, мы можем предложить более простой путь, не требующий создания новых реквизитов в метаданных (если это критично). Проанализируем ситуацию: пользователь может выбрать в поле склад значение «Прочие склады» (созданный нами элемент справочника), а в стандартном поле Комментарий написать уточнение.
Для реализации этого подхода выполним следующее:
Склады элемент с наименованием "Ввод вручную" или "Прочие".Посмотрим на пример кода для модификации печатной формы:
// В процедуре формирования печатной формы
ПредставлениеСклада = "";
Если Объект.Склад = Справочники.Склады.НайтиПоНаименованию("Прочие") Тогда
// Если выбран спец-склад, берем название из комментария или доп. реквизита
ПредставлениеСклада = Объект.Комментарий;
Иначе
ПредставлениеСклада = СокрЛП(Объект.Склад.Наименование);
КонецЕсли;
ОбластьМакета.Параметры.СкладНазвание = ПредставлениеСклада;
Этот метод — самый безопасный для системы. Он не раздувает базу данных, не меняет структуру индексов SQL и гарантирует, что при обмене данными (например, в Бухгалтерию) документ не «отвалится» из-за неверного типа данных.
Если ваша конфигурация использует «Библиотеку стандартных подсистем» (БСП), то лучшим решением будет использование механизма Дополнительных реквизитов. Проанализируем преимущества: вам не нужно менять конфигурацию в конфигураторе, всё настраивается в пользовательском режиме.
Выясним, как это работает:
Это решение идеально подходит для ситуаций, когда нужно «вчера», а бюджет на разработку ограничен. Программисту останется только подправить печатную форму, чтобы она приоритетно выводила значение этого доп. реквизита.
Рассмотрим подробнее, почему разработчики 1С так сопротивляются превращению ссылочных полей в строковые. Выясним причину через архитектуру хранения данных в SQL.
1. Структура таблиц SQL. При использовании составного типа данных (Ссылка + Строка) вместо одной колонки _Fld123RRef в базе SQL создаются три: _Fld123_TYPE (тип), _Fld123_RRef (идентификатор ссылки) и _Fld123_S (сама строка). Это увеличивает объем данных и замедляет выполнение запросов.
2. Проблемы индексации. Поиск и группировка по строковым полям неопределенной длины работают значительно медленнее, чем по внутренним идентификаторам (GUID). Если у вас тысячи документов списания, отчет «Ведомость по товарам» может начать «тормозить» при попытке разыменовать такие поля.
3. Сходимость данных. Проанализируем человеческий фактор. Пользователь напишет «Склад 1», «склад 1», «Склад №1» и «Склад 1 » (с пробелом). Для 1С это четыре разных склада. При попытке построить отчет вы получите «чехарду» данных, которую невозможно будет свести автоматически. Именно поэтому рекомендуется всегда настаивать на заведении элементов в справочнике.
Прежде чем приступать к кодингу, проведем «воспитательную беседу» с заказчиком. Важно объяснить, что 1С — это не печатная машинка, а система учета. Предложите пользователю альтернативу:
Подразделения, не подменяя понятия.Таким образом, мы рассмотрели несколько путей решения задачи. Самым надежным является использование дополнительных реквизитов или подмена поля на форме с сохранением данных в отдельную строку. Это позволяет избежать «мусора» в аналитических отчетах и при этом дает пользователю необходимую свободу ввода.