Пытался сделать развертку по всем товарам/складам/дням. В моем случае 1С зависала когда в ТЗ было около 1000000 строк (3 дня по всем товарам по всем складам). Поэтому пошел другим путем. Основной (внешний) отчет с группировкой "день", и при выводе в печатную форму получаю остатки функцией на 1 день и заполняю ими нужные места во внешнем запросе.
Вот запрос для получения начального и конечного остатков на день.
Функция НайтиОстатки_ПрямойЗапрос(наДату) ТекстЗапроса1=" |select | Матрица1.Товар [Товар $Справочник.Товары] |, Матрица1.Склад [Склад $Справочник.Склады] |, sum(Матрица1.ОстатокТовараНач) as ОстатокТовараНач |, sum(Матрица1.ОстатокТовараКон) as ОстатокТовараКон |from |( |SELECT РегОстНачальные.Товар | , РегОстНачальные.Склад | , РегОстНачальные.ОстатокТовараОстаток as ОстатокТовараНач | , 0 as ОстатокТовараКон |FROM $РегистрОстатки.ОстаткиТоваров(:наДату,,"; Если спТовары.РазмерСписка() <> 0 Тогда ТекстЗапроса1=ТекстЗапроса1+" |(Товар IN (SELECT val FROM #выбТовары)) |"; КонецЕсли; Если ((спТовары.РазмерСписка() <> 0) и (спСклады.РазмерСписка() <> 0)) Тогда ТекстЗапроса1=ТекстЗапроса1+" | AND " ; КонецЕсли; Если спСклады.РазмерСписка() <> 0 Тогда ТекстЗапроса1=ТекстЗапроса1+" |(Склад IN (SELECT val FROM #выбСклады)) |"; КонецЕсли; ТекстЗапроса1=ТекстЗапроса1+" |,, | ОстатокТовара) AS РегОстНачальные | |union all | |SELECT РегОстКон.Товар | , РегОстКон.Склад | , 0 as ОстатокТовараНач | , РегОстКон.ОстатокТовараОстаток as ОстатокТовараКон |FROM $РегистрОстатки.ОстаткиТоваров(:наДату~,,"; Если спТовары.РазмерСписка()<> 0 Тогда ТекстЗапроса1=ТекстЗапроса1+" |(Товар IN (SELECT val FROM #выбТовары)) |"; КонецЕсли; Если ((спТовары.РазмерСписка()<> 0) и (спСклады.РазмерСписка() <> 0)) Тогда ТекстЗапроса1=ТекстЗапроса1+" | AND " ; КонецЕсли; Если спСклады.РазмерСписка() <> 0 Тогда ТекстЗапроса1=ТекстЗапроса1+" |(Склад IN (SELECT val FROM #выбСклады)) |"; КонецЕсли; ТекстЗапроса1=ТекстЗапроса1+" |,, | ОстатокТовара) AS РегОстКон |) as Матрица1 | |group by Матрица1.Товар, Матрица1.Склад |order by Матрица1.Товар, Матрица1.Склад |"; итЗапроса = СоздатьОбъект("ИндексированнаяТаблица"); рс.УстановитьТекстовыйПараметр("наДату", наДату); рс.УложитьСписокОбъектов(спТовары,"#выбТовары","Товары"); рс.УложитьСписокОбъектов(спСклады,"#выбСклады","Склады"); Ответ=рс.ВыполнитьИнструкцию(ТекстЗапроса1,итЗапроса); ПостроитьИндекс(итЗапроса,тИндекс); Возврат итЗапроса; КонецФункции
Функция НайтиВЗапросПоОстаткам(итЗапроса,тИндекс,сзЧтоИщем) Ответ=итЗапроса.НайтиСтроку(тИндекс,сзЧтоИщем,0,1); //Сообщить("Ответ "+Ответ+" "+итЗапроса.НомерСтроки()+"нач: "+итЗапроса.ОстатокТовараНач+", кон: "+итЗапроса.ОстатокТовараКон); Если Ответ <> 0 Тогда НачОст=итЗапроса.ОстатокТовараНач; КонОст=итЗапроса.ОстатокТовараКон; Иначе НачОст=0; КонОст=0; КонецЕсли; сзОтвет.УдалитьВсе(); сзОтвет.ДобавитьЗначение(НачОст); сзОтвет.ДобавитьЗначение(КонОст); Возврат сзОтвет; КонецФункции
во внешнем отчет соответственно:
тИндекс="*Товар,*Склад";
// ищем остатки сзОтвет.УдалитьВсе(); сзОтвет.ДобавитьЗначение(текТовар.ТекущийЭлемент()); сзОтвет.ДобавитьЗначение(текСклад.ТекущийЭлемент()); сзОтветОст=НайтиВЗапросПоОстаткам(ЗапросПоОстаткам,тИндекс,сзОтвет); НачОстКол=сзОтветОст.ПолучитьЗначение(1); КонОстКол=сзОтветОст.ПолучитьЗначение(2);
Остатки по всем товарам/складам на 1 день - от 2х до 8 секунд
|