Имя: Пароль:
1C
1C 7.7
v7: Как ускорить? Может у кого есть идеи
,
0 Double_Medved
 
15.01.14
15:02
Добрый день! Менеджеры вечно путали и забывали где что лежит, и в отчет Остатки ТМЦ лазить им неудобно, вообщем сделал им поле в документе, которое отображает остатки выбранной в строке номенклатуры. То есть эта функция выполняется каждый раз при выборе строки. Все бы нормально, но выполняется она примерно секунду, в принципе ползая по большому документу это неудобно. Может я где-то сделал не оптимально? Может как-то можно быстрее обратиться к данным?
1 Double_Medved
 
15.01.14
15:02
//Формирует стоку, которая показывает остатки за минусом резерва (ОстаткиТМЦ-РезервыТМЦ) на дату документа, до его проведения
//То есть всегда показывает то количество, которое было до проведения документа - чтобы можно было видеть хватает количества для проведения или перепроведения или нет
Функция СвободныеОстатки()
    ИнфоТекст = ""; //Строка для вывода результата
    Рег = СоздатьОбъект("Регистры");
    РегРезервы = Рег.РезервыТМЦ;
    РегОстатки = Рег.ОстаткиТМЦ;
    РегРезервы.ВременныйРасчет(1);  
    РегОстатки.ВременныйРасчет(1);
    Рег.Актуальность(1);
    Рег.РассчитатьРегистрыНа(ТекущийДокумент());
    //Переберем все склады и посмотрим на них остатки  
    Склады = СоздатьОбъект("Справочник.Склады");  
    Склады.ВыбратьЭлементы();
    Пока Склады.ПолучитьЭлемент() = 1 Цикл
        РезервПоСкладу = РегРезервы.СводныйОстаток(,Номенклатура,Склады.ТекущийЭлемент(),,,"Количество");
        ОстаткиПоСкладу = РегОстатки.СводныйОстаток(,Номенклатура,Склады.ТекущийЭлемент(),,"Количество");
        КоличествоОстатковЗаМинусомРезерва = ОстаткиПоСкладу - РезервПоСкладу;    
        Если КоличествоОстатковЗаМинусомРезерва <> 0 Тогда
            ИнфоТекст = ИнфоТекст + Склады.ТекущийЭлемент()+ ": " + КоличествоОстатковЗаМинусомРезерва + " шт, ";    
        КонецЕсли;  
    КонецЦикла;  
    //Уберем последнюю запятую
    ДлинаИнфоТекст = СтрДлина(ИнфоТекст);
    ИнфоТекст = Лев(ИнфоТекст,ДлинаИнфоТекст-2);
    Если ИнфоТекст = "" Тогда
        ИнфоТекст = "нет";
    КонецЕсли;
    Если (Номенклатура.ВидНоменклатуры = Перечисление.ВидыНоменклатуры.Услуга)
        или (Номенклатура.ВидНоменклатуры = Перечисление.ВидыНоменклатуры.Работа) Тогда
        ИнфоТекст = "";
    КонецЕсли;
    Возврат ИнфоТекст;    
КонецФункции
2 Voronve
 
15.01.14
15:06
Добавить:

спФирмы = СоздатьОбъект("СписокЗначений");
СпрФирмы = СоздатьОбъект("Справочник.Фирмы");
СпрФирмы.ВыбратьЭлементы();
Пока СпрФирмы.ПолучитьЭлемент() = 1 Цикл
Если СпрФирмы.ПометкаУдаления() = 1 Тогда Продолжить; КонецЕсли;
спФирмы.ДобавитьЗначение(СпрФирмы.ТекущийЭлемент());
КонецЦИкла;

Заменить:
РезервПоСкладу = РегРезервы.СводныйОстаток(спФирмы,Номенклатура,Склады.ТекущийЭлемент(),,,"Количество");
ОстаткиПоСкладу = РегОстатки.СводныйОстаток(спФирмы,Номенклатура,Склады.ТекущийЭлемент(),,"Количество");
3 m-serg74
 
15.01.14
15:06
(0) 1С++ и прямые запросы, причем делать чтобы получать остатки сразу на все строки, на скорость запроса не повлияет но если вернутся на строку для которой уже запрашивались остатки второй раз можно не спрашивать
4 mikecool
 
15.01.14
15:06
переделать на прямой запрос
5 Попытка1С
 
15.01.14
15:07
Создание объектов вынести за функцию.
6 Попытка1С
 
15.01.14
15:07
А так прямой параметризированный запрос 1с++
7 Double_Medved
 
15.01.14
15:07
(2) Спасибо, но там только одна фирма
8 ЧеловекДуши
 
15.01.14
15:07
(0) Все не оптимально. Менеджера послать в ...АД и сделать, как это делает 1С. Ведь она не спроста так делает ;)
9 Voronve
 
15.01.14
15:09
Заменить:
РезервПоСкладу = РегРезервы.СводныйОстаток(Фирма,Номенклатура,Склады.ТекущийЭлемент(),,,"Количество");
ОстаткиПоСкладу = РегОстатки.СводныйОстаток(Фирма,Номенклатура,Склады.ТекущийЭлемент(),,"Количество");
10 Double_Medved
 
15.01.14
15:09
(4) Точно, чтож я сразу не подумал. А как правильно сделать запрос на дату документа? То есть не на начало дня, а на 5 часов 35 минут например?
11 dk
 
15.01.14
15:10
капец получать остатки в цикле по каждому складу
проще фильтр по списку складов задать и выгрузитьитоги
кроме того можно кэширование в тз сделать и не расчитывать заново при переходе между строками
1с++ есть? скуль?
12 ЧеловекДуши
 
15.01.14
15:10
(4) Даже на прямом запросе, скорость заведения или редактирования документа падает.
Следовательно не каждому нужно сеё чудо с остатками :)

К примеру Оператору вообще побоку на остатки, ему лишь бы побыстрее налопатить 1000-2000 документов и домой :)
13 Джинн
 
15.01.14
15:10
(8) +100500
14 Voronve
 
15.01.14
15:10
РезервПоСкладу = РегРезервы.СводныйОстаток(<Вот тут не должно быть пусто, иначе запрос будет ворочаться очень долго>,Номенклатура,Склады.ТекущийЭлемент(),,,"Количество");
        ОстаткиПоСкладу = РегОстатки.СводныйОстаток(<Вот тут не должно быть пусто, иначе запрос будет ворочаться очень долго>,Номенклатура,Склады.ТекущийЭлемент(),,"Количество");
15 dk
 
15.01.14
15:11
(10) рассчитатьрегистрына, но это не ускорит ))
16 m-serg74
 
15.01.14
15:11
(10) а (3) не заметно так, да? :)
17 ЧеловекДуши
 
15.01.14
15:14
(10) Это просто... Держи...

    
Функция глУстановитьНаборЗаписей() Экспорт
    глОбъектНаборЗаписей = 0;
    глОбъектНаборЗаписей = СоздатьОбъект("ODBCRecordSet");
    //глОбъектНаборЗаписей.АвтоТипизация(1) ;

    Если (IsSQL=1) Тогда
        глОбъектНаборЗаписей.УстБД1С();  
    Иначе
        DataBase = СоздатьОбъект("ODBCDatabase");
        Рез = DataBase.DriverConnect("DRIVER=Microsoft Visual FoxPro Driver;Deleted=Yes;Null=Yes;Collate=RUSSIAN;Exclusive=No;SourceType=DBF;SourceDB="+КаталогИБ());
        глОбъектНаборЗаписей.SetDatabase(DataBase);
    КонецЕсли;

    Если глОтладкаSQL = 1 Тогда
        глОбъектНаборЗаписей.Отладка();
    КонецЕсли;
    
    Возврат глОбъектНаборЗаписей ;
КонецФункции

    
    Мета=СоздатьОбъект("MetaDataWork");
    
    ЗапросSQL = глУстановитьНаборЗаписей();
    
    НачДата = ВыбНачПериода;
    КонДата = ВыбКонПериода;
    Если ПустоеЗначение(НачДок)=0 Тогда
        НачДата=Мета.ПолучитьДатуВремяИдДок(СформироватьПозициюДокумента(НачДок,0));
    КонецЕсли;
    Если ПустоеЗначение(КонДок)=0 Тогда
        КонДата=СформироватьПозициюДокумента(КонДок,1);//Мета.ПолучитьДатуВремяИдДок(
    КонецЕсли;
    
    ЗапросSQL.УстановитьТекстовыйПараметр("ВыбДатаОтгрузкиН",НачДата);
    
    //ЗапросSQL.УложитьСписокОбъектов("?????????", "#Firms", "Фирмы");
    ЗапросSQL.УложитьСписокОбъектов(ВыбТовар, "#Tovar", "Номенклатура");
    ЗапросSQL.УложитьСписокОбъектов(ВыбСклад, "#Sklad", "Склады");
    //ЗапросSQL.УложитьСписокОбъектов(ВыбНомУпак, "#VidUpak");
    
    //Реквизиты и группировки
    Если Пометка("Склад")=1 Тогда
        ДопРекв=ДопРекв+?(ПустоеЗначение(ДопРекв)=1,"","
        |, ")+"ОстТМЦ.Склад [Склад $Справочник.Склады]";
        ДопГрупп=ДопГрупп+?(ПустоеЗначение(ДопГрупп)=1,"","
        |, ")+"ОстТМЦ.Склад";
        //
        ДопСворачивать=ДопСворачивать+?(ПустоеЗначение(ДопСворачивать)=1,"",",")+"Склад";
    КонецЕсли;
    Если Пометка("Номенклатура")=1 Тогда
        ДопРекв=ДопРекв+?(ПустоеЗначение(ДопРекв)=1,"","
        |, ")+"ОстТМЦ.Номенклатура [Номенклатура $Справочник.Номенклатура]";
        ДопГрупп=ДопГрупп+?(ПустоеЗначение(ДопГрупп)=1,"","
        |, ")+"ОстТМЦ.Номенклатура";
        //
        ДопСворачивать=ДопСворачивать+?(ПустоеЗначение(ДопСворачивать)=1,"",",")+"Номенклатура";
    КонецЕсли;
    
    //Условие отбора
    ДопУсловия="";
    Если ВыбТовар.РазмерСписка()>0 Тогда
        ДопУсловия=ДопУсловия+"
        | "+?(ПустоеЗначение(ДопУсловия)=1,"","AND ")+"Номенклатура IN (SELECT VAL FROM #Tovar)";
    КонецЕсли;
    Если ВыбСклад.РазмерСписка()>0 Тогда
        ДопУсловия=ДопУсловия+"
        | "+?(ПустоеЗначение(ДопУсловия)=1,"","AND ")+"Склад IN (SELECT VAL FROM #Sklad)";
    КонецЕсли;
    
    ТекстЗапроса="
    |SELECT "+ДопРекв+"
    |        "+?(ПустоеЗначение(ДопРекв)=1,"",",")+"Sum(ОстТМЦ.КоличествоОстаток) [НачНетто $Число]
    |        ,Sum(ОстТМЦ.КоличествоБруттоОстаток) [НачБрутто $Число]
    |        ,Sum(0) [КонНетто $Число]
    |        ,Sum(0) [КонБрутто $Число]
    |FROM $РегистрОстатки.ОстаткиТМЦ(:ВыбДатаОтгрузкиН,,";
    ТекстЗапроса=ТекстЗапроса+ДопУсловия+"
    |        ,(Фирма,Склад,Номенклатура,ТипУпаковки,НомерУпаковки),(Количество,КоличествоБрутто)) AS ОстТМЦ";
    Если ПустоеЗначение(ДопГрупп)=0 Тогда
        ТекстЗапроса=ТекстЗапроса+"
        |Group By "+ДопГрупп+"
        |HAVING (Sum(ОстТМЦ.КоличествоОстаток)<>0) or (Sum(ОстТМЦ.КоличествоБруттоОстаток)<>0)";
    КонецЕсли;
    
    //ТекстЗапроса="Select * From "+ИмяВременнойТаблицыТовара+" as TMDB";
    
    Если ЗапросSQL.Подготовить(ТекстЗапроса) = 0 Тогда
        Сообщить(ЗапросSQL.GetLastError(), "!");
        Возврат ;
    КонецЕсли;
    
    Если ТипЗначенияСтр(ТЗ_Запроса)="ТаблицаЗначений" Тогда
        ТЗ_Запроса.Очистить();
    Иначе
        ТЗ_Запроса=СоздатьОбъект("ТаблицаЗначений");
    КонецЕсли;
    
    ЗапросSQL.Открыть();
    ЗапросSQL.ПолучитьРезультатыВ_ТЗ(ТЗ_Запроса,1);    
    ЗапросSQL.Close();  
    
    Если ТЗ_Запроса.КоличествоКолонок()=0 Тогда
        Сообщить("Ошибка в запросе SQL! Запрос не выполнен!");
        Возврат;
    КонецЕсли;
18 ЧеловекДуши
 
15.01.14
15:16
+(17) ... продолжение... но только на конец...

    
    ЗапросSQL.УстановитьТекстовыйПараметр("ВыбДатаОтгрузкиК",КонДата);
    
    ЗапросSQL.УложитьСписокОбъектов(ВыбТовар, "#Tovar", "Номенклатура");
    ЗапросSQL.УложитьСписокОбъектов(ВыбСклад, "#Sklad", "Склады");
    
    ТекстЗапроса="
    |SELECT "+ДопРекв+"
    |        "+?(ПустоеЗначение(ДопРекв)=1,"",",")+"Sum(0) [НачНетто $Число]
    |        ,Sum(0) [НачБрутто $Число]
    |        ,Sum(ОстТМЦ.КоличествоОстаток) [КонНетто $Число]
    |        ,Sum(ОстТМЦ.КоличествоБруттоОстаток) [КонБрутто $Число]
    |FROM $РегистрОстатки.ОстаткиТМЦ(:ВыбДатаОтгрузкиК~,,";
    ТекстЗапроса=ТекстЗапроса+ДопУсловия+"
    |        ,(Фирма,Склад,Номенклатура,ТипУпаковки,НомерУпаковки),(Количество,КоличествоБрутто)) AS ОстТМЦ";
    Если ПустоеЗначение(ДопГрупп)=0 Тогда
        ТекстЗапроса=ТекстЗапроса+"
        |Group By "+ДопГрупп+"
        |HAVING (Sum(ОстТМЦ.КоличествоОстаток)<>0) or (Sum(ОстТМЦ.КоличествоБруттоОстаток)<>0)";
    КонецЕсли;
    
    //ТекстЗапроса="Select * From "+ИмяВременнойТаблицыТовара+" as TMDB";
    
    Если ЗапросSQL.Подготовить(ТекстЗапроса) = 0 Тогда
        Сообщить(ЗапросSQL.GetLastError(), "!");
        Возврат ;
    КонецЕсли;
    
    Если ТипЗначенияСтр(ТЗ_Запроса2)="ТаблицаЗначений" Тогда
        ТЗ_Запроса2.Очистить();
    Иначе
        ТЗ_Запроса2=СоздатьОбъект("ТаблицаЗначений");
    КонецЕсли;
    
    ЗапросSQL.Открыть();
    ЗапросSQL.ПолучитьРезультатыВ_ТЗ(ТЗ_Запроса2,1);    
    ЗапросSQL.Close();  
    
    Если ТЗ_Запроса2.КоличествоКолонок()=0 Тогда
        Сообщить("Ошибка в запросе SQL! Запрос не выполнен!");
        Возврат;
    КонецЕсли;
19 Джинн
 
15.01.14
15:18
(10) Одна глупость порождает другую глупость. При контроле остатков на документ Вы потом будете разгребать отрицательные остатки и устроите войну менеджеров за ликвидный товар.
20 ЧеловекДуши
 
15.01.14
15:23
(19) Зато какие будут сражения, сколько воплей, и все закончится опять обращение к Программисту, что бы он это убрал :)
21 Злой Бобр
 
15.01.14
15:25
(0) Вам нужно текущий остаток а не остаток на документ. Ответ в (19) только подтверждает ваше заблуждение.
22 Mikeware
 
15.01.14
15:28
(20) зато без работы не останется.
зы. а вообще, очень показательная парочка....
23 Double_Medved
 
15.01.14
15:41
Да, спасибо, пожалуй правильней будет показывать текущий остаток.
24 varelchik
 
15.01.14
16:44
(23) мда.
а посмотреть в типовых было слабо?
25 Злой Бобр
 
15.01.14
17:05
(24) Зачем? Человек просто слегка протупил. Вполне типичная ошибка начинающего 1С-ника. Я тоже на эти грабли наступал. Так что ничего страшного. Автор осознал и исправился.
26 Double_Medved
 
15.01.14
18:03
(25) А все-таки как-то можно в запросе установить не только дату, но и время? Гугл молчит
27 Double_Medved
 
15.01.14
18:04
Например сделать запрос с 15.01.2014 12:00 по 15.01.2014 14:00 ?
28 Злой Бобр
 
15.01.14
19:03
Зачем тебе время? Для текущего остатка вытягивай последний остаток и непарься:
Регистр.Товары.Остаток(Товар,Склад,"Кво");
29 aka MIK
 
15.01.14
19:15
(0) Нафейхоа тебе остатки на момент документа? Делай на ТА будет  зело быстрее
30 aka MIK
 
15.01.14
19:17
(26) СформироватьПозициюДокумента() и на нее смотреть остатки
Ошибка? Это не ошибка, это системная функция.