При формировании печатных форм соглашений, графиков рассрочки или расчетов задолженности в платформе 1С:Предприятие 7.7 часто возникает задача повторить вывод секций таблицы заданное число раз, соответствующее количеству месяцев. Рассмотрим типичные ошибки, возникающие при реализации таких алгоритмов, и разберем правильные способы организации цикла и расчета дат.
Разберем типичный фрагмент кода, в котором допущены сразу три распространенные ошибки при построении графика задолженности:
ДатаДок + ДобавитьМесяц(ДатаДок, 1) ошибочно, так как функция ДобавитьМесяц() сама по себе возвращает полноценное значение типа Дата. Сложение двух дат в 1С 7.7 приводит к сложению их внутренних числовых представлений (юлианских дней), в результате чего получается дата из далекого будущего.СуммаДолг = СуммаДолг + СуммаДолг удваивает значение на каждом шаге цикла вместо равномерного добавления ежемесячной доли.Пока: для фиксированного числа итераций (например, если количество месяцев задано числовым реквизитом на форме) цикл с предусловием усложняет код и может привести к бесконечному зацикливанию при ошибках в условиях выхода.Когда число повторений заранее известно и хранится в реквизите диалога Месяц (или мес), оптимальным решением является использование цикла Для со счетчиком. Проанализируем правильный вариант построения модуля формирования печатной формы:
Процедура СформироватьГрафик()
// Проверяем корректность введенного количества месяцев
Если (ПустоеЗначение(Месяц) = 1) Или (Месяц <= 0) Тогда
Предупреждение("Укажите корректное количество месяцев!");
Возврат;
КонецЕсли;
Таб = СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("Сформировать");
ДатаДок = ТекущаяДата();
НазваниеОрганизации = Константа.ЗаголовокДляСоглашения;
Контрагент = Контр.Наименование;
Паспорт = Контр.ПаспортныеДанные;
АдресК = Контр.Адрес;
Сумма = Контр.СуммаДолга;
Таб.ВывестиСекцию("Шапка");
// Рассчитываем базовый ежемесячный платеж
СуммаМес = Окр(Сумма / Месяц, 2);
Накоплено = 0;
Для НомерМесяца = 1 По Месяц Цикл
// Корректно смещаем дату на нужное число месяцев вперед
ДатаМесяца = ДобавитьМесяц(ДатаДок, НомерМесяца);
// В последнем месяце учитываем возможную погрешность округления копеек
Если НомерМесяца = Месяц Тогда
ТекущийПлатеж = Сумма - Накоплено;
Иначе
ТекущийПлатеж = СуммаМес;
Накоплено = Накоплено + ТекущийПлатеж;
КонецЕсли;
Таб.ВывестиСекцию("Долг");
КонецЦикла;
Таб.ТолькоПросмотр(1);
Таб.Показать("График платежей");
КонецПроцедуры
Если по логике алгоритма требуется именно накопление суммы и завершение цикла по достижению общего долга, необходимо завести отдельную переменную для шага прироста и накопителя. Рассмотрим, как выглядит корректный вариант:
СуммаМес = Окр(Сумма / Месяц, 2);
СуммаДолг = 0;
НомерШага = 1;
Пока СуммаДолг < Сумма Цикл
ДатаМесяца = ДобавитьМесяц(ДатаДок, НомерШага);
Если (СуммаДолг + СуммаМес) > Сумма Тогда
ТекущийПлатеж = Сумма - СуммаДолг;
Иначе
ТекущийПлатеж = СуммаМес;
КонецЕсли;
СуммаДолг = СуммаДолг + ТекущийПлатеж;
Таб.ВывестиСекцию("Долг");
НомерШага = НомерШага + 1;
КонецЦикла;
Сумма / Месяц всегда делайте проверку значения реквизита. Если реквизит диалога пуст или равен нулю, 1С 7.7 аварийно завершит выполнение с системной ошибкой.ДобавитьМесяц: данная функция автоматически учитывает разное количество дней в месяцах и високосные годы. Смещение на 1 месяц от 31.01 корректно вернет 28.02 (или 29.02). Чтобы привязать платеж к строго первому или последнему числу, комбинируйте вызов с функциями НачМесяца() или КонМесяца().Таб.ВывестиСекцию() печатная форма не отображается на экране сама. Обязательно вызывайте Таб.Показать(), а для запрета случайных правок пользователем используйте Таб.ТолькоПросмотр(1).