Главная » 1С Предприятие » МОДУЛЬ  ОТЧЕТА  С ЗАПРОСОМ

0

Длинный  код по  выбору данных  принято  заменять запросами  к файлам базы данных.  В СУБД общего назначения, например FoxPro,  запросы не только компактнее по коду, но и эффективнее по быстродействию. В 1С последнее качество запросов не столь очевидно.

Результатом  выполнения   запроса  является   таблица,  содержащая  отобранные  запросом данные.  На основе этой таблицы можно,  например, создать отчет,  выполнить требуемые вычисления или иные предусмотренные алгоритмом  действия.

Запрос 1С  это  объект,  например запС, появляющийся в  программе  в  результате

присваивания

запС = СоздатьОбъект("Запрос");

Содержание  запроса оформляется в  1С, как  правило,  в виде длинной, расположенной   на  нескольких   строчках   символьной  именованной  константы,  например   текст ЗапС,  которая затем  употребляется в  качестве  параметра метода  Выполнить:

флаг = запС.Выполнить(текстЗапС);

Метод  Выполнить  вернет  1  при  успешном  выполнении  запроса  или  0  -в  случае неудачи.

Оставим диалог  обработки  Проба   без  изменений,  но  удалим из  ее  модуля  ранее внесенный в  него  код  (кроме процедуры ПриОткрытии) и заменим его  на нижеприводимые  процедуры  и   функции.  Первая,  имеющая   имя  ЗапрСотр,  выполняет   запрос  к справочнику  Сотрудники_2,  выбирая в  результате   данные,  удовлетворяющие  перечисленным   в  разд.   5.11.1   критериям.  Процедура  ВывТабСотр   формирует,  используя макет  таблицы  Сотрудники_2  (см.  рис. 5.57)  обработки  Проба, отчет.  Разумеется, если в диалоге (см.  рис. 5.56)  для  переменной обр задано  значение  Высшее, а для  переменной  окл  2000, то  итоговый отчет  полностью совпадет  с  результатом,  содержащимся в табл.  5.7.

Назначение  иных  программных  компонентов  модуля  обработки  Проба  будет  поясняться сопровождающим  их комментарием.

// Установим начальные значения переменных диалога обр и окл

процедура ПриОткрытии() перем  видОбр; ОчиститьОкноСообщений();

видОбр =  СоздатьОбъект("Справочник.Образование_2"); видОбр.ВыбратьЭлементы(); видОбр.ПолучитьЭлемент();

// Используем в качестве начального значения переменной обр

// первый элемент справочника Образование_2 обр = видОбр.ТекущийЭлемент();

окл  = 2000.0                      //                руб.

конецПроцедуры // ПриОткрытии

// Формируем и выполняем запрос  по сотрудникам,

// имеющим образование обр и оклад, не меньший окл

// Функция принимает и возвращает параметр запС типа Запрос функция ЗапрСотр(запС)

Перем текстЗапС;                       //                          Содержание запроса перем  рабДат;

рабДат = РабочаяДата(); текстЗапС = "

| период с рабДат  по рабДат;            //       Дата для периодического реквизита Оклад

// Переменные запроса

| род = Справочник.Сотрудники_2.ТекущийЭлемент.Родитель;

| имяСотр = Справочник.Сотрудники_2.Наименование;

| код = Справочник.Сотрудники_2.Код;

| образование = Справочник.Сотрудники_2.Образование;

| оклад = Справочник.Сотрудники_2.Оклад;

// Задаем порядок  выборки данных

| группировка род;

|  группировка имяСотр;

| условие ((образование  = обр)  и (оклад >= окл));";

// Выполняем  запрос и возвращаем 1 в случае удачи, или 0, если есть проблемы возврат запС.Выполнить(текстЗапС);

конецФункции // ЗапрСотр

функция НайтиДП(сСотр  2, код) далее

// Выводит данные в таблицу Сотрудники_2  обработки Проба процедура ВывТабСотр(запС)

перем табл;

// Создаем объекты  сСотр_2 и табл

// Объект сСотр_2 создается для функции НайтиДП, осуществляющей поиск

// даты  приема на работу  сотрудника

сСотр_2 = СоздатьОбъект("Справочник.Сотрудники_2"); табл = СоздатьОбъект("Таблица");

// Свяжем  переменную табл с таблицей  Сотрудники_2, содержащей макет отчета  табл.ИсходнаяТаблица("Сотрудники_2");

// При выводе применяем заданные по умолчанию  параметры таблицы;

// для  их изменения следует  обратиться  к методу  Опции табл.ВывестиСекцию("заг");                //           Выводим секцию заг

// Вывод запроса в таблицу Сотрудники_2 пока запС.Группировка("род") = 1 цикл

подр = запС.Род;

табл.ВывестиСекцию("подр");

пока запС.Группировка("имяСотр") = 1 цикл сотр = запС.ИмяСотр;

код = запС.Код;

дП = НайтиДП(сСотр_2, код);  ставка = запС.Оклад;

// Вывод очередной  строки в отчет

табл.ВывестиСекцию("сотр"); конецЦикла; // пока

конецЦикла; // пока

табл.ВывестиСекцию("датаОтч");             //        Дата отчета

// Запрещаем редактирование результирующей таблицы табл.ТолькоПросмотр(1);

// Задаем в методе  Показать заголовок  окна  с результирующей таблицей табл.Показать("Выборка из справочника Сотрудники_2");

конецПроцедуры // ВывТабСотр

// Находит, если есть  ссылка на приказ о приеме  на работу, дату трудоустройства сотрудника  функция НайтиДП(сСотр  2, код)

сСотр_2.НайтиПоКоду(код, 0);               //         Ищем во  всем справочнике

// Вернем либо дату приказа  о приеме на работу, либо символ -, если

// в рассматриваемой записи справочника Сотрудники_2  нет ссылки на приказ возврат ?(ПустоеЗначение(сСотр_2.ПриказПрием) = 0,

сСотр_2.ПриказПрием.ДатаПриема,"-");

конецФункции // НайтиДП

процедура Выполнить()                     //              Связана с кнопкой Пуск  обработки Проба  перем запС, тЗнач;

// Создаем объекты запС и тЗнач  запС = СоздатьОбъект("Запрос"); если ЗапрСотр(запС) = 0 тогда

возврат;                             //                 Запрос не выполнен

конецЕсли;

// Если в отчете нет сведений о сотрудниках если запС.Группировка("род") = 0 тогда

Предупреждение("Сотрудников, отвечающих заданным условиям, нет.");

возврат; иначе

запС.ВНачалоВыборки(); конецЕсли;

// Создаем объект тЗнач для промежуточной демонстрации выборки запроса тЗнач = СоздатьОбъект("ТаблицаЗначений");

// Выгружаем все переменные запроса в таблицу значений тЗнач

// для его предварительного просмотра запС.Выгрузить(тЗнач, 1);

// Просмотр таблицы значений (результатов запроса) тЗнач.ВыбратьСтроку(, "Запрос  в таблице значений");

// Выводим выборку запроса в таблицу Сотрудники_2

ВывТабСотр(запС); конецПроцедуры // Выполнить

Результат  приведен в  табл.  5.7.

Сделаем некоторые пояснения.

Результатом запроса является  выборка,  являющаяся  последовательностью  записей. Фактически  выборка  является  таблицей,  в   столбцах   которой  расположены  значения заданных  в  тексте   запроса переменных  в   нашем  случае  переменных родг   имяСотр, код,  образование и  оклад.  В  общем  случае  выборка  состоит из  нескольких  групп, задаваемых в  тексте  запроса оператором  Группировка.

Быстрый  просмотр выборки  запроса можно   организовать,  выполнив  два  следующих метода:

// Выгружаем все переменные запроса в таблицу значений тЗнач

запС.Выгрузить(тЗнач, 1);

// Просмотр таблицы значений

тЗнач.ВыбратьСтроку(, "Запрос  в таблице значений");

Результат см. на рис. 5.58.

Рис.  5.58.  Запрос запС,  отображенный  в таблице значений  тЗнач

Просмотр таблицы  показывает,  что  в  ней  расположены все нужные   нам  данные (кроме даты  приказа  о приеме на работу), причем сгруппированные  и  упорядоченные надлежащим  образом. Объем  выбираемых данных, способ  группировки  и  их  порядок определяется текстом  запроса.

Текст  запроса текстЗапС  содержит, во-первых, дату, задаваемую  строкой  "период с рабДат  по  рабДат".  Дата  в  этом  запросе нужна  только  для  определения  значения  периодического реквизита Оклад  и играет ту же роль, что  и метод  ИспользоватьДату при простой выборке  из справочника.  Далее  перечисляются реквизиты,  значения  которых  необходимо  разместить  в  запросе  (в  результирующей  таблице),  и  порядок выборки, устанавливаемый  операторами  Группировка.  Критерий  выбора  данных   задается   оператором Условие.

Последовательность операторов  Группировка, например

| группировка род;

| группировка имяСотр;

приводит к  созданию  вложенных   групп   данных.   Так,  в   нашем  случае  употребленные группировки отображают имеющуюся  в справочнике Сотрудники_2 иерархию данных.

В тексте  запроса можно  размещать внешние по  отношению  к запросу переменные, но только  те, к которым есть доступ  в программном компоненте,  содержащем команду  выполнения запроса

// Должны быть видны имеющиеся в тексте запроса переменные рабДат, обр и окл

запС.Выполнить(текстЗапС);

Поскольку в тексте  запроса нельзя  разместить  строку "дП  =  Справочник.Сотрудники_2.ПриказПрием.ДатаПриема;"

задающую выборку  (эти  ограничения накладывает   1С), то для  получения  даты  приема сотрудника  на  работу  в  код  введена функция  НайтиДП,  работающая  со  специально  созданным  для   нее   объектом  сСотр_1,   имеющим  разновидность   типа  Справочники.Сотрудники_2.

Так  как  текст  запроса является  символьной переменной, то для  его  формирования можно    использовать   несколько  строк,  объединяя   их   при   помощи   употребляемой со строками операцией конкатенации (сложения). Например:

// Дата для периодического реквизита Оклад  датаЗапр = "период с рабДат по рабДат;";

перемЗапр = "                               //                   Переменные запроса

| род = Справочник.Сотрудники_2.ТекущийЭлемент.Родитель;

| имяСотр = Справочник.Сотрудники_2.Наименование;

| код = Справочник.Сотрудники_2.Код;

| образование = Справочник.Сотрудники_2.Образование;

| оклад = Справочник.Сотрудники_2.Оклад;";

групЗапр = "группировка род;                  //              Группы запроса

| группировка имяСотр;";  услЗапр = " // Условие выборки

| условие  ((образование = обр) и (оклад >= окл));";

// Формируем текст запроса

текстЗапС = датаЗапр  + перемЗапр + групЗапр  + услЗапр;

Для  получения  отчета, отображенного в табл.  5.7, можно, поскольку мы  выгрузили запрос  в таблицу значений  тЗнач,  было  бы употребить  следующий  код:

// Позиционируемся перед первой строкой таблицы значений тЗнач

тЗнач.ВыбратьСтроки();

// Перебор строк таблицы значений начинается с ее первой строки пока тЗнач.ПолучитьСтроку() = 1 цикл

подр = тЗнач.Род;

если ПустоеЗначение(подр) = 1 тогда       //    Ничего не вводим

продолжить;                          //               Переход  на начало  цикла конецЕсли;

сотр = тЗнач.ИмяСотр;

// Вывод очередной строки в отчет

если ПустоеЗначение(сотр) = 1 тогда        //    Строка содержит имя подразделения

табл.ВывестиСекцию("подр");

иначе                                    //                      Строка содержит данные о сотруднике

код = тЗнач.Код;

дП = НайтиДП(сСотр_2, код); ставка = тЗнач.Оклад; табл.ВывестиСекцию("сотр");

конецЕсли; конецЦикла; // пока

Однако  для  перебора  элементов   выборки,   созданной  запросом,  в   большинстве случаев  удобнее  пользоваться методом  Группировка, принимающим  имя группы  и  получающим  очередное  значение   выборки  в   заданной  группе.   Поскольку  сразу  после выполнения  запроса он  позиционируется перед  первой своей записью, то первое употребление метода  Группировка с именем  старшей группы, например

запС.Группировка("род");

обеспечит перемещение  на первую запись выборки.

Перебор записей начинается  с первой старшей группы.  После  ее выбора можно перебрать  принадлежащие  ей  записи,  вновь употребив  метод  Группировка,  но  передав  ему в качестве  параметра имя группы, расположенной  на  следующем уровне иерархии выборки. Метод  Группировка вернет 0, если  либо  выбрана  запись другого  уровня иерархии выборки, либо выборка  исчерпана.  В  противном  случае  Группировка  возвращает число  1. Понятно, что для  перебора более  всего подходит управляющая конструкция цикл Пока, которую  мы и применили в вышеприведенной процедуре Выполнить.

Поскольку наш  запрос  имеет две вложенные  группы, род и  имяСотр,  то для  перебора их  записей  пришлось  использовать  вложенные   конструкции  Пока. Если  нужно  вывести только  значения старшей группы, то достаточно одного  цикла, например такого:

пока запС.Группировка("род") = 1 цикл подр = запС.Род; табл.ВывестиСекцию("подр");

конецЦикла; // пока

Нам  уже  понятно, что  доступ  к  отдельному компоненту  записи  выборки  запроса осуществляется  по  известной  схеме   <имя  запроса>.<имя  переменной запроса>, например

Сообщить(запС.ИмяСотр);                             // Печатаем имя сотрудника

Источник: Бартеньев О. В. 1С:Предприятие:  программирование для  всех.  Базовые объекты и расчеты на одной дискете. М.: Диалог-МИФИ, 2005. 464 с.

По теме:

  • Комментарии