// Получает структуру для индикации прогресса цикла.
//
// Параметры:
// КоличествоПроходов – Число - максимальное значение счетчика;
// ПредставлениеПроцесса – Строка, "Выполнено" – отображаемое название процесса;
// ВнутреннийСчетчик - Булево, *Истина - использовать внутренний счетчик с начальным значением 1,
// иначе нужно будет передавать значение счетчика при каждом вызове обновления индикатора;
// КоличествоОбновлений - Число, *100 - всего количество обновлений индикатора;
// ЛиВыводитьВремя - Булево, *Истина - выводить приблизительное время до окончания процесса;
// РазрешитьПрерывание - Булево, *Истина - разрешает пользователю прерывать процесс.
// МинимальныйПериодОбновления - Число, *1 - с, обновлять не чаще чем этот период, 0 - по количеству обновлений,
// эта реализация не поддерживает дробные значения;
//
// Возвращаемое значение:
// Структура - которую потом нужно будет передавать в метод ЛксОбработатьИндикатор.
//
Функция ЛксПолучитьИндикаторПроцесса(Знач КоличествоПроходов = 0, ПредставлениеПроцесса = "Выполнение", ВнутреннийСчетчик = Истина, Знач КоличествоОбновлений = 100, ЛиВыводитьВремя = Истина, РазрешитьПрерывание = Истина, МинимальныйПериодОбновления = 1) Экспорт
Индикатор = Новый Структура;
Если КоличествоПроходов = 0 Тогда
Состояние(ПредставлениеПроцесса + "...");
КоличествоПроходов = 1;
КонецЕсли;
Индикатор.Вставить("КоличествоПроходов", КоличествоПроходов);
Индикатор.Вставить("ПредставлениеПроцесса", ПредставлениеПроцесса);
Индикатор.Вставить("ЛиВыводитьВремя", ЛиВыводитьВремя);
Индикатор.Вставить("РазрешитьПрерывание", РазрешитьПрерывание);
Индикатор.Вставить("ДатаНачалаПроцесса", ТекущаяДата());
Индикатор.Вставить("МинимальныйПериодОбновления", МинимальныйПериодОбновления);
Индикатор.Вставить("ДатаСледующегоОбновления", Дата('00010101'));
Индикатор.Вставить("ВнутреннийСчетчик", ВнутреннийСчетчик);
Если КоличествоОбновлений > 0 Тогда
Шаг = КоличествоПроходов / КоличествоОбновлений;
Иначе
Шаг = 0;
КонецЕсли;
Индикатор.Вставить("Шаг", Шаг);
Индикатор.Вставить("СледующийСчетчик", 0);
Индикатор.Вставить("Счетчик", 0);
Возврат Индикатор;
КонецФункции
// Проверяет и обновляет индикатор. Нужно вызывать на каждом проходе индицируемого цикла.
//
// Параметры:
// Индикатор – Структура – индикатора, полученная методом ЛксПолучитьИндикаторПроцесса;
// Счетчик – Число – внешний счетчик цикла, используется при ВнутреннийСчетчик = Ложь.
//
Процедура ЛксОбработатьИндикатор(Индикатор, Счетчик = 0) Экспорт
Если Индикатор.ВнутреннийСчетчик Тогда
Счетчик = Индикатор.Счетчик + 1;
Индикатор.Счетчик = Счетчик;
КонецЕсли;
Если Индикатор.РазрешитьПрерывание Тогда
ОбработкаПрерыванияПользователя();
КонецЕсли;
ОбновитьИндикатор = Истина;
ТекущаяДата = ТекущаяДата();
Если Индикатор.МинимальныйПериодОбновления > 0 Тогда
Если ТекущаяДата < Индикатор.ДатаСледующегоОбновления Тогда
ОбновитьИндикатор = Ложь;
КонецЕсли;
КонецЕсли;
Если ОбновитьИндикатор Тогда
Если Индикатор.Шаг > 0 Тогда
Если Счетчик >= Индикатор.СледующийСчетчик Тогда
Индикатор.СледующийСчетчик = Цел(Счетчик + Индикатор.Шаг);
Иначе
ОбновитьИндикатор = Ложь;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если ОбновитьИндикатор Тогда
Индикатор.СледующийСчетчик = Цел(Счетчик + Индикатор.Шаг);
Если Индикатор.ЛиВыводитьВремя Тогда
ПрошлоВремени = ТекущаяДата - Индикатор.ДатаНачалаПроцесса;
Осталось = ПрошлоВремени * (Индикатор.КоличествоПроходов / Счетчик - 1);
ОсталосьДней = Цел(Осталось / (24*60*60));
ТекстОсталось = ", Осталось: ";
Если ОсталосьДней > 0 Тогда
ТекстОсталось = ТекстОсталось + ОсталосьДней + "д";
КонецЕсли;
ТекстОсталось = ТекстОсталось + Формат(Дата(1,1,1) + Осталось, "ДЛФ=T");
ТекстОсталось = ТекстОсталось + ?(Индикатор.РазрешитьПрерывание, ". Прервать: Ctrl+Break", "");
Иначе
ТекстОсталось = "";
КонецЕсли;
ТекстСостояния = Индикатор.ПредставлениеПроцесса + " " + Формат(Счетчик / Индикатор.КоличествоПроходов * 100, "ЧЦ=3; ЧДЦ=0") + "% " + ТекстОсталось;
Состояние(ТекстСостояния);
КонецЕсли;
Если Счетчик = Индикатор.КоличествоПроходов Тогда
Состояние("");
КонецЕсли;
КонецПроцедуры
Ключевым моментом в ЛксОбработатьИндикатор() для обновления состояния является требование выполнения
в общем случае двух (любое можно отключить) условий:
- прошло минимальное время с момента последнего обновления
- не превысить заданное общее число обновлений
Вот пример их использования.
КоличествоДанных = 100000;
Индикатор = ЛксПолучитьИндикаторПроцесса(КоличествоДанных, "Проверка данных");
Для Счетчик = 1 По КоличествоДанных Цикл
ЛксОбработатьИндикатор(Индикатор, Счетчик);
КонецЦикла;
КоличествоДанных = 100000;
Индикатор = ЛксПолучитьИндикаторПроцесса(КоличествоДанных, "Проверка данных", Истина);
Для Счетчик = 1 По КоличествоДанных Цикл
ЛксОбработатьИндикатор(Индикатор);
КонецЦикла;