В процессе разработки на платформе 1С:Предприятие 7.7 программисты часто сталкиваются с необходимостью передать сформированную таблицу из одного отчета в другой. Типичная ситуация: один отчет подготавливает данные и формирует печатную форму, а второй должен отобразить эту же таблицу, но уже в интерактивном режиме — для редактирования пользователем (в так называемом режиме ввода данных). При попытке прямого присваивания вида Таблица = ТаблицаИзДругогоОтчета система выдает классическую ошибку: «Попытка присвоить значение недоступной для записи переменной (Таблица)». Это происходит потому, что объект Таблица на форме является предопределенным элементом управления, который нельзя заменить целиком другим объектом.
В рамках данной статьи мы подробно разберем, как обойти это ограничение, рассмотрим методы передачи данных через глобальные переменные, контексты форм и внешние файлы, а также проанализируем особенности работы в режиме ввода данных.
Разберем ситуацию: почему мы не можем просто скопировать один объект в другой? В 1С 7.7 переменная Таблица, размещенная на форме отчета, жестко связана с визуальным компонентом. Когда мы пытаемся выполнить присваивание, система интерпретирует это как попытку переопределить системный объект, что запрещено. Вместо полной замены объекта нам необходимо либо заполнить существующий объект данными, либо использовать методы отображения уже существующего в памяти объекта.
Один из самых простых и популярных способов в среде «семерки» — использование глобальной переменной, объявленной в Глобальном модуле. Это позволяет «подвесить» таблицу в памяти и обратиться к ней из любого другого контекста.
Проанализируем алгоритм реализации. Сначала в Глобальном модуле необходимо объявить переменную:
// В Глобальном модуле
Перем глПеременная Экспорт;
Теперь рассмотрим код в первом (формирующем) отчете. Здесь мы создаем объект, заполняем его и помещаем в глобальную переменную. Чтобы решение было универсальным и позволяло передавать несколько таблиц одновременно, лучше использовать объект СписокЗначений.
// В ПЕРВОМ ОТЧЕТЕ (формирование):
Если ТипЗначенияСтр(глПеременная) <> "СписокЗначений" Тогда
глПеременная = СоздатьОбъект("СписокЗначений");
КонецЕсли;
текТаблица = СоздатьОбъект("Таблица");
текТаблица.ИсходнаяТаблица("ИмяМакета");
// Здесь идет ваш алгоритм вывода данных:
// текТаблица.ВывестиСекцию(...);
// текТаблица.Опции(0,0,0,0);
// Добавляем таблицу в список с уникальным ключом
глПеременная.ДобавитьЗначение(текТаблица, "МояУникальнаяТаблица");
Во втором отчете, который должен отобразить эти данные, нам нужно извлечь объект из списка и использовать его. Рассмотрим, как это сделать:
// ВО ВТОРОМ ОТЧЕТЕ (прием):
Если ПустоеЗначение(глПеременная) = 0 Тогда
Если ТипЗначенияСтр(глПеременная) = "СписокЗначений" Тогда
ИмяПоиска = "МояУникальнаяТаблица";
Для Счетчик = 1 По глПеременная.РазмерСписка() Цикл
ИмяТаблицы = "";
текТаблица = глПеременная.ПолучитьЗначение(Счетчик, ИмяТаблицы);
Если ИмяТаблицы = ИмяПоиска Тогда
// Важный нюанс: метод Показать() открывает таблицу в новом окне
текТаблица.Показать(ИмяТаблицы);
// Если нужно вывести в объект на форме, используем другие методы
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЕсли;
Если мы не хотим загромождать глобальный модуль лишними переменными, выясним причину, почему бы не передать таблицу напрямую при открытии отчета. Функция ОткрытьФорму имеет третий параметр, который позволяет передать произвольный контекст.
Рассмотрим этот процесс по шагам:
ПриОткрытии() обрабатываем полученные данные.Пример кода вызова:
// В первом отчете
ТабДляПередачи = СоздатьОбъект("Таблица");
// ... заполнение таблицы ...
ОткрытьФорму("Отчет.ВторойОтчет", ТабДляПередачи);
Пример кода получения во втором отчете:
Процедура ПриОткрытии()
Парам = Форма.Параметр;
Если ТипЗначенияСтр(Парам) = "Таблица" Тогда
// Здесь мы можем использовать методы Вывести()
// для копирования содержимого в текущую форму
ТаблицаНаФорме.Вывести(Парам);
КонецЕсли;
КонецПроцедуры
Если таблицы содержат тысячи строк, передача их через оперативную память может быть не самым надежным вариантом. Рассмотрим надежный способ с использованием промежуточного файла. Объект Таблица в 1С 7.7 умеет сохранять себя на диск в родном формате .mxl и загружаться из него.
Разберем алгоритм работы:
// В первом отчете сохраняем результат
ИмяФайла = КаталогВременныхФайлов() + "temp_report.mxl";
Таб.Записать(ИмяФайла, "MXL");
// Во втором отчете загружаем данные в объект на форме
ТаблицаНаФорме.Открыть(ИмяФайла);
// Устанавливаем режим редактирования
ТаблицаНаФорме.ТолькоПросмотр(0);
Этот метод гарантирует, что оформление, шрифты и объединения ячеек будут перенесены в первозданном виде. После загрузки файл можно удалить с помощью команды ФС.УдалитьФайл(ИмяФайла).
Перенос таблицы — это только половина дела. Если ваша задача состоит в том, чтобы пользователь мог вводить данные в ячейки, нужно выполнить ряд настроек. Разберем основные моменты:
Таблица.ТолькоПросмотр(0).Как справедливо заметили участники обсуждения, часто «зло» кроется не в самой таблице, а в попытке использовать визуальный объект для хранения данных. Если данные из одного отчета нужны в другом для расчетов или модификации, правильнее будет передавать Таблицу Значений (ТЗ), а не печатную форму. Выясним почему: ТЗ — это чистые данные без оформления, они обрабатываются в разы быстрее, и их гораздо легче передавать между модулями.
Схема работы в таком случае:
ТЗ.ТЗ передается во второй отчет.ТЗ строит свою визуальную Таблицу через циклы и секции.Хотя это требует написания дополнительного кода вывода, такой подход считается более «профессиональным» и отказоустойчивым в архитектуре 1С 7.7.
Подведем итоги. Для быстрой реализации задачи идеально подходит метод с глобальной переменной или списком значений. Если же вы стремитесь к чистоте кода, используйте передачу через контекст формы. В случаях, когда важна визуальная идентичность сложного отчета, лучшим выбором станет сохранение во временный MXL-файл. Помните, что режим ввода данных требует явного отключения свойства ТолькоПросмотр, иначе пользователь не сможет взаимодействовать с таблицей.