Имя: Пароль:
1C
 
СправочникСписок. Динамические элементы
0 pessok
 
14.10.10
15:26
Доброго времени суток. У меня возникла проблемы с тривиальной, на первый взгляд, задачей. Существует справочник "Контрагенты", в котором имеется табличная часть "Услуги", имеющая реквизиты НаименованиеУслуги с типом СправочникСсылка.Услуги и СтатусРаботы с типом ПеречислениеСсылка.СтатусыРабот. В форме списка требуется динамически создавать колонки с НазваниеУслуги, которые должны раскрашиваться в зависимости от СтатусыРабот. По умолчанию, в ТЧ справочника Контрагенты внесены все возможные услуги из справочника Услуги, благо их не много, но количество может увеличиться, потому приходится делать динамическое заполнение СправочникСписок. В справочнике Контрагенты порядка 3000 записей. Конфигурация самописная. В принципе, написанный мной код работает, но ОЧЕНЬ медленно. Хотелось бы выслушать мнения гуру по данному вопросу :) В Выкладываю код на растерзание.
Форма:

Процедура ПриОткрытии()
   СпрУслуги = Справочники.Услуги.Выбрать();
   Колонка = ЭлементыФормы.СправочникСписок.Колонки;
   Пока СпрУслуги.Следующий() Цикл
       Попытка
           НоваяКолонка = Колонка.Добавить(СпрУслуги.Наименование);
           НоваяКолонка.Ширина = 9;
           НоваяКолонка.ГоризонтальноеПоложениеВШапке = ГоризонтальноеПоложение.Центр;
       Исключение
           Предупреждение("Невозможно создать колонку "+СпрУслуги.Наименование+"!"+Символы.ПС+"Нельзя использовать пробелы в названии услуги!");
       КонецПопытки;
   КонецЦикла;
КонецПроцедуры


СправочникСписок:

Процедура СправочникСписокПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
   СпрУслуги = Справочники.Услуги.Выбрать();
   Пока СпрУслуги.Следующий() Цикл
       НазваниеКолонки = СпрУслуги.Наименование;
       Ячейка = ОформлениеСтроки.Ячейки.Найти(НазваниеКолонки);
       Для Каждого СтрокаТЧ Из Справочники.Контрагенты.НайтиПоНаименованию(ДанныеСтроки.Наименование).Услуги Цикл
               Если СтрокаТЧ.НаименованиеУслуги = Справочники.Услуги.НайтиПоНаименованию(НазваниеКолонки) Тогда
               Если СтрокаТЧ.СтатусРаботы = Перечисления.СтатусыРабот.ВПроцессе Тогда
                   Ячейка.ЦветФона = Новый Цвет(255,210,13);
               ИначеЕсли СтрокаТЧ.СтатусРаботы = Перечисления.СтатусыРабот.Работаем Тогда
                   Ячейка.ЦветФона = Новый Цвет(51,153,102);
               ИначеЕсли СтрокаТЧ.СтатусРаботы = Перечисления.СтатусыРабот.НеРаботаем Тогда
                   Ячейка.ЦветФона = Новый Цвет(250,100,100);
               КонецЕсли;
           КонецЕсли;
       КонецЦикла;
   КонецЦикла;

Прошу очень больно ногами не бить, ни разу до этого не сталкивался с динамическими списками
1 Hmster
 
14.10.10
15:51
Не надо ЭТО в справочник пихать. Если ОЧЕНЬ хочется создай отчет.
2 pessok
 
14.10.10
16:00
Дело в том, что это НАДО, к сожалению, пихать в справочник, я не сам себе начальник. Да и, в принципе, если это запихивать не в справочник. то куда? Отчет это выход, конечно, но немного костыльный. По существу, возможно ли организовать именно то, что требуется в данный момент, не потеряв существенно в скорости?
3 GenV
 
14.10.10
16:02
(2) Сделай ТЗ в обработке, заполняемую по кнопке. По крайней мере, будете ждать только при заполнении. Прокрутка нормально работать будет.
ЗЫ Пора уже привыкать что это не 7.7
4 pessok
 
14.10.10
16:02
Да и отчет не даст всех возможностей работы с формой, как пример - РежимВыделенияСтроки.
5 pessok
 
14.10.10
16:03
(3) К сожалению, не вариант. ФФорма списка должна являться рабочим столом
6 GenV
 
14.10.10
16:13
(5) У тебя вариантов, то не много - либо ТЗ, либо отчет, либо тормоза ...
7 Михаил Козлов
 
14.10.10
16:14
(0) Немного ускорить может ПриПолученииДанных с кэшем. Но смысла не вижу: ни отбора ни сортировки по этим колонкам делать нельзя. Только раскраска. Проще отбор в списке в соответствии с потребностями (например, Услуга такая-то, статус такой-то).
8 pessok
 
14.10.10
16:21
(6) Либо отговорить начальника... Но с ТЗ рассмотрю, спасибо.
(7) Пробовал, ускоряет действительно немного, и при таком объеме практически незаметно. Немного не понял. что Вы имели ввиду под "Проще отбор в списке в соответствии с потребностями (например, Услуга такая-то, статус такой-то)". Спсиок нужно выводить полностью. Ну разве что с отбором по менеджеру.
9 Михаил Козлов
 
14.10.10
16:29
На форме списка организуете поля ввода для задания фильтров на услуги и статусы. Лучше через отбор построителя (табличное поле) для возможности задавать разные условия.
По кнопке (или еще как-то) определяете, какие контрагенты удовлетворяют этим условиям, их в список (значений) и отбор для СправочникСписок с видом сравнения ВСписке. Делал похоже, вроде, ничего.

Только сейчас обратил внимание на
"Для Каждого СтрокаТЧ Из Справочники.Контрагенты.НайтиПоНаименованию(ДанныеСтроки.Наименование).Услуги Цикл...".
Зачем контрагента ищете в справочнике? Он же у Вас уже есть: ДанныеСтроки.Ссылка.
10 pessok
 
14.10.10
16:38
(9) Попробую с отбором, но не уверен, что понравится начальству :) Цель - сделать работу менеджера по типу "Нажать, чтобы было пи###то, а желательно не нажимать ничего!", прошу прощения за мат. На проблемы программирования всем наплевать. Желательно все же не создавать дополнительных полей выбора. Отбор по менеджеру автоматический из реквизита справочника. Спасибо за поправку обхода, действительно не усмотрел!
11 Михаил Козлов
 
14.10.10
16:46
(10) Если начальству нужно только раскрасить, то попробуйте ПриПолученииДанных с кэшем (типа индексированной ТЗ). И сразу установить (в ПриОткрытии, там где добавляете колонки) соответствие колонок табличного поля и услуг, чтобы обращаться к колонкам по индексу, а не искать по наименованию. Вполне возможно, производительность будет приемлимая.
12 GenV
 
14.10.10
16:47
(10) Попробуй в ПриПолученииДанных сначало собрать массив всех контрагентов и помещения их в соответствие Ссылка->ОформлениеСтроки, затем запросом к Контрагенты.Услуги (с отбором по полученному массиву контрагентов) получить нужные данные. Потом повторный перебор и по ссылке, услуге и статусу из запроса установка цвета колонки. По крайней мере намного быстрее (0) будет.
13 pessok
 
14.10.10
16:53
(11) Пробовал нечто подобное с занесением в ТЗ и обработкой в ПриОткрытии. Форма открывается быстрее, но полнотекстовый поиск и отрисовка новых строк также хромает. или я Вас не до конца понял?
(12) Чесно говоря, не совсем понял, что конкретно надо сделать... Есть ссылочка на небольшой пример или нечто подобное? Можно абстрактно :)
14 GenV
 
14.10.10
16:54
15 pessok
 
14.10.10
16:57
(14) спасибо, почитаю
16 Александр Б
 
14.10.10
17:02
У тебя при выводе каждой строки идет выборка справочника услуги, что тоже очень сильно замедляет работу.
Можно сделать следующее, прочитать услуги один раз при открытии формы, как у тебя уже есть. А эту переменную добавить в реквизит или объявнить на всю форму.
И уже при выводе строки не перечитывать спрУслуги а уже готовую смотреть.
По необходимости добавить кнопку на форму, которая будет обновлять спрУслуги. Но это понадобится только тогда, если в момент, когда открыта форма, добавлена новая услуга. Но я так понимаю, что это будет не часто.
17 pessok
 
14.10.10
17:09
(16) Я понимаю, что обход по услугам идет при выводе каждой строки, но вот как этого обхода не делать, я никак понять не могу, в том то и дело. Толи туплю уже к концу дня, толи просто туплю... >>А эту переменную добавить в реквизит или объявнить на всю форму.
Какую конкретно переменную, и как не обходя каждый элемент СправочникСписок с ней сравнить? Вот в чем вопрос :)
18 FIXXXL
 
14.10.10
17:11
чет у меня ощущение, что изначально структура хранения данных непродумана, оттого и тормоза

не лучше б было связку Контрагент-Услуга-Статус хранить в регистре сведений? оттуда и получать запросом быстрее
19 Александр Б
 
14.10.10
17:12
В самом начале модуля формы сделай "Перем СпрУслуги"; либо можешь в реквизиты формы добавить.
А в процедуре ПриВыводеСтроки делай СпрУслуги.Сбросить();
Это первый вариант.

Второй:
СпрУслуги сделать не выборку, а выгружать. А потом вместо СпрУслуги.Следующий() использовать Для Каждого
20 Александр Б
 
14.10.10
17:14
+(19)
то есть вместо

Процедура СправочникСписокПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
   СпрУслуги = Справочники.Услуги.Выбрать();
   Пока СпрУслуги.Следующий() Цикл

Делай

Процедура СправочникСписокПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
   СпрУслуги.Сбросить();

   Пока СпрУслуги.Следующий() Цикл
21 Александр Б
 
14.10.10
17:14
Это уже как минимум в разы ускорит вывод.
22 pessok
 
14.10.10
17:25
(21) Спасибо, попробую сейчас
(18) Возможно, Вы и правы. Но теперь уже, к сожалению, поздно :) Переписывать всю структуру конфы я не готов.
23 pessok
 
14.10.10
17:30
(21) Гм. Определил глобальную переменную в модуле формы. Перебираю, соответственно в ПриОткрытии. В ПриВыводеСтроки убрал определение и сделал перед обходом СпрУслуги.Сбросить()
Ругается: Метод объекта не обнаружен... (Сбросить). чяднт?
24 Михаил Козлов
 
14.10.10
17:33
(13) Пока без кэша. Заводите в модуле формы переменную, скажем ЛокаторУслуг. В При Открытии пишете:
ЛокаторУслуг = Новый Соответствие;
Потом внутри цикла после
НоваяКолонка = Колонка.Добавить(СпрУслуги.Наименование);
//имейте в виду, что если наименвание услуги не сможет быть именем колонки, то возникнет ошибка
пишете ЛокаторУслуг.Вставить(СпрУслуги.Ссылка, НоваяКолонка.Имя);  

В ПриПолученииДанных перебирая строки ТЧ услуги
ДЛЯ каждого услуга ИЗ ОформленияСтрок.ДанныеСтроки.Ссылка.Услуги Цикл
 имяКолонкиТП = ЛокаторУслуг.Получить(услуга);
 // здесь устанавливаете цвет ячейки по имени колонки
КонецЦикла;
25 pessok
 
14.10.10
17:37
(24) Спасибо, попробуем. Через соответствия я еще не пробовал :)
26 Александр Б
 
14.10.10
17:49
(23)
Сделай вместо СпрУслуги = Справочники.Услуги.Выбрать(); обычный запрос.

По типу

Запрос = Новый Запрос("ВЫБРАТЬ * ИЗ Справочник.Услуги");
СпрУслуги = Запрос.Выполнить().Выбрать();

Так точно будет работать. Только что проверил.
27 pessok
 
14.10.10
17:54
(23) Окей, тоже попробую :)
28 pessok
 
14.10.10
17:54
Всем спасибо, буду разбираться с Вашими советами и отпишусь о результатах :)
29 pessok
 
14.10.10
18:09
(26) Через запрос сработало, но на скорость, к сожалению, никак не повлияло.
30 Александр Б
 
14.10.10
18:24
(29) Этот способ явно быстрее. Но если мало скорость увеличилась, значит "основная замедляющая состовляющая" связана с контрагентом. Читай советы, пробуй :)
31 pessok
 
14.10.10
18:26
(30) та пробую. по-разному пробую, но что-то пока никак :)
32 Александр Б
 
14.10.10
18:29
Нужно при открытии подготовить ТЗ, как уже советовали, чтобы при выводе строки делать поиск не по БД, а из оперативной памяти, то есть подготовленной переменной.
Точно будет быстрее. Почитай, что предложили, или придумай еще какой механизм.
33 pessok
 
14.10.10
18:30
(24) не могу разобраться, как обращаться к членам Соответствия. При раскраске попробовал код

Процедура СправочникСписокПриПолученииДанных(Элемент, ОформленияСтрок)
   Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл
       Для Каждого Услуга Из ОформлениеСтроки.ДанныеСтроки.Ссылка.Услуги Цикл
           имяКолонкиТП = ЛокаторУслуг.Получить(Услуга);
           Ячейка = ОформлениеСтроки.Ячейки.Найти(имяКолонкиТП.НаименованиеУслуги);
           Если имяКолонкиТП.НаименованиеУслуги = Справочники.Услуги.НайтиПоНаименованию(имяКолонкиТП.НаименованиеУслуги) Тогда
               Если имяКолонкиТП.СтатусРаботы = Перечисления.СтатусыРабот.ВПроцессе Тогда
                   Ячейка.ЦветФона = Новый Цвет(255,210,13);
               ИначеЕсли имяКолонкиТП.СтатусРаботы = Перечисления.СтатусыРабот.Работаем Тогда
                   Ячейка.ЦветФона = Новый Цвет(51,153,102);
               ИначеЕсли имяКолонкиТП.СтатусРаботы = Перечисления.СтатусыРабот.НеРаботаем Тогда
                   Ячейка.ЦветФона = Новый Цвет(250,100,100);
               КонецЕсли;
           КонецЕсли;
       КонецЦикла;
   КонецЦикла;
КонецПроцедуры

Но ругается на            Ячейка = ОформлениеСтроки.Ячейки.Найти(имяКолонкиТП.НаименованиеУслуги);
Значение не является значением объектного типа (НаименованиеУслуги)
Понимаю, что неправильно обращаюсь к элементу, а как правильно. Что-то даже и нагуглить ничего толком не получилось. Заранее спасибо :)
34 Михаил Козлов
 
14.10.10
18:44
Перестаньте искать в справочниках и колонках таб. поля.
имяКолонкиТП должно быть именем колонки (посмотрите под отладчиком - мог ошибиться).
Соответствующая ячейка: Ячейка = ОформлениеСтроки.Ячейки[имяКолонкиТП]; Соответствующая строка ТЧ - услуга (переменная цикла). Ее статус: услуга.СтатусРаботы - по нему и раскрашивайте.
35 pessok
 
14.10.10
21:08
(34) Благодарю за разъяснения. Теперь понятно. Учиться никогда не грех :) Завтра попробую на работе. Еще раз спасибо
36 pessok
 
14.10.10
21:17
(32) завтра попробую и с соответствием и с ТЗ. Спасибо :)
37 pessok
 
15.10.10
09:59
(34) Огромное спасибо, скорость, действительно, возросла в разы. В принципе, даже на медленной машинке работает более-менее шустро. Может можно сделать еще быстрее, простите за наглость? :)
38 Михаил Козлов
 
15.10.10
11:41
(37) Кэш используете? Под кэшем я понимаю некоторую структуру в памяти, в которой хранятся уже полученные данные. Например, Соответствие, в котором ключом будет ссылка на справочник контрагентов, а значением, скажем, тоже Соответствие, у которого ключом будет имя колонки и цвет. Или массив цветов, так чтобы за цветом обращаться по индексу. В этом случае при необходимости раскрасить Вы лезете в верхнее соответствие за цветами. Если их нет - добавляете нужные данные.
39 pessok
 
15.10.10
11:53
(38) Окей, сделаем, спасибо!
Считаю тему закрытой :)