Как программно получить данные из табличной части документа в 1С 8.3 Управляемые формы?

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

При разработке функционала в системе 1С часто возникает необходимость получить доступ к данным, хранящимся в табличных частях документов. Это может потребоваться для анализа, формирования отчетов, выполнения расчетов или интеграции с другими подсистемами — здесь пригодится выгрузка любых данных на основе произвольных запросов. Рассмотрим подробно, как мы можем программно получить такую информацию в конфигурациях на платформе 1С 8.3 с использованием управляемых форм.

Мы выясним, какие методы и объекты платформы 1С предоставляют нам эту возможность, разберем различные сценарии использования, а также рассмотрим примеры кода, которые помогут нам в работе.

Основные подходы к получению данных из табличной части

Существует два основных способа программного доступа к данным табличных частей в 1С: через объект документа и с помощью запросов к базе данных. Каждый из этих подходов имеет свои особенности и области применения, которые позволяют реализовать эффективный доступ к данным табличных частей в различных условиях.

1. Получение данных через объект документа

Этот способ является наиболее интуитивно понятным и используется, когда нам нужен полный доступ к данным табличной части, возможно, с последующим их изменением (для этого есть настройка автозаполнения реквизитов и табличных частей документов). Мы будем работать непосредственно с объектом документа.

Пошаговое получение данных через объект документа

  1. Получение ссылки на документ: Прежде всего, нам нужна ссылка на конкретный документ, из которого мы хотим получить данные. Мы можем получить эту ссылку из различных источников: из списка документов, из реквизита формы, из параметров обработки и так далее. Пусть у нас есть переменная СсылкаНаДокумент.

  2. Получение объекта документа: Чтобы работать с данными табличных частей, нам необходимо получить объект документа из его ссылки. Мы делаем это с помощью метода ПолучитьОбъект(). Это действие загружает все данные документа, включая все его табличные части, из базы данных в оперативную память.

    Важно: Метод ПолучитьОбъект() является серверным вызовом и должен выполняться в соответствующем контексте (модуль объекта, серверный вызов из модуля формы), что важно учитывать для оптимизации клиент-серверного взаимодействия.

    
    // Предположим, что СсылкаНаДокумент - это уже полученная ссылка на нужный документ (например, ДокументСсылка.РеализацияТоваровУслуг)
    ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
    

    На этом шаге мы всегда должны проверять, успешно ли мы получили объект, чтобы избежать ошибок в случае, если ссылка недействительна или документ был удален.

    
    Если ДокументОбъект = Неопределено Тогда
        Сообщить("Не удалось получить объект документа по ссылке.");
        Возврат; // Выходим из функции или процедуры
    КонецЕсли;
    
  3. Доступ к табличной части: После того как мы получили объект документа, мы можем получить доступ к его табличным частям как к свойствам этого объекта. Например, если у документа 'РеализацияТоваровУслуг' есть табличная часть с именем 'Товары', мы обращаемся к ней как ДокументОбъект.Товары.

    Каждая табличная часть представляет собой коллекцию строк (тип ТабличнаяЧастьМенеджер или ТабличнаяЧастьОбъекта в зависимости от контекста). Мы можем перебрать эти строки в цикле.

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

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

Рассмотрим полный пример функции, которая получает номенклатуру и количество из табличной части "Товары" документа "РеализацияТоваровУслуг" по переданной ссылке:


// Функция для получения данных из табличной части документа по ссылке
Функция ПолучитьДанныеТабличнойЧастиДокумента(СсылкаНаДокумент) Экспорт

    Если ТипЗнч(СсылкаНаДокумент) <> Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда
        Сообщить("Передана неверная ссылка на документ РеализацияТоваровУслуг.");
        Возврат Неопределено;
    КонецЕсли;

    ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();

    Если ДокументОбъект = Неопределено Тогда
        Сообщить("Документ не найден или не является объектом.");
        Возврат Неопределено;
    КонецЕсли;

    // Создадим список для хранения полученных данных
    СписокСтрокТЧ = Новый СписокЗначений;

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

        СписокСтрокТЧ.Добавить(ДанныеСтроки);
    КонецЦикла;

    Возврат СписокСтрокТЧ;

КонецФункции

// Пример вызова:
// МояСсылка = Документы.РеализацияТоваровУслуг.НайтиПоНомеру("00000001", Дата("20230101"));
// Если МояСсылка <> Неопределено Тогда
//     ДанныеИзТЧ = ПолучитьДанныеТабличнойЧастиДокумента(МояСсылка);
//     Если ДанныеИзТЧ <> Неопределено Тогда
//         Для Каждого СтрокаИзСписка Из ДанныеИзТЧ Цикл
//             Сообщить("Номенклатура: " + СтрокаИзСписка.Номенклатура + ", Количество: " + СтрокаИзСписка.Количество + ", Сумма: " + СтрокаИзСписка.Сумма);
//         КонецЦикла;
//     КонецЕсли;
// КонецЕсли;

Работа с данными табличной части в форме документа

Если мы находимся в модуле формы управляемого приложения и хотим получить данные из табличной части открытого, но, возможно, еще не записанного документа, мы можем обратиться к реквизиту формы Объект. Этот реквизит представляет собой объект документа, связанный с формой, и содержит все актуальные, в том числе и несохраненные, данные.


// В модуле формы управляемого приложения (например, в обработчике команды)
// Объект - это основной реквизит формы, тип которого соответствует объекту документа (например, ДокументОбъект.РеализацияТоваровУслуг)

// Если документ изменен, но еще не записан, мы все равно получим актуальные данные
// из табличной части через реквизит Объект.
Если Объект.Модифицирован Тогда 
    Сообщить("Документ изменен, данные берутся из формы.");
Иначе
    Сообщить("Документ не изменен, данные актуальны на момент открытия или последней записи.");
КонецЕсли;

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

Этот подход особенно удобен, когда нам нужно работать с данными, которые пользователь только что ввел, но еще не сохранил в базе. Для более сложных манипуляций часто применяются универсальные обработки данных — для таких задач подойдёт универсальная обработка выгрузки табличных частей документов.

2. Получение данных с помощью запросов

Для более сложных сценариев, когда нам нужно получить данные из табличной части, возможно, с применением фильтров, сортировок, группировок, или объединения с другими таблицами базы данных, мы используем язык запросов 1С. Запросы часто являются более производительным способом получения данных (их написание и отладку облегчают инструменты разработчика с консолью запросов), особенно если нам нужна только часть информации из табличной части, а не весь объект документа.

Пошаговое получение данных через запрос

  1. Создание объекта запроса: Мы начинаем с создания нового объекта Запрос.

    
    Запрос = Новый Запрос;
    
  2. Формирование текста запроса: Самая важная часть – это составление текста запроса. Табличные части документов в 1С хранятся как отдельные таблицы базы данных. Имя такой таблицы обычно имеет вид Документ.ИмяДокумента.ИмяТабличнойЧасти. Например, для табличной части 'Товары' документа 'РеализацияТоваровУслуг' имя будет Документ.РеализацияТоваровУслуг.Товары.

    В запросе мы можем выбрать необходимые поля (реквизиты) из этой табличной части. Обязательно нужно указать связь с родительским документом через поле Ссылка, чтобы выбрать данные для конкретного документа.

    
    Запрос.Текст =
        "ВЫБРАТЬ
        |    РеализацияТоваровУслугТовары.Номенклатура КАК Номенклатура,
        |    РеализацияТоваровУслугТовары.Количество КАК Количество,
        |    РеализацияТоваровУслугТовары.Сумма КАК Сумма
        |ИЗ
        |    Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары
        |ГДЕ
        |    РеализацияТоваровУслугТовары.Ссылка = &СсылкаНаДокумент";
    
  3. Установка параметров запроса: Если в тексте запроса используются параметры (например, &СсылкаНаДокумент), мы должны установить их значения перед выполнением запроса с помощью метода УстановитьПараметр().

    
    // Предположим, что МояСсылкаНаДокумент - это переменная с ссылкой на нужный документ
    Запрос.УстановитьПараметр("СсылкаНаДокумент", МояСсылкаНаДокумент);
    
  4. Выполнение запроса: Запрос выполняется методом Выполнить(), который возвращает объект РезультатЗапроса.

    
    РезультатЗапроса = Запрос.Выполнить();
    
  5. Обработка результата запроса: Для доступа к данным из РезультатЗапроса мы используем метод Выбрать(), который возвращает объект ВыборкаИзРезультатаЗапроса. Мы можем перебрать строки выборки в цикле, чтобы получить доступ к выбранным полям.

    
    Выборка = РезультатЗапроса.Выбрать();
    
    Пока Выборка.Следующий() Цикл
        Сообщить("Номенклатура: " + Выборка.Номенклатура + ", Количество: " + Выборка.Количество + ", Сумма: " + Выборка.Сумма);
    КонецЦикла;
    

Пример получения данных из табличной части с помощью запроса

Рассмотрим функцию, которая использует запрос для получения данных из табличной части "Товары" документа "РеализацияТоваровУслуг":


// Функция для получения данных из табличной части документа с помощью запроса
Функция ПолучитьДанныеТабличнойЧастиЗапросом(СсылкаНаДокумент) Экспорт

    Если ТипЗнч(СсылкаНаДокумент) <> Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда
        Сообщить("Передана неверная ссылка на документ РеализацияТоваровУслуг.");
        Возврат Неопределено;
    КонецЕсли;

    Запрос = Новый Запрос;
    Запрос.Текст =
        "ВЫБРАТЬ
        |    РеализацияТоваровУслугТовары.Номенклатура КАК Номенклатура,
        |    РеализацияТоваровУслугТовары.Количество КАК Количество,
        |    РеализацияТоваровУслугТовары.Сумма КАК Сумма
        |ИЗ
        |    Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары
        |ГДЕ
        |    РеализацияТоваровУслугТовары.Ссылка = &СсылкаНаДокумент";

    Запрос.УстановитьПараметр("СсылкаНаДокумент", СсылкаНаДокумент);

    РезультатЗапроса = Запрос.Выполнить();
    Выборка = РезультатЗапроса.Выбрать();

    СписокСтрокТЧ = Новый СписокЗначений;

    Пока Выборка.Следующий() Цикл
        ДанныеСтроки = Новый Структура;
        ДанныеСтроки.Вставить("Номенклатура", Выборка.Номенклатура);
        ДанныеСтроки.Вставить("Количество", Выборка.Количество);
        ДанныеСтроки.Вставить("Сумма", Выборка.Сумма);

        СписокСтрокТЧ.Добавить(ДанныеСтроки);
    КонецЦикла;

    Возврат СписокСтрокТЧ;

КонецФункции

// Пример вызова:
// МояСсылка = Документы.РеализацияТоваровУслуг.НайтиПоНомеру("00000001", Дата("20230101"));
// Если МояСсылка <> Неопределено Тогда
//     ДанныеИзТЧ = ПолучитьДанныеТабличнойЧастиЗапросом(МояСсылка);
//     Если ДанныеИзТЧ <> Неопределено Тогда
//         Для Каждого СтрокаИзСписка Из ДанныеИзТЧ Цикл
//             Сообщить("Номенклатура: " + СтрокаИзСписка.Номенклатура + ", Количество: " + СтрокаИзСписка.Количество + ", Сумма: " + СтрокаИзСписка.Сумма);
//         КонецЦикла;
//     КонецЕсли;
// КонецЕсли;

Когда какой подход использовать?

Мы видим, что оба метода позволяют получить данные из табличной части, но они подходят для разных задач:

  1. Через объект документа (Ссылка.ПолучитьОбъект().ТабличнаяЧасть):

    • Преимущества: Простота использования, если уже есть объект документа или его ссылка, и нам нужны все данные документа, включая все табличные части и реквизиты шапки. Позволяет не только читать, но и изменять данные табличной части (после чего необходимо вызвать метод Записать()). Удобно, если мы работаем в модуле формы с еще не записанным документом.
    • Недостатки: Менее производительно, если нам нужны данные только из одной табличной части или лишь несколько полей, так как загружается весь объект документа. Требует серверного контекста.
  2. С помощью запроса (Запрос):

    • Преимущества: Высокая производительность при получении большого объема данных или при необходимости выборки только определенных полей. Позволяет использовать мощный язык запросов для фильтрации, сортировки, группировки, объединения данных из нескольких таблиц. Отлично подходит для формирования отчетов и сложных выборок.
    • Недостатки: Не позволяет напрямую изменять данные табличной части. Требует более глубокого понимания языка запросов.

Важные моменты и лучшие практики

Мы разобрали ключевые методы получения данных из табличных частей документов в 1С 8.3 Управляемые формы. Выбирайте подход, который наилучшим образом соответствует вашей задаче, учитывая требования к производительности 1С, объему данных и необходимости изменения информации. Правильное применение этих методов значительно упростит вашу работу с системой 1С.

← На главную