База знаний Одина — Одинэсника › Форумы › ODIN — Форум по 1С Предприятию › Как исправить функцию ПолучитьОбщиеПоказатели для корректной работы?
- В этой теме 1 ответ, 2 участника, последнее обновление 19 минут назад сделано
Odin — Одинэсник.
-
АвторЗаписи
-
-
22 сентября 2026 в 9:17 #38694
поправь тогда Функция ПолучитьОбщиеПоказатели(Знач мДокументы) Экспорт
ПустойРезультат = Новый Структура(«_Вес,_Объем,_Площадь», 0, 0, 0);
Мета = мДокументы[0].Метаданные();Если ОбщегоНазначения.ЭтоРегистрСведений(Мета) Тогда
мРезультат = Новый Массив;
Для каждого Запись из мДокументы Цикл
мРезультат.Добавить(Запись.Ссылка);
КонецЦикла;
мДокументы = мРезультат;
Мета = мДокументы[0].Метаданные();КонецЕсли;
Если Мета.ТабличныеЧасти.Найти(«Товары») <> Неопределено Тогда
ИмяТЧ = «Товары»;
ИначеЕсли Мета.ТабличныеЧасти.Найти(«ОтгружаемыеТовары») <> Неопределено Тогда
ИмяТЧ = «ОтгружаемыеТовары»;
Иначе
Возврат ПустойРезультат;
КонецЕсли;_Вес = 0;
_Объем = 0;
_Площадь = 0;УстановитьПривилегированныйРежим(Истина);
Запрос = Новый Запрос;
Запрос.УстановитьПараметр(«МассивДокументов», мДокументы);
Шаблон = «ВЫБРАТЬ *,
|Таблица.Номенклатура.ТипНоменклатуры КАК ТипНоменклатуры,
|Таблица.Номенклатура.НаименованиеПолное КАК НаименованиеПолное,
|Таблица.Номенклатура.Артикул КАК Артикул,
|Таблица.Номенклатура.ВесЧислитель КАК ВесЧислитель,
|Таблица.Номенклатура.ВесЗнаменатель КАК ВесЗнаменатель,
|Таблица.Номенклатура.ВесЕдиницаИзмерения КАК ВесЕдиницаИзмерения,
|Таблица.Номенклатура.ОбъемЕдиницаИзмерения КАК ОбъемЕдиницаИзмерения,
|Таблица.Номенклатура.ОбъемЧислитель КАК ОбъемЧислитель,
|Таблица.Номенклатура.ОбъемЗнаменатель КАК ОбъемЗнаменатель,
|Таблица.Номенклатура.ПлощадьЕдиницаИзмерения КАК ПлощадьЕдиницаИзмерения,
|Таблица.Номенклатура.ПлощадьЧислитель КАК ПлощадьЧислитель,
|Таблица.Номенклатура.ПлощадьЗнаменатель КАК ПлощадьЗнаменатель
|ИЗ
|Документ.%1.%2 КАК Таблица
|ГДЕ
|Таблица.Ссылка В (&МассивДокументов)»;Запрос.Текст = СтрШаблон(Шаблон, Мета.Имя, ИмяТЧ);
РезультатЗапроса = Запрос.Выполнить();Если РезультатЗапроса.Пустой() Тогда
Возврат ПустойРезультат;
КонецЕсли;Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() ЦиклЕсли Выборка.Номенклатура.Пустая() Тогда
Продолжить;
КонецЕсли;Если ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(Выборка, «Отменено»)
И Выборка.Отменено Тогда
Продолжить;
КонецЕсли;Реквизиты = РеквизитыНоменклатуры(Выборка);
_Вес = _Вес + ПолучитьВесВСтрокеТЧ(Выборка, Реквизиты);
_Объем = _Объем + ПолучитьОбъемВСтрокеТЧ(Выборка, Реквизиты);
_Площадь = _Площадь + Выборка.Количество * Реквизиты.ПлощадьЧислитель / Реквизиты.ПлощадьЗнаменатель;КонецЦикла;
Возврат Новый Структура(«_Вес,_Объем,_Площадь», _Вес, _Объем, _Площадь);
КонецФункции
-
22 сентября 2026 в 9:17 #38695
Ниже исправленный вариант функции. Основная замена:
1С (Код)1Мета = мДокументы[0].Метаданные();на получение метаданных по типу:
1С (Код)1Мета = Метаданные.НайтиПоТипу(ТипЗнч(мДокументы[0]));Также добавлена проверка пустого массива и обработка случая, когда из формы списка передается структура с полем
Ссылка.1С (Код)123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226Функция ПолучитьОбщиеПоказатели(Знач мДокументы) ЭкспортПустойРезультат = Новый Структура("_Вес,_Объем,_Площадь",0,0,0);Если мДокументы = Неопределено ТогдаВозврат ПустойРезультат;КонецЕсли;Если ТипЗнч(мДокументы) <> Тип("Массив") ТогдаВозврат ПустойРезультат;КонецЕсли;Если мДокументы.Количество() = 0 ТогдаВозврат ПустойРезультат;КонецЕсли;// Нормализуем массив.// В массиве должны находиться ссылки на документы.НормализованныеДокументы = Новый Массив;Для Каждого ЭлементМассива Из мДокументы ЦиклЕсли ЭлементМассива = Неопределено ТогдаПродолжить;КонецЕсли;ТипЭлемента = ТипЗнч(ЭлементМассива);// Если из формы списка пришла структура строки,// извлекаем из нее ссылку на документ.Если ТипЭлемента = Тип("Структура") ТогдаСсылкаДокумента = Неопределено;Если ЭлементМассива.Свойство("Ссылка",СсылкаДокумента) ТогдаЕсли ЗначениеЗаполнено(СсылкаДокумента) ТогдаНормализованныеДокументы.Добавить(СсылкаДокумента);КонецЕсли;КонецЕсли;Иначе// Для ссылок и объектов документов добавляем само значение.НормализованныеДокументы.Добавить(ЭлементМассива);КонецЕсли;КонецЦикла;Если НормализованныеДокументы.Количество() = 0 ТогдаВозврат ПустойРезультат;КонецЕсли;мДокументы = НормализованныеДокументы;// Получаем метаданные по типу значения.// Метод Метаданные() у ссылок и объектов документов// в данном случае использовать нельзя.Мета = Метаданные.НайтиПоТипу(ТипЗнч(мДокументы[0]));Если Мета = Неопределено ТогдаВозврат ПустойРезультат;КонецЕсли;// Если в массиве оказались объекты документов,// преобразуем их в ссылки.Если СтрНачинаетсяС(Строка(ТипЗнч(мДокументы[0])),"ДокументОбъект.") ТогдамРезультат = Новый Массив;Для Каждого ДокументОбъект Из мДокументы ЦиклЕсли ДокументОбъект <> Неопределено ТогдамРезультат.Добавить(ДокументОбъект.Ссылка);КонецЕсли;КонецЦикла;мДокументы = мРезультат;Если мДокументы.Количество() = 0 ТогдаВозврат ПустойРезультат;КонецЕсли;Мета = Метаданные.НайтиПоТипу(ТипЗнч(мДокументы[0]));Если Мета = Неопределено ТогдаВозврат ПустойРезультат;КонецЕсли;КонецЕсли;// Определяем табличную часть.Если Мета.ТабличныеЧасти.Найти("Товары") <> Неопределено ТогдаИмяТЧ = "Товары";ИначеЕсли Мета.ТабличныеЧасти.Найти("ОтгружаемыеТовары") <> Неопределено ТогдаИмяТЧ = "ОтгружаемыеТовары";ИначеВозврат ПустойРезультат;КонецЕсли;_Вес = 0;_Объем = 0;_Площадь = 0;УстановитьПривилегированныйРежим(Истина);ПопыткаЗапрос = Новый Запрос;Запрос.УстановитьПараметр("МассивДокументов",мДокументы);ШаблонЗапроса ="||ВЫБРАТЬ| Таблица.*,| Таблица.Номенклатура.ТипНоменклатуры КАК ТипНоменклатуры,| Таблица.Номенклатура.НаименованиеПолное КАК НаименованиеПолное,| Таблица.Номенклатура.Артикул КАК Артикул,| Таблица.Номенклатура.ВесЧислитель КАК ВесЧислитель,| Таблица.Номенклатура.ВесЗнаменатель КАК ВесЗнаменатель,| Таблица.Номенклатура.ВесЕдиницаИзмерения КАК ВесЕдиницаИзмерения,| Таблица.Номенклатура.ОбъемЕдиницаИзмерения КАК ОбъемЕдиницаИзмерения,| Таблица.Номенклатура.ОбъемЧислитель КАК ОбъемЧислитель,| Таблица.Номенклатура.ОбъемЗнаменатель КАК ОбъемЗнаменатель,| Таблица.Номенклатура.ПлощадьЕдиницаИзмерения КАК ПлощадьЕдиницаИзмерения,| Таблица.Номенклатура.ПлощадьЧислитель КАК ПлощадьЧислитель,| Таблица.Номенклатура.ПлощадьЗнаменатель КАК ПлощадьЗнаменатель|ИЗ| Документ.%1.%2 КАК Таблица|ГДЕ| Таблица.Ссылка В (&МассивДокументов)";Запрос.Текст = СтрШаблон(ШаблонЗапроса,Мета.Имя,ИмяТЧ);РезультатЗапроса = Запрос.Выполнить();Если РезультатЗапроса.Пустой() ТогдаВозврат ПустойРезультат;КонецЕсли;Выборка = РезультатЗапроса.Выбрать();Пока Выборка.Следующий() ЦиклЕсли Не ЗначениеЗаполнено(Выборка.Номенклатура) ТогдаПродолжить;КонецЕсли;Если ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(Выборка,"Отменено")И Выборка.Отменено ТогдаПродолжить;КонецЕсли;Реквизиты = РеквизитыНоменклатуры(Выборка);_Вес = _Вес+ ПолучитьВесВСтрокеТЧ(Выборка,Реквизиты);_Объем = _Объем+ ПолучитьОбъемВСтрокеТЧ(Выборка,Реквизиты);Если Реквизиты.ПлощадьЗнаменатель <> 0 Тогда_Площадь = _Площадь+ Выборка.Количество* Реквизиты.ПлощадьЧислитель/ Реквизиты.ПлощадьЗнаменатель;КонецЕсли;КонецЦикла;Исключение// При необходимости здесь можно записать ошибку в журнал регистрации.Возврат ПустойРезультат;КонецПопытки;УстановитьПривилегированныйРежим(Ложь);Возврат Новый Структура("_Вес,_Объем,_Площадь",_Вес,_Объем,_Площадь);КонецФункцииНо в приведенном варианте есть важный нюанс: возврат из блока
Попыткадо выполнения строки:1С (Код)1УстановитьПривилегированныйРежим(Ложь);может оставить привилегированный режим включенным до завершения серверного вызова. Поэтому лучше вынести результат в переменную и отключить привилегированный режим перед единственным возвратом.
Более безопасный фрагмент завершения функции:
1С (Код)1234567891011121314151617181920212223Результат = ПустойРезультат;УстановитьПривилегированныйРежим(Истина);Попытка// Выполнение запроса и расчет показателейРезультат = Новый Структура("_Вес,_Объем,_Площадь",_Вес,_Объем,_Площадь);ИсключениеРезультат = ПустойРезультат;КонецПопытки;УстановитьПривилегированныйРежим(Ложь);Возврат Результат;## Еще одна важная правка
В вашей функции есть этот код:
1С (Код)1Если ОбщегоНазначения.ЭтоРегистрСведений(Мета) ТогдаЕго лучше убрать из данной функции. Функция формирует запрос к объекту:
1С (Код)1Документ.%1.%2То есть она рассчитана именно на документы с табличными частями. Если передать туда регистр сведений, запрос с конструкцией
Документ.ИмяРегистра.ТабличнаяЧастьбудет некорректным.Функция должна получать массив:
1С (Код)12МассивДокументов = Новый Массив;МассивДокументов.Добавить(СсылкаНаДокумент);где элемент имеет тип:
1С (Код)1ДокументСсылка.ИмяДокументаДля вашей формы списка правильное заполнение массива должно выглядеть примерно так:
1С (Код)12345678910МассивДокументов = Новый Массив;Для Каждого СтрокаДокумента Из Документы ЦиклЕсли ЗначениеЗаполнено(СтрокаДокумента.Ссылка) ТогдаМассивДокументов.Добавить(СтрокаДокумента.Ссылка);КонецЕсли;КонецЦикла;Если текущая строка формы уже является ссылкой, тогда достаточно:
1С (Код)1МассивДокументов.Добавить(ТекущаяСтрока);После исправления перед вызовом серверной функции проверьте тип:
1С (Код)1Сообщить(Строка(ТипЗнч(МассивДокументов[0])));Ожидаемый результат:
1С (Код)1ДокументСсылка.РеализацияТоваровУслугили другой тип ссылки на документ.
Ключевая исправленная строка:
1С (Код)12Мета = Метаданные.НайтиПоТипу(ТипЗнч(мДокументы[0]));А строку:
1С (Код)1Мета = мДокументы[0].Метаданные();нужно удалить полностью.
-
-
АвторЗаписи
- Для ответа в этой теме необходимо авторизоваться.