Как динамически сформировать строки табличного поля по выбранному периоду в управляемой форме 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В этой статье мы подробно рассмотрим процесс создания внешней обработки в 1С:Предприятии 8.3 с управляемой формой. Наша задача — реализовать функциональность, позволяющую пользователю выбрать период (дату начала и дату окончания), а затем динамически заполнить табличное поле на форме строками, где каждая строка будет соответствовать одному дню из выбранного периода. Мы разберем основные понятия, такие как реквизиты формы, табличные поля и таблицы значений, и предоставим пошаговую инструкцию с примерами кода.

Понимание задачи: Реквизиты, Колонки и Строки Табличного Поля

Прежде чем перейти к практической реализации, давайте проясним ключевые термины, которые часто вызывают вопросы, особенно у начинающих разработчиков 1С. Корректное понимание этих понятий является фундаментом для успешной работы с управляемыми формами.

  1. Реквизиты формы: Это, по сути, переменные, которые хранят данные, связанные непосредственно с формой. Реквизиты могут быть различных типов: примитивные (строка, число, дата, булево), а также более сложные объекты, такие как ТаблицаЗначений, ДеревоЗначений или ДинамическийСписок. В нашем случае, даты начала и окончания периода будут представлены как реквизиты формы.
  2. Табличное поле: Это визуальный элемент управления, который размещается на управляемой форме. Его основное назначение — отображение табличных данных. Важно понимать, что само по себе табличное поле не хранит данные; оно является лишь "представлением" данных, которые хранятся в привязанном к нему источнике. Таким источником, как правило, выступает другой реквизит формы, например, ТаблицаЗначений или ТабличнаяЧастьОбъекта.
  3. Колонки Табличного поля: Определяют структуру данных, которые будут отображаться в таблице. Например, если мы отображаем список дней, у таблицы может быть колонка "Дата", "ДеньНедели" и так далее. Колонки обычно определяются либо в конфигураторе при создании реквизита формы типа ТаблицаЗначений, либо могут быть добавлены программно уже в процессе работы.
  4. Строки Табличного поля: Это отдельные записи данных, которые отображаются в таблице. Каждая строка состоит из набора значений, соответствующих определенным колонкам. В нашей текущей задаче нам необходимо динамически создавать именно строки, где каждая строка будет представлять один день из выбранного пользователем периода.

Изначально в постановке задачи могло возникнуть предположение о необходимости динамического создания *колонок* для каждого дня (например, "День 1", "День 2" и т.д.). Однако, уточнение показало, что требуется отобразить каждый день как отдельную *строку* в таблице. Для эффективной реализации такого подхода в 1С наиболее подходящим инструментом является использование объекта ТаблицаЗначений.

Основной подход: Использование ТаблицыЗначений как источника данных

Для динамического формирования строк в табличном поле на управляемой форме мы будем использовать реквизит формы типа ТаблицаЗначений. Это мощный и гибкий программный объект, который позволяет нам полностью контролировать как структуру (колонки), так и содержимое (строки) таблицы непосредственно из кода. Когда ТабличноеПоле на форме привязано к такому реквизиту, любые программные изменения в ТаблицеЗначений автоматически отображаются на форме, обеспечивая динамическое обновление пользовательского интерфейса.

Пошаговая реализация

Давайте пошагово разберем процесс создания внешней обработки и ее функционала.

  1. Шаг 1: Создание внешней обработки и формы

    Начнем с базовой подготовки в конфигураторе.

    1. Откроем конфигуратор 1С:Предприятия.
    2. Создадим новую внешнюю обработку, выбрав в меню
      
      Файл -> Новый -> Внешняя обработка
      
      .
    3. Сохраним созданную обработку в удобном месте на диске с расширением
      
      .epf
      
      .
    4. Перейдем на вкладку "Формы" новой обработки и создадим новую управляемую форму. Можем назвать ее, например,
      
      ФормаОсновная
      
      .
  2. Шаг 2: Добавление реквизитов формы для ввода периода

    Нам потребуется два реквизита для того, чтобы пользователь мог указать интересующий его временной интервал.

    1. В окне "Реквизиты" формы (обычно находится слева внизу) добавим новый реквизит, нажав кнопку с изображением плюса или клавишу
      
      Insert
      
      .
    2. Зададим его свойства:
      • Имя:
        
        ДатаНачала
        
      • Тип:
        
        Дата
        
        (в свойствах типа выберем "Состав даты": Дата)
    3. Аналогичным образом добавим второй реквизит:
      • Имя:
        
        ДатаОкончания
        
      • Тип:
        
        Дата
        
        (в свойствах типа выберем "Состав даты": Дата)
    4. Перетащим эти два реквизита из окна "Реквизиты" в область элементов формы. Платформа 1С автоматически создаст для них соответствующие элементы управления — поля ввода даты.
  3. Шаг 3: Создание реквизита формы типа "ТаблицаЗначений"

    Теперь создадим реквизит, который будет служить источником данных для нашего динамически заполняемого табличного поля.

    1. В окне "Реквизиты" формы добавим еще один новый реквизит.
    2. Зададим его свойства:
      • Имя:
        
        ДанныеПериода
        
        (или любое другое осмысленное имя, например,
        
        СписокДней
        
        )
      • Тип:
        
        ТаблицаЗначений
        
    3. После создания реквизита типа
      
      ТаблицаЗначений
      
      , нам необходимо определить его колонки. Для нашей задачи потребуется одна колонка, которая будет хранить дату дня.
      1. Выделим только что созданный реквизит
        
        ДанныеПериода
        
        в окне "Реквизиты".
      2. Внизу этого же окна "Реквизиты" появится вкладка "Колонки". Перейдем на нее.
      3. На вкладке "Колонки" добавим новую колонку, нажав кнопку с плюсом.
      4. Зададим ее свойства:
        • Имя:
          
          День
          
        • Тип:
          
          Дата
          
          (в свойствах типа выберем "Состав даты": Дата)
    4. Это гарантирует, что наша
      
      ТаблицаЗначений
      
      будет иметь необходимую структуру для хранения дат.
  4. Шаг 4: Размещение табличного поля и кнопки на форме

    На этом шаге мы разместим визуальные элементы на форме, чтобы пользователь мог взаимодействовать с нашей обработкой.

    1. Перетащим реквизит
      
      ДанныеПериода
      
      из окна "Реквизиты" в область элементов формы. Платформа 1С автоматически создаст для него элемент управления
      
      ТабличноеПоле
      
      .
    2. Добавим кнопку, которая будет инициировать процесс заполнения таблицы.
      1. В окне "Элементы" формы найдем группу "Команды" (если ее нет, создадим новую группу команд).
      2. В эту группу добавим новую команду, нажав соответствующую кнопку.
      3. Зададим ее свойства:
        • Имя:
          
          Заполнить
          
        • Действие: Выберем опцию "Создать на клиенте и сервере" для автоматического создания процедур-обработчиков
          
          &НаКлиенте
          
          и
          
          &НаСервере
          
          .
      4. Перетащим эту команду из окна "Команды" на форму, чтобы создать кнопку с заголовком "Заполнить".
  5. Шаг 5: Написание кода для динамического заполнения таблицы

    Перейдем к написанию основной логики, которая будет заполнять нашу таблицу. Откроем модуль формы (обычно двойным щелчком по названию формы или через контекстное меню "Открыть модуль"). Мы увидим, что автоматически были созданы процедуры

    
    Заполнить
    
    (на клиенте) и
    
    ЗаполнитьНаСервере
    
    (на сервере). Важно помнить, что вся логика работы с данными, включая добавление строк в ТаблицуЗначений, должна выполняться на сервере.

    Рассмотрим код, который будет получать даты начала и окончания с формы, очищать нашу ТаблицуЗначений и затем заполнять ее новыми строками, представляющими каждый день в выбранном периоде.

    
    &НаСервере
    Процедура ЗаполнитьНаСервере()
        // Получаем значения дат с реквизитов формы.
        // В серверном контексте к реквизитам формы можно обращаться напрямую по их именам.
        ДатаНачалаПериода = ДатаНачала;
        ДатаОкончанияПериода = ДатаОкончания;
    
        // Выполняем предварительные проверки, чтобы избежать ошибок и некорректного поведения.
        // Проверяем, что обе даты были указаны пользователем.
        Если ДатаНачалаПериода = Неопределено ИЛИ ДатаОкончанияПериода = Неопределено Тогда
            Сообщить("Пожалуйста, укажите и дату начала, и дату окончания периода.", СтатусСообщения.Важное);
            Возврат; // Выходим из процедуры, так как данные некорректны.
        КонецЕсли;
    
        // Проверяем, что дата начала не позднее даты окончания.
        Если ДатаНачалаПериода > ДатаОкончанияПериода Тогда
            Сообщить("Дата начала не может быть позднее даты окончания.", СтатусСообщения.Важное);
            Возврат; // Выходим из процедуры.
        КонецЕсли;
    
        // Очищаем существующую ТаблицуЗначений перед новым заполнением.
        // Это гарантирует, что старые данные не будут смешиваться с новыми.
        ДанныеПериода.Очистить(); 
    
        // Инициализируем переменную для итерации по дням.
        // Используем НачалоДня() для стандартизации времени до 00:00:00,
        // что важно для корректного сравнения и инкрементации дат.
        ТекущаяДата = НачалоДня(ДатаНачалаПериода);
                
        // Цикл для добавления каждой даты в таблицу.
        // Цикл продолжается, пока текущая дата меньше или равна дате окончания периода.
        Пока ТекущаяДата <= НачалоДня(ДатаОкончанияПериода) Цикл
            // Добавляем новую строку в реквизит формы типа ТаблицаЗначений (ДанныеПериода).
            // Метод Добавить() возвращает ссылку на вновь созданную строку.
            НоваяСтрока = ДанныеПериода.Добавить(); 
                    
            // Заполняем колонку "День" новой строки значением текущей даты.
            // "День" - это имя колонки, которую мы определили ранее для ТаблицыЗначений.
            НоваяСтрока.День = ТекущаяДата; 
                    
            // Переходим к следующему дню.
            // Функция ДобавитьМесяц(Дата, СмещениеМесяцев, СмещениеДней, СмещениеСекунд)
            // является удобным и надежным способом для выполнения операций с датами.
            // В данном случае, мы прибавляем 1 день, оставляя месяцы и секунды без изменений.
            ТекущаяДата = ДобавитьМесяц(ТекущаяДата, 0, 1); 
        КонецЦикла;
    КонецПроцедуры
    
    &НаКлиенте
    Процедура Заполнить(Команда)
        // Эта процедура выполняется на клиенте (в пользовательском интерфейсе).
        // Она просто вызывает серверную процедуру ЗаполнитьНаСервере(),
        // где происходит вся основная логика работы с данными.
        ЗаполнитьНаСервере();
    КонецПроцедуры
    

    Разберем ключевые моменты представленного кода:

    1. 
      ДатаНачала
      
      и
      
      ДатаОкончания
      
      : В серверном контексте мы можем обращаться к реквизитам формы напрямую по их именам без использования префикса
      
      Элементы.
      
      . Это упрощает код и делает его более читаемым.
    2. 
      ДанныеПериода.Очистить()
      
      : Перед каждым новым заполнением таблицы мы вызываем этот метод, чтобы удалить все ранее отображенные строки. Это гарантирует, что пользователь всегда видит актуальный список дней, соответствующий последнему выбранному периоду.
    3. 
      ТекущаяДата = НачалоДня(ДатаНачалаПериода)
      
      : Использование функции
      
      НачалоДня()
      
      является хорошей практикой. Она устанавливает время для даты начала в 00:00:00, что предотвращает потенциальные проблемы с сравнением дат и инкрементацией, если исходные даты содержали время.
    4. 
      Пока ТекущаяДата <= НачалоДня(ДатаОкончанияПериода) Цикл
      
      : Условие цикла гарантирует, что будут включены все дни, начиная с даты начала и заканчивая датой окончания, включая саму дату окончания.
    5. 
      НоваяСтрока = ДанныеПериода.Добавить()
      
      : Этот метод является фундаментальным для динамического добавления строк в ТаблицуЗначений. Он создает новую пустую строку и возвращает на нее ссылку, которую мы сохраняем в переменной
      
      НоваяСтрока
      
      .
    6. 
      НоваяСтрока.День = ТекущаяДата
      
      : После получения ссылки на новую строку, мы можем заполнять ее колонки. В данном случае, мы присваиваем значение
      
      ТекущаяДата
      
      в колонку
      
      День
      
      . Имя колонки (
      
      День
      
      ) должно точно соответствовать имени, которое мы задали для колонки реквизита
      
      ДанныеПериода
      
      в конфигураторе.
    7. 
      ТекущаяДата = ДобавитьМесяц(ТекущаяДата, 0, 1)
      
      : Это предпочтительный способ инкрементации даты на один день в 1С. Функция
      
      ДобавитьМесяц
      
      корректно обрабатывает переходы через месяцы и годы, в отличие от простого прибавления секунд, которое может быть менее надежным в некоторых случаях.

Динамическое создание колонок (более сложный сценарий)

Хотя в нашей основной задаче требуется динамическое формирование строк в таблице с заранее определенными колонками, стоит упомянуть о возможности более сложного сценария, когда необходимо динамически создавать сами колонки ТаблицыЗначений или даже реквизиты формы в процессе выполнения программы. Такой подход может быть актуален, если, например, количество и имена колонок должны зависеть от выбранных пользователем параметров, периода или других динамических условий.

Для программного добавления колонок в уже существующий реквизит формы типа ТаблицаЗначений используется метод Колонки.Добавить(). Если же нам требуется создать сам реквизит формы "на лету" (что бывает реже для ТаблицаЗначений, но возможно для других типов), то применяется метод ИзменитьРеквизиты().

Рассмотрим пример программного добавления колонки в ТаблицуЗначений, если бы она не была определена в конфигураторе:


&НаСервере
Процедура ДинамическоеСозданиеКолонокНаСервере()
    // Предположим, что реквизит формы "ДанныеПериода" уже существует,
    // но его колонки еще не определены или нужно добавить новую.

    // Проверяем, существует ли уже колонка "День".
    // Если нет, то создаем ее программно.
    Если ДанныеПериода.Колонки.Найти("День") = Неопределено Тогда
        // Добавляем новую колонку с именем "День" и типом "Дата"
        ДанныеПериода.Колонки.Добавить("День", Новый ОписаниеТипов("Дата")); 
        Сообщить("Колонка 'День' была добавлена в ТаблицуЗначений программно.");
    Иначе
        Сообщить("Колонка 'День' уже существует в ТаблицеЗначений.");
    КонецЕсли;

    // После добавления колонок можно приступать к заполнению строк,
    // как это было описано в основной задаче.
    // ...
КонецПроцедуры

Этот код позволяет гибко настроить структуру таблицы в зависимости от потребностей. Метод


ОписаниеТипов()
используется для указания типа данных создаваемой колонки. Для более сложного сценария, когда каждая колонка должна представлять отдельный день (например, "День_01.01.2000", "День_02.01.2000"), пришлось бы использовать комбинацию

ИзменитьРеквизиты
для создания множества реквизитов формы, а затем программно размещать их на форме или же динамически формировать колонки ТаблицыЗначений с уникальными именами. Однако, как мы выяснили, это не является целью нашей текущей задачи, которая сфокусирована на динамическом формировании строк.

Заключение

Мы успешно рассмотрели и реализовали создание внешней обработки в 1С:Предприятии 8.3 с управляемой формой, которая динамически формирует табличное поле. Наша обработка позволяет пользователю выбрать период и затем выводит каждый день этого периода как отдельную строку в таблице.

Использование реквизита формы типа ТаблицаЗначений, привязанного к ТабличномуПолю, является стандартным, гибким и наиболее эффективным подходом для решения подобных задач в 1С. Этот метод позволяет нам полностью контролировать данные, отображаемые в таблице, изменять их структуру и содержимое программно, что делает его незаменимым инструментом для разработки интерактивных и динамичных пользовательских интерфейсов.

Применяя описанные шаги и принципы, вы сможете создавать разнообразные отчеты и обработки, которые будут эффективно обрабатывать и представлять табличные данные в системе 1С:Предприятие.

← На главную