Структуры в 1С

Получение списка родительских и подчиненных документов из структуры подчиненности

Структуру подчиненности документа можно увидеть, запустив из документа общую форму «ФормаСтруктурыПодчиненности». Но как получить связанные документы для обработки данных? Я взял процедуры из модуля этой формы, немного поколдовал, и превратил их в пару функций, возвращающих список документов из структуры подчиненности нужного документа. Нужно отметить, что иерархии подчиненности в результатах работы функций нет, в отличие от процедур, работающих с деревом значений в форме. Вот хочу поделиться результатом со всеми, так как мне самому бывает приятно заполучить иногда кусочек готового кода, который впоследствие можно использовать для решения своих задач.

Функция ПолучитьРодительскиеДокументы(ДокументСсылка, СписокСвязанныхДокументов = Неопределено, мУжеВСписке = Неопределено) Экспорт Если СписокСвязанныхДокументов = Неопределено Тогда СписокСвязанныхДокументов = Новый СписокЗначений; КонецЕсли; Если мУжеВСписке = Неопределено Тогда мУжеВСписке = Новый Соответствие; КонецЕсли; МетаданныеДокумента = ДокументСсылка.Метаданные(); СписокРеквизитов = Новый СписокЗначений; Для Каждого Реквизит ИЗ МетаданныеДокумента.Реквизиты Цикл ТипыРеквизита = Реквизит.Тип.Типы(); Для Каждого ТекущийТип ИЗ ТипыРеквизита Цикл МетаданныеРеквизита = Метаданные.НайтиПоТипу(ТекущийТип); Если МетаданныеРеквизита<>Неопределено И Метаданные.Документы.Содержит(МетаданныеРеквизита) И ПравоДоступа(«Чтение», МетаданныеРеквизита) Тогда Попытка ЗначениеРеквизита = ДокументСсылка; Исключение Прервать; КонецПопытки; ЕСли ЗначениеРеквизита<>Неопределено И НЕ ЗначениеРеквизита.Пустая() И ТипЗнч(ЗначениеРеквизита) = ТекущийТип И мУжеВСписке = Неопределено И СписокРеквизитов.НайтиПоЗначению(ДокументСсылка) = Неопределено Тогда Попытка СписокРеквизитов.Добавить(ЗначениеРеквизита,Формат(ЗначениеРеквизита.Дата,»ДФ=yyyyMMddЧЧММсс»)); Исключение ОтладкаТекстОшибки = ОписаниеОшибки(); КонецПопытки; КонецЕсли; КонецЕсли; КонецЦикла; КонецЦикла; Для Каждого ТЧ Из МетаданныеДокумента.ТабличныеЧасти Цикл СтрРеквизитов = «»; Попытка СодержимоеТЧ = ДокументСсылка.Выгрузить(); Исключение Прервать; КонецПопытки; Для Каждого Реквизит ИЗ ТЧ.Реквизиты Цикл ТипыРеквизита = Реквизит.Тип.Типы(); Для Каждого ТекущийТип ИЗ ТипыРеквизита Цикл МетаданныеРеквизита = Метаданные.НайтиПоТипу(ТекущийТип); Если МетаданныеРеквизита<>Неопределено И Метаданные.Документы.Содержит(МетаданныеРеквизита) И ПравоДоступа(«Чтение», МетаданныеРеквизита) Тогда СтрРеквизитов = СтрРеквизитов + ?(СтрРеквизитов = «», «», «, «) + Реквизит.Имя; Прервать; КонецЕсли; КонецЦикла; КонецЦикла; СодержимоеТЧ.Свернуть(СтрРеквизитов); Для Каждого КолонкаТЧ ИЗ СодержимоеТЧ.Колонки Цикл Для Каждого СтрокаТЧ ИЗ СодержимоеТЧ Цикл Попытка ЗначениеРеквизита = СтрокаТЧ; Исключение Продолжить; КонецПопытки; МетаданныеЗначения = Метаданные.НайтиПоТипу(ТипЗнч(ЗначениеРеквизита)); Если МетаданныеЗначения = Неопределено Тогда // базовый тип Продолжить; КонецЕсли; ЕСли ЗначениеРеквизита<>Неопределено И НЕ ЗначениеРеквизита.Пустая() И Метаданные.Документы.Содержит(МетаданныеЗначения) И мУжеВСписке = Неопределено Тогда Если СписокРеквизитов.НайтиПоЗначению(ЗначениеРеквизита) = Неопределено Тогда Попытка СписокРеквизитов.Добавить(ЗначениеРеквизита,Формат(ЗначениеРеквизита.Дата,»ДФ=yyyyMMddЧЧММсс»)); Исключение ОтладкаТекстОшибки = ОписаниеОшибки(); КонецПопытки; КонецЕсли; КонецЕсли; КонецЦикла; КонецЦикла; КонецЦикла; мУжеВСписке.Вставить(ДокументСсылка, Истина); Для Каждого СтрСЗ Из СписокРеквизитов Цикл СписокСвязанныхДокументов = ПолучитьРодительскиеДокументы(СтрСЗ.Значение, СписокСвязанныхДокументов, мУжеВСписке); КонецЦикла; Запрос = Новый Запрос(«ВЫБРАТЬ РАЗРЕШЕННЫЕ Ссылка | ИЗ Документ.»+МетаданныеДокумента.Имя + » ГДЕ Ссылка = &Ссылка»); Запрос.УстановитьПараметр(«Ссылка», ДокументСсылка); Выборка = Запрос.Выполнить().Выбрать(); ЕСли Выборка.Следующий() Тогда СписокСвязанныхДокументов.Добавить(Выборка.Ссылка); Иначе СписокСвязанныхДокументов.Добавить(ДокументСсылка); КонецЕсли; Возврат СписокСвязанныхДокументов; КонецФункции Функция ПолучитьПодчиненныеДокументы(ДокументСсылка, СписокСвязанныхДокументов = Неопределено, мУжеВСписке = Неопределено) Экспорт Если СписокСвязанныхДокументов = Неопределено Тогда СписокСвязанныхДокументов = Новый СписокЗначений; КонецЕсли; Если мУжеВСписке = Неопределено Тогда мУжеВСписке = Новый Соответствие; КонецЕсли; Таблица = ПолныеПрава.ПолучитьВыборкуПоКритериюОтбора(«СвязанныеДокументы», ДокументСсылка); КэшПоТипамДокументов = Новый Соответствие; Для Каждого СтрокаТаблицы ИЗ Таблица Цикл МетаданныеДокумента = СтрокаТаблицы.Ссылка.Метаданные(); Если Не ПравоДоступа(«Чтение», МетаданныеДокумента) Тогда Продолжить; КонецЕсли; ИмяДокумента = МетаданныеДокумента.Имя; СинонимДокумента = МетаданныеДокумента.Синоним; СтруктураТипа = КэшПоТипамДокументов; Если СтруктураТипа = Неопределено Тогда СтруктураТипа = Новый Структура(«Синоним, МассивСсылок», СинонимДокумента, Новый Массив); КэшПоТипамДокументов.Вставить(ИмяДокумента, СтруктураТипа); КонецЕсли; СтруктураТипа.МассивСсылок.Добавить(СтрокаТаблицы.Ссылка); КонецЦикла; ЕСли КэшПоТипамДокументов.Количество() = 0 Тогда Возврат СписокСвязанныхДокументов; КонецЕсли; ТекстЗапросаНачало = «ВЫБРАТЬ РАЗРЕШЕННЫЕ * ИЗ («; ТекстЗапросаКонец = «) КАК ПодчиненныеДокументы «; Запрос = Новый Запрос; Для Каждого КлючИЗначение ИЗ КэшПоТипамДокументов Цикл Запрос.Текст = Запрос.Текст + ?(Запрос.Текст = «», » |ВЫБРАТЬ «, » |ОБЪЕДИНИТЬ ВСЕ |ВЫБРАТЬ») + » |Ссылка |ИЗ Документ.» + КлючИЗначение.Ключ + » |ГДЕ Ссылка В (&» + КлючИЗначение.Ключ + «)»; Запрос.УстановитьПараметр(КлючИЗначение.Ключ, КлючИЗначение.Значение.МассивСсылок); КонецЦикла; Запрос.Текст = ТекстЗапросаНачало + Запрос.Текст + ТекстЗапросаКонец; Выборка = Запрос.Выполнить().Выбрать(); Пока Выборка.Следующий() Цикл Если мУжеВСписке = Неопределено Тогда СписокСвязанныхДокументов.Добавить(Выборка.Ссылка); мУжеВСписке.Вставить(Выборка.Ссылка, Истина); СписокСвязанныхДокументов = ПолучитьПодчиненныеДокументы(Выборка.Ссылка, СписокСвязанныхДокументов, мУжеВСписке); КонецЕсли; КонецЦикла; Возврат СписокСвязанныхДокументов; КонецФункции

Основной параметр функций «ДокументСсылка» — обязательный. Это ссылка на документ, для которого будем получать родительские (подчиненные) документы.

Также может быть полезен в работе параметр «СписокСвязанныхДокументов». Он не является обязательным, и используется для хранения списка документов из структуры подчиненности. Его можно задать, если, например, нужен общий список и родительских, и подчиненных документов.

Примеры:

1. Получение общего списка родительских документов двух и более документов.

СписокСвязанныхДокументов = ПолучитьРодительскиеДокументы(ДокументСсылка1); СписокСвязанныхДокументов = ПолучитьРодительскиеДокументы(ДокументСсылка2, СписокСвязанныхДокументов);

2. Получение общего списка и родительских, и подчиненных документов.

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

Дополнение:

Структура в 1С 8.3 — работа на примерах

Структура в 1С 8.3 это динамический набор данных (коллекция значений), каждый элемент которой состоит из пары «Ключ» и «Значение». Ключи структуры уникальны, поэтому ими можно идентифицировать значения. Ключ структуры должен иметь строковый тип данных и отвечать требованиям к именам переменных. К значениям структуры можно обращаться как к свойствам объекта, при этом ключ используется как имя свойства.

Создание структуры

Автомобиль = Новый Структура(«Марка,ДатаВыпуска,ПробегКМ»,»BMW»,Дата(‘20190101’),25000);

Результат:

Добавление элементов, установка значений

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

Автомобиль.Вставить(«Цвет»,»Белый»);//Добавили ключ и значение. Автомобиль.Вставить(«Цвет»,»Чёрный»);// Т.к. ключ «Цвет» уже существует, произошла замена значения. //Другие способы для установки значений Автомобиль.Цвет = «Белый»;//Для ключа «Цвет» установили значение «Белый» Автомобиль = «Чёрный»;//Для ключа «Цвет» установили значение «Чёрный»

Как узнать количество элементов структуры

КоличествоЭлементов = Автомобиль.Количество();

Обход элементов структуры

Для Каждого Элемент Из Автомобиль Цикл Ключ = Элемент.Ключ; Значение = Элемент.Значение; Сообщить(Ключ + » — » + Значение); КонецЦикла;

Проверить ключ структуры на существование

// Если ключ существует, выражение вернёт «ИСТИНА» иначе вернёт «ЛОЖЬ» Автомобиль.Свойство(«Марка»);

Получить значение элемента структуры по ключу

ЗначениеЭлемента = Неопределено; Автомобиль.Свойство(«Марка «,ЗначениеЭлемента);

Удалить элемент структуры

Автомобиль.Удалить(«Цвет «);

Удалить все элементы структуры

Автомобиль.Очистить();

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

&НаКлиенте Процедура СтруктураВТЗ(Команда) РасписаниеДня = Новый Структура(); РасписаниеДня.Вставить(«Начало»,»08:00″); РасписаниеДня.Вставить(«Обед»,»12:00″); РасписаниеДня.Вставить(«Конец»,»17:00″); ТаблицаЗнач = СтруктураВТЗНаСервере(РасписаниеДня); КонецПроцедуры &НаСервере Функция СтруктураВТЗНаСервере(РасписаниеДня) ТЗ = Новый ТаблицаЗначений; ТЗ.Колонки.Добавить(«Период»); ТЗ.Колонки.Добавить(«Время»); Для Каждого КлючИЗначение из РасписаниеДня Цикл НоваяСтрока = ТЗ.Добавить(); НоваяСтрока.Период = КлючИЗначение.Ключ; НоваяСтрока.Время = КлючИЗначение.Значение; КонецЦикла; Возврат ТЗ;

КонецФункции

Наша команда предоставляет услуги по консультированию, настройке и внедрению 1С.
Связаться с нами можно по телефону +7 499 350 29 00.
Услуги и цены можно увидеть по .
Будем рады помочь Вам!

Результат:

Как скопировать структуру

Пример №1

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

Пример №2

Способ работает в рамках одной информационной базы.

&НаКлиенте Процедура СкопироватьСтруктуру2(Команда) Структура = Новый Структура(); Структура.Вставить(«Фамилия»,»Петров»); Структура.Вставить(«Имя»,»Пётр»); Структура.Вставить(«Отчество»,»Петрович»); КопияСтруктуры = СкопироватьСтруктуруНаСервере(Структура); КонецПроцедуры &НаСервере Функция СкопироватьСтруктуруНаСервере(Структура) КопияСтруктуры = ЗначениеИзСтрокиВнутр(ЗначениеВСтрокуВнутр(Структура)); Возврат КопияСтруктуры; КонецФункции

Пример №3

&НаКлиенте Процедура СкопироватьСтруктуру3(Команда) Структура = Новый Структура(); Структура.Вставить(«Фамилия»,»Петров»); Структура.Вставить(«Имя»,»Пётр»); Структура.Вставить(«Отчество»,»Петрович»); КопияСтруктуры = Новый ФиксированнаяСтруктура(Структура); КонецПроцедуры

В примере №3 структура будет скопирована в неизменную (фиксированную) структуру. Для такого вида структур не доступны методы Вставить(), Удалить(), Очистить(). Если требуется изменить фиксированную структуру, её необходимо скопировать в обычную.

ОбычнаяСтруктура = Новый Структура(ФиксированнаяСтруктура);

1C обратиться к документу-основанию для вывода печатной формы

Несколько замечаний по коду:

  1. ЗаявкаНаДоставку.Ссылка В (&Ссылка) — бессмысленно использовать В, если в параметре — один документ. ЗаявкаНаДоставку.Ссылка = &Ссылка.

  2. Во втором запросе нет параметра Ссылка, а он зачем-то устанавливается. Зато не устанавливается нужный параметр ДокументОснование.

  3. Старайтесь все данные, которые нужно получить, получать в одном запросе. Если у Вас совсем разные данные в запросах — делайте несколько, но в пакетном запросе. Это повышает быстродействие за счёт уменьшения количества обращений к базе данных.

  4. Ответ на ваш комментарий — да, чтобы документ-основание был у другого документа, нужно создать реквизит в этом документе и вам нужно самостоятельно в коде позаботиться о том, чтобы этот реквизит заполнялся.

  5. Без полного описания того, что вы хотите, сложно вам помочь. Какие данные должны получаться из документа, а какие — из его основания? Какая между ними взаимосвязь? Общая схема запроса примерно отвечающего вашим условиям:

ВЫБРАТЬ ВозвратДенег.Ссылка КАК ДокументВозвратДенег, ВозвратДенег.Валюта КАК Валюта, ВозвратДенег.Контрагент КАК Контрагент, ВозвратДенег.Дата, ДенежныеРасходыРасходы.СтатьяРасходов, ДенежныеРасходыРасходы.Сумма, ДенежныеРасходыРасходы.Ссылка КАК ДокументДенежныеРасходы ИЗ Документ.ВозвратДенег КАК ВозвратДенег ЛЕВОЕ СОЕДИНЕНИЕ Документ.ДенежныеРасходы.Расходы КАК ДенежныеРасходыРасходы ПО ВозвратДенег.ДокументОснование = ДенежныеРасходыРасходы.Ссылка ИТОГИ МАКСИМУМ(Валюта), МАКСИМУМ(Контрагент) ПО ДокументВозвратДенег

Пояснения — ВозвратДенег здесь — это документ, а ДенежныеРасходы — это основание. Ссылка на основание хранится в реквизите ДокументОснование — вы видите это в условии связи. Итоги здесь для того, чтобы получить двухуровневое дерево — на верхнем уровне будет документ ВозвратДенег и его реквизиты. Обратите внимание — все его реквизиты указаны в разделе ИТОГИ. Это для того, чтобы они выводились на верхнем уровне. Остальные реквизиты — реквизиты документа-основания, будут находиться на втором уровне дерева. Обход делается так:

РезультатЗапроса = Запрос.Выполнить(); ВыборкаДокументВозвратДенег = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); Пока ВыборкаДокументВозвратДенег.Следующий() Цикл // Вставить обработку выборки ВыборкаДокументВозвратДенег ВыборкаДетальныеЗаписи = ВыборкаДокументВозвратДенег.Выбрать(); Пока ВыборкаДетальныеЗаписи.Следующий() Цикл // Вставить обработку выборки ВыборкаДетальныеЗаписи КонецЦикла; КонецЦикла;

Оставить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *