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