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