以下是我的excel的代码
虽然通过宏创建多个依赖项,但我在
上遇到错误.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:=xlBetween, Formula1:="=indirect("A" & i)"
仍然试图弄清楚如何将范围值传递到公式部分
Sub listing()
Dim cellv As Range
For i = 3 To 10000
Set cella = Sheet1.Range("A" & i)
With cella.Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:=xlBetween, Formula1:="=Main"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = "Invalid Input"
.InputMessage = ""
.ErrorMessage = "Select the location only from the dropdown list."
.ShowInput = False
.ShowError = True
End With
Set cellb = Sheet1.Range("B" & i)
With cellb.Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:=xlBetween, Formula1:="=indirect("A" & i)"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = "Invalid Input"
.InputMessage = ""
.ErrorMessage = "Select the location only from the dropdown list."
.ShowInput = False
.ShowError = True
End With
Next
End Sub
答案 0 :(得分:0)
如果我的理解是正确的,你有以下几点:
Main
的定义名称,其中包含已定义名称或范围列表这是您想要实现的目标:
A
的列Main
中的数据验证,以便用户从其包含的已定义名称中进行选择。B
中的数据验证,指向在A
列中相邻单元格中选择的已定义名称现在,您在评论的回答中提到1000 cells
,但您的代码已For i = 3 To 10000
然而,想到的问题很少:
此工作簿是否可以同时使用1000个定义的名称?
您的用户是否会手动从其他1000个已定义名称中选择1000个项目?
这个清单的用途是什么?
还要记住(正如@JoeMalpass今天提醒我的那样)
使用
INDIRECT
非常适合小型数据集,它可以使事情成为现实 在较大的床单上有点迟钝,因为它是一个易变的功能 需要在工作簿中的任何更改时重新计算(甚至 对使用或者没有影响的单元格所做的更改 由间接函数引用。)
在您的情况下,您计划在至少1000个单元格中使用INDIRECT
函数。我不是在试图挑战你的解决方案,但是我想,既然你正在使用VBA,那么应该有其他更实用的方法来满足你的需求。 在这方面,我将以分开的答案为您提供VBA解决方案。
基于以上内容,让我们继续您的代码。您的代码有两个错误:
在B列的数据验证的“Formula1”中,INDIRECT
公式的串联需要是数据类型Variant,因此将其更改为:
Formula1:="=INDIRECT(" & CVar("A" & i) & ")"
第二个错误是尝试手动创建此数据验证时触发的同一错误:
Source目前正在评估错误。
图。 1
这基本上意味着数据验证指向名为“”
(空白)的不存在的定义名称。
手动执行此操作后,您可以选择继续并创建数据验证,并在用户使用有效的定义名称更新“源”单元格后最终符合所需目的。但是,VB中的此错误不允许创建数据验证。
可以通过为列A
中的每个源单元格临时分配一个已知名称(即Main
)来修复此问题,并在创建列B
中的数据验证后将其清除
以下是修订后的代码
还添加了过程Process_IniEnd
以使代码运行得更快
Option Explicit
Sub DataValidation_Indirect()
Const kRow As Integer = 1000
Dim CllA As Range, CllB As Range
Dim i As Integer
Process_IniEnd 1
Rem Clear Target Cells in Columns A & B
ThisWorkbook.Sheets(1).Range(Cells(3, 1), Cells(kRow, 2)).Clear 'Replace [ThisWorkbook.Sheets(1)] as required
For i = 3 To kRow
Rem Set Cell A in Columns A
Set CllA = ThisWorkbook.Sheets(1).Range("A" & i) 'Replace [ThisWorkbook.Sheets(1)] as required
Rem Set Validation in Cell A
With CllA.Validation
.Delete
.Add Type:=xlValidateList, _
AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, _
Formula1:="=Main"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = "Invalid Input"
.InputMessage = ""
.ErrorMessage = "Select the location only from the dropdown list."
.ShowInput = False
.ShowError = True
End With
Rem Enter Temporary Name in Cell A
CllA.Value = "Main"
Rem Set Cell B in Columns B
Set CllB = ThisWorkbook.Sheets(1).Range("B" & i) 'Replace [ThisWorkbook.Sheets(1)] as required
Rem Set Validation in Cell B
With CllB.Validation
.Delete
.Add Type:=xlValidateList, _
AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, _
Formula1:="=INDIRECT(" & CVar("A" & i) & ")"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = "Invalid Input"
.InputMessage = ""
.ErrorMessage = "Select the location only from the dropdown list."
.ShowInput = False
.ShowError = True
End With
Rem Clear Temporary Name in Cell A
CllA.ClearContents
Next
Process_IniEnd 0
End Sub
Sub Process_IniEnd(blIni As Boolean)
Select Case blIni
Case True
With Application
.Calculation = xlManual
.EnableEvents = False
.DisplayAlerts = False
.ScreenUpdating = False
End With
Case False
With Application
.EnableEvents = True
.DisplayAlerts = True
.ScreenUpdating = True
.Calculation = xlAutomatic
End With
End Select
End Sub
答案 1 :(得分:0)
如果我的理解是正确的,你有以下几点:
Main
的已定义名称,其中包含已定义名称或范围列表这是您想要实现的目标:
A
”的列Main
中的数据验证,以便用户从其包含的已定义名称中进行选择B
中的数据验证,指向在A
列中相邻单元格中选择的已定义名称基于上述情况,我建议当用户在Worksheet_Change
列
B
事件在列A
中创建数据验证
此解决方案需要:
A
B
事件传递的更改验证范围,在列Worksheet_Change
中创建数据验证的过程将以下代码粘贴到工作表的VB代码中。 (要激活工作表的VB代码,请右键单击工作表的选项卡,然后选择“查看代码”,参见图1)
Option Explicit
Private Sub Worksheet_Change(ByVal RngSrc As Range)
WshEvn_DataValidation RngSrc
End Sub
然后将以下代码粘贴到同一工作簿中的VB模块
中Option Explicit
Const kRow As Integer = 1000
Sub DataValidation_Main()
Dim CllA As Range
Dim i As Integer
Debug.Print "Ini: "; Now
Process_IniEnd 1
Rem Clear Target Cells in Columns A & B
ThisWorkbook.Sheets(1).Range(Cells(3, 1), Cells(kRow, 2)).Clear 'Replace [ThisWorkbook.Sheets(1)] as required
For i = 3 To kRow
Rem Set Cell A in Columns A
Set CllA = ThisWorkbook.Sheets(1).Range("A" & i) 'Replace [ThisWorkbook.Sheets(1)] as required
Rem Set Validation in Cell A
With CllA.Validation
.Delete
.Add Type:=xlValidateList, _
AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, _
Formula1:="=Main"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = "Invalid Input"
.InputMessage = ""
.ErrorMessage = "Select the location only from the dropdown list."
.ShowInput = False
.ShowError = True
End With
Next
Process_IniEnd 0
Debug.Print "End: "; Now
End Sub
Sub WshEvn_DataValidation(ByVal RngSrc As Range)
Dim RngTrg As Range
Dim rCll As Range
Debug.Print "Ini: "; Now
Process_IniEnd 1
Rem Validate Source Range & Set Target Range
Set RngTrg = Application.Intersect(RngSrc, RngSrc.Worksheet.Range(Cells(3, 1), Cells(kRow, 1)))
If Not (RngTrg Is Nothing) Then
For Each rCll In RngTrg.Cells
Rem Set Validation in Column B
With rCll.Offset(0, 1).Validation
.Delete
On Error Resume Next
.Add Type:=xlValidateList, _
AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, _
Formula1:="=" & rCll.Value2
If Err.Number <> 0 Then GoTo NEXT_Cll
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = "Invalid Input"
.InputMessage = ""
.ErrorMessage = "Select the location only from the dropdown list."
.ShowInput = False
.ShowError = True
End With
NEXT_Cll:
Next: End If
Process_IniEnd 0
Debug.Print "End: "; Now
End Sub
Sub Process_IniEnd(blIni As Boolean)
Select Case blIni
Case True
With Application
.Calculation = xlManual
.EnableEvents = False
.DisplayAlerts = False
.ScreenUpdating = False
End With
Case False
With Application
.EnableEvents = True
.DisplayAlerts = True
.ScreenUpdating = True
.Calculation = xlAutomatic
End With
End Select
End Sub