При разработке на платформе 1С:Предприятие 8.2 (или при использовании обычных форм в версии 8.3) начинающие программисты часто сталкиваются с трудностями при попытке автоматического наполнения таблиц. Одной из самых распространенных ошибок является неправильный выбор события для добавления строк. Давайте подробно разберем, почему код может не работать, к каким последствиям приводят ошибки в логике и как реализовать задачу правильно.
Рассмотрим ситуацию, представленную в вопросе. Автор пытается добавить строку внутри процедуры ПриВыводеСтроки. Проанализируем, почему это критическая ошибка. Событие ПриВыводеСтроки вызывается платформой в тот момент, когда конкретная строка таблицы отрисовывается на экране монитора. Это происходит при открытии формы, при прокрутке списка (скроллинге), при изменении размеров окна или даже при наведении курсора.
Если мы поместим команду Добавить() внутрь этого обработчика, возникнет следующая цепочка событий:
ПриВыводеСтроки.Важно запомнить правило: процедура ПриВыводеСтроки предназначена только для оформления (изменение цвета текста, фона, шрифта или отображение расчетного текста в колонках, не связанных с данными). Изменять структуру данных (добавлять или удалять строки) в этом событии категорически запрещено.
Проанализируем фрагмент кода автора и выясним, какие опечатки мешают корректной работе. В исходном сообщении мы видим:
Процедура ТаблицаПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
Если ДанныеСтроки = Неопределенно Тогда
Возврат;
КонецЕсли;
ОформлениеСтроки.Ячеки.УслугаНаименование.Значение = ДанныеСтроки.Таблица.Наименование;
ОформлениеСтроки.Ячейки.УЕТ.Значение = ДанныеСтроки.Таблица.Количество;
НоваяСтрока = ЭтотОбъкт.Таблица.Добавить;
НоваяСтрока.Услуга = "Текст";
КонецПроцедуры
Здесь допущено несколько серьезных ошибок:
ОформлениеСтроки.Ячеки — пропущена буква "й". Правильно: ОформлениеСтроки.Ячейки.ЭтотОбъкт — опечатка в слове "Объект". Правильно: ЭтотОбъект.Таблица.Добавить — отсутствие скобок при вызове метода. Правильно: Таблица.Добавить().ДанныеСтроки.Таблица.Наименование — если "Таблица" это имя табличной части, то обращение внутри ДанныеСтроки (которая сама является строкой этой таблицы) к родителю через точку некорректно. Обычно обращаются просто ДанныеСтроки.Наименование.Если нам нужно, чтобы при открытии документа или обработки таблица автоматически заполнялась данными, следует использовать процедуру ПриОткрытии. Давайте разберем по шагам, как это реализовать правильно.
Предположим, у нас есть документ с табличной частью Услуги. Нам нужно добавить в неё несколько строк программно. Рассмотрим правильный пример кода:
Процедура ПриОткрытии()
// Проверим, пустая ли таблица, чтобы не добавлять строки повторно при каждом переоткрытии
Если ЭтотОбъект.Услуги.Количество() = 0 Тогда
// Добавляем первую строку
НоваяСтрока = ЭтотОбъект.Услуги.Добавить();
НоваяСтрока.Наименование = "Консультация специалиста";
НоваяСтрока.Количество = 1;
НоваяСтрока.Цена = 1500;
// Добавляем вторую строку
НоваяСтрока = ЭтотОбъект.Услуги.Добавить();
НоваяСтрока.Наименование = "Выезд на объект";
НоваяСтрока.Количество = 1;
НоваяСтрока.Цена = 500;
КонецЕсли;
КонецПроцедуры
В данном случае мы обращаемся напрямую к объекту данных. После выполнения этого кода строки будут физически добавлены в табличную часть, и форма отобразит их автоматически.
Иногда "Таблица" на форме — это не табличная часть документа, а реквизит формы типа ТаблицаЗначений. В этом случае работа с ней немного отличается. Проанализируем ситуацию, когда данные нужно добавить в произвольную таблицу на форме.
Процедура ЗаполнитьТаблицуНаФорме()
// Очищаем таблицу перед заполнением
ЭтаФорма.ЭлементыФормы.МояТаблица.Значение.Очистить();
// Получаем саму таблицу значений
ТЗ = ЭтаФорма.ЭлементыФормы.МояТаблица.Значение;
// Добавляем данные в цикле
Для Каждого ТекУслуга Из Справочники.Номенклатура.Выбрать() Цикл
Если ТекУслуга.ЭтоГруппа Тогда
Продолжить;
КонецЕсли;
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.УслугаНаименование = ТекУслуга.Наименование;
НоваяСтрока.УЕТ = 1;
КонецЦикла;
// Важный момент для обычных форм:
// Нужно явно указать элементу формы, что данные обновились
ЭтаФорма.ЭлементыФормы.МояТаблица.СоздатьКолонки();
КонецПроцедуры
Вызов метода СоздатьКолонки() или Обновить() помогает интерфейсу корректно отобразить изменения, если структура таблицы была изменена динамически.
Вернемся к событию ПриВыводеСтроки. Выясним причину, почему программисты часто пытаются использовать его для записи данных. Часто стоит задача не изменить данные в базе, а просто показать "виртуальное" значение пользователю (например, результат сложения двух колонок, который не должен храниться в документе).
Для этих целей используйте свойство УстановитьТекст. Рассмотрим пример:
Процедура ТаблицаПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
Если ДанныеСтроки = Неопределенно Тогда
Возврат;
КонецЕсли;
// Правильный способ отобразить данные без их записи в объект:
СуммаСНалогом = ДанныеСтроки.Сумма * 1.2;
ОформлениеСтроки.Ячейки.ВсегоСНалогом.УстановитьТекст(Строка(СуммаСНалогом));
// Также здесь можно менять цвет
Если СуммаСНалогом > 1000 Тогда
ОформлениеСтроки.Ячейки.ВсегоСНалогом.ЦветТекста = ЦветаСтиля.ОсобыйТекст;
КонецЕсли;
КонецПроцедуры
Использование УстановитьТекст не вызывает изменения данных в строке, а значит, не провоцирует бесконечные циклы перерисовки. Это легитимный и правильный способ работы в данном событии.
Если ваша таблица содержит сотни или тысячи строк, использование ПриВыводеСтроки может привести к "тормозам" интерфейса, так как процедура вызывается для каждой строки отдельно. Выясним, как сделать работу более эффективной.
В платформе 8.2 существует событие ПриПолученииДанных. Оно работает не с одной строкой, а сразу с массивом строк, которые видны на экране. Проанализируем пример оптимизированного кода:
Процедура ТаблицаПриПолученииДанных(Элемент, ОформленияСтрок)
// ОформленияСтрок содержит коллекцию строк, видимых на экране
Для Каждого Оформление Из ОформленияСтрок Цикл
Данные = Оформление.ДанныеСтроки;
Если Данные <> Неопределенно Тогда
// Выполняем расчеты
Оформление.Ячейки.Статус.УстановитьТекст("Обработано");
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Этот метод значительно быстрее, так как позволяет, например, одним запросом получить данные из базы для всех видимых строк сразу, вместо того чтобы делать отдельный запрос в цикле для каждой строки.
Мы проанализировали ситуацию и выяснили, что программное добавление строк требует четкого понимания жизненного цикла формы. Для того чтобы успешно манипулировать данными таблиц в 1С 8.2, придерживайтесь следующих рекомендаций:
Основные выводы:
Добавить() в процедурах ПриВыводеСтроки и ПриПолученииДанных.ПриОткрытии или специализированные обработчики кнопок (например, "Заполнить").Ячейки, ЭтотОбъект).ТабличнаяЧасть), а оформление — в объекте ОформлениеСтроки.ПутьКДанным) с вашим объектом.Соблюдение этих принципов позволит вам создавать стабильные и быстрые интерфейсы, избегая "зависаний" и непредсказуемого поведения программы.