7.7 Вопросы по языку

Тема в разделе "Общие вопросы "1С:Предприятие 7.7"", создана пользователем Vertex, 20 июл 2011.

  1. Бухгалтерский угодник
    Offline

    Бухгалтерский угодник Администраторы Команда форума Администратор

    Регистрация:
    29 дек 2008
    Сообщения:
    21.523
    Симпатии:
    407
    Баллы:
    104
    Пост №33... Флаг нам нужен для выхода из цикла. Он конечно итак выйдет, но зачем нам лопатить лишние доки??????
    Код:
    Если ТЗ.Итог("Флаг")=ТЗ.КоличествоСтрок() Тогда
    Прервать; //цикл по документам
    КонецЕсли;
    
    
    
    Изначально итог по колонке ФЛАГ у нас =0. По мере заполнения мы каждой колонке присваиваем 1. Если сумма по колоке флаг=количеству строк (т.е. везде единицы) - нам больше нечего делать в цикле по документам. Понятно?
  2. TopicStarter Overlay
    Vertex
    Offline

    Vertex Опытный в 1С

    Регистрация:
    14 июн 2011
    Сообщения:
    468
    Симпатии:
    4
    Баллы:
    29
    Даа.....спасибо огромное.

    Интересно написанно. Сразу не вкурил
    :angry:
  3. TopicStarter Overlay
    Vertex
    Offline

    Vertex Опытный в 1С

    Регистрация:
    14 июн 2011
    Сообщения:
    468
    Симпатии:
    4
    Баллы:
    29
    Доброго дня, прошу совета по оптимизации.
    Код:
    ТЗ.ВыбратьСтроки();
    
    Сч = 0;
    
    Пока ТЗ.ПолучитьСтроку()=1 Цикл
    Сч = Сч + 1; 
    ДокПост.ОбратныйПорядок(1);
    ДокПост.ВыбратьДокументы();
    Пока ДокПост.ПолучитьДокумент()=1 Цикл  
    
    ДокПост.ВыбратьСтроки();
    Пока ДокПост.ПолучитьСтроку()=1 Цикл
    Если (СокрЛП(ТЗ.Товар) = СокрЛП(ДокПост.Номенклатура)) И (ТЗ.Флаг = 0)  Тогда  
    
    ТЗ.УстановитьЗначение(Сч,"Поставщик",ДокПост.Контрагент);    
    ТЗ.УстановитьЗначение(Сч,"Флаг",1);    
    
    ИначеЕсли ТЗ.Флаг = 1 Тогда    
    Продолжить; // <-------------
    КонецЕсли;  
    
    КонецЦикла;    
    КонецЦикла;   
    Если ТЗ.Итог("Флаг")=ТЗ.КоличествоСтрок() Тогда
    Сообщить(" !!ALERT!! Cработало условие выхода  ");
    Прервать; //цикл по документам
    КонецЕсли;
    //        Сообщить("  Флаг = "+ТЗ.Итог("Флаг")+" Колво стр "+ТЗ.КоличествоСтрок());
    КонецЦикла;
    
    
    
    
    Я так понимаю нужно реализовать следующую конструкцию: если флаг = 1 тогда нужно выйти на самый верхний цикл в котором таблица переходит на другую строку...так?
    Но оператор продолжить перебрасывает в начало цикла по перебору строк документа.... как достойно решить данную задачу?
    Создать метку и использовать оператор перехода на верхний уровень цикла?
  4. dianofob
    Offline

    dianofob (-_-)y-.o0O

    Регистрация:
    3 июл 2009
    Сообщения:
    711
    Симпатии:
    0
    Баллы:
    26
    лучше переписать на черный запрос.. а так вместо Продолжить - Прервать
    Код:
    Пока ТЗ.ПолучитьСтроку()=1 Цикл
    Сч = Сч + 1; 
    ДокПост.ОбратныйПорядок(1);
    ДокПост.ВыбратьДокументы();
    Пока ДокПост.ПолучитьДокумент()=1 Цикл  
    VT = CreateObject("ValueTable");
    ДокПост.UnloadTable();
    nStr = 0;
    If VT.FindValue(ТЗ.Товар,nStr,"Номенклатура") = 0 Then
    Break;
    Else
    ТЗ.Поставщик = ДокПост.Контрагент;
    ТЗ.Флаг = 1;
    EndIf;
    КонецЦикла;   
    Если ТЗ.Итог("Флаг")=ТЗ.КоличествоСтрок() Тогда
    Сообщить(" !!ALERT!! Cработало условие выхода  ");
    Прервать; //цикл по документам
    КонецЕсли;
    //        Сообщить("  Флаг = "+ТЗ.Итог("Флаг")+" Колво стр "+ТЗ.КоличествоСтрок());
    КонецЦикла;
    
    
  5. TopicStarter Overlay
    Vertex
    Offline

    Vertex Опытный в 1С

    Регистрация:
    14 июн 2011
    Сообщения:
    468
    Симпатии:
    4
    Баллы:
    29
    Это что за метод?

    Насколько помню у документов не работает выгрузка табличной части документа. Тока вроде в запросах
  6. Бухгалтерский угодник
    Offline

    Бухгалтерский угодник Администраторы Команда форума Администратор

    Регистрация:
    29 дек 2008
    Сообщения:
    21.523
    Симпатии:
    407
    Баллы:
    104
    UnloadTable - ВыгрузитьТабличнуюЧасть


    Выгрузить многострочную часть документа в таблицу значений.
  7. dianofob
    Offline

    dianofob (-_-)y-.o0O

    Регистрация:
    3 июл 2009
    Сообщения:
    711
    Симпатии:
    0
    Баллы:
    26
    ну да, токо ТЗ в параметр метода надо передать..
    у документов нет метода для поиска значения в ТЧ, поэтому приходится выгружать в ТЗ
  8. TopicStarter Overlay
    Vertex
    Offline

    Vertex Опытный в 1С

    Регистрация:
    14 июн 2011
    Сообщения:
    468
    Симпатии:
    4
    Баллы:
    29
    Доброго дня.
    С номенклатурой закончил.
    Вопрос возник по взаиморасчётам.

    Код:
    Процедура ВзаиморасчетыПоставщики(ДБФПост)       
    
    Запрос  = СоздатьОБъект("Запрос");	
    
    ТекстЗапроса = " 
    |С НачДата По НачДата;
    |Договор = Регистр.Поставщики.Договор;
    |Долг      = Регистр.Поставщики.СуммаРуб; 
    |Группировка Договор Без Групп;           
    |Функция Итог = КонОст(Долг);
    |";
    
    Если Запрос.Выполнить(ТекстЗапроса)=0 Тогда
    Возврат;
    КонецЕсли; 
    
    Пока Запрос.Группировка(1)=1 Цикл
    _Пост  = Запрос.Договор.Владелец;
    ДБФПост.Добавить();
    ДБФПост.Kontr = Строка(_Пост);
    ДБФПост.Dolg  = Запрос.Итог;
    ДБФПост.Записать();
    КонецЦикла;
    
    КонецПроцедуры //ВзаиморасчетыПоставщики() 
    
    По сути запрос должен выводить общий итог по поставщику......
    но эта сумма не совпадает с отчётом ведомость по контрагентам. :angry:
    Из за чего такое может быть?
  9. Бухгалтерский угодник
    Offline

    Бухгалтерский угодник Администраторы Команда форума Администратор

    Регистрация:
    29 дек 2008
    Сообщения:
    21.523
    Симпатии:
    407
    Баллы:
    104
    Потому что поставщик может выступать и в роли покупателя....
    Вы отчет по контрагентам как смотрели? Общие взаиморасчеты? Сделайте запрос еще по покупателям и объедините результат в одну ТЗ
  10. TopicStarter Overlay
    Vertex
    Offline

    Vertex Опытный в 1С

    Регистрация:
    14 июн 2011
    Сообщения:
    468
    Симпатии:
    4
    Баллы:
    29
    Незнаю почему но не работает(((((((((((((
    Хочется оптимизировать а то выгрузка будет идти около суток у меня 16 тыц строк в ТЗ....упасть не встать
  11. Бухгалтерский угодник
    Offline

    Бухгалтерский угодник Администраторы Команда форума Администратор

    Регистрация:
    29 дек 2008
    Сообщения:
    21.523
    Симпатии:
    407
    Баллы:
    104
    Не работает потому что не позиционируете строку таблицы значений
    Код:
    ...
    Иначе
    ТЗ.ПолучитьСтрокуПоНомеру(nStr);
    ...
    КонецЕсли;
    ...
    
    
    
    
    +
    нет проверки что строка уже заполнена т.е. в ТЗ попадут неактуальные значения цены и/или поставщика

    +
    16 тыс. строк через ЗначениеВФайл выгружать конечно же не кошерно, т.к. этот метод медленно (мягко сказано) работает с большими файлами. Выход:
    1) или бить на несколько ТЗ (уже после обработки)
    2) выгружать в текст с разделителями или DBF
    3) в таблицу заполняем и сохраняем
  12. dianofob
    Offline

    dianofob (-_-)y-.o0O

    Регистрация:
    3 июл 2009
    Сообщения:
    711
    Симпатии:
    0
    Баллы:
    26
    "ТЗ.ПолучитьСтрокуПоНомеру(nStr);" - нельзя, так как у нас уже спозиционирована строка здесь "Пока ТЗ.ПолучитьСтроку()=1 Цикл", а в этом случае может еще и цикл слететь.
    вопрос в следующем: в ТЗ номенклатура уникальна? т.е. сгруппирована? если да то флаг и поставщик попадет последний.
    я бы переписал все напрямой запрос к бд, ну или хотя бы на черный..
    Если получившееся добро выгружается в итоге в эксель - тогда нужно писать алгоритм записи в эксель через OLE, или сохранять кусками и клеить через OLE, ну или использовать какие-нибудь ВК (например я когда-то смотрел rik_sql)..
  13. dianofob
    Offline

    dianofob (-_-)y-.o0O

    Регистрация:
    3 июл 2009
    Сообщения:
    711
    Симпатии:
    0
    Баллы:
    26
    примерно так это выглядит на варианте с прямыми запросами

    Код:
    Function ВернутьТАбПоступлений(Номенклатура)
    pRS = CreateObject("ODBCRecordset"); //для файловой платформы нужна еще строка подключения к базе
    StrSQL = "
    |SELECT
    |Поступление.IDDoc,
    |Поступление.Контрагент [Поставщик Справочник.Контрагенты],
    |CAST(LEFT(ЖурДок.DATE_TIME_IDDOC, 8) AS datetime)  as ДатаДокумента,
    |ЖурДок.IsMark Пометка,
    |FROM 
    |Документ.Поступление as Поступление  
    |
    |INNER JOIN 
    |_1SJOURN as ЖурДок 
    |ON ЖурДок.IDDOC = Поступление.IDDOC
    |
    |Left JOIN 
    |ДокументСтроки.Поступление as ПоступлениеТЧ
    |ON ПоступлениеТЧ.IDDOC = Поступление.IDDOC
    |
    |WHERE ПоступлениеТЧ.Номенклатура = :Номенклатура
    |AND ЖурДок.IsMark = 0";
    
    //|ORDER BY CAST(LEFT(ЖурДок.DATE_TIME_IDDOC, 8) AS datetime) Desc";
    
    pRS.SetTextParam("Номенклатура",Номенклатура);
    oVT = CreateObject("ValueTable");
    pRS.ExecuteStatement(StrSQL,oVT);
    Return oVT;
    EndFunction
    
    Процедура ВариантСПрямымЗапросом(ТЗ)
    ЗагрузитьВнешнююКомпоненту(КаталогИБ() + "1CPP.dll");
    ИтогФлаг = 0;
    Сч = 0;
    ТЗ.ВыбратьСтроки();
    Пока ТЗ.ПолучитьСтроку()=1 Цикл
    Сч = Сч + 1; 
    VT = ВернутьТАбПоступлений(ТЗ.Номенклатура);
    If VT.LinesCnt()>0 Then
    VT.GetLineByNumber(VT.LinesCnt()); //Берем последнее
    ТЗ.Поставщик = VT.Поставщик;
    ТЗ.Флаг = 1;
    ИтогФлаг = ИтогФлаг+1;
    EndIf;
    Если ИтогФлаг = ТЗ.КоличествоСтрок() Тогда //Это условие по идее должно работать на последней строке ТЗ
    Сообщить(" !!ALERT!! Cработало условие выхода  ");
    Прервать; //цикл по документам
    КонецЕсли;
    //        Сообщить("  Флаг = "+ТЗ.Итог("Флаг")+" Колво стр "+ТЗ.КоличествоСтрок());
    КонецЦикла    
    КонецПроцедуры
    
    
    
  14. TopicStarter Overlay
    Vertex
    Offline

    Vertex Опытный в 1С

    Регистрация:
    14 июн 2011
    Сообщения:
    468
    Симпатии:
    4
    Баллы:
    29
    В ТЗ номенклатура не уникальна т.е таблица имеет вид

    Товар1 Склад1 Фирма1
    Товар1 Склад2 Фирма1
    Товар1 Склад3 Фирма1
    Товар1 Склад2 Фирма2
    =================
    Товар2 Склад1 Фирма1
    Товар2 Склад2 Фирма1
    Товар2 Склад3 Фирма1
    Товар2 Склад2 Фирма2

    Тоесть каждый товар на всех фирмах и складах

    ЗЫ.. я с прямыми запросами исчо не работал, и база у мну SQL
  15. dianofob
    Offline

    dianofob (-_-)y-.o0O

    Регистрация:
    3 июл 2009
    Сообщения:
    711
    Симпатии:
    0
    Баллы:
    26
    ну, вот, значит добавится еще проверка по складам и фирме
    так попробуй, если нет других уважительных причин этого не делать..тем более что sql.
    скорость поиска возрастет в разы, потому что цикл по документам это медленно.
    А если у документа есть регистр - лучше попытаться искать в нем - всё быстрее будет, чем так
  16. Бухгалтерский угодник
    Offline

    Бухгалтерский угодник Администраторы Команда форума Администратор

    Регистрация:
    29 дек 2008
    Сообщения:
    21.523
    Симпатии:
    407
    Баллы:
    104
    Действительно... Ошибся
  17. Бухгалтерский угодник
    Offline

    Бухгалтерский угодник Администраторы Команда форума Администратор

    Регистрация:
    29 дек 2008
    Сообщения:
    21.523
    Симпатии:
    407
    Баллы:
    104
    Если у вас нет перемещений (т.е. просто от поставщика на конкретный склад/фирму) то цикл нужно организовывать по другому.

    Внешний - по документам. Внутренний по ТЗ. ТЗ должна быть ОБЯЗАТЕЛЬНО отсотрирована в порядке Фирма-Склад-Номенклатура.
    Тогда код будет выглядеть так
    Код:
    Тмп = СоздатьОбъект("ТаблицаЗначений");
    ДокПост.ОбратныйПорядок(1);
    ДокПост.ВыбратьДокументы();
    Пока ДокПост.ПолучитьДокумент()=1 Цикл  
    ДокПост.Выгрузить(Тмп); 
    а=0;
    Если ТЗ.НайтиЗначение(Док.Фирма,а,"Фирма")=1 Тогда
    Для к=а По ТЗ.КоличествоСтрок() Цикл
    ТЗ.ПолучитьСтрокуПоНомеру(к);
    Если ТЗ.Фирма<>ДокПост.Фирма Тогда //кончилась фирма в ТЗ
    Прервать;
    КонецЕсли;
    Если ТЗ.Склад<>ДокПост.Склад Тогда //фирма та, но склад не тот
    Продолжить;
    КонецЕсли;
    Если ТЗ.Флаг = 1 Тогда //цену уже установили...
    Продолжить;
    КонецЕсли;
    кк=0;
    Если Тмп.НайтиЗнаяение(ТЗ.Номенклатура,кк,"Номенклатура")=1 Тогда
    Тмп.ПолучитьСтрокуПоНомеру(кк);
    ТЗ.Поставщик = ДокПост.Контрагент;
    ТЗ.Флаг = 1;
    ТЗ.Цена=Тмп.Цена; //этого в коде не было но по условию же вам нужна цена поступления
    КонецЕсли;
    КонецЦикла;
    КонецЕсли;
    Если ТЗ.Итог("Флаг")=ТЗ.КоличествоСтрок() Тогда
    Сообщить(" !!ALERT!! Cработало условие выхода  ");
    Прервать; 
    КонецЕсли;
    КонецЦикла;
    
    
    
    
  18. TopicStarter Overlay
    Vertex
    Offline

    Vertex Опытный в 1С

    Регистрация:
    14 июн 2011
    Сообщения:
    468
    Симпатии:
    4
    Баллы:
    29
    Я подредактировал алгортм который предложип фобец

    Код:
    ТЗ_Док = СоздатьОбъект("ТаблицаЗначений"); 
    
    Пока ТЗ.ПолучитьСтроку()=1 Цикл
    Сч = Сч + 1;       
    
    Если ТЗ.Товар = _ТоварБуфер Тогда
    ТЗ.УстановитьЗначение(Сч,"Поставщик",_КонтрБуфер);    
    ТЗ.УстановитьЗначение(Сч,"Флаг",1);  
    ТЗ.УстановитьЗначение(Сч,"ЦенаЗак",_ЦенаЗакБуфер);
    Сообщить(" Установлен поставщик из буфера "+ ТЗ.Товар);
    Продолжить;
    КонецЕсли;
    
    ДокПост.ОбратныйПорядок(1);
    ДокПост.ВыбратьДокументы();
    Пока ДокПост.ПолучитьДокумент()=1 Цикл  
    
    
    
    ТЗ_Док.УдалитьСтроки();
    
    СчСтр = 0;
    
    ДокПост.ВыгрузитьТабличнуюЧасть(ТЗ_Док);
    
    Если Тз_Док.НайтиЗначение(ТЗ.Товар,СчСтр,"Номенклатура")=0 Тогда
    Продолжить;
    Иначе    
    ТЗ.УстановитьЗначение(Сч,"Поставщик",ДокПост.Контрагент);    
    ТЗ.УстановитьЗначение(Сч,"Флаг",1);
    ТЗ.УстановитьЗначение(Сч,"ЦенаЗак",Тз_Док.ПолучитьЗначение(СчСтр,"Цена"));
    
    _ЦенаЗакБуфер = Тз_Док.ПолучитьЗначение(СчСтр,"Цена");
    _ТоварБуфер   = ТЗ.Товар;
    _КонтрБуфер   = ДокПост.Контрагент;    
    
    Сообщить(" Установлен флаг 1 "+Тз_Док.ПолучитьЗначение(СчСтр,"Номенклатура"));
    Прервать;
    КонецЕсли;
    КонецЦикла;  
    
    
    Если ТЗ.Итог("Флаг")=ТЗ.КоличествоСтрок() Тогда
    Сообщить(" !!ALERT!! Cработало условие выхода  ");
    Прервать; //цикл по документам
    КонецЕсли;
    Сообщить(Сч);
    КонецЦикла;
    
    
    Производительность возрасла многократно.
    Сравнил результаты, всё идентично, но всё же прошу опытных пробежаться глазами по строкам.....всё ли в порядке!?
    p.s Боюсь ошибиться
  19. Бухгалтерский угодник
    Offline

    Бухгалтерский угодник Администраторы Команда форума Администратор

    Регистрация:
    29 дек 2008
    Сообщения:
    21.523
    Симпатии:
    407
    Баллы:
    104
    Все зависит от частоты поступлений... Думаю в моем алгоритме (сначала доки потом ТЗ) будет еще быстрее. Дело в том что вы выбираете построчно номенклауру, а здесь заполняется сразу вся ТЧ документа....
  20. dianofob
    Offline

    dianofob (-_-)y-.o0O

    Регистрация:
    3 июл 2009
    Сообщения:
    711
    Симпатии:
    0
    Баллы:
    26
    имхо, "ТЗ.УстановитьЗначение(Сч,"Поставщик",ДокПост.Контрагент); " на больших объемах будет ощутимо медленнее чем "ТЗ.Поставщик = ДокПост.Контрагент".
    "ТЗ_Док.УдалитьСтроки();" - можно убрать.

    если документов относительно немного, но они большие (много строк) то наверное приемлемо.. если наоборот- то, скорее, соглашусь с Бухгалтерский угодником, проще будет пробежаться по докам один раз.. ну, а другую версию решения я уже предлагал :)

Поделиться этой страницей