Как автоматически заполнить реквизиты в подчиненном справочнике 1С 7.7 на основе предыдущей записи

Программист 1С v7.7 Управленческий учет
← На главную

В процессе разработки на платформе 1С:Предприятие 7.7 часто возникает задача упрощения ввода данных пользователем. Одной из таких задач является автоматическое заполнение полей новой строки в подчиненном справочнике значениями из предыдущей (последней) записи. Рассмотрим ситуацию, когда у нас есть трехуровневая иерархия справочников: Контрагенты -> Договора -> СрокиПоставкиТМЦ. Нам необходимо, чтобы при добавлении новой записи в СрокиПоставкиТМЦ поле Номенклатура заполнялось автоматически значением из последней созданной записи этого же договора.

Использование процедуры ПриРедактированииНовойСтроки

Для реализации этой логики в форме списка справочника наиболее подходящим методом является предопределенная процедура ПриРедактированииНовойСтроки(). Эта процедура вызывается системой в тот момент, когда пользователь нажимает клавишу Ins или выбирает пункт меню "Новый", и в списке появляется новая пустая строка, готовая к заполнению.

Разберем базовый алгоритм, который позволяет найти последнее введенное значение:

  1. Создаем объект типа Справочник нужного вида.
  2. Устанавливаем фильтр по текущему владельцу, чтобы искать данные только в рамках текущего договора.
  3. Перебираем элементы и запоминаем значение нужного реквизита.

Проанализируем пример кода, который решает эту задачу:


Процедура ПриРедактированииНовойСтроки()
    Перем ПоследнееЗначение;
    // Создаем объект справочника для поиска
    Спр = СоздатьОбъект("Справочник.СрокиПоставкиТМЦ");
    
    // Устанавливаем владельца, чтобы выборка шла только по конкретному договору
    // Владелец - это контекстная переменная формы списка подчиненного справочника
    Спр.ИспользоватьВладельца(Владелец);
    
    // Запускаем выборку всех элементов этого владельца
    Спр.ВыбратьЭлементы();
    
    // Проходим циклом до самого конца
    Пока Спр.ПолучитьЭлемент() = 1 Цикл
        ПоследнееЗначение = Спр.Номенклатура;
    КонецЦикла;
    
    // Устанавливаем найденное значение в новую строку
    Номенклатура = ПоследнееЗначение;  
КонецПроцедуры

Оптимизация поиска через обратный порядок

Предложенный выше метод с циклом Пока отлично работает на небольших объемах данных. Однако, если у одного договора могут быть сотни или тысячи записей о сроках поставки, полный перебор элементов может вызвать заметную задержку. Чтобы ускорить работу, мы можем использовать метод ОбратныйПорядок(). Это позволит нам получить последний элемент сразу, не листая весь справочник.

Рассмотрим оптимизированный вариант кода:


Процедура ПриРедактированииНовойСтроки()
    Спр = СоздатьОбъект("Справочник.СрокиПоставкиТМЦ");
    Спр.ИспользоватьВладельца(Владелец);
    
    // Включаем режим выборки в обратном порядке
    Спр.ОбратныйПорядок(1);
    
    // Устанавливаем сортировку по коду (или по другому индексированному реквизиту)
    Спр.ПорядокКодов();
    
    // Начинаем выборку
    Спр.ВыбратьЭлементы();
    
    // Получаем первый элемент из обратной выборки (т.е. самый последний по факту)
    Если Спр.ПолучитьЭлемент() = 1 Тогда
        Номенклатура = Спр.Номенклатура;
    КонецЕсли;
КонецПроцедуры

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

Альтернативный метод: НайтиПоследнийЭлемент

В 1С 7.7 существует системный метод НайтиПоследнийЭлемент(). Он работает максимально быстро, так как обращается к итогам или индексам таблицы. Однако при работе с подчиненными справочниками нужно быть осторожными. Рассмотрим, как применить его правильно:


Спр = СоздатьОбъект("Справочник.СрокиПоставкиТМЦ");
Спр.ИспользоватьВладельца(Владелец);
Если Спр.НайтиПоследнийЭлемент() = 1 Тогда
    Номенклатура = Спр.Номенклатура;
КонецЕсли;

Этот метод работает корректно только в том случае, если для справочника установлена основная сортировка (например, по коду) и она совпадает с логикой "последнего элемента".

Обработка пустых значений при записи

Иногда возникают ситуации, когда автоматическое заполнение может быть лишним. Например, если пользователь очистил поле Количество, логично предположить, что и Номенклатура в этой строке не нужна. Для реализации такой "самоочистки" можно использовать предопределенную процедуру ПриЗаписи() в модуле формы.

Выясним, как это реализовать:


Процедура ПриЗаписи()
    // Если количество не заполнено, принудительно очищаем номенклатуру
    Если Количество = 0 Тогда
        Номенклатура = ПолучитьПустоеЗначение("Справочник.Номенклатура");
    КонецЕсли;
КонецПроцедуры

Однако более профессиональным подходом будет использование СтатусВозврата(0), чтобы не позволять записывать пустые или некорректные строки, вместо того чтобы просто очищать их реквизиты. Это заставит пользователя либо заполнить данные корректно, либо отменить ввод строки.

Нюансы работы в многопользовательском режиме

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

Если для бизнес-логики критично брать значение именно из своего последнего ввода в рамках текущего сеанса, рекомендуется использовать переменные модуля формы. Вы можете запоминать выбранную номенклатуру в процедуре ПриЗаписи() в переменную, объявленную в самом верху модуля (вне процедур), и использовать её при создании следующей строки.

Пример использования переменной модуля:


Перем ПамятьНоменклатуры; // Переменная сохраняет значение пока открыта форма

Процедура ПриРедактированииНовойСтроки()
    Если ПустоеЗначение(ПамятьНоменклатуры) = 0 Тогда
        Номенклатура = ПамятьНоменклатуры;
    КонецЕсли;
КонецПроцедуры

Процедура ПриЗаписи()
    ПамятьНоменклатуры = Номенклатура;
КонецПроцедуры

Этот подход считается наиболее "чистым" с точки зрения пользовательского опыта, так как он не зависит от физического порядка записей в базе данных и работает мгновенно без обращений к объекту Справочник.

Подведение итогов

Мы рассмотрели несколько способов автоматизации ввода в 1С 7.7. Для простых задач достаточно перебора в ПриРедактированииНовойСтроки(). Для высоконагруженных систем лучше использовать ОбратныйПорядок() или НайтиПоследнийЭлемент(). А для обеспечения максимального удобства конкретного пользователя лучше всего подходит механизм кэширования значений в переменных модуля формы.

← На главную