Как реализовать автоматическое обновление таблицы значений в 1С 7.7 при изменении данных другими пользователями?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

В процессе разработки на платформе 1С 7.7 программисты часто сталкиваются с ограничением: интерфейс не обновляется автоматически при изменении данных в базе другими пользователями. Рассмотрим классическую ситуацию. У нас есть открытая форма (отчет или обработка), на которой отображается таблица значений (ТЗ) со списком документов, например, РеализацияТМЦ. В одном из столбцов выводится «Номер бланка». Если другой пользователь в этот момент откроет документ и заполнит номер бланка, в нашей открытой форме данные останутся старыми до тех пор, пока мы не нажмем кнопку «Обновить» или не переоткроем форму.

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

Метод 1. Использование вспомогательного справочника («Очередь обновлений»)

Проанализируем самый простой и надежный метод, который не требует использования сторонних библиотек и глубокого знания SQL. Его суть заключается в создании механизма регистрации изменений.

Во-первых, создадим в конфигурации служебный справочник, назовем его ОчередьОбновлений. В нем нам достаточно одного реквизита — Объект (тип «Документ» или «Строка» для универсальности).

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


Процедура ПриЗаписи()
    СпрОчередь = СоздатьОбъект("Справочник.ОчередьОбновлений");
    СпрОчередь.Новый();
    СпрОчередь.Объект = ТекущийДокумент();
    СпрОчередь.Записать();
КонецПроцедуры

В-третьих, в форме нашей обработки нам нужно настроить опрос этого справочника. Поскольку в 1С 7.7 ОбработкаОжидания штатно работает только в глобальном модуле, мы можем вызвать ее оттуда, чтобы она раз в 10–20 секунд проверяла наличие новых записей в ОчередьОбновлений.

Рассмотрим алгоритм проверки:

  1. Программа обращается к справочнику ОчередьОбновлений.
  2. Если найдены новые записи, мы перебираем их и ищем соответствующие строки в нашей таблице значений ТЗ по ссылке на документ.
  3. Обновляем только нужные ячейки (поле НомерБланка).
  4. Удаляем обработанные записи из справочника, чтобы не обрабатывать их повторно.

Метод 2. Использование внешней компоненты FormEx (Таймеры и Внешние события)

Выясним, как сделать обновление более элегантным с помощью популярной компоненты FormEx. Штатная ОбработкаОжидания имеет существенный минус — она одна на всю систему. Если какая-то другая процедура тоже захочет использовать ожидание, произойдет конфликт.

С помощью FormEx мы можем реализовать локальный таймер непосредственно в форме обработки. Проанализируем, как это работает. При срабатывании таймера компонента генерирует ВнешнееСобытие, которое мы перехватываем в одноименной процедуре модуля формы.

Посмотрим на пример кода для инициализации таймера в процедуре ПриОткрытии:


Процедура ПриОткрытии()
    // Загружаем компоненту, если она еще не загружена
    ЗагрузитьВнешнююКомпоненту("FormEx.dll");
    Сервис = СоздатьОбъект("Сервис");
    // Устанавливаем таймер на 5000 миллисекунд (5 секунд)
    Сервис.УстановитьТаймер(5000);
КонецПроцедуры

Теперь опишем реакцию на срабатывание таймера:


Процедура ПриВнешнемСобытии(Источник, Событие, Данные)
    Если Событие = "Timer" Тогда
        // Здесь вызываем процедуру обновления данных в ТЗ
        ОбновитьДанныеВТаблице();
    КонецЕсли;
КонецПроцедуры

Этот метод хорош тем, что он не блокирует работу пользователя и позволяет форме «просыпаться» самостоятельно. При этом внутри ОбновитьДанныеВТаблице лучше не перечитывать всю базу, а использовать быстрый запрос или проверку флага изменений.

Метод 3. Прямые SQL-запросы и триггеры (для SQL-версий базы)

Если ваша база работает на MS SQL Server, мы можем задействовать всю мощь реляционных баз данных. Рассмотрим ситуацию, когда документов тысячи, и обычный перебор будет слишком медленным.

Мы можем установить SQL-триггер на таблицу документа РеализацияТМЦ. Триггер будет срабатывать при любой операции UPDATE и записывать ID измененного документа в отдельную техническую таблицу в базе данных.

Для считывания этих данных в 1С 7.7 идеально подойдет компонента 1С++. Разберем по шагам, как это реализовать:

  1. Создаем SQL-таблицу _QueueUpdate с полями DocID и ChangeTime.
  2. Настраиваем триггер на таблицу документа (например, _1SJOURN или таблицу конкретного документа).
  3. В 1С через объект ODBCRecordset выполняем прямой запрос к нашей таблице _QueueUpdate.

Посмотрим на пример прямого запроса:


ТекстЗапроса = "
|SELECT DocID FROM _QueueUpdate WHERE Processed = 0
|";
Записи = СоздатьОбъект("ODBCRecordset");
ТабРезультат = Записи.ВыполнитьИнструкцию(ТекстЗапроса);

Прямые запросы отрабатывают в десятки раз быстрее штатных методов 1С. После получения списка ID мы быстро находим строки в нашей ТЗ и обновляем только их. Это максимально производительный метод, который практически не нагружает сервер.

Метод 4. Механизм регистрации изменений 1SUPDTS (УРБД)

Интересный и нестандартный способ — использование таблицы 1Supdts. Это системная таблица, которая используется механизмом распределенных баз данных (УРБД) для отслеживания измененных объектов.

Важный нюанс: система начинает записывать данные в 1Supdts только в том случае, если в базе создан хотя бы один периферийный узел. Вам не обязательно реально выполнять обмен данными — достаточно просто завести узел в «Администрировании распределенных ИБ».

Как только узел создан, 1С сама начнет регистрировать все изменения. Программисту остается только периодически считывать записи из 1Supdts, относящиеся к виду РеализацияТМЦ. После того как мы обновили данные в форме, записи из таблицы можно удалять или помечать как прочитанные (хотя с системными таблицами нужно быть крайне осторожными).

Особенности визуального обновления интерфейса

Проанализируем еще одну проблему: даже если вы программно изменили значение в объекте ТЗ, пользователь может не увидеть изменений на экране сразу. В 1С 7.7 визуальное обновление элементов управления иногда «запаздывает».

Чтобы принудительно перерисовать таблицу, можно использовать несколько хитростей:

Резюме по выбору решения

Подведем итоги нашего анализа. Выбор метода зависит от ваших условий: 1. Если нельзя использовать внешние компоненты (DBF-версия): используйте схему со справочником-очередью и глобальной ОбработкойОжидания. Это надежно и просто в реализации.

2. Если разрешены внешние компоненты: используйте FormEx для настройки локального таймера в форме. Это позволит избежать изменения глобального модуля и сделает решение автономным.

3. Для высоконагруженных SQL-систем: лучшим выбором будут SQL-триггеры и прямые запросы через 1С++. Это обеспечит мгновенную реакцию интерфейса на изменения без нагрузки на систему.

Применяя эти подходы, мы создаем динамичный и современный интерфейс даже в такой консервативной платформе, как 1С 7.7, обеспечивая пользователям актуальность данных в реальном времени.

← На главную