При разработке отчетов на базе Системы компоновки данных (СКД) программисты часто сталкиваются с требованием заказчика: «Нужно, чтобы в сформированном отчете можно было вручную заполнить колонку, и программа тут же пересчитала итог». По умолчанию СКД предназначена для вывода данных «как есть» из базы, и механизм интерактивного редактирования в ней не является штатным. Однако, используя возможности платформы «1С:Предприятие 8», мы можем обойти эти ограничения.
В этой статье мы разберем несколько стратегий реализации этой задачи: от настройки свойств табличного документа до использования внешних наборов данных для сохранения введенной информации.
Разберем ситуацию, когда отчет уже сформирован, и нам нужно разрешить пользователю ввод данных в определенные ячейки. Для этого нам необходимо программно вмешаться в процесс вывода отчета. Проанализируем основные шаги:
Во-первых, по умолчанию любой отчет, сформированный СКД, имеет установленное свойство ТолькоПросмотр = Истина. Чтобы пользователь мог что-то напечатать, нам нужно изменить это свойство у результирующего табличного документа. Во-вторых, необходимо снять защиту с конкретных ячеек или колонок.
Рассмотрим пример кода, который можно разместить в модуле формы отчета после команды формирования:
// Сначала разрешаем редактирование документа в целом
Результат.ТолькоПросмотр = Ложь;
// Определяем область, которую хотим сделать редактируемой (например, колонку "ВводДанных")
// Для этого можно пройти циклом по строкам или использовать поиск области по имени
Для НомерСтроки = 1 По Результат.ВысотаТаблицы Цикл
Ячейка = Результат.Область(НомерСтроки, 5); // Допустим, 5-я колонка
Ячейка.Защита = Ложь;
КонецЦикла;
Чтобы ячейка вела себя не как текстовое поле, а как полноценное поле ввода (например, с выбором числа или даты), мы должны использовать свойства СодержитЗначение и ТипЗначения. Это позволит пользователю вводить данные строго определенного типа.
Выясним, как заставить отчет реагировать на действия пользователя. Если нам нужно, чтобы при вводе числа в одну колонку автоматически менялось значение в другой, нам понадобится обработчик события ПриИзмененииСодержимогоОбласти у элемента формы Поле табличного документа.
Проанализируем алгоритм работы этого обработчика:
Пример реализации обработчика на управляемой форме:
&НаКлиенте
Процедура РезультатПриИзмененииСодержимогоОбласти(Элемент, Область)
// Проверяем, что изменение произошло в нужной нам колонке
Если Область.Лево = 5 Тогда // Номер нашей редактируемой колонки
ТекущаяСтрока = Область.Верх;
ВведенноеЗначение = Область.Текст; // Или Область.Значение
// Допустим, нам нужно умножить введенное число на цену из 4-й колонки
Цена = Число(Элемент.Область(ТекущаяСтрока, 4).Текст);
РезультатРасчета = Число(ВведенноеЗначение) * Цена;
// Записываем результат в 6-ю колонку
Элемент.Область(ТекущаяСтрока, 6).Текст = Формат(РезультатРасчета, "ЧДЦ=2");
КонецЕсли;
КонецПроцедуры
Важный момент: использование свойства Текст удобно для простых расчетов, но если в ячейке хранятся типизированные данные, лучше использовать свойство Значение, предварительно настроив СодержитЗначение = Истина.
Если задача стоит именно в добавлении «пустых» строк для будущего заполнения, мы можем реализовать это на уровне текста запроса в схеме компоновки данных. Рассмотрим, как подготовить структуру отчета, в которой изначально будут пустые строки.
Посмотрим на пример запроса, использующего ОБЪЕДИНИТЬ ВСЕ:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Товар,
Остатки.КоличествоОстаток КАК Количество
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки ПО Номенклатура.Ссылка = Остатки.Номенклатура
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка),
0
// Здесь мы создаем "пустышку", которую пользователь сможет заполнить позже
Однако такой подход редко бывает эффективным для 500 строк. В этом случае лучше использовать Внешние наборы данных. Мы можем программно сформировать таблицу значений нужной структуры, заполнить её пустыми строками и передать в СКД.
Главная проблема ручного ввода в отчет заключается в том, что при нажатии кнопки «Сформировать» все введенные данные стираются, так как отчет строится заново. Чтобы этого избежать, разберем архитектурно правильный подход:
ТабличныйДокумент и считываем все данные, введенные пользователем, в ТаблицуЗначений.ВнешниеНаборыДанных.Таким образом, введенные данные «приклеиваются» к строкам отчета даже после его обновления.
Проанализируем совет из обсуждения на форуме: если отчет подразумевает массовый ввод данных (500 строк и более) с формулами и сложной логикой, использование стандартного вывода СКД может быть избыточным и неудобным. В таких случаях целесообразно использовать элемент формы ТабличноеПоле (в обычных формах) или таблицу формы, связанную с ТаблицейЗначений (в управляемых формах).
Преимущества такого подхода:
ПриИзменении для каждой колонки отдельно.После того как пользователь заполнил все данные в такой интерактивной таблице, вы можете вызвать формирование «настоящего» отчета СКД, который просто выведет эти данные в красивом макете для печати.
Мы выяснили, что напрямую СКД не поддерживает «живое» редактирование ячеек, но это реализуемо через программное управление ТабличнымДокументом. Если вам нужно просто добавить несколько полей для пометок, используйте свойства Защита и ТолькоПросмотр. Если же требуется сложный расчет и сохранение данных — лучше смотреть в сторону использования внешних наборов данных или предварительного ввода данных в специализированные объекты базы.