Как правильно использовать запросы из отчетов СКД 1С:ЗУП/ЗГУ в своей обработке, избегая пустых результатов?

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом Управленческий учет
← На главную

Когда мы сталкиваемся с необходимостью получить данные из типовых отчетов 1С:ЗУП или 1С:ЗГУ (особенно связанных со сложными подсистемами, такими как штатное расписание) и использовать их в своей обработке, часто возникает ситуация, когда запрос, скопированный из СКД отчета, возвращает пустой результат. При необходимости выполнить перенос данных между базами 1С:ЗУП 3, включая кадровые сведения и расчеты, применяются специализированные инструменты. Давайте вместе разберем, почему это происходит и как правильно работать с такими запросами.

Исходная проблема: запрос с "ВЫБРАТЬ ПЕРВЫЕ 0"

Наш коллега столкнулся с запросом из штатного отчета СКД, который начинался с конструкции ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 0 ... ПОМЕСТИТЬ Представления_ШтатноеРасписание. Далее следовал второй пакет запроса, который выбирал данные из этой временной таблицы Представления_ШтатноеРасписание. При попытке выполнить этот запрос напрямую в обработке, он возвращал пустые данные.


Запрос = новый запрос ;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц ;
Запрос.УстановитьПараметр("ДатаАктуальности", ДатаЗапр);
Запрос.Текст = "ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 0 
| ЗНАЧЕНИЕ(Справочник.Организации.ПустаяСсылка) КАК Организация,
| ЗНАЧЕНИЕ(Справочник.ШтатноеРасписание.ПустаяСсылка) КАК ПозицияШтатногоРасписания,
... // Опущено для краткости
|ПОМЕСТИТЬ Представления_ШтатноеРасписание 
|ГДЕ 
| ""ТолькоРазрешенные"" = ИСТИНА 
| И ""ДатаАктуальности"" = &ДатаАктуальности 
| И ""ВключатьНачисления"" = ЛОЖЬ 
|; 
| 
|////////////////////////////////////////////////////////////­//////////////////// 
|ВЫБРАТЬ 
| ДанныеОстатковПозиций.ПозицияШтатногоРасписания КАК ПозицияШтатногоРасписания,
... // Опущено для краткости
|ИЗ 
| Представления_ШтатноеРасписание КАК ДанныеОстатковПозиций" ;
РезультатЗапроса = Запрос.Выполнить; // Результат пустой

Причина пустого результата: конструкция "ВЫБРАТЬ ПЕРВЫЕ 0"

Давайте подробно рассмотрим, почему такой запрос возвращает пустые данные.

  1. Определение структуры временной таблицы: Конструкция ВЫБРАТЬ ... ПЕРВЫЕ 0 ... ПОМЕСТИТЬ используется в первом пакете запроса для того, чтобы лишь определить структуру временной таблицы (в нашем случае, Представления_ШтатноеРасписание), но при этом не заполнить ее никакими данными. То есть, таблица будет создана со всеми указанными колонками, но ни одной записи в ней не будет.
  2. Выборка из пустой таблицы: Второй пакет запроса, ВЫБРАТЬ ... ИЗ Представления_ШтатноеРасписание, пытается получить данные из этой только что созданной, но абсолютно пустой временной таблицы. Естественно, результатом будет пустая выборка.

Таким образом, когда мы напрямую копируем и выполняем такой запрос, мы получаем пустой результат, потому что первый пакет сознательно не возвращает ни одной записи.

Важно понимать: Конструкция ПЕРВЫЕ 0 — это не ошибка в запросе СКД, а часть его внутреннего механизма. В контексте работы СКД, этот "пустой" запрос является шаблоном, который платформа 1С или специализированные процедуры конфигурации динамически изменяют и дополняют реальными данными. Без такого динамического дополнения, запрос остается "пустышкой".

Специфика запросов в 1С:ЗУП и 1С:ЗГУ – механизм представлений

Конфигурации "Зарплата и управление персоналом" (ЗУП) и "Зарплата и кадры государственного учреждения" (ЗГУ) имеют достаточно сложную архитектуру данных. Они активно используют так называемый механизм представлений (виртуальных таблиц). Это одна из ключевых особенностей, которую нам необходимо учитывать при работе с их данными программно. Если же требуется перенос данных между похожими конфигурациями 1С с поиском по произвольным полям, используются специализированные обработки.

  1. Виртуальные таблицы и их назначение: Представления – это не реальные таблицы в базе данных, а программно формируемые наборы данных. Они служат для того, чтобы скрывать от разработчика сложную логику получения и агрегирования информации из множества регистров, справочников и документов. Мы обращаемся к ним как к обычным таблицам, но на самом деле за кулисами запускается сложный код, который собирает нужные данные. Например, Представления_ШтатноеРасписание – это как раз такое представление.
  2. Динамическое изменение запросов: Запросы в типовых отчетах СКД часто содержат специальные "заглушки" или "указания" для этих представлений. Например, строки "ТолькоРазрешенные" = ИСТИНА, "ДатаАктуальности" = &ДатаАктуальности, "ВключатьНачисления" = ЛОЖЬ в секции ГДЕ первого пакета – это не обычные условия фильтрации, а скорее инструкции для программного кода, который будет динамически преобразовывать этот шаблон запроса в полноценный запрос к реальным данным. Эти строки интерпретируются не системой запросов напрямую, а специальными процедурами 1С.
  3. Роль модуля ЗарплатаКадрыОбщиеНаборыДанных: В ЗУП/ЗГУ существуют общие модули, такие как ЗарплатаКадрыОбщиеНаборыДанных, которые содержат процедуры для работы с этими представлениями. В типовых отчетах СКД вызов таких процедур происходит, например, в обработчике события ПриКомпоновкеРезультата модуля объекта отчета. Эти процедуры могут выполнять следующие действия:
    • Замена текста запроса: Они могут полностью заменить "пустышку" запроса к представлению на сложный, реальный запрос к регистрам и справочникам, подставив в него нужные условия и параметры.
    • Заполнение временных таблиц: Если используются временные таблицы, они могут быть заполнены программно до выполнения основного запроса.

Именно поэтому прямое копирование запроса из СКД и его выполнение в обработке без использования этих специальных механизмов ЗУП/ЗГУ приводит к пустому результату. Для интерактивной отладки и проверки таких конструкций можно использовать консоль запросов с поддержкой механизма представлений ЗУП.

Рекомендации по использованию запросов из типовых конфигураций

Учитывая сложность и динамичность работы с данными в ЗУП/ЗГУ, мы рекомендуем следующие подходы:

1. Откажитесь от прямого копирования запросов "как есть"

Копирование текста запроса из СКД отчета ЗУП/ЗГУ и попытка его прямого выполнения в вашей обработке – это, как правило, тупиковый путь. Для качественной миграции информации раздел с решениями для переноса данных ЗУП содержит инструменты для различных сценариев перехода. Причины следующие:

  1. Изменения структуры данных: Структура хранения данных в ЗУП/ЗГУ может быть очень сложной и часто меняется от релиза к релизу. Если вы написали свой запрос, опираясь на текущую структуру, то после очередного обновления конфигурации он может перестать работать или выдавать некорректные данные.
  2. Изменения программного интерфейса: Даже если структура данных не меняется, программный интерфейс для работы с представлениями (то есть, логика их формирования) может изменяться. Это означает, что если вы попытаетесь "имитировать" работу СКД, то вам придется постоянно адаптировать ваш код.

2. Используйте программный интерфейс типовых конфигураций (БСП)

Наиболее стабильный и правильный подход – это использование программного интерфейса, предоставляемого самой конфигурацией (часто это часть Библиотеки стандартных подсистем – БСП). Эти механизмы предназначены для получения данных с учетом всей бизнес-логики конфигурации и адаптируются разработчиками 1С при каждом обновлении.

  1. Функция ЗарплатаКадрыОбщиеНаборыДанных.ЗаменитьЗапросыКПредставлениямВиртуальныхТаблиц(): Для динамической замены запросов к представлениям мы можем использовать функцию ЗаменитьЗапросыКПредставлениямВиртуальныхТаблиц() из общего модуля ЗарплатаКадрыОбщиеНаборыДанных. Эта функция принимает текст запроса, находит в нем обращения к представлениям и заменяет их на реальные запросы к данным, учитывая переданные параметры.
  2. Пример использования в вашей обработке: Давайте посмотрим, как мы можем модифицировать код нашего коллеги, чтобы он заработал с учетом механизма представлений:

// Предположим, что ДатаЗапр уже определена
ДатаЗапр = НачалоМесяца(ТекущаяДата()); // Пример даты

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

// Создаем объект Запрос
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;

// Устанавливаем параметры запроса. Важно: для параметров представлений,
// которые заключены в кавычки, например, ""ТолькоРазрешенные"",
// используются специальные механизмы, а не прямая установка параметра запроса.
// В данном случае, параметр &ДатаАктуальности - обычный параметр запроса.
Запрос.УстановитьПараметр("ДатаАктуальности", ДатаЗапр);

// Вызываем функцию для замены запросов к виртуальным таблицам
// Эта функция принимает на вход текст запроса и объект Запрос
// и изменяет Запрос.Текст, подставляя реальные запросы к данным.
ТекстЗапросаСПредставлениями = ЗарплатаКадрыОбщиеНаборыДанных.ЗаменитьЗапросыКПредставлениямВиртуальныхТаблиц(ТекстЗапросаШаблон, Запрос);

// Присваиваем преобразованный текст запросу
Запрос.Текст = ТекстЗапросаСПредставлениями;

// Выполняем запрос
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    Сообщить("Позиция: " + Выборка.ПозицияШтатногоРасписания + ", Ставок: " + Выборка.КоличествоСтавок);
КонецЦикла;

Пояснения к коду:

  1. Мы сначала создаем "сырой" текст запроса, который включает обращение к представлению Представления_ШтатноеРасписание.
  2. Создаем обычный объект Запрос и устанавливаем МенеджерВременныхТаблиц.
  3. Устанавливаем обычные параметры запроса, такие как &ДатаАктуальности. Обратите внимание, что параметры типа "ТолькоРазрешенные" не устанавливаются как обычные параметры запроса. Эти "псевдо-параметры" используются функцией замены представлений для определения логики, по которой будут собираться данные.
  4. Ключевой шаг: Вызываем функцию ЗарплатаКадрыОбщиеНаборыДанных.ЗаменитьЗапросыКПредставлениямВиртуальныхТаблиц(ТекстЗапросаШаблон, Запрос). Эта функция выполнит всю магию: она проанализирует ТекстЗапросаШаблон, определит обращения к представлениям и заменит их на реальные запросы к регистрам и справочникам ЗУП/ЗГУ, учитывая также "псевдо-параметры" вроде `"ТолькоРазрешенные"`. При этом она модифицирует объект Запрос (например, может установить дополнительные параметры или изменить свойства МенеджерВременныхТаблиц).
  5. Полученный (преобразованный) текст запроса присваивается свойству Запрос.Текст, и только после этого мы выполняем запрос.

Этот подход гарантирует, что ваша обработка будет получать данные так же, как и типовой отчет, и будет более устойчива к обновлениям конфигурации. При необходимости отлаживать отчеты с подобными источниками можно использовать консоль СКД для работы с представлениями ЗУП.

3. Работа с параметрами, передаваемыми в представления

Параметры, такие как "ТолькоРазрешенные" = ИСТИНА или "ВключатьНачисления" = ЛОЖЬ, являются особенными. Они не являются стандартными параметрами запроса 1С. Вместо этого, они служат своего рода "ключами", по которым механизм представлений определяет, какую именно версию запроса к данным ему нужно построить или какие фильтры применить. Как правило, эти значения жестко задаются в тексте запроса или могут быть переданы через специальную структуру параметров, которая затем обрабатывается функцией ЗаменитьЗапросыКПредставлениямВиртуальныхТаблиц. Мы должны внимательно изучать документацию или исходный код типовых конфигураций, чтобы понять, как эти "параметры" интерпретируются.

Альтернативный подход: написание собственного запроса

В некоторых случаях, если нам нужны относительно простые данные, и мы точно знаем структуру регистров, к которым обращаемся, мы можем написать свой собственный запрос, минуя механизм представлений. Однако этот подход сопряжен с серьезными рисками в ЗУП/ЗГУ:

  1. Сложность структуры: ЗУП/ЗГУ известны своей сложной и многогранной структурой данных. Чтобы собрать даже, казалось бы, простые данные по штатному расписанию, вам может потребоваться объединить информацию из нескольких регистров, справочников и даже документов.
  2. Постоянные изменения: Разработчики 1С часто меняют внутреннюю структуру хранения данных в ЗУП/ЗГУ. Ваш самописный запрос может перестать работать после очередного обновления, и вам придется его переписывать. Это особенно актуально для динамично развивающихся областей, таких как учет штатного расписания, где уже были значительные изменения (например, в ЗГУ 3.1.10 был пересмотрен механизм учета занятых ставок).
  3. Неучет бизнес-логики: Самостоятельно написанный запрос может не учитывать всю сложную бизнес-логику конфигурации (например, как правильно рассчитывается ФОТ, ставки, занятость с учетом специфических документов и настроек). Механизм представлений делает это автоматически.

Когда это может быть оправдано: Если вы абсолютно уверены в стабильности структуры для конкретных, очень простых данных, или вам нужен очень специфичный набор, который сложно получить через представления, и вы готовы регулярно поддерживать свой запрос. Например, если речь идет о прямом запросе к конкретному справочнику без сложной логики.

Заключение

Работа с запросами из типовых отчетов СКД 1С:ЗУП/ЗГУ в своих обработках требует понимания внутренней архитектуры этих конфигураций, особенно механизма представлений. Мы выяснили, что конструкция ВЫБРАТЬ ПЕРВЫЕ 0 является частью шаблона, который динамически преобразуется. Мы рекомендуем использовать программный интерфейс, предоставляемый конфигурацией (например, функции из ЗарплатаКадрыОбщиеНаборыДанных), для получения данных из представлений. Этот подход обеспечивает стабильность, корректность данных и меньшую зависимость от внутренних изменений конфигурации. Самостоятельное написание запросов к регистрам ЗУП/ЗГУ возможно, но требует глубоких знаний и готовности к постоянной поддержке.

← На главную