ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: sandorn

[求助] 求助:将逐条记录根据父子关系改为树状结构

[复制链接]

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-3-9 10:34 | 显示全部楼层

使用了一下,非常好,感谢!!!!

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-3-9 12:36 | 显示全部楼层
micch 发表于 2019-3-9 10:19
不熟练递归,练习一下,结果排序只会最基础的,还不会多关键字排序

感谢,很好用的代码

TA的精华主题

TA的得分主题

发表于 2019-3-9 12:39 | 显示全部楼层
sandorn 发表于 2019-3-9 12:36
感谢,很好用的代码

我也是初学递归,还在琢磨中,能用就好

TA的精华主题

TA的得分主题

发表于 2019-3-9 13:00 | 显示全部楼层

看的一頭霧水,是否一定要用call 递归 才能完成這題目?

TA的精华主题

TA的得分主题

发表于 2019-3-9 21:59 | 显示全部楼层
chis3 发表于 2019-3-9 13:00
看的一頭霧水,是否一定要用call 递归 才能完成這題目?

递归的你看不懂,非递归的你更看不懂了。不是一定要用递归,不过不用的话写起来有些烦琐,因为需要自己来管理回溯,但速度会更快。

TA的精华主题

TA的得分主题

发表于 2019-3-10 08:28 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
sandorn 发表于 2019-3-9 10:33
首先非常感谢帮助!!各级均可能是多个,没有限定的单线,能否优化一下?

'再加字典,输出格式处理起来有点晕,试了一下好像差不多,,,

Option Explicit

Dim result, dic(2), lastpos

Sub test()
  Dim arr, i, j, key, t, m, n, flag As Boolean
  For i = 0 To UBound(dic)
    Set dic(i) = CreateObject("scripting.dictionary")
  Next
  arr = Range("a2:b" & Cells(Rows.Count, "a").End(xlUp).Row)
  ReDim result(1 To UBound(arr, 1), 1 To 10 ^ 2) As String
  For i = 1 To UBound(arr, 1)
    For j = 1 To UBound(arr, 1)
      If arr(i, 1) = arr(j, 2) Then Exit For
    Next
    If j = UBound(arr, 1) + 1 Then
      dic(0)(arr(i, 1)) = dic(0)(arr(i, 1)) + 1
    End If
  Next
  For Each key In dic(0).keys
    For i = 1 To dic(0)(key)
      flag = True
      For j = 1 To UBound(arr, 1)
        If arr(j, 1) = key Then
          m = m + 1: n = 1: t = arr(j, 2)
          If flag Then result(m, n) = key: flag = False
          arr(j, 1) = vbNullString: lastpos = m
          dic(1).RemoveAll: dic(2)(arr(j, 2)) = m
          Call rec(arr, arr(j, 2), m, n, t)
          n = n + 1: result(lastpos, n) = t
        End If
  Next j, i, key
  [s1].Resize(UBound(arr, 1), UBound(result, 2)) = result
End Sub

Function rec(arr, s, m, n, t)
  Dim i, j, tt
  For i = 1 To UBound(arr, 1)
    If s = arr(i, 1) Then
      If dic(1).exists(arr(i, 1)) Then
        dic(2)(arr(i, 1)) = dic(2)(arr(i, 1)) + 1
        result(dic(2)(arr(i, 1)), dic(1)(arr(i, 1)) + 1) = arr(i, 2)
        If m < dic(2)(arr(i, 1)) Then m = dic(2)(arr(i, 1))
        lastpos = lastpos + 1
      Else
        n = n + 1: dic(2)(arr(i, 1)) = lastpos
        dic(1)(arr(i, 1)) = n
        t = arr(i, 2)
        result(dic(2)(arr(i, 1)), dic(1)(arr(i, 1))) = arr(i, 1)
        result(dic(2)(arr(i, 1)), dic(1)(arr(i, 1)) + 1) = arr(i, 2)
      End If
      arr(i, 1) = vbNullString
      Call rec(arr, arr(i, 2), m, n, t)
    End If
  Next
End Function

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2019-3-10 14:13 | 显示全部楼层
提供一个pq的递归解法,供参考:
  1. = let fx=(m,n)=>if List.MatchesAll(m,each List.Last(_)=null) then #table(n,List.Transform(m,each List.FirstN(_,n)))
  2.                 else @fx( List.TransformMany( m,
  3.                                               (L)=>let a=List.Select(Table.ToRows(源),each _{0}=L{n})
  4.                                                     in if a{0}?=null then {{}} else a,
  5.                                               (x,y)=>x&{y{1}?}), n+1)
  6.     in fx(Table.ToRows(Table.SelectRows(源,each not List.Contains(源[职员],[推荐人]))),1)
复制代码
2019-03-10_141258.jpg

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2019-3-10 18:22 | 显示全部楼层
呵呵,看到好多老师都能递归,可惜小菜鸟的我实在理解不了递归的思路。
刚学习了数组和字典,用此方法 献丑了,希望老师指点下代码哦
D1.gif

TA的精华主题

TA的得分主题

发表于 2019-3-10 18:25 | 显示全部楼层
本帖最后由 我是HR 于 2019-3-10 18:35 编辑
  1. Sub 父子关系()
  2.     Dim arr, dic, brr(1 To 10000), crr()
  3.     Set dic = CreateObject("scripting.dictionary")
  4.     Set d = CreateObject("scripting.dictionary")
  5.     Application.ScreenUpdating = False
  6.     arr = [a1].CurrentRegion
  7.     For i = 2 To UBound(arr)
  8.         dic(arr(i, 1)) = dic(arr(i, 1)) & "|" & arr(i, 2)
  9.     Next i
  10.     i = 1
  11.     For n = 2 To UBound(arr)
  12.         If dic.exists(arr(n, 1)) Then
  13.             h = h + 1
  14.             brr(h) = arr(n, 1)
  15.             Do While i <= h
  16.                 xm = Mid(brr(i), InStrRev(brr(i), "-") + 1)
  17.                 If InStr(dic(xm), "|") Then
  18.                     ms = Split(Mid(dic(xm), 2), "|")
  19.                     For x = 0 To UBound(ms)
  20.                         h = h + 1
  21.                         brr(h) = brr(i) & "-" & ms(x)
  22.                         Cells(h, "m") = brr(h)
  23.                     Next x
  24.                 End If
  25.                 i = i + 1
  26.                 If dic.exists(xm) Then dic.Remove xm
  27.             Loop
  28.         End If
  29.     Next n
  30.     dic.RemoveAll
  31.     For i = 1 To h
  32.         dic(brr(i)) = ""
  33.     Next i
  34.     For Each k In dic.keys
  35.         For i = 1 To h
  36.             If InStr(brr(i), k & "-") Then
  37.                 dic.Remove k
  38.                 Exit For
  39.             End If
  40.         Next i
  41.     Next
  42.     x = 0
  43.     ReDim crr(1 To dic.Count, 1 To 20)
  44.     For Each k In dic.keys
  45.         x = x + 1
  46.         For j = 0 To UBound(Split(k, "-"))
  47.             crr(x, j + 1) = Split(k, "-")(j)
  48.         Next j
  49.     Next
  50.     For j = 1 To 20
  51.         For i = 1 To x - 1
  52.             If Len(crr(i, j)) Then
  53.                 For a = i + 1 To x
  54.                     If Len(crr(a, j)) And crr(a, j) = crr(i, j) Then crr(a, j) = ""
  55.                 Next a
  56.             End If
  57.         Next i
  58.     Next j
  59.     [o1].Resize(x, 20) = crr
  60.     Set dic = Nothing: Set d = Nothing
  61.     Application.ScreenUpdating = True
  62. End Sub
复制代码

评分

2

查看全部评分

TA的精华主题

TA的得分主题

发表于 2019-3-11 21:52 | 显示全部楼层
参与一下:
Sub test()
Dim ar, i&, d, d1, d2, dk, br, myr&, myc&
Set d = CreateObject("scripting.dictionary")
Set d1 = CreateObject("scripting.dictionary")
ar = Range("a1").CurrentRegion
For i = 2 To UBound(ar)
    d(ar(i, 1)) = d(ar(i, 1)) & "|" & ar(i, 2)
    d1(ar(i, 1)) = ""
Next i
For i = 2 To UBound(ar)
    If d1.exists(ar(i, 2)) Then
        d1.Remove (ar(i, 2))
    End If
Next i
ReDim br(1 To i, 1 To i)
dk = d1.keys
myr = 1
For i = 0 To UBound(dk)
    Call digui(dk(i), d, br, myr, 1, myc)
Next i
Range("m2").Resize(myr, myc) = br
End Sub
Sub digui(s, d, br, myr, c, myc)
Dim ds, i&
If c > myc Then myc = c
br(myr, c) = s
If d(s) = "" Then
    myr = myr + 1
    Exit Sub
End If
ds = Split(d(s), "|")
For i = 1 To UBound(ds)
    Call digui(ds(i), d, br, myr, c + 1, myc)
Next i
End Sub

评分

2

查看全部评分

您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-5-5 08:16 , Processed in 0.033994 second(s), 11 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表