Как открыть табличный документ из реквизита или коллекции управляемой формы

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

При переходе с обычных форм на управляемое приложение многие разработчики сталкиваются с неприятным ограничением: метод Показать(), который раньше легко открывал табличный документ прямо из ячейки таблицы значений, теперь вызывает ошибку "Недопустимая операция для реквизита формы". В этой статье мы детально разберем, почему это происходит, как устроена работа с данными в управляемом приложении и какими способами можно реализовать привычный функционал редактирования табличных документов в коллекциях.

Почему возникает ошибка: архитектурный аспект

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

В управляемых формах (УФ) все иначе. Данные на форме — это не сами объекты 1С (такие как ТабличныйДокумент или ТаблицаЗначений), а их специальные проекции: ДанныеФормыСтруктура, ДанныеФормыКоллекция и ДанныеФормыЭлементКоллекции. Когда вы помещаете табличный документ в реквизит управляемой формы, он проходит через механизм сериализации. Платформа жестко ограничивает вызов метода Показать() для таких «связанных» данных, так как метод пытается создать независимое окно, которое не умеет синхронизироваться с контекстом формы в реальном времени. Синтакс-помощник прямо указывает: «Если табличный документ является реквизитом управляемой формы, то вызов метода приводит к возникновению исключения».

Решение №1: Использование вспомогательной формы (рекомендуемый способ)

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

Разберем алгоритм по шагам:

  1. На сервере помещаем нужный табличный документ из коллекции во Временное хранилище.
  2. Передаем адрес хранилища в новую форму через параметры.
  3. В новой форме при создании извлекаем документ и выводим его в локальный реквизит.
  4. После редактирования возвращаем измененный документ обратно через механизм оповещений.

Посмотрим на пример реализации кода в основной форме:


&НаКлиенте
Процедура ОткрытьТабличныйДокументИзСписка(Команда)
    
    ТекущиеДанные = Элементы.ТаблицаСписка.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Получаем адрес временного хранилища на сервере
    АдресХранилища = ПодготовитьТабДокНаСервере(ТекущиеДанные.НомерСтроки);
    
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("АдресТабДока", АдресХранилища);
    
    // Описываем оповещение о закрытии формы редактирования
    ОписаниеОповещения = Новый ОписаниеОповещения("ПослеЗакрытияРедактора", ЭтотОбъект, ТекущиеДанные.НомерСтроки);
    
    ОткрытьФорму("ВнешняяОбработка.МояОбработка.Форма.ФормаРедакторТабДока", ПараметрыФормы, ЭтотОбъект, , , , ОписаниеОповещения);
    
КонецПроцедуры

&НаСервере
Функция ПодготовитьТабДокНаСервере(НомерСтроки)
    
    // Ищем строку в реквизите формы (например, ТЗДанные)
    СтрокаКоллекции = ТЗДанные.НайтиПоИдентификатору(НомерСтроки);
    // Помещаем объект во временное хранилище
    Возврат ПоместитьВоВременноеХранилище(СтрокаКоллекции.ТабличныйДокумент, ЭтаФорма.УникальныйИдентификатор);
    
КонецФункции

Теперь проанализируем код вспомогательной формы (ФормаРедакторТабДока). В ней должен быть создан реквизит РедактируемыйДокумент с типом ТабличныйДокумент, который вынесен на форму как поле.


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    Если Параметры.Свойство("АдресТабДока") Тогда
        // Извлекаем документ из хранилища в локальный реквизит формы
        РедактируемыйДокумент = ПолучитьИзВременногоХранилища(Параметры.АдресТабДока);
        АдресВХ = Параметры.АдресТабДока; // Сохраняем адрес для возврата
    КонецЕсли;
    
КонецПроцедуры

&НаКлиенте
Процедура СохранитьИЗакрыть(Команда)
    
    // Помещаем измененный документ обратно в хранилище перед закрытием
    ПоместитьОбратноНаСервере();
    Закрыть(Истина); // Возвращаем признак успеха
    
КонецПроцедуры

&НаСервере
Процедура ПоместитьОбратноНаСервере()
    ПоместитьВоВременноеХранилище(РедактируемыйДокумент, АдресВХ);
КонецПроцедуры

Решение №2: Копирование в локальную переменную (быстрый просмотр)

Если вам нужно только показать документ без сложной обратной связи, или вы готовы вручную переприсвоить объект, можно воспользоваться методом Копировать(). Выясним причину, почему это работает: когда вы создаете копию объекта в локальную переменную на клиенте, эта переменная больше не является реквизитом формы. Она становится независимым программным объектом типа ТабличныйДокумент.

Разберем пример кода:


&НаКлиенте
Процедура ПоказатьКопиюДокумента(Команда)
    
    ТекущиеДанные = Элементы.ТаблицаСписка.ТекущиеДанные;
    
    // Важно: работаем через копию, чтобы разорвать связь с реквизитом формы
    ТабДокКопия = ТекущиеДанные.ТабличныйДокумент.Копировать();
    
    // Теперь метод Показать() отработает без ошибок
    ТабДокКопия.Показать("Просмотр документа");
    
    // Но помните: изменения в окне 'ТабДокКопия' НЕ попадут обратно в ТекущиеДанные автоматически!
    
КонецПроцедуры

Важный нюанс: использование метода Копировать() удобно, но оно не обеспечивает интерактивного сохранения. Если пользователь внесет правки в открывшемся окне и нажмет кнопку «Сохранить» в системном меню табличного документа, изменения запишутся в файл (если он выберет путь), но не в вашу таблицу значений на форме.

Сравнение подходов

Выбор метода зависит от ваших бизнес-требований:

Подводные камни при работе с коллекциями в УФ

Обратите внимание на тип колонки в вашей таблице значений (реквизите формы). Чтобы в ней можно было хранить табличный документ, тип колонки должен быть Произвольный. Если вы попытаетесь жестко типизировать колонку как ТабличныйДокумент в редакторе реквизитов формы, платформа может вести себя некорректно при передаче данных между клиентом и сервером.

Также помните про производительность. Табличный документ — это «тяжелый» объект. Если в вашей коллекции 1000 строк и в каждой лежит заполненный ТабличныйДокумент, форма будет открываться крайне медленно из-за огромного объема данных, передаваемых с сервера на клиент при каждом обновлении страницы. В таких случаях лучше хранить в коллекции только идентификаторы или ссылки, а сам ТабличныйДокумент формировать на сервере динамически только в момент запроса на просмотр.

Заключение

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

← На главную