Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Excel 从vba中的数据列表创建联接矩阵(如外部联接)_Excel_Vba - Fatal编程技术网

Excel 从vba中的数据列表创建联接矩阵(如外部联接)

Excel 从vba中的数据列表创建联接矩阵(如外部联接),excel,vba,Excel,Vba,我有两个列,看起来像: field group1 a 1.2 b 0.2 c 2.4 field group2 a 0.2 c 0.8 field group3 c 0.6 d 0.8 field group1 group2 group3 a 1.2

我有两个列,看起来像:

 field     group1
  a          1.2
  b          0.2
  c          2.4
field      group2
  a          0.2
  c          0.8
field      group3
 c           0.6
 d           0.8
field       group1       group2       group3
 a            1.2         0.2 
 b            0.2           
 c            2.4         0.8          0.6
 d                                     0.8
等等。我已经思考了一段时间,但似乎找不到一个好办法。 是否有一种有效的方法使数据集看起来像:

 field     group1
  a          1.2
  b          0.2
  c          2.4
field      group2
  a          0.2
  c          0.8
field      group3
 c           0.6
 d           0.8
field       group1       group2       group3
 a            1.2         0.2 
 b            0.2           
 c            2.4         0.8          0.6
 d                                     0.8

等等。有什么帮助或想法吗?

所以我有一个想法,它并不漂亮,但可能会奏效。。。 复制整个字段列并将其粘贴到新的工作表中,使用“数据”选项卡并点击“删除重复项”,如果您将其转换为字段a、b、c、d,则可以删除类似以下内容的公式(未测试)”=INDEX(Sheet1!b:b,MATCH($b$1,Sheet1!A1:A3,0))”

match中的搜索范围故意很小,没有$to,如果你向下拖动这个公式,它将进一步搜索(A2:A4、A3:A5等),一旦你得到所有的搜索范围,只需查找/替换所有的N/As删除空白和你的好


如果我有时间,我会尝试整理一个小宏,它会更干净。

在大纲中:创建
group1
列的副本,筛选大于
0
的值并删除这些值。用相应的组填充空格,然后旋转。

我会先用宏重新排列数据,方法如下:

Sub sa()
For Each cl In Range("B2:B1000").Cells
    If IsNumeric(cl.Value) And Not IsEmpty(cl.Value) Then
        If Not IsNumeric(cl.Offset(-1, 0).Value) Then
             cl.Offset(0, 1).Value = cl.Offset(-1, 0).Value
        Else
             cl.Offset(0, 1).Value = cl.Offset(-1, 1).Value
        End If
    End If
Next
End Sub
这样,数据将与此列分配一起重新排列:

[field] [value] [group]

然后就可以很容易地做你想做的事情了,只需创建一个透视表。。。如果需要进一步的帮助,请在评论中告诉我。

对于一次性,您可能只需要使用公式来确定行所在的组,然后根据其他人在对您的问题的评论中所述的方法进行旋转

但是,为了重复使用/减少麻烦,下面的方法应该有效

这将根据问题中所需的输出,对您的测试数据和新表上的输出起作用

它在内存中工作,因此当扩展到数千个单元时,它应该具有良好的性能

Sub blah()

    'Declarations
    Dim outWs As Worksheet
    Dim inArr, outArr
    Dim vector(), groups()
    Dim outC As Collection
    Dim currentGroup As Long
    Dim i As Long, j As Long
    Dim key

     'load data
    inArr = Selection.Value

    Set outC = New Collection

    'iterate through
    For i = LBound(inArr, 1) To UBound(inArr, 1)

        If inArr(i, LBound(inArr, 2)) Like "field*" Then 'new group

            currentGroup = currentGroup + 1
            ReDim Preserve groups(1 To currentGroup)
            groups(currentGroup) = inArr(i, LBound(inArr, 2) + 1) 'assign group name

        Else 'is a record/field

            key = inArr(i, LBound(inArr, 2))
            'retrieve existing, ignoring the exception thrown if key does not exist
            On Error Resume Next
            vector = outC(key)
            If Err.Number = 5 Then 'error raised when key does not exist
                ReDim vector(0 To currentGroup)
                vector(0) = key 'add key
            Else
                outC.Remove (key) 'the reference of item is immutable so we must remove and add again
                ReDim Preserve vector(0 To currentGroup) 'resize vector
            End If
            On Error GoTo 0

            vector(currentGroup) = inArr(i, LBound(inArr, 2) + 1) 'assign value to current group in vector
            outC.Add vector, key 'add to results
            Erase vector

        End If

    Next i

    'Process our results collection into an array suitable for dumping to a sheet
    ReDim outArr(1 To outC.Count, 1 To currentGroup + 1)
    For i = 1 To outC.Count
        For j = 0 To UBound(outC(i))
            outArr(i, j + LBound(outArr, 2) - LBound(outC(i))) = outC(i)(j)
        Next j
    Next i

    'dump data
    With ActiveWorkbook.Worksheets.Add
        .Range(.Cells(1, 2), .Cells(1, 1 + UBound(groups))).Value = groups
        .Range(.Cells(2, 1), .Cells(1 + UBound(outArr, 1), UBound(outArr, 2))).Value = outArr
    End With

    Exit Sub

End Sub

我希望这会有所帮助。

只需将其放在透视表中,从下拉列表中取消选择字段标识符(即“group3”)。啊,我错过了这一部分,我通常只需再添加一列并使用类似于:=IF(LEFT(D5,5)=“Group”,D5,E4)的内容,然后将其放在透视表中。如果有组名,则取组名,如果没有,则复制组名上方的组名。=如果(上(左(D5,5))=“组”,D5,E4)有时会丢失大写字母。我在下面添加了一个宏,该宏在内存中执行必要的标识和转换,可重复使用/大型数据集。对于一次性查询,您也可以使用查找公式从上面查找最近的组(在c列中,插入“=IF(ISTEXT(B1),ROW(),”),然后在d中插入“=INDEX($B$1:$B1,MATCH(MAX($c$1:$C1),$B$1:$B1,0))并向下拖动)。这将返回行组名。然后,使用已标识的组名作为列标题,对数据透视表等应用一个过程。或者,根据上面我的注释中的公式获得组名列后,不使用数据透视,而是在另一个工作表上对其进行重复删除,并将其转置以获得列标题,然后重复删除字段名和将它们粘贴到列标题的左侧,然后索引并匹配包裹在IFERROR(_u,“”)中的值,以获取每个字段(行)和组(列)的交点处的值@pnuts谢谢。我重复它只是为了显示输入>输出。但是,是的,这不是必要的。我会删除它哇,这也是一个非常快速的执行。谢谢。是时候让我真正了解你所做的并从中学习了。