Как исправить ошибку "Недостаточно фактических параметров" и настроить перетаскивание файлов в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке на управляемых формах в 1С программисты часто сталкиваются с ошибками вызова процедур и функций, а также с трудностями при реализации интерактивных механизмов, таких как Drag-and-Drop (перетаскивание файлов). Разберем по шагам, почему возникает ошибка "Недостаточно фактических параметров", как правильно спроектировать вызовы методов и как прикрутить удобное перетаскивание файлов из операционной системы прямо в форму 1С.

Проанализируем причину ошибки "Недостаточно фактических параметров"

Рассмотрим ситуацию, когда при выполнении кода платформа выдает ошибку: Недостаточно фактических параметров (ДобавитьФайлы). Чтобы быстро найти проблемное место в модуле, воспользуемся удобной комбинацией клавиш: нажмем Ctrl + G и введем номер строки, указанный в тексте ошибки (в нашем случае это строка 77). Это переместит курсор прямо на ошибочный метод.

Выясним причину на примере исходного кода. Процедура добавления файлов была объявлена следующим образом:


&НаКлиенте 
Процедура ДобавитьФайлы(Команда) 
    Если ЗначениеЗаполнено(Объект.Ссылка) Тогда 
        Оповещение = Новый ОписаниеОповещения("ОбработатьВыборФайла", ЭтотОбъект); 
        НачатьПомещениеФайла(Оповещение, , , Истина, УникальныйИдентификатор); 
    Иначе 
        Оповещение = Новый ОписаниеОповещения("ОтветНаВопросЗаписать", ЭтотОбъект); 
        ТекстВопроса = "Элемент не записан, Записать?"; 
        ПоказатьВопрос(Оповещение, ТекстВопроса, РежимДиалогаВопрос.ДаНет); 
    КонецЕсли; 
КонецПроцедуры

Эта процедура описана как обработчик команды формы, поэтому она ожидает один обязательный параметр — Команда. Однако в другом месте кода (в обработчике ответа на вопрос) программист пытается вызвать её как непараметризуемую:


&НаКлиенте 
Процедура ОтветНаВопросЗаписать(Результат, ДополнительныеПараметры) Экспорт 
    Если Результат = КодВозвратаДиалога.Да Тогда 
        ЭтотОбъект.Записать(); 
        ДобавитьФайлы; // ОШИБКА ЗДЕСЬ
    КонецЕсли; 
КонецПроцедуры

Платформа видит, что процедура ДобавитьФайлы требует один параметр, а передано ноль. Отсюда и возникает исключение.

Как правильно исправить эту ошибку (Best Practice)

Часто разработчики применяют "костыли", передавая фиктивный параметр, например ДобавитьФайлы(0) или ДобавитьФайлы(Неопределено). Посмотрим на этот подход: он действительно уберет ошибку компиляции, но считается плохим стилем программирования (anti-pattern). Обработчик команды формы не должен вызываться вручную из других процедур.

Рассмотрим архитектурно правильный подход: выделим общую бизнес-логику в отдельную непараметризуемую процедуру, и будем вызывать её из всех необходимых мест (в том числе из обработчика кнопки и из метода ответа на вопрос диалога).


// Выносим основную логику в отдельную процедуру без параметров
&НаКлиенте
Процедура ВыполнитьДобавлениеФайла()
    Если ЗначениеЗаполнено(Объект.Ссылка) Тогда
        Оповещение = Новый ОписаниеОповещения("ОбработатьВыборФайла", ЭтотОбъект);
        НачатьПомещениеФайла(Оповещение, , , Истина, УникальныйИдентификатор);
    Иначе
        Оповещение = Новый ОписаниеОповещения("ОтветНаВопросЗаписать", ЭтотОбъект);
        ТекстВопроса = "Элемент не записан. Записать?";
        ПоказатьВопрос(Оповещение, ТекстВопроса, РежимДиалогаВопрос.ДаНет);
    КонецЕсли;
КонецПроцедуры

// Обработчик кнопки вызывает нашу общую процедуру
&НаКлиенте
Процедура ДобавитьФайлы(Команда)
    ВыполнитьДобавлениеФайла();
КонецПроцедуры

// Обработчик ответа на вопрос теперь тоже обращается к корректному методу
&НаКлиенте
Процедура ОтветНаВопросЗаписать(Результат, ДополнительныеПараметры) Экспорт
    Если Результат = КодВозвратаДиалога.Да Тогда
        ЭтотОбъект.Записать();
        ВыполнитьДобавлениеФайла(); // Ошибка полностью исключена
    КонецЕсли;
КонецПроцедуры

Реализуем перетаскивание (Drag-and-Drop) файлов на форму

Посмотрим на второй вопрос: как сделать так, чтобы пользователь мог захватить файл в Проводнике Windows и перетащить его мышкой прямо в таблицу на форме 1С? Для этого необходимо выполнить настройку элементов и написать корректные обработчики событий.

Шаг 1. Настройка элемента формы

В свойствах таблицы формы (или декорации), куда планируется бросать файлы, необходимо найти свойство РазрешитьПеретаскивание и установить его в значение Истина. Без этого события перетаскивания просто не будут срабатывать.

Шаг 2. Обработка события "ПроверкаПеретаскивания"

Хорошим тоном является проверка того, что именно пользователь пытается перетащить. Если это не файл, мы должны отклонить действие.


&НаКлиенте
Процедура ФайлыПроверкаПеретаскивания(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Поле)
    // Разрешаем перетаскивание только если это файл(ы)
    Если ТипЗнч(ПараметрыПеретаскивания.Значение) <> Тип("Файл") 
       И ТипЗнч(ПараметрыПеретаскивания.Значение) <> Тип("Массив") Тогда
        СтандартнаяОбработка = Ложь;
        ПараметрыПеретаскивания.Действие = ДействиеПеретаскивания.Отмена;
    КонецЕсли;
КонецПроцедуры

Шаг 3. Обработка события "Перетаскивание"

Когда пользователь отпускает кнопку мыши, срабатывает событие Перетаскивание. Платформа помещает перетаскиваемый объект в свойство ПараметрыПеретаскивания.Значение. Разберем подробнее логику обработки:

  1. Отключаем стандартную обработку с помощью СтандартнаяОбработка = Ложь;.
  2. Проверяем тип перетаскиваемого значения. Если это одиночный файл, он будет иметь тип Файл.
  3. Получаем полный путь к файлу из свойства ПолноеИмя.
  4. Передаем путь в типовую асинхронную процедуру НачатьПомещениеФайла.

Посмотрим на готовый пример кода:


&НаКлиенте
Процедура ФайлыПеретаскивание(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Поле)
    СтандартнаяОбработка = Ложь; 
    
    ПеретаскиваемоеЗначение = ПараметрыПеретаскивания.Значение;
    
    // Проверяем, что перетащили именно объект типа Файл
    Если ТипЗнч(ПеретаскиваемоеЗначение) = Тип("Файл") Тогда
        
        ПолныйПутьКФайлу = ПеретаскиваемоеЗначение.ПолноеИмя;
        Оповещение = Новый ОписаниеОповещения("ОбработатьВыборФайла", ЭтотОбъект);
        
        // Передаем путь к файлу в качестве 3-го параметра. 
        // Параметр ИнтерактивныйВыбор неявно станет Ложь из-за переданного пути.
        НачатьПомещениеФайла(Оповещение, , ПолныйПутьКФайлу, Истина, УникальныйИдентификатор);
        
    ИначеЕсли ТипЗнч(ПеретаскиваемоеЗначение) = Тип("Массив") Тогда
        // Если перетаскивается сразу несколько файлов, то значение будет Массивом.
        // Для обработки массива используется метод НачатьПомещениеФайлов()
    КонецЕсли;
    
КонецПроцедуры

Проанализируем этот алгоритм: благодаря передаче пути ПолныйПутьКФайлу в функцию НачатьПомещениеФайла, система не станет показывать диалог выбора файла, а тихо в фоновом режиме загрузит перетащенный файл во временное хранилище и вызовет ваше оповещение ОбработатьВыборФайла. В самом оповещении (которое уже описано в исходном коде) вы благополучно вызовете серверную процедуру для сохранения данных в базу.

← На главную