|
v7: Пропуск из ТЗ элементов | ☑ | ||
---|---|---|---|---|
0
myr4ik07
13.09.16
✎
23:09
|
ТЗ - таблица знач в которой выгружены остатки с фильтром склад и номенкл группа.
Перебираю ТЗ и вижу, что некоторые строки из ТЗ пропускаются в цикле, отладчиком смотрю на "них" - данные есть, обычные строки. http://paste1c.ru/zJW код логика заключается удалить из ТЗ строки, которые не соответствуют некому условию, может тут беда? |
|||
1
Franchiser
гуру
13.09.16
✎
23:15
|
Да, строки надо перебирать с конца.
Как-то так: для сч = -ТЗ.Количество() по -1 цикл сч = сч+1; КонецЦикла; |
|||
2
Franchiser
гуру
13.09.16
✎
23:17
|
ВНИМАНИЕ
Часто требуется удалить строки, удовлетворяющие определенному условию. Так как при удалении строки из таблицы значений следующая строка становится текущей, то указанная ниже программа может удалить НЕ ВСЕ необходимые строки. //ЭТА ПРОГРАММА НЕПРАВИЛЬНАЯ !!! ТабЗнач.ВыбратьСтроки(); Пока ТабЗнач.ПолучитьСтроку()=1 Цикл ...Если <условие> Тогда ......ТабЗнач.УдалитьСтроку(); //следующая строка стала текущей, ...КонецЕсли; КонецЦикла; В этом случае я рекомендую использовать следующий прием: ТабЗнач.ВыбратьСтроки(); Пока ТабЗнач.ПолучитьСтроку()=1 Цикл ~начало: ...Если <условие> Тогда ......ТабЗнач.УдалитьСтроку(); //следующая строка стала текущей ......Если ТабЗнач.НомерСтроки<>0 Тогда ........ Перейти ~начало; ......КонецЕсли; ...КонецЕсли; КонецЦикла; А вот еще один правильный алгоритм, предложенный Wlad: ТабЗнач.выбратьстроки(); Пока ТабЗнач.ПолучитьСтроку()=1 Цикл .......Пока (<условие>) и (ТабЗнач.НомерСтроки<>0) Цикл ..............ТабЗнач.УдалитьСтроку(); //следующая строка стала текущей .......КонецЦикла; КонецЦикла; http://www.mista.ru/tutor_1c/tz.htm |
|||
3
myr4ik07
13.09.16
✎
23:20
|
(2) да, читал эту статью и по чему то без внимания
|
|||
4
myr4ik07
13.09.16
✎
23:22
|
(2) атасец, как бы оно
Пока ТЗ.ПолучитьСтроку() = 1 Цикл ~начало: //получим из ТЗ следующую номенклатуру //выберем документы с опеределенным периодом РасходнаяНакладная = создатьобъект("документ.РасходнаяНакладная"); ВыборкаДокументов = РасходнаяНакладная.ВыбратьДокументы(ДнейНеликвид,ТекущаяДата()); пока РасходнаяНакладная.ПолучитьДокумент()=1 Цикл //не проведенные пропускаем // если РасходнаяНакладная.Проведен() = 0 тогда // продолжить; // конецесли; //помечанные на удаление пропускаем // если РасходнаяНакладная.ПометкаУдаления() = 1 тогда // продолжить; // конецесли; //получим из выборки следующий документ ТабличнаяЧастьДокумента = создатьобъект("ТаблицаЗначений"); //выгружаем в ТЗ ТЧ документа РасходнаяНакладная.ВыгрузитьТабличнуюЧасть(ТабличнаяЧастьДокумента,"ТМЦ"); ИдСтроки = 0; если ТабличнаяЧастьДокумента.НайтиЗначение(ТЗ.ТМЦ,ИдСтроки,"ТМЦ") = 1 тогда //в ТЧ документа была найдена номенклатура - не нужно показывать ее в отчете ТЗ.УдалитьСтроку(); Если ТЗ.НомерСтроки<>0 Тогда Перейти ~начало; КонецЕсли; иначе //в ТЧ документа не была найдена номенклатура - покажем ее в отчете продолжить; конецесли; конеццикла; конеццикла; очень спасибо |
|||
5
Garykom
гуру
13.09.16
✎
23:22
|
Для особо продвинутых удалялщиков... Повторю не нужно удалять строки из ТЗ.
Лучше переносить только нужные строки в новую ТЗ. |
|||
6
Franchiser
гуру
13.09.16
✎
23:22
|
я предпочитаю искать в типовом коде 7.7 (например ЗИК) строку по конфигурации"по -1 цикл" и делаю такое удаление по номеру строки.
|
|||
7
myr4ik07
13.09.16
✎
23:25
|
(5) та мне в голове из 8-ки так привычнее )) вот поэтому и беда
|
|||
8
hhhh
13.09.16
✎
23:28
|
(7) в 8-ке та же фигня.
|
|||
9
Franchiser
гуру
13.09.16
✎
23:29
|
(8) в 8-ке если удалять в цикле "для каждого" если не ошибаюсь все ок
|
|||
10
myr4ik07
13.09.16
✎
23:31
|
(8) для каждого все норм, та и вообще, никаких проблем не было с удаление в 8-ке, не знаю даже о чем ты
|
|||
11
Franchiser
гуру
13.09.16
✎
23:32
|
(10) не ну если удалять в цикле для сч=0 по Тз.КоличествоСтрок() то м.б. проблемы
|
|||
12
myr4ik07
13.09.16
✎
23:32
|
(8) * о чем Вы (10) имел ввиду
|
|||
13
myr4ik07
13.09.16
✎
23:33
|
(11) ну, короче я не сталкивался с проблемой такой поэтому заблудился )
|
|||
14
myr4ik07
13.09.16
✎
23:33
|
всем спасибо
|
|||
15
Zhuravlik
13.09.16
✎
23:41
|
(9) не ок
(0) Лучше всего не морочиться - если условие сложное, перебрать ТЗ, строки к удалению поместить в массив. Потом перебрать массив, из тз удалить нужные строки. Это не самое быстрое, но самое простое. И самое понятное. Особенно когда смотришь на этот код через пару месяцев. А самое верное решение - это (5) - не допускать наличия в ТЗ лишних строк. |
|||
16
Zhuravlik
13.09.16
✎
23:44
|
(2)(3) это для 7.7 :)
(4) Метки использовать нехорошо |
|||
17
Franchiser
гуру
13.09.16
✎
23:48
|
(15) есть метод НАйтиСтроки() и потом перебор массива этих строк (с типом строка тз) для последующего удаления
|
|||
18
Zhuravlik
13.09.16
✎
23:50
|
(17) Тогда уж Скопировать() с отбором по структуре :)
|
|||
19
Zhuravlik
13.09.16
✎
23:51
|
(17) перебор массива нужен для сложного условия, которое в структуру не загонишь. Но можно добавлять булевскую колонку, заполнять ее по условию, потом Скопировать() с отбором по ней же. По идее самый быстрый способ для v8.
|
|||
20
Zhuravlik
13.09.16
✎
23:54
|
А для 77 самый лучший способ - это вот такой:
//****************************************************************************** // ОчисткаТЗ() // Параметры: ТЗ, которую надо очистить // В ТЗ д.б. Колонки с идентификаторами "НадоУдалить" и "ОПС" (оригинальный порядок строк) // Описание: очищает ТЗ от ненужных строк Процедура глОчисткаТЗ(ТЗдляЧистки, ОПС="+ОПС", КолонкаУдалить="НадоУдалить", Режим=0) Экспорт Попытка НадоУдалить = ТЗдляЧистки.Итог(КолонкаУдалить); Исключение Возврат; КонецПопытки; ТЗКС = ТЗдляЧистки.КоличествоСтрок(); Если Режим <> 0 Тогда Сообщить("> ["+ТекущееВремя()+"]: *** удаляем "+НадоУдалить+" из "+ТЗКС+" ****"); КонецЕсли; Если НадоУдалить <= 0 Тогда Возврат; КонецЕсли; Если НадоУдалить >= ТЗКС Тогда ТЗдляЧистки.УдалитьСтроки(); Иначе ТЗРаб = СоздатьОбъект("ТаблицаЗначений"); ТЗдляЧистки.Выгрузить(ТЗРаб); ТЗРаб.Сортировать("+"+КолонкаУдалить); ТЗРаб.Выгрузить(ТЗдляЧистки,1,ТЗКС-НадоУдалить); ТЗРаб = 0; КонецЕсли; Если ОПС = "###" Тогда Возврат; КонецЕсли; //сортировать не надо //восстановим оригинальный порядок строк ТЗдляЧистки.Сортировать(ОПС); КонецПроцедуры //глОчисткаТЗ() Взято отсюда http://catalog.mista.ru/public/57376/, пост 19. В свое время забирал себе в конфу, в глобальник. |
|||
21
Franchiser
гуру
14.09.16
✎
00:00
|
Ну Скопировать() я бы не советовал (только в крайнем случае, когда нельзя описать ОТБОР), т.к. если ТЗ большая это и много строк нужно удалять - будет жрать оперативную память.
|
|||
22
Franchiser
гуру
14.09.16
✎
00:01
|
(20) слишком заморочено, нормальной способ перебор строк ТЗ и удаления с конца - мало кода и все понятно
|
|||
23
Злопчинский
14.09.16
✎
00:51
|
(22) этот код практически самый быстрый из нескольких вариантов - ещё на проклабе тестили, и этот ещё можно ускорить заменив метод выгрузить на метод заполнить
А вот вариант с обрезкой количества строк одноимённым методом был чем-то косячный |
|||
24
Simod
14.09.16
✎
07:43
|
(0) За последние 15 лет тему поднимали несколько сотен раз.
(23) После сортировки и установки количества строк сбивается сортировка и удаляются не те строки. |
|||
25
Злопчинский
14.09.16
✎
08:27
|
(24) аиесли отсортировать и перекинуть в другую из и обрезать количеством строк то тожеикосяк будет?
|
|||
26
Это_mike
14.09.16
✎
08:31
|
а индексированную таблицу - рассматриваем? :-)
|
|||
27
Duke1C
14.09.16
✎
09:43
|
(4) еще какой атасец, глядя на код))
Вот так попробуй: СписЗн=СоздатьОбъект("СписокЗначений"); ТЗ.Выгрузить(СписЗн,,,"Номенклатура"); ВыбКонПериода=ТекущаяДата(); Запрос = СоздатьОбъект("Запрос"); ТекстЗапроса = "Период с ДнейНеликвид по ВыбКонПериода; |Номенклатура = Документ.РасходнаяНакладная.Номенклатура; |Функция Счётчик = Счётчик(); |Группировка Номенклатура; |Условие(Номенклатура в СписЗн);"; Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда Возврат; КонецЕсли; Пока Запрос.Группировка() = 1 Цикл Стр=ПолучитьПустоеЗначение("Число"); Если ТЗ.НайтиЗначение(Запрос.Номенклатура,Стр,"Номенклатура")=1 Тогда ТЗ.УдалитьСтроку(Стр); КонецЕсли; КонецЦикла; |
|||
28
Simod
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% , я оговорочкеу оставил.. "по идее"... бо на первый взгляд оно да... а оно вон как...
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |