VBA: форматировать ячейку при ошибке #VALUE - PullRequest
1 голос
/ 15 декабря 2011

Я создал функцию, которая ищет определенное значение в диапазоне и возвращает соседние характеристики.

Function Busca(valor As String)
    Dim bus(0 To 1)
    bus(0) = Worksheets("Sheet2").Range("A1:A10").Find(valor, LookAt:=xlWhole). _
        Offset(0, 1)
    bus(1) = Worksheets("Sheet2").Range("A1:A10").Find(valor, LookAt:=xlWhole). _
        Offset(0, 2)
    Busca = bus
End Function

Если в A1:A10 нет совпадения для valor, функция возвращает {#VALUE,#VALUE}, что нормально, но я бы хотел вместо этого вернуть что-то вроде {"No match", ""} с ячейкой «Нет совпадения» данный цвет. Я пробовал проверку данных, обработку ошибок и If Then с ActiveCell.Interior.ColorIndex безрезультатно. Кроме того, если ошибка будет исправлена, я бы хотел, чтобы ячейка снова стала прозрачной.

Я думаю, что обработчик событий мог бы добиться цели, но я новичок в VBA, и есть еще много вещей, которые я не понимаю.

EDIT

Как предлагается, пояснить:

Как заставить выходные ячейки изменить цвет, если совпадение не найдено, и не иметь цвета, если совпадение найдено (в VBA)?

Ответы [ 2 ]

3 голосов
/ 15 декабря 2011

Это полностью переписанный ответ в свете новой информации от спрашивающего.

Если я правильно понимаю, вы хотите создать пользовательскую функцию, которая изменит цвет ячейки.В следующем тексте справки Microsoft по пользовательским функциям сказано, что вы не можете:

Количество ключевых слов VBA, которые вы можете использовать в пользовательских функциях, меньше, чем число, которое вы можете использовать в макросах.Пользовательским функциям не разрешается делать что-либо кроме возврата значения в формулу на рабочем листе или в выражение, используемое в другом макросе или функции VBA.Например, пользовательские функции не могут изменять размеры окон, редактировать формулу в ячейке или изменять параметры шрифта, цвета или рисунка для текста в ячейке.Если вы включите код «действия» такого рода в процедуру функции, функция вернет значение #VALUE!ошибка.

Я знаю две альтернативы, которые могут удовлетворить ваши требования.Третий вариант был добавлен позже после вспышки вдохновения.

Альтернатива 1: предложить раскрывающийся список разрешенных значений

Поместить курсор на ячейку, которая являетсяиметь ограниченные значения.Выберите Данные на панели инструментов, затем Проверка.Появится форма проверки данных.

Выберите вкладку Настройки, если она еще не выбрана.Нажмите на поле под «Разрешить:» и выберите Список.В поле «Источник» введите: «= $ A $ 1: $ A $ 10».(Требуется "=". $ S важны, если вы хотите иметь возможность создавать копии этой ячейки.) Нажмите OK.

Когда пользователь помещает курсор в эту ячейку, он может либо ввестиразрешенное значение или можете выбрать допустимое значение из списка.Попытка ввести любое другое значение приведет к сообщению об ошибке.Другие вкладки в форме проверки данных позволяют вводить справочное сообщение и собственное сообщение об ошибке.

Из-за значения $ s в поле источника вы можете скопировать исходную ячейку и ее проверку в другие ячейки.

Альтернатива 2: условное форматирование

Если допустимые значения являются диапазоном, условное форматирование будет соответствовать вашим требованиям.Например, допустимый диапазон от 10 до 20.

Выберите «Формат» на панели инструментов, затем «Условное форматирование».

Отображаются поля для условия 1.«Между» уже отображается.В полях справа введите 10 и 20.

Нажмите «Добавить», чтобы отобразить поля для условия 2. Замените «между» на «Меньше». В следующем поле введите 10. Нажмите «Формат». Нажмите «Цвет». Выберите «Красный»Нажмите кнопку ОК.

Нажмите кнопку Добавить, чтобы отобразить поля для условия 3. Заменить «на» на «Больше чем».В следующем поле введите 20. Нажмите Формат.Нажмите Цвет.Выберите Красный.Нажмите OK.

Нажмите OK, чтобы принять условное форматирование.

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

Вы можете создать столько копий отформатированной ячейки, сколько пожелаете.

Событие изменения рабочего листа

Я должен был подумать о событиях раньше.Я считаю, что это именно то, что вы хотите.

В редакторе VBA, Project Explorer обычно виден в левой части экрана.Если это не так, нажмите Ctrl+R.

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

Область кода будет озаглавлена ​​«Рабочий лист», но в противном случае она будет пустой.В этой области можно размещать различные подпрограммы, но соответствующие подпрограммы являются подпрограммами событий рабочего листа.Это процедуры, которые будут вызываться всякий раз, когда происходит событие, такое как активированная или деактивированная таблица.Требуемое событие - Change, которое вызывается каждый раз, когда пользователь меняет ячейку.Привлекательность этой подпрограммы в том, что она может делать все что угодно.

Скопируйте и вставьте нижеприведенную подпрограмму Worksheet_Change в область кода рабочего листа.

Ее параметр - это адрес ячейки, которую пользовательизменилось.

TgtRngList установлен в список диапазонов, которые вы хотите патрулировать.Я установил это на C1: C1000, F1: F1000 и A1.Вам придется изменить это на диапазоны, которые вы хотите патрулировать.

OKValueList установлен в список разрешенных значений для патрулируемых диапазонов.Они могут быть где-то на листе, но я думаю, что их легче определить здесь.Измените список на что хотите.

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

Option Explicit
Sub Worksheet_Change(ByVal ChangedCell As Range)

  ' This routine is called whenever the user changes a cell.
  ' It is not called if a cell is changed by Calculate

  Dim ColChanged As Integer
  Dim InxOV As Integer
  Dim InxTR As Integer
  Dim OKValueList() As Variant
  Dim Patrolled As Boolean
  Dim RowChanged As Integer
  Dim TgtColLeft As Integer
  Dim TgtColRight As Integer
  Dim TgtRngPartList() As String
  Dim TgtRngList() As Variant
  Dim TgtRngPart As String
  Dim TgtRowBottom As Integer
  Dim TgtRowTop As Integer
  Dim ValueChanged As String
  Dim ValueOK As Boolean

  ' Fill TgtRngList withe ranges that are to be patrolled by this routine
  TgtRngList = Array("C1:C1000", "F1:F1000", "A1")

  ' Fill OKValueList with the permitted values for these cells.
  OKValueList = Array("V1", "V2", "V3", "V4", "V5", _
                      "V6", "V7", "V8", "V9", "V10")

  ColChanged = ChangedCell.Column
  RowChanged = ChangedCell.Row

  Patrolled = False
  For InxTR = LBound(TgtRngList) To UBound(TgtRngList)
    TgtRngPartList = Split(TgtRngList(InxTR), ":")
    ' Decode top left of range
    TgtRngPart = TgtRngPartList(LBound(TgtRngPartList))
    TgtRowTop = Range(TgtRngPart).Row
    TgtColLeft = Range(TgtRngPart).Column
    If LBound(TgtRngPartList) = UBound(TgtRngPartList) Then
      ' There is no colon so single cell range
      TgtRowBottom = TgtRowTop
      TgtColRight = TgtColLeft
    Else
      TgtRngPart = TgtRngPartList(UBound(TgtRngPartList))
      TgtRowBottom = Range(TgtRngPart).Row
      TgtColRight = Range(TgtRngPart).Column
    End If
    If RowChanged >= TgtRowTop And RowChanged <= TgtRowBottom And _
       ColChanged >= TgtColLeft And ColChanged <= TgtColRight Then
      ' This is a patrolled cell
      Patrolled = True
      Exit For
    End If
  Next
  If Patrolled Then
    With ActiveSheet
      ValueChanged = .Cells(RowChanged, ColChanged).Value
      ' Check value against permitted list
      ValueOK = False
      For InxOV = LBound(OKValueList) To UBound(OKValueList)
        If ValueChanged = OKValueList(InxOV) Then
          ValueOK = True
          Exit For
        End If
      Next
      If ValueOK Then
        ' Set cell black
        .Cells(RowChanged, ColChanged).Font.Color = RGB(0, 0, 0)
      Else
        ' Set cell red
        .Cells(RowChanged, ColChanged).Font.Color = RGB(255, 0, 0)
      End If
    End With
  End If

End Sub

Надеюсь, это поможет.

0 голосов
/ 15 декабря 2011

Я не уверен, куда вы идете со смещением, добавленным к xlWhole, который указывает, следует ли проверять всю ячейку. Вот некоторые заметки, вы увидите, что find возвращает объект:

Function Busca(valor As String)
''http://msdn.microsoft.com/en-us/library/aa195730(v=office.11).aspx
Dim bus(0 To 1)
With Worksheets("Sheet2").Range("A1:A10")
    Set c = .Find(valor, LookAt:=xlWhole)
    If Not c Is Nothing Then
        bus(0) = c.Address

        Set c = .FindNext(c)
        If Not c Is Nothing Then
            bus(1) = c.Address
        Else
            bus(1) = "None"
        End If
    Else
        bus(0) = "None"
    End If
End With
Debug.Print bus(0), bus(1)
Busca = bus
End Function
...