【问题标题】:Dynamically generate array of Years for data validation list Excel VBA为数据验证列表Excel VBA动态生成年份数组
【发布时间】:2020-02-28 02:04:39
【问题描述】:

我正在向表格中的单元格添加数据验证下拉列表,并希望使用从 Today()+110 years back 的年份数组动态填充它。例如 2020,2019,2018,2017,2016,2015,2014,2013,2012,2011,2010。我尝试使用Evaluate 的简写,即[],但由于某些原因,我收到了错误 2015。

    With .ListColumns("Select Year").DataBodyRange
        With .Cells(1).Validation
            .Delete
            '.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:=xlBetween, Formula1:="<Year>,2020, 2019,2018,2017,2016,2015,2014,2013,2012,2011,2010"
            .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:=xlBetween, Formula1:=[Transpose(Text(date( (year(today())+1) + row(1:10), 1, 1), "yyyy"))]
            .IgnoreBlank = True
            .InCellDropdown = True
            .InputTitle = ""
            .ErrorTitle = ""
            .InputMessage = ""
            .ErrorMessage = ""
            .ShowInput = True
            .ShowError = True
        End With
        .Cells(1).Value2 = "<Year>"
    End With

公式为:

Formula1:=[Transpose(Text(date( (year(today())+1) + row(1:10), 1, 1), "yyyy"))]

为什么突然不工作了?是否有另一种快速生成年份的方法?

这是我在下面添加的屏幕截图。在我运行以下代码之前,它一直在工作:

Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
If Target.Name = "Instructions" Then
    ThisWorkbook.Sheets("Instructions").Visible = True
    Target.Follow ' here is where error occurred and evaluate stopped working!
End If
End Sub

【问题讨论】:

  • 方括号表达式写在哪里(在哪个模块中)?如果它在工作表的代码隐藏中,我怀疑它在工作表的上下文中工作(即Worksheet.Evaluate) - 否则,它在ActiveSheet 的上下文中工作(即Application.Evaluate)。您可能希望通过将方括号表达式替换为显式传递给适当的Evaluate 方法的字符串来明确上下文。
  • 我正在Module 中测试它。尝试了Application.Evaluate 并传递了一个字符串,但仍然得到Error 2015。见这里:arr = Application.Evaluate("Transpose(Text(date( (year(today())+2) - row(1:10), 1, 1), ""yyyy""))")

标签: excel vba date validation evaluate


【解决方案1】:
  1. 你的数学不正确:
[Transpose(Text(date( (year(today())+2) - row(1:10), 1, 1), "yyyy"))]
  1. 当使用xlValidateList 时,它需要一个逗号分隔的列表而不是一个数组。所以创建和数组变量并使用 Join:
    Dim arr As Variant
    arr = [Transpose(Text(date( (year(today())+2) - row(1:10), 1, 1), "yyyy"))]


     With .ListColumns("Select Year").DataBodyRange
        With .Cells(1).Validation
            .Delete
            '.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:=xlBetween, Formula1:="<Year>,2020, 2019,2018,2017,2016,2015,2014,2013,2012,2011,2010"
            .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:=xlBetween, Formula1:=Join(arr, ",")
            .IgnoreBlank = True
            .InCellDropdown = True
            .InputTitle = ""
            .ErrorTitle = ""
            .InputMessage = ""
            .ErrorMessage = ""
            .ShowInput = True
            .ShowError = True
        End With
        .Cells(1).Value2 = "<Year>"
    End With

为什么不用一个简单的循环而不是用公式填充数组:

Dim arr(1 To 10) As Long

Dim i As Long
For i = 1 To 10
    arr(i) = Year(Date) + 2 - i
Next i

【讨论】:

  • 注意:列表有它可以接受的最大字符数;考虑改为定义一个工作簿范围的Name(方括号表达式已经被Excel的计算引擎评估),这样验证列表就可以是=TheDefinedName
  • @scott Craner, @mathieu Guindon 我不得不编辑我的帖子以更好地解释它,这样你就可以收集实际发生的事情并告诉我为什么 evaluate 停止工作。
  • @ScottCraner 在.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:=xlBetween, Formula1:=Join(Arr, ",") 上获得Invalid procedure call or argument
  • @sifar 它对我有用,没有问题。所以不确定。
  • @ScottCraner 我在 Workbook_Open 中声明了 Arr,所以它给出了那个错误。当我在模块中将其声明为Public Arr 时,它能够毫无问题地添加数据验证。非常感谢! :-)
【解决方案2】:

使用方括号表达式定义工作簿范围的命名范围:

现在您的数据验证公式可以简单地为=Years

经验法则,避免在 VBA 代码中使用方括号表达式。它适用于即时窗格中的一次性代码和调试器指令,不适用于生产代码。

【讨论】:

  • 如何使用 vba 添加上述命名范围?
  • @sifar ThisWorkbook.Names.Add "Years", "=TRANSPOSE(TEXT(DATE((YEAR(TODAY())+1) + ROW(1:10), 1, 1), ""yyyy""))"
  • FWIW 我已经验证这可行 - ?TypeName([Years]) prints Variant()
猜你喜欢
  • 2021-06-05
  • 2018-12-15
  • 2018-03-03
  • 2021-02-24
  • 2013-07-10
  • 1970-01-01
  • 2012-11-29
  • 2013-11-12
  • 1970-01-01
相关资源
最近更新 更多