При разработке и сопровождении конфигураций на платформе 1С:Предприятие 7.7 программисты часто сталкиваются с необходимостью повторного использования одного и того же кода в разных документах. Типичный пример — процедура вывода на печать, логика которой идентична для нескольких объектов, но сами документы имеют разные названия или слегка отличающиеся структуры табличных частей. Перенос такого кода в Глобальный модуль (ГМ) позволяет избежать дублирования и упрощает дальнейшее обновление алгоритмов.
В этой статье мы подробно разберем, как превратить локальную процедуру формы в глобальную, научимся передавать контекст документа и работать с реквизитами, имена которых могут отличаться в разных документах.
Главная особенность 1С 7.7 заключается в том, что Глобальный модуль «не знает» о существовании реквизитов формы, текущей строки табличной части или встроенных функций документа (таких как ВыбратьСтроки() или ДатаДок), если они вызываются напрямую. Чтобы код заработал вне модуля формы, нам необходимо передать в процедуру специальный параметр — контекст.
Проанализируем ситуацию: если мы просто скопируем код из модуля формы в ГМ, система выдаст ошибку «Переменная не определена». Для решения этой проблемы мы будем использовать переменную, содержащую ссылку на сам объект документа.
Рассмотрим, как должна измениться структура процедуры. Во-первых, нам нужно добавить ключевое слово Экспорт, чтобы процедура стала доступна из других модулей. Во-вторых, мы добавим входящий параметр (назовем его Конт).
Разберем на примере исходного кода из вопроса пользователя. Первоначальный вид процедуры в модуле формы:
Процедура Направления()
// Локальный код...
ВыбратьСтроки();
Пока ПолучитьСтроку()=1 Цикл
// Работа с реквизитами
КонецЦикла;
КонецПроцедуры
После переноса в Глобальный модуль заголовок и обращения к методам документа должны выглядеть так:
Процедура глНаправления(Конт) Экспорт
// Теперь обращаемся ко всем методам через Конт
Конт.ВыбратьСтроки();
Пока Конт.ПолучитьСтроку() = 1 Цикл
// Работа с реквизитами через Конт
КонецЦикла;
КонецПроцедуры
В исходной задаче упоминалось, что названия колонок или реквизитов могут отличаться. Если в одном документе колонка называется ФакторВредности, а в другом по-другому, прямое обращение Конт.ФакторВредности вызовет ошибку в тех документах, где такого имени нет. Чтобы сделать процедуру по-настоящему универсальной, проанализируем использование метода ПолучитьАтрибут().
Вместо жесткого написания имени реквизита, мы можем определять вид документа и выбирать нужное имя:
ВидДока = Конт.Вид();
Если ВидДока = "ПриемНаРаботу" Тогда
ИмяКолонки = "ФакторВредности";
ИначеЕсли ВидДока = "Медосмотр" Тогда
ИмяКолонки = "ВредныйФактор";
КонецЕсли;
// Получаем значение динамически
ТекЗначение = Конт.ПолучитьАтрибут(ИмяКолонки);
Когда процедура находится в модуле формы, команда Таб.ИсходнаяТаблица("Направления") ищет таблицу, которая «нарисована» в самом документе (на закладке «Таблица»). При переносе кода в Глобальный модуль система не сможет найти этот макет автоматически.
Существует два основных способа решения этой проблемы:
ИсходнаяТаблица будет искать макет среди глобальных шаблонов конфигурации..mxl. В коде используйте Таб.Открыть(ПутьКФайлу).Рассмотрим вариант с Общими таблицами, так как он наиболее удобен для поддержки. В коде ГМ это будет выглядеть стандартно, но важно убедиться, что имя таблицы уникально во всей конфигурации.
Теперь выясним, как правильно вызвать нашу новую глобальную процедуру из документа. В модуле формы документа (в кнопке или процедуре печати) достаточно написать одну строку, передав зарезервированное слово Контекст:
Процедура Печать()
глНаправления(Контекст);
КонецПроцедуры
Слово Контекст в модуле формы 7.7 является ссылкой на текущий объект документа со всеми его данными и реквизитами формы.
Ниже приведен фрагмент переработанного кода с учетом всех рекомендаций. Мы добавили создание объектов справочников, привязку к дате документа через контекст и универсальный перебор строк.
Процедура глНаправления(Конт) Экспорт
Таб = СоздатьОбъект("Таблица");
// Таблица должна быть перенесена в "Общие таблицы"
Таб.ИсходнаяТаблица("Направления");
ТЗ = СоздатьОбъект("ТаблицаЗначений");
ТЗ.НоваяКолонка("Услуга");
ТЗ.НоваяКолонка("Отдел");
// Работаем с табличной частью документа
Конт.ВыбратьСтроки();
Пока Конт.ПолучитьСтроку() = 1 Цикл
// Пример получения реквизита (динамически или напрямую через Конт)
ТекФактор = Конт.ФакторВредности;
Если (ТекФактор.Код = "10893") Тогда
Продолжить;
КонецЕсли;
СпцВр = СоздатьОбъект("Справочник.СпискиСпецВрачей");
СпцВр.ИспользоватьВладельца(ТекФактор);
СпцВр.ВыбратьЭлементы();
Пока СпцВр.ПолучитьЭлемент() = 1 Цикл
ТЗ.НоваяСтрока();
ТЗ.Услуга = СпцВр.Должность.Наименование;
// Используем дату документа из контекста
Должн = СоздатьОбъект("Справочник.Должности");
Должн.ИспользоватьДату(Конт.ДатаДок);
Если Должн.НайтиЭлемент(СпцВр.Должность) = 1 Тогда
// Логика заполнения
КонецЕсли;
КонецЦикла;
КонецЦикла;
// В конце выводим таблицу
Таб.ТолькоПросмотр(1);
Таб.Показать("Печать направлений");
КонецПроцедуры
Проанализируем несколько критических моментов, которые часто упускают при переносе кода:
Перем, не будут доступны в Глобальном модуле. Если они нужны для печати, их также придется передавать как параметры или извлекать из контекста формы.[Цена * Количество], убедитесь, что все переменные внутри выражения доступны. При печати из ГМ лучше явно заполнять параметры секции: Таб.ВывестиСекцию("Строка"), предварительно заполнив переменные, на которые ссылается макет.Конт.ПолучитьАтрибут() работает медленнее, чем прямое обращение. Если в табличной части тысячи строк, рекомендуется один раз в начале процедуры определить вид документа и использовать условия Если...Тогда вне цикла.Таким образом, мы рассмотрели процесс централизации кода в 1С 7.7. Это эффективный способ управления конфигурацией, который позволяет избежать ошибок при внесении изменений сразу в несколько похожих документов. Главное — помнить о передаче контекста и правильном расположении макетов печатных форм.