8.х Регистр сведений

Тема в разделе "Конфигурирование на платформе "1С:Предприятие 8"", создана пользователем mhl, 20 окт 2007.

  1. TopicStarter Overlay
    mhl
    Offline

    mhl Опытный в 1С

    Регистрация:
    23 июн 2007
    Сообщения:
    418
    Симпатии:
    0
    Баллы:
    26
    Столкнулся с такой проблемой. Имеется документ который берет данные из регистра сведений. Вот его код:
    Код:
    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    |    ПроизводственныеНормыСрезПоследних.Материал,
    |    ПроизводственныеНормыСрезПоследних.Период,
    |    ПроизводственныеНормыСрезПоследних.НомерДокумента
    |ИЗ
    |    РегистрСведений.ПроизводственныеНормы.СрезПервых КАК ПроизводственныеНормыСрезПервых";
    
    Запрос.УстановитьПараметр("Дата", ЭлементыФормы.Дата.Значение);
    Результат = Запрос.Выполнить();
    Выборка = Результат.Выбрать();
    Пока Выборка.Следующий() Цикл
    СтрокаТабличнойЧасти = ЭлементыФормы.ТаблЧасть.ТекущиеДанные;
    Если Выборка.Материал = СтрокаТабличнойЧасти.Номенклатура Тогда
    Докум = Документы.НормыПроизводства.Выбрать();
    Пока Докум.Следующий() Цикл
    Если Выборка.НомерДокумента = Докум.Номер Тогда
    ТабРасх = Докум.РасходныеМатериалы;
    Для Каждого ДСтр Из ТабРасх Цикл
    НоваяСтрока = ТаблЧасть.Добавить();
    НоваяСтрока.Номенклатура = ДСтр.Материал;
    НоваяСтрока.НормаКолво = ДСтр.Количество;
    НоваяСтрока.НормаЕдИзм = ДСтр.ЕдИзм;
    НоваяСтрока.НормаЦена = ДСтр.Цена;
    НоваяСтрока.НормаСумма = ДСтр.Сумма;
    КонецЦикла;
    КонецЕсли;
    КонецЦикла;
    КонецЕсли;
    КонецЦикла;
    
    
    Так вот, если сделать срез первых он не будет брать значения со старой датой, даже если другие значения отсутствуют. Если сделать срез последних, то наоборот не будет брать новые даты. Мне нужно чтобы он брал значения с датой как у документа, если такие отсутствуют, то наиболее близкие к ним.
  2. BabySG
    Offline

    BabySG Администраторы Команда форума Администратор

    Регистрация:
    10 июн 2007
    Сообщения:
    11.853
    Симпатии:
    12
    Баллы:
    29
    Как это вообще взлетело?
  3. lazy
    Offline

    lazy Модераторы Команда форума Модератор

    Регистрация:
    1 сен 2007
    Сообщения:
    2.127
    Симпатии:
    4
    Баллы:
    29
    Работать лень, поэтому разберу твой пример, в надежде показать ошибки, и направить в более верном направлении.

    В комментариях пояснены ошибки в данном коде.

    Код:
    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    |    ПроизводственныеНормыСрезПоследних.Материал,
    |    ПроизводственныеНормыСрезПоследних.Период,
    |    ПроизводственныеНормыСрезПоследних.НомерДокумента
    |ИЗ
    |    РегистрСведений.ПроизводственныеНормы.СрезПервых КАК ПроизводственныеНормыСрезПервых"; 
    
    Запрос.УстановитьПараметр("Дата", ЭлементыФормы.Дата.Значение);  // почему не использовал просто Дата?
    Результат = Запрос.Выполнить();
    Выборка = Результат.Выбрать();
    Пока Выборка.Следующий() Цикл // из за отсутствия сравнения в запросе эта выборка сделает кучу не нужных циклов
    СтрокаТабличнойЧасти = ЭлементыФормы.ТаблЧасть.ТекущиеДанные; // почему ты без конца обращаешься к одному и тому же элементу формы? поьзователь врядли успеет сдвинуть курсор в таблице. Соответственно все время выполнения модуля это будет одна и та же номенклатура, так зачем в теле цикла лишние инструкции?
    Если Выборка.Материал = СтрокаТабличнойЧасти.Номенклатура Тогда // вот эту конструкцию нужно заменить на параметр в запросе
    Докум = Документы.НормыПроизводства.Выбрать(); // Легко заменяется НайтиПоНомеру(<Номер документа>, <Дата интервала>) увеличивая производительность
    Пока Докум.Следующий() Цикл
    Если Выборка.НомерДокумента = Докум.Номер Тогда // ага, а если у тебя организация работает больше чем один год? в твою табличную часть будут попадать данные документов из предыдущих периодов, и кому то (возможно тебе) придется исправлять этот косяк. Причем с течением времени, юзеры привыкнут, к тому, что обработка работает верно, и будут жать не задумываясь - и смогут заметить, что у них материалов используется больше, чем надо спустя месяц(ы) с вытекающим отсюда скандалом и исправлять будет труднее...
    ТабРасх = Докум.РасходныеМатериалы;
    Для Каждого ДСтр Из ТабРасх Цикл
    НоваяСтрока = ТаблЧасть.Добавить();
    НоваяСтрока.Номенклатура = ДСтр.Материал;
    НоваяСтрока.НормаКолво = ДСтр.Количество;
    НоваяСтрока.НормаЕдИзм = ДСтр.ЕдИзм;
    НоваяСтрока.НормаЦена = ДСтр.Цена;
    НоваяСтрока.НормаСумма = ДСтр.Сумма;
    КонецЦикла;
    КонецЕсли;
    КонецЦикла;
    КонецЕсли;
    КонецЦикла;
    
    Вот примерный код, как следовало бы это переписать, естественно, что я это не проверял. Просто пример оптимизации. Как его использовать - решай сам:
    Код:
    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    |    ПроизводственныеНормыСрезПоследних.Материал,
    |    ПроизводственныеНормыСрезПоследних.Период,   
    |    ПроизводственныеНормыСрезПоследних.НомерДокумента
    |ИЗ
    |    РегистрСведений.ПроизводственныеНормы.СрезПоследних(&Дата, Материал = &Номенклатура) КАК ПроизводственныеНормыСрезПоследних";
    
    Запрос.УстановитьПараметр("Дата", Дата);
    Запрос.УстановитьПараметр("Номенклатура", ЭлементыФормы.ТаблЧасть.ТекущиеДанные.Номенклатура);
    
    Результат = Запрос.Выполнить();
    Выборка = Результат.Выбрать();
    Пока Выборка.Следующий() Цикл // собственно с учетом параметров к виртуальной таблице - в выборке должен быть только один эелемент, но я не уверен, не глянув на конфигурацию.
    Докум = НайтиПоНомеру(Выборка.НомерДокумента, <Дата интервала>); // вот здесь я не могу сориентироваться - у меня нету прод рукой твоего конфига, и поэтому дату интервала ты должен будешь сам придумать, как сделать. Думаю, что Выборка.Период подойдет. Да и сама технология в данном случае сомнительна в том смысле, что раз есть номер документа, значит есть и ссылка на документ, которую можно получить в запросе.
    ТабРасх = Докум.РасходныеМатериалы;
    Для Каждого ДСтр Из ТабРасх Цикл
    НоваяСтрока = ТаблЧасть.Добавить();
    НоваяСтрока.Номенклатура = ДСтр.Материал;
    НоваяСтрока.НормаКолво = ДСтр.Количество;
    НоваяСтрока.НормаЕдИзм = ДСтр.ЕдИзм;
    НоваяСтрока.НормаЦена = ДСтр.Цена;
    НоваяСтрока.НормаСумма = ДСтр.Сумма;
    КонецЦикла;
    КонецЦикла;
    
    В целом, считаю, что сам такой подход не оптимален. Скорее всего есть возможность извлечь данные получаемые в данном примере не из документа, а из регистра сведений или накопления.

    Так, же в одной из тем ты спрашивал, что такое виртуальные таблицы. Так вот, виртуальные таблицы - это механизм предоставляемый 1С, который расширяет возможности языка запросов по сравнению с языком запросов SQL.

    В отличие от "реальных" таблиц виртуальные нигде не хранятся, и генерируются сервером в момент обращения к ним. При обращении к виртуальным таблицам можно передавать параметры. И выходные данные будут включать в себя только данные вычисленные с использованием передаваемых параметров. Примером обращения к виртуальным таблицам служат СрезПервых,срезПоследних для регистров сведений, Остатки, Обороты для регистров накопления, ОборотКр,оборотДт для регистров бухгалтерии и т.д. Виртуальные таблицы бывают только у регистров. При этом данные виртуальных таблиц вычисляются - например при обращении к вирт. таблице Остатки ведется вычисление по регистру остатка по заданным в параметрах измерениях - результатами запроса будут суммы по каждому измерению регистра. т.е. все записи Расход и Приход будут суммироваться. У разных виртуальных таблиц разные наборы параметров. Обращение к параметрам ведется в скобках "РегистрСведений.ПроизводственныеНормы.СрезПоследних(&Дата, Номенклатура = &Номенклатура)", где через запятую перечислены параметры. Если параметр не указан, он выставляется "по умолчанию". Посмотреть - какие есть параметры и какую информацию выдает обращение к виртуальной таблице можно либо в Желтой книжечке которая идет в поставке 1С8(наиболее полно описываются), либо в конструкторе запросов(очень кратко, но всегда под рукой). За наглядными примерами и более подробными объяснениями отсылаю к книжкам товарища Радченко и прочих дядек...
  4. TopicStarter Overlay
    mhl
    Offline

    mhl Опытный в 1С

    Регистрация:
    23 июн 2007
    Сообщения:
    418
    Симпатии:
    0
    Баллы:
    26
    Попытался сделать так:
    Код:
    СтрокаТЧ = ЭлементыФормы.ТаблЧасть.ТекущиеДанные;
    Отбор = Новый Структура("Номенклатура", СтрокаТЧ.Номенклатура);
    Запись = РегистрыСведений.ПроизводственныеНормы.ПолучитьПоследнее(ТекущаяДата(), Отбор);
    
    Выдает ошибку на последней строке, неверный параметр №2

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