При разработке решений на платформе 1С:Предприятие 8.3 мы часто сталкиваемся с различиями в поведении кода между различными типами клиентов. Одной из таких распространенных ситуаций является некорректная работа прямого доступа к элементам табличных частей документов по индексу на мобильном клиенте, хотя на тонком клиенте тот же код отрабатывает без проблем. Давайте подробнее рассмотрим эту проблему и выясним, как ее эффективно решить.
Представим, что у нас есть задача, описанная на форуме: нам необходимо получить данные из табличной части документа, например, из табличной части «Приложения» документа «Задача», и использовать их в шаблоне уведомления. На тонком клиенте мы можем использовать прямой доступ к строке табличной части по индексу, как в примере:
ПараметрыШаблона.Вставить("Приложение", Объект.Ссылка.Задача.Приложения[0].Приложение);
Этот код отлично работает в среде тонкого клиента, успешно извлекая информацию из первой строки колонки «Приложение» и подставляя ее в шаблон. Однако, когда мы пытаемся выполнить тот же код на мобильном клиенте, он неожиданно перестает работать, данные не подтягиваются, и мы сталкиваемся с тем, что мобильный клиент «не видит» такого обращения к табличной части.
Для того чтобы понять, почему возникает такая ситуация, нам необходимо проанализировать особенности архитектуры мобильного клиента 1С. Хотя мобильный клиент и является аналогом тонкого клиента и способен работать в онлайн-режиме, у него есть свои специфические отличия в части взаимодействия с информационной базой и обработки данных. Рассмотрим основные причины:
Элементы.[ИмяТабчасти].ТекущиеДанные) может возвращать Неопределено на мобильном клиенте, что указывает на ограничения при работе с объектными данными.Таким образом, прямое индексированное обращение к коллекциям табличных частей на мобильном клиенте является ненадежным способом получения данных. Платформа 1С не гарантирует, что полный объект документа со всеми его табличными частями будет всегда доступен на клиенте в том же виде, как это происходит на тонком клиенте.
Наиболее надежным и рекомендуемым способом получения данных из табличных частей документов при работе с мобильным клиентом является использование запросов 1С. Запросы выполняются на сервере, что позволяет обойти ограничения мобильного клиента по прямому объектному доступу и гарантирует получение актуальных и полных данных.
Давайте рассмотрим, как мы можем переписать наш код для получения первой строки из табличной части «Приложения» с использованием запроса.
Нам необходимо сформировать запрос, который явно выберет требуемое поле из табличной части документа. Для этого мы создаем новый объект Запрос, устанавливаем его текст и параметры, а затем выполняем запрос.
// Создаем новый объект Запрос
Запрос = Новый Запрос;
// Формируем текст запроса.
// Мы выбираем поле "Приложение" из табличной части "Приложения" документа "Задача".
// Важно: запрос всегда работает с метаданными, поэтому указываем "Документ.Задача.Приложения".
// Условие "ГДЕ ЗадачаПриложения.Ссылка = &СсылкаНаЗадачу" позволяет нам выбрать данные
// именно для того документа, который мы обрабатываем.
Запрос.Текст =
"ВЫБРАТЬ
| ЗадачаПриложения.Приложение
|ИЗ
| Документ.Задача.Приложения КАК ЗадачаПриложения
|ГДЕ
| ЗадачаПриложения.Ссылка = &СсылкаНаЗадачу
|УПОРЯДОЧИТЬ ПО
| ЗадачаПриложения.НомерСтроки"; // Добавляем упорядочивание для гарантии 'первой' строки
Обратите внимание на использование псевдонима ЗадачаПриложения для нашей табличной части в запросе. Также мы добавили условие УПОРЯДОЧИТЬ ПО ЗадачаПриложения.НомерСтроки, чтобы гарантировать, что при выборке мы всегда будем получать строки в определенном порядке, что важно, если нам нужна именно «первая» строка в логическом смысле (по порядку создания или по номеру строки).
Для того чтобы запрос знал, к какому именно документу «Задача» мы обращаемся, нам необходимо установить параметр &СсылкаНаЗадачу. Этот параметр будет содержать ссылку на текущий объект документа.
// Устанавливаем параметр запроса.
// 'Объект.Ссылка.Задача' здесь представляет ссылку на документ,
// с которым мы работаем в контексте обработчика.
Запрос.УстановитьПараметр("СсылкаНаЗадачу", Объект.Ссылка.Задача);
После установки параметров мы можем выполнить запрос и обработать полученный результат.
// Выполняем запрос и получаем результат в виде выборки.
РезультатЗапроса = Запрос.Выполнить().Выбрать();
// Проверяем, есть ли хотя бы одна строка в результате запроса.
Если РезультатЗапроса.Следующий() Тогда
// Если строка найдена, получаем значение поля "Приложение"
// и вставляем его в ПараметрыШаблона.
ПараметрыШаблона.Вставить("Приложение", РезультатЗапроса.Приложение);
КонецЕсли;
Метод Выбрать() возвращает объект ВыборкаИзРезультатаЗапроса, который позволяет нам последовательно обходить строки результата. Метод Следующий() перемещает нас к следующей строке выборки и возвращает Истина, если строка существует, или Ложь, если строк больше нет. Таким образом, мы безопасно получаем данные из первой доступной строки.
Собирая все шаги вместе, получаем следующий надежный и работоспособный код для получения данных из табличной части на мобильном клиенте:
// Проверяем, что ссылка на задачу существует, прежде чем пытаться получить данные
Если ЗначениеЗаполнено(Объект.Ссылка.Задача) Тогда
// Создаем новый объект Запрос
Запрос = Новый Запрос;
// Формируем текст запроса для получения поля "Приложение" из первой строки табличной части "Приложения"
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ЗадачаПриложения.Приложение
|ИЗ
| Документ.Задача.Приложения КАК ЗадачаПриложения
|ГДЕ
| ЗадачаПриложения.Ссылка = &СсылкаНаЗадачу
|УПОРЯДОЧИТЬ ПО
| ЗадачаПриложения.НомерСтроки"; // Упорядочиваем по номеру строки для получения 'первой'
// Устанавливаем параметр запроса - ссылку на текущий документ "Задача"
Запрос.УстановитьПараметр("СсылкаНаЗадачу", Объект.Ссылка.Задача);
// Выполняем запрос
РезультатЗапроса = Запрос.Выполнить();
// Получаем выборку из результата запроса
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
// Проверяем, есть ли данные в выборке
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
// Если данные есть, вставляем значение поля "Приложение" в ПараметрыШаблона
ПараметрыШаблона.Вставить("Приложение", ВыборкаДетальныеЗаписи.Приложение);
Иначе
// Если данных нет, можно установить пустое значение или выполнить другие действия
ПараметрыШаблона.Вставить("Приложение", ""); // Например, пустая строка
КонецЕсли;
Иначе
// Если ссылка на задачу не заполнена, устанавливаем пустое значение
ПараметрыШаблона.Вставить("Приложение", "");
КонецЕсли;
В этом примере мы добавили ВЫБРАТЬ ПЕРВЫЕ 1 для еще большей оптимизации, чтобы запрос возвращал только одну необходимую нам строку, что особенно актуально для больших табличных частей и для уменьшения объема передаваемых данных.
Помимо прямого использования запросов, существуют и другие подходы, которые могут быть полезны в схожих ситуациях:
ТаблицыЗначений, Массива или Структуры). Важно помнить, что при передаче сложных типов данных между клиентом и сервером могут возникать ошибки, и иногда требуется преобразование в более простые, сериализуемые типы.Таким образом, для обеспечения надежной и корректной работы с данными на мобильном клиенте 1С, особенно при обращении к табличным частям документов, мы настоятельно рекомендуем использовать язык запросов. Это не только решает проблему с видимостью данных, но и способствует более эффективному и безопасному взаимодействию клиентской части с сервером информационной базы.