Выделите элементы в списке со списком после использования, чтобы пользователи не могли их выбрать - PullRequest
1 голос
/ 05 апреля 2020

У меня есть проект, над которым я работаю для развертывания оборудования в новых местах. У меня есть комбинированное окно пользовательской формы со списком IP-адресов, которые будут назначены определенным элементам оборудования (например, машинам с кредитными картами). Я пытаюсь найти способ, когда один из IP-адресов будет выбран для использования, чтобы элемент в списке выпадающих списков был либо удален, либо выделен серым цветом, и пользователь не мог повторно его использовать. Но если по какой-то причине IP-адрес снова становится доступным, этот элемент теперь доступен для использования в списке. Аппаратное обеспечение, IP и другая информация будут добавлены в таблицу / базу данных в Excel. Поэтому я предполагаю, что мне нужно проверить этот список IP по этой таблице / базе данных. Но я заблудился относительно того, как я могу выполнить проверку. Я пробовал проверять данные, но я хотел бы это сделать в VBA на основе комбинированного списка. enter image description here

А вот текущий код, предоставляющий поле со списком IP-адресов. Вы можете ввести один IP или диапазон.

Private Sub Submit_Data_Click()
 Dim wb As Workbook, ws As Worksheet, rngTarget As Range
    Dim s1 As String, ip1 As Variant
    Dim s2 As String, ip2 As Variant
    Dim i As Integer, n As Integer

    Set wb = ThisWorkbook
    Set ws = wb.Sheets("Arrays")
    Set rngTarget = ws.Range("I" & Rows.Count).End(xlUp)

    If Me.Add_single_IP = True Then
        s1 = Me.sgle_IP_add_tb1
        s2 = s1
    Else
        s1 = Me.rge_IP_start_tb2
        s2 = Me.Rge_IP_End_tb2
    End If

    ' split string into bytes
    ip1 = Split(s1, ".")
    ip2 = Split(s2, ".")

    ' validate
    Dim msg As String
    If UBound(ip1) <> 3 Or UBound(ip2) <> 3 Then
        msg = "IP must be n.n.n.n"
    ElseIf ip1(3) > 255 Or ip2(3) > 255 Then
        msg = "Host must be 1 to 255"
    ElseIf ip1(3) > ip2(3) Then
        msg = s1 & " is greater then " & s2
    ElseIf ip1(0) <> ip2(0) Or ip1(1) <> ip2(1) Or ip1(2) <> ip2(2) Then
        msg = "Different networks"
    End If

    ' failed validation
    If Len(msg) > 0 Then
        MsgBox msg, vbCritical, s1 & "-" & s2
        Exit Sub
    End If

    ' calc range and write to sheet
    n = ip2(3) - ip1(3) + 1
    For i = 1 To n
       Set rngTarget = rngTarget.Offset(1, 0) ' move down
       rngTarget = Join(ip1, ".")
       ip1(3) = ip1(3) + 1
    Next
    MsgBox n & " addresses added ", vbInformation, s1 & "-" & s2
End Sub

enter image description here Как я уже говорил ранее ... Если я могу удалить IP из выбора, так как они назначены так то, что у нас нет дубликатов, а затем есть возможность сделать их доступными снова, если аппаратная часть больше не используется, это здорово. Если это проще, тогда разрешить ему все еще быть видимым, но серым в списке, и, конечно, НЕ позволять его выбирать, и добавление пользователю ошибки MsgBox о том, что IP-адрес уже используется, также будет работать хорошо.

Спасибо за любую помощь.

Ответы [ 2 ]

1 голос
/ 07 апреля 2020

Я бы вводил все IP-адреса в отдельный вспомогательный диапазон с 2 столбцами. Первый столбец будет иметь IP-адрес, а второй столбец будет иметь значение Да или Нет . Я бы использовал комбинацию INDEX и MATCH для динамического заполнения 2-го столбца (объяснено ниже).

Затем я бы заполнил combobox новым столбцом, заполненным IP-адресом , но только IP-адреса, заполненные в combobox, - это адреса с Нет в столбце рядом с ним, поскольку они не «используются».


  Example of the Helper columns:            Example of your Array sheet columns:
         A            B                            H                 I
   +------------+------------+               +--------------+-----------------+ 
 1 | IP Address |   In Use?  |             1 | Brand/Model  |  CC Machine IP  |
 2 |  10.0.0.1  |     Yes    |             2 |  Model ABC   |     10.0.0.1    |
 3 |  10.0.0.2  |     Yes    |             3 |  Brand 123   |     10.0.0.4    |
 4 |  10.0.0.3  |     No     |             4 |              |                 |
 5 |  10.0.0.4  |     Yes    |             5 |  Brand 456   |     10.0.0.2    |
 6 |  10.0.0.5  |     No     |             6 |              |                 |
   +------------+------------+               +--------------+-----------------+

Это заполнит combobox значениями; 10.0.0.3 и 10.0.0.5 в таком порядке без пробелов между ними.


Но как именно мы этого достигаем?

Предположим, я установил вспомогательные столбцы на новом листе с именем "HelperSheet" с 'IP-адресами' в Column A и «Используется?» Да / Нет в Column B, а IP-адреса из введенной вами пользовательской формы вводятся в лист "Arrays". Вы можете внести необходимые изменения в эти значения в своем собственном коде.

Сначала введите все IP-адреса, которые вы хотите использовать, в Column A. Порядок, в котором вы их вводите, будет определять порядок, в котором они будут заполняться в combobox.

Чтобы упростить его, вы можете ввести первый IP-адрес, а затем заполнить остальные. Вы можете заполнить значения / формулы, щелкнув в правом нижнем углу ячейки и перетащив вниз по листу.

Далее нам нужно ввести формулу INDEX / MATCH в Column B в Первая строка IP-адрес был введен. Если ваш первый IP-адрес находится в ячейке A2, первая формула должна быть рядом с ним в ячейке B2.

= IFERROR (IF (INDEX (Arrays! $ I $ 1: $ I $ 255, MATCH (A1, массивы! $ I $ 1: $ I $ 255,0)) = A1, «Да»), «Нет»)

Если вы хотите узнать больше об этих Функции листов, о которых вы можете прочитать на Страница поддержки Microsoft Office :

Затем заполните формулу вниз по столбцу до последней строки IP-адреса , Вы можете заполнить значения / формулы, щелкнув в правом нижнем углу ячейки и перетащив вниз по листу.

Теперь каждая ячейка в Column B, у которой есть IP-адрес рядом с in in У Column A должна быть указанная выше формула. Единственным отличием будет ссылка на A1 в функции MATCH, так как это не абсолютная ссылка (которая будет выглядеть как $A$1 ) - поскольку это относительная ссылка, она будет увеличивать число для каждой строки.

Когда вы начнете заполнять Column I на листе "Arrays", значения в Column B on "HelperSheet" начнет меняться на Да , если они соответствуют соответствующему значению в Column A. Естественно, что при удалении IP-адреса с Column I на "Arrays" значение в Column B на "HelperSheet" изменится на NO . Любой введенный IP-адрес, который не совпадает с адресом на "HelperSheet", будет игнорироваться.


Теперь для заполнения Combobox

В VBE, щелкните по листу Arrays из списка внизу слева и измените раскрывающиеся списки на «Рабочий лист» и «Изменить». Этот код будет выполняться каждый раз, когда вносятся изменения в лист "Arrays" .

Snip of VBE showing Sheet1(Arrays) selected and the appropriate drop down selections being made.

Вот пример кода (комментарии были добавлены справа, чтобы помочь объяснить каждую строку по мере необходимости).

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

Private Sub Worksheet_Change(ByVal Target As Range)                'Target is the cell/cells that a change has been made on to make the code run.

Dim IPRangeItem As Long
Dim myArray As Variant
Dim IPRange As Range
Dim LastRow As Long
Dim ArrayCounter As Long

If Target.Column = 9 Then                                                         'This will only run the code below if the column the cells was changed in is I (the 9th column) otherwise it will exit the subroutine.

    LastRow = ThisWorkbook.Sheets("HelperSheet").Cells(Rows.Count, 1).End(xlUp).Row    'Finding the last row on our helper sheet where the IP addresses are entered. 
    Set IPRange = ThisWorkbook.Sheets("HelperSheet").Range("A1:B" & LastRow)
    myArray = IPRange                                                             'This line puts the range defined above straight into an Array.

        UserForm2.ComboBox1.Clear                                              'Ensures the combobox is always empty before values are assigned. 
        ArrayCounter = 1
        For IPRangeItem = 1 To UBound(myArray)
            If myArray(ArrayCounter, 2) = "No" Then                           'Looking to see if the value in Column B was "No" (remember we put the entire helper range into an array which is faster and easier to use)
                UserForm2.ComboBox1.AddItem myArray(ArrayCounter, 1)                'If it was a "Yes" the IP address value is added to the Combobox list otherwise as below nothing happens.
            Else
                'Do nothing
            End If
            ArrayCounter = ArrayCounter + 1
        Next IPRangeItem
Else
    'Do nothing
End If
End Sub

Теперь при каждом изменении значения Column I на вашем листе "Arrays" в поле со списком будут повторно вводиться все адреса , которые не используются , принимая во внимание внесенные изменения.

ПРИМЕЧАНИЕ: Формула, введенная в Column B для "HelperSheet", оценивает только до строки 255, если вам нужно расширить это, вам нужно обновить диапазоны в INDEX и MATCH разделы соответственно.

ПРИМЕЧАНИЕ: Поскольку этот код запускается каждый раз ЛЮБОЕ изменение вносится на листе "Arrays", это может привести к снижению производительности при большом количестве изменений часто вносится в ваш лист - этот код не запускается при обновлении / изменении любых других листов.

Вот пример обоих диапазонов и поля со списком:

Таблица массивов:

Example of the data entered into the Arrays sheet.

Таблица вспомогательных данных:

Example of data entered into the HelperSheet sheet

Список ComboBox:

Example of the populated combobox list based on the data entered into the sheets.

Обратите внимание, что в комбинированном списке отсутствуют адреса, которые вы ввели в лист "Arrays" как они «используются» на основе значений "HelperSheet".

1 голос
/ 06 апреля 2020

Удалите столбец I из RowSource поля со списком и добавьте нужные элементы при инициализации формы.

Private Sub UserForm_Initialize()

    Dim ws As Worksheet, iLastRow As Long, i As Long
    Set ws = ThisWorkbook.Sheets("Arrays")
    Me.ComboBox1.Clear
    iLastRow = ws.Cells(Rows.Count, "I").End(xlUp).Row
    For i = 3 To iLastRow
        If Len(ws.Cells(i, "H")) = 0 Then ' not assigned
            Me.ComboBox1.AddItem ws.Cells(i, "I")
        End If
    Next

End Sub
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...