Метод ПолучитьЭлементыСписка() часто задваивает по 5-8 строк на стыке страниц

tormozit Закрыто Средний

Вызываю метод ПолучитьЭлементыСписка() Турбоконфа в большом списке реквизитов формы и часто получаю повторяющиеся серии обычно 5-8 строк на стыке страниц (полосы прокрутки).

ВнешняяОбработка1.epf

Комментарии

tormozit
#1, 27 декабря 2024 20:25

@bolsun Есть ли шанс на исправление этой проблемы на твоей стороне? Я конечно могу попытаться выявить эту серию повторов строк и удалять такие дубли, но от этого и вред может появиться.


bolsun
#2, 28 декабря 2024 12:34

(1) tormozit, посмотрю


bolsun
#3, 28 декабря 2024 13:50

У меня не воспроизводится, добавил на всякий случай задержку 20мс после нажатия PageDown, проверь поможет или нет.

6.3.9128.28263
https://disk.yandex.ru/d/ay0Wg6IBTsxSxg


tormozit
#4, 28 декабря 2024 13:56

Проверил на 6.3.9128.28263. Проблема сохранилась.
На всякий случай вот повторы непосредственно в массиве


tormozit
#5, 28 декабря 2024 13:57

(3) bolsun, чтобы воспроизвелось, постарайся сделать размеры табличного поля списка реквизитов в точности как на моей картинке


bolsun
#6, 28 декабря 2024 13:59

(4) tormozit, все равно не воспроизводится.
Попробуй увеличивать коэффициент задержки, пока проблема не исчезнет.


bolsun
#7, 28 декабря 2024 14:00


tormozit
#8, ред. 28 декабря 2024 14:06

Поставил 50. Проблема осталась. Похоже она с задержкой не связана.


bolsun
#9, 28 декабря 2024 14:12

(8) tormozit, пришли ролик и лог.


bolsun
#10, 28 декабря 2024 14:14

а еще скриншоты, если нажимать PageDown, куда перемещается список.


tormozit
#11, 28 декабря 2024 14:16

Чистейший тест из одной инструкции языка

Ссылка скрыта

После первого листания вперед

Похоже что ты не учитываешь наложение у последней страницы на предпоследнюю


bolsun
#12, 28 декабря 2024 14:20

(11) tormozit, да, теперь понял. Похоже нужно проверять уникальность по RuntimeId


bolsun
#13, 28 декабря 2024 14:21

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


bolsun
#14, 28 декабря 2024 14:23

Либо проверять для них по BoundingRectangle, что менее надежно.


tormozit
#15, ред. 28 декабря 2024 14:35

(12) bolsun, насколько я заметил, RuntimeId уникален для позиции в видимой области списка, а не для элемента самого списка. Т.е. на всех страницах одного поля списка первый видимый элемент имеет одинаковый RuntimeId.


tormozit
#16, ред. 28 декабря 2024 14:51

Тогда остается только способ из (1) - искать непрерывную серию строк в начале последней страницы, которая совпадает по содержимому всех ячеек с последними строками предыдущей страницы. Число колонок получаем через горизонтальные рамки https://turboconf.ru/Tasks/9950


tormozit
#17, 28 декабря 2024 14:44

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

Первая страница

Вторая страница

А вот какую таблицу я получил - пропали 3 строки на стыке страниц


bolsun
#18, 28 декабря 2024 15:02

(17) tormozit, в этом окне можно получить все элементы без обхода, просто нажав Ctrl+C.


tormozit
#19, ред. 28 декабря 2024 15:11

(18) bolsun, это лишь частный случай. Я говорю про общий случай - универсальную функцию получения содержимого списка.


tormozit
#20, ред. 28 декабря 2024 15:14

Еще можно переложить на меня часть этих проблем путем добавления метода "ПолучитьВидимыеЭлементыСписка()" и тогда листанием и наложением страниц буду заниматься уже я.


tormozit
#21, 28 декабря 2024 15:22

(17) tormozit, и тут задержка не влияет. Видимо тут ты наоборот умышленно пропускаешь строки, думая что они будут дублями.


bolsun
#22, 29 декабря 2024 13:38

(20) tormozit,
6.3.9129.26751
https://disk.yandex.ru/d/ay0Wg6IBTsxSxg

API

  • Добавлен метод ТурбоКонф.ПолучитьВидимыеЭлементыСписка()
    Метод возвращает видимые элементы текущего списка.
    Возвращаемое значение. Структура
  • ИменаЭлементов. Массив. Строка
  • ГраницыЭлементов. Массив целых чисел
Элементы = ТурбоКонф.ПолучитьВидимыеЭлементыСписка();

Для каждого Имя Из Элементы.ИменаЭлементов Цикл
    Сообщить(Имя);
КонецЦикла;

Для каждого Значение Из Элементы.ГраницыЭлементов Цикл
    Сообщить(Значение);
КонецЦикла;


tormozit
#23, ред. 29 декабря 2024 17:09

(22) bolsun, работает некорректно. Всегда переходит в начало списка (проверял в том же списке). Ожидалось просто получение тех ячеек, которые уже видны, без какого либо воздействия на состояние списка.
Тест

			ТурбоКонф.Клавиша(Клавиши.PageDown); 
			ТурбоКонф.Клавиша(Клавиши.PageDown); 
			ВидимыеЯчейки = ТурбоКонф.ПолучитьВидимыеЭлементыСписка();


bolsun
#24, 29 декабря 2024 19:25

Убрал нажатие Home
6.3.9129.38237
https://disk.yandex.ru/d/ay0Wg6IBTsxSxg


tormozit
#25, ред. 29 декабря 2024 22:07

Позиция теперь не меняется, как и ожидал. Но длительность очень большая -1900мс на один вызов при 20 строках и 6 колонках, а ПолучитьЭлементыСписка в тех же условиях 1300мс с учетом 2-х страниц (одной смены листа). Т.е. где то в 3 раза медленнее. Возможно причина в сборе границ. Собирать их нужно только при первом вызове. Дальше они уже не меняются в рамках одного сканирования списка. Поэтому предлагаю добавить параметр-флаг для сбора границ. Я его буду включать только при первом вызове. А дальше буду только тексты ячеек получать.


tormozit
#26, ред. 29 декабря 2024 23:52

Написал и простестировал алгоритм, который работает корректно везде при выполнении всех условий:

  • нет колонок с динамическим (зависящим от текущей строки) заголовком
  • нет неудобно расположенных полных дублей строк

Но работает он заметно медленнее чем ПолучитьЭлементыСписка() и вся разница в длительности обусловлена вызовами ПолучитьВидимыеЭлементыСписка()

ТурбоКонф.Клавиша(Клавиши.Home);
	МоментНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
	ВидимыеЯчейки = ТурбоКонф.ПолучитьВидимыеЭлементыСписка(); 
	Сообщить("ПолучитьВидимыеЭлементыСписка - " + (ТекущаяУниверсальнаяДатаВМиллисекундах() - МоментНачала) + " мс");
	ЧислоКолонок=1;
		ЛеваяГраницаСписка = Неопределено;
		ЗаголовокПервойКолонки = МодулиИР.ирОбщий.ПоследнийФрагментЛкс(ВидимыеЯчейки.ИменаЭлементов[0], " ", Ложь);
		Для ИндексЯчейки = 0 По ВидимыеЯчейки.ИменаЭлементов.ВГраница() Цикл
			Если Истина
				И ВидимыеЯчейки.ГраницыЭлементов[ИндексЯчейки*4 + 0] = 0 
				И ВидимыеЯчейки.ГраницыЭлементов[ИндексЯчейки*4 + 2] = 0
			Тогда
				Продолжить;
			КонецЕсли;
			ЛеваяГраницаЯчейки = ВидимыеЯчейки.ГраницыЭлементов[ИндексЯчейки*4 + 0];
			Если ЛеваяГраницаСписка = Неопределено Тогда
				ЛеваяГраницаСписка = ЛеваяГраницаЯчейки; 
			Иначе
				Если Истина
					И ЗаголовокПервойКолонки = МодулиИР.ирОбщий.ПоследнийФрагментЛкс(ВидимыеЯчейки.ИменаЭлементов[ИндексЯчейки], " ", Ложь)
					И ЛеваяГраницаЯчейки = ЛеваяГраницаСписка 
				Тогда
					Прервать;
				КонецЕсли;
			КонецЕсли;
		КонецЦикла;
		Если ИндексЯчейки > 0 Тогда
			ЧислоКолонок = ИндексЯчейки;
		КонецЕсли;
	ТекстыЯчеек = ВидимыеЯчейки.ИменаЭлементов;
	ЧислоВидимыхСтрок = ВидимыеЯчейки.ИменаЭлементов.Количество() / ЧислоКолонок;
	ТурбоКонф.Клавиша(Клавиши.PageDown);
	ЧислоСтрокПересеченияСтраниц = 1000;
	Пока Истина Цикл
		ТурбоКонф.Клавиша(Клавиши.PageDown); 
		ВидимыеЯчейки = ТурбоКонф.ПолучитьВидимыеЭлементыСписка();
		ИндексВидимойСтроки = 0;
		Для ОбратныйИндексСтроки = 0 По ЧислоВидимыхСтрок - 1 Цикл
			ИндексСтроки = ТекстыЯчеек.Количество() / ЧислоКолонок - 1 - ОбратныйИндексСтроки;
			ЯчейкиСтрокРавны = Истина;
			Для ИндексКолонки = 0 По ЧислоКолонок - 1 Цикл
				Если ВидимыеЯчейки.ИменаЭлементов[ИндексВидимойСтроки*ЧислоКолонок+ИндексКолонки] <> ТекстыЯчеек[ИндексСтроки*ЧислоКолонок+ИндексКолонки] Тогда
					// Не поддерживаем колонки с засимым от строки заголовком (например поля набора данных компоновки)
					ЯчейкиСтрокРавны = Ложь;
					Прервать;
				КонецЕсли;
			КонецЦикла;
			Если ЯчейкиСтрокРавны Тогда
				Для Сч=0 По (ОбратныйИндексСтроки+1)*ЧислоКолонок-1 Цикл
					ВидимыеЯчейки.ИменаЭлементов.Удалить(0);
				КонецЦикла;
				Прервать;
			КонецЕсли;
		КонецЦикла;
		ДополнитьМассивЛкс(ТекстыЯчеек, ВидимыеЯчейки.ИменаЭлементов);
		Если ВидимыеЯчейки.ИменаЭлементов.Количество() = 0 Тогда
			Прервать;
		КонецЕсли;
		ЧислоСтрокПересеченияСтраниц = ОбратныйИндексСтроки;
	КонецЦикла;


tormozit
#27, 29 декабря 2024 22:14

Еще было бы полезно в результате метода ПолучитьВидимыеЭлементыСписка() добавить свойство ИндексТекущегоЭлемента. Опять же оно нужно при сканировании только при первом вызове.


bolsun
#28, 29 декабря 2024 22:53

https://disk.yandex.ru/d/ay0Wg6IBTsxSxg

Добавлен параметр РасширеннаяИнформация.
Кроме имен элементов будут получены ГраницыЭлементов и ИндексТекущегоЭлемента. Необязательный. По умолчанию Ложь. Булево.

Также оптимизировано получение границ элементов.


tormozit
#29, ред. 29 декабря 2024 23:34

(28) bolsun, подтверждаю ускорение и корректную работу нового флага и свойства. Надежность/корректность механизма сканирования списка выросла и скорость теперь сопоставима с ПолучитьЭлементыСписка().


bolsun
#30, 10 января 2025 19:01

bolsun изменил статус на Закрыто


Для вставки изображения или файла, перетащите его в поле редактора или вставьте файл из буфера