Табличную часть документа 1С программно заполняют и правят в самых разных доработках: загрузка заказа с сайта, пересчёт сумм перед записью, удаление пустых строк, замена товара в сотне документов, выборка строк для отчёта. Ниже — законченный код для платформы 8.3 на каждый случай: модуль объекта, таблица значений, запрос, справочник и управляемая форма. Методы сверены со справкой платформы 8.3.27, имена типовых объектов — с выгрузками УТ 11.4 и КА 2.5.
Одна и та же табличная часть Товары попадает в код в четырёх видах, и возможности у них разные:
| Откуда | Что это | Можно менять |
|---|---|---|
ЭтотОбъект в модуле объекта, СоздатьДокумент(), Ссылка.ПолучитьОбъект() | табличная часть объекта со всеми методами | да, потом Записать() |
Ссылка.Товары | та же табличная часть только для чтения; документ читается из базы целиком | нет: Добавить, Удалить, Загрузить, Сортировать вызывают ошибку выполнения |
Объект.Товары в модуле управляемой формы | ДанныеФормыКоллекция | да, но методов меньше |
запрос к таблице Документ.Имя.Товары | строки всех документов с полями Ссылка и НомерСтроки | нет, только выборка |
Код из следующих разделов пишут в модуле объекта (в конфигураторе: окно документа → вкладка «Прочее» → «Модуль объекта»), в серверном общем модуле или в модуле обработки. В тонком и веб-клиенте объектов нет, там доступна только коллекция формы.
Свой документ ЗаказТоваров с табличной частью Товары: добавление с поиском, вставка первой строкой, два способа удаления, проверка повторов и пересчёт сумм перед записью. Для сообщений используются функции БСП.
// Модуль объекта документа ЗаказТоваров (своя доработка), конфигурация на БСП.
// Табличная часть Товары: Номенклатура (СправочникСсылка.Номенклатура),
// Количество (Число 15,3), Цена (Число 15,2), Сумма (Число 15,2).
// Реквизит шапки СуммаДокумента (Число 15,2).
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
#Область ПрограммныйИнтерфейс
// Добавляет товар. Если номенклатура уже есть в документе, увеличивает количество
// в её строке (цена - последняя переданная). Возвращает строку, куда попал товар.
Функция ДобавитьТовар(Номенклатура, Количество, Цена) Экспорт
СтрокаТоваров = Товары.Найти(Номенклатура, "Номенклатура");
Если СтрокаТоваров = Неопределено Тогда
СтрокаТоваров = Товары.Добавить();
СтрокаТоваров.Номенклатура = Номенклатура;
КонецЕсли;
СтрокаТоваров.Количество = СтрокаТоваров.Количество + Количество;
СтрокаТоваров.Цена = Цена;
СтрокаТоваров.Сумма = Окр(СтрокаТоваров.Количество * СтрокаТоваров.Цена, 2);
Возврат СтрокаТоваров;
КонецФункции
// Ставит услугу (например, доставку) первой строкой: вставляет новую или переносит наверх.
Процедура ПоставитьПервойСтрокой(Услуга, Цена) Экспорт
СтрокаТоваров = Товары.Найти(Услуга, "Номенклатура");
Если СтрокаТоваров = Неопределено Тогда
СтрокаТоваров = Товары.Вставить(0);
СтрокаТоваров.Номенклатура = Услуга;
СтрокаТоваров.Количество = 1;
Иначе
Индекс = Товары.Индекс(СтрокаТоваров);
Если Индекс > 0 Тогда
Товары.Сдвинуть(СтрокаТоваров, -Индекс);
КонецЕсли;
КонецЕсли;
СтрокаТоваров.Цена = Цена;
СтрокаТоваров.Сумма = Окр(СтрокаТоваров.Количество * Цена, 2);
КонецПроцедуры
// Удаляет строки без номенклатуры или с нулевым количеством.
// Возвращает число удалённых строк.
Функция УдалитьПустыеСтроки() Экспорт
Удалено = 0;
Индекс = Товары.Количество() - 1;
// С конца: после Удалить() нижние строки поднимаются, меняя индекс и НомерСтроки
Пока Индекс >= 0 Цикл
СтрокаТоваров = Товары[Индекс];
Если Не ЗначениеЗаполнено(СтрокаТоваров.Номенклатура) Или СтрокаТоваров.Количество = 0 Тогда
Товары.Удалить(Индекс);
Удалено = Удалено + 1;
КонецЕсли;
Индекс = Индекс - 1;
КонецЦикла;
Возврат Удалено;
КонецФункции
// Удаляет все строки с указанной номенклатурой.
Процедура УдалитьНоменклатуру(Номенклатура) Экспорт
// НайтиСтроки возвращает сами строки: удалять их можно в любом порядке
Найденные = Товары.НайтиСтроки(Новый Структура("Номенклатура", Номенклатура));
Для Каждого СтрокаТоваров Из Найденные Цикл
Товары.Удалить(СтрокаТоваров);
КонецЦикла;
КонецПроцедуры
#КонецОбласти
#Область ОбработчикиСобытий
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
// Одна номенклатура - одна строка. Ключ - номенклатура, значение - номер её первой строки
ПервыеСтроки = Новый Соответствие;
Для Каждого СтрокаТоваров Из Товары Цикл
Если Не ЗначениеЗаполнено(СтрокаТоваров.Номенклатура) Тогда
Продолжить;
КонецЕсли;
НомерПервой = ПервыеСтроки[СтрокаТоваров.Номенклатура];
Если НомерПервой = Неопределено Тогда
ПервыеСтроки.Вставить(СтрокаТоваров.Номенклатура, СтрокаТоваров.НомерСтроки);
Продолжить;
КонецЕсли;
Текст = СтрШаблон("Строка %1: «%2» уже есть в строке %3.",
Формат(СтрокаТоваров.НомерСтроки, "ЧГ=0"), СтрокаТоваров.Номенклатура, Формат(НомерПервой, "ЧГ=0"));
// В пути к полю индекс с нуля: функция БСП сама вычтет единицу из НомерСтроки
Поле = ОбщегоНазначенияКлиентСервер.ПутьКТабличнойЧасти("Товары", СтрокаТоваров.НомерСтроки, "Номенклатура");
ОбщегоНазначения.СообщитьПользователю(Текст, ЭтотОбъект, Поле, , Отказ);
КонецЦикла;
КонецПроцедуры
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Строки могли изменить из кода в обход формы - пересчитываем здесь
Для Каждого СтрокаТоваров Из Товары Цикл
СтрокаТоваров.Сумма = Окр(СтрокаТоваров.Количество * СтрокаТоваров.Цена, 2);
КонецЦикла;
СуммаДокумента = Товары.Итог("Сумма");
КонецПроцедуры
#КонецОбласти
#КонецЕсли
Найти(Значение, "Номенклатура") возвращает первую подходящую строку или Неопределено — по справке, метод для уникальных значений. НайтиСтроки(Структура) отдаёт массив ссылок на сами строки: изменения через элемент массива сразу попадают в табличную часть.Вставить(0) создаёт строку на нулевой позиции, Сдвинуть(Строка, -Индекс) переносит туда существующую.УдалитьПустыеСтроки идёт с конца: после удаления нижние строки поднимаются, меняя индекс и НомерСтроки, и в прямом цикле следующая строка осталась бы непроверенной.Удалить принимает и индекс, и саму строку, поэтому строки из НайтиСтроки удаляются без расчёта индексов.ПутьКТабличнойЧасти собирает поле вида Товары[4].Номенклатура и сам вычитает единицу: в пути индекс с нуля, а НомерСтроки — с единицы.ПередЗаписью пересчитывает строки и сумму шапки через Итог("Сумма"): при записи из кода обработчики формы не работают. Проверка ОбменДанными.Загрузка пропускает пересчёт при загрузке из обмена.В типовых УТ и КА строки пересчитывают общие модули конфигурации, сумму документа — модуль объекта. Как вызвать их из кода, разобрано в статье о программном создании документа.
На управляемой форме Объект.Товары — уже не табличная часть, а ДанныеФормыКоллекция со своим набором методов. Сводка по справке платформы:
| Метод | Что делает | У Объект.Товары на форме |
|---|---|---|
Добавить(), Вставить(Индекс) | новая строка в конце или на позиции | есть, и на клиенте |
Удалить(Индекс или Строка), Очистить() | удаляет строку или все строки | есть |
Найти(Значение, Колонки) | первая строка со значением или Неопределено | нет |
НайтиСтроки(Отбор) | массив строк по структуре отбора | есть; на клиенте, по справке, обращается к серверу |
Итог(Колонка) | сумма колонки | есть, только для числовых колонок |
Выгрузить(), Загрузить(Таблица) | в таблицу значений и обратно | только на сервере |
ВыгрузитьКолонку(), ЗагрузитьКолонку() | колонка в массив и обратно | нет |
Сортировать(), Сдвинуть() | порядок строк | есть; Сортировать на клиенте обращается к серверу |
Свернуть() | сворачивает одинаковые строки | нет |
Индекс(), Получить(), Количество() | позиция строки, строка по позиции, число строк | есть |
Если нужного метода у коллекции нет, на сервере документ получают через РеквизитФормыВЗначение("Объект") — пример ниже.
У табличной части есть свои Свернуть и Сортировать. По справке, колонки группировки и суммирования в Свернуть вместе должны покрыть всю табличную часть и не пересекаться, поэтому ниже список группировок собирается из метаданных — колонка, добавленная доработкой, не потеряется. А по полю, которого в строках нет, например по артикулу, сортируют через таблицу значений.
// Продолжение модуля объекта ЗаказТоваров: процедуры - в область ПрограммныйИнтерфейс.
// Сворачивает одинаковые строки. Группировка - по всем реквизитам табличной части,
// кроме суммируемых: если в Товары добавят колонку, она тоже попадёт в группировку.
Процедура СвернутьТовары(Знач КолонкиСуммирования = "Количество, Сумма") Экспорт
Суммируемые = СтрРазделить(СтрЗаменить(КолонкиСуммирования, " ", ""), ",", Ложь);
Группировки = Новый Массив;
Для Каждого Реквизит Из Метаданные().ТабличныеЧасти.Товары.Реквизиты Цикл
Если Суммируемые.Найти(Реквизит.Имя) = Неопределено Тогда
Группировки.Добавить(Реквизит.Имя);
КонецЕсли;
КонецЦикла;
// Свернуть у табличной части: два списка вместе должны покрыть все её колонки
Товары.Свернуть(СтрСоединить(Группировки, ", "), КолонкиСуммирования);
КонецПроцедуры
// Сортирует строки по артикулу номенклатуры (реквизит Артикул есть в УТ 11.4).
// В табличной части такой колонки нет, поэтому сортируем таблицу значений
// с дополнительной колонкой и загружаем строки обратно.
Процедура СортироватьПоАртикулу() Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Артикул КАК Артикул
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка В (&СписокНоменклатуры)";
// ВыгрузитьКолонку - массив значений колонки в порядке строк
Запрос.УстановитьПараметр("СписокНоменклатуры", Товары.ВыгрузитьКолонку("Номенклатура"));
Артикулы = Новый Соответствие;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Артикулы.Вставить(Выборка.Ссылка, Выборка.Артикул);
КонецЦикла;
Таблица = Товары.Выгрузить(); // колонка НомерСтроки выгружается тоже
Таблица.Колонки.Добавить("Артикул", Новый ОписаниеТипов("Строка"));
Для Каждого СтрокаТаблицы Из Таблица Цикл
Артикул = Артикулы[СтрокаТаблицы.Номенклатура];
СтрокаТаблицы.Артикул = ?(Артикул = Неопределено, "", Артикул);
КонецЦикла;
// При равных артикулах сохраняется прежний порядок строк
Таблица.Сортировать("Артикул, НомерСтроки");
Товары.Загрузить(Таблица);
КонецПроцедуры
Выгрузить() отдаёт и колонку НомерСтроки — по ней строки с одинаковым артикулом сохраняют прежний порядок. Загрузить() удаляет старые строки и переносит значения только в колонки с совпадающими именами: Артикул пропускается, номера строк идут заново по порядку. У Выгрузить есть вариант с отбором: Товары.Выгрузить(Новый Структура("Цена", 0), "НомерСтроки, Номенклатура") вернёт только строки без цены и две колонки.
ЗагрузитьКолонку строк не добавляет: значения массива по порядку индексов ложатся в существующие строки. Так удобно копировать колонку в колонку, например у пересчёта товаров УТ 11.4 с парами учётных и фактических колонок:
// Пересчёт товаров УТ 11.4 (Пересчет - объект документа ПересчетТоваров):
// фактическое количество = учётному во всех строках, в единицах хранения и в упаковках
Пересчет.Товары.ЗагрузитьКолонку(Пересчет.Товары.ВыгрузитьКолонку("Количество"), "КоличествоФакт");
Пересчет.Товары.ЗагрузитьКолонку(Пересчет.Товары.ВыгрузитьКолонку("КоличествоУпаковок"), "КоличествоУпаковокФакт");
Читать строки многих документов через объекты долго: каждое Ссылка.Товары загружает документ целиком. Запрос берёт только нужные поля. В таблице Документ.РеализацияТоваровУслуг.Товары поле Ссылка — документ строки, НомерСтроки — её номер, а через Ссылка. доступны реквизиты шапки.
// В каких проведённых реализациях за период и в каких строках продавался товар.
// Колонки табличной части Товары сверены по УТ 11.4 и КА 2.5.
Функция ПродажиТовара(Номенклатура, НачалоПериода, КонецПериода) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| Товары.Ссылка КАК Документ,
| Товары.Ссылка.Дата КАК Дата,
| Товары.НомерСтроки КАК НомерСтроки,
| Товары.Количество КАК Количество,
| Товары.Цена КАК Цена,
| Товары.СуммаСНДС КАК СуммаСНДС
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК Товары
|ГДЕ
| Товары.Номенклатура = &Номенклатура
| И Товары.Ссылка.Проведен
| И Товары.Ссылка.Дата МЕЖДУ &НачалоПериода И &КонецПериода
|
|УПОРЯДОЧИТЬ ПО
| Товары.Ссылка.МоментВремени,
| НомерСтроки";
Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(НачалоПериода));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(КонецПериода));
// Одна строка результата - одна строка табличной части
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Запрос удобно отладить в бесплатной консоли запросов. Если документы нужны вместе со строками, есть вложенная таблица: в запросе к Документ.РеализацияТоваровУслуг КАК Реализация поле Реализация.Товары.(НомерСтроки, Номенклатура, Количество) КАК Товары вернёт строки каждого документа одним полем.
Групповое изменение строк — тот же запрос плюс запись объектов. Пример для своего ЗаказТоваров: заменить номенклатуру во всех заказах за период. Код кладут в серверный общий модуль или во внешнюю обработку.
// Замена номенклатуры во всех заказах за период. ЗаказТоваров - документ
// из листингов выше (СвернутьТовары, ОбработкаПроверкиЗаполнения в модуле объекта).
// Возвращает массив заказов, которые не удалось записать.
Функция ЗаменитьНоменклатуруВЗаказах(СтараяНоменклатура, НоваяНоменклатура, НачалоПериода, КонецПериода) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| Товары.Ссылка КАК Ссылка
|ИЗ
| Документ.ЗаказТоваров.Товары КАК Товары
|ГДЕ
| Товары.Номенклатура = &СтараяНоменклатура
| И Товары.Ссылка.Дата МЕЖДУ &НачалоПериода И &КонецПериода
| И НЕ Товары.Ссылка.ПометкаУдаления";
Запрос.УстановитьПараметр("СтараяНоменклатура", СтараяНоменклатура);
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(НачалоПериода));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(КонецПериода));
НеЗаписаны = Новый Массив;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Заказ = Выборка.Ссылка.ПолучитьОбъект();
Отбор = Новый Структура("Номенклатура", СтараяНоменклатура);
Для Каждого СтрокаТоваров Из Заказ.Товары.НайтиСтроки(Отбор) Цикл
СтрокаТоваров.Номенклатура = НоваяНоменклатура;
КонецЦикла;
// Если новая номенклатура уже была в заказе, одинаковые строки сольются
Заказ.СвернутьТовары();
// Из кода проверка заполнения сама не запускается
Если Заказ.Проведен И Не Заказ.ПроверитьЗаполнение() Тогда
НеЗаписаны.Добавить(Выборка.Ссылка);
Продолжить;
КонецЕсли;
// Записать() без параметра пишет в режиме Запись: движения остались бы старыми
Режим = ?(Заказ.Проведен, РежимЗаписиДокумента.Проведение, РежимЗаписиДокумента.Запись);
Попытка
Заказ.Записать(Режим);
Исключение
НеЗаписаны.Добавить(Выборка.Ссылка);
ЗаписьЖурналаРегистрации("ЗаменаНоменклатурыВЗаказах", УровеньЖурналаРегистрации.Ошибка,
Заказ.Метаданные(), Выборка.Ссылка, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
КонецЦикла;
Возврат НеЗаписаны;
КонецФункции
Главное — режим записи. Записать() без параметров пишет в режиме Запись: строки сохранятся, а движения проведённого документа останутся прежними. Поэтому проведённые заказы записываются с РежимЗаписиДокумента.Проведение, как при перепроведении. Ошибка одного заказа не останавливает остальные: она уходит в журнал регистрации.
С табличной частью справочника всё так же: получить объект, изменить строки, записать — без проведения. У иерархического справочника табличная часть бывает только у элементов, только у групп или у тех и других: это её свойство «Использование» в конфигураторе. Создание самих элементов — в статье о программном создании элемента справочника.
// Своя конфигурация: справочник Спецификации, табличная часть Состав
// (Номенклатура - СправочникСсылка.Номенклатура, Количество - Число 15,3).
// Заменяет состав спецификации строками таблицы значений с теми же колонками.
Процедура ЗаписатьСоставСпецификации(Спецификация, НовыйСостав) Экспорт
Элемент = Спецификация.ПолучитьОбъект();
// Загрузить сначала удаляет все старые строки, колонки сопоставляются по именам
Элемент.Состав.Загрузить(НовыйСостав);
// Строки без количества удаляем по самим строкам - индексы не нужны
Для Каждого СтрокаСостава Из Элемент.Состав.НайтиСтроки(Новый Структура("Количество", 0)) Цикл
Элемент.Состав.Удалить(СтрокаСостава);
КонецЦикла;
Элемент.Записать();
КонецПроцедуры
// УТ 11.4: состав основного варианта комплектации номенклатуры.
// Справочник ВариантыКомплектацииНоменклатуры подчинён справочнику Номенклатура,
// комплектующие лежат в его табличной части Товары.
Функция СоставКомплекта(Номенклатура) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| Состав.НомерСтроки КАК НомерСтроки,
| Состав.Номенклатура КАК Номенклатура,
| Состав.Характеристика КАК Характеристика,
| Состав.Количество КАК Количество
|ИЗ
| Справочник.ВариантыКомплектацииНоменклатуры.Товары КАК Состав
|ГДЕ
| Состав.Ссылка.Владелец = &Номенклатура
| И Состав.Ссылка.Основной
| И НЕ Состав.Ссылка.ПометкаУдаления
|
|УПОРЯДОЧИТЬ ПО
| НомерСтроки";
Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
На клиенте строку под курсором берут из Элементы.Товары.ТекущиеДанные, всю коллекцию — из Объект.Товары. Всё, чему нужны методы объекта или код модуля объекта, выполняется на сервере: РеквизитФормыВЗначение("Объект") возвращает настоящий объект документа, а ЗначениеВРеквизитФормы возвращает изменения в форму. Так форма вызывает ДобавитьТовар и СвернутьТовары из модуля объекта, не дублируя логику.
// Модуль формы документа ЗаказТоваров (управляемая форма).
// Реквизиты формы: НоменклатураДляДобавления (СправочникСсылка.Номенклатура),
// ЦенаДляДобавления (Число 15,2), ИтогСумма (Число 15,2).
// Команды: ДобавитьПозицию, СвернутьСтроки.
// ДобавитьТовар и СвернутьТовары - экспортные методы модуля объекта (листинги выше).
&НаКлиенте
Процедура ТоварыПриНачалеРедактирования(Элемент, НоваяСтрока, Копирование)
// Серверные методы формы здесь вызывать нельзя - только значения по умолчанию
Если НоваяСтрока И Не Копирование Тогда
Элемент.ТекущиеДанные.Количество = 1;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ТоварыПриОкончанииРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования)
СтрокаТоваров = Элемент.ТекущиеДанные;
Если СтрокаТоваров <> Неопределено Тогда
СтрокаТоваров.Сумма = Окр(СтрокаТоваров.Количество * СтрокаТоваров.Цена, 2);
КонецЕсли;
// Итог у коллекции формы работает на клиенте, цикл не нужен
ИтогСумма = Объект.Товары.Итог("Сумма");
КонецПроцедуры
&НаКлиенте
Процедура ДобавитьПозицию(Команда)
Если Не ЗначениеЗаполнено(НоменклатураДляДобавления) Тогда
ПоказатьПредупреждение(, "Выберите номенклатуру");
Возврат;
КонецЕсли;
Индекс = ДобавитьПозициюНаСервере();
// Курсор - на строку, куда попал товар: новую или ту, где выросло количество
Элементы.Товары.ТекущаяСтрока = Объект.Товары[Индекс].ПолучитьИдентификатор();
ИтогСумма = Объект.Товары.Итог("Сумма");
КонецПроцедуры
&НаКлиенте
Процедура СвернутьСтроки(Команда)
СвернутьСтрокиНаСервере();
ИтогСумма = Объект.Товары.Итог("Сумма");
КонецПроцедуры
&НаСервере
Функция ДобавитьПозициюНаСервере()
// Документ - объект: методы модуля объекта и все методы табличной части
Документ = РеквизитФормыВЗначение("Объект");
СтрокаТоваров = Документ.ДобавитьТовар(НоменклатураДляДобавления, 1, ЦенаДляДобавления);
Индекс = Документ.Товары.Индекс(СтрокаТоваров);
ЗначениеВРеквизитФормы(Документ, "Объект");
Модифицированность = Истина;
Возврат Индекс;
КонецФункции
&НаСервере
Процедура СвернутьСтрокиНаСервере()
Документ = РеквизитФормыВЗначение("Объект");
Документ.СвернутьТовары();
ЗначениеВРеквизитФормы(Документ, "Объект");
Модифицированность = Истина;
КонецПроцедуры
ПриНачалеРедактирования справка запрещает вызывать серверные методы формы — только значения по умолчанию.Объект.Товары[Индекс].ПолучитьИдентификатор().Модифицированность = Истина: программные изменения форму изменённой не помечают, и при закрытии она не спросит о записи.Обработчики колонок, выделенные строки и итоги в подвале — в статье о таблице формы.
Найти, Свернуть или ВыгрузитьКолонку вызвали у Объект.Товары на форме. У ДанныеФормыКоллекция таких методов нет: ищите через НайтиСтроки, остальное делайте с объектом из РеквизитФормыВЗначение. На клиенте той же ошибкой заканчиваются Выгрузить и Загрузить.Сдвинуть и Сортировать, номера пересчитываются сами.Товары[Строка.НомерСтроки]. Индекс считается с нуля, номер — с единицы: нужно Товары[Строка.НомерСтроки - 1] или Товары.Индекс(Строка). Другие причины — в статье про выход индекса за границы.Для Каждого по самой табличной части: после каждого удаления следующая строка пропускается, а ошибки нет.НомерСтроки запомнили как ключ, а строки потом удалили или отсортировали. В УТ 11.4 для связи есть служебные колонки: у реализации КлючСвязи связывает строку Товары со строками СкидкиНаценки, КодСтроки указывает на строку заказа, есть и ИдентификаторСтроки. Строки типового документа без учёта этих колонок не сворачивают и не удаляют.ПередЗаписью. В реализации УТ 11.4 сумма документа — это СуммаСНДС строк без многооборотной тары, которую клиент вернёт без залога (экспортная функция ПолучитьСуммуДокумента модуля объекта), и Итог("Сумма") с ней может разойтись.КоличествоУпаковок считается в упаковках строки, а Количество — в единицах хранения. Для итога по товару суммируйте Количество.Записать() без режима.На сервере: Приемник.Товары.Загрузить(Источник.Товары.Выгрузить()). Колонки сопоставятся по именам, колонки приёмника без пары останутся пустыми. Источником может быть и ссылка: Выгрузить у табличной части ссылки работает, запрещены только изменяющие методы.
Через квадратные скобки: ДокументОбъект[ИмяТабличнойЧасти]. Есть ли такая табличная часть, проверяет ДокументОбъект.Метаданные().ТабличныеЧасти.Найти(ИмяТабличнойЧасти) <> Неопределено. Так пишут универсальные обработки для любых документов и справочников.
Исторически 99 999: номер строки хранился пятью разрядами. В 8.3.27 у табличной части появилось свойство ДлинаНомераСтроки — от 5 до 9 разрядов. По справке, новой табличной части в режиме совместимости выше 8.3.26 назначается 9, а в режиме 8.3.26 и ниже допустимо только 5.
У табличной части в конфигураторе поставьте «Проверка заполнения» = «Выдавать ошибку», у обязательных колонок — тоже. Из формы проверка запускается сама, из кода — методом ПроверитьЗаполнение(). В своём коде достаточно условия Товары.Количество() = 0.
Если строки документов должны заполняться из файлов, сайта или маркетплейса, а в типовой к ним привязаны скидки, серии и заказы, ошибка в коде тихо портит данные. Такие доработки берут исполнители площадки: услуги по доработке 1С, в том числе обработки на заказ. Разместите задачу бесплатно — оценка тоже бесплатная, ответ в течение рабочего дня.
Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.