База знаний Одина — Одинэсника › Форумы › ODIN — Форум по 1С Предприятию › Как разбить период по месяцам в 1С 8.3 для табличной части? › Ответ в теме: Как разбить период по месяцам в 1С 8.3 для табличной части?
Чтобы разбить период с ДатаНач по ДатаКон на месячные интервалы с учетом частичных месяцев (как в вашем примере), нужно написать код, который будет формировать записи табличной части с нужными датами начала и конца для каждого периода.
Пример кода для кнопки на форме документа 1С 8.3 (обычные формы):
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
&НаКлиенте Процедура РазбитьПериод(Команда) // Получаем даты из реквизитов формы ДатаНач = ЭтаФорма.Элементы.ДатаНач.Значение; ДатаКон = ЭтаФорма.Элементы.ДатаКон.Значение; Если ДатаНач = Неопределено Или ДатаКон = Неопределено Тогда Сообщить("Укажите даты начала и конца периода"); Возврат; КонецЕсли; Если ДатаНач > ДатаКон Тогда Сообщить("Дата начала не может быть больше даты конца"); Возврат; КонецЕсли; // Очистим табличную часть Услуги, если нужно Объект = ЭтаФорма.Объект; Объект.Услуги.Очистить(); // Переменная для текущей даты начала периода ТекДатаНач = ДатаНач; Пока ТекДатаНач <= ДатаКон Цикл // Определяем последний день месяца для ТекДатаНач ПоследнийДеньМесяца = КонецМесяца(ТекДатаНач); // Дата конца периода - либо конец месяца, либо ДатаКон, если он раньше Если ПоследнийДеньМесяца > ДатаКон Тогда ТекДатаКон = ДатаКон; Иначе ТекДатаКон = ПоследнийДеньМесяца; КонецЕсли; // Добавляем новую строку в табличную часть НоваяСтрока = Объект.Услуги.Добавить(); // Заполняем даты начала и конца периода НоваяСтрока.Д_нач = ТекДатаНач; НоваяСтрока.Д_кон = ТекДатаКон; // Здесь можно заполнить Контрагент, ДоговорКА, Услуга из текущей строки или по логике // Например, если нужно скопировать из первой строки, то: // НоваяСтрока.Контрагент = ...; // НоваяСтрока.ДоговорКА = ...; // НоваяСтрока.Услуга = ...; // Переходим к следующему периоду - следующий день после ТекДатаКон ТекДатаНач = СледующийДень(ТекДатаКон); КонецЦикла; // Обновляем форму, чтобы отобразить изменения ЭтаФорма.Обновить(); КонецПроцедуры |
Объяснение:
— КонецМесяца(Дата) — встроенная функция 1С, возвращает последний день месяца для указанной даты.
— СледующийДень(Дата) — возвращает дату +1 день.
— Цикл идет от ДатаНач до ДатаКон, разбивая период на месячные интервалы.
— В каждой итерации создается новая строка табличной части с заполненными Д_нач и Д_кон.
— Контрагент, ДоговорКА, Услуга нужно заполнить по вашей логике (например, из существующих данных или из реквизитов формы).
Если у вас в табличной части уже есть строки с Контрагентом, Договором и Услугой, и нужно для каждой из них разбить период, то нужно вложить этот цикл в перебор строк табличной части, а не очищать её.
Если нужно разбить период для каждой строки ТЧ, то пример:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
&НаКлиенте Процедура РазбитьПериодПоСтрокам(Команда) Объект = ЭтаФорма.Объект; ДатаНач = ЭтаФорма.Элементы.ДатаНач.Значение; ДатаКон = ЭтаФорма.Элементы.ДатаКон.Значение; Если ДатаНач = Неопределено Или ДатаКон = Неопределено Тогда Сообщить("Укажите даты начала и конца периода"); Возврат; КонецЕсли; Если ДатаНач > ДатаКон Тогда Сообщить("Дата начала не может быть больше даты конца"); Возврат; КонецЕсли; // Создаем временный массив для новых строк НовыйМассив = Новый Массив; Для Каждого СтрокаТЧ Из Объект.Услуги Цикл ТекДатаНач = ДатаНач; Пока ТекДатаНач <= ДатаКон Цикл ПоследнийДеньМесяца = КонецМесяца(ТекДатаНач); Если ПоследнийДеньМесяца > ДатаКон Тогда ТекДатаКон = ДатаКон; Иначе ТекДатаКон = ПоследнийДеньМесяца; КонецЕсли; НоваяСтрока = Новый Структура; НоваяСтрока.Вставить("Контрагент", СтрокаТЧ.Контрагент); НоваяСтрока.Вставить("ДоговорКА", СтрокаТЧ.ДоговорКА); НоваяСтрока.Вставить("Услуга", СтрокаТЧ.Услуга); НоваяСтрока.Вставить("Д_нач", ТекДатаНач); НоваяСтрока.Вставить("Д_кон", ТекДатаКон); НовыйМассив.Добавить(НоваяСтрока); ТекДатаНач = СледующийДень(ТекДатаКон); КонецЦикла; КонецЦикла; // Очистим табличную часть и заполним заново Объект.Услуги.Очистить(); Для Каждого НоваяСтрока Из НовыйМассив Цикл НоваяСтрокаТЧ = Объект.Услуги.Добавить(); НоваяСтрокаТЧ.Контрагент = НоваяСтрока.Контрагент; НоваяСтрокаТЧ.ДоговорКА = НоваяСтрока.ДоговорКА; НоваяСтрокаТЧ.Услуга = НоваяСтрока.Услуга; НоваяСтрокаТЧ.Д_нач = НоваяСтрока.Д_нач; НоваяСтрокаТЧ.Д_кон = НоваяСтрока.Д_кон; КонецЦикла; ЭтаФорма.Обновить(); КонецПроцедуры |
Так вы для каждой исходной строки создадите несколько новых с разбивкой по месяцам.
Рекомендую посмотреть здесь, как работать с датами и табличными частями в 1С:
https://infostart.ru/public/1042547/
https://helpf.pro/faq82/view/1423.html