При разработке в среде 1С:Предприятие 8.3, особенно при подготовке к экзамену «1С:Специалист по платформе», часто возникает задача: при выборе одного документа в табличной части текущего, автоматически развернуть его состав и заполнить строки. Начинающие разработчики часто сталкиваются с тем, что при попытке «провалиться» в выбранную ссылку через отладчик, они видят пустые значения или невозможность обращения к табличной части. Разберем подробно, почему так происходит и как правильно реализовать этот функционал.
Первым делом проанализируем ситуацию, описанную автором темы. Попытка обратиться к данным через конструкцию Строка.РасходнаяНакладная.СписокНоменклатуры на клиенте обречена на провал. В управляемом приложении 1С действует строгое разделение контекстов:
Shift+F9 не позволяет посмотреть внутрь документа.Рассмотрим по шагам, как реализовать алгоритм заполнения табличной части «Список накладных» в документе «Распределение затрат».
Для начала нам нужно определить момент, когда должна сработать логика. Оптимальным вариантом является событие ПриИзменении для поля, в котором пользователь выбирает накладную. Проанализируем пример кода для клиентской процедуры:
&НаКлиенте
Процедура СписокНакладныхРасходнаяНакладнаяПриИзменении(Элемент)
// Получаем текущую строку табличной части
ТекущаяСтрока = Элементы.СписокНакладных.ТекущиеДанные;
Если ТекущаяСтрока = Неопределено Тогда
Возврат;
КонецЕсли;
// Если накладная выбрана, вызываем серверную процедуру
Если ЗначениеЗаполнено(ТекущаяСтрока.РасходнаяНакладная) Тогда
ЗаполнитьСоставНакладнойНаСервере(ТекущаяСтрока.НомерСтроки - 1);
КонецЕсли;
КонецПроцедуры
Обратите внимание: мы передаем индекс строки или идентификатор, чтобы на сервере знать, какую именно строку мы начали заполнять.
Выясним причину, по которой использование метода ПолучитьОбъект() на сервере считается плохим тоном в задачах уровня «Специалист». Этот метод считывает абсолютно все данные документа (все реквизиты, все табличные части), что создает лишнюю нагрузку на память и сеть. Правильнее и эффективнее использовать объект Запрос.
Рассмотрим структуру серверной процедуры:
&НаСервере
Процедура ЗаполнитьСоставНакладнойНаСервере(ИндексСтроки)
// Получаем доступ к строке через Объект (данные формы)
ТекущаяСтрокаТЧ = Объект.СписокНакладных[ИндексСтроки];
СсылкаНаНакладную = ТекущаяСтрокаТЧ.РасходнаяНакладная;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РасходнаяНакладнаяСписокНоменклатуры.Номенклатура КАК Товар,
| РасходнаяНакладнаяСписокНоменклатуры.Сумма КАК Себестоимость
|ИЗ
| Документ.РасходнаяНакладная.СписокНоменклатуры КАК РасходнаяНакладнаяСписокНоменклатуры
|ГДЕ
| РасходнаяНакладнаяСписокНоменклатуры.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", СсылкаНаНакладную);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
// Первая строка накладной заполнит текущую строку ТЧ
ПерваяСтрока = Истина;
Пока Выборка.Следующий() Цикл
Если ПерваяСтрока Тогда
НоваяСтрока = ТекущаяСтрокаТЧ;
ПерваяСтрока = Ложь;
Иначе
// Для остальных позиций создаем новые строки
НоваяСтрока = Объект.СписокНакладных.Добавить();
НоваяСтрока.РасходнаяНакладная = СсылкаНаНакладную;
КонецЕсли;
НоваяСтрока.Товар = Выборка.Товар;
НоваяСтрока.Себестоимость = Выборка.Себестоимость;
КонецЦикла;
КонецПроцедуры
Проанализируем специфику задачи 1.15. В этой задаче требуется распределить сумму затрат по товарам из накладных. Важно помнить, что если в накладной несколько товаров, то сумма должна распределяться пропорционально (например, себестоимости).
Важный момент: если вы программно добавляете строки в табличную часть, которая отображается на форме, данные в реквизите Объект синхронизируются автоматически. Однако, если вы хотите, чтобы пользователь сразу увидел изменения в интерфейсе, убедитесь, что вы работаете с данными формы Объект, а не пытаетесь менять данные непосредственно в базе через Документы.РаспределениеЗатрат.СоздатьДокумент().
В сообщениях форума упоминалось, что отладчик «не заходит» в серверную процедуру. Посмотрим на возможные причины этого поведения:
-debug. В противном случае точки останова на сервере будут игнорироваться.Отладка -> Подключение и проверьте, что в списке доступных предметов есть «Сервер». Если его нет, нажмите кнопку «Автоматическое подключение» и установите галочку напротив «Серверные вызовы».Рассмотрим совет из сообщения №5. Иногда удобнее использовать механизм подбора (кнопка «Подбор»). В этом случае пользователь выбирает одну или несколько накладных в отдельной форме, а затем в обработчике ОбработкаВыбора вы на сервере перебираете все выбранные ссылки и заполняете таблицу по аналогии с вышеуказанным кодом. Это предотвращает «дерганье» интерфейса при случайном изменении значения в строке.
Резюмируем: Для получения реквизитов табличной части другого документа (реквизита реквизита) необходимо:
Запрос к табличной части нужного документа с фильтром по Ссылка.Добавить().Такой подход гарантирует высокую производительность системы и корректную работу в управляемом интерфейсе 1С:Предприятие 8.3.