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