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