Имя: Пароль:
1C
1С v8
Запрос ко всем документам. Нужна помощь
,
0 Varlant1n
 
28.10.20
09:21
Передо мной стоит задача создание внешней обработки с одной лишь кнопкой, при нажатии на которую произойдет следующее:
Обработка через запрос обратится ко всем документам. В каждом документе будут удалены все, кроме 5-и первых элементов в документе за месяц. То есть, как пример, у меня есть Документ АвансовыйОтчет. В этом документе очень много элементов. И они добавляются уже 8 месяцев. В каждом месяце добавлялось порядка 1000 элементов. Так вот при нажатии на кнопку мне надо, чтобы обработка в документе АвансовыйОтчет разделила элементы по месяцам и в каждом месяце удалила все, кроме первых 5 добавленных в этот месяц.

В данный момент на руках у меня есть следующий код:

Для Каждого МетоданноеДокументы Из Метаданные.Документы Цикл
        ИмяДокумента = МетоданноеДокументы.Имя;
        Запрос = Новый Запрос;
        Запрос.Текст =  
        "ВЫБРАТЬ
        |    "+ИмяДокумента+".Ссылка
        |ИЗ
        |    Документ."+ИмяДокумента+" КАК "+ИмяДокумента+"
        |ГДЕ
        |    "+ИмяДокумента+".Дата МЕЖДУ &НачальнаяДата И &КонечнаяДата
        |УПОРЯДОЧИТЬ ПО
        |     Дата
        |ИТОГИ ПО
        |     Дата ПЕРИОДАМИ(МЕСЯЦ, &НачальнаяДата, &КонечнаяДата)";
        НачальнаяДата = Дата(2000,1,1);
        КонечнаяДата = Дата(2030,1,1);
        Запрос.УстановитьПараметр("НачальнаяДата",НачальнаяДата);
        Запрос.УстановитьПараметр("КонечнаяДата",КонечнаяДата);
        Результат = Запрос.Выполнить().Выгрузить();
        Счетчик = 0;
        Для каждого Элемент Из Результат Цикл
            Счетчик = Счетчик + 1;
            Если Счетчик > 5 Тогда
                Элемент.Ссылка.ПолучитьОбъект().УстановитьПометкуУдаления(Истина);
                ПомеченныеНаУдаление = НайтиПомеченныеНаУдаление();
                УстановитьМонопольныйРежим(Истина);
                УдалитьОбъекты(ПомеченныеНаУдаление, Истина);
            Иначе
                Прервать;
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;

Но он не работает почему-то. При этом ошибку не выдает. В локальных переменных в ТипЗначения: АвансовыйОтчет, Null
1 ДенисЧ
 
28.10.20
09:24
Для каждого Элемент Из Результат Цикл
            Счетчик = Счетчик + 1;
            Если Счетчик > 5 Тогда
            Иначе
                Прервать;
            КонецЕсли;

У тебя цикл не выполняется ни разу
2 Varlant1n
 
28.10.20
09:27
Как я это могу исправить? У меня просто, видимо, мозгов не хватает... Буду Вам очень благодарен!
3 ДенисЧ
 
28.10.20
09:30
(2) Попробовать почитать учебник информатики за 9й класс, где циклы описываются?
Или хотя бы предназачение оператора Прервать в справке?
4 ДенисЧ
 
28.10.20
09:30
И кстати... Нигде не увидел проверку условия "первые 5 в _каждом_ месяце"...
5 ИУБиПовиц
 
28.10.20
09:32
(2) ну наверное так
Если Счетчик > 5 Тогда
Прервать;
            Иначе
//удаление
                
            КонецЕсли;

И монопольный режим зачем устанавливать при каждой итерации в истину, и не скидывать в ложь.
В чем смысл
(4) Ну итоги периодами сделал то, а конфигуратор сам догадается:)
6 ИУБиПовиц
 
28.10.20
09:33
И наверное, это долго будет работать:)
7 Chameleon1980
 
28.10.20
09:34
обходрезультатазапроса
8 ГдеСобака Зарыта
 
28.10.20
09:39
Человек, который придумал такое задание - больной. Держитесь от него подальше.
9 Varlant1n
 
28.10.20
09:45
(5)
Для Каждого МетоданноеДокументы Из Метаданные.Документы Цикл
        ИмяДокумента = МетоданноеДокументы.Имя;
        Запрос = Новый Запрос;
        Запрос.Текст =  
        "ВЫБРАТЬ
        |    "+ИмяДокумента+".Ссылка
        |ИЗ
        |    Документ."+ИмяДокумента+" КАК "+ИмяДокумента+"
        |ГДЕ
        |    "+ИмяДокумента+".Дата МЕЖДУ &НачальнаяДата И &КонечнаяДата
        |УПОРЯДОЧИТЬ ПО
        |     Дата
        |ИТОГИ ПО
        |     Дата ПЕРИОДАМИ(МЕСЯЦ, &НачальнаяДата, &КонечнаяДата)";
        НачальнаяДата = Дата(2000,1,1);
        КонечнаяДата = Дата(2030,1,1);
        Запрос.УстановитьПараметр("НачальнаяДата",НачальнаяДата);
        Запрос.УстановитьПараметр("КонечнаяДата",КонечнаяДата);
        Результат = Запрос.Выполнить().Выбрать();
        УстановитьМонопольныйРежим(Истина);
        Счетчик = 0;
        Для каждого Элемент Из Результат Цикл
            Счетчик = Счетчик + 1;
            Если Счетчик > 5 Тогда
                Прервать;
            Иначе
                Элемент.Ссылка.ПолучитьОбъект().УстановитьПометкуУдаления(Истина);
                ПомеченныеНаУдаление = НайтиПомеченныеНаУдаление();
                УдалитьОбъекты(ПомеченныеНаУдаление, Истина);
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;

Теперь 1С ругается таким образом:
{Обработка.ОбезличиваниеДанных.Форма.Форма.Форма(32)}: Итератор для значения не определен
        Для каждого Элемент Из Результат Цикл
10 Затейник
 
28.10.20
09:47
Тестовое задание?
11 Varlant1n
 
28.10.20
09:47
(10) Да, проект в университете
12 ДенисЧ
 
28.10.20
09:48
13 Затейник
 
28.10.20
09:49
(11) Запрос в цикле? Сразу двойка. и на пересдачу.
14 ИУБиПовиц
 
28.10.20
09:56
(9)
Результат = Запрос.Выполнить().Выбрать();
Верните выгрузить:)
15 Волшебник
 
28.10.20
09:58
(12) Мне тоже глаза резануло
16 ИУБиПовиц
 
28.10.20
09:59
(13) Ладно б еще работало, так еще и не работает как в задании требовалось:)
17 Затейник
 
28.10.20
10:01
В этой задаче прекрасно всё! И сомнительные условия! и разрушительный характер самой обработки! и выборка ВСЕХ документов! И бессмысленное удаление в каждом месяце оставление лишь 5 документов. Кстати, вопрос, как ты определяешь эти 5 первых документов которые требуется оставить ? по какому признаку ? по дате ? по сумме ? или просто на обум?
18 Varlant1n
 
28.10.20
10:03
(17) Я определяю 5 первых документов по дате. То есть мне надо в каждом документе оставить 5 первых добавленных, а остальные удалить...
19 Волшебник
 
28.10.20
10:07
Обработка ТерминаторБазДанных
20 Затейник
 
28.10.20
10:07
Но ведь пользователи могут вносить документы хаотично, сначала за 1 число, потом за 30, потом за 20, потом за 15. Получается перво добавленные документы у тебя в разных числах. Требуется уточнить условие задачи. Сортируем по дате документа или по дате фактического добавления?
21 Varlant1n
 
28.10.20
10:10
(20) Я сортировал по Дате (возрастание). Чтобы от первых документов к последним шло всё

|УПОРЯДОЧИТЬ ПО
|     Дата
22 ИУБиПовиц
 
28.10.20
10:11
(18) Как я понял, надо оставить первые 5 доков в месяце.
А в текущем виде Обработка оставит всего 5 доков каждого вида. вне зависимости от месяца
(20) Ну скорее всего по дате дока
23 Затейник
 
28.10.20
10:15
(21)

Так запрос ты должен обходить по группировкам, а не сплошником весь.
24 Varlant1n
 
28.10.20
10:17
(22) Но ведь я сортирую по периодам (Месяц)

|ИТОГИ ПО
|     Дата ПЕРИОДАМИ(МЕСЯЦ, &НачальнаяДата, &КонечнаяДата)";
25 Затейник
 
28.10.20
10:19
Что-то типа такого http://catalog.mista.ru/1c/articles/125988/
26 Затейник
 
28.10.20
10:25
После запроса ты должен получать не Таблицу значений, а ВЫБОРКУ!
и дальше обрабатывать данные из запроса выборкой по группировкой. еще пару вложенных циклов.
27 ИУБиПовиц
 
28.10.20
10:26
не сортируешь, а говоришь что запрос будет иметь итоги
И надо Результат = Запрос.Выполнить().Выгрузить();
А или выборку с обходои, ну или дерево с обходом
28 Varlant1n
 
28.10.20
10:32
(27) Вот я сделал следующее. Но все равно ошибка: {Обработка.ОбезличиваниеДанных.Форма.Форма.Форма(30)}: Метод объекта не обнаружен (Выбрать)
        ВыборкаДокумента = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруп




Результат = Запрос.Выполнить().Выгрузить();
        ВыборкаДокумента = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам, "Дата");
        Счетчик = 0;
        Пока ВыборкаДокумента.Следующий() Цикл
            Счетчик = Счетчик + 1;
            Если Счетчик > 5 Тогда
                ВыборкаДокумента.Ссылка.ПолучитьОбъект().УстановитьПометкуУдаления(Истина);
                ПомеченныеНаУдаление = НайтиПомеченныеНаУдаление();
                УстановитьМонопольныйРежим(Истина);
                УдалитьОбъекты(ПомеченныеНаУдаление, Истина);
            Иначе
                Прервать;
            КонецЕсли;
        КонецЦикла;
29 Волшебник
 
28.10.20
10:36
(28) Надо стараться. ВыборкаИзРезультатаЗапроса и ТаблицаЗначений — это разные объекты
30 ИУБиПовиц
 
28.10.20
10:52
Результат = Запрос.Выполнить().Выгрузить();
надо
Результат = Запрос.Выполнить()

и
  Если Счетчик > 5 Тогда
                ВыборкаДокумента.Ссылка.ПолучитьОбъект().УстановитьПометкуУдаления(Истина);
                ПомеченныеНаУдаление = НайтиПомеченныеНаУдаление();
                УстановитьМонопольныйРежим(Истина);
                УдалитьОбъекты(ПомеченныеНаУдаление, Истина);
            Иначе
                Прервать;
            КонецЕсли;
:)
ну сразу ж прервется:) говорили ж уже
31 Varlant1n
 
28.10.20
11:18
У меня к вам, дорогие форумчане, вопрос. Нужно ли мне пользоваться ИТОГИ ПО для того, чтобы группировать по месяцам, или надо пользоваться ГРУППИРОВАТЬ ПО? Потому что как только я в запросе использую ИТОГИ ПО, он мне выдает в результате таблицу значений.
32 Волшебник
 
28.10.20
11:19
(31) Скорее дерево значений
33 ДенисЧ
 
28.10.20
11:19
(31) Если ты делаешь итоги по, то и выгружать нужно соответственно не плоскую таблицу, а дерево.
Посмотри параметры РезультатЗапроса.Выгрузить()
34 Затейник
 
28.10.20
11:23
Таблица значений получается когда ты пишешь Результат = Запрос.Выполнить().Выгрузить();
А ты должен писать выборку ВыборкаПоИтогам = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПОГруппировкам, "Дата");

Пока ВыборкаПоИтогам.Следующий() Цикл

ВыборкаДокументов = ВыборкаПоИтогам.Выбрать();
  Пока ВыборкаДокументов.Следующий() Цикл

  КонецЦикла;
КонецЦикла;

Два вложенных цикла, первый по итогам, это твои месяца, второй цикл по документам внутри каждого месяца
35 Varlant1n
 
28.10.20
11:24
У переменной Результат: Значение: ТаблицаЗначений и Тип: ТаблицаЗначений
Это то, что я получаю результатом запроса. По идее там уже всё расположено по дате и по каждому месяцу. Но я не могу теперь сделать выборку и с помощью счетчика удалить ненужные мне документы. Так как у меня ошибка из-за Ссылка.ПолучитьОбъект().
36 Затейник
 
28.10.20
11:29
"У переменной Результат: Значение: ТаблицаЗначений и Тип: ТаблицаЗначений"

Вот здесь уже не правильно. Таблица значений тебе не нужна, она не подойдет для твоего проекта, так понятно ?
37 Varlant1n
 
28.10.20
11:29
(36) Да, понятно. Сейчас буду пробовать сделать так, как вы сказали выше. Посмотрю как получится
38 Затейник
 
28.10.20
11:32
Вот я сделал следующее. Но все равно ошибка: {Обработка.ОбезличиваниеДанных.Форма.Форма.Форма(30)}: Метод объекта не обнаружен (Выбрать)
        ВыборкаДокумента = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруп

Результат = Запрос.Выполнить().Выгрузить();

Так строчка должна быть одна.

1) Результат = Запрос.Выполнить().Выбрать(ОбходРезультатЗапроса.Погруппировкам, "Дата");
39 Varlant1n
 
28.10.20
11:34
(34) Огромное спасибо Вам за помощь! Просто огромное! И все остальным и за советы и за насмешки надо мной (это придает мотивации изучать программирование). Всё получилось! Но у меня к Вам последний вопрос. Стоит ли в цикле по документам, писать Попытку? То есть может ли данная процедура дать ошибку в каком-то случае? Допустим, когда документов нет.
40 ИУБиПовиц
 
28.10.20
12:40
(39) Если доков нет, то и  ошибки не будет, а вот если заблокирован может и дать
41 ИУБиПовиц
 
28.10.20
12:46
И кстати, не очень хорошо что дергаешь сервер в цикле по метаданным, можно вообще все в запрос унести и одним запросом выдернуть.
Но чет я попробовал, как то тормознуто получилось, но у мну доков то много что б так извращаться над ними:)

&НаСервере
Процедура ОкНаСервере()
    запрос = Новый Запрос;
    ПервыйВход = Истина;
    для каждого мета из Метаданные.Документы цикл
        ИмяДок = Мета.Имя;
        
         Подзапрос =   "ВЫБРАТЬ
         |    АвансовыйОтчет.Ссылка КАК Ссылка,
         |    АвансовыйОтчет.Док КАК ИмяДока,
         |    НАЧАЛОПЕРИОДА(АвансовыйОтчет.Дата, МЕСЯЦ) КАК Месяц
         |ПОМЕСТИТЬ Док
         |ИЗ
         |    Документ.АвансовыйОтчет КАК АвансовыйОтчет
         |ГДЕ
         |    АвансовыйОтчет.Дата >= &Дата
         |Объединить ВСЕ
         |";
        
         Подзапрос = Стрзаменить(Подзапрос,"АвансовыйОтчет.Док", """" + ИмяДОк + """" );
         Подзапрос = Стрзаменить(Подзапрос,"АвансовыйОтчет",ИмяДОк );
        

         Если не ПервыйВход тогда
            Подзапрос = Стрзаменить(Подзапрос,"ПОМЕСТИТЬ Док","" );
        КонецЕсли;
        

                 
        
        Запрос.Текст = Запрос.Текст + Подзапрос;
        ПервыйВход = ЛОЖЬ;
        
    КонецЦикла;
    

запрос.Текст = лев(Запрос.Текст, СтрДлина(Запрос.Текст)  - 16);

запрос.Текст = запрос.Текст + "
     |;
         |ВЫБРАТЬ РАЗЛИЧНЫЕ
         |    Док.Ссылка КАК Ссылка,
         |    Док.Месяц КАК Месяц,
     |    Док.ИмяДока КАК ИмяДока,
         |    СУММА(1) КАК Счетчик
         |ИЗ
         |    Док КАК Док
         |        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Док КАК Док1
         |        ПО Док.Месяц = Док1.Месяц
         |            И Док.ИмяДока = Док1.ИмяДока
         |            И Док.Ссылка.МоментВремени <= Док1.Ссылка.МоментВремени
         |
         |СГРУППИРОВАТЬ ПО
         |    Док.Ссылка,
         |    Док.Месяц ,
         |    Док.ИмяДока
         |
         |ИМЕЮЩИЕ
         |    КОЛИЧЕСТВО(Док1.Ссылка) <= 2 //тут 5 надо, но еще тормознутее будет
         |
         |УПОРЯДОЧИТЬ ПО
         |    ИмяДока,
         |    Месяц,
         |    Ссылка" ;

Запрос.УстановитьПараметр("Дата",объект.Дата);
тз = Запрос.Выполнить().Выгрузить();

СзНаУдаление = Новый СписокЗначений;

для каждого стр из тз цикл
    СзНаУдаление.Добавить(Стр.Ссылка);
КонецЦикла;

для каждого эл из СзНаУдаление цикл
    Об = эл.Значение;
    Сообщить(ОБ);
    //тут устанавливаешь пометку на удаление
КонецЦикла;

//тут ищешь помеченные и удаляешь,



    
КонецПроцедуры
42 Chameleon1980
 
28.10.20
13:37
развернули наконец (7)
43 Волшебник
 
28.10.20
13:40
(42) Ты знал, ты знал...