Общий модуль 1С 8.3: Клиент, Сервер, Вызов сервера, ПовтИсп

Дата: 21.09.2026 10:04:16
Общие модули
Программирование 1С
Клиент-сервер
Доработка 1С
Комментарий:
0
Платформа:
8.3
Конфигурация:
Любая
Формы:
Любые

Общий модуль 1С — модуль без собственных данных с экспортными процедурами и функциями для форм, объектов, обработок и регламентных заданий. Где выполняется его код и кто может его вызвать, решают флажки в свойствах. Ошибка во флажках оборачивается сообщением «Переменная не определена» на клиенте или лишними серверными вызовами, от которых тормозит форма.

Ниже — шесть модулей для проверки ИНН контрагента: формат проверяется на клиенте, дубли ищутся одним вызовом сервера, настройка читается через кэш. Тот же код работает в форме, модуле объекта и расширении. Константу КонтролироватьДублиИНН (Булево) добавьте сами, справочник Контрагенты с реквизитом ИНН есть в большинстве типовых. Платформа — 8.3.6 и новее.

Общий модуль 1С: флажки и их сочетания

Модуль создают в конфигураторе: «Общие» → «Общие модули» → «Добавить». Дальше в палитре свойств выбирают контексты:

  • Сервер — запросы, запись объектов, регистры.
  • Клиент (управляемое приложение) — тонкий, веб- и толстый клиент в управляемом режиме: сообщения, диалоги, формы.
  • Клиент (обычное приложение) — толстый клиент на обычных формах. В БСП его ставят и серверным модулям: в обычном приложении модули объектов компилируются и на клиенте.
  • Внешнее соединение — доступ через COM-соединение из другой базы или программы.
  • Вызов сервера — экспортные методы серверного модуля доступны клиенту. Без флажка клиент модуль не видит.
  • Привилегированный — код выполняется без проверки прав и RLS.
  • Глобальный — методы вызываются без имени модуля. Клиентские глобальные модули компилируются при запуске и замедляют старт.
  • Повторное использование возвращаемых значений — кэш результатов функций на время вызова или сеанса.
ЗадачаФлажкиСуффикс имени
Запросы, запись, расчётыСервер, Внешнее соединение, Клиент (обычное приложение)нет или Сервер
Вызов с клиента без контекста формыСервер, Вызов сервераВызовСервера
Сообщения, диалоги, открытие формКлиент (управляемое приложение)Клиент
Вычисления без обращения к базеоба «Клиента», Сервер, Внешнее соединениеКлиентСервер
Кэш на серверекак у серверного + повторное использованиеПовтИсп
Кэш на клиенте, меньше серверных вызововКлиент (управляемое приложение) + «На время сеанса»КлиентПовтИсп
Код, которому нужны полные праваСервер, ПривилегированныйПолныеПрава
Обработчики ожидания, методы без имени модуляКлиент (управляемое приложение), ГлобальныйГлобальный

Суффиксы — соглашение стандартов 1С, платформа их не проверяет, зато по вызову сразу видно, где он выполнится. Серверные модули БСП называются без суффикса (ОбщегоНазначения), а в КА 2.5 больше сотни модулей с суффиксом Сервер, например АссортиментСервер. Привилегированных модулей в КА 2.5 нет совсем: привилегированный режим включают точечно в коде.

Клиент-серверный общий модуль

Сюда кладут код без обращения к базе: проверки формата, расчёты, работу со строками. На клиенте он выполняется без вызова сервера, на сервере — напрямую.

// Общий модуль ПроверкаКонтрагентовКлиентСервер.
// Флажки: Клиент (управляемое приложение), Клиент (обычное приложение),
// Сервер, Внешнее соединение.

// Проверяет длину, состав и контрольные цифры ИНН.
//
// Параметры:
//  ИНН - Строка - ИНН организации (10 цифр) или физического лица (12 цифр).
//
// Возвращаемое значение:
//  Строка - текст ошибки; пустая строка, если ИНН корректен.
//
Функция ОшибкаИНН(ИНН) Экспорт

    СтрокаИНН = СокрЛП(ИНН);
    Длина = СтрДлина(СтрокаИНН);
    Если Длина <> 10 И Длина <> 12 Тогда
        Возврат НСтр("ru = 'ИНН должен состоять из 10 или 12 цифр'");
    КонецЕсли;

    Цифры = Новый Массив;
    Для Позиция = 1 По Длина Цикл
        ТекущийСимвол = Сред(СтрокаИНН, Позиция, 1);
        Если СтрНайти("0123456789", ТекущийСимвол) = 0 Тогда
            Возврат НСтр("ru = 'ИНН может содержать только цифры'");
        КонецЕсли;
        Цифры.Добавить(Число(ТекущийСимвол));
    КонецЦикла;

    Если Длина = 10 Тогда
        Верно = (КонтрольнаяЦифра(Цифры, "2,4,10,3,5,9,4,6,8") = Цифры[9]);
    Иначе
        Верно = (КонтрольнаяЦифра(Цифры, "7,2,4,10,3,5,9,4,6,8") = Цифры[10])
            И (КонтрольнаяЦифра(Цифры, "3,7,2,4,10,3,5,9,4,6,8") = Цифры[11]);
    КонецЕсли;

    Возврат ?(Верно, "", НСтр("ru = 'Неверные контрольные цифры ИНН'"));

КонецФункции

// Без Экспорт: функция видна только внутри этого модуля.
Функция КонтрольнаяЦифра(Цифры, СтрокаВесов)

    Веса = СтрРазделить(СтрокаВесов, ",");
    Сумма = 0;
    Для Индекс = 0 По Веса.ВГраница() Цикл
        Сумма = Сумма + Цифры[Индекс] * Число(Веса[Индекс]);
    КонецЦикла;

    Возврат (Сумма % 11) % 10;

КонецФункции
  • ОшибкаИНН с Экспорт вызывают форма, модуль объекта и другие модули.
  • КонтрольнаяЦифра без Экспорт видна только внутри модуля, вызов снаружи даст «Метод объекта не обнаружен».
  • Текст ошибки вместо Булево годится и для сообщения на клиенте, и для отказа в записи на сервере.
  • Здесь разрешены только методы, доступные в обоих контекстах: Новый Запрос сломает компиляцию на клиенте. Серверную ветку оборачивают в #Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда … #КонецЕсли.

Общий серверный модуль и флажок «Вызов сервера»

Серверному модулю флажок «Вызов сервера» не нужен: его и так видят модули объектов, серверные процедуры форм и регламентные задания.

// Общий модуль ПроверкаКонтрагентов.
// Флажки: Сервер, Внешнее соединение, Клиент (обычное приложение).

// Ищет других контрагентов с тем же ИНН.
//
// Параметры:
//  ИНН - Строка - проверяемый ИНН.
//  ТекущийКонтрагент - СправочникСсылка.Контрагенты - исключается из поиска.
//
// Возвращаемое значение:
//  Массив из Структура - свойства Ссылка и Наименование.
//
Функция ДублиПоИНН(ИНН, ТекущийКонтрагент) Экспорт

    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    |    Контрагенты.Ссылка КАК Ссылка,
    |    Контрагенты.Наименование КАК Наименование
    |ИЗ
    |    Справочник.Контрагенты КАК Контрагенты
    |ГДЕ
    |    Контрагенты.ИНН = &ИНН
    |    И Контрагенты.Ссылка <> &ТекущийКонтрагент
    |    И НЕ Контрагенты.ПометкаУдаления";
    Запрос.УстановитьПараметр("ИНН", СокрЛП(ИНН));
    Запрос.УстановитьПараметр("ТекущийКонтрагент", ТекущийКонтрагент);

    Дубли = Новый Массив;
    Выборка = Запрос.Выполнить().Выбрать();
    Пока Выборка.Следующий() Цикл
        Дубли.Добавить(Новый Структура("Ссылка, Наименование",
            Выборка.Ссылка, Выборка.Наименование));
    КонецЦикла;

    Возврат Дубли;

КонецФункции
  • Результат — массив структур из ссылок и строк, его можно вернуть на клиент. СправочникОбъект или ТаблицаЗначений на тонкий клиент не передаются.
  • Наименование возвращается вместе со ссылкой, потому что на клиенте Ссылка.Наименование не прочитать.

Для клиента заводят тонкий модуль-шлюз с флажками «Сервер» и «Вызов сервера»:

// Общий модуль ПроверкаКонтрагентовВызовСервера.
// Флажки: Сервер, Вызов сервера.

// Шлюз к ПроверкаКонтрагентов.ДублиПоИНН для клиентского кода.
Функция ДублиПоИНН(Знач ИНН, Знач ТекущийКонтрагент) Экспорт

    // Параметры пришли с клиента: проверяем типы, прежде чем передать дальше.
    Если ТипЗнч(ИНН) <> Тип("Строка") Тогда
        ВызватьИсключение НСтр("ru = 'Параметр ИНН должен быть строкой'");
    КонецЕсли;
    Если ТипЗнч(ТекущийКонтрагент) <> Тип("СправочникСсылка.Контрагенты") Тогда
        ТекущийКонтрагент = Справочники.Контрагенты.ПустаяСсылка();
    КонецЕсли;

    Возврат ПроверкаКонтрагентов.ДублиПоИНН(ИНН, ТекущийКонтрагент);

КонецФункции

// Шлюз для клиентского кэша настроек.
Функция НастройкиПроверки() Экспорт

    Возврат ПроверкаКонтрагентовПовтИсп.НастройкиПроверки();

КонецФункции
  • Функцию шлюза может вызвать любой клиентский код, включая внешнюю обработку, поэтому шлюз проверяет типы параметров. Логика остаётся в серверном модуле.
  • Знач в параметрах: без него параметры после вызова возвращаются на клиент, а это лишний трафик.

Повторное использование возвращаемых значений

Режим задаётся для всего модуля. Платформа запоминает результат функции для каждого набора параметров и при повторном вызове не выполняет её тело. «На время вызова» — кэш живёт до конца текущего вызова сервера. «На время сеанса» — дольше, но в общем случае значение удаляется через 20 минут после вычисления или через 6 минут после последнего использования, а также при нехватке памяти и перезапуске рабочего процесса.

// Общий модуль ПроверкаКонтрагентовПовтИсп.
// Флажки: Сервер, Внешнее соединение, Клиент (обычное приложение).
// Повторное использование возвращаемых значений: На время вызова.

// Возвращаемое значение:
//  ФиксированнаяСтруктура - свойство КонтролироватьДубли (Булево).
//
Функция НастройкиПроверки() Экспорт

    // Настройка нужна всем, а права на константу есть не у всех.
    УстановитьПривилегированныйРежим(Истина);
    КонтролироватьДубли = Константы.КонтролироватьДублиИНН.Получить();
    УстановитьПривилегированныйРежим(Ложь);

    Возврат Новый ФиксированнаяСтруктура("КонтролироватьДубли", КонтролироватьДубли);

КонецФункции
  • При загрузке тысячи контрагентов одним вызовом сервера константа прочитается один раз, а следующий вызов получит свежее значение.
  • Привилегированный режим включён только на чтение константы — это безопаснее, чем привилегированный модуль целиком.
  • ФиксированнаяСтруктура не даёт вызывающему коду изменить закэшированное значение.
// Общий модуль ПроверкаКонтрагентовКлиентПовтИсп.
// Флажки: Клиент (управляемое приложение).
// Повторное использование возвращаемых значений: На время сеанса.

Функция НастройкиПроверки() Экспорт

    // Первый вызов идёт на сервер, следующие возвращают значение из кэша клиента.
    Возврат ПроверкаКонтрагентовВызовСервера.НастройкиПроверки();

КонецФункции

Первый вызов идёт на сервер, следующие берут ответ из кэша клиента, и изменение поля ИНН не стоит лишнего обращения к серверу.

Ловушки повторного использования:

  • Устаревшие данные. Администратор включил константу, а у пользователей контроль не работает: клиентский кэш держит старое значение. ОбновитьПовторноИспользуемыеЗначения() сбрасывает кэш только своего сеанса, поэтому на сеанс кэшируйте то, что не меняется днём.
  • Изменяемый результат. Кэш отдаёт тот же экземпляр: добавили элемент в возвращённый Массив — следующий вызов получит изменённый массив. Возвращайте фиксированные коллекции.
  • Скрытые параметры. Всё, от чего зависит результат (организация, дата, пользователь), передавайте параметрами — примитивными значениями или ссылками.
  • Побочные эффекты. При попадании в кэш тело не выполняется: запись в журнал внутри функции сработает один раз.
  • Серверный кэш не экономит вызовы. Модули вида БухгалтерскийУчетВызовСервераПовтИсп экономят вычисление, но клиент всё равно обращается к серверу.

Клиентский модуль и вызов из формы

Клиентский модуль собирает проверку в сценарий: формат — локально, дубли — одним вызовом сервера, ошибка — у поля.

// Общий модуль ПроверкаКонтрагентовКлиент.
// Флажки: Клиент (управляемое приложение).

// Проверяет ИНН в форме контрагента и выводит ошибку у поля.
//
// Возвращаемое значение:
//  Булево - Истина, если ошибок нет.
//
Функция ПроверитьИНН(ИНН, ТекущийКонтрагент) Экспорт

    // Формат проверяем на клиенте, без обращения к серверу.
    ТекстОшибки = ПроверкаКонтрагентовКлиентСервер.ОшибкаИНН(ИНН);
    Если ЗначениеЗаполнено(ТекстОшибки) Тогда
        СообщитьОбОшибке(ТекстОшибки);
        Возврат Ложь;
    КонецЕсли;

    Если Не ПроверкаКонтрагентовКлиентПовтИсп.НастройкиПроверки().КонтролироватьДубли Тогда
        Возврат Истина;
    КонецЕсли;

    // Один внеконтекстный вызов сервера.
    Дубли = ПроверкаКонтрагентовВызовСервера.ДублиПоИНН(ИНН, ТекущийКонтрагент);
    Если Дубли.Количество() > 0 Тогда
        СообщитьОбОшибке(СтрШаблон(НСтр("ru = 'ИНН уже указан у контрагента «%1»'"),
            Дубли[0].Наименование));
        Возврат Ложь;
    КонецЕсли;

    Возврат Истина;

КонецФункции

Процедура СообщитьОбОшибке(ТекстОшибки)

    Сообщение = Новый СообщениеПользователю;
    Сообщение.Текст = ТекстОшибки;
    Сообщение.Поле = "Объект.ИНН";
    Сообщение.Сообщить();

КонецПроцедуры
  • Сервер вызывается только для корректного ИНН и только при включённом контроле.
  • Путь «Объект.ИНН» в свойстве Поле привязывает сообщение к полю основного реквизита формы.
// Модуль формы элемента справочника Контрагенты.
// В форме добавлена команда ПоказатьДубли.

&НаКлиенте
Процедура ИННПриИзменении(Элемент)

    Если ЗначениеЗаполнено(Объект.ИНН) Тогда
        ПроверкаКонтрагентовКлиент.ПроверитьИНН(Объект.ИНН, Объект.Ссылка);
    КонецЕсли;

КонецПроцедуры

&НаКлиенте
Процедура ПоказатьДубли(Команда)

    Если Не ЗначениеЗаполнено(Объект.ИНН) Тогда
        Возврат;
    КонецЕсли;

    // Так нельзя: модуль без флажка «Вызов сервера» на клиенте не виден.
    // ЧислоДублей = ПроверкаКонтрагентов.ДублиПоИНН(Объект.ИНН, Объект.Ссылка).Количество();

    ЧислоДублей = ЧислоДублейНаСервере(Объект.ИНН, Объект.Ссылка);
    ПоказатьПредупреждение(, СтрШаблон(НСтр("ru = 'Контрагентов с таким ИНН: %1'"), ЧислоДублей));

КонецПроцедуры

&НаСервереБезКонтекста
Функция ЧислоДублейНаСервере(Знач ИНН, Знач ТекущийКонтрагент)

    // На сервере серверный общий модуль доступен напрямую.
    Возврат ПроверкаКонтрагентов.ДублиПоИНН(ИНН, ТекущийКонтрагент).Количество();

КонецФункции
  • ИННПриИзменении вызывает только клиентский модуль и не зависит от устройства проверки.
  • Команда ПоказатьДубли идёт к серверному модулю через &НаСервереБезКонтекста: на сервер уходят два параметра. &НаСервере гонял бы туда и обратно все данные формы — он нужен, когда сервер меняет реквизиты формы.
  • Закомментированная строка — частая ошибка: модуль без «Вызов сервера» на клиенте не виден.

Итог: при ошибке формата форма не обращается к серверу, при корректном ИНН делает один вызов и ещё один за сеанс — за настройкой.

Тот же код на сервере: модуль объекта

// Модуль объекта справочника Контрагенты.

#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда

Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)

    Если Не ЗначениеЗаполнено(ИНН) Тогда
        Возврат;
    КонецЕсли;

    // Та же функция, что проверяла поле в форме.
    ТекстОшибки = ПроверкаКонтрагентовКлиентСервер.ОшибкаИНН(ИНН);

    Если Не ЗначениеЗаполнено(ТекстОшибки)
        И ПроверкаКонтрагентовПовтИсп.НастройкиПроверки().КонтролироватьДубли
        И ПроверкаКонтрагентов.ДублиПоИНН(ИНН, Ссылка).Количество() > 0 Тогда
        ТекстОшибки = НСтр("ru = 'Контрагент с таким ИНН уже есть'");
    КонецЕсли;

    Если ЗначениеЗаполнено(ТекстОшибки) Тогда
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = ТекстОшибки;
        Сообщение.Поле = "ИНН";
        Сообщение.УстановитьДанные(ЭтотОбъект);
        Сообщение.Сообщить();
        Отказ = Истина;
    КонецЕсли;

КонецПроцедуры

#КонецЕсли
  • ОшибкаИНН — та же функция, что в форме: правило описано один раз.
  • Логические выражения вычисляются сокращённо, поэтому запрос к базе стоит последним условием.
  • УстановитьДанные(ЭтотОбъект) связывает сообщение с объектом, и форма подсветит поле ИНН.
  • При программной записи через Записать() обработчик не срабатывает — вызывайте ПроверитьЗаполнение() явно.

Общий модуль в расширении

Свой модуль в расширении создают так же, с теми же флажками, а имя начинают с префикса расширения: Расш1_ПроверкаКонтрагентов. Код основной конфигурации модули расширения не видит, их вызывают объекты самого расширения.

Чтобы изменить существующий модуль без снятия с поддержки, его заимствуют и перехватывают метод. Пример: у ИНН «0000000000» контрольные цифры сходятся, а такой ИНН нужно отсекать.

// Расширение с префиксом Расш1_.
// Общий модуль ПроверкаКонтрагентовКлиентСервер заимствован из конфигурации.

&Вместо("ОшибкаИНН")
Функция Расш1_ОшибкаИНН(ИНН)

    // Выполняем исходную функцию и получаем её результат.
    ТекстОшибки = ПродолжитьВызов(ИНН);

    // У «0000000000» контрольные цифры сходятся, но такой ИНН не нужен.
    Если ПустаяСтрока(ТекстОшибки) И ПустаяСтрока(СтрЗаменить(СокрЛП(ИНН), "0", "")) Тогда
        ТекстОшибки = НСтр("ru = 'ИНН не может состоять из одних нулей'");
    КонецЕсли;

    Возврат ТекстОшибки;

КонецФункции
  • ПродолжитьВызов выполняет исходную функцию и возвращает её результат.
  • Перехват работает везде, где компилируется модуль: в форме и в модуле объекта.
  • Если после обновления у метода изменятся параметры или имя, расширение придётся поправить.
  • Пока у расширения включён «Безопасный режим», на привилегированный режим в его коде не рассчитывайте.

Типичные ошибки

  • «Переменная не определена (ПроверкаКонтрагентов)» — модуль недоступен в этом контексте: клиент обращается к серверному модулю без флажка «Вызов сервера» или обычное приложение — к модулю без «Клиент (обычное приложение)».
  • «Процедура или функция с указанным именем не определена (ОшибкаИНН)» — метод неглобального модуля вызван без имени модуля. Та же ошибка, когда серверная процедура формы вызывает клиентскую.
  • «Метод объекта не обнаружен (КонтрольнаяЦифра)» — модуль виден, но метод без Экспорт или с опечаткой.
  • «Тип не определен (Запрос)», «Переменная не определена (Справочники)» — серверный код попал в клиентский или клиент-серверный модуль.
  • «Поле объекта не обнаружено (Наименование)» — на клиенте реквизит читают через точку от ссылки. Получите его на сервере.
  • Модуль не виден, хотя флажки стоят — не обновлена конфигурация базы данных или сеанс открыт до обновления.
  • Форма тормозит при вводе — в ПриИзменении стоит вызов ВызовСервера. Проверки переносите в КлиентСервер, неизменные данные — в КлиентПовтИсп.

Частые вопросы

Как создать общий модуль в 1С 8.3?

В конфигураторе откройте ветку «Общие» → «Общие модули», нажмите «Добавить», задайте имя с суффиксом контекста и отметьте флажки в палитре свойств. Методы для вызова из других модулей помечайте Экспорт, затем обновите конфигурацию базы данных (F7).

Можно ли объявить переменную в общем модуле?

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

Можно ли вызвать общий модуль из внешней обработки?

Да, по тем же правилам: из модуля объекта обработки доступны серверные модули, из клиентского кода её формы — клиентские и модули с флажком «Вызов сервера». Свой общий модуль внутри внешней обработки создать нельзя.

Когда проще заказать

Если код скопирован по десятку форм, а формы делают лишние серверные вызовы, структуру модулей быстрее перепроектировать с опытным программистом — посмотрите услуги по доработке 1С. Опишите задачу в форме размещения задания, и исполнители предложат решение через расширение, без снятия конфигурации с поддержки.

По теме

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.


1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.