Как программно получить значение ячейки табличной части во внешней обработке 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Работа с табличными частями — это одна из самых частых задач, с которыми сталкивается разработчик при создании внешних обработок. На первый взгляд задача кажется простой: нужно «пробежаться» по строкам и забрать данные. Однако на практике начинающие программисты часто натыкаются на ошибки контекста (клиент-сервер) или проблемы с производительностью. В этой статье мы подробно разберем, как правильно обращаться к данным табличной части, почему возникают ошибки типа «Значение не является значением объектного типа» и как оптимизировать ваш код.

Базовый способ: Перебор строк в цикле

Самый очевидный и правильный способ получить значения всех ячеек в определенной колонке — это использование цикла Для каждого. Рассмотрим ситуацию, когда у нас есть внешняя обработка, и в ней создана табличная часть с именем Товары, в которой есть реквизит Цена.

Проанализируем пример кода для обхода такой таблицы:


Для Каждого СтрокаТаблицы Из Объект.Товары Цикл
    // Получаем значение из колонки "Цена"
    ТекущаяЦена = СтрокаТаблицы.Цена;
    
    // Здесь можно выполнять действия со значением
    Сообщить("Цена товара: " + ТекущаяЦена);
КонецЦикла;

В данном примере Объект — это основное представление данных вашей внешней обработки. Переменная СтрокаТаблицы на каждой итерации цикла будет содержать данные текущей строки. Обращение к конкретной ячейке происходит через точку: Строка.ИмяРеквизита.

Разбор ошибки «Значение не является значением объектного типа (ТабличнаяЧасть)»

Часто при попытке выполнить цикл, как показано выше, система выдает ошибку. Выясним причину ее возникновения. Чаще всего это происходит из-за путаницы в контекстах исполнения кода на Клиенте и на Сервере.

В управляемых формах 1С 8.3 данные на форме представлены типом ДанныеФормыКоллекция, в то время как на сервере (в модуле объекта) это полноценная ТабличнаяЧасть. Если вы пытаетесь обратиться к методам, которые доступны только объекту метаданных, находясь в контексте клиентской процедуры, вы получите ошибку.

Рассмотрим важные нюансы:

  1. Точность имен: Проверьте, что имя табличной части в коде в точности совпадает с именем в дереве метаданных обработки. 1С чувствительна к опечаткам.
  2. Доступность данных: На клиенте вы работаете с данными через Объект.ИмяТЧ. Если вам нужно передать эту таблицу в фоновое задание или сложную функцию общего модуля, лучше сначала преобразовать ее в массив структур или таблицу значений на сервере.

Альтернативные способы получения данных

Иногда полный перебор строк в цикле избыточен. Рассмотрим ситуации, когда нам нужно получить значение конкретной ячейки без обхода всей таблицы.

1. Доступ по индексу

Если нам заранее известен номер строки, мы можем обратиться к ней напрямую. Помните, что в 1С индексация строк начинается с 0.


// Получаем цену из третьей строки (индекс 2)
Если Объект.Товары.Количество() > 2 Тогда
    ЗначениеЯчейки = Объект.Товары[2].Цена;
КонецЕсли;

2. Поиск конкретного значения через метод Найти()

Если нам нужно найти строку, в которой ячейка содержит определенное значение (например, поиск товара по артикулу), используем встроенный метод:


// Ищем строку, где Артикул равен "001"
СтрокаПоиска = Объект.Товары.Найти("001", "Артикул");

Если СтрокаПоиска <> Неопределено Тогда
    // Мы нашли строку, теперь можем взять значение любой другой ячейки в этой строке
    НужнаяЦена = СтрокаПоиска.Цена;
КонецЕсли;

3. Работа с текущей строкой (выбор пользователя)

Если задача стоит в том, чтобы получить значение ячейки в той строке, которую пользователь выделил курсором прямо сейчас, цикл вообще не нужен. Используем свойство ТекущиеДанные:


// Этот код обычно пишется в модуле формы
ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;

Если ТекущаяСтрока <> Неопределено Тогда
    ВыбраннаяЦена = ТекущаяСтрока.Цена;
КонецЕсли;

Оптимизация и работа с базой данных внутри цикла

Разберем ситуацию, упомянутую в обсуждении: когда внутри цикла по табличной части создаются или изменяются объекты базы данных (например, справочники или документы). Рассмотрим пример с копированием объектов:


Для Каждого Строка из Объект.СписокОС Цикл
    // Создаем копию объекта из ячейки "ОсновноеСредство"
    НовОС = Строка.ОсновноеСредство.Скопировать();
    НовОС.Организация = Объект.ОрганизацияПолучатель;
    
    // ВНИМАНИЕ: Запись внутри цикла замедляет работу СУБД
    НовОС.Записать(); 
КонецЦикла;

Важный совет по производительности: Вызов метода Записать() внутри цикла — это «тяжелая» операция. При каждой итерации программа обращается к серверу баз данных, открывает транзакцию, записывает данные и закрывает транзакцию. Если в таблице 1000 строк, это будет работать крайне медленно.

Чтобы ускорить процесс, проанализируем возможность использования транзакций или пакетной записи. Если логика позволяет, лучше сначала собрать все данные в массив, а потом обработать их. Но если запись каждого объекта уникальна и необходима, старайтесь хотя бы минимизировать количество обращений к серверу (используйте серверный контекст процедуры).

Выгрузка в Таблицу Значений

Если вам нужно выполнить сложную сортировку, группировку или поиск по нескольким колонкам сразу, мы рекомендуем выгрузить табличную часть в объект ТаблицаЗначений. Это делается одной командой на сервере:


// Работает только в серверном коде
ТаблицаДанных = Объект.Товары.Выгрузить();

// Теперь у нас есть полноценная таблица в памяти, с которой можно работать:
ТаблицаДанных.Сортировать("Цена Убыв");
НужнаяСтрока = ТаблицаДанных.Найти(100, "Цена");

Это особенно полезно во внешних обработках, предназначенных для анализа больших объемов данных, так как работа с ТаблицаЗначений в памяти сервера происходит значительно быстрее, чем прямое обращение к коллекции данных формы.

Резюме

Для получения значения ячейки во внешней обработке:

← На главную