Имя: Пароль:
1C
1С v8
Неверная сортировка ТЧ по номеру строки
0 azernot
 
30.08.17
14:05
Столкнулся со странностью которую не могу объянсить

Есть ТЧ, в которой есть поле связи со строками другой ТЧ (по полю КлючСвязи). Перед записью, мне надо проверить, что в первой строке каждой группы строк по КлючСвязи, выполняется определённое условие.

Для того, чтобы проще было обходить ТЧ, выполняю код

ТЧ.Сортировть("КлючСвязи, НомерСтроки");

Ожидаю, что после такой сортировки, все строки с одинаковым ключом будут следовать подряд, при этом изначальный порядок строк внутри каждой группы с одинаковым ключом не изменится.

Однако, по факту получаю до вызова метода Сортировать() порядок строк:
Индекс    Знак    Значение    КлючСвязи    НомерСтроки    ТипПеременной
0    "+"    ФПВ    "0238f336-1cdd-4ca4-837a-5ed9b4732284"    1    Показатель
1    "*"    0,005    "0238f336-1cdd-4ca4-837a-5ed9b4732284"    2    Число
2    "*"    КОВ    "0238f336-1cdd-4ca4-837a-5ed9b4732284"    3    Показатель
3    "+"    0    "29653d23-175a-4d75-b98b-9bc200847529"    4    Число
4    "*"    КОВ    "29653d23-175a-4d75-b98b-9bc200847529"    5    Показатель
5    "+"    0    "398d634f-b366-466c-8378-a345b1ceaa08"    6    Число
6    "+"    ФЛД    "80962eb9-f79c-4ed7-bf9d-aa8e3a782a19"    7    Показатель
7    "*"    0,005    "80962eb9-f79c-4ed7-bf9d-aa8e3a782a19"    8    Число
8    "*"    КОВ    "80962eb9-f79c-4ed7-bf9d-aa8e3a782a19"    9    Показатель
9    "+"    ФМА    "a6d3e74d-31a6-4554-b985-6610e4e0501b"    10    Показатель
10    "*"    0,02    "a6d3e74d-31a6-4554-b985-6610e4e0501b"    11    Число
11    "*"    КОВ    "a6d3e74d-31a6-4554-b985-6610e4e0501b"    12    Показатель
12    "+"    0    "a9ddb9ff-518a-4544-af77-63b09c916a2b"    13    Число
13    "*"    КОВ    "a9ddb9ff-518a-4544-af77-63b09c916a2b"    14    Показатель
14    "+"    ФБВ    "ea31911c-14de-4bb9-b236-46b11141edc9"    15    Показатель
15    "*"    0,005    "ea31911c-14de-4bb9-b236-46b11141edc9"    16    Число
16    "*"    КОВ    "ea31911c-14de-4bb9-b236-46b11141edc9"    17    Показатель

После вызова метода Сортировать(), порядок строк:
Индекс    Знак    Значение    КлючСвязи    НомерСтроки    ТипПеременной
0    "+"    ФПВ    "0238f336-1cdd-4ca4-837a-5ed9b4732284"    1    Показатель
1    "*"    0,005    "0238f336-1cdd-4ca4-837a-5ed9b4732284"    2    Число
2    "*"    КОВ    "0238f336-1cdd-4ca4-837a-5ed9b4732284"    3    Показатель
3    "+"    0    "29653d23-175a-4d75-b98b-9bc200847529"    4    Число
4    "*"    КОВ    "29653d23-175a-4d75-b98b-9bc200847529"    5    Показатель
5    "+"    0    "398d634f-b366-466c-8378-a345b1ceaa08"    6    Число
6    "*"    КОВ    "80962eb9-f79c-4ed7-bf9d-aa8e3a782a19"    7    Показатель
7    "*"    0,005    "80962eb9-f79c-4ed7-bf9d-aa8e3a782a19"    8    Число
8    "+"    ФЛД    "80962eb9-f79c-4ed7-bf9d-aa8e3a782a19"    9    Показатель
9    "+"    ФМА    "a6d3e74d-31a6-4554-b985-6610e4e0501b"    10    Показатель
10    "*"    0,02    "a6d3e74d-31a6-4554-b985-6610e4e0501b"    11    Число
11    "*"    КОВ    "a6d3e74d-31a6-4554-b985-6610e4e0501b"    12    Показатель
12    "+"    0    "a9ddb9ff-518a-4544-af77-63b09c916a2b"    13    Число
13    "*"    КОВ    "a9ddb9ff-518a-4544-af77-63b09c916a2b"    14    Показатель
14    "+"    ФБВ    "ea31911c-14de-4bb9-b236-46b11141edc9"    15    Показатель
15    "*"    0,005    "ea31911c-14de-4bb9-b236-46b11141edc9"    16    Число
16    "*"    КОВ    "ea31911c-14de-4bb9-b236-46b11141edc9"    17    Показатель

Т.е. строки с индексом 6 и 8 меняются местами, хотя КлючСвязи у них одинаковый!
Что делать, как бороться?
1 Buster007
 
30.08.17
14:22
чето не понял, строки поменялись, а номер строки у этих строк - нет. Как это понимать?
2 Лефмихалыч
 
30.08.17
14:27
(0) надо выйти, хлопнуть дверкой, и снова войти. В твоем примере поменялись не строки, а значение колонки "Значение". А такого не может быть. Ты кудато не туда смотришь или делаешь что-то не так, как описываешь тут
3 Йохохо
 
30.08.17
14:27
вероятно не стоит служебное НомерСтроки использовать т.к. ТЧ может копироваться в новую и потом непредсказуемо
4 azernot
 
30.08.17
14:39
(1) НомерСтроки - служебное поле. После сортировки номер строки меняется в соответствии с сортировкой.
(2) Меняются местами именно строки. Грубо говоря, это видно на форме. Делаю я просто: в отладчке ставлю точку останова, открываю ТЧ ДО выполнения метода, вывожу в таблицу, далее жму F10, открываю ТЧ ПОСЛЕ выполнения метода, вывожу в таблицу. Смотрю эти две таблицы и вижу расхождения.

(3) Чуть подробнее, где это? На всякий случай: ТЧ ниоткуда не копируется. Заполняется пользователем вручную.


Всё это делается на
Управление торговлей, редакция 11.2 (11.2.3.284)
1С:Предприятие 8.3 (8.3.8.2137)
Управляемые формы. Тонкий клиент.

Конкретно, в обработчике

Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)

    
    ПоследнийКлючСвязи = Неопределено;
    
    Формулы.Сортировать("КлючСвязи, НомерСтроки");
    
    Для Индекс = 0 по Формулы.Количество() - 1 Цикл
        Строка = Формулы.Получить(Индекс);
        Если НЕ ПоследнийКлючСвязиУсловия = Строка.КлючСвязиУсловия Тогда
            Если Строка.Знак <> "+" И Строка.Знак <> "-" Тогда
                ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Ошибка бла-бла-бла");

        КонецЕсли;
        ПоследнийКлючСвязи = Строка.КлючСвязи;        

    КонецЦикла;
5 Buster007
 
30.08.17
14:41
(4) в твое примере видно
6    "+"    ФЛД    "80962eb9-f79c-4ed7-bf9d-aa8e3a782a19"    7
после сортировки
6    "*"    КОВ    "80962eb9-f79c-4ed7-bf9d-aa8e3a782a19"    7

хочешь сказать, что так и должно быть?
6 azernot
 
30.08.17
14:44
(5) Вот именно, что так быть не должно!
В данном случае, такая сортировка вообще не должна менять ничего а таблице, потому как она и без того отсортирована правильно. Но она почему-то меняет местами строки с индексом 6 и 8.
7 Йохохо
 
30.08.17
14:48
(4) я имел в виду поведение платформы при вызове Сортировать, отсортировала копию ТЧ и кинула на место старой. Я бы попробовал скопировать НомерСтроки в СтрН и ТЧ.Сортировть("КлючСвязи, СтрН"); т.к. на служебное НомерСтроки платформа может в общем то и забить
8 azernot
 
30.08.17
14:57
(7) А-а-а. Я тебя изначально не понял. Неправильно ударение в слове "стоит" мысленно проставил.. Подумал, что у меня где-то свойство "Использовать" не стоИт для служебного поля "НомерСтроки" :)
Блин, как же не хочется организовывать свой, отдельный номер строки в табличной части...
9 RS2017
 
30.08.17
14:58
У меня вполне ожидаемое поведение платформы. Правда режим совместимости 8.2.13:

{ВнешняяОбработка.ВнешняяОбработка1.Форма.Форма.Форма(3)}: Ошибка при вызове метода контекста (Сортировать)
    ТабличнаяЧасть1.Сортировать("НомерСтроки");
по причине:
Недопустимое значение параметра (параметр номер '1')
10 azernot
 
30.08.17
17:16
(9) Спасибо.
Действительно, поле "НомерСтроки" попросту недоступно для сортировки через метод Сортировать()
Однако, оно доступоно для сортировки, например, через запрос к Табличной части.

Что меня ввело в заблуждение:
- при использовании метода
ТЧ.Сортировть("КлючСвязи, НомерСтроки");
с ПОЛНЫМИ ПРАВАМИ, как это ни странно, результат совпадает с ожидаемым (даже если намеренно премешать строки по полю КлючСвязи, сортировка выполняется именно так как должна по логике вещей.

- при использовании метода
ТЧ.Сортировть("КлючСвязи, НомерСтроки");
с НЕ полными правами наблюдается такое поведение как в сабже.

Возможно права тут и ни при чём, возможно, если подольше поколдовать с разными наборами прав можно получить ещё более удивительные результаты...
Жаль, что система прямо не ругается не недоступное для сортировки поле "НомерСтроки" при вызове метода Сортировать()


Саму проблему я обошёл следующим способом:

Процедура СортировкаТЧПоПолюВПорядкеСледования(ТЧ, ИмяПоляСортировки)
    
    
    Запрос = Новый Запрос;
    Запрос.Текст =
        "ВЫБРАТЬ
        |    ТЧ.НомерСтроки,
        |    ТЧ.КлючСвязи
        |ПОМЕСТИТЬ ДанныеТЧ
        |ИЗ
        |    &ТЧ КАК ТЧ
        |;
        |
        |////////////////////////////////////////////////////////////////////////////////
        |ВЫБРАТЬ
        |    ДанныеТЧ.НомерСтроки КАК НомерСтроки,
        |    ДанныеТЧ.КлючСвязи КАК КлючСвязи
        |ИЗ
        |    ДанныеТЧ КАК ДанныеТЧ
        |
        |УПОРЯДОЧИТЬ ПО
        |    КлючСвязи,
        |    НомерСтроки
        |ИТОГИ ПО
        |    КлючСвязи";
        
    Запрос.Текст = СтрЗаменить(Запрос.Текст, "КлючСвязи", ИмяПоляСортировки);    
    Запрос.УстановитьПараметр("ТЧ",ТЧ);
    РезультатЗапроса = Запрос.Выполнить();
    
    ВыборкаПолеСортировки = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
    
    СоответствиеСтрокТЧПоНомеру = Новый Соответствие;
    //Сначала обход для заполнения соответсвтия строки и их изначальных номеров строки
    Пока ВыборкаПолеСортировки.Следующий() Цикл
        ВыборкаДетальныеЗаписи = ВыборкаПолеСортировки.Выбрать();
        Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
            СтрокаТЧ = ТЧ.Получить(ВыборкаДетальныеЗаписи.НомерСтроки-1);
            СоответствиеСтрокТЧПоНомеру.Вставить("НомерСтроки"+Формат(ВыборкаДетальныеЗаписи.НомерСтроки,"ЧГ="), СтрокаТЧ);
        КонецЦикла;
    КонецЦикла;
    
    //Обход для измнения порядка строк в нужном
    ВыборкаПолеСортировки.Сбросить();
    ТекИндекс = 0;
    Пока ВыборкаПолеСортировки.Следующий() Цикл
        ВыборкаДетальныеЗаписи = ВыборкаПолеСортировки.Выбрать();
        Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
            СтрокаТЧ = СоответствиеСтрокТЧПоНомеру.Получить("НомерСтроки"+Формат(ВыборкаДетальныеЗаписи.НомерСтроки,"ЧГ="));
            Сдвиг = ТекИндекс - ТЧ.Индекс(СтрокаТЧ);
            Если НЕ Сдвиг = 0  Тогда
                ТЧ.Сдвинуть(СтрокаТЧ, Сдвиг);
            КонецЕсли;
            ТекИндекс = ТекИндекс + 1;
        КонецЦикла;
    КонецЦикла;
КонецПроцедуры
11 Вафель
 
30.08.17
17:23
а вообще имеет ли смысл сортировать ТЧ по номеру строки?
Это вообще как?
12 Вафель
 
30.08.17
17:24
мне кажется вначале нужно в ТЗ выгрузить.
Ибо номер строки это виртуальный реквизит
13 azernot
 
30.08.17
17:25
(11) Ну по одному номеру строки конечно бессмысленно. Она и так уже сортирована по нему :)
А вот по каким-то другим полям с сохранением общего порядка следования строк - вполне даже может понадобиться. Мне, например, понадобилось :)
14 azernot
 
30.08.17
17:33
(12) Может быть действительно проще выгрузить ТЧ в ТЗ, отсортировать и загрузить обратно..
Но не хочется однажды наткнуться на какое-нибудь богом забытое примечание мелким шрифтом на 8547 странице описания платформы, что мол
"... метод Загрузить() табличной части не гарантирует сохранение порядка строк из таблицы значений..."
15 Вафель
 
30.08.17
18:00
(13) При сортировке по другому полю, номер строки тут же меняется
16 Вафель
 
30.08.17
18:01
Те по фкту ты сортируешь по одному полю. А сортировка внтури одного поля никак не регламентируется. На что ты и попался