При работе с платформой 1С:Предприятие 8.3, особенно на управляемых формах, часто возникает задача по выводу различных данных в табличном виде. Это могут быть результаты расчетов, списки объектов, отчеты или, как в нашем случае, простая таблица умножения. Давайте разберем несколько подходов к решению этой задачи, сосредоточившись на наиболее "каноничных" и гибких методах, которые позволят вам эффективно работать с табличными данными в 1С.
Прежде чем погружаться в детали, важно понять фундаментальный принцип управляемых форм 1С: разделение данных и представления. Это означает, что данные, которые мы хотим отобразить, хранятся в специальных реквизитах формы (например, типа ТаблицаЗначений или ТабличныйДокумент), а затем на форме создается элемент, который эти данные визуализирует для пользователя. Ваша задача как разработчика — подготовить данные и "привязать" их к соответствующему элементу формы.
Для простых задач, таких как вывод фиксированной таблицы, чаще всего используют реквизит формы типа ТаблицаЗначений. Для более сложного форматирования или вывода отчетов подходит ТабличныйДокумент. Если же нам нужен интерактивный список с сортировкой, отбором и возможностью редактирования, мы будем работать с ДинамическимСписком. Сегодня мы подробно рассмотрим первые два подхода.
Этот способ является наиболее распространенным и гибким для программного формирования табличных данных на управляемой форме. Мы будем использовать объект ТаблицаЗначений как хранилище наших данных, а затем отобразим его на форме.
Прежде всего, нам нужна база для работы. Создадим новую обработку, которая будет содержать нашу форму и логику.
ВыводТаблицыУмножения.Форма». Откройте форму для редактирования.Это один из самых важных шагов. Здесь мы не только создадим реквизит, но и определим структуру колонок нашей будущей таблицы. Этот реквизит будет служить "хранилищем" для данных, которые мы затем выведем на форму.
РезультатТаблицаТаблицаЗначенийРезультатТаблица.Колонка1, Заголовок: x 1, Тип: СтрокаКолонка2, Заголовок: x 2, Тип: СтрокаКолонка9, Заголовок: x 9, Тип: СтрокаМы используем тип Строка, так как хотим выводить не просто число, а отформатированную строку вида "2 x 3 = 6".
Теперь, когда у нас есть структура данных, нам нужно "нарисовать" ее на форме, чтобы пользователь мог видеть результат.
РезультатТаблица из левого верхнего окна (Реквизиты) в центральное окно (Элементы). Платформа 1С автоматически создаст соответствующий элемент формы типа «Таблица» и свяжет его с вашим реквизитом.ТолькоПросмотр и установите для него галочку (значение Истина).ЗаполнитьТаблицу).Самое интересное — написание кода. Вся логика по заполнению нашей таблицы будет выполняться программно. Платформа 1С уже создала для вас "скелет" процедур, и нам остается лишь заполнить их содержанием.
Этот подход является наиболее рекомендованным для сложных или ресурсоемких операций, так как он позволяет выполнять "тяжелые" вычисления на сервере, а клиент лишь управляет вызовом и отображением. В нашем случае, хотя заполнение таблицы умножения не является "тяжелой" операцией, это хороший пример для демонстрации правильной архитектуры.
Ваш код будет выглядеть следующим образом:
&НаСервере
Процедура ЗаполнитьТаблицуНаСервере()
// Критерий 5: Очищаем таблицу перед заполнением.
// Это гарантирует, что при повторных нажатиях кнопки таблица будет обновляться,
// а не добавлять новые строки к уже существующим.
РезультатТаблица.Очистить();
// Задаем границы циклов для удобства и читаемости кода.
// Избегаем "магических чисел" (чисел, смысл которых не ясен без контекста).
НачалоДиапазона = 1;
КонецДиапазона = 9;
// Критерий 2: Используем внешний цикл для создания строк.
// Этот цикл будет отвечать за второй множитель в выражении "Множимое x Множитель".
Для Множитель = НачалоДиапазона По КонецДиапазона Цикл
// Создаем новую пустую строку в нашей таблице значений.
// Метод Добавить() возвращает объект типа ДанныеФормыЭлементКоллекции,
// который представляет собой новую строку.
НоваяСтрока = РезультатТаблица.Добавить();
// Критерий 3: Используем внутренний цикл для заполнения колонок, без хардкода.
// Этот цикл будет отвечать за первый множитель.
Для Множимое = НачалоДиапазона По КонецДиапазона Цикл
// Критерий 1: Вычисляем результат умножения.
// Избегаем использования константных цифр непосредственно в логике вычисления.
Результат = Множимое * Множитель;
// Формируем текстовое представление для ячейки.
// Функция СтрШаблон() позволяет создать строку из шаблона,
// подставляя значения вместо числовых параметров (%1, %2 и т.д.).
ТекстЯчейки = СтрШаблон("%1 x %2 = %3", Множимое, Множитель, Результат);
// Динамически определяем имя колонки.
// Например, для первого множителя = 1, имя колонки будет "Колонка1".
// Это позволяет нам заполнять колонки по их имени, а не по индексу,
// что делает код более гибким и читаемым.
ИмяКолонки = "Колонка" + Множимое;
// Заполняем нужную колонку в только что созданной строке.
// Обращение к колонке по имени через квадратные скобки (НоваяСтрока[ИмяКолонки])
// является стандартным способом работы с колонками ТаблицыЗначений.
НоваяСтрока[ИмяКолонки] = ТекстЯчейки;
КонецЦикла; // Конец внутреннего цикла (по колонкам)
КонецЦикла; // Конец внешнего цикла (по строкам)
КонецПроцедуры
// Клиентский обработчик просто вызывает серверную процедуру.
// Директива &НаКлиенте означает, что эта процедура выполняется на стороне клиента.
&НаКлиенте
Процедура ЗаполнитьТаблицу(Команда)
// Вызов серверной процедуры, которая выполнит всю основную работу.
ЗаполнитьТаблицуНаСервере();
КонецПроцедуры
Обратите внимание на директивы &НаСервере и &НаКлиенте. Они указывают, где будет выполняться код. Логика, связанная с данными и потенциально "тяжелыми" вычислениями, помещается в серверную процедуру, а клиентская процедура лишь вызывает ее. Это ключевой принцип работы с управляемыми формами в 1С.
Если задача не требует доступа к серверным данным или выполнения сложных вычислений, а также если объем данных небольшой, всю логику можно разместить непосредственно в клиентской процедуре. В нашем случае, для таблицы умножения 9x9, это вполне допустимо и может быть даже проще для понимания начинающим.
При этом подходе нам не понадобится отдельная серверная процедура. Код для заполнения таблицы будет выглядеть так:
&НаКлиенте
Процедура ЗаполнитьТаблицу(Команда)
// Критерий 5: Очищаем таблицу перед заполнением.
// Это гарантирует, что при повторных нажатиях кнопки таблица будет обновляться.
РезультатТаблица.Очистить();
// Задаем границы циклов для удобства и читаемости кода.
НачалоДиапазона = 1;
КонецДиапазона = 9;
// Критерий 2: Используем внешний цикл для создания строк.
Для Множитель = НачалоДиапазона По КонецДиапазона Цикл
// Создаем новую пустую строку в нашей таблице значений.
НоваяСтрока = РезультатТаблица.Добавить();
// Критерий 3: Используем внутренний цикл для заполнения колонок.
Для Множимое = НачалоДиапазона По КонецДиапазона Цикл
// Критерий 1: Вычисляем результат умножения.
Результат = Множимое * Множитель;
// Формируем текстовое представление для ячейки.
ТекстЯчейки = СтрШаблон("%1 x %2 = %3", Множимое, Множитель, Результат);
// Динамически определяем имя колонки.
ИмяКолонки = "Колонка" + Множимое;
// Заполняем нужную колонку в созданной строке.
НоваяСтрока[ИмяКолонки] = ТекстЯчейки;
КонецЦикла; // Конец внутреннего цикла (по колонкам)
КонецЦикла; // Конец внешнего цикла (по строкам)
КонецПроцедуры
Этот вариант, предложенный в одном из сообщений, является более компактным, если вся необходимая информация доступна на клиенте и нет необходимости в интенсивных серверных операциях.
Также возможно использование более универсального способа обращения к реквизитам формы через функции РеквизитФормыВЗначение() и ЗначениеВРеквизитФормы(). Это может быть полезно, когда нужно программно получить и обновить значение реквизита, например, в случае с коллекциями, которые были переданы на клиент, но напрямую не привязаны к элементу формы или если мы хотим более явно управлять синхронизацией между реквизитом и его представлением на форме.
Пример кода, использующий этот подход (предполагается, что реквизит формы называется ТаблицаУмножения и имеет колонки Реквизит1, Реквизит2 и т.д.):
ТаблицаЗначений = РеквизитФормыВЗначение("ТаблицаУмножения", Тип("ТаблицаЗначений"));
ТаблицаЗначений.Очистить();
КоличествоКолонок = ТаблицаЗначений.Колонки.Количество;
Для Счетчик = 1 По КоличествоКолонок Цикл
НоваяСтрока = ТаблицаЗначений.Добавить();
Для НомерКолонки = 1 По КоличествоКолонок Цикл
НоваяСтрока["Реквизит" + НомерКолонки] = "" + НомерКолонки + " х " + Счетчик + " = " + Счетчик * НомерКолонки;
КонецЦикла;
КонецЦикла;
ЗначениеВРеквизитФормы(ТаблицаЗначений, "ТаблицаУмножения");
Этот пример демонстрирует программное заполнение таблицы и обратное присвоение измененных данных реквизиту формы.
После написания кода всегда необходимо проверить его работу.
F7).F5).Таблица на форме должна заполниться данными таблицы умножения. Если что-то пошло не так, вернитесь в Конфигуратор и используйте отладчик для поиска ошибок.
Объект ТабличныйДокумент предоставляет гораздо более широкие возможности для форматирования и оформления вывода по сравнению с ТаблицаЗначений. Его часто используют для формирования отчетов, печатных форм или других документов, где важен внешний вид ячеек (цвет, шрифт, объединение ячеек и т.д.).
Для использования ТабличногоДокумента нам потребуется создать реквизит формы соответствующего типа и, возможно, макет, если мы хотим использовать предопределенное оформление. Однако его можно заполнять и программно, ячейка за ячейкой.
Пример программного заполнения ТабличногоДокумента (предполагаем, что у нас есть реквизит формы ТаблицаУмножения типа ТабличныйДокумент и макет ТаблицаУмножения в обработке):
&НаСервере
Процедура ВывестиТаблицуНаСервере()
// Получаем объект нашей обработки, чтобы иметь доступ к ее макетам.
Обработка = РеквизитФормыВЗначение("Объект");
// Получаем макет ТабличногоДокумента из обработки.
// Макет может содержать предопределенные области, стили и текст.
МакетТаблицаУмножения = Обработка.ПолучитьМакет("ТаблицаУмножения");
// Заполняем ячейки макета данными.
// ВысотаТаблицы и ШиринаТаблицы - это свойства макета,
// если он настроен соответствующим образом, или можно использовать константы.
Для НомерСтроки = 1 По МакетТаблицаУмножения.ВысотаТаблицы Цикл
Для НомерКолонки = 1 По МакетТаблицаУмножения.ШиринаТаблицы Цикл
// Обращаемся к конкретной области (ячейке) макета по ее координатам.
// Свойство Текст позволяет задать текстовое содержимое ячейки.
МакетТаблицаУмножения.Область(НомерСтроки, НомерКолонки).Текст = СтрШаблон("%1 * %2 = %3", НомерКолонки, НомерСтроки, НомерКолонки*НомерСтроки);
КонецЦикла;
КонецЦикла;
// Очищаем существующий ТабличныйДокумент на форме перед выводом нового.
ТаблицаУмножения.Очистить();
// Выводим заполненный макет в элемент ТабличныйДокумент на форме.
ТаблицаУмножения.Вывести(МакетТаблицаУмножения);
КонецПроцедуры
В этом примере мы сначала получаем макет, затем программно заполняем его ячейки и в конце выводим этот заполненный макет в элемент формы, привязанный к реквизиту типа ТабличныйДокумент.
ДинамическийСписок — это мощный инструмент для вывода на форму любых данных в виде списка, таблицы или дерева. Он не хранит данные в явном виде, а динамически получает их из источника (например, из таблицы метаданных или произвольного запроса) по мере необходимости. Это идеальный вариант для отображения больших объемов данных.
Для задачи вывода таблицы умножения ДинамическийСписок, возможно, является избыточным, так как данные генерируются, а не выбираются из существующей базы. Однако для вывода списков элементов справочников, документов или регистров это будет наиболее правильный и эффективный подход.
Рассмотренные подходы к выводу табличных данных в 1С:Предприятии на управляемых формах являются наиболее правильными и рекомендуемыми с точки зрения архитектуры платформы. Давайте кратко подытожим, почему именно так:
ТаблицаЗначений, ТабличныйДокумент) от «как мы это показываем» (элемент формы «Таблица», «Поле табличного документа»). Это делает код более структурированным, облегчает отладку и поддержку, а также позволяет легко менять внешний вид без изменения логики данных.&НаСервере) является лучшей практикой. Сервер, как правило, имеет больше вычислительных ресурсов, быстрый доступ к базе данных и другим ресурсам. Клиент же (&НаКлиенте) должен отвечать только за взаимодействие с пользователем и вызов серверных операций, передавая им необходимые параметры. Это обеспечивает более высокую производительность и отзывчивость пользовательского интерфейса. Хотя для простых задач, как наша таблица умножения, допустимо и полностью клиентское выполнение, привычка разделять логику полезна для будущих, более сложных проектов.ТаблицаЗначений.Добавить()) и заполнение колонок по имени (НоваяСтрока[ИмяКолонки]) или через области (МакетТаблицаУмножения.Область(...).Текст) делает ваш код крайне гибким. Вы не привязаны к жестко заданным индексам или именам ячеек в дизайнере, что позволяет легко адаптировать логику под меняющиеся требования (например, изменить размер таблицы или количество колонок без переписывания всего кода).Надеемся, что эта подробная инструкция поможет вам не только решить текущую задачу, но и глубже понять принципы работы с управляемыми формами в 1С:Предприятии 8.3. Успехов в изучении платформы!