При работе с устаревшими, но все еще актуальными системами на платформе 1С:Предприятие 7.7, часто возникают задачи массового изменения данных. Типичный пример — корректировка окладов для определенной категории сотрудников. Однако простого перебора справочника недостаточно: важно учитывать статус сотрудника, чтобы не затронуть тех, кто уже прекратил трудовые отношения с организацией. Рассмотрим, как правильно реализовать обработку для изменения окладов программистов, игнорируя уволенных коллег.
В исходном варианте, предложенном автором темы, используется простой перебор справочника Сотрудники с фильтром по реквизиту Должность. Давайте проанализируем этот код:
Процедура Выполнить2()
Должн = СоздатьОбъект("Справочник.Должности");
Должн.НайтиПоНаименованию("Программист");
Сотрудник = СоздатьОбъект("Справочник.Сотрудники");
Сотрудник.ВыбратьЭлементыПоРеквизиту("Должность", Должн, 0, 0);
Пока Сотрудник.ПолучитьЭлемент() = 1 Цикл
Сотрудник.Оклад = Число(200000);
Сотрудник.Записать();
Сообщить("Заменен оклад для сотрудника: " + СокрЛП(Сотрудник.Наименование));
КонецЦикла;
КонецПроцедуры
Проанализируем слабые места этого кода:
ВыбратьЭлементыПоРеквизиту требует точной ссылки на элемент. Если НайтиПоНаименованию не сработает, код может повести себя непредсказуемо.Самый простой способ — добавить условие внутри цикла Пока. Если в вашей конфигурации предусмотрен реквизит Уволен (типа Число или Булево), решение будет выглядеть следующим образом:
Пока Сотрудник.ПолучитьЭлемент() = 1 Цикл
// Проверяем, не является ли элемент группой
Если Сотрудник.ЭтоГруппа() = 1 Тогда
Продолжить;
КонецЕсли;
// Проверяем статус увольнения
Если Сотрудник.Уволен = 1 Тогда
Продолжить; // Пропускаем уволенного
КонецЕсли;
Сотрудник.Оклад = 200000;
Сотрудник.Записать();
КонецЦикла;
В большинстве профессиональных конфигураций (например, "Зарплата и Кадры") статус сотрудника определяется через Перечисление. Выясним причину, почему это надежнее: перечисления исключают ошибки ввода. Рассмотрим пример кода, где статус проверяется через объект Состояние или Статус:
// Предположим, статус хранится в реквизите "Состояние"
Если Сотрудник.Состояние = Перечисление.СостоянияФизЛиц.Уволен Тогда
Продолжить;
КонецЕсли;
Или, как было предложено в обсуждении, через проверку статуса сотрудника:
Если Сотрудник.Статус = Перечисление.СтатусыСотрудников.Уволен Тогда
Продолжить;
КонецЕсли;
Разберем важный нюанс платформы 1С 7.7. Если Оклад является периодическим, его значение зависит от даты. Присваивание Сотрудник.Оклад = 200000 запишет значение на текущую рабочую дату. Если нам нужно установить оклад с определенного числа, правильно использовать метод Установить.
Проанализируем улучшенный код с учетом всех правок:
Процедура Выполнить2()
Перем Должн, Сотрудник, ВыбДата;
ВыбДата = РабочаяДата(); // или любая нужная дата начала действия оклада
Должн = СоздатьОбъект("Справочник.Должности");
Если Должн.НайтиПоНаименованию("Программист", 0, 1) = 0 Тогда
Предупреждение("Должность 'Программист' не найдена!");
Возврат;
КонецЕсли;
Сотрудник = СоздатьОбъект("Справочник.Сотрудники");
// Используем ТекущийЭлемент() для передачи ссылки в фильтр
Сотрудник.ВыбратьЭлементыПоРеквизиту("Должность", Должн.ТекущийЭлемент(), 0, 0);
Пока Сотрудник.ПолучитьЭлемент() = 1 Цикл
// Пропускаем группы
Если Сотрудник.ЭтоГруппа() = 1 Тогда
Продолжить;
КонецЕсли;
// Пропускаем уволенных (проверка по дате увольнения, если она заполнена)
Если Сотрудник.ДатаУвольнения.Выбран() = 1 Тогда
Если Сотрудник.ДатаУвольнения <= ВыбДата Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
// Устанавливаем периодический реквизит корректно
Сотрудник.Оклад.Установить(ВыбДата, 200000);
// Сохраняем изменения
Сотрудник.Записать();
Сообщить("Обновлен оклад: " + Сотрудник.Наименование);
КонецЦикла;
КонецПроцедуры
Если ваша база данных работает на Microsoft SQL Server, для ускорения процесса (особенно если сотрудников тысячи) можно использовать прямой SQL-запрос. Посмотрим на пример, предложенный в сообщении 6, но с важным уточнением: прямое изменение таблиц SQL обходит бизнес-логику 1С и должно применяться только в крайних случаях.
-- Пример логики запроса (метакод)
UPDATE $Справочник.Сотрудники
SET $Справочник.Сотрудники.Оклад = 200000
WHERE $Справочник.Сотрудники.Должность = (SELECT TOP 1 id FROM $Справочник.Должности WHERE descr = 'Программист')
AND ismark = 0 -- Не помечен на удаление
AND $Справочник.Сотрудники.Уволен = 0;
Важное замечание: В 1С 7.7 поле ismark означает только пометку на удаление. Факт увольнения обычно хранится в отдельных полях таблиц справочника или в таблицах периодических реквизитов (const или 1svprop).
Чтобы ваша обработка прошла проверку (преподавателем или заказчиком), следуйте этим правилам:
ЭтоГруппа(). Попытка записать данные в папку справочника — частая причина аварийного завершения обработок.НайтиПоНаименованию всегда проверяйте результат возврата (1 — найдено, 0 — нет).Сообщить(), чтобы видеть прогресс выполнения и понимать, сколько сотрудников было обработано.Таким образом, комбинируя проверку должности и анализ реквизитов состояния (или даты увольнения), мы получаем надежный инструмент для управления кадровыми данными, который не затронет архивные записи организации.