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