При разработке учетных решений в 1С часто возникает задача: отобразить в общем журнале документов или динамическом списке краткое содержание документа (например, наименования первых трех позиций номенклатуры через запятую). Табличные части документов напрямую выводить в стандартные списки не рекомендуется из соображений производительности СУБД, поэтому применяют денормализацию — сохранение краткой строки в реквизит шапки документа при его записи.
Разберем типичные ошибки начинающих разработчиков при реализации этой задачи и пошагово выясним, как правильно настроить метаданные и написать программный код.
Проанализируем частые заблуждения, с которыми сталкиваются разработчики:
ИзменитьРеквизиты(): Программное добавление реквизитов формы создает реквизиты только в оперативной памяти конкретной открытой формы. Такие реквизиты не сохраняются в базе данных и физически не могут быть отображены в журнале документов.ПередЗаписью(Отказ, ПараметрыЗаписи) с двумя параметрами принадлежит модулю формы. Если логика сохранения должна работать независимо от того, как записывается документ (интерактивно через форму или программно из обработки), код должен находиться в модуле объекта, где процедура имеет сигнатуру ПередЗаписью(Отказ) с одним параметром.Рассмотрим порядок действий в конфигураторе. Нам необходимо добавить постоянный реквизит, сохраняемый в базе данных:
КраткийСостав.Теперь разберем алгоритм сбора строк. Откроем модуль объекта документа. Найдем или создадим предопределенную процедуру ПередЗаписью. Нам необходимо обойти строки табличной части (например, первые 3–5 строк), получить наименования и объединить их через запятую.
Посмотрим на пример правильной реализации:
Процедура ПередЗаписью(Отказ)
// Прерываем обработку, если происходит фоновый обмен данными
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
МассивЭлементов = Новый Массив;
// Ограничиваем количество обрабатываемых строк, чтобы не перегружать шапку
КоличествоСтрок = Мин(Товары.Количество(), 3);
Для Индекс = 0 По КоличествоСтрок - 1 Цикл
СтрокаТЧ = Товары[Индекс];
Если ЗначениеЗаполнено(СтрокаТЧ.Номенклатура) Тогда
МассивЭлементов.Добавить(Строка(СтрокаТЧ.Номенклатура));
КонецЕсли;
КонецЦикла;
// Соединяем элементы массива через запятую с пробелом
КраткийСостав = СтрСоединить(МассивЭлементов, ", ");
// Обрезаем строку по максимальной длине реквизита во избежание ошибок переполнения
ДлинаПоля = Метаданные().Реквизиты.КраткийСостав.Тип.КвалификаторыСтроки.Длина;
Если ДлинаПоля > 0 Тогда
КраткийСостав = Лев(КраткийСостав, ДлинаПоля);
КонецЕсли;
КонецПроцедуры
В приведенном коде метод СтрСоединить объединяет массив текстовых представлений номенклатуры в одну строку, а функция Лев() контролирует длину результирующей строки в соответствии с ограничениями метаданных.
Выясним, как вывести заполненный реквизит в общий журнал документов:
СоставДокумента).КраткийСостав).Если требуется, чтобы пользователь видел итоговую строку состава документа прямо на форме сразу в момент добавления или изменения строк, не дожидаясь нажатия кнопки записи, алгоритм переносят в события формы.
Рассмотрим, как это работает на практике: для элемента формы табличной части назначаются обработчики ПослеУдаления и ПриОкончанииРедактирования. В этих процедурах вызывается аналогичный алгоритм формирования строки, который сразу присваивает значение реквизиту Объект.КраткийСостав.
Важное примечание: Новые реквизиты не заполняются автоматически в ранее созданных документах базы данных. Чтобы колонка заполнилась для старых документов, их потребуется перезаписать с помощью группового перепроведения или специальной обработки.