Почему мобильный клиент 1С не видит прямого обращения к строкам табличной части документа и как это исправить?

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

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

Представим, что у нас есть задача, описанная на форуме: нам необходимо получить данные из табличной части документа, например, из табличной части «Приложения» документа «Задача», и использовать их в шаблоне уведомления. На тонком клиенте мы можем использовать прямой доступ к строке табличной части по индексу, как в примере:


ПараметрыШаблона.Вставить("Приложение", Объект.Ссылка.Задача.Приложения[0].Приложение);

Этот код отлично работает в среде тонкого клиента, успешно извлекая информацию из первой строки колонки «Приложение» и подставляя ее в шаблон. Однако, когда мы пытаемся выполнить тот же код на мобильном клиенте, он неожиданно перестает работать, данные не подтягиваются, и мы сталкиваемся с тем, что мобильный клиент «не видит» такого обращения к табличной части.

Почему прямой доступ к табличной части может не работать на мобильном клиенте?

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

  1. Особенности архитектуры мобильного клиента: Мобильный клиент разработан с учетом ограничений мобильных устройств – меньшая производительность, особенности сетевого взаимодействия и работы с памятью. В связи с этим платформа 1С может применять различные оптимизации и механизмы работы с данными, которые отличаются от работы тонкого клиента. Прямое обращение к сложным объектам по ссылке и индексам может не всегда корректно обрабатываться или быть неэффективным в этой среде.
  2. Сериализация и передача данных: При работе с мобильным клиентом данные постоянно передаются между клиентской частью и сервером. Сложные структуры объектов, такие как полные объекты документов с табличными частями, могут требовать специфической сериализации, которая не всегда гарантирует полный доступ к вложенным свойствам напрямую на клиенте. В некоторых случаях, прямой доступ к текущим данным элементов формы (например, Элементы.[ИмяТабчасти].ТекущиеДанные) может возвращать Неопределено на мобильном клиенте, что указывает на ограничения при работе с объектными данными.
  3. Безопасность и оптимизация: Платформа 1С может иметь внутренние механизмы, которые ограничивают прямой доступ к некоторым данным объектов на мобильном клиенте для повышения безопасности, управляемости или оптимизации производительности. Это делается для того, чтобы минимизировать нагрузку на мобильное устройство и трафик, передавая только те данные, которые явно запрошены или необходимы для текущей операции.

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

Эффективное решение: Использование запросов для получения данных

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

Давайте рассмотрим, как мы можем переписать наш код для получения первой строки из табличной части «Приложения» с использованием запроса.

Шаг 1: Создание и выполнение запроса

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


// Создаем новый объект Запрос
Запрос = Новый Запрос;

// Формируем текст запроса. 
// Мы выбираем поле "Приложение" из табличной части "Приложения" документа "Задача".
// Важно: запрос всегда работает с метаданными, поэтому указываем "Документ.Задача.Приложения".
// Условие "ГДЕ ЗадачаПриложения.Ссылка = &СсылкаНаЗадачу" позволяет нам выбрать данные 
// именно для того документа, который мы обрабатываем.
Запрос.Текст = 
    "ВЫБРАТЬ
    |    ЗадачаПриложения.Приложение
    |ИЗ
    |    Документ.Задача.Приложения КАК ЗадачаПриложения
    |ГДЕ
    |    ЗадачаПриложения.Ссылка = &СсылкаНаЗадачу
    |УПОРЯДОЧИТЬ ПО
    |    ЗадачаПриложения.НомерСтроки"; // Добавляем упорядочивание для гарантии 'первой' строки

Обратите внимание на использование псевдонима ЗадачаПриложения для нашей табличной части в запросе. Также мы добавили условие УПОРЯДОЧИТЬ ПО ЗадачаПриложения.НомерСтроки, чтобы гарантировать, что при выборке мы всегда будем получать строки в определенном порядке, что важно, если нам нужна именно «первая» строка в логическом смысле (по порядку создания или по номеру строки).

Шаг 2: Установка параметров запроса

Для того чтобы запрос знал, к какому именно документу «Задача» мы обращаемся, нам необходимо установить параметр &СсылкаНаЗадачу. Этот параметр будет содержать ссылку на текущий объект документа.


// Устанавливаем параметр запроса.
// 'Объект.Ссылка.Задача' здесь представляет ссылку на документ,
// с которым мы работаем в контексте обработчика.
Запрос.УстановитьПараметр("СсылкаНаЗадачу", Объект.Ссылка.Задача);

Шаг 3: Выполнение запроса и обработка результата

После установки параметров мы можем выполнить запрос и обработать полученный результат.


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

// Проверяем, есть ли хотя бы одна строка в результате запроса.
Если РезультатЗапроса.Следующий() Тогда
    // Если строка найдена, получаем значение поля "Приложение"
    // и вставляем его в ПараметрыШаблона.
    ПараметрыШаблона.Вставить("Приложение", РезультатЗапроса.Приложение);
КонецЕсли;

Метод Выбрать() возвращает объект ВыборкаИзРезультатаЗапроса, который позволяет нам последовательно обходить строки результата. Метод Следующий() перемещает нас к следующей строке выборки и возвращает Истина, если строка существует, или Ложь, если строк больше нет. Таким образом, мы безопасно получаем данные из первой доступной строки.

Полный пример кода с использованием запроса

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


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

    // Формируем текст запроса для получения поля "Приложение" из первой строки табличной части "Приложения"
    Запрос.Текст = 
        "ВЫБРАТЬ ПЕРВЫЕ 1
        |    ЗадачаПриложения.Приложение
        |ИЗ
        |    Документ.Задача.Приложения КАК ЗадачаПриложения
        |ГДЕ
        |    ЗадачаПриложения.Ссылка = &СсылкаНаЗадачу
        |УПОРЯДОЧИТЬ ПО
        |    ЗадачаПриложения.НомерСтроки"; // Упорядочиваем по номеру строки для получения 'первой'

    // Устанавливаем параметр запроса - ссылку на текущий документ "Задача"
    Запрос.УстановитьПараметр("СсылкаНаЗадачу", Объект.Ссылка.Задача);

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

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

    // Проверяем, есть ли данные в выборке
    Если ВыборкаДетальныеЗаписи.Следующий() Тогда
        // Если данные есть, вставляем значение поля "Приложение" в ПараметрыШаблона
        ПараметрыШаблона.Вставить("Приложение", ВыборкаДетальныеЗаписи.Приложение);
    Иначе
        // Если данных нет, можно установить пустое значение или выполнить другие действия
        ПараметрыШаблона.Вставить("Приложение", ""); // Например, пустая строка
    КонецЕсли;
Иначе
    // Если ссылка на задачу не заполнена, устанавливаем пустое значение
    ПараметрыШаблона.Вставить("Приложение", "");
КонецЕсли;

В этом примере мы добавили ВЫБРАТЬ ПЕРВЫЕ 1 для еще большей оптимизации, чтобы запрос возвращал только одну необходимую нам строку, что особенно актуально для больших табличных частей и для уменьшения объема передаваемых данных.

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

Помимо прямого использования запросов, существуют и другие подходы, которые могут быть полезны в схожих ситуациях:

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

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

← На главную