Когда мы сталкиваемся с необходимостью получить данные из типовых отчетов 1С:ЗУП или 1С:ЗГУ (особенно связанных со сложными подсистемами, такими как штатное расписание) и использовать их в своей обработке, часто возникает ситуация, когда запрос, скопированный из СКД отчета, возвращает пустой результат. При необходимости выполнить перенос данных между базами 1С:ЗУП 3, включая кадровые сведения и расчеты, применяются специализированные инструменты. Давайте вместе разберем, почему это происходит и как правильно работать с такими запросами.
Наш коллега столкнулся с запросом из штатного отчета СКД, который начинался с конструкции ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 0 ... ПОМЕСТИТЬ Представления_ШтатноеРасписание. Далее следовал второй пакет запроса, который выбирал данные из этой временной таблицы Представления_ШтатноеРасписание. При попытке выполнить этот запрос напрямую в обработке, он возвращал пустые данные.
Запрос = новый запрос ;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц ;
Запрос.УстановитьПараметр("ДатаАктуальности", ДатаЗапр);
Запрос.Текст = "ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 0
| ЗНАЧЕНИЕ(Справочник.Организации.ПустаяСсылка) КАК Организация,
| ЗНАЧЕНИЕ(Справочник.ШтатноеРасписание.ПустаяСсылка) КАК ПозицияШтатногоРасписания,
... // Опущено для краткости
|ПОМЕСТИТЬ Представления_ШтатноеРасписание
|ГДЕ
| ""ТолькоРазрешенные"" = ИСТИНА
| И ""ДатаАктуальности"" = &ДатаАктуальности
| И ""ВключатьНачисления"" = ЛОЖЬ
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ДанныеОстатковПозиций.ПозицияШтатногоРасписания КАК ПозицияШтатногоРасписания,
... // Опущено для краткости
|ИЗ
| Представления_ШтатноеРасписание КАК ДанныеОстатковПозиций" ;
РезультатЗапроса = Запрос.Выполнить; // Результат пустой
Давайте подробно рассмотрим, почему такой запрос возвращает пустые данные.
ВЫБРАТЬ ... ПЕРВЫЕ 0 ... ПОМЕСТИТЬ используется в первом пакете запроса для того, чтобы лишь определить структуру временной таблицы (в нашем случае, Представления_ШтатноеРасписание), но при этом не заполнить ее никакими данными. То есть, таблица будет создана со всеми указанными колонками, но ни одной записи в ней не будет.ВЫБРАТЬ ... ИЗ Представления_ШтатноеРасписание, пытается получить данные из этой только что созданной, но абсолютно пустой временной таблицы. Естественно, результатом будет пустая выборка.Таким образом, когда мы напрямую копируем и выполняем такой запрос, мы получаем пустой результат, потому что первый пакет сознательно не возвращает ни одной записи.
Важно понимать: Конструкция ПЕРВЫЕ 0 — это не ошибка в запросе СКД, а часть его внутреннего механизма. В контексте работы СКД, этот "пустой" запрос является шаблоном, который платформа 1С или специализированные процедуры конфигурации динамически изменяют и дополняют реальными данными. Без такого динамического дополнения, запрос остается "пустышкой".
Конфигурации "Зарплата и управление персоналом" (ЗУП) и "Зарплата и кадры государственного учреждения" (ЗГУ) имеют достаточно сложную архитектуру данных. Они активно используют так называемый механизм представлений (виртуальных таблиц). Это одна из ключевых особенностей, которую нам необходимо учитывать при работе с их данными программно. Если же требуется перенос данных между похожими конфигурациями 1С с поиском по произвольным полям, используются специализированные обработки.
Представления_ШтатноеРасписание – это как раз такое представление."ТолькоРазрешенные" = ИСТИНА, "ДатаАктуальности" = &ДатаАктуальности, "ВключатьНачисления" = ЛОЖЬ в секции ГДЕ первого пакета – это не обычные условия фильтрации, а скорее инструкции для программного кода, который будет динамически преобразовывать этот шаблон запроса в полноценный запрос к реальным данным. Эти строки интерпретируются не системой запросов напрямую, а специальными процедурами 1С.ЗарплатаКадрыОбщиеНаборыДанных: В ЗУП/ЗГУ существуют общие модули, такие как ЗарплатаКадрыОбщиеНаборыДанных, которые содержат процедуры для работы с этими представлениями. В типовых отчетах СКД вызов таких процедур происходит, например, в обработчике события ПриКомпоновкеРезультата модуля объекта отчета. Эти процедуры могут выполнять следующие действия:
Именно поэтому прямое копирование запроса из СКД и его выполнение в обработке без использования этих специальных механизмов ЗУП/ЗГУ приводит к пустому результату. Для интерактивной отладки и проверки таких конструкций можно использовать консоль запросов с поддержкой механизма представлений ЗУП.
Учитывая сложность и динамичность работы с данными в ЗУП/ЗГУ, мы рекомендуем следующие подходы:
Копирование текста запроса из СКД отчета ЗУП/ЗГУ и попытка его прямого выполнения в вашей обработке – это, как правило, тупиковый путь. Для качественной миграции информации раздел с решениями для переноса данных ЗУП содержит инструменты для различных сценариев перехода. Причины следующие:
Наиболее стабильный и правильный подход – это использование программного интерфейса, предоставляемого самой конфигурацией (часто это часть Библиотеки стандартных подсистем – БСП). Эти механизмы предназначены для получения данных с учетом всей бизнес-логики конфигурации и адаптируются разработчиками 1С при каждом обновлении.
ЗарплатаКадрыОбщиеНаборыДанных.ЗаменитьЗапросыКПредставлениямВиртуальныхТаблиц(): Для динамической замены запросов к представлениям мы можем использовать функцию ЗаменитьЗапросыКПредставлениямВиртуальныхТаблиц() из общего модуля ЗарплатаКадрыОбщиеНаборыДанных. Эта функция принимает текст запроса, находит в нем обращения к представлениям и заменяет их на реальные запросы к данным, учитывая переданные параметры.
// Предположим, что ДатаЗапр уже определена
ДатаЗапр = НачалоМесяца(ТекущаяДата()); // Пример даты
// Изначальный текст запроса с обращениями к представлению
ТекстЗапросаШаблон = "ВЫБРАТЬ РCODE> РАЗРЕШЕННЫЕ ПЕРВЫЕ 0
| ЗНАЧЕНИЕ(Справочник.Организации.ПустаяСсылка) КАК Организация,
| ЗНАЧЕНИЕ(Справочник.ШтатноеРасписание.ПустаяСсылка) КАК ПозицияШтатногоРасписания,
| ЗНАЧЕНИЕ(Справочник.ПодразделенияОрганизаций.ПустаяСсылка) КАК Подразделение,
| ЗНАЧЕНИЕ(Справочник.Должности.ПустаяСсылка) КАК Должность,
| ЗНАЧЕНИЕ(Справочник.РазрядыКатегорииДолжностей.ПустаяСсылка) КАК РазрядКатегория,
| ЗНАЧЕНИЕ(Справочник.ГрафикиРаботыСотрудников.ПустаяСсылка) КАК ГрафикРаботыСотрудников,
| ЗНАЧЕНИЕ(Справочник.СтатьиФинансированияЗарплата.ПустаяСсылка) КАК СтатьяФинансирования,
| 0 КАК КоличествоСтавок,
| 0 КАК ФОТ,
| 0 КАК ФОТМин,
| 0 КАК ФОТМакс,
| 0 КАК ФОТПозиции,
| 0 КАК ФОТПозицииМин,
| 0 КАК ФОТПозицииМакс,
| 0 КАК ОкладТариф,
| 0 КАК ОкладТарифМин,
| 0 КАК ОкладТарифМакс,
| 0 КАК ЗанятаПостоянно,
| 0 КАК ЗанятаВременно,
| 0 КАК ПодработкаПостоянно,
| 0 КАК ПодработкаВременно,
| 0 КАК СовмещенаПостоянно,
| 0 КАК СовмещенаВременно,
| 0 КАК Забронирована,
| 0 КАК ВременноОсвобождена
|ПОМЕСТИТЬ Представления_ШтатноеРасписание
|ГДЕ
| ""ТолькоРазрешенные"" = ИСТИНА
| И ""ДатаАктуальности"" = &ДатаАктуальности
| И ""ВключатьНачисления"" = ЛОЖЬ
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ДанныеОстатковПозиций.ПозицияШтатногоРасписания КАК ПозицияШтатногоРасписания,
| ДанныеОстатковПозиций.КоличествоСтавок КАК КоличествоСтавок,
| ДанныеОстатковПозиций.КоличествоСтавок - ДанныеОстатковПозиций.ЗанятаПостоянно - ДанныеОстатковПозиций.ЗанятаВременно - ДанныеОстатковПозиций.ПодработкаПостоянно - ДанныеОстатковПозиций.ПодработкаВременно - ДанныеОстатковПозиций.СовмещенаПостоянно - ДанныеОстатковПозиций.СовмещенаВременно - ДанныеОстатковПозиций.Забронирована КАК СвободноСтавок,
| ДанныеОстатковПозиций.ЗанятаПостоянно КАК ЗанятаПостоянно,
| ДанныеОстатковПозиций.ЗанятаВременно КАК ЗанятаВременно,
| ДанныеОстатковПозиций.ПодработкаПостоянно КАК ПодработкаПостоянно,
| ДанныеОстатковПозиций.ПодработкаВременно КАК ПодработкаВременно,
| ДанныеОстатковПозиций.СовмещенаПостоянно КАК СовмещенаПостоянно,
| ДанныеОстатковПозиций.СовмещенаВременно КАК СовмещенаВременно,
| ДанныеОстатковПозиций.Забронирована КАК Забронирована,
| ДанныеОстатковПозиций.ВременноОсвобождена КАК СвободнаВременно,
| ДанныеОстатковПозиций.ФОТ КАК ФОТ,
| ДанныеОстатковПозиций.ФОТМин КАК ФОТМин,
| ДанныеОстатковПозиций.ФОТМакс КАК ФОТМакс,
| ДанныеОстатковПозиций.ФОТПозиции КАК ФОТПоПозиции,
| ДанныеОстатковПозиций.ФОТПозицииМин КАК ФОТПоПозицииМин,
| ДанныеОстатковПозиций.ФОТПозицииМакс КАК ФОТПоПозицииМакс,
| ДанныеОстатковПозиций.ОкладТариф КАК ОкладТариф,
| ДанныеОстатковПозиций.ОкладТарифМин КАК ОкладТарифМин,
| ДанныеОстатковПозиций.ОкладТарифМакс КАК ОкладТарифМакс
|ИЗ
| Представления_ШтатноеРасписание КАК ДанныеОстатковПозиций";
// Создаем объект Запрос
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
// Устанавливаем параметры запроса. Важно: для параметров представлений,
// которые заключены в кавычки, например, ""ТолькоРазрешенные"",
// используются специальные механизмы, а не прямая установка параметра запроса.
// В данном случае, параметр &ДатаАктуальности - обычный параметр запроса.
Запрос.УстановитьПараметр("ДатаАктуальности", ДатаЗапр);
// Вызываем функцию для замены запросов к виртуальным таблицам
// Эта функция принимает на вход текст запроса и объект Запрос
// и изменяет Запрос.Текст, подставляя реальные запросы к данным.
ТекстЗапросаСПредставлениями = ЗарплатаКадрыОбщиеНаборыДанных.ЗаменитьЗапросыКПредставлениямВиртуальныхТаблиц(ТекстЗапросаШаблон, Запрос);
// Присваиваем преобразованный текст запросу
Запрос.Текст = ТекстЗапросаСПредставлениями;
// Выполняем запрос
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить("Позиция: " + Выборка.ПозицияШтатногоРасписания + ", Ставок: " + Выборка.КоличествоСтавок);
КонецЦикла;
Пояснения к коду:
Представления_ШтатноеРасписание.Запрос и устанавливаем МенеджерВременныхТаблиц.&ДатаАктуальности. Обратите внимание, что параметры типа "ТолькоРазрешенные" не устанавливаются как обычные параметры запроса. Эти "псевдо-параметры" используются функцией замены представлений для определения логики, по которой будут собираться данные.ЗарплатаКадрыОбщиеНаборыДанных.ЗаменитьЗапросыКПредставлениямВиртуальныхТаблиц(ТекстЗапросаШаблон, Запрос). Эта функция выполнит всю магию: она проанализирует ТекстЗапросаШаблон, определит обращения к представлениям и заменит их на реальные запросы к регистрам и справочникам ЗУП/ЗГУ, учитывая также "псевдо-параметры" вроде `"ТолькоРазрешенные"`. При этом она модифицирует объект Запрос (например, может установить дополнительные параметры или изменить свойства МенеджерВременныхТаблиц).Запрос.Текст, и только после этого мы выполняем запрос.Этот подход гарантирует, что ваша обработка будет получать данные так же, как и типовой отчет, и будет более устойчива к обновлениям конфигурации. При необходимости отлаживать отчеты с подобными источниками можно использовать консоль СКД для работы с представлениями ЗУП.
Параметры, такие как "ТолькоРазрешенные" = ИСТИНА или "ВключатьНачисления" = ЛОЖЬ, являются особенными. Они не являются стандартными параметрами запроса 1С. Вместо этого, они служат своего рода "ключами", по которым механизм представлений определяет, какую именно версию запроса к данным ему нужно построить или какие фильтры применить. Как правило, эти значения жестко задаются в тексте запроса или могут быть переданы через специальную структуру параметров, которая затем обрабатывается функцией ЗаменитьЗапросыКПредставлениямВиртуальныхТаблиц. Мы должны внимательно изучать документацию или исходный код типовых конфигураций, чтобы понять, как эти "параметры" интерпретируются.
В некоторых случаях, если нам нужны относительно простые данные, и мы точно знаем структуру регистров, к которым обращаемся, мы можем написать свой собственный запрос, минуя механизм представлений. Однако этот подход сопряжен с серьезными рисками в ЗУП/ЗГУ:
Когда это может быть оправдано: Если вы абсолютно уверены в стабильности структуры для конкретных, очень простых данных, или вам нужен очень специфичный набор, который сложно получить через представления, и вы готовы регулярно поддерживать свой запрос. Например, если речь идет о прямом запросе к конкретному справочнику без сложной логики.
Работа с запросами из типовых отчетов СКД 1С:ЗУП/ЗГУ в своих обработках требует понимания внутренней архитектуры этих конфигураций, особенно механизма представлений. Мы выяснили, что конструкция ВЫБРАТЬ ПЕРВЫЕ 0 является частью шаблона, который динамически преобразуется. Мы рекомендуем использовать программный интерфейс, предоставляемый конфигурацией (например, функции из ЗарплатаКадрыОбщиеНаборыДанных), для получения данных из представлений. Этот подход обеспечивает стабильность, корректность данных и меньшую зависимость от внутренних изменений конфигурации. Самостоятельное написание запросов к регистрам ЗУП/ЗГУ возможно, но требует глубоких знаний и готовности к постоянной поддержке.