![]() |
|
1С:Предприятие
:: 1С:Предприятие 7.7 и ранее
|
|
| ||
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 | |||
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 | |||
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 | |||
Злопчинский 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% , я оговорочкеу оставил.. "по идее"... бо на первый взгляд оно да... а оно вон как... |
|
Список тем форума
|