Имя: Пароль:
1C
1C 7.7
v7: Как разделить таблицу значений на две по условию ?
,
0 BalBess
 
22.09.20
11:52
соб-но сабж, что-то поиском не нашел

задача - есть ТЗ (скопированная табличная часть документа)
мне нужно по условию разделить ее на 2 других (с сохранением всех колонок и значений есс-но)
в идеале в первой ТЗ оставить только те строки, которых нет во второй ТЗ
1 FIXXXL
 
22.09.20
11:56
создаешь пустую копию исходной
создаешь массив для сохранения удаляемых строк
исходную обходишь в цикле, нужные строки добавляешь в копию и в массив
удаляешь в исходной согласно массива
2 trdm
 
22.09.20
11:59
(1) > удаляешь в исходной согласно массива
//******************************************************************************
// глУдалитьСтрокиПоСписку(ТаблЗнач, СЗУдалСтрок)
// Удаляет строки из таблицы значений, номера которых сидят в СЗУдалСтрок
Процедура глУдалитьСтрокиПоСписку(ТаблЗнач, СЗУдалСтрок, псВызовИз = "") Экспорт
    СЗУдалСтрок_РазмерСписка = СЗУдалСтрок.РазмерСписка();
    Если СЗУдалСтрок_РазмерСписка = 0 Тогда
        Возврат;
    КонецЕсли;
    СЗУдалСтрок.Сортировать(1);
    СЗУдалСтрокУже = СоздатьОбъект("СписокЗначений");
    СЦСЗУдалСтрок = 0;
    ТипЗначенияСтр_ТаблЗнач = ТипЗначенияСтр(ТаблЗнач);
    Для СЦСЗУдалСтрок = 1 По СЗУдалСтрок_РазмерСписка Цикл
        НомУдалСтроки = Число(СЗУдалСтрок.ПолучитьЗначение(СЦСЗУдалСтрок));
        Если СЗУдалСтрокУже.НайтиЗначение(НомУдалСтроки)>0 Тогда
            Продолжить;
        КонецЕсли;
        СЗУдалСтрокУже.ДобавитьЗначение(НомУдалСтроки);
        Если ТипЗначенияСтр_ТаблЗнач = "ТаблицаЗначений" Тогда
            Если ТаблЗнач.КоличествоСтрок()>=НомУдалСтроки Тогда
                Попытка
                    ТаблЗнач.УдалитьСтроку(НомУдалСтроки); //{} © ТрДм 17.11.2014 16:38:14 - глючит непонятно почему.
                Исключение
                КонецПопытки;
            КонецЕсли;
        ИначеЕсли ТипЗначенияСтр_ТаблЗнач = "СписокЗначений" Тогда
            Если ТаблЗнач.РазмерСписка()>=НомУдалСтроки Тогда
                ТаблЗнач.УдалитьЗначение(НомУдалСтроки);
            КонецЕсли;
        КонецЕсли;
        Состояние("Чистка таблицы: " + глПрогрессор(СЗУдалСтрок_РазмерСписка, СЦСЗУдалСтрок));
    КонецЦикла;
КонецПроцедуры // глУдалитьСтрокиПоСписку()
3 BalBess
 
22.09.20
12:07
(1) да все понятно, но что конкретно )

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

как это сделать

> удаляешь в исходной согласно массива

при удалении одной строки - номера строк не пересчитываются ?
например мне нужно удалить 1 и 3, удаляю 1 - третья строка не становиться 2 ?
4 BalBess
 
22.09.20
12:12
Да, забыл еще написать, жел-но без циклов обхода колонок и без ПолучитьЗначение / УстановитьЗначение
5 Mikeware
 
22.09.20
12:19
(4) ИТЗ, индекс, установитьФильр....
6 BalBess
 
22.09.20
12:53
(5) вообще не знаю таких слов )
7 FIXXXL
 
22.09.20
12:53
8 BalBess
 
22.09.20
13:01
(7) так я сам могу сделать, представляете 10000 строк в документе, и 15 колонок, сколько это дело будет работать
150'000 раз будет вызываться Получить / Установить Значение
9 Mikeware
 
22.09.20
13:05
(6) учить надо?
10 Bigbro
 
22.09.20
13:06
копируешь ТЗ в ТЗ2
обходишь ТЗ по своему условию, удаляешь ненужное, с хвоста, это быстро.
обходишь вторую ТЗ по нахождению строки из 1й удаляешь.
профит.
11 Simod
 
22.09.20
13:08
(10) Построчное удаление это долго..
12 Mikeware
 
22.09.20
13:09
(10) добавить ключ, посчитать количество значений ключа, отсортировать по нему, выгрузить с первой по количество значений ключа в одну тз, и с количествоЗначяений до ноца в другую
13 Simod
 
22.09.20
13:10
(0) 1. Добавляешь колонку в ТЗ
2. Обходишь строки и устанавливаешь 0 или 1
3. Сортируешь и выгружаешь количество строк по Итог(<Добавленная колока>)

Это общий принцип.
14 FIXXXL
 
22.09.20
13:10
(8) я семерку не знаю практически :)
там ТЗ в запрос можно засунуть? или два запроса к ТЧ и выгрузить две ТЗ?
15 Bigbro
 
22.09.20
13:10
(11) для 10 000 строк? нет не долго, вполне приемлемо.
хотя (12) конечно правильнее и быстрее.
16 Simod
 
22.09.20
13:12
(15) Скорость может отличаться в 2 и более раз..
17 Simod
 
22.09.20
13:12
(14) Нельзя.
18 Simod
 
22.09.20
13:13
(14) Да и 8.* быстрее обрабатывать ТЗ без запроса.
19 Карст
 
22.09.20
13:13
сделать две таблицы и в каждой

Для А=-ТЗ.Количествостро() по -1
ТЗ.Получитьстрокупономеру(А*(-1));

Если Мое условие тогда
ТЗ.Удалитьстроку(А*(-1));

КонеЦесли;

КонецЦикла

И у каждой ТЗ - удалить свое
20 Mikeware
 
22.09.20
13:13
(17) в черный можно :-)
21 Mikeware
 
22.09.20
13:14
тьфумля! (20) читать как "в прямой - можно"
22 BalBess
 
22.09.20
13:14
(12) (13) идею понял, буду пробовать

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

Процедура РазделитьТЗ(ТЗ_вход, ТЗ1, ТЗ2)
    ТЗ1 = СоздатьОбъект("ТаблицаЗначений");  
    ТЗ2 = СоздатьОбъект("ТаблицаЗначений");
    ТЗ_врем = СоздатьОбъект("ТаблицаЗначений");  // временная ТЗ
    
    ТЗ_вход.Выгрузить(ТЗ1, 1, 1); // копируем структуру
    ТЗ_вход.УдалитьСтроки();
        
    ТЗ_вход.Выгрузить(ТЗ2, 1, 1); // копируем структуру
    ТЗ_вход.УдалитьСтроки();
    
    ТЗ_вход.ВыбратьСтроки();
    Пока ТЗ_вход.ПолучитьСтроку() = 1 Цикл
         ТЗ_вход.Выгрузить(ТЗ_врем, ТЗ_вход.НомерСтроки, ТЗ_вход.НомерСтроки); // копируем одну строку во временную ТЗ

         Если ТЗ_вход.Количество > 0 Тогда // любое условие
            ТЗ1.КоличествоСтрок(ТЗ1.КоличествоСтрок() + 1); // добавляем пустую строку
            КолВоСтрок = ТЗ1.КоличествоСтрок();
             ТЗ1.Заполнить(ТЗ_врем, КолВоСтрок, КолВоСтрок); // заполняем одну строку из временной ТЗ
         Иначе    
            ТЗ2.КоличествоСтрок(ТЗ2.КоличествоСтрок() + 1); // добавляем пустую строку
            КолВоСтрок = ТЗ2.КоличествоСтрок();
             ТЗ2.Заполнить(ТЗ_врем, КолВоСтрок, КолВоСтрок); // заполняем одну строку из временной ТЗ
        КонецЕсли;    
                      
    КонецЦикла;
    ТЗ_вход.Очистить();
    
КонецПроцедуры
23 Simod
 
22.09.20
13:15
Думал, что вопросы на собеседовании на удалении строк из ТЗ по условию уже не катят. А нет, все еще актуально.
24 Mikeware
 
22.09.20
13:19
(22) анафига "копия структуры"?
и ващще, там же 8 строк должно быть (если проверка как функция )...
25 BalBess
 
22.09.20
13:19
(22) опечатка в начале, (лишнее вычищал, )
    ТЗ_вход.Выгрузить(ТЗ1, 1, 1); // копируем структуру
    ТЗ1.УдалитьСтроки(); // вместо ТЗ_вход.УдалитьСтроки()
        
    ТЗ_вход.Выгрузить(ТЗ2, 1, 1); // копируем структуру
    ТЗ2.УдалитьСтроки(); // вместо ТЗ_вход.УдалитьСтроки()
26 BalBess
 
22.09.20
13:23
(24) без "копии структуры" не работает. Заполнить(<Знач>,<НачСтрока>,<КонСтрока>,<Колонки>) - видимо работает как ЗаполнитьЗначенияСвойств - только по совпадающим колонкам
про 8 строк не понял (
27 Aleksey
 
22.09.20
13:29
Странно что ещё никто не предлажил запрос
28 Mikeware
 
22.09.20
13:32
КоличествоЗначенийКлюча=0;
ТЗ_Вход.НоваяКолонка("Ключ","Число",1,0);
Для сч=1 по тз_Вход.КоличествоСтрок() Цкл
  тз_вход.Ключ=Ключ(тзВход.ТутКлючевоеПоле);
  КоличествоЗначенийКлюча=КоличествоЗначенийКлюча+тз_вход.Ключ;
КонецЦикла;
тзВход.Сортировать("-Ключ");
тз_вход.Выгрузить(тз1,1,КоличествоЗначенийКлюча);
тз_вход.Выгрузить(тз2,КоличествоЗначенийКлюча+1,тз_Вход.КоличествоСтрок());
---------
ну да, 9, видимо КЦ не посчитал
29 Simod
 
22.09.20
13:33
(28) Вместо КоличествоЗначенийКлюча можно использовать Итог(). Будет 7.
30 Mikeware
 
22.09.20
13:41
(29) угу.
ну а с индексированными при простом ключе получается вроде 5.
" - я себе дом построил!
-- молодец! а сколько комнат?
- одна.
-- Правильно! Меньше и смысла нет!"
©
31 trad
 
22.09.20
13:49
ТЗ2 = СоздатьОбъект("ТаблицаЗначений");
ТЗ2.Загрузить(ТЗ);
Для ТекСтр = -ТЗ.КоличествоСтрок() По -1 Цикл
  ТЗ.ПолучитьСтрокуПоНомеру(-Тек);
  Если УсловиеВыполнено Тогда
    ТЗ.УдалитьСтроку(-Тек);
  Иначе
    ТЗ2.УдалитьСтроку(-Тек);
  КонецЕсли
КонецЦикла
32 BalBess
 
22.09.20
13:50
(28) проверил, ваш метод быстрее моего в 2 раза, спасибо
только еще одна строчка у меня в цикле
    ТЗ_вход.ПолучитьстрокуПоНомеру(сч);
т.к. условие в самой таблице
33 Mikeware
 
22.09.20
14:02
(32) Можно ВыбратьСтроки() - получитьСтроку()
если условие простое, то с ИТЗ будет еще проще и быстрее.
впрочем, пофиг
34 Карст
 
22.09.20
14:03
жесть ))) пост (19) не прочитан видимо
35 Mikeware
 
22.09.20
14:11
(34) анахрена заниматься такой хней?
36 trad
 
22.09.20
15:16
(34) прочитан, конечно
37 BalBess
 
23.09.20
06:29
потестил. итого
мой способ ) - 1100мс
(28) - 524мс (через ключ) - в 2 раза быстрее
(31) - 4445мс (через удаление строк) - в 4 раза медленнее

всем спасибо )
38 BalBess
 
23.09.20
06:39
попутный вопрос, можно как-то скопировать строку документа (со всеми колонками) в другой документ ?
без таблицы значений, и без обхода колонок через метаданные
39 Mikeware
 
23.09.20
08:09
(38) а чем ТЗ не нравится? Для мелких объемов, имхо, вполне нормально
40 Mikeware
 
23.09.20
08:09
(37) а ключ какой?
41 Aleksey
 
23.09.20
08:43
(14) 1sqlite + УложитьТЗ(). Ну или запрос к ТЧ
42 Mikeware
 
23.09.20
08:48
(27)(41) см (21)
43 BalBess
 
23.09.20
11:30
(39) нет, все устраивает, думал можно как-то проще. Обходишь строки документа и по условию раскидываешь в другие документы.
(40) ваш ) в (28)
44 Aleksey
 
23.09.20
17:56
(42) и где там решение через запрос?
45 Злопчинский
 
23.09.20
21:25
(43) можно и так, проблема в чем? обходи строки документа и по условию раскидывай в другие документы.
46 trad
 
24.09.20
09:19
(37) сохранять порядок строк не требуется?
2 + 2 = 3.9999999999999999999999999999999...