Вход | Регистрация


1С:Предприятие :: 1С:Предприятие 7.7 и ранее

v7: Пропуск из ТЗ элементов

v7: Пропуск из ТЗ элементов
Я
   myr4ik07
 
13.09.16 - 23:09
ТЗ - таблица знач в которой выгружены остатки с фильтром склад и номенкл группа.
Перебираю ТЗ и вижу, что некоторые строки из ТЗ пропускаются в цикле, отладчиком смотрю на "них" - данные есть, обычные строки.
http://paste1c.ru/zJW код

логика заключается удалить из ТЗ строки, которые не соответствуют некому условию, может тут беда?
 
 
   Franchiser
 
1 - 13.09.16 - 23:15
Да, строки надо перебирать с конца.
Как-то так:
для сч = -ТЗ.Количество() по -1 цикл
сч = сч+1;
КонецЦикла;
   Franchiser
 
2 - 13.09.16 - 23:17
ВНИМАНИЕ
Часто требуется удалить строки, удовлетворяющие определенному условию.
Так как при удалении строки из таблицы значений следующая строка становится текущей,
то указанная ниже программа может удалить НЕ ВСЕ необходимые строки.

//ЭТА ПРОГРАММА НЕПРАВИЛЬНАЯ !!!
ТабЗнач.ВыбратьСтроки();
Пока ТабЗнач.ПолучитьСтроку()=1 Цикл
...Если <условие> Тогда
......ТабЗнач.УдалитьСтроку();//следующая строка стала текущей,

...КонецЕсли;
КонецЦикла;


В этом случае я рекомендую использовать следующий прием:

ТабЗнач.ВыбратьСтроки();
Пока ТабЗнач.ПолучитьСтроку()=1 Цикл
~начало: 
...Если <условие> Тогда
......ТабЗнач.УдалитьСтроку();//следующая строка стала текущей

......Если ТабЗнач.НомерСтроки<>0 Тогда
........ Перейти ~начало;
......КонецЕсли;
...КонецЕсли;
КонецЦикла;

А вот еще один правильный алгоритм, предложенный Wlad:

ТабЗнач.выбратьстроки();
Пока ТабЗнач.ПолучитьСтроку()=1 Цикл
.......Пока (<условие>) и (ТабЗнач.НомерСтроки<>0) Цикл
..............ТабЗнач.УдалитьСтроку();//следующая строка стала текущей

.......КонецЦикла;
КонецЦикла;
http://www.mista.ru/tutor_1c/tz.htm
   myr4ik07
 
3 - 13.09.16 - 23:20
(2) да, читал эту статью и по чему то без внимания
   myr4ik07
 
4 - 13.09.16 - 23:22
(2) атасец, как бы оно
    Пока ТЗ.ПолучитьСтроку() = 1 Цикл     
                ~начало: 
                //получим из ТЗ следующую номенклатуру     

                
                //выберем документы с опеределенным периодом

                РасходнаяНакладная = создатьобъект("документ.РасходнаяНакладная");     
                ВыборкаДокументов = РасходнаяНакладная.ВыбратьДокументы(ДнейНеликвид,ТекущаяДата());            

                пока РасходнаяНакладная.ПолучитьДокумент()=1 Цикл   
                    //не проведенные пропускаем

                //    если РасходнаяНакладная.Проведен() = 0 тогда

                //        продолжить;

                //    конецесли;    

                    //помечанные на удаление пропускаем

                //    если РасходнаяНакладная.ПометкаУдаления() = 1 тогда

                //        продолжить;

                //    конецесли;

                    
                    
                    //получим из выборки следующий документ    

                    
                    ТабличнаяЧастьДокумента = создатьобъект("ТаблицаЗначений");  
                    //выгружаем в ТЗ ТЧ документа

                    РасходнаяНакладная.ВыгрузитьТабличнуюЧасть(ТабличнаяЧастьДокумента,"ТМЦ");
                    
                    ИдСтроки = 0;
                    если ТабличнаяЧастьДокумента.НайтиЗначение(ТЗ.ТМЦ,ИдСтроки,"ТМЦ") = 1 тогда
                        //в ТЧ документа была найдена номенклатура - не нужно показывать ее в отчете

                        ТЗ.УдалитьСтроку();  
                        Если ТЗ.НомерСтроки<>0 Тогда 
                            Перейти ~начало;
                        КонецЕсли;
                        иначе         
                        //в ТЧ документа не была найдена номенклатура - покажем ее в отчете

                        продолжить;
                    конецесли;
                конеццикла;    
            конеццикла;

очень спасибо
   Garykom
 
5 - 13.09.16 - 23:22
Для особо продвинутых удалялщиков... Повторю не нужно удалять строки из ТЗ.

Лучше переносить только нужные строки в новую ТЗ.
   Franchiser
 
6 - 13.09.16 - 23:22
я предпочитаю искать в типовом коде 7.7 (например ЗИК) строку по конфигурации"по -1 цикл" и делаю такое удаление по номеру строки.
   myr4ik07
 
7 - 13.09.16 - 23:25
(5) та мне в голове из 8-ки так привычнее )) вот поэтому и беда
   hhhh
 
8 - 13.09.16 - 23:28
(7) в 8-ке та же фигня.
   Franchiser
 
9 - 13.09.16 - 23:29
(8) в 8-ке если удалять в цикле "для каждого" если не ошибаюсь все ок
   myr4ik07
 
10 - 13.09.16 - 23:31
(8) для каждого все норм, та и вообще, никаких проблем не было с удаление в 8-ке, не знаю даже о чем ты
 
 Рекламное место пустует
   Franchiser
 
11 - 13.09.16 - 23:32
(10) не ну если удалять в цикле для сч=0 по Тз.КоличествоСтрок()  то м.б. проблемы
   myr4ik07
 
12 - 13.09.16 - 23:32
(8) * о чем Вы (10) имел ввиду
   myr4ik07
 
13 - 13.09.16 - 23:33
(11) ну, короче я не сталкивался с проблемой такой поэтому заблудился )
   myr4ik07
 
14 - 13.09.16 - 23:33
всем спасибо
   Zhuravlik
 
15 - 13.09.16 - 23:41
(9) не ок
(0) Лучше всего не морочиться - если условие сложное, перебрать ТЗ, строки к удалению поместить в массив. Потом перебрать массив, из тз удалить нужные строки. Это не самое быстрое, но самое простое. И самое понятное. Особенно когда смотришь на этот код через пару месяцев.
А самое верное решение - это (5) - не допускать наличия в ТЗ лишних строк.
   Zhuravlik
 
16 - 13.09.16 - 23:44
(2)(3) это для 7.7 :)
(4) Метки использовать нехорошо
   Franchiser
 
17 - 13.09.16 - 23:48
(15) есть метод НАйтиСтроки() и потом перебор массива этих строк (с типом строка тз) для последующего удаления
   Zhuravlik
 
18 - 13.09.16 - 23:50
(17) Тогда уж Скопировать() с отбором по структуре :)
   Zhuravlik
 
19 - 13.09.16 - 23:51
(17) перебор массива нужен для сложного условия, которое в структуру не загонишь. Но можно добавлять булевскую колонку, заполнять ее по условию, потом Скопировать() с отбором по ней же. По идее самый быстрый способ для v8.
   Zhuravlik
 
20 - 13.09.16 - 23:54
А для 77 самый лучший способ - это вот такой:

//****************************************************************************** 

// ОчисткаТЗ() 
// Параметры: ТЗ, которую надо очистить 

// В ТЗ д.б. Колонки с идентификаторами "НадоУдалить" и "ОПС" (оригинальный порядок строк) 
// Описание: очищает ТЗ от ненужных строк 

Процедура глОчисткаТЗ(ТЗдляЧистки, ОПС="+ОПС", КолонкаУдалить="НадоУдалить", Режим=0) Экспорт 

Попытка НадоУдалить = ТЗдляЧистки.Итог(КолонкаУдалить); 
Исключение    Возврат; 
КонецПопытки; 

ТЗКС = ТЗдляЧистки.КоличествоСтрок(); 
Если Режим <> 0 Тогда 
Сообщить("> ["+ТекущееВремя()+"]: *** удаляем "+НадоУдалить+" из "+ТЗКС+" ****"); 
КонецЕсли; 

Если НадоУдалить <= 0 Тогда Возврат; КонецЕсли; 

Если НадоУдалить >= ТЗКС Тогда 
ТЗдляЧистки.УдалитьСтроки(); 
Иначе 
ТЗРаб = СоздатьОбъект("ТаблицаЗначений"); 
ТЗдляЧистки.Выгрузить(ТЗРаб); 
ТЗРаб.Сортировать("+"+КолонкаУдалить); 
ТЗРаб.Выгрузить(ТЗдляЧистки,1,ТЗКС-НадоУдалить); 
ТЗРаб = 0; 
КонецЕсли; 
Если ОПС = "###" Тогда Возврат; КонецЕсли;//сортировать не надо 

//восстановим оригинальный порядок строк 
ТЗдляЧистки.Сортировать(ОПС); 
КонецПроцедуры    //глОчисткаТЗ()



Взято отсюда http://catalog.mista.ru/public/57376/, пост 19.
В свое время забирал себе в конфу, в глобальник.
   Franchiser
 
21 - 14.09.16 - 00:00
Ну Скопировать() я бы не советовал (только в крайнем случае, когда нельзя описать ОТБОР), т.к. если ТЗ большая это и много строк нужно удалять - будет жрать оперативную память.
   Franchiser
 
22 - 14.09.16 - 00:01
(20) слишком заморочено, нормальной способ перебор строк ТЗ и удаления с конца - мало кода и все понятно
   Злопчинский
 
23 - 14.09.16 - 00:51
(22)  этот код практически самый быстрый из нескольких вариантов - ещё на проклабе тестили, и этот ещё можно ускорить заменив метод выгрузить на метод заполнить

А вот вариант с обрезкой количества строк одноимённым методом был чем-то косячный
   Simod
 
24 - 14.09.16 - 07:43
(0) За последние 15 лет тему поднимали несколько сотен раз.
(23) После сортировки и установки количества строк сбивается сортировка и удаляются не те строки.
   Злопчинский
 
25 - 14.09.16 - 08:27
(24)  аиесли отсортировать и перекинуть в другую из и обрезать количеством строк то тожеикосяк будет?
   Это_mike
 
26 - 14.09.16 - 08:31
а индексированную таблицу - рассматриваем? :-)
   Duke1C
 
27 - 14.09.16 - 09:43
(4) еще какой атасец, глядя на код))
Вот так попробуй:

        СписЗн=СоздатьОбъект("СписокЗначений");
    ТЗ.Выгрузить(СписЗн,,,"Номенклатура");
    ВыбКонПериода=ТекущаяДата();
    Запрос = СоздатьОбъект("Запрос");
    ТекстЗапроса = "Период с ДнейНеликвид по ВыбКонПериода;
    |Номенклатура = Документ.РасходнаяНакладная.Номенклатура;
    |Функция Счётчик = Счётчик();
    |Группировка Номенклатура;
    |Условие(Номенклатура в СписЗн);";
    Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
        Возврат;
    КонецЕсли;
    Пока Запрос.Группировка() = 1 Цикл
        Стр=ПолучитьПустоеЗначение("Число");
        Если ТЗ.НайтиЗначение(Запрос.Номенклатура,Стр,"Номенклатура")=1 Тогда
            ТЗ.УдалитьСтроку(Стр);
        КонецЕсли;
    КонецЦикла;
   Simod
 
28 - 14.09.16 - 13:04
(25) Там как раз и надо отсортировать и выгрузить в другую ТЗ. Тогда Ок. Если отсортировать и обрезать (КоличествоСтрок()), то данные побьются.
   Злопчинский
 
29 - 14.09.16 - 13:14
(28) это понятно. мну чисто исследовательски интересно если отсортировать и полностью выгрузить(заполнить?) в другую ТЗ - и уже её обрезать по количествустрок - тоже трабл будет..?
   Эльниньо
 
30 - 15.09.16 - 10:03
Думал, что знаю все алгоритмы удаления "лишних" строк.
Копаюсь в конфе. Нашёл ещё 2 алгоритма
   Эльниньо
 
31 - 15.09.16 - 10:23
Дарю безвозмездно, т.е даром:

// Алгоритм Эльниньо в один проход и без лишних сущностей и телодвижений

ТЗ.ВыбратьСтроки();
 Пока ТЗ.ПолучитьСтроку() = 1 Цикл 
     Пока ТЗ.ЧтоТо = Ненужное Цикл
         ТЗ.УдалитьСтроку();
         Если ТЗ.НомерСтроки = 0 Тогда
            Прервать;
         КонецЕсли;
     КонецЦикла;
КонецЦикла;
   Харлампий Дымба
 
32 - 15.09.16 - 11:08
Инд=Тз.КоличествоСтрок()
Пока Инд>0 Цикл
 ТЗ.ПолучитьСтрокуПоНомеру(Инд);
 Если ТЗ.ННеНужна=Да Тогда
  ТЗ.УдалитьСтроку(Инд);
 КонецЕсли;
 Инд=Инд-1;
КонецЦикла;
   Харлампий Дымба
 
33 - 15.09.16 - 11:16
//Код из типовой (почти):


Функция глТаблицаЗначенийУдалитьСтроки(Таб, ИдКолонки, ЗначениеПоиска) Экспорт
    
    НайденныеСтроки = СоздатьОбъект("ТаблицаЗначений");
    ВремТаб = СоздатьОбъект("ТаблицаЗначений");
    Таб.Выгрузить(НайденныеСтроки);
    НайденныеСтроки.УдалитьСтроки();
    НайденныеСтроки.Выгрузить(ВремТаб);
    
    Для Сч=1 По Таб.КоличествоСтрок() Цикл
        Если ЗначениеПоиска <> Таб.ПолучитьЗначение(Сч,ИдКолонки) Тогда
            Таб.Выгрузить(ВремТаб,Сч,Сч,);
            БылоСтрок = НайденныеСтроки.КоличествоСтрок();
            НайденныеСтроки.КоличествоСтрок(БылоСтрок+1);
            НайденныеСтроки.Заполнить(ВремТаб,БылоСтрок+1); 
        КонецЕсли;    
    КонецЦикла;    
    
    Возврат НайденныеСтроки;
    
КонецФункции
 
 
   Злопчинский
 
34 - 15.09.16 - 11:25
(31) кривой код по идее - те же самые траблы с пропусками строк
   Злопчинский
 
35 - 15.09.16 - 11:26
(33) Таб.ПолучитьЗначение(Сч,ИдКолонки)
- тормозная строка сильно
   Харлампий Дымба
 
36 - 15.09.16 - 11:36
(35) А кто говорил, что это самый оптимальный код? На мой взгляд, слишком вычурный.
Просто как вариант.
Ну и Таб.ПолучитьЗначение(Сч,ИдКолонки) нужно для универсальности, когда имя колонки отбора заранее неизвестно. Когда известно - можно и через Таб.ВыбратьСтроки()
   Харлампий Дымба
 
37 - 15.09.16 - 11:48
ТЗ.НоваяКолонка("НадоОставить","Число",1,0);
ТЗ.ВыбратьСтроки();
Пока ТЗ.ПолучитьСтроку()=1 Цикл
    ТЗ.НадоОставить=?(ТЗ.Ненужна=Да,1,0);
КонецЦикла;
ТЗ.Сортировать("НадоОставить-");
ТЗ.КоличествоСтрок(ТЗ.Итог("НадоОставить"));

//либо, вместо последней строчки:

//ИтоговаяТЗ=СоздатьОбъект("ТаблицаЗначений");
//ТЗ.Выгрузить(ИтоговаяТЗ,,,ТЗ.Итог("НадоОставить"));
   Эльниньо
 
38 - 15.09.16 - 11:55
(34) Ещё один критик. Сколько уже было, потом извинялись.
Посмотри вынимательно.
Покойный залекс тоже поначалу Ха-ха, на следующий день принёс извинения
   Харлампий Дымба
 
39 - 15.09.16 - 12:02
(37) Извиняюсь, наоборот же -
ТЗ.НадоОставить=?(ТЗ.Ненужна=Да,0,1)
   Злопчинский
 
40 - 15.09.16 - 15:40
(38) не вопрос, если я облажался - я всегда признаю и извиняюсь.
   Злопчинский
 
41 - 15.09.16 - 16:02
(38) ага, хитро! ;-)
приношу извинения.
но выморочено.
   Злопчинский
 
42 - 15.09.16 - 16:02
(37) ТЗ.Сортировать("НадоОставить-");
ТЗ.КоличествоСтрок(ТЗ.Итог("НадоОставить"));

см. (28)
   Эльниньо
 
43 - 15.09.16 - 16:35
(41) Просто нестандартно, что и приводит к неверной оценке
Почти у всех первая реакция такая.
Слышал, что этот алгоритм уже в каком-то учебнике прописали
   Злопчинский
 
44 - 15.09.16 - 18:06
(43) я-то вообщем не утверждал на 100% , я оговорочкеу оставил.. "по идее"... бо на первый взгляд оно да... а оно вон как...


Список тем форума
Рекламное место пустует  Рекламное место пустует
Компьютеры — это как велосипед. Только для нашего сознания. Стив Джобс
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.
Тема не обновлялась длительное время, и была помечена как архивная. Добавление сообщений невозможно.
Но вы можете создать новую ветку и вам обязательно ответят!
Каждый час на Волшебном форуме бывает более 2000 человек.
Рекламное место пустует