Автоматизация рутинных операций — одна из важнейших задач при сопровождении любых учетных систем. В платформе 1С:Предприятие 7.7 задача автоматического формирования отчетов по расписанию остается крайне актуальной. Пользователям часто требуется получать свежие аналитические данные к определенному времени (например, к началу рабочего дня или к отчетному часу), не тратя время на ручной запуск, выбор параметров в диалоговых окнах и нажатие кнопок.
В этой статье мы подробно рассмотрим, как реализовать запуск отчетов с заранее сохраненными или динамически формируемыми параметрами по расписанию. Мы разберем как штатные возможности платформы, так и более продвинутые варианты с использованием системных скриптов и внешних компонент. Кроме того, мы опровергнем некоторые опасные заблуждения, которые часто встречаются на форумах, и покажем, как избежать критических ошибок при реализации таймеров.
Для того чтобы отчет мог выполняться без интерактивного участия пользователя (в так называемом "тихом" или фоновом режиме), нам необходимо научить форму отчета самостоятельно обрабатывать входящие параметры, запускать расчет и закрываться после завершения работы. Главным инструментом для этого в 1С 7.7 служит предопределенная процедура ПриОткрытии и системная функция СтатусВозврата.
Рассмотрим подробнее, как устроен этот механизм. Когда мы открываем форму отчета программно, мы можем передать в нее контекст или структуру параметров. Внутри процедуры ПриОткрытии мы анализируем эти параметры. Если они переданы, система заполняет реквизиты диалога, вызывает основную процедуру формирования отчета (например, Сформировать) и затем вызывает команду СтатусВозврата(0). Данная команда сообщает платформе, что открытие формы необходимо отменить. В результате форма выполняет весь необходимый код, но визуально на экране пользователя даже не появляется, мгновенно закрываясь после завершения процесса.
Давайте посмотрим на пример реализации такого кода внутри модуля формы отчета:
Процедура ПриОткрытии()
// Получаем переданный параметр запуска
ПараметрыЗапуска = Форма.Параметр;
// Проверяем, открыт ли отчет интерактивно или программно по расписанию
Если ПустоеЗначение(ПараметрыЗапуска) = 0 Тогда
// Параметры переданы — работаем в автоматическом режиме
// Разбираем параметры. Это может быть строка, список значений или структура
Если ТипЗначенияСтр(ПараметрыЗапуска) = "СписокЗначений" Тогда
ДатаНач = ПараметрыЗапуска.Получить("ДатаНачала");
ДатаКон = ПараметрыЗапуска.Получить("ДатаКонца");
ВыбФирма = ПараметрыЗапуска.Получить("Фирма");
Иначе
// Если параметры переданы простой строкой, задаем значения по умолчанию
ДатаНач = НачалоМесяца(ТекущаяДата());
ДатаКон = ТекущаяДата();
КонецЕсли;
// Запускаем формирование отчета
Сформировать();
// Сохраняем результат (например, в реестр, файл или отправляем на почту)
// В данном примере мы просто закрываем форму, не выводя ее на экран
СтатусВозврата(0);
Возврат;
КонецЕсли;
// Если параметров нет, отчет открывается как обычно для ручной работы пользователя
ДатаНач = РабочаяДата();
ДатаКон = РабочаяДата();
КонецПроцедуры
Такой подход позволяет использовать один и тот же файл отчета (.ert) как для повседневной ручной работы пользователей, так и для автоматического формирования по расписанию.
При проектировании запуска задач внутри запущенного сеанса 1С 7.7 разработчики часто обращаются к штатному методу ОбработкаОжидания. На форумах можно встретить утверждение, что в системе можно запустить "хоть десяток" независимых обработчиков ожидания. Внимание: это грубейшее и очень опасное заблуждение!
Архитектура платформы «1С:Предприятие 7.7» накладывает жесткое ограничение: в рамках одного пользовательского сеанса может быть активен только один глобальный обработчик ожидания. Каждое новое выполнение функции ОбработкаОжидания(ИмяПроцедуры, Интервал) полностью перезаписывает и отменяет предыдущий таймер. Если в вашей конфигурации уже работает какая-то подсистема на таймере (например, встроенный "Блокнот" или автопроверка почты), запуск вашего отчета через новый индивидуальный вызов ОбработкаОжидания гарантированно нарушит работу существующего процесса.
Как же решить эту проблему штатными средствами? Нам необходимо применить паттерн "Диспетчер задач". Вместо запуска нескольких независимых таймеров мы создаем одну единую процедуру-диспетчер в Глобальном модуле и назначаем ее единственным глобальным обработчиком ожидания при старте системы. Внутри этой процедуры мы последовательно вызываем все необходимые функции, контролируя время их выполнения и счетчики.
Разберем по шагам, как настроить такую схему в Глобальном модуле конфигурации:
Переменная глОтчетУжеВыполненСегодня Экспорт;
// В Глобальном модуле объявляем процедуру-диспетчер
Процедура глДиспетчерТаймеров() Экспорт
// 1. Вызываем штатный блокнот (периодичность, например, каждые 30 секунд)
Попытка
глПроверитьБлокнот();
Исключение
// Защищаем таймер от падения при ошибках в блокноте
КонецПопытки;
// 2. Проверяем условия для запуска нашего регламентного отчета
Если ИмяПользователя() = "Петя" Тогда
// Проверяем, наступило ли целевое время (например, 14:00)
// Чтобы отчет не запускался по кругу в течение всей минуты, контролируем факт запуска
Если (ТекущееВремя() >= "14:00:00") И (ТекущееВремя() <= "14:01:00") Тогда
Если глОтчетУжеВыполненСегодня = 0 Тогда
ОткрытьФорму("Отчет", "Автозапуск", КаталогИБ() + "ExtForms\MyReport.ert");
глОтчетУжеВыполненСегодня = 1; // Флаг предотвращения повторного запуска
КонецЕсли;
Иначе
// Сбрасываем флаг, когда время ушло вперед, для следующего дня
Если ТекущееВремя() > "14:01:00" Тогда
глОтчетУжеВыполненСегодня = 0;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Процедура ПриНачалеРаботыСистемы()
// Инициализируем глобальные переменные
глОтчетУжеВыполненСегодня = 0;
// Запускаем единый таймер с интервалом в 30 секунд
ОбработкаОжидания("глДиспетчерТаймеров", 30);
КонецПроцедуры
Этот способ позволяет бесконфликтно сосуществовать любым периодическим процессам в вашей базе данных 1С 7.7 без использования сторонних библиотек.
Если вам все же жизненно необходимы настоящие, независимые и многопоточные таймеры, штатный механизм не справится. В этом случае на помощь приходит популярная внешняя компонента FormEx. Она значительно расширяет возможности встроенного языка 1С 7.7 и предоставляет специальный объект Сервис, у которого есть собственный, усовершенствованный метод работы с событиями времени.
С использованием FormEx мы можем регистрировать независимые обработчики ожидания, привязывать их к конкретным экранным формам и гибко управлять их жизненным циклом. Это полностью избавляет разработчика от необходимости писать сложные диспетчеры в Глобальном модуле и перегружать конфигурацию лишним кодом.
Идея запускать тяжелые отчёты прямо в сеансе "живого" пользователя, работающего за компьютером, имеет огромный недостаток. Представьте ситуацию: Петя в 14:00 увлеченно вводит важную многострочную накладную. Внезапно фокус ввода перехватывается, экран "замораживается", появляется песочные часы, и система начинает формировать тяжелый отчет по продажам за полугодие. Это не только раздражает пользователя, но и может привести к потере не сохраненных данных или ошибкам ввода.
Гораздо более профессиональным и надежным решением является запуск отчета в фоновом режиме под специально созданной учетной записью робота (например, Robot_Reports) с помощью планировщика задач Windows (Task Scheduler).
При таком сценарии планировщик операционной системы в назначенное время запускает процесс 1С, передавая ему необходимые инструкции. Робот незаметно для пользователей формирует отчет, сохраняет готовый результат (в формате Excel, PDF или MXL) в сетевую папку или отправляет его инициатору по электронной почте, после чего корректно закрывает свой сеанс.
Давайте проанализируем три основных метода реализации внешнего запуска и передачи параметров.
Это самый элегантный и гибкий способ. Вместо создания громоздких текстовых файлов-настроек, мы пишем небольшой сценарий на языке VBScript. Планировщик Windows запускает этот сценарий, который программно создает COM-объект 1С 7.7, подключается к базе данных, открывает нужный отчет и передает в его форму любые параметры напрямую.
Посмотрим на пример VBS-скрипта (файл run_report.vbs):
' Создаем объект подключения к 1С 7.7
Set v77 = CreateObject("V77.Application")
' Инициализируем подключение к базе данных
' Параметры: каталог базы, имя пользователя, пароль, монопольный режим
BaseFolder = "C:\1C_Bases\OurTrade\"
User = "Robot_Reports"
Password = "SuperPassword"
ConnectionLine = "/D""" & BaseFolder & """ /N""" & User & """ /P""" & Password & """"
Result = v77.Initialize(v77.RMTrade, ConnectionLine, "NO_SPLASH_SHOW")
If Result Then
' Задаем параметры для передачи в отчет (например, список через запятую)
Params = "Фирма=ООО Рога и Копыта;Период=Месяц"
' Программно открываем внешний отчет и передаем параметры третьим аргументом
' Путь к отчету должен быть абсолютным
v77.OpenForm "Report", Params, BaseFolder & "ExtForms\SalesSchedule.ert"
' Закрываем 1С после выполнения работы отчета
' (В самом отчете при открытии должен отработать СтатусВозврата(0))
v77.EvalExpr "ЗавершитьРаботуСистемы(0)"
Else
WScript.Echo "Не удалось подключиться к базе данных 1С!"
End If
Если вы предпочитаете использовать стандартные файлы сценариев командной строки (.bat), передать сложные параметры напрямую через параметры запуска 1С 7.7 не получится (в отличие от платформы 1С 8.х с ее ключом /C). В этом случае применяется классический метод файлов-флагов.
Перед запуском 1С наш батник или внешняя система записывает текстовый файл настроек (например, params.ini) в рабочий каталог пользователя. При старте системы процедура ПриНачалеРаботыСистемы проверяет наличие этого файла, считывает параметры, запускает отчет, а затем обязательно удаляет файл-флаг, чтобы избежать повторного запуска при обычном интерактивном входе пользователя.
Пример кода обработки файла настроек в 1С 7.7:
Процедура ПриНачалеРаботыСистемы()
КаталогФлага = КаталогПользователя();
ИмяФайлаФлага = КаталогФлага + "params.ini";
Если ФС.СуществуетФайл(ИмяФайлаФлага) = 1 Тогда
// Читаем параметры из файла
Текст = СоздатьОбъект("Текст");
Текст.Открыть(ИмяФайлаФлага);
Если Текст.КоличествоСтрок() > 0 Тогда
ПараметрОтчета = Текст.ПолучитьСтроку(1);
// Открываем отчет и передаем параметр
ОткрытьФорму("Отчет", ПараметрОтчета, КаталогИБ() + "ExtForms\MyReport.ert");
КонецЕсли;
// Удаляем файл-флаг, чтобы не запуститься повторно
ФС.УдалитьФайл(ИмяФайлаФлага);
// Завершаем работу системы робота
ЗавершитьРаботуСистемы(0);
КонецЕсли;
КонецПроцедуры
Еще один оригинальный и простой способ передать параметры из командного файла в 1С 7.7 без создания промежуточных файлов — это использование системных переменных окружения. В батнике перед строкой запуска 1С мы задаем переменную среды с нужным значением:
set REPORT_TARGET_DEPT=ОтделПродаж
"C:\Program Files\1Cv77\bin\1cv7s.exe" enterprise /D"C:\1C_Bases\OurTrade\" /N"Robot_Reports" /P"RobotPassword"
Внутри программного кода 1С 7.7 мы можем легко считать эту переменную, обратившись к Windows Script Host через OLE-объект:
Процедура ПриНачалеРаботыСистемы()
Если ИмяПользователя() = "Robot_Reports" Тогда
Попытка
Shell = СоздатьОбъект("WScript.Shell");
ВыбОтдел = Shell.ExpandEnvironmentStrings("%REPORT_TARGET_DEPT%");
Исключение
ВыбОтдел = "";
КонецПопытки;
Если ПустаяСтрока(ВыбОтдел) = 0 Тогда
// Открываем и выполняем отчет для данного отдела
ОткрытьФорму("Отчет", ВыбОтдел, КаталогИБ() + "ExtForms\DepartmentReport.ert");
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Мы детально изучили все возможные варианты настройки автоматического запуска отчетов в 1С 7.7. Для простых задач внутри сеанса пользователя отлично подойдет доработанный единый "Диспетчер таймеров" на базе штатной ОбработкиОжидания. Для более серьезных задач генерации регламентированной отчетности мы рекомендуем использовать связку планировщика Windows, VBS-скриптов и выделенного пользователя-робота. Это гарантирует бесперебойную работу системы, экономит процессорное время рабочих станций пользователей и автоматизирует рутину на самом высоком профессиональном уровне.