При разработке в расширениях 1С программисты часто сталкиваются с необходимостью добавить возможность прикрепления файлов к новым или существующим объектам метаданных. Если в основной конфигурации используется стандартная библиотека стандартных подсистем (БСП) и ее модуль «Работа с файлами», попытка подключить новый справочник присоединенных файлов через расширение приводит к ошибке выполнения кода. Система выбрасывает исключение при проверке типов параметров.
В этой статье мы подробно разберем, почему возникает данная проблема, как она решается на современных версиях платформы 1С, и какие обходные пути существуют для конфигураций, работающих на старых режимах совместимости.
Рассмотрим детально, как работает механизм прикрепления файлов в БСП. Для хранения файлов создается подчиненный справочник (например, КандидатыПрисоединенныеФайлы для справочника Кандидаты). Чтобы БСП могла единообразно работать со всеми файлами в базе данных, в системе существуют специальные метаданные — Определяемые типы:
ОпределяемыйТип.ПрисоединенныйФайл — содержит список ссылок на все справочники присоединенных файлов в системе.ОпределяемыйТип.ВладелецПрисоединенныхФайлов — содержит список ссылок на объекты-владельцы (документы, справочники), к которым эти файлы прикрепляются.При вызове любой стандартной функции БСП, например, РаботаСФайлами.ДвоичныеДанныеФайла(), первым делом срабатывает жесткая проверка входящих параметров с помощью метода:
ОбщегоНазначенияКлиентСервер.ПроверитьПараметр(
"РаботаСФайлами.ДвоичныеДанныеФайла",
"ПрисоединенныйФайл",
ПрисоединенныйФайл,
Метаданные.ОпределяемыеТипы.ПрисоединенныйФайл.Тип
);
Если тип вашего нового справочника присоединенных файлов отсутствует в определяемом типе основной конфигурации, функция ПроверитьПараметр() вызывает исключение, и дальнейшая работа с файлом становится невозможной.
Сложность заключается в том, что в старых версиях платформы 1С изменять состав определяемых типов внутри расширений было запрещено. Ниже мы детально рассмотрим варианты решения этой проблемы в зависимости от версии вашей платформы.
Если режим совместимости вашей конфигурации установлен в значение 8.3.20.1549 или выше, вам крупно повезло. Фирма «1С» добавила полноценную поддержку определяемых типов в расширениях. Программисту больше не нужно писать сложный обходной код.
Выполним следующие шаги для настройки:
ПрисоединенныйФайл из основной конфигурации.ВладелецПрисоединенныхФайлов.ПрисоединенныйФайл добавим ссылку на наш новый справочник присоединенных файлов (например, СправочникСсылка.КандидатыПрисоединенныеФайлы).ВладелецПрисоединенныхФайлов добавим ссылку на сам объект-владелец (например, СправочникСсылка.Кандидаты).После этого платформа автоматически объединит типы из основной конфигурации и расширения, и стандартные проверки БСП начнут выполняться без ошибок.
Если конфигурация работает в режиме совместимости ниже 8.3.20 (например, 8.3.17 или 8.3.14), расширить определяемые типы напрямую невозможно. В таком случае нам придется программно перехватить вызовы БСП, где происходит проверка типов параметров, используя механизм аннотаций &Вместо.
Проанализируем по шагам, как реализовать этот обход:
Шаг 1. Создание вспомогательной функции для динамического расширения типов
Создадим в общем модуле нашего расширения (например, в модуле с возможностью вызова на клиенте и сервере) функцию, которая будет динамически конструировать правильное описание типов, добавляя к стандартным типам БСП наш тип из расширения:
Функция ПолучитьОписаниеТипов_ПрисоединенныйФайл() Экспорт
// Получаем массив стандартных типов из основной конфигурации
МассивТипов = Метаданные.ОпределяемыеТипы.ПрисоединенныйФайл.Тип.Типы();
// Добавляем наш собственный тип из расширения
МассивТипов.Добавить(Тип("СправочникСсылка.КандидатыПрисоединенныеФайлы"));
// Возвращаем новое описание типов, содержащее все необходимые типы
Возврат Новый ОписаниеТипов(МассивТипов);
КонецФункции
Шаг 2. Перехват функции проверки двоичных данных
Теперь перехватим функцию ДвоичныеДанныеФайла в общем модуле РаботаСФайлами с помощью аннотации &Вместо. Нам нужно подменить передаваемое описание типов в момент проверки:
&Вместо("ДвоичныеДанныеФайла")
Функция Расш_ДвоичныеДанныеФайла(Знач ПрисоединенныйФайл, Знач ВызыватьИсключение = Истина)
// Проверяем, относится ли переданный файл к нашему справочнику из расширения
Если ТипЗнч(ПрисоединенныйФайл) = Тип("СправочникСсылка.КандидатыПрисоединенныеФайлы") Тогда
// Получаем расширенный массив типов
ПрисоединенныйФайл_Тип = ПолучитьОписаниеТипов_ПрисоединенныйФайл();
// Выполняем аналогичную БСП проверку параметров, но с использованием нашего описания типов
ОбщегоНазначенияКлиентСервер.ПроверитьПараметр(
"РаботаСФайлами.ДвоичныеДанныеФайла",
"ПрисоединенныйФайл",
ПрисоединенныйФайл,
ПрисоединенныйФайл_Тип
);
// Ниже пишем вызов оригинального кода получения данных для нашего файла.
// Обычно это обращение к регистру сведений "ДвоичныеДанныеФайлов" или получение из тома.
// (Рекомендуется скопировать типовой алгоритм функции ДвоичныеДанныеФайла из БСП)
Иначе
// Если тип стандартный — просто продолжаем стандартный вызов
Возврат ПродолжитьВызов(ПрисоединенныйФайл, ВызыватьИсключение);
КонецЕсли;
КонецФункции
Аналогичным образом потребуется перехватить другие ключевые функции общего модуля РаботаСФайлами, в которых жестко вызывается метод ПроверитьПараметр (например, функцию ДанныеФайла).
Существует еще один изящный способ, который позволяет полностью избежать изменения программного кода БСП и перехвата функций контроля типов. Мы можем использовать стандартный справочник БСП ПапкиФайлов в качестве посредника.
Разберем этот метод подробнее:
СвязьОбъектовИПапокФайлов), который будет связывать наш справочник Кандидаты из расширения с элементами справочника ПапкиФайлов из основной конфигурации.Кандидаты) программно создаем новый элемент в справочнике ПапкиФайлов с наименованием, соответствующим нашему кандидату, и записываем эту связь в созданный регистр сведений.Кандидата, а найденную или созданную для него ПапкуФайлов.Поскольку справочник ПапкиФайлов изначально входит во все определяемые типы БСП, система без каких-либо доработок и ошибок проверки типов позволит добавлять, просматривать, изменять и удалять файлы. Для пользователя этот процесс будет выглядеть абсолютно прозрачно.
Даже если мы успешно обойдем проверку типов параметров, при работе с файлами в расширении могут возникнуть сопутствующие проблемы. Проанализируем самые частые из них и способы их устранения:
1. Ошибки при записи в регистр «ФайлыВРабочемКаталоге»
При открытии файлов на редактирование БСП фиксирует это в регистре сведений ФайлыВРабочемКаталоге. Измерение Файл в данном регистре имеет тип ОпределяемыйТип.ПрисоединенныйФайл. На старых платформах запись в этот регистр для файлов из расширения может завершиться ошибкой базы данных. В этом случае придется также перехватывать процедуры записи в данный регистр через &Вместо или использовать Решение 3 с папками файлов.
2. Отсутствие пиктограмм (иконок) файлов в списках
Иногда файлы, созданные через расширение, отображаются в списках со стандартной «пустой» иконкой вместо значков Word, Excel или PDF. Это происходит из-за того, что при создании записи не заполнился индекс картинки. Чтобы решить эту проблему, в процедуре создания или записи присоединенного файла принудительно вызывайте заполнение индекса:
ПрисоединенныйФайл.ИндексКартинки = РаботаСФайламиСлужебныйКлиентСервер.ПолучитьИндексПиктограммыФайла(ПрисоединенныйФайл.Расширение);
3. Хранение файлов в томах на диске
Если в вашей базе настроено хранение файлов в томах на диске, БСП определяет путь к физическому файлу на основе типа его владельца. Убедитесь, что подписки на события БСП (например, очистка файлов при удалении владельца) корректно обрабатывают ваш новый справочник из расширения. В случае сбоев вам потребуется вручную реализовать аналогичную логику очистки в модуле объекта вашего справочника.
Вывод: выбор решения зависит от версии платформы, на которой работает ваша база 1С. Если есть возможность обновить платформу и режим совместимости до версии 8.3.20 — используйте встроенный механизм определяемых типов в расширениях. Если база работает на старой платформе и изменения основной конфигурации запрещены, оптимальным выбором будет перехват функций через &Вместо или использование архитектурного маневра со справочником-посредником.