Столкнулся давеча с задачей:
- Пользователям сложно смотреть отчёты, в которых много колонок. Им хотелось подсвечивать текущую строку (строку в которую они ткнули мышкой), чтобы с неё взгляд не сбивался на соседние строки.
- Также необходимо, чтобы при выделении пользователем нескольких ячеек из соседних строк, выделялись все эти несколько строк.
- Далее решено было добавить этот механизм ВО ВСЕ отчёты и ПРИ ЭТОМ НИЧЕГО НЕ СЛОМАТЬ (здесь было МНОГО тонкостей - всё подробно откомментил в программном коде).
Поиск решения:
- Установка выделенных строк не подходит, т.к. придётся скидывать выделение произведённое пользователем, и сломается суммирование чисел в выделенных ячейках, т.к. будет выделяться целиком строка.
- Также можно вытащить заголовки строк - но это отъедает лишнее место и для выделения строки, надо тыкать именно в заголовок, а при переходе к ячейке, это выделение слетит и опять ломай глаза для поиска соседних ячеек по строке
- Поэтому выбран вариант обведения строки, лишённый минусов выше, но имеющий дополнительный плюс - внутри обведённой строки, отдельно видно выделенные ячейки, что позволяет фокусировать на них внимание.
- При этом не стал менять цвет обведения по причинам (но при желании это несложно добавить):
	- чтобы он не совпал с цветом фона текущей или соседней строки и гарантированно нормально выделялся на фоне строки. А цвет обведения по умолчанию должен изначально удовлетворять данным правилам - поэтому его лучше не трогать.
- выше производительность, не нужно в дополнение сохранять и восстанавливать ещё и цвет границы.
 
- Вместо того, чтобы обводить ячейки, естественно можно их заливать фоном. Реализация будет почти та же самая, что и предложена в статье. Не стал делать по причинам:
	- Но в таком случае есть риск не угадать с фоном, чтобы он одновременно нормально отображался для всех настроек оформления в разных базах.
- Выбранный цвет фона может совпасть с соседним цветом фона.
- Также вероятность найти отчёт, где ячейки имеют разный фон, выше, чем отчёт, где ячейки по-разному обведены. А когда в строке разные настройки ячеек, это несёт доп. сложности, и в производительности кода и в подборе правильного нового фона выделения.
- При заливке фоном мы потеряем то выделение фоном, которое существует и несёт дополнительную информацию. Например, потеряем выделение цветом особой ячейки, или при выделении нескольких строк потеряем чередование цвета строк, которое часто делают для удобства просмотра строк в отчёте.
- Для выделения фоном, надо вычислять и хранить больше данных - хранить данные не только верхней и нижней выделенной строки, но и всех внутренних - чтобы вернуть их потом в исходное положение
 
Смысл найденного решения:
- получаем выделенные строки
- запоминаем их обведение до наших изменений
- обводим выделенные строки
- снимаем обведение с предыдущих выделенных строк
- ЧТОБЫ НИЧЕГО НЕ СЛОМАТЬ учитываем, что обведение могло быть разным у разных ячеек строки
Распространение решения:
Чтобы решение появилось сразу во всех отчётах, где не переопределена форма отчёта, в общую форму отчёта добавляем программный код ниже. Для отчётов, у которых определена собственная форма отчёта, очевидно, данную настройку надо провести в собственной форме.
&НаКлиенте
Перем ДанныеВыделенныхСтрок;
&НаКлиенте
Процедура ОтчетТабличныйДокументПриАктивизации(Элемент)
    // Делаем через обработчик ожидания, чтобы дать возможность выделить несколько строк,
    // т.к. событие срабатывает сразу при выделении первой ячейки.
    ПодключитьОбработчикОжидания("ВыделитьТеущиеСтроки", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ВыделитьТеущиеСтроки()
    // 1. Найдём строки, где выделены ячейки
    ТекВерх = ОтчетТабличныйДокумент.ТекущаяОбласть.Верх;
    ТекНиз = ОтчетТабличныйДокумент.ТекущаяОбласть.Низ;
    ОбластьТекСтроки = ОтчетТабличныйДокумент.Область(ТекНиз,,ТекВерх);
    
    // 2. Скинем предыдущее обведение в состояние до нашего вмешательства
    Если ДанныеВыделенныхСтрок <> Неопределено Тогда
        //2.1. Если выделенные строки не менялись - ничего не делаем
        Если ТекВерх = ДанныеВыделенныхСтрок.Верх И ТекНиз = ДанныеВыделенныхСтрок.Низ Тогда
            Возврат;
        КонецЕсли;
        
        // 2.2. Вернём назад верхнюю границу
        // Обнаружена багофича, что если строке целиком вернуть толщину, которая была у неё изначально, то результат будет отличаться от начального.
        // Изначально для колонок идущих правее последней колонки (т.е. с номером больше, чем ШиринаТаблицы) Границы не отображаются.
        // Но после установки новой границы, начнёт отображаться. Поэтому сначала полностью стираем границу, которую мы установили выделением,
        // потом для колонок отчёта (с первой по ШиринаТаблицы) возвращаем сохранённую границу.
        // Альтернативный вариант - можно выделять не всю строку, а только колонки с первой по ШиринаТаблицы - но он кажется менее функциональным и интуитивно понятным.
        
        НевидимаяЛиния = Новый Линия(ТипЛинииЯчейкиТабличногоДокумента.НетЛинии);
        СтрокаВерх = ОтчетТабличныйДокумент.Область(ДанныеВыделенныхСтрок.Верх,, ДанныеВыделенныхСтрок.Верх);
        СтрокаВерх.ГраницаСверху = НевидимаяЛиния;
        
        ОбластьВерх = ОтчетТабличныйДокумент.Область(ДанныеВыделенныхСтрок.Верх, 1, ДанныеВыделенныхСтрок.Верх, ОтчетТабличныйДокумент.ШиринаТаблицы);
        Если ДанныеВыделенныхСтрок.ГраницаСверху <> Неопределено Тогда
            ОбластьВерх.ГраницаСверху = ДанныеВыделенныхСтрок.ГраницаСверху;
        Иначе
            Для Каждого НастройкиЯчейки Из ДанныеВыделенныхСтрок.УникальныеНастройкиГраницыВерх Цикл
                ТекЯчейкаВерх = ОтчетТабличныйДокумент.Область(ДанныеВыделенныхСтрок.Верх, НастройкиЯчейки.НомерКолонки,
                        ДанныеВыделенныхСтрок.Верх, НастройкиЯчейки.НомерКолонки);
                ТекЯчейкаВерх.ГраницаСверху = НастройкиЯчейки.ГраницаСверху;
            КонецЦикла;
        КонецЕсли;
        
        // 2.3. Вернём назад нижнюю границу
        СтрокаНиз = ОтчетТабличныйДокумент.Область(ДанныеВыделенныхСтрок.Низ,, ДанныеВыделенныхСтрок.Низ);
        СтрокаНиз.ГраницаСнизу = НевидимаяЛиния;
        
        ОбластьНиз = ОтчетТабличныйДокумент.Область(ДанныеВыделенныхСтрок.Низ, 1, ДанныеВыделенныхСтрок.Низ, ОтчетТабличныйДокумент.ШиринаТаблицы);
        Если ДанныеВыделенныхСтрок.ГраницаСнизу <> Неопределено Тогда
            ОбластьНиз.ГраницаСнизу = ДанныеВыделенныхСтрок.ГраницаСнизу;
        Иначе
            Для Каждого НастройкиЯчейки Из ДанныеВыделенныхСтрок.УникальныеНастройкиГраницыНиз Цикл
                ТекЯчейкаНиз = ОтчетТабличныйДокумент.Область(ДанныеВыделенныхСтрок.Низ, НастройкиЯчейки.НомерКолонки,
                        ДанныеВыделенныхСтрок.Низ, НастройкиЯчейки.НомерКолонки);
                ТекЯчейкаНиз.ГраницаСнизу = НастройкиЯчейки.ГраницаСнизу;
            КонецЦикла;
        КонецЕсли;
    КонецЕсли;
        
    // 3. При выделении всего документа, дальнейшие действия не требуются.
    // Более того, если не сделать эту проверку, то дальше упадём с ошибкой, при попытке получения ячейки с координатами (0,х,0,х)
    ВыделенВесьТабДок = ТекВерх = 0 Или ТекНиз = 0;
    Если ВыделенВесьТабДок Тогда
        // обработка выделенных строк на прошлом шаге для случая, когда ВыделенВесьТабДок = Истина, инициирует событие ПриАктивизации.
        // Чтобы не заходить в бесконечный цикл, очистим данные выделенных строк.
        ДанныеВыделенныхСтрок = Неопределено;
        Возврат;
    КонецЕсли;
    
    // 4. Запомним текущие значения обведённости строк
    ДанныеВыделенныхСтрок = Новый Структура;
    ДанныеВыделенныхСтрок.Вставить("Верх", ТекВерх);
    ДанныеВыделенныхСтрок.Вставить("Низ", ТекНиз);
    ДанныеВыделенныхСтрок.Вставить("ГраницаСверху", ОбластьТекСтроки.ГраницаСверху);
    ДанныеВыделенныхСтрок.Вставить("ГраницаСнизу", ОбластьТекСтроки.ГраницаСнизу);
    
    // В общем случае у разных ячеек строки могут быть разные настройки Границ (настройки обведения)
    // и чтобы вернуть их назад, их надо запомнить.
    // Свойство ГраницаСверху (и все остальные границы) для области будет иметь значение неопределено,
    // если для разных ячеек области у этой границы будут отличаться толщина или тип границы
    // Отмечу, что ЦветРамки при этом, может отличаться, и на Границы это никак не повлияет,
    // т.к. ЦветРамки является самостоятельным свойством области, как и сама Граница.
    
    УникальныеНастройкиГраницыВерх = Новый Массив;
    ДанныеВыделенныхСтрок.Вставить("УникальныеНастройкиГраницыВерх", УникальныеНастройкиГраницыВерх);
    Если ОбластьТекСтроки.ГраницаСверху = Неопределено Тогда
        Для НомерКолонки = 1 По ОтчетТабличныйДокумент.ШиринаТаблицы Цикл
            НастройкиЯчейки = Новый Структура("НомерКолонки, ГраницаСверху");
            НастройкиЯчейки.НомерКолонки = НомерКолонки;
            
            ЯчейкаВерх = ОтчетТабличныйДокумент.Область(ТекВерх, НомерКолонки, ТекВерх, НомерКолонки);
            НастройкиЯчейки.ГраницаСверху = ЯчейкаВерх.ГраницаСверху;
            
            УникальныеНастройкиГраницыВерх.Добавить(НастройкиЯчейки);
        КонецЦикла;
    КонецЕсли;
    
    УникальныеНастройкиГраницыНиз = Новый Массив;
    ДанныеВыделенныхСтрок.Вставить("УникальныеНастройкиГраницыНиз", УникальныеНастройкиГраницыНиз);
    Если ОбластьТекСтроки.ГраницаСнизу = Неопределено Тогда
        Для НомерКолонки = 1 По ОтчетТабличныйДокумент.ШиринаТаблицы Цикл
            НастройкиЯчейки = Новый Структура("НомерКолонки, ГраницаСнизу");
            НастройкиЯчейки.НомерКолонки = НомерКолонки;
            
            ЯчейкаНиз = ОтчетТабличныйДокумент.Область(ТекНиз, НомерКолонки, ТекНиз, НомерКолонки);
            НастройкиЯчейки.ГраницаСнизу = ЯчейкаНиз.ГраницаСнизу;
            
            УникальныеНастройкиГраницыНиз.Добавить(НастройкиЯчейки);
        КонецЦикла;
    КонецЕсли;
    
    // 5. Обведём текущие строки сверху и снизу самой толстой линией.
    // Ограничения (встречаются крайне редко): если строка уже обведена самой толстой линией, то при установке курсора на ней, ничего не изменится.
    // Избавиться от этого без побочных эффектов невозможно, потому что,
    // если в таком случае наоборот убирать обведение, то строка перестанет выделяться на фоне остальных строк.
    // Логика подсказывает, что выделенных строк в отчёте должно быть меньшинство, иначе теряется смысл их выделения.
    // Поэтому даже если на практике и встретится такой отчёт (а вероятность этого мала),
    // то выделение текущей строки в нём всё равно будет приносить, тот результат, которого мы и добивались.
    НаибольшаяВозможнаяТолщинаЛинии = 3;//ограничение платформы
    Линия = Новый Линия(ТипЛинииЯчейкиТабличногоДокумента.Сплошная, НаибольшаяВозможнаяТолщинаЛинии);
    
    СтрокаВерх = ОтчетТабличныйДокумент.Область(ТекВерх,,ТекВерх);
    СтрокаВерх.ГраницаСверху = Линия;
    
    СтрокаНиз = ОтчетТабличныйДокумент.Область(ТекНиз,,ТекНиз);
    СтрокаНиз.ГраницаСнизу = Линия;
КонецПроцедуры
Побочное действие (НЕСУЩЕСТВЕННОЕ и встречаются крайне РЕДКО):
- если выделить несколько таблиц внутри одного отчёта, то выделение слетит до выделения первой таблицы. Поэтому при необходимости скопировать несколько таблиц, можно скопировать сначала весь отчёт.
Ограничения и особенности (встречаются крайне редко):
- Если строка уже обведена самой толстой линией, то при установке курсора на ней, ничего не изменится. Избавиться от этого без побочных эффектов невозможно, потому что, если в таком случае наоборот убирать обведение, то строка перестанет выделяться на фоне остальных строк. Логика подсказывает, что выделенных строк в отчёте должно быть меньшинство, иначе теряется смысл их выделения. Поэтому даже если на практике и встретится такой отчёт (а вероятность этого мала), то выделение текущей строки в нём всё равно будет приносить, тот результат, которого мы и добивались.
- Если в выделенной строке есть объединённые по вертикали ячейки, то обведение, в отличие от выделения, не разделит визуально объединённую ячейку на две части, а просто не будет в ней отображаться - в основном такое может быть только в шапке отчёта, где данный функционал и не нужен.
------------------------------------
ИНТЕРЕСНЫХ ВАМ ЗАДАЧ, ПЛОДОТВОРНОЙ РАБОТЫ И ОРИГИНАЛЬНЫХ/ОПТИМАЛЬНЫХ РЕШЕНИЙ!!
Проверено на платформе 8.3.17.1989.
Вступайте в нашу телеграмм-группу Инфостарт
 
                                 
                                     
                                     
                                     
                                     
                                     
                                     
                                     
                                    