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