Vba MsgBox后出现类型不匹配错误

Vba MsgBox后出现类型不匹配错误,vba,excel,Vba,Excel,我的数据如下 更新的问题 当我运行上述宏时,我不知道为什么它在MsgBox coll(j)之后会出现类型不匹配错误,我只想将数据存储在数组中并传递数据,这里我对范围(“A1:A10”)中的每个r使用其中A10长度是静态的我如何才能找到上次写入的列?当您向集合中添加内容时,键需要是字符串,因此请使用: coll.Add r.Value, CStr(r.Value) 而不是: coll.Add r.Value, r.Value 您仍在将coll(j)分配给非数组的变量。 您需要: ReDim m

我的数据如下

更新的问题


当我运行上述宏时,我不知道为什么它在
MsgBox coll(j)
之后会出现
类型不匹配错误
,我只想将数据存储在数组中并传递数据,这里我对范围(“A1:A10”)中的每个r使用
其中
A10
长度是静态的我如何才能找到上次写入的列?

当您向集合中添加内容时,键需要是字符串,因此请使用:

coll.Add r.Value, CStr(r.Value)
而不是:

coll.Add r.Value, r.Value
您仍在将
coll(j)
分配给非数组的
变量。
您需要:

ReDim myArr(1 to coll.Count)
在for循环之前,然后在循环中:

myArr(j) = coll(j)

在回答这个问题之前,我想写下我相信你们正在努力实现的目标;当您确认这是您正在尝试做的事情时,我将尝试帮助您获得工作代码来实现它。这通常是通过注释来完成的,但是到目前为止注释的线程有点脱节,代码相当复杂

  • 您在工作表中有数据(称为“sheet1”-但可能是其他内容)
  • 第一列包含某些可能重复的值
  • 你不知道可能有多少列。。。你想知道吗
  • 您试图在列A中找到每个唯一的值(称之为“键值”),并在消息框中显示它(一次一个)。这看起来更像是调试步骤,而不是最终程序的实际功能
  • 然后打开A列上的自动过滤器;仅选择与特定值匹配的行
  • 使用与工作表名称相同的值,可以查看此类工作表是否存在:如果存在,则清除其内容;如果没有,则在工作簿末尾创建它(并为其指定键的名称)
  • 在sheet1的A列中选择所有具有相同(键)值的行,并将它们复制到名称等于筛选的A列中的值的工作表中
  • 您希望对A列中的每个唯一(键)值重复步骤5-8
  • 当所有这些都完成后,我相信您(至少)比A列中的键值多了一张表(您还有初始数据表);但是,您不会删除任何“多余”的工作表(使用其他名称)。每个工作表将只包含与工作表1当前内容相对应的数据行(任何早期数据都已删除)
  • 在操作过程中,打开和关闭自动过滤;您希望最终禁用自动筛选
  • 请确认这确实是您正在尝试的操作。如果您能对A列中的值的格式给出一个想法,那将是很有帮助的。我怀疑有些事情可以比你现在做的更有效率。最后,我想知道以这种方式组织数据的全部目的是否是以特定的方式组织数据,并可能进行进一步的计算/图形等。excel(VBA)中内置了各种函数为了使数据提取工作更容易,很少有人需要这种数据重新排列来完成特定的工作。如果你愿意对此发表评论

    下面的代码完成上述所有操作。请注意每个
    ,以及处理特定任务的函数/子例程(
    唯一
    创建或清除
    ,以及
    工作表列表
    )。这使得顶层代码更易于阅读和理解。还请注意,错误捕获仅限于检查工作表是否存在的一小部分,对我来说,它运行时没有问题;如果出现任何错误,请告诉我工作表中的内容,因为这可能会影响所发生的事情(例如,
    a
    列中的单元格包含工作表名称中不允许的字符,如
    /\!
    等。还要注意,您的代码正在删除“CurrentRegion”。根据您试图实现的目标,“UsedRange”也许更好

    Option Explicit
    
    Sub Solution()
      Dim shData As Worksheet
      Dim nameRange As Range
      Dim r As Range, c As Range, A1c As Range, s As String
      Dim uniqueNames As Variant, v As Variant
    
      Set shData = Sheets("Sheet1")  ' sheet with source data
      Set A1c = shData.[A1]          ' first cell of data range - referred to a lot...
      Set nameRange = Range(A1c, A1c.End(xlDown)) ' find all the contiguous cells in the range
    
      ' find the unique values: using custom function
      ' omit second parameter to suppress dialog
      uniqueNames = unique(nameRange, True)
    
      Application.ScreenUpdating = False ' no need for flashing screen...
    
      ' check if sheet with each name exists, or create it:
      createOrClear uniqueNames
    
      ' filter on each value in turn, and copy to corresponding sheet:
      For Each v In uniqueNames
        A1c.AutoFilter Field:=1, Criteria1:=v, _
          Operator:=xlAnd
        A1c.CurrentRegion.Copy Sheets(v).[A1]
      Next v
    
      ' turn auto filter off
      A1c.AutoFilter
    
      ' and screen updating on
      Application.ScreenUpdating = True
    
    End Sub
    
    Function unique(r As Range, Optional show)
      ' return a variant array containing unique values in range
      ' optionally present dialog with values found
      ' inspired by http://stackoverflow.com/questions/3017852/vba-get-unique-values-from-array
      Dim d As Object
      Dim c As Range
      Dim s As String
      Dim v As Variant
    
      If IsMissing(show) Then show = False
    
      Set d = CreateObject("Scripting.Dictionary")
    
      ' dictionary object will create unique keys
      ' have to make it case-insensitive
      ' as sheet names and autofilter are case insensitive
      For Each c In r
        d(LCase("" & c.Value)) = c.Value
      Next c
    
      ' the Keys() contain unique values:
      unique = d.Keys()
    
      ' optionally, show results:
      If show Then
        ' for debug, show the list of unique elements:
        s = ""
        For Each v In d.Keys
          s = s & vbNewLine & v
        Next v
        MsgBox "unique elements: " & s
      End If
    
    End Function
    
    Sub createOrClear(names)
      Dim n As Variant
      Dim s As String
      Dim NewSheet As Worksheet
    
      ' loop through list: add new sheets, or delete content
      For Each n In names
        s = "" & n ' convert to string
        If worksheetExists(s) Then
          Sheets(s).[A1].CurrentRegion.Clear ' UsedRange might be better...?
        Else
          With ActiveWorkbook.Sheets
            Set NewSheet = .Add(after:=Sheets(.Count))
            NewSheet.Name = s
          End With
        End If
      Next n
    
    End Sub
    
    Function worksheetExists(wsName)
    ' adapted from http://www.mrexcel.com/forum/excel-questions/3228-visual-basic-applications-check-if-worksheet-exists.html
      worksheetExists = False
      On Error Resume Next
      worksheetExists = (Sheets(wsName).Name <> "")
      On Error GoTo 0
    End Function
    
    选项显式
    子解()
    将数据设置为工作表
    将名称范围变暗为范围
    尺寸r为量程,c为量程,A1c为量程,s为串
    Dim uniqueNames作为变体,v作为变体
    使用源数据设置shData=图纸(“图纸1”)'图纸
    设置A1c=shData。[A1]'数据范围的第一个单元格-参考了很多。。。
    Set nameRange=Range(A1c,A1c.End(xlDown))'查找范围中的所有连续单元格
    '查找唯一值:使用自定义函数
    '忽略第二个参数以抑制对话框
    uniqueNames=唯一(名称范围,真)
    Application.ScreenUpdate=False“无需闪烁屏幕…”。。。
    '检查每个名称的工作表是否存在,或创建它:
    createOrClear uniqueNames
    '依次筛选每个值,并复制到相应的工作表:
    对于uniqueNames中的每个v
    A1c.自动筛选字段:=1,标准1:=v_
    运算符:=xlAnd
    A1c.CurrentRegion.Copy表(五)。[A1]
    下一个v
    '关闭自动过滤器
    自动过滤器
    '和屏幕更新
    Application.ScreenUpdating=True
    端接头
    功能唯一(r为范围,可选显示)
    '返回包含范围内唯一值的变量数组
    '可选地显示找到值的对话框
    “灵感来自http://stackoverflow.com/questions/3017852/vba-get-unique-values-from-array
    将d作为对象
    调光范围
    像线一样变暗
    Dim v作为变体
    如果IsMissing(show),则show=False
    Set d=CreateObject(“Scripting.Dictionary”)
    '字典对象将创建唯一的键
    “必须使其不区分大小写
    '因为工作表名称和自动筛选不区分大小写
    对于r中的每个c
    d(LCase(“&c.Value))=c.Value
    下一个c
    '键()包含唯一的值:
    unique=d.Keys()
    '显示结果(可选):
    如果演出的话
    '对于调试,显示唯一元素的列表:
    s=“”
    对于每个v In d.键
    s=s&v换行符&v
    下一个v
    MsgBox“唯一元素:&s”
    如果结束
    端函数
    子createOrClear(名称)
    作为变体的dimn
    把s当作s
    
    Option Explicit
    
    Sub Solution()
      Dim shData As Worksheet
      Dim nameRange As Range
      Dim r As Range, c As Range, A1c As Range, s As String
      Dim uniqueNames As Variant, v As Variant
    
      Set shData = Sheets("Sheet1")  ' sheet with source data
      Set A1c = shData.[A1]          ' first cell of data range - referred to a lot...
      Set nameRange = Range(A1c, A1c.End(xlDown)) ' find all the contiguous cells in the range
    
      ' find the unique values: using custom function
      ' omit second parameter to suppress dialog
      uniqueNames = unique(nameRange, True)
    
      Application.ScreenUpdating = False ' no need for flashing screen...
    
      ' check if sheet with each name exists, or create it:
      createOrClear uniqueNames
    
      ' filter on each value in turn, and copy to corresponding sheet:
      For Each v In uniqueNames
        A1c.AutoFilter Field:=1, Criteria1:=v, _
          Operator:=xlAnd
        A1c.CurrentRegion.Copy Sheets(v).[A1]
      Next v
    
      ' turn auto filter off
      A1c.AutoFilter
    
      ' and screen updating on
      Application.ScreenUpdating = True
    
    End Sub
    
    Function unique(r As Range, Optional show)
      ' return a variant array containing unique values in range
      ' optionally present dialog with values found
      ' inspired by http://stackoverflow.com/questions/3017852/vba-get-unique-values-from-array
      Dim d As Object
      Dim c As Range
      Dim s As String
      Dim v As Variant
    
      If IsMissing(show) Then show = False
    
      Set d = CreateObject("Scripting.Dictionary")
    
      ' dictionary object will create unique keys
      ' have to make it case-insensitive
      ' as sheet names and autofilter are case insensitive
      For Each c In r
        d(LCase("" & c.Value)) = c.Value
      Next c
    
      ' the Keys() contain unique values:
      unique = d.Keys()
    
      ' optionally, show results:
      If show Then
        ' for debug, show the list of unique elements:
        s = ""
        For Each v In d.Keys
          s = s & vbNewLine & v
        Next v
        MsgBox "unique elements: " & s
      End If
    
    End Function
    
    Sub createOrClear(names)
      Dim n As Variant
      Dim s As String
      Dim NewSheet As Worksheet
    
      ' loop through list: add new sheets, or delete content
      For Each n In names
        s = "" & n ' convert to string
        If worksheetExists(s) Then
          Sheets(s).[A1].CurrentRegion.Clear ' UsedRange might be better...?
        Else
          With ActiveWorkbook.Sheets
            Set NewSheet = .Add(after:=Sheets(.Count))
            NewSheet.Name = s
          End With
        End If
      Next n
    
    End Sub
    
    Function worksheetExists(wsName)
    ' adapted from http://www.mrexcel.com/forum/excel-questions/3228-visual-basic-applications-check-if-worksheet-exists.html
      worksheetExists = False
      On Error Resume Next
      worksheetExists = (Sheets(wsName).Name <> "")
      On Error GoTo 0
    End Function