ОЛЕСЯ МАКРОВИЧ
ИДЕАЛЬНЫЙ МАКРОС ДЛЯ КООРДИНАТНОГО ВЫДЕЛЕНИЯ
Умная фокусировка строки и столбца в Excel без потери форматирования
Вы уже видели, что в последних версиях Excel на вкладке «Вид» появилась кнопка «Фокусировка на ячейке»? Строка и столбец активной ячейки подсвечиваются автоматически и работать действительно удобнее.

Но что делать, если такой кнопки в вашей версии Excel нет?
Я долгое время видела в интернете два основных решения:
– через условное форматирование
– через макросы
Оба варианта рабочие. Но у каждого есть серьёзные недостатки (если интересно – свои аргументы написала ниже). И именно из-за них я решила сделать своё решение.

Я разработала макрос, который:
– перед подсветкой запоминает исходные цвета ячеек (круто же?:)
– при смене выбора восстанавливает их
– корректно обрабатывает клики вне UsedRange
– не использует Selection
– не ломает существующее форматирование
нет риска повредить данные
– может включаться и выключаться

По сути, это аккуратная программная фокусировка строки и столбца для версий Excel, где встроенной функции ещё нет.

Вот макрос, а ниже - инструкция 🙂

 

Option Explicit

Private mPrev As Object              ' Scripting.Dictionary
Private mPrevRange As Range          ' что подсвечивали в прошлый раз

Private Const FOCUS_COLOR As Long = 13828095 ' мягкий жёлтый (RGB(255, 255, 210))

Private mFocusEnabled As Boolean


Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    On Error GoTo ErrH
    
    If Not mFocusEnabled Then Exit Sub
    
    If Target Is Nothing Then Exit Sub
    If Target.Cells.CountLarge > 1 Then Set Target = Target.Cells(1, 1)

    Application.EnableEvents = False
    Application.ScreenUpdating = False

    RestorePrevious
    ApplyFocus Target

SafeExit:
    Application.ScreenUpdating = True
    Application.EnableEvents = True
    Exit Sub

ErrH:
    MsgBox "Ошибка " & Err.Number & vbCrLf & Err.Description, vbExclamation
    Resume SafeExit
End Sub

Private Sub ApplyFocus(ByVal c As Range)
    Dim ur As Range, rngRow As Range, rngCol As Range, focusRng As Range
    Dim cell As Range, key As String

    Set ur = Me.UsedRange
    If ur Is Nothing Then Exit Sub
    
    If Intersect(c, ur) Is Nothing Then Exit Sub


    ' строка и столбец ограничены UsedRange
    Set rngRow = Intersect(Me.Range(ur.Cells(1, 1), ur.Cells(ur.Rows.Count, ur.Columns.Count)).EntireRow, Me.Rows(c.Row))
    Set rngRow = Intersect(rngRow, ur)

    Set rngCol = Intersect(Me.Range(ur.Cells(1, 1), ur.Cells(ur.Rows.Count, ur.Columns.Count)).EntireColumn, Me.Columns(c.Column))
    Set rngCol = Intersect(rngCol, ur)

    If rngRow Is Nothing And rngCol Is Nothing Then Exit Sub

    If rngRow Is Nothing Then
        Set focusRng = rngCol
    ElseIf rngCol Is Nothing Then
        Set focusRng = rngRow
    Else
        Set focusRng = Union(rngRow, rngCol)
    End If

    ' исключаем активную ячейку без "вычитания диапазонов"
    If mPrev Is Nothing Then Set mPrev = CreateObject("Scripting.Dictionary")
    mPrev.RemoveAll

    For Each cell In focusRng.Cells
        If cell.Address = c.Address Then
            ' пропускаем активную
        Else
            key = cell.Address(False, False)
            mPrev(key) = Array(cell.Interior.Pattern, cell.Interior.ColorIndex, cell.Interior.Color)
        End If
    Next cell

    ' подсветка
    For Each cell In focusRng.Cells
        If cell.Address <> c.Address Then
            cell.Interior.Pattern = xlSolid
            cell.Interior.Color = FOCUS_COLOR
        End If
    Next cell

    Set mPrevRange = focusRng
End Sub

Private Sub RestorePrevious()
    If mPrevRange Is Nothing Then Exit Sub
    If mPrev Is Nothing Then Exit Sub
    If mPrev.Count = 0 Then
        Set mPrevRange = Nothing
        Exit Sub
    End If

    Dim cell As Range, key As String, pack As Variant

    For Each cell In mPrevRange.Cells
        key = cell.Address(False, False)
        If mPrev.Exists(key) Then
            pack = mPrev(key)
            cell.Interior.Pattern = pack(0)

            If pack(1) = xlColorIndexNone Then
                cell.Interior.ColorIndex = xlColorIndexNone
            Else
                cell.Interior.Color = pack(2)
            End If
        End If
    Next cell

    Set mPrevRange = Nothing
    mPrev.RemoveAll
End Sub


Public Sub FocusOn()
    mFocusEnabled = True
End Sub

Public Sub FocusOff()
    mFocusEnabled = False
    RestorePrevious ' чтобы сразу убрать подсветку
End Sub

Public Sub FocusToggle()
    If mFocusEnabled Then
        FocusOff
    Else
        FocusOn
    End If
End Sub

'Private Sub Worksheet_Activate()
'    If mFocusEnabled = False Then mFocusEnabled = True
'End Sub

 
1️⃣ Этот макрос нужно целиком скопировать и вставить в модуль листа. Для этого щёлкните по ярлыку листа, где нужно координатное выделение, выберите команду "Просмотреть код" и в открывшемся редакторе справа вставьте скопированный выше код.

2️⃣ Теперь на листе с таблицей добавьте любую фигуру (можно из вкладки "Вставка" обычный прямоугольник) и через контекстное меню добавьте этой фигуре макрос FocusToggle Кнопку можете подписать, как вам нравится (у меня это "Вкл/Выкл"), поместить в удобное место, и пользоваться. Готово!
Почему стандартные решения меня не устроили
1. Условное форматирование
Да, оно работает.
Но:
  • иногда обновляется нестабильно
  • может конфликтовать с уже существующими правилами
  • легко ломается при копировании диапазонов
  • добавляет лишнюю «слойность» в файл
Если таблица сложная, с большим количеством правил, это не всегда комфортный инструмент.

2. Макросы с простой заливкой
Многие макросы делают так:
– при клике заливают строку и столбец
– при следующем клике заливают новые
Проблема в том, что при этом уничтожается родная заливка ячеек.
Если у вас:
– цветовое кодирование
– зоны ввода
– расчётные области и т.д.
то после работы такого макроса структура файла нарушается.
Для меня это критично.

3. Имитация выделения через Selection
Есть ещё подход, когда строка и столбец не заливаются цветом, а «выделяются» через Selection.
Минусы:
– можно случайно скопировать или удалить лишние данные
– можно нечаянно перезаписать выделенные ячейки
– визуально это выглядит странновато
– (!!!) нарушается привычная логика работы
Итог: чем дольше работаешь в Excel, тем больше от него хочется. Это факт 🙂

Надеюсь, у меня получилось сделать нечто действительно корректное и полезное! Пользуйтесь и долгой и крепкой вам дружбы с Excel! ❤️