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