Имя: Пароль:
1C
1С v8
Вопрос по удалению строк документа по номеру строки
0 asder117
 
25.09.20
09:06
Коллеги доброе время суток..прошу не пинать сразу..просто на вроде легком вопросе встал в ступор.
Есть документ в 4000 строк, есть таблица с номерами строк которые надо удалить
На первый взгляд приходит такое:
    для каждого СтрокаДляУдаления из СтрокиВДокументах цикл
        если СтрокаДляУдаления.СтрокаТН = "" тогда
            продолжить
        КонецЕсли;
////++++Тестово удалим строки
ОбъектДок = ТН.ПолучитьОбъект();
СтруктураДляПоиска = Новый Структура("НомерСтроки", СтрокаДляУдаления.СтрокаТН);
ТабличнаяЧастьДок = ОбъектДок.Материалы;
//Получаем список строк соответсвтвующих отбору, и перебором удаляем.
МассивПустыхСтрок = ТабличнаяЧастьДок.НайтиСтроки(СтруктураДляПоиска);
Для каждого Строка Из МассивПустыхСтрок Цикл
    попытка
    ТабличнаяЧастьДок.Удалить(Строка);
    Сообщить("удалена строка " + СтрокаДляУдаления.СтрокаТН)
исключение
    
    конецпопытки
КонецЦикла;
Но не тут то было после удаления номер строки поменяется...тут и вопрос как скопом удалить необходимые 1000 строк в доке...Спасибо заранее
1 MouHacTaBHuk
 
25.09.20
09:11
(0) удаляй просто обратным циклом, от 4000 до 1
2 Fish
 
25.09.20
09:11
(0) Так всё верно у тебя написано, удалятся нужные строки.
3 Fish
 
25.09.20
09:13
+(2) только вот цикл по удалению надо вынести за рамки первого цикла. А он у тебя зачем-то внутри.
4 asder117
 
25.09.20
09:13
(2) Когда удаляются строки из табличной части нумерация сдвигается и удаляться могут не те строки
5 asder117
 
25.09.20
09:14
(3) В смысле...хотя я понял можно номера строк загнать в массив и потом обратным перебором грохнуть строки..только вспомнит как с конца начать перебор
6 Fish
 
25.09.20
09:14
(4) Первым циклом ты отбираешь все строки для удаления в массив строк. А уже потом (а не внутри этого цикла, как у тебя) ты удаляешь эти строки.
7 Fish
 
25.09.20
09:15
(5) Не номера строк. Метод НайтиСтроки вернут тебе Массив самих строки. И при удалении уже пофиг на изменение номера - удалятся только отобранные строки.
8 asder117
 
25.09.20
09:18
(6) // Вставить содержимое обработчика.
    для каждого СтрокаДляУдаления из СтрокиВДокументах цикл
        если СтрокаДляУдаления.СтрокаТН = "" тогда
            продолжить
        КонецЕсли;
////++++Тестово удалим строки
ОбъектДок = ТН.ПолучитьОбъект();
СтруктураДляПоиска = Новый Структура("НомерСтроки", СтрокаДляУдаления.СтрокаТН);
ТабличнаяЧастьДок = ОбъектДок.Материалы;
КонецЦикла;
//Получаем список строк соответсвтвующих отбору, и перебором удаляем.
МассивПустыхСтрок = ТабличнаяЧастьДок.НайтиСтроки(СтруктураДляПоиска);
Для каждого Строка Из МассивПустыхСтрок Цикл
    попытка
    ТабличнаяЧастьДок.Удалить(Строка);
    Сообщить("удалена строка " + СтрокаДляУдаления.СтрокаТН)
исключение
    
    конецпопытки
КонецЦикла;
////----
Типа такого получается? Только мне кажется структура это не то что надо может в массив лучше
9 asder117
 
25.09.20
09:18
(7) Я это понял тут и застопорился
10 Fish
 
25.09.20
09:19
(8) Для начала скажи, что такое у тебя СтрокиВДокументах и что такое ТН?
11 Fish
 
25.09.20
09:21
(8) Так не сработает, ты удалишь только строки по последнему значению СтрокаТН.
12 asder117
 
25.09.20
09:21
(10) СтрокиВДокументах - таблица номеров строк документа ТН Это документ требования накладня
13 asder117
 
25.09.20
09:23
(11) Вот и я о томже тогда может лучше в первом цикле строки загнать в массив точнее номера а потом массив загнать в НайтиСтрои и удалить
14 hhhh
 
25.09.20
09:26
(13) вот номера точно не нужно загонять. Сами строки загони.
15 Fish
 
25.09.20
09:27
(12) Тогда делай как-то так:
МассивДляУдаления = Новый Массив;
для каждого СтрокаДляУдаления из СтрокиВДокументах цикл

Если ЗначениеЗаполнено(СтрокаДляУдаления.СтрокаТН) Тогда
СтрокаДляУдаления = ТН.Материалы.Найти(СтрокаДляУдаления.СтрокаТН,"НомерСтроки");
Если СтрокаДляУдаления <> Неопределено Тогда
МассивДляУдаления.Добавить(СтрокаДляУдаления);
КонецЕсли;
КонецЕсли;

ОбъектДок = ТН.ПолучитьОбъект();
Для каждого Строка Из МассивДляУдаленияЦикл
    ОбъектДок.Материалы.Удалить(Строка);
исключение
16 Fish
 
25.09.20
09:28
+(15) Забыл конецЦикла перед получитьОбъект. И вместо исключения тоже конецЦикла.
17 Fish
 
25.09.20
09:30
А получать объект в цикле это нехорошо, раз у тебя всего один документ.
18 asder117
 
25.09.20
09:31
(14) (15) (16) Спасибо я к этому тоже уже пришел
ЗначениеЗаполнено(СтрокаДляУдаления.СтрокаТН) главное чтобы хорошо сработал с пустым строковым значением
(17) Знаю просто уже заработался
19 Fedor-1971
 
25.09.20
09:32
(13) погоди шашкой махать, Вот это работа внутри ОДНОГО документа

ОбъектДок = ТН.ПолучитьОбъект(); - получили ОБЪЕКТ ТН, т.е. сам документ
ТабличнаяЧастьДок = ОбъектДок.Материалы;

Вот ТУТ Перебирай циклом свои условия удаления
Для каждого текУсловие из МассивУсловийОчистки цикл

  СтруктураДляПоиска = Новый Структура("НомерСтроки", !!!Условие!!!!); - настроили поиск
  МассивПустыхСтрок = ТабличнаяЧастьДок.НайтиСтроки(СтруктураДляПоиска); - получил выборку СТРОК, не омеров!!!

  Для каждого СтрокаТЧ Из МассивПустыхСтрок Цикл
    Сообщить("удалена строка " + СтрокаТЧ.????); , например, СтрокаТЧ.Номенклатура
    ТабличнаяЧастьДок.Удалить(СтрокаТЧ);
   КонецЦикла;
КонецЦикла;
20 asder117
 
25.09.20
09:37
(19) Все номера загоняем в МассивУсловийОчистки получается и потом его перебираем
"СтруктураДляПоиска = Новый Структура("НомерСтроки", !!!Условие!!!!); - настроили поиск
  МассивПустыхСтрок = ТабличнаяЧастьДок.НайтиСтроки(СтруктураДляПоиска); - получил выборку СТРОК, не омеров!!!
"
Тут мы ищем одну строку по номеру и загоняем ее в массив и получается массив обновляется а не добавляется и я так думаю придем к удалению только последней строки
21 asder117
 
25.09.20
09:39
(19)  СтруктураДляПоиска = Новый Структура("НомерСтроки", !!!Условие!!!!); - настроили поиск После удаления номер строки поменяется и мы получается найдем следующую строку...
Остальное все мне понятно
22 hhhh
 
25.09.20
09:44
(19) Для каждого текУсловие из МассивУсловийОчистки цикл

  СтруктураДляПоиска = Новый Структура("НомерСтроки", !!!Условие!!!!); - настроили поиск
  МассивПустыхСтрок = ТабличнаяЧастьДок.НайтиСтроки(СтруктураДляПоиска); - получил выборку СТРОК, не омеров!!!

КонецЦикла;

  Для каждого СтрокаТЧ Из МассивПустыхСтрок Цикл
    Сообщить("удалена строка " + СтрокаТЧ.????); , например, СтрокаТЧ.Номенклатура
    ТабличнаяЧастьДок.Удалить(СтрокаТЧ);
   КонецЦикла;
23 Fedor-1971
 
25.09.20
09:48
(20) Погоди, это кусок твоего кода я не знаю ни количества условий, ни их состава.
НайтиСтроки гонять для поиска по номеру одной строки для удаления как-то жирно

В (15) тебе предложили перебрать ТЧ, каждую (!!!) строку проверить на Все (!!!) нужные тебе условия и сформировать массив СтрокДляУдаления.

Дальше скопом просто удаляем выбранные строки

Так более эффективно, чем гонять НайтиСтроки
24 asder117
 
25.09.20
10:01
(15) Не взлетело
25 Saari
 
25.09.20
10:02
Готовое решение (проверил, работает):

ДокОбъект = ТН.ПолучитьОбъект();
инд = ДокОбъект.Материалы.Количество();
Пока инд > 0 Цикл
  СтруктураДляПоиска = Новый Структура("СтрокаТН", инд);
  Отбор = СтрокиВДокументах.НайтиСтроки(СтруктураДляПоиска);
  Если Отбор.Количество() > 0 Тогда
    СтрокаДляУдаления = ТН.Материалы.Найти(инд, "НомерСтроки");
    Если СтрокаДляУдаления <> Неопределено Тогда
        ДокОбъект.Материалы.Удалить(СтрокаДляУдаления);
    КонецЕсли;
  КонецЕсли;
  инд = инд - 1;    
КонецЦикла;
    
ДокОбъект.Записать();
26 asder117
 
25.09.20
10:03
(23) 15 не взлетел..строки остались как стояли
27 Saari
 
25.09.20
10:03
Думаю, теперь взлетит.
28 asder117
 
25.09.20
10:04
(25) Я тоже думаю так как передала практически таккже с индексами
29 Saari
 
25.09.20
10:05
(28) проверяй и скажи результат.
30 Fish
 
25.09.20
10:07
(26) Так после удаления надо документ записать.
31 asder117
 
25.09.20
10:09
(25) (29) Я его ткрываю для просмотра без записи и записываю после проверки...
Сейчас попробую
32 asder117
 
25.09.20
10:10
(30) ДокОбъект.Записать();
ФормаДок = ДокОбъект.ПолучитьФорму("ФормаДокумента");
ФормаДок.Открыть();
33 asder117
 
25.09.20
10:12
(32) было 3162 строки и осталось
34 asder117
 
25.09.20
10:13
(25) 3162 строки было и остались....ничего не понимаю
35 Fish
 
25.09.20
10:14
(34) Посмотри в отладчике, может, у тебя строки для удаления не ищутся.
36 Bigbro
 
25.09.20
10:15
34 ответа жесть.
второй список с номерами для удаления отсортируй по номерам.
проходишь по этому списку от большего к меньшему удаляешь строку по номеру. все!
37 asder117
 
25.09.20
10:17
(35) ок
38 Saari
 
25.09.20
10:19
(34) Я проверил этот код. Работает. И сортировать ничего не надо.
Покажи свой код полностью.
39 Fish
 
25.09.20
10:19
(36) Мы тут не ищем лёгких путей, а ты пришёл и всё упростил :))
40 asder117
 
25.09.20
10:21
ДокОбъект = ТН.ПолучитьОбъект();
инд = ДокОбъект.Материалы.Количество();
Пока инд > 0 Цикл
  СтруктураДляПоиска = Новый Структура("СтрокаТН", инд);
  Отбор = СтрокиВДокументах.НайтиСтроки(СтруктураДляПоиска);
  Если Отбор.Количество() > 0 Тогда
    СтрокаДляУдаления = ТН.Материалы.Найти(инд, "НомерСтроки");
    Если СтрокаДляУдаления <> Неопределено Тогда
        ДокОбъект.Материалы.Удалить(СтрокаДляУдаления);
    КонецЕсли;
  КонецЕсли;
  инд = инд - 1;    
КонецЦикла;
//ФормаДок = ДокОбъект.ПолучитьФорму("ФормаДокумента");
//ФормаДок.Открыть();
    
ДокОбъект.Записать();
ФормаДок = ДокОбъект.ПолучитьФорму("ФормаДокумента");
ФормаДок.Открыть(); (38)
41 Saari
 
25.09.20
10:23
ТН должна содержать ссылку на документ. Это так?
42 asder117
 
25.09.20
10:23
(41) Да само собой
43 Saari
 
25.09.20
10:24
(42) только что повторил. Все работает, форма открывается с уже удаленными строками.
44 Saari
 
25.09.20
10:26
Стоп!
Замени СтрокаДляУдаления = ТН.Материалы.Найти(инд, "НомерСтроки");
на строку СтрокаДляУдаления = ДокОбъект.Найти(инд, "НомерСтроки");
45 Saari
 
25.09.20
10:26
на строку СтрокаДляУдаления = ДокОбъект.Материалы.Найти(инд, "НомерСтроки");
46 Saari
 
25.09.20
10:27
(45) правильно.
47 Saari
 
25.09.20
10:30
(42) Как там результат?
48 asder117
 
25.09.20
10:32
(47) Похоже я понял в чем причина...неразрывный пробел в номере похоже и тут и косячит..
49 Saari
 
25.09.20
10:33
(48) но строку переправь на эту: СтрокаДляУдаления = ДокОбъект.Материалы.Найти(инд, "НомерСтроки");
значения в таблице с номерами строк должны быть числовые.
50 asder117
 
25.09.20
10:35
(47) Стоп а СтрокаТН Как попадает в структуру...мы похоже цикл забыли по табличной части где указаны номера строк
51 Fish
 
25.09.20
10:37
(48) Номер строки должен быть числом.
52 asder117
 
25.09.20
10:37
для каждого СтрокаДляУдаления из СтрокиВДокументах цикл
        если СтрокаДляУдаления.СтрокаТН = "" тогда
            продолжить
        КонецЕсли;
Конеццикла
Я этот кусок же вставлял чтобы он у меня проходил по строкам где есть зополнен номерСтрокиТН
53 asder117
 
25.09.20
10:37
(51) Да понял я
54 Saari
 
25.09.20
10:41
(48) Напиши проверку для таблицы номеров:
Для Каждого Стр из СтрокиВДокументах Цикл
   Стр.СтрокаТН = СтрЗаменить(Стр.СтрокаТН, Символы.НПП, "");
   Стр.СтрокаТН = Число(Стр.СтрокаТН);
КонецЦикла;
Уберутся пробелы в номерах и превратятся в числа.
55 asder117
 
25.09.20
10:42
(54) Я переделал все норм теперь числа на в (49) у тебя в инд попадает не тот номер строки и таб части а тот индекса цикла из перебора
56 Saari
 
25.09.20
10:44
ну а теперь работает?
57 Saari
 
25.09.20
10:46
(55) да, но по инд я ищу номер строки в таблице с номерами строк. и если он есть, то удаляю строку в документе по этому номеру.
58 asder117
 
25.09.20
10:47
(56) В инд не попадают мои строки
59 Saari
 
25.09.20
10:48
(58) С чего вдруг они не попадут?
Они не попадут только в одном случае: если номер строки в таблице больше количества строк в документе.
60 Saari
 
25.09.20
10:48
(58) ну а теперь взлетело?
61 Saari
 
25.09.20
10:55
Предлагаю еще один вариант (попроще):

СтрокиВДокументах.Сортировать("СтрокаТН Убыв");

ДокОбъект = ТН.ПолучитьОбъект();
КоличествоСтрокДокумента = ДокОбъект.Материалы.Количество();    
Для Каждого Стр Из СтрокиВДокументах Цикл
  Если Стр.СтрокаТН <= КоличествоСтрокДокумента Тогда
    СтрокаДляУдаления = ДокОбъект.Материалы.Найти(Стр.СтрокаТН, "НомерСтроки");
    Если СтрокаДляУдаления <> Неопределено Тогда
           ДокОбъект.Материалы.Удалить(СтрокаДляУдаления);
    КонецЕсли;
  КонецЕсли;
КонецЦикла;
    
ДокОбъект.Записать();
ФормаДок = ДокОбъект.ПолучитьФорму("ФормаДокумента");
ФормаДок.Открыть();
62 Saari
 
25.09.20
10:55
этот вариант вообще без инд
63 Saari
 
25.09.20
11:01
Вы где?
64 asder117
 
25.09.20
11:04
(63) тут проверяю
65 asder117
 
25.09.20
11:08
(63) взлетело...у менгя табчасть изначально не видел..через док.табчасть..все норм смотрим..
66 asder117
 
25.09.20
11:09
(62) Спасибо большое..общими трудами свояли...
67 Saari
 
25.09.20
11:11
(65) так в моих примерах везде док.табчасть написано.
68 Garykom
 
гуру
25.09.20
11:12
(0) Запомни! Копирование быстрее удаления! В 99% случаев.

Короче создаешь новый документ и переносишь туда только нужные строки ))
69 asder117
 
25.09.20
11:51
(68) отчасти соглашусь..и этим пользуюусь..такой механизм у меня есть..просто не есть хорошо плодить документы
70 Fedor-1971
 
25.09.20
12:04
(69) Это трындец товарищи присяжные заседатели.

выремТЗ = ДокОбъект.Материалы.Выгрузить();
ДокОбъект.Материалы.Очистить();
Для каждого текСтрока из времТЗ цикл
  Если ..Проверяем условие заполненности .. тогда
     нов = ДокОбъект.Материалы.Добавить();
     ЗаполнитьЗначенияСвойств(нов, текСтрока);
  КонецЕсли;
КонецЦикла;

тут, документ записать


т.е. просто пройти через временную таблицу значений не вариант?
71 asder117
 
25.09.20
12:10
(70) еще один вариант решения вопроса...сколько программеров столько мнений