Имя: Пароль:
1C
1С v8
Знатоки помогите! Что это - глюк платформы или что??
, , ,
0 Vade_kirza
 
07.02.20
18:51
Всем веселой пятницы! задача была перенести строки с определенной номенклатурой из одной т.ч. в другую. казалось бы все просто но не тут то было. В общем обработку я написал, но она почему то не отрабатывала, я полез в отладчик и с удивлением заметил, что все работает! но как только я убрал точки останова, снова все перестало работать. т.е. те документы которые я прошел в отладке изменились, а дальше нет. В общем путем испытаний я понял, что как только я перестаю идти по отладке он перестает "видеть" нужную мне номенклатуру при сравнении. Вначале было простое сравнение на первые 5 букв имени, затем переделал на массив с номенклатурой, но результат одинаковый. Пока рвал волосы на себе заметил, что он делает сам 1 строку, а потом все. Так как задача разовая, сделал так, чтобы если хоть раз он нашел то что мне нужно он запускал всю процедуру заново. Так сработало, но я понять не могу что за фигня? пробовал на 8.3.16.1030, на 8.3.15.1830, конфа БП 3.0.75.70. Ниже прикладываю код обработки, за запрос в цикле не пинайте)) это вынужденная мера))
1 Vade_kirza
 
07.02.20
18:53
&НаСервере
Процедура ВыполнитьНаСервере()
    
        Массив = Новый Массив;
    ЗапросНоменклатура = Новый Запрос;
    ЗапросНоменклатура.Текст = "ВЫБРАТЬ
                               |    Номенклатура.Ссылка КАК Ссылка
                               |ИЗ
                               |    Справочник.Номенклатура КАК Номенклатура
                               |ГДЕ
                               |    Номенклатура.Наименование ПОДОБНО ""Полис%""";
    ЗапросНоменклатура.УстановитьПараметр("Полис", "Полис");
    ВыборкаНоменклатура = ЗапросНоменклатура.Выполнить().Выбрать();
    Пока ВыборкаНоменклатура.Следующий() Цикл
         Массив.Добавить(ВыборкаНоменклатура.Ссылка);
    КонецЦикла;
    Заново = Истина;
    Пока Заново Цикл
        Заново = Ложь;
    
    Запрос = Новый Запрос;
    Запрос.Текст =
        "ВЫБРАТЬ
        |    ОтчетОРозничныхПродажах.Ссылка КАК Ссылка
        |ИЗ
        |    Документ.ОтчетОРозничныхПродажах КАК ОтчетОРозничныхПродажах
        |ГДЕ
        |    ОтчетОРозничныхПродажах.Дата МЕЖДУ &ДатаНач И &ДатаКон";
    
    Запрос.УстановитьПараметр("ДатаКон", КонецДня(Объект.ДатаОкончания));
    Запрос.УстановитьПараметр("ДатаНач", НачалоДня(Объект.ДатаНачала));
    
    РезультатЗапроса = Запрос.Выполнить();
    
    ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
    НадоЗаписать = Ложь;
    Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
        НачатьТранзакцию();
        ДокОбъект = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
        Если ДокОбъект.РучнаяКорректировка Тогда
            ЗафиксироватьТранзакцию();
            Продолжить;
        КонецЕсли;
        Для каждого стр из ДокОбъект.Товары Цикл
//ТУТ вначале было просто сравнение Если ВРЕГ(Лев(стр.номенклатура, 5)) = "ПОЛИС" Тогда, потом переделал так как тут
            Индекс = Массив.Найти(стр.Номенклатура);
            Если Индекс <> Неопределено Тогда
                Заново = Истина;
                НовСтрока = ДокОбъект.АгентскиеУслуги.Добавить();
                ЗаполнитьЗначенияСвойств(НовСтрока, стр);
                НовСтрока.СчетРасчетов = ПланыСчетов.Хозрасчетный.ПрочиеРасчетыСРазнымиДебиторамиИКредиторами;
                НовСтрока.Контрагент = Справочники.Контрагенты.НайтиПоКоду("00-000322");
                НовСтрока.ДоговорКонтрагента = Справочники.ДоговорыКонтрагентов.НайтиПоКоду("00-000413");
                ДокОбъект.Товары.Удалить(стр);
                НадоЗаписать = Истина;
            КонецЕсли;
        КонецЦикла;
        Если НадоЗаписать Тогда
        Попытка
            ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
//пробовал тут вставить 3 секунды задержки, не помогло
            НадоЗаписать = Ложь;
    Исключение
        ОтменитьТранзакцию();
        КонецПопытки;
        КонецЕсли;
        ЗафиксироватьТранзакцию();
    КонецЦикла;
    КонецЦикла;
    
КонецПроцедуры
2 lodger
 
07.02.20
18:58
и тут такой же
Один и тот же код выполняется по-разному в зависимости от скорости работы. Глюки? )

у вас одна пятница на двоих?
опять наблюдение Отладчиком нарушает квантовую неопределенность копрокода?
3 Надо работать
 
07.02.20
18:58
кеш почисть
4 Vade_kirza
 
07.02.20
19:02
(3) кеш чистый, я ж базу только загрузил себе
5 Vade_kirza
 
07.02.20
19:03
(2) ссылка не открывается( 404 not found
6 lubitelxml
 
07.02.20
19:03
7 AlvlSpb
 
07.02.20
19:41
(0) Убери везде НачатьТранзакцию(), Отменить и Зафиксировать.
8 Лефмихалыч
 
07.02.20
20:27
за такой код в приличных местах могут кодилище начистить до блеска
9 Vade_kirza
 
07.02.20
21:09
(7) я это добавил потом, после того как понял, что происходит, это была просто проверка
10 Vade_kirza
 
07.02.20
21:10
(8) простите за мой код, но тут вопрос не в этом, а почему такое происходит. Можете дать мне свой вариант кода, я его проверю и отпишусь тут
11 Vade_kirza
 
07.02.20
21:15
(8) давайте проще скажу - вот строчка кода: "Если ВРЕГ(Лев(стр.номенклатура, 5)) = "ПОЛИС" Тогда", в ДокОбъект.Товары 5 строк, в каждой одна и та же номенклатура, я 2 раза прохожу отладкой - он удаляет эти 2 строки и переносит в таб часть Агентские услуги. далее я убираю точку остановки и ставлю ее на ДокОбъект.Записать(РежимЗаписиДокумента.Проведение) и нажимаю F5, когда он встает туда, я вижу что в ДокОбъект.товары - 3 строки. Почему? т.е. после того как я перестал идти отладчиком он перестал видеть что ВРЕГ(Лев(стр.номенклатура, 5)) = "ПОЛИС" = Истина
12 Vade_kirza
 
07.02.20
21:15
(8) Вопрос именно в этом, а не в том, какой у меня код
13 Vade_kirza
 
07.02.20
21:17
(8) далее я подумал, что возможно глюк платформы на сравнение строк и переделал, как в моем коде - на проверку есть ли данная номенклатура в массиве, но результат оказался тот же
14 Доминошник
 
07.02.20
21:19
(11)
1. в ДокОбъект.Товары 5 строк
2. он удаляет эти 2 строки
3. я вижу что в ДокОбъект.товары - 3 строки

Вроде всё норм (5-2=3)? Или я чего-то не понимаю..
15 Vade_kirza
 
07.02.20
21:19
(14) он должен был дальше удалить эти 3 строки так же как удалил первые 2
16 Доминошник
 
07.02.20
21:23
(15) А зачем, обходя в цикле табличную часть, пытаться удалять строки?
На сколько я понимаю, не так это делается (или надо обходить "с конца")....
17 Vade_kirza
 
07.02.20
21:24
(16) есть 10 строк в т.ч. Товары, из них 5 туда попали ошибочно при загрузке откуда то, нужно их из Товары удалить и перенести их в Агентские услуги
18 Доминошник
 
07.02.20
21:28
(17)
https://helpf.pro/faq/view/515.html
v8: Удаление строк табличной части справочника по условию

Сначала отбери, что нужно удалить, потом это "только нужное" удаляй.
19 AlvlSpb
 
07.02.20
21:31
(13) Твоя ошибка в том, что ты удаляешь строки в ТЧ сразу в цикле
Смотри: Удалил строку с индексом 0, на ее место встала строка с инд 1 и стала с инд 0. Цикл переходит к след строке (изначально она с инд 2, но стала с инд 1) В итоге каждая четная строка НЕ удаляется. Поэтому у тебя переносится только три строки. Сделай 7 строк и перенесется 4 строки и т.д.
20 Vade_kirza
 
07.02.20
21:35
(19) 1)почему тогда в отладке все работает?
21 Vade_kirza
 
07.02.20
21:38
(19) давай по другому, я прошел отладкой 5 документов - все ок, как только выключил - перестало работать.
22 AlvlSpb
 
07.02.20
22:17
(20) Да не работает и в отладке, не может работать. Тебе выше дали ссылки как делать.
23 Borteg
 
07.02.20
22:40
Для каждого стр из ДокОбъект.Товары Цикл
//ТУТ вначале было просто сравнение Если ВРЕГ(Лев(стр.номенклатура, 5)) = "ПОЛИС" Тогда, потом переделал так как тут

            Индекс = Массив.Найти(стр.Номенклатура);
            Если Индекс <> Неопределено Тогда
                Заново = Истина;
                НовСтрока = ДокОбъект.АгентскиеУслуги.Добавить();
                ЗаполнитьЗначенияСвойств(НовСтрока, стр);
                НовСтрока.СчетРасчетов = ПланыСчетов.Хозрасчетный.ПрочиеРасчетыСРазнымиДебиторамиИКредиторами;
                НовСтрока.Контрагент = Справочники.Контрагенты.НайтиПоКоду("00-000322");
                НовСтрока.ДоговорКонтрагента = Справочники.ДоговорыКонтрагентов.НайтиПоКоду("00-000413");
                ДокОбъект.Товары.Удалить(стр);
                НадоЗаписать = Истина;
            КонецЕсли;
        КонецЦикла;

Ты в одном цикле и перебираешь и удаляешь???
24 dmpl
 
07.02.20
22:54
(0) Какие выражения вычисляются в Табло?
25 Лефмихалыч
 
08.02.20
09:39
(10) потому и происходит, что код так написан. В нем нечего чинить, его надо написать с нуля правильно. Запрос должен быть только ОДИН. В цикле не должно быть запросов. Вечный цикл не нужен. Трюки с транзакцией - в пень выкинуть. Циклы по строкам ТЧ - убрать. НайтиПоКоду - убрать.
Если после этого всего чудеса продолжатся, тогда приходи. А до тех пор обсуждать нечего: код - говнище, а говнище правильно работать не может.
26 Конструктор1С
 
08.02.20
13:26
Омайгадбл, Данила! Ты что, крэйзи? (с)

Код под просто ужасен
27 Конструктор1С
 
08.02.20
13:34
Чувак, у тебя в коде мёд, говно и пчёлы. Декомпозиция просто ужасная. За раз ты пытаешься делать несколько дел - сидеть на стуле, жонглировать, танцевать и петь песню. Удивительно ли, что при такой "многозадачности" постоянно что-то отваливается... Разложи задачу на составные части и решай их последовательно
28 Vade_kirza
 
08.02.20
15:33
(25) 1) трюки с транзакцией мне просто посоветовали попробовать, уберу так как не помогло. 2) запросов у меня 2, хорошо переделаю в один но так как разовая задача это не имеет значения. 3) вечного цикла нет.4) без найти по коду никак, так как в ТЧ агентские услуги есть поля которых нет в Товары, их надо заполнить определенными значениями. Единственное, я не знаю как избавится от цикла по строкам ТЧ, если подскажете как сделать правильно буду благодарен.
29 Vade_kirza
 
08.02.20
15:39
(25) про НайтиПоКоду понял, Вы имеете в виду то, что надо заранее найти их, а потом только вставлять значение.
30 craxx
 
08.02.20
15:42
(29) тебе нельзя программировать. Освой другую профессию.
31 Vade_kirza
 
08.02.20
15:44
(30) спасибо
32 Vade_kirza
 
08.02.20
15:47
(30) именно для этого я и создал эту ветку, чтобы понять это мои ошибки или нет. Если мои, то я был бы рад узнать в чем они, и в будущем не повторять их
33 Vade_kirza
 
08.02.20
15:48
(30) на данный момент, из того что написал Лефмихалыч, я понял что ошибка в обходе в цикле ТЧ и удалением строк, теперь хочу понять как сделать правильно
34 rphosts
 
08.02.20
15:55
(1) ёкарный бабай!!!
35 Vade_kirza
 
08.02.20
17:40
Все, спасибо всем (7) (8) (14) (19) (22) (23) (27) да это говнокод, но благодаря Вам я понял что это не глюк а именно говнокод) переделал все как писали выше и заработало. Всех обнимаю, благодаря Вам я узнаю новое, не пинайте пожалуйста.
36 Vade_kirza
 
08.02.20
17:41
&НаСервере
Процедура ВыполнитьНаСервере()
    Массив = Новый Массив;
    ЗапросНоменклатура = Новый Запрос;
    ЗапросНоменклатура.Текст = "ВЫБРАТЬ
    |    Номенклатура.Ссылка КАК Ссылка
    |ИЗ
    |    Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |    Номенклатура.Наименование ПОДОБНО ""Полис%""";
    ЗапросНоменклатура.УстановитьПараметр("Полис", "Полис");
    ВыборкаНоменклатура = ЗапросНоменклатура.Выполнить().Выбрать();
    Пока ВыборкаНоменклатура.Следующий() Цикл
        Массив.Добавить(ВыборкаНоменклатура.Ссылка);
    КонецЦикла;
    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    |    ОтчетОРозничныхПродажах.Ссылка КАК Ссылка
    |ИЗ
    |    Документ.ОтчетОРозничныхПродажах КАК ОтчетОРозничныхПродажах
    |ГДЕ
    |    ОтчетОРозничныхПродажах.Дата МЕЖДУ &ДатаНач И &ДатаКон";    
    Запрос.УстановитьПараметр("ДатаКон", КонецДня(Объект.ДатаОкончания));
    Запрос.УстановитьПараметр("ДатаНач", НачалоДня(Объект.ДатаНачала));    
    РезультатЗапроса = Запрос.Выполнить();    
    ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
    НадоЗаписать = Ложь;
    Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
        ДокОбъект = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
        СтруктураДляПоиска = Новый Структура("Номенклатура", Массив);
        Если ДокОбъект.РучнаяКорректировка Тогда
            Продолжить;
        КонецЕсли;
        Для каждого стр из ДокОбъект.Товары Цикл
            Индекс = Массив.Найти(стр.Номенклатура);
            Если Индекс <> Неопределено Тогда        
                НовСтрока = ДокОбъект.АгентскиеУслуги.Добавить();
                ЗаполнитьЗначенияСвойств(НовСтрока, стр);
                НовСтрока.СчетРасчетов = ПланыСчетов.Хозрасчетный.ПрочиеРасчетыСРазнымиДебиторамиИКредиторами;
                НовСтрока.Контрагент = Справочники.Контрагенты.НайтиПоКоду("00-000322");
                НовСтрока.ДоговорКонтрагента = Справочники.ДоговорыКонтрагентов.НайтиПоКоду("00-000413");
                НадоЗаписать = Истина;
            КонецЕсли;
        КонецЦикла;
        КолВо = ДокОбъект.Товары.Количество()-1;        
        ИндексСтроки = КолВо;        
        Для счетчик = 0 по КолВо Цикл            
            Запись = ДокОбъект.Товары.Получить(ИндексСтроки);
            Индекс = Массив.Найти(стр.Номенклатура);
            Если Индекс <> Неопределено Тогда
                НадоУдалить = Истина;
            Иначе
                НадоУдалить = Ложь;
            КонецЕсли;            
            если НадоУдалить тогда                
                ДокОбъект.Товары.Удалить(Запись);                
            КонецЕсли;            
            ИндексСтроки = ИндексСтроки - 1;            
        КонецЦикла;  
        Если НадоЗаписать Тогда
            МассивПустыхСтрок = ДокОбъект.Товары.НайтиСтроки(СтруктураДляПоиска);             
            Для каждого Строка Из МассивПустыхСтрок Цикл                 
                ДокОбъект.Товары.Удалить(Строка);             
            КонецЦикла;
            ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
            НадоЗаписать = Ложь;
        КонецЕсли;
    КонецЦикла;    
КонецПроцедуры
37 Vade_kirza
 
08.02.20
17:43
Если и тут есть то, "за что в приличных местах могут кодилище начистить" (c) Лефмихалыч,  укажите - исправлю
38 Vade_kirza
 
08.02.20
18:02
Извиняюсь, не тот код выложил (36)
39 Vade_kirza
 
08.02.20
18:02
Процедура ВыполнитьНаСервере()
    Массив = Новый Массив;
    ЗапросНоменклатура = Новый Запрос;
    ЗапросНоменклатура.Текст = "ВЫБРАТЬ
    |    Номенклатура.Ссылка КАК Ссылка
    |ИЗ
    |    Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |    Номенклатура.Наименование ПОДОБНО ""Полис%""";
    ЗапросНоменклатура.УстановитьПараметр("Полис", "Полис");
    ВыборкаНоменклатура = ЗапросНоменклатура.Выполнить().Выбрать();
    Пока ВыборкаНоменклатура.Следующий() Цикл
        Массив.Добавить(ВыборкаНоменклатура.Ссылка);
    КонецЦикла;
    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    |    ОтчетОРозничныхПродажах.Ссылка КАК Ссылка
    |ИЗ
    |    Документ.ОтчетОРозничныхПродажах КАК ОтчетОРозничныхПродажах
    |ГДЕ
    |    ОтчетОРозничныхПродажах.Дата МЕЖДУ &ДатаНач И &ДатаКон";    
    Запрос.УстановитьПараметр("ДатаНач", НачалоДня(Объект.ДатаНачала));
    Запрос.УстановитьПараметр("ДатаКон", КонецДня(Объект.ДатаОкончания));
    РезультатЗапроса = Запрос.Выполнить();    
    ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
    НадоЗаписать = Ложь;
    Контрагент = Справочники.Контрагенты.НайтиПоКоду("00-000322");
    Договор = Справочники.ДоговорыКонтрагентов.НайтиПоКоду("00-000413");
    Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
        ДокОбъект = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
        Если ДокОбъект.РучнаяКорректировка Тогда
            Продолжить;
        КонецЕсли;
        Для каждого стр из ДокОбъект.Товары Цикл
            Индекс = Массив.Найти(стр.Номенклатура);
            Если Индекс <> Неопределено Тогда        
                НовСтрока = ДокОбъект.АгентскиеУслуги.Добавить();
                ЗаполнитьЗначенияСвойств(НовСтрока, стр);
                НовСтрока.СчетРасчетов = ПланыСчетов.Хозрасчетный.ПрочиеРасчетыСРазнымиДебиторамиИКредиторами;
                НовСтрока.Контрагент = Контрагент;
                НовСтрока.ДоговорКонтрагента = Договор;
                НадоЗаписать = Истина;
            КонецЕсли;
        КонецЦикла;
        КолВо = ДокОбъект.Товары.Количество()-1;        
        ИндексСтроки = КолВо;        
        Для счетчик = 0 по КолВо Цикл            
            Запись = ДокОбъект.Товары.Получить(ИндексСтроки);
            Индекс = Массив.Найти(стр.Номенклатура);
            Если Индекс <> Неопределено Тогда
                НадоУдалить = Истина;
            Иначе
                НадоУдалить = Ложь;
            КонецЕсли;            
            если НадоУдалить тогда                
                ДокОбъект.Товары.Удалить(Запись);                
            КонецЕсли;            
            ИндексСтроки = ИндексСтроки - 1;            
        КонецЦикла;  
        Если НадоЗаписать Тогда
            ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
            НадоЗаписать = Ложь;
        КонецЕсли;
    КонецЦикла;    
КонецПроцедуры
40 Ёпрст
 
08.02.20
18:20
(39) всё как бэ в топку
41 Vade_kirza
 
08.02.20
18:23
(40) Ваш ник полностью отражает мою реакцию на Ваш ответ((
42 Ёпрст
 
08.02.20
18:23
Написать ОДИН запрос, в котором будут ССылки на ОтчетОРозничныхПродажах и нужные строки для удаления.
И всякие условия типа ДокОбъект.РучнаяКорректировка воткнуть в сам текст запроса, Выкинуть из кода вот это -  Контрагент = Справочники.Контрагенты.НайтиПоКоду("00-000322");
    Договор = Справочники.ДоговорыКонтрагентов.НайтиПоКоду("00-000413");

и задать это через реквизиты формы с типом клиентос и договор.
43 Ёпрст
 
08.02.20
18:27
И если че.. то вот так удалять


  Для счетчик = 0 по КолВо Цикл            
            Запись = ДокОбъект.Товары.Получить(ИндексСтроки);
      ДокОбъект.Товары.Удалить(Запись);



Не верно, удаляют с конца коллекции

  Для счетчик = - ДокОбъект.Товары.Количество() по -1 Цикл            
            Запись = ДокОбъект.Товары[-счетчик+1];
            ДокОбъект.Товары.Удалить(Запись);
44 Vade_kirza
 
08.02.20
18:33
(43) Спасибо! по поводу того, что должен быть один запрос - да, я согласен, но если это разовая задача и мне так проще и это не влияет на конечный результат? согласен, нужно учиться делать так, чтобы ПРОЩЕ было сделать ПРАВИЛЬНО, но на данный момент, к сожалению, мне не хватает опыта
45 Vade_kirza
 
08.02.20
18:34
(43) Для счетчик = 0 по КолВо Цикл            
            Запись = ДокОбъект.Товары.Получить(ИндексСтроки);
      ДокОбъект.Товары.Удалить(Запись);

Это гугл подсказал...
46 Лефмихалыч
 
08.02.20
18:38
(39) гораздо лучше, но все равно хрень.
Запросом выбери номера строк, которые надо перенести, с сортирвкой по убыванию номера строки. В запросе сделай итоги по документу. При обходе группировке по документу получаешь объект документа, потом при обходе детальных записей добавляешь строку копированием во вторую ТЧ и удаляешь строку из первой. Всё это - просто по номеру строки. После обхода детальных записей просто записываешь документ.
47 acht
 
08.02.20
18:49
(46) > Запросом выбери номера строк

А потом в промежутке между выполнением запроса и обработкой объекта внезапно выполняется давно ждущая своего часа транзакция второго сеанса, которая измененяет документ вместе с его номерами строк. И ты тут же начининаешь раздавать советы о важности блокировок и заставляешь накручивать безумные конструкции кода (:

Здесь как раз ссылками лучше оперировать. Выбрать верхним уровнем документы-кандидаты на обработку, в нижней группировке - номенклатуру. При проходе по объекту прописать вариант, что если номенклатуры нет, то пропускаешь весь документ.
48 Лефмихалыч
 
08.02.20
19:02
(47) тупое бесполезное умствование и попытка самоутвердиться за чужой счет
49 acht
 
08.02.20
19:07
(48) Явная обида и демонстрация комплексов?
50 Лефмихалыч
 
08.02.20
19:25
(49) констатация факта