将文本文件中的数据排序为树结构
Sort data from Text File into tree structure
我在一个带分隔符的文本文件中有数据,其中包含项目列表及其相互关系,如下所示
Data set text file
其中每个项目 ID 都是不同的,父 wbs 列显示与父项目的关系。
我能够将上述数据导入 excel,但无法弄清楚如何在 excel 中以树格式构建它们,并且还要确保在每个节点下对项目进行排序再次通过他们的序列号
For i = 3 To LastRow
Dim found As Boolean = False
For k = 2 To wbssht.UsedRange.Rows.Count
If wbssht.Cells(k, 1).value = sht.Cells(i, 3).value Then
wbssht.Rows(k + 1).insert
wbssht.Cells(k + 1, 1).value = sht.Cells(i, 1).value
wbssht.Cells(k + 1, 3).value = wbssht.Cells(k, 3).value + 2
wbssht.Cells(k + 1, 2).value = Space(wbssht.Cells(k + 1, 3).value) & sht.Cells(i, 2).value
wbssht.Cells(k + 1, 4).value = sht.Cells(k, 3).value 'parentwbs
wbssht.Cells(k + 1, 5).value = sht.Cells(k, 4).value 'sequence
found = True
Exit For
End If
Next
If found = False Then
wbssht.Cells(wbssht.UsedRange.Rows.Count + 1, 1).value = sht.Cells(i, 1).value
wbssht.Cells(wbssht.UsedRange.Rows.Count, 2).value = sht.Cells(i, 2).value
wbssht.Cells(wbssht.UsedRange.Rows.Count, 3).value = 0
wbssht.Cells(wbssht.UsedRange.Rows.Count, 4).value = sht.Cells(i, 3).value
wbssht.Cells(wbssht.UsedRange.Rows.Count, 5).value = sht.Cells(i, 4).value
End If
Next
我正在尝试实现如下图 excel 中的缩进输出结构。
Expected output
我知道它可能非常简单,但可能需要一些不同的方法。
试试这个代码:
Private Sub TreeView1_KeyUp(KeyCode As Integer, ByVal Shift As Integer)
'Checking what button is pressed.
Select Case KeyCode
'If F5 is pressed.
Case Is = 116
'Declarations.
Dim RngList As Range
Dim RngTarget As Range
Dim DblNameOffset As Double
Dim DblParentOffset As Double
Dim DblSequenceOffset As Double
Dim StrMarker As String
Dim NodNode As Node
Dim DblRow As Double
Dim DblCounter01 As Double
Dim DblItemMax
Dim ObjTreeView As Object
'Setting RngList as the first value in the Item ID column.
Set RngList = Sheets("Sheet1").Range("A2")
'Setting ObjTreeView.
Set ObjTreeView = ActiveSheet.Shapes("TreeView1")
'Setting StrMarker as a value that won't be in any Item ID value nor in any Sequence value.
StrMarker = " | "
'Setting the variables as offests of each column of data from the Item ID column.
DblNameOffset = 1
DblParentOffset = 2
DblSequenceOffset = 3
'Changing RngList to cover the whole Item ID list.
Set RngList = RngList.Parent.Range(RngList, RngList.End(xlDown))
'Setting DblItemMax as the count of Item IDs.
DblItemMax = Excel.WorksheetFunction.CountA(RngList)
'Checking that RngList does not contain any non unique value, non numeric value, blank cell.
For Each RngTarget In RngList
Select Case True
Case Is = (Excel.WorksheetFunction.CountIf(RngList, RngTarget.Value) > 1)
MsgBox "Non unique item ID found. The treeview will not be updated.", vbCritical + vbOKOnly, "Invalid item ID: " & RngTarget.Value
Exit Sub
Case Is = (RngTarget.Value = "")
MsgBox "Blank ID found. The treeview will not be updated.", vbCritical + vbOKOnly, "Invalid item ID in cell " & RngTarget.Address(False, False)
Exit Sub
Case Is = (IsNumeric(RngTarget.Value) = False)
MsgBox "Non numeric item ID found. The treeview will not be updated.", vbCritical + vbOKOnly, "Invalid item ID: " & RngTarget.Value
Exit Sub
End Select
Next
'Clearing ObjTreeView of any previous nodes.
ObjTreeView.OLEFormat.Object.Object.Nodes.Clear
'Covering each Item ID from the smalles to the greatest.
For DblCounter01 = 1 To DblItemMax
'Setting DblRow as the number of row in RngList that contains the given Item ID.
With Excel.WorksheetFunction
DblRow = .Match(.Small(RngList, DblCounter01), RngList, 0)
End With
'Setting RngTarget as the cell that contains the given Item ID.
Set RngTarget = RngList.Cells(DblRow, 1)
'Checking if the given parent name exist in RngList.
If Excel.WorksheetFunction.CountIf(RngList, RngTarget.Offset(0, DblParentOffset).Value) = 0 Then
'If it doesn't exist, the new node is added with no parent node.
ActiveSheet.Shapes("TreeView1").OLEFormat.Object.Object.Nodes.Add , , "K" & RngTarget.Value, RngTarget.Offset(0, DblSequenceOffset) & StrMarker & RngTarget.Offset(0, DblNameOffset)
Else
'If it exists, the new node is added under its parent node.
ActiveSheet.Shapes("TreeView1").OLEFormat.Object.Object.Nodes.Add "K" & RngTarget.Offset(0, DblParentOffset), tvwChild, "K" & RngTarget.Value, RngTarget.Offset(0, DblSequenceOffset) & StrMarker & RngTarget.Offset(0, DblNameOffset)
End If
Next
'Sorting each node (they were added with the Sequence value at the beginning of it text).
For Each NodNode In ActiveSheet.Shapes("TreeView1").OLEFormat.Object.Object.Nodes
NodNode.Sorted = True
Next
'Cutting out the sequence value from the text of each node using the properly placed StrMarker.
For Each NodNode In ActiveSheet.Shapes("TreeView1").OLEFormat.Object.Object.Nodes
NodNode.Text = Split(NodNode.Text, StrMarker)(1)
Next
End Select
End Sub
这是一个私人子程序,当您在选择树视图时按 F5 键将激活它。因此,您必须将它放在树视图所在的 sheet 的模块中。它假定您的树视图名为 TreeView1。它还假定您的列表位于名为 Sheet1 的 sheet 的单元格 A1 中;这意味着在 Sheet1 的单元格 A1 中,您将找到 header“项目 ID”,而在单元格 A2 中,您将找到第一个 ID。请注意,您可以将列表放在一个 sheet 中,将树视图放在另一个中。无论如何,您都可以根据需要编辑代码本身(也许您可以更改列表地址、树视图名称或激活它所按下的键)。其他参数也可以自定义。
该代码会检查任何空的、非数字的、非唯一的项目 ID,如果找到其中任何一个,它就会自行终止。
列表可以按任意顺序排序。无论如何,代码应该可以工作。在您的数据示例中,第一个项目 (27521) 的 parent 名称 (18133) 在项目 ID 列中没有匹配项。在这种情况下,代码会创建一个没有 parent 节点的节点。在任何情况下,假设任何项目 ID 都有一个较低项目 ID 的父亲。
我在一个带分隔符的文本文件中有数据,其中包含项目列表及其相互关系,如下所示
Data set text file
其中每个项目 ID 都是不同的,父 wbs 列显示与父项目的关系。
我能够将上述数据导入 excel,但无法弄清楚如何在 excel 中以树格式构建它们,并且还要确保在每个节点下对项目进行排序再次通过他们的序列号
For i = 3 To LastRow
Dim found As Boolean = False
For k = 2 To wbssht.UsedRange.Rows.Count
If wbssht.Cells(k, 1).value = sht.Cells(i, 3).value Then
wbssht.Rows(k + 1).insert
wbssht.Cells(k + 1, 1).value = sht.Cells(i, 1).value
wbssht.Cells(k + 1, 3).value = wbssht.Cells(k, 3).value + 2
wbssht.Cells(k + 1, 2).value = Space(wbssht.Cells(k + 1, 3).value) & sht.Cells(i, 2).value
wbssht.Cells(k + 1, 4).value = sht.Cells(k, 3).value 'parentwbs
wbssht.Cells(k + 1, 5).value = sht.Cells(k, 4).value 'sequence
found = True
Exit For
End If
Next
If found = False Then
wbssht.Cells(wbssht.UsedRange.Rows.Count + 1, 1).value = sht.Cells(i, 1).value
wbssht.Cells(wbssht.UsedRange.Rows.Count, 2).value = sht.Cells(i, 2).value
wbssht.Cells(wbssht.UsedRange.Rows.Count, 3).value = 0
wbssht.Cells(wbssht.UsedRange.Rows.Count, 4).value = sht.Cells(i, 3).value
wbssht.Cells(wbssht.UsedRange.Rows.Count, 5).value = sht.Cells(i, 4).value
End If
Next
我正在尝试实现如下图 excel 中的缩进输出结构。
Expected output
我知道它可能非常简单,但可能需要一些不同的方法。
试试这个代码:
Private Sub TreeView1_KeyUp(KeyCode As Integer, ByVal Shift As Integer)
'Checking what button is pressed.
Select Case KeyCode
'If F5 is pressed.
Case Is = 116
'Declarations.
Dim RngList As Range
Dim RngTarget As Range
Dim DblNameOffset As Double
Dim DblParentOffset As Double
Dim DblSequenceOffset As Double
Dim StrMarker As String
Dim NodNode As Node
Dim DblRow As Double
Dim DblCounter01 As Double
Dim DblItemMax
Dim ObjTreeView As Object
'Setting RngList as the first value in the Item ID column.
Set RngList = Sheets("Sheet1").Range("A2")
'Setting ObjTreeView.
Set ObjTreeView = ActiveSheet.Shapes("TreeView1")
'Setting StrMarker as a value that won't be in any Item ID value nor in any Sequence value.
StrMarker = " | "
'Setting the variables as offests of each column of data from the Item ID column.
DblNameOffset = 1
DblParentOffset = 2
DblSequenceOffset = 3
'Changing RngList to cover the whole Item ID list.
Set RngList = RngList.Parent.Range(RngList, RngList.End(xlDown))
'Setting DblItemMax as the count of Item IDs.
DblItemMax = Excel.WorksheetFunction.CountA(RngList)
'Checking that RngList does not contain any non unique value, non numeric value, blank cell.
For Each RngTarget In RngList
Select Case True
Case Is = (Excel.WorksheetFunction.CountIf(RngList, RngTarget.Value) > 1)
MsgBox "Non unique item ID found. The treeview will not be updated.", vbCritical + vbOKOnly, "Invalid item ID: " & RngTarget.Value
Exit Sub
Case Is = (RngTarget.Value = "")
MsgBox "Blank ID found. The treeview will not be updated.", vbCritical + vbOKOnly, "Invalid item ID in cell " & RngTarget.Address(False, False)
Exit Sub
Case Is = (IsNumeric(RngTarget.Value) = False)
MsgBox "Non numeric item ID found. The treeview will not be updated.", vbCritical + vbOKOnly, "Invalid item ID: " & RngTarget.Value
Exit Sub
End Select
Next
'Clearing ObjTreeView of any previous nodes.
ObjTreeView.OLEFormat.Object.Object.Nodes.Clear
'Covering each Item ID from the smalles to the greatest.
For DblCounter01 = 1 To DblItemMax
'Setting DblRow as the number of row in RngList that contains the given Item ID.
With Excel.WorksheetFunction
DblRow = .Match(.Small(RngList, DblCounter01), RngList, 0)
End With
'Setting RngTarget as the cell that contains the given Item ID.
Set RngTarget = RngList.Cells(DblRow, 1)
'Checking if the given parent name exist in RngList.
If Excel.WorksheetFunction.CountIf(RngList, RngTarget.Offset(0, DblParentOffset).Value) = 0 Then
'If it doesn't exist, the new node is added with no parent node.
ActiveSheet.Shapes("TreeView1").OLEFormat.Object.Object.Nodes.Add , , "K" & RngTarget.Value, RngTarget.Offset(0, DblSequenceOffset) & StrMarker & RngTarget.Offset(0, DblNameOffset)
Else
'If it exists, the new node is added under its parent node.
ActiveSheet.Shapes("TreeView1").OLEFormat.Object.Object.Nodes.Add "K" & RngTarget.Offset(0, DblParentOffset), tvwChild, "K" & RngTarget.Value, RngTarget.Offset(0, DblSequenceOffset) & StrMarker & RngTarget.Offset(0, DblNameOffset)
End If
Next
'Sorting each node (they were added with the Sequence value at the beginning of it text).
For Each NodNode In ActiveSheet.Shapes("TreeView1").OLEFormat.Object.Object.Nodes
NodNode.Sorted = True
Next
'Cutting out the sequence value from the text of each node using the properly placed StrMarker.
For Each NodNode In ActiveSheet.Shapes("TreeView1").OLEFormat.Object.Object.Nodes
NodNode.Text = Split(NodNode.Text, StrMarker)(1)
Next
End Select
End Sub
这是一个私人子程序,当您在选择树视图时按 F5 键将激活它。因此,您必须将它放在树视图所在的 sheet 的模块中。它假定您的树视图名为 TreeView1。它还假定您的列表位于名为 Sheet1 的 sheet 的单元格 A1 中;这意味着在 Sheet1 的单元格 A1 中,您将找到 header“项目 ID”,而在单元格 A2 中,您将找到第一个 ID。请注意,您可以将列表放在一个 sheet 中,将树视图放在另一个中。无论如何,您都可以根据需要编辑代码本身(也许您可以更改列表地址、树视图名称或激活它所按下的键)。其他参数也可以自定义。
该代码会检查任何空的、非数字的、非唯一的项目 ID,如果找到其中任何一个,它就会自行终止。
列表可以按任意顺序排序。无论如何,代码应该可以工作。在您的数据示例中,第一个项目 (27521) 的 parent 名称 (18133) 在项目 ID 列中没有匹配项。在这种情况下,代码会创建一个没有 parent 节点的节点。在任何情况下,假设任何项目 ID 都有一个较低项目 ID 的父亲。