Обновление динамического выпадающего списка в excel при изменении значения ячейки

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

Вот форма, которую увидит пользователь:

введите здесь описание изображения

В настоящее время обе колонки F и H основаны на формуле проверки данных:

INDIRECT("VList!"&SUBSTITUTE(ADDRESS(1,MATCH($B11,VList!$1:$1,0),1),"1","")&"2:"&SUBSTITUTE(ADDRESS(1,MATCH($B11,VList!$1:$1,0),1),"1","")&COUNTA(INDIRECT("VList!"&ADDRESS(1,MATCH($B11,VList!$1:$1,0),4)&":"&ADDRESS(100,MATCH($B11,VList!$1:$1),4))))

... где VList относится к листу, как показано ниже:

введите здесь описание изображения

Итак, мой вопрос здесь в том, что, основываясь на имени проекта в столбце B, есть ли способ обновить список в листе VList со значением "Cost Per Unit" [Cell E11], чтобы раскрывающийся список в F12 и H12 автоматически обновлялся со значением "Cost Per Unit"?

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

Редактировать: Итак, мне сказали, что коды VBA могут запускаться автоматически при изменении значения ячейки, поэтому я также открыт для любых решений/помощи с VBA. Тем временем будем изучать это направление!

Edit2: ниже добавлена ​​простая иллюстрация, которая, надеюсь, лучше отображает то, чего я пытаюсь достичь в Excel: введите здесь описание изображения

*Edit3: я начинаю изучать метод Worksheet_SelectionChange, и вот что у меня получилось:

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Dim projectName As String
    Dim VariableList As Worksheet
    Dim Form As Worksheet

    Dim thisRow As Integer
    Dim correctColumn As Integer
    Dim lastRow As Integer

    Set VariableList = ThisWorkbook.Sheets("VList")
    Set Form = ThisWorkbook.Sheets("Form")

    On Error GoTo EndingSub

    If Target.Column = 5 Then
        thisRow = Target.Row
        projectName = Form.Cells(thisRow, 2)

        correctColumn = Application.Match(projectName, VariableList.Range("1:1"), 0)

        lastRow = VariableList.Columns(correctColumn).Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row

        VariableList.Cells(lastRow + 1, correctColumn).value = Form.Cells(5, thisRow).value

    End If

EndingSub:

End Sub

Почему-то значение Form.Cells(5, thisRow).Value всегда пусто.

Если я изменю его на Target.Value, он по-прежнему будет принимать предыдущее значение, которое было введено (например, я сначала поместил «ABC» в качестве новой переменной, она не обновляется. Я изменил новую переменную на «DEF», она обновляет список с помощью « ABC" вместо "DEF"). Он также принимает ВСЕ значения, которые каким-то образом находятся в столбце E.

Кроме того, нажатие Enter после того, как я поместил один вход в E11, также приводит к обновлению обоих значений E11 и E12, когда было изменено только E12. Однако, если я щелкну мышью после ввода E11, обновится только значение E11.

Что именно я делаю неправильно здесь?


person lyk    schedule 15.04.2015    source источник
comment
Вы не можете обновить значение другой ячейки с помощью формулы, только ячейку, в которой содержится формула. Есть ли причина, по которой вы не хотите использовать VBA?   -  person SierraOscar    schedule 15.04.2015
comment
@SOofWXLS, не может использовать VBA, потому что на данный момент требуется обновить список сразу после того, как ячейка E11 получит входное значение. Я не думаю, что есть какой-либо способ вызвать код VBA из такого действия? Таким образом, поиск мнений здесь, если это вообще возможно   -  person lyk    schedule 15.04.2015
comment
На самом деле, это именно то, для чего можно использовать VBA... это называется событием изменения и очень часто используется для VBA.   -  person SierraOscar    schedule 15.04.2015
comment
@SOofWXLS о, так VBA позволяет автоматически запускать код при событиях (например, при изменении значения ячейки)? Хорошо, спасибо за подсказку, я тем временем попытаюсь исследовать это направление сейчас!   -  person lyk    schedule 15.04.2015
comment
Это может помочь вам начать: cpearson.com/excel/Events.aspx   -  person SierraOscar    schedule 15.04.2015
comment
@SOofWXLS, спасибо за ссылку! будем разбираться =)   -  person lyk    schedule 15.04.2015
comment
@lyk, можете ли вы добавить изображение ожидаемого поведения, которое вы ищете? расширенный пример подойдет. Благодарность   -  person Marcel    schedule 15.04.2015
comment
@AHC, привет, чего я пытаюсь добиться, так это того, что как только пользователь вводит стоимость за единицу в форме в разделе NewVariable (столбец E), это автоматически обновляется в листе VList в столбце A, который имеет Заголовок Project1. Стоимость за единицу будет обновлена ​​в списке в ячейке A6. Вам все еще требуется изображение для этого?   -  person lyk    schedule 16.04.2015
comment
@AHC добавил изображение, надеюсь, оно немного понятнее?   -  person lyk    schedule 16.04.2015
comment
Это намного яснее. Надеюсь, вы получите множество ответов, особенно если вы измените/добавите тег для Excel VBA.   -  person user3819867    schedule 22.04.2015
comment
@user3819867 user3819867 о да, спасибо за это! добавили, так как раньше я не думал, что это возможно с vba =)   -  person lyk    schedule 23.04.2015


Ответы (1)


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

Private Sub Worksheet_Change(ByVal Target As Range)
Dim NewVar As Range
On Error GoTo Err
Set NewVar = Range("C:C") 'data entered here, could be a referstorange kind of named range reference
If Application.WorksheetFunction.CountA(Intersect(Target, NewVar)) <> 0 Then Call ertdfgcvb(Target, NewVar) 'only run if there's an intersect, f*ed up but works anyway
Err:
End Sub

Sub ertdfgcvb(Target As Range, NewVar As Range)
Dim ws As Worksheet, Valid As Long, project As String, ListElmnt As String, Unlisted As Boolean, rng1 As Range, rng2 As Range

Set ws = Sheets("VList") 'the data that you refresh
Valid = 2 'projects in column B
HeaderRow = 1 'headers in Vlist are in row #1
uRow = Cells.Rows.Count 'f* yeah, compatibility considerations

For Each Cell In Intersect(Target, NewVar) 'will evaluate for each cell individually, in case you were to insert columns
    ListElmnt = Cell.Value2            'stores the prospective list element
    r = Cell.Row                       'stores the list element's row to...
    project = Cells(r, Valid).Value2   'identify the related project

    HeaderRowRef = HeaderRow & ":" & HeaderRow
    ColumnNum = ws.Range(HeaderRowRef).Find(What:=project, SearchDirection:=xlPrevious, SearchOrder:=xlByColumns, LookAt:=xlWhole).Column   'finds the project in VList
    'MsgBox ws.Name
    Set rng1 = ws.Cells(HeaderRow + 1, ColumnNum)
    Set rng2 = ws.Cells(uRow, ColumnNum)
    LastRow = ws.Range(ws.Cells(HeaderRow + 1, ColumnNum), ws.Cells(uRow, ColumnNum)).Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row 'finds the last row for the project in VList 'f*ed up but works
    Unlisted = True                                                                  'assumes it's unlisted
        For x = HeaderRow + 1 To LastRow
            If ListElmnt = CStr(ws.Cells(x, ColumnNum).Value2) Then Unlisted = False 'unless proven otherwise
        Next
    If Unlisted Then ws.Cells(LastRow + 1, ColumnNum) = ListElmnt                    'if it's unlisted it gets appended to the end of the list
Next
End Sub

РЕДАКТИРОВАТЬ:
Как очистить таблицу, например:

Sub ert()
Dim rng As Range

Set rng = Range("Táblázat1")         'obviously the table name
Do While x < rng.Rows.Count          'for each row
    If rng(x, 1).Value2 = "" Then    'if it's empty
        rng(x, 1).Delete Shift:=xlUp 'then delete but retaining the table format
    Else
        x = x + 1                    'else go to the next line (note: with deletion comes a shift up!)
    End If
Loop

End Sub
person user3819867    schedule 22.04.2015
comment
См. загруженный файл. - person user3819867; 22.04.2015
comment
Теперь, когда я думаю об этом, вы можете просто принять другие переменные (не в списке), а затем запустить ту же подпрограмму. В этом случае ваш текущий столбец станет устаревшим, поэтому ввод будет более удобным. - person user3819867; 22.04.2015
comment
omg, это блестящее решение, большое спасибо! Мне просто нужно еще немного отредактировать, чтобы заменить неправильные значения (например, пользователь набрал Testing, но обнаружил, что это опечатка, должно быть Testing1, и поэтому Testing1 должен заменить Testing. - person lyk; 23.04.2015
comment
и в любом случае, я не могу использовать таблицы, потому что VList также создается из кодов VBA и будет периодически очищаться и обновляться новыми данными... трудно объяснить, но да... - person lyk; 23.04.2015
comment
есть ли способ .Find использовать предыдущее значение ячейки в NewVariable и заменить его правильным? - person lyk; 23.04.2015
comment
Пробовал Target.Value в методе selectionChange, но до сих пор не работает - person lyk; 23.04.2015
comment
Целью может быть или не быть одна ячейка, я бы не рекомендовал использовать Target.Value. Предыдущая позиция VList может быть сохранена в глобальной переменной, заменяющей HeaderRow + 1, или рассчитана заново из предоставленного вами описания. Использовать глобальную переменную не рекомендуется, так как вам потребуется применить правило исключения при первом использовании (после открытия книги). Второй вариант не дает вам никаких преимуществ, требует больше вычислений. - person user3819867; 23.04.2015
comment
Удаление из таблицы можно сделать через Ctrl - или с помощью простых методов, таких как описанный в моей правке. - person user3819867; 23.04.2015
comment
аааа, понятно... к сожалению, я не могу использовать метод таблицы, так как не могу преобразовать данные в VList в формат таблицы по причинам, изложенным ранее... но тем временем я попытаюсь найти альтернативы, спасибо ! - person lyk; 23.04.2015