Как записать значение строкового периода (месяц и год) в реквизит документа с типом Дата?

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

При разработке документов в конфигурациях на базе 1С:Предприятие 8.3, особенно в таких решениях, как Зарплата и управление персоналом 3.1, часто возникает необходимость реализовать удобный выбор периода. Вместо стандартного поля ввода даты пользователю привычнее видеть текстовое представление, например, «Июль 2022». Однако в базе данных этот период должен храниться как полноценная дата (обычно первое число месяца). Рассмотрим подробно, как организовать двустороннюю связь между строковым реквизитом формы и реквизитом объекта типа Дата.

Постановка задачи и анализ механизмов

Представим ситуацию: у нас есть документ, в котором имеется реквизит ПериодНачисления (тип Дата). На форме документа мы создаем вспомогательный реквизит ПериодНачисленияСтрокой (тип Строка). Нам необходимо обеспечить:

  1. Заполнение строки при открытии: Если документ уже существует, форма должна преобразовать дату 01.07.2022 в строку «Июль 2022».
  2. Интерактивный выбор: При нажатии на кнопку выбора в поле строки должен открываться список месяцев.
  3. Запись значения: При выборе месяца из списка или ручном вводе программа должна вычислить начало этого месяца и записать его в основной реквизит Объект.ПериодНачисления.

Проанализируем типовые механизмы. В конфигурации ЗУП 3.1 этот функционал уже реализован и вынесен в общие модули. Использование стандартных функций — это лучший способ избежать ошибок и обеспечить единство интерфейса.

Решение 1: Использование типового функционала ЗУП 3.1

Для того чтобы повторить механизм выбора периода как в типовых документах, выполним следующие шаги. Прежде всего, разберем работу с событиями формы.

В процедуре ПриСозданииНаСервере или ПриЧтенииНаСервере необходимо инициализировать строковый реквизит. Если мы просто выведем дату в строку, она будет выглядеть как «01.07.2022 0:00:00», что нам не подходит. Используем функцию получения представления месяца.

Рассмотрим пример кода для инициализации формы:


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

В этом коде мы используем метод ЗарплатаКадрыКлиентСервер.ПолучитьПредставлениеМесяца(), который корректно формирует строку на основании переданной даты. Это избавляет нас от ручного форматирования.

Решение 2: Обработка выбора и синхронизация данных

Теперь выясним, как передать данные обратно из строки в объект при изменении значения пользователем. Для поля ПериодНачисленияСтрокой на форме следует создать обработчик события ПриИзменении. В типовых конфигурациях за это отвечает клиентский модуль.

Проанализируем ситуацию, когда мы работаем с нестандартным документом. Нам нужно превратить строку обратно в дату. Самый надежный способ в рамках ЗУП — вызвать процедуру ЗарплатаКадрыКлиент.ПериодНачисленияПриИзменении, но если вы строите свою логику, можно воспользоваться следующим подходом:


&НаКлиенте
Процедура ПериодНачисленияСтрокойПриИзменении(Элемент)
    
    // Вызываем типовой механизм для заполнения Объект.ПериодНачисления
    // и обновления самой строки (например, если пользователь ввел "июл 22")
    ПараметрыОбработки = Новый Структура;
    ПараметрыОбработки.Вставить("ИмяРеквизитаДаты", "ПериодНачисления");
    ПараметрыОбработки.Вставить("ИмяРеквизитаСтроки", "ПериодНачисленияСтрокой");
    
    // Эта функция сама распарсит строку и запишет дату в Объект
    ЗарплатаКадрыКлиент.ПериодНачисленияПриИзменении(ЭтаФорма, ПараметрыОбработки);
    
КонецПроцедуры

Важный момент: если вы используете собственные алгоритмы и не хотите зависеть от типовых модулей, вам придется реализовать «парсер» строки. Рассмотрим, как это сделать вручную.

Решение 3: Ручной разбор строки (универсальный метод)

Если ваша конфигурация не содержит модулей ЗарплатаКадрыКлиент, или вы работаете в пустой базе, можно применить алгоритм сопоставления. Разберем пример кода, который преобразует строку «Июль 2022» в дату 01.07.2022:


&НаКлиенте
Функция ПреобразоватьСтрокуВДату(Знач СтрПериод)
    
    День = "01";
    // Определяем номер месяца по вхождению подстроки
    Если СтрНайти(СтрПериод, "Январь") > 0 Тогда
        Месяц = "01";
    ИначеЕсли СтрНайти(СтрПериод, "Февраль") > 0 Тогда
        Месяц = "02";
    ИначеЕсли СтрНайти(СтрПериод, "Март") > 0 Тогда
        Месяц = "03";
    ИначеЕсли СтрНайти(СтрПериод, "Апрель") > 0 Тогда
        Месяц = "04";
    ИначеЕсли СтрНайти(СтрПериод, "Май") > 0 Тогда
        Месяц = "05";
    ИначеЕсли СтрНайти(СтрПериод, "Июнь") > 0 Тогда
        Месяц = "06";
    ИначеЕсли СтрНайти(СтрПериод, "Июль") > 0 Тогда
        Месяц = "07";
    ИначеЕсли СтрНайти(СтрПериод, "Август") > 0 Тогда
        Месяц = "08";
    ИначеЕсли СтрНайти(СтрПериод, "Сентябрь") > 0 Тогда
        Месяц = "09";
    ИначеЕсли СтрНайти(СтрПериод, "Октябрь") > 0 Тогда
        Месяц = "10";
    ИначеЕсли СтрНайти(СтрПериод, "Ноябрь") > 0 Тогда
        Месяц = "11";
    Иначе
        Месяц = "12";
    КонецЕсли;
    
    // Извлекаем последние 4 символа как год
    Год = Прав(СокрЛП(СтрПериод), 4);
    
    // Собираем строку формата "ДД.ММ.ГГГГ" и преобразуем в Дату
    СтрокаДаты = День + "." + Месяц + "." + Год;
    Попытка
        Возврат Дата(СтрокаДаты);
    Исключение
        Возврат '00010101';
    КонецПопытки;
    
КонецФункции

Этот метод прямолинеен, но эффективен. После получения даты её необходимо присвоить реквизиту Объект.ПериодНачисления.

Особенности работы с управляемыми формами

Проанализируем типичную ошибку начинающих разработчиков: «При открытии существующего документа поле периода пустое». Это происходит из-за того, что данные реквизита ПериодНачисленияСтрокой существуют только «на экране» (в памяти формы) и не сохраняются в базе данных автоматически вместе с объектом.

Чтобы избежать этой проблемы, всегда используйте процедуру ПриЧтенииНаСервере на форме документа. В отличие от ПриСозданииНаСервере, она срабатывает каждый раз, когда данные объекта считываются из базы (например, после записи или при перечитывании данных).

Рассмотрим правильную структуру инициализации:


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

Использование форматной строки "ДФ='MMMM yyyy'" — это быстрый способ получить название месяца и год без использования внешних функций. Однако помните, что Формат() зависит от локализации системы (языковых настроек).

Дополнительный функционал: Кнопки регулирования

Для удобства пользователя можно включить у поля ПериодНачисленияСтрокой свойство «Кнопка регулирования». Это позволит переключать месяцы стрелками «вверх» и «вниз». Разберем, как это запрограммировать:


&НаКлиенте
Процедура ПериодНачисленияСтрокойРегулирование(Элемент, Направление, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // Определяем шаг изменения (1 месяц или -1 месяц)
    Шаг = ?(Направление > 0, 1, -1);
    
    // Вычисляем новую дату
    НоваяДата = ДобавитьМесяц(Объект.ПериодНачисления, Шаг);
    Объект.ПериодНачисления = НоваяДата;
    
    // Обновляем строковое представление
    ПериодНачисленияСтрокой = ЗарплатаКадрыКлиентСервер.ПолучитьПредставлениеМесяца(НоваяДата);
    
КонецПроцедуры

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

← На главную