Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как можно оптимизировать обработку табличной части документа
Украинский 1С форум: всё про 1С 8.3, 1С 8.2, 1С 8.1, 1С 8.0, 1С 7.7 > Программисту > Программирование в 1С Предприятие 8.2 > Программирование обычных форм 1С 8.2 и не интерфейсной логики
bizisoft
Здравствуйте.
1С:Предприятие 8.2 (8.2.19.130)
"Альфа-Авто: Автосервис+Автозапчасти, украинская версия 4.1" (4.1.17.01)

Есть такой документ как Изменение цен компании, в котором устанавливаются цены для товаров в разрезе выбранного типа цен.
Например: у поставщика куплен товар, проведена приходная накладная. В Изменение цен компании выбирается эта приходная как документ основание и заполняется ТЧ по документу основания.
В ТЧ отображаются старая цена (которая была установлена ранее), базовая цена (цена из приходной), себестоимость (судя по значениям это итоговая себестоимость товара), а также % наценки, сумма наценки и Новая цена.

Добавил поле ПредыдущаяСебестоимость, в которую вывожу себестоимость товара, но без учета товара из приходной, т.е. делаю выборку по партиям до даты приходной накладной.
Все это действие выполняю в процедуре ПриПолученииДанных - все вроде работает, но тормоза при этом неописуемые.
При любом чихе (изменение данных, простая смена строки) происходит проход по ТЧ и выполнение запроса для каждой строки, что не по феншую.

...
        Если РасчетЦенОт=1 Тогда            
            Если НЕ ДокументОснование.Пустая() Тогда    
                ДокОсн = ДокументОснование.Ссылка;
                //Сообщить(ДокОсн.Номер);
                //Сообщить(ДокОсн.Дата);
                //Сообщить(ДокОсн.Номер);
                ЗапросПартии = Новый Запрос;                      
                ЗапросПартии.Текст =
                    "ВЫБРАТЬ
                    |    ПартииТоваровКомпанииОстатки.Номенклатура,
                    |    ПартииТоваровКомпанииОстатки.СуммаУпрОстаток / ПартииТоваровКомпанииОстатки.КоличествоОстаток КАК Себест
                    |ИЗ
                    |    РегистрНакопления.ПартииТоваровКомпании.Остатки КАК ПартииТоваровКомпанииОстатки
                    |ГДЕ
                    |    ПартииТоваровКомпанииОстатки.Номенклатура = &Номенклатура
                    |    И ПартииТоваровКомпанииОстатки.Партия.Дата < &Дата";                 
                ЗапросПартии.УстановитьПараметр("Номенклатура",ДанныеСтроки.Номенклатура);         
                ЗапросПартии.УстановитьПараметр("Дата",ДокОсн.Дата);         
                Результат = ЗапросПартии.Выполнить();
                ТЗ = Результат.Выгрузить();
                //ТЗ.Свернуть("Номенклатура","Себест");
                Сумма = 0;
                КолВо = 0;
                Для Каждого Стр Из ТЗ Цикл
                //Выб = Результат.Выбрать();
                //ПредыдущаяСебестоимость = 0;
                //Пока Выб.Следующий() Цикл
                    //Сообщить(Выб.Номенклатура);
                    //Сообщить(Выб.Себест);
                    Сумма = Сумма+Стр.Себест;
                    КолВо = КолВо+1;
                    Сообщить(Сумма);
                    Сообщить(КолВо);
                    //ПредыдущаяСебестоимость = Выб.Себест; //ЗапросПартии.Выполнить().Выгрузить()[0][1];//.Себест;
                    //Сообщить(ПредыдущаяСебестоимость);
                КонецЦикла;
                Попытка
                    ПредыдущаяСебестоимость = Сумма/КолВо;
                Исключение
                    ПредыдущаяСебестоимость = 0;
                КонецПопытки;
                ОформлениеСтроки.Ячейки.ПредыдущаяСебестоимость.ОтображатьТекст=Истина;
                ОформлениеСтроки.Ячейки.ПредыдущаяСебестоимость.Текст=Формат(ПредыдущаяСебестоимость,"ЧЦ=15; ЧДЦ=2");
            КонецЕсли;            
        КонецЕсли;            
...


Подскажите пожалуйста как можно оптимизировать этот процесс?
bizisoft
bizisoft @ Вчера, 21:44 необходимо зарегистрироваться для просмотра ссылки ,
Получилось немного доработать посредством вынесения запроса из цикла
Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл

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



Насколько такое решение верно или есть более изысканные способы?
andr_andrey
bizisoft @ Сегодня, 2:53 необходимо зарегистрироваться для просмотра ссылки ,
sava1
добавить в тз индекс по номенклатуре
andr_andrey
Использование виртуальной таблицы "Остатки" без параметров - странно.
Если данных очень много, то возможно не стоит на клиента тащить таблицу значений, а использовать объект "Выборка".
Хотите ускорения поиска в остатках, надо понимать сколько их будет. Вполне возможно, придётся использовать не только "тз с индексом", а и хеш-таблицу (Соответствие).
bizisoft
andr_andrey @ Сегодня, 14:12 необходимо зарегистрироваться для просмотра ссылки ,
Данных очень много - сколько считается много? Предположительно в ТЧ может быть 10000 строк, допускаю до 40000 строк, что маловероятно, т.к. это вся номенклатура.
Забыл написать база файловая.
А можно уточнить, что имеется ввиду под хеш-таблицей (Соответствие)?
andr_andrey
bizisoft @ Сегодня, 19:21 необходимо зарегистрироваться для просмотра ссылки ,
Прошу прощения у администратора за кросс-линки, но по другому переписывать нет смысла:
необходимо зарегистрироваться для просмотра ссылки
необходимо зарегистрироваться для просмотра ссылки
необходимо зарегистрироваться для просмотра ссылки
необходимо зарегистрироваться для просмотра ссылки
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.