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