При разработке отчетов с использованием табличных документов программисты часто сталкиваются с ситуацией, когда визуально данные в строках отображаются корректно (разные номера, даты и суммы), но при попытке расшифровать строку (двойной клик) открывается всегда один и тот же объект — как правило, последний из списка. Рассмотрим причины этого поведения на конкретном примере и разберем, как правильно организовать вывод данных в 1С.
Основная причина кроется в понимании того, как 1С работает с объектом ТабличныйДокумент и его областями. Когда мы вызываем метод Макет.ПолучитьОбласть("ИмяСекции"), система создает в оперативной памяти экземпляр этой области. Если этот вызов происходит вне цикла, мы работаем с одним и тем же объектом на каждой итерации. Если же мы повторно заполняем параметры этой области, не очищая их и не обновляя значения, в результирующий документ попадает то, что находится в памяти объекта в момент вызова метода Вывести().
В коде, представленном в обсуждении, прослеживается критическая ошибка логики: отчет формируется фактически дважды. Сначала происходит расчет и объединение ячеек, затем выполняется ТабДок.Очистить(), и запускается второй цикл вывода. Именно на этом этапе "теряется" корректное значение расшифровки.
Проанализируем фрагмент кода из сообщения №10, который привел к проблеме. Обратим внимание на то, как заполняются параметры во втором цикле после очистки документа:
// ... код первого формирования ...
ТабДок.Очистить();
// ... настройки оформления ...
Пока ВыборкаЗаказ.Следующий Цикл
// Здесь заполняются текстовые параметры
Строка.Параметры.НомерПП = а;
Строка.Параметры.НомерЗаказа = ПолучитьНомер(ВыборкаЗаказ.Ссылка.Номер);
// ОШИБКА: Пропущен параметр расшифровки!
// Во втором цикле отсутствует строка:
// Строка.Параметры.РНомерЗаказа = ВыборкаЗаказ.Ссылка;
ТабДок.Вывести(Строка);
КонецЦикла;
В первом цикле (до очистки) параметр РНомерЗаказа (который в макете указан как Параметр расшифровки для ячейки с номером заказа) успешно заполнялся. После завершения первого цикла в объекте Строка в параметре РНомерЗаказа осталась ссылка на самый последний документ из выборки. Когда начался второй цикл, программа обновила текстовые параметры (номер, дата, контрагент), но так как явного присвоения значения параметру расшифровки не было, 1С использовала "старое" значение, зависшее в памяти объекта области. В итоге во всех выведенных строках расшифровка стала указывать на один и тот же документ.
Для исправления ситуации необходимо придерживаться следующих правил при работе с макетами:
Строка) внутри цикла, убедитесь, что на каждой итерации вы присваиваете значения всем параметрам, включая параметры расшифровки.Правильный вариант заполнения параметров в цикле должен выглядеть так:
Пока Выборка.Следующий() Цикл
// Получаем область заново или гарантированно заполняем ВСЕ параметры
СекцияСтрока = Макет.ПолучитьОбласть("Строка");
СекцияСтрока.Параметры.НомерЗаказа = Выборка.Номер;
// Явно заполняем параметр расшифровки на каждой итерации!
СекцияСтрока.Параметры.ПараметрРасшифровкиДокумента = Выборка.Ссылка;
ТабДок.Вывести(СекцияСтрока);
КонецЦикла;
Иногда удобнее не полагаться на параметры макета, а назначать расшифровку напрямую выведенной области. Рассмотрим, как это сделать программно. Этот метод более гибкий, так как позволяет записывать в расшифровку не только ссылки, но и структуры или массивы данных.
Разберем пример:
// Выводим область
ТабДок.Вывести(СекцияСтрока);
// Определяем координаты только что выведенной строки
НомерПоследнейСтроки = ТабДок.ВысотаТаблицы;
// Назначаем расшифровку конкретной ячейке (например, в колонке 3)
Ячейка = ТабДок.Область(НомерПоследнейСтроки, 3);
Ячейка.Расшифровка = Выборка.Ссылка;
Важный нюанс: Чтобы расшифровка работала, у ТабличногоДокумента на форме должно быть установлено свойство ТолькоПросмотр = Истина. Если документ доступен для редактирования, двойной клик будет открывать ячейку для ввода текста, а не запускать механизм расшифровки.
Если вы столкнулись с подобной проблемой, проанализируйте ситуацию по следующим шагам:
ТабДок.Вывести(Строка).Строка.Параметры.ИмяВашегоПараметраРасшифровки.Следующий(), значит, в коде отсутствует команда присваивания ссылки в этот параметр..Параметры....Помните, что метод ТабДок.Очистить() удаляет только содержимое результирующего документа, но не обнуляет переменные областей макета, которые вы уже получили с помощью ПолучитьОбласть(). Будьте внимательны при повторном использовании объектов областей!