Продвинутый курс. Занятие №7

Второе занятие 1-го блока продвинутого курса.

Необходимо изучить следующие главы текущего блока.
Глава 2. Обработчики событий.
Глава 3. Объектные типы данных.
Глава 4. Критерий отбора.
Глава 5. Команды.

К сожалению, у Вас недостаточно прав для просмотра этой записи. Если Вы еще не залогинены на сайте
залогиньтесь.

Если не активировали токен — посмотрите видео-инструкцию (видео N5)

Если вы залогинены, у Вас активирован токен доступа, но вы все равно видите эту запись —
напишите нам на e-mail поддержки.

комментариев 12 на “Продвинутый курс. Занятие №7”

  1. Задание выполнено.
    1. В документы поступления и реализации добавлен реквизит  “Основание” для хранения родительского документа.  Для хранения связей документов создан критерий отбора, в состав которого включен данный реквизит.
    2.  Заполнение дерева значений, иллюстрирующего структуру подчиненности документов, осуществляется с помощью рекурсивной процедуры. Для поиска подчиненных документов используется виртуальная таблица критерия отбора, полученная с помощью   запроса.  Реализована защита от зацикливания рекурсивной процедуры.

  2.  
    Задание выполнила. С заполнением реквизитов при вводе на основании сложностей не возникло. Для запоминания родительского документа создала новые реквизиты “Документ основание”, включила их в критерий отбора. В отчете рекурсивно вызываю процедуру, добавляющую новые строки в дерево значений. Для получения списка дочерних документов использую запрос к таблице критерия отбора.
     

  3. respublica 31.05.2011 в 18:05

    Задание выполнил.
    1. Добавил для документов поступления и реализации возможность ввода на основании друг друга. В обработке заполнения переношу идентичные по имени и по типу реквизиты документа и его табличных частей . Пример кода:
    <code>
    мРеквизитыМетаданные = Метаданные().Реквизиты;
    мРеквизитыДанныеЗаполнения = ДанныеЗаполнения.Метаданные().Реквизиты;
    Для Каждого Реквизит ИЗ мРеквизитыМетаданные Цикл
    мИмя = Реквизит.Имя;
    Если НЕ мРеквизитыДанныеЗаполнения.Найти(мИмя) = Неопределено
    И мРеквизитыДанныеЗаполнения[мИмя].Тип = Реквизит.Тип Тогда
    ЭтотОбъект[мИмя] = ДанныеЗаполнения[мИмя];
    КонецЕсли;
    КонецЦикла;

    </code>
    Для хранения “родительского документа” создал реквизит ДокументОснование (тип ДокументСсылка).
    2. Для построения структуры подчинености создал критерий отбора, тип ДокументСсылка, графы – реквизиты ДокументОснование. Структура подчиненности получается в результате рекурсивной функции, на каждой итерации которой добавляются ссылки, полученные в результате метода КритерииОтбора.ПодчиненныеДокументы.Найти(мСсылка). Для вывода структуры в форме документа создал спец. элемент формы (тип ДанныеФормыДерево).

  4. Домашнее задание выполнено.
    Обеспечен ввод на основании для документов поступления и реализации. При вводе на основании анализируются метаданные документа-родителя и вводимого документа. Если у документа-родителя находится реквизит с таким же именем и типом, как у вводимого документа, то осуществляется копирование. При копировании табличных частей в вводимый документ добавляются новые строки и производится аналогичная процедура сопоставления для реквизитов табличной части. Для реализации и поступления создан реквизит для хранения ссылки на документ-родитель.
    Для получения подчиненных документов создан критерий отбора. Чтобы отобразить структуру подчиненности, была создана общая команда и общая форма. Команда размещена в панели навигации форм документов поступления и реализации. На общей форме располагается дерево значений. При вызове команды в общую форму передается параметр – ссылка на документ, для которого нужно построить структуру подчиненности. В событии формы “ПриСозданииНаСервере” вызывается рекурсивная процедура, которая на каждом уровне рекурсии обращается запросом к критерию отбора для получения подчиненных документов. Чтобы дерево при отображении полностью раскрывалось, свойство “НачальноеОтображениеДерева” установлено в значение “Раскрывать все уровни”.

  5. ДЗ выполнила. Копирование однотипных реквизитов сделала через обработку заполнения, для “родительского” документа добавила реквизит “ДокОснование”. Создала критерий отбора “ДляПодчиненностиДокументов” куда вошли реквизиты ДокОснование из документов. Основываясь на данных критерия отбора для выбранного документа строю дерево дочерних документов(использую рекурсию). Вот с выводом полученной информации немного не получилось, не поняла как вывести отчет в форму текущего документа, вывела дерево через форму обработки.

  6. Задание выполнено:
    1.  В документах Поступление и Реализация создал реквизит ДокументОснование (составного типа). Добавил критерий отбора, определил состав. Также создал пару соответствующих общих команд Поступление и Реализация (группа Командная панель формы.Создать на основании, в параметрах все те же Документы.Ссылки) . В модуле команд:
    <code>
    ОткрытьФорму(“Документ.ПоступлениеТоваровИУслуг.ФормаОбъекта”, Новый Структура(“Основание”, ПараметрКоманды), ПараметрыВыполненияКоманды.Источник, ПараметрыВыполненияКоманды.Уникальность, ПараметрыВыполненияКоманды.Окно);
    </code> Для реализации соответственно Документ.РеализацияТоваровИУслуг.
    В ОбработкеЗаполнения документов при условии, что ДанныеЗаполнения соответствуют типам документов основания вставил ЗаполнитьЗначенияСвойств(ЭтотОбъект, ДанныеЗаполнения) + заполнение самого реквизита ДокументОснование. Кстати, очень долго не мог понять почему в данных заполнения было Неопределено, пришлось пошерстить форумы и, оказывается, у структуры параметров должно быть строго значение “Основание”. Где-нибудь есть список предопределенных параметров, которые можно использовать при передачи  в командах?
    2. Решение второго задания сделал аналогично тому, как в типовой конфигурации УНФ. Создал Общую команду, которая открывает общую форму СтруктураПодчиненности. В обработчике ПриСозданииНаСервере вызываю рекурсивную процедуру построения подчиненных(на основании) документов. При построении текста запроса по подчиненным документам опирался на созданный ранее критерий отбора.
    А вообще, реально ли обойтись одним запросом и  собрать весь перечень подчиненных документов любой структуры и неопределенной степенью  вложенности?

    • Все-таки не реально обойтись одним запросом при неопределенном уровне вложенности.
      Поскольку придется организовывать либо рекурсивный, либо циклический алгоритм.
      Вообще циклы можно организовывать на стороне СУБД, но только платформа “1С:Предприятие 8” не предоставляет такой возможности.

  7. Задание выполнил
    1.Добавил реквизит ДокументОснование в документы поступления и реализации и указал в свойствах возможные документы для ввода на основании.
    Для реализации заполнения создал подписку на событие ОбработкаЗаполнения для этих двух документов. Для заполнения реквизитов шапки использую возможности работы с метаданными. Для заполнения тч Товары использую метод табличной части Загрузить, который при загрузке сопоставляет имена колонок.
    2.Для формирования структуры подчиненности создал критерий отбора ВзаимосвязанныеДокументы указал необходимые типы данных и состав.А так же общую команду Структура подчиненности. В качестве группы указал Панель навигации формы.Перейти, в типе параметров команды выбрал оба наших документа. В обработке команды вызывается общая форма, на которой выводится дерево подчиненности в виде дерева значений. Для элемента формы дерева свойство начальное отображение выставил в Раскрывать все уровни.
    Поскольку в задании указано только построение дерева дочерних документов, то с родительскими документами не стал ничего делать.

  8. В части ввода на основании затруденений не было. Документ-основание записываем в дополнительный реквизит “Основание”. Его можно не выводить на форму, или установить свойство “ТолькоПросмотр”. Обеспечим таким образом отсутствие взаимных ссылок документов при ручном вводе, избавимся от зацикливания при формировании дерева связанных документов. Настроим критерий отбора “СвязанныеДокументы”, включив в состав реквизиты “Основание”.
    Добавим общую форму “СтруктураПодчиненности” для формирования отчета. В команде “СтруктураПодчиненности” документа открываем форму отчета. Ссылку на документ передаем в параметры формы отчета, при создании на сервере сохраняем значение в реквизите формы “Ссылка” и вызываем процедуру  СформироватьОтчетНаСервере(). Добавим реквизит формы ТабличныйДокумент для вывода отчета. При формировании дерева документов для наглядности каждый уровень выводим с отступом.
    Процедура СформироватьОтчетНаСервере()
    НомерСтроки=1;
    Отступ=0;
    ТабДок.Очистить();
    Область=ТабДок.Область(НомерСтроки,1);
    Область.Текст=Ссылка;
    ВывестиСтроку(Ссылка, НомерСтроки, Отступ);
    ТабДок.Показать();
    КонецПроцедуры
    Процедура ВывестиСтроку(СсылкаНаДокумент,НомерСтроки,Отступ)
    Запрос = Новый Запрос;
    Запрос.Текст =
    “ВЫБРАТЬ
    | СвязанныеДокументы.Ссылка
    |ИЗ
    | КритерийОтбора.СвязанныеДокументы(&Ссылка) КАК СвязанныеДокументы”;
    Запрос.УстановитьПараметр(“Ссылка” , СсылкаНаДокумент);
    Результат=Запрос.Выполнить();
    Если Не Результат.Пустой() тогда
    Выборка = Результат.Выбрать();
    ТабДок.НачатьГруппуСтрок(СсылкаНаДокумент,Истина);
    Отступ=Отступ+3;
    Пока Выборка.Следующий() Цикл
    НомерСтроки=НомерСтроки+1;
    Область=ТабДок.Область(НомерСтроки,1);
    Область.Текст=Выборка.Ссылка;
    Область.Отступ=Отступ;
    ТабДок.НачатьГруппуСтрок(Выборка.Ссылка,Истина);
    ВывестиСтроку(Выборка.Ссылка,НомерСтроки,Отступ);
    ТабДок.ЗакончитьГруппуСтрок();
    КонецЦикла;
    ТабДок.ЗакончитьГруппуСтрок();
    Отступ=Отступ-3;
    КонецЕсли;
    КонецПроцедуры

    Также добавим команду формы “Обновить” для обновления данных в открытом документе.
    P.S. Кажется, я неточно поняла, в каком виде выводить отчет, но результат в общем тот же.

  9. Задание выполнено.
    В документах поступления и реализации товаров создан реквизит ДокументОснование. В обработчиках ОбработкаЗаполнения вызывается процедура общего серверного модуля:
    <code>
    Процедура ЗаполнитьДанныеНаОсновании(Документ, ДанныеЗаполнения, СтандартнаяОбработка) Экспорт
    Попытка
    Если НЕ Метаданные.Документы.Содержит(ДанныеЗаполнения.Метаданные()) Тогда
    Возврат;
    КонецЕсли;
    Исключение
    Возврат;
    КонецПопытки;

    СтандартнаяОбработка = Ложь;
    ЗаполнитьЗначенияСвойств(Документ, ДанныеЗаполнения, ,”Номер,Дата,ПометкаУдаления,Проведен”);
    Документ.ДокументОснование = ДанныеЗаполнения;

    ТабличныеЧасти = ДанныеЗаполнения.Метаданные().ТабличныеЧасти;
    ТабличныеЧастиДок = Документ.Метаданные().ТабличныеЧасти;

    Для каждого ТЧ Из ТабличныеЧасти Цикл
    Если ТабличныеЧастиДок.Найти(ТЧ.Имя)<>Неопределено Тогда
    Документ[ТЧ.Имя].Загрузить(ДанныеЗаполнения[ТЧ.Имя].Выгрузить());
    КонецЕсли;
    КонецЦикла;
    КонецПроцедуры
    </code>
    Таким образом копируются значения всех совпадающих реквизитов и состав табличных частей.
    Создана параметризованная общая команда СтруктураПодчиненности, группа команды указана как “Панель навигации формы.См. также”. Тип параметра – ссылки на 2 документа (поступление и реализация). Также создана общая форма, которая открывается в обработчике команды. Ссылка на документ передается в параметрах формы. В самой форме создан реквизит типа ДеревоЗначений с 1 колонкой Документ. В свойствах элемента формы для дерева параметр НачальноеОтображениеДерева установлен в “Раскрывать все уровни”. Заполнение дерева происходит при открытии формы.
    Немного расширил задание – в дерево выводятся не только подчиненные документы, но и вышестоящие с полной структурой, т.е. всегда отображается полное дерево, независимо от того, на каком уровне и в какой ветке находится текущий документ. При этом строка дерева, соответствующая текущему документу выделена.
    Код модуля формы:
    <code>
    &НаСервере
    Перем ИдСтроки, ИдСтрокиТекДок;

    &НаСервере
    Процедура ДобавитьДокумент(Документ, Строки)
    СтрокаДок = Строки.Добавить();
    СтрокаДок.Документ = Документ;
    ИдСтроки=ИдСтроки+1;
    Если Документ = Параметры.Документ Тогда
    ИдСтрокиТекДок = ИдСтроки;
    КонецЕсли;

    Массив = КритерииОтбора.ДокументОснование.Найти(Документ);
    Для каждого Док Из Массив Цикл
    ДобавитьДокумент(Док, СтрокаДок.Строки);
    КонецЦикла;
    КонецПроцедуры

    &НаСервере
    Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    Корень = Параметры.Документ;
    Попытка
    Пока ЗначениеЗаполнено(Корень.ДокументОснование) Цикл
    Корень = Корень.ДокументОснование;
    КонецЦикла;
    Исключение
    КонецПопытки;

    ИдСтрокиТекДок = 0;
    ИдСтроки = -1;

    Дерево = РеквизитФормыВЗначение(“СтруктураПодчиненности”);
    ДобавитьДокумент(Корень, Дерево.Строки);
    ЗначениеВРеквизитФормы(Дерево, “СтруктураПодчиненности”);
    Элементы.СтруктураПодчиненности.ТекущаяСтрока = ИдСтрокиТекДок;
    КонецПроцедуры
    </code>

  10. Готово! Создан реквизит “Основание” для поступления и реализации.
    Для заполнение в общем модуле создана процедура
    Процедура ЗаполнениеПриВводеНаОсновании(Источник, Приемник) Экспорт

    МетаданныеИсточника = Источник.Метаданные();
    МетаданныеПриемника = Приемник.Метаданные();

    ЗаполнитьЗначенияСвойств(Приемник, Источник,,”Номер, Дата, ПометкаУдаления, Проведен, Основание”);

    Для Каждого ТабличнаяЧасть из МетаданныеИсточника.ТабличныеЧасти Цикл

    Если НЕ МетаданныеПриемника.ТабличныеЧасти.Найти(ТабличнаяЧасть.Имя) = Неопределено Тогда
    ТЗИсточника = Источник[ТабличнаяЧасть.Имя].Выгрузить();
    Приемник[ТабличнаяЧасть.Имя].Загрузить(ТЗИсточника);
    КонецЕсли;

    КонецЦикла;

    Если МетаданныеИсточника.Реквизиты.Найти(“Основание”)<> Неопределено и МетаданныеПриемника.Реквизиты.Найти(“Основание”)<> Неопределено Тогда
    Приемник.Основание = Источник;
    КонецЕсли;

    КонецПроцедуры
    Критерий отбора создан. Дерево заполняется через рекурсию
    Процедура ВывестиПодчиненные(Основание, Строка)

    Запрос = Новый Запрос;
    Запрос.Текст =
    “ВЫБРАТЬ
    |    СтруктураПодчиненности.Ссылка
    |ИЗ
    |    КритерийОтбора.СтруктураПодчиненности(&Основание) КАК СтруктураПодчиненности”;

    Запрос.УстановитьПараметр(“Основание”, Основание);

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

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

    Пока ВыборкаДетальныеЗаписи.Следующий() Цикл

    Основание = ВыборкаДетальныеЗаписи.Ссылка;

    НоваяСтрока = Строка.Строки.Добавить();
    НоваяСтрока.Ссылка = Основание;

    ВывестиПодчиненные(Основание, НоваяСтрока);

    КонецЦикла;

    КонецПроцедуры // ВывестиПодчиненные()

    Для элемента формы указано, что дерево должно разворачиваться.

  11. Кононов Сергей 25.05.2011 в 11:01

     
    Задание выполнил.
    1. В первой части задания(обеспечить ввод документов на основании) я решил конструктором ввода на основании. Перед этим я добавил каждому документу реквизит ДокументОснование составного типа указанных документов в ТЗ. И в обработке заполнения так же сохраняю документ на основании которого введен.
    2. Создал критерий отбора состав которого указал данные реквизиты двух документов ДокументОснование.
    3. Так как команда вывода структуры подчиненности должна быть в обоих документах, то я создал общую параметризуемую команду СтруктураПодчиненности, тип параметров которой были ссылки на наши два документа (составной тип). Группу для этой общей команды я указал “Панель навигации формы.Важное”.
    Для отображения дерева подчиненности, я создал общую форму с реквизитами РезультатОтбора типа дерево значений (для вывода нашего дерева подчиненности) и реквизит СсылкаНаОбъект – типа составной ссылки на наши два документа, в этот реквизит мы будем передавать нашу ссылку. Решение задачи построил след. образом: при выполнении команды передаю в общую форму ссылку на документ, далее отбираю критерием отбора все документы удовлетворяющие моей ссылке и вывожу поочередно каждый в дерево, потом для каждого выводимого документа я опять выполняю поиск критерием отбора и снова вывожу уже подчиненные подчиненных. Это я организовал с помощью рекурсивной процедуры. Приведу код выполнения заполнения дерева, процедуры приведены по мере ледования их вызовов:
    <cod>
    &НаСервере
    Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

    Параметры.Свойство(“Документ”, СсылкаНаДокумент);

    РезультатДерево = СформироватьДеревоПодчиненныхДокументов(СсылкаНаДокумент);

    ЗначениеВРеквизитФормы(РезультатДерево, “РезультатОтбора”);

    Элементы.РезультатОтбора.НачальноеОтображениеДерева = НачальноеОтображениеДерева.РаскрыватьВсеУровни;

    КонецПроцедуры
    &НаСервереБезКонтекста
    Функция СформироватьДеревоПодчиненныхДокументов(СсылкаНаДокумент)

    Дерево = Новый ДеревоЗначений;
    Дерево.Колонки.Добавить(“Документ”);

    СтрокаДерева = Дерево.Строки.Добавить();
    СтрокаДерева.Документ = СсылкаНаДокумент;

    ДобавитьПодчиненные(СтрокаДерева, СсылкаНаДокумент);

    Возврат Дерево;

    КонецФункции
    &НаСервереБезКонтекста
    Процедура ДобавитьПодчиненные(СтрокаДерева, СсылкаНаДокумент)

    Запрос = Новый Запрос;
    Запрос.Текст = “ВЫБРАТЬ РАЗРЕШЕННЫЕ
    | ОтборПоДокументам.Ссылка
    |ИЗ
    | КритерийОтбора.ОтборПоДокументам(&ЗначениеКритерияОтбора) КАК ОтборПоДокументам”;

    Запрос.УстановитьПараметр(“ЗначениеКритерияОтбора”, СсылкаНаДокумент);

    Таблица = Запрос.Выполнить().Выгрузить();
    Если Таблица.Количество()=0 Тогда
    Возврат;
    КонецЕсли;

    Для каждого Строка Из Таблица Цикл
    НоваяСтрокаДерева = СтрокаДерева.Строки.Добавить();
    НоваяСтрокаДерева.Документ = Строка.Ссылка;
    ДобавитьПодчиненные(НоваяСтрокаДерева, Строка.Ссылка);

     
    Задание выполнил.
    1. В первой части задания(обеспечить ввод документов на основании) я решил конструктором ввода на основании. Перед этим я добавил каждому документу реквизит ДокументОснование составного типа указанных документов в ТЗ. И в обработке заполнения так же сохраняю документ на основании которого введен.
    2. Создал критерий отбора состав которого указал данные реквизиты двух документов ДокументОснование.
    3. Так как команда вывода структуры подчиненности должна быть в обоих документах, то я создал общую параметризуемую команду СтруктураПодчиненности, тип параметров которой были ссылки на наши два документа (составной тип). Группу для этой общей команды я указал “Панель навигации формы.Важное”.
    Для отображения дерева подчиненности, я создал общую форму с реквизитами РезультатОтбора типа дерево значений (для вывода нашего дерева подчиненности) и реквизит СсылкаНаОбъект – типа составной ссылки на наши два документа, в этот реквизит мы будем передавать нашу ссылку. Решение задачи построил след. образом: при выполнении команды передаю в общую форму ссылку на документ, далее отбираю критерием отбора все документы удовлетворяющие моей ссылке и вывожу поочередно каждый в дерево, потом для каждого выводимого документа я опять выполняю поиск критерием отбора и снова вывожу уже подчиненные подчиненных. Это я организовал с помощью рекурсивной процедуры. Приведу код выполнения заполнения дерева, процедуры приведены по мере ледования их вызовов:
     
    <cod>
     
    &НаСервере
    Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

    Параметры.Свойство(“Документ”, СсылкаНаДокумент);

    РезультатДерево = СформироватьДеревоПодчиненныхДокументов(СсылкаНаДокумент);

    ЗначениеВРеквизитФормы(РезультатДерево, “РезультатОтбора”);

    Элементы.РезультатОтбора.НачальноеОтображениеДерева = НачальноеОтображениеДерева.РаскрыватьВсеУровни;

    КонецПроцедуры
     
    &НаСервереБезКонтекста
    Функция СформироватьДеревоПодчиненныхДокументов(СсылкаНаДокумент)

    Дерево = Новый ДеревоЗначений;
    Дерево.Колонки.Добавить(“Документ”);

    СтрокаДерева = Дерево.Строки.Добавить();
    СтрокаДерева.Документ = СсылкаНаДокумент;

    ДобавитьПодчиненные(СтрокаДерева, СсылкаНаДокумент);

    Возврат Дерево;

    КонецФункции
     
    &НаСервереБезКонтекста
    Процедура ДобавитьПодчиненные(СтрокаДерева, СсылкаНаДокумент)

    Запрос = Новый Запрос;
    Запрос.Текст = “ВЫБРАТЬ РАЗРЕШЕННЫЕ
    | ОтборПоДокументам.Ссылка
    |ИЗ
    | КритерийОтбора.ОтборПоДокументам(&ЗначениеКритерияОтбора) КАК ОтборПоДокументам”;

    Запрос.УстановитьПараметр(“ЗначениеКритерияОтбора”, СсылкаНаДокумент);

    Таблица = Запрос.Выполнить().Выгрузить();
    Если Таблица.Количество()=0 Тогда
    Возврат;
    КонецЕсли;

    Для каждого Строка Из Таблица Цикл
    НоваяСтрокаДерева = СтрокаДерева.Строки.Добавить();
    НоваяСтрокаДерева.Документ = Строка.Ссылка;
    ДобавитьПодчиненные(НоваяСтрокаДерева, Строка.Ссылка);
    КонецЦикла;
     
    КонецПроцедуры
     
    </cod>