ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[求助] VBA编程有偿代做

[复制链接]

TA的精华主题

TA的得分主题

发表于 2022-3-23 13:22 | 显示全部楼层
本帖最后由 笨鸟飞不高 于 2022-3-23 16:06 编辑
1256366515 发表于 2022-3-23 11:24
实测数据运行很久都没有结果。

..............................

TA的精华主题

TA的得分主题

 楼主| 发表于 2022-3-23 14:39 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册

结果如图,本该终止了,又形成了一个环状
结果有误.png

TA的精华主题

TA的得分主题

发表于 2022-3-23 15:17 | 显示全部楼层
1256366515 发表于 2022-3-22 20:51
单元格里面的字符数  限定为了一个,影响实际操作

可以用字典做个映射,单字符做 KEY,全称放到 ITEM 里去

TA的精华主题

TA的得分主题

发表于 2022-3-23 15:36 | 显示全部楼层
1256366515 发表于 2022-3-23 14:39
结果如图,本该终止了,又形成了一个环状

是的,递归还没入门,凭感觉写的

TA的精华主题

TA的得分主题

 楼主| 发表于 2022-3-23 17:22 | 显示全部楼层
笨鸟飞不高 发表于 2022-3-23 15:36
是的,递归还没入门,凭感觉写的

这样的话就会造成本来很多是重复的,你再加一个环,编程不重复的,结果这么多行,没有办法使用的

TA的精华主题

TA的得分主题

发表于 2022-3-23 19:01 | 显示全部楼层
1256366515 发表于 2022-3-23 17:22
这样的话就会造成本来很多是重复的,你再加一个环,编程不重复的,结果这么多行,没有办法使用的

你参照其他大神的吧,我的可以忽略

TA的精华主题

TA的得分主题

 楼主| 发表于 2022-3-23 19:32 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
笨鸟飞不高 发表于 2022-3-23 19:01
你参照其他大神的吧,我的可以忽略

已经非常感谢了

TA的精华主题

TA的得分主题

发表于 2022-3-23 20:49 | 显示全部楼层
将系统转置数组修改为循环转置数组,解决出错问题。
但因为数据太多,运行时间太长,几个小时,47812个闭环,太恐怖了
  1. Sub CloseLink()
  2.     Dim vSplit As Variant, vSplitLink As Variant
  3.     Dim vLen As Variant, sLink As String, vLink As Variant
  4.     Dim sFirst As String, nBit As Long, sMid As String, bIsSame As Boolean, sStr As String
  5.     Dim nI As Long
  6.    
  7.     With [A1].CurrentRegion
  8.         vData = .Offset(1).Resize(.Rows.Count - 1).Value
  9.     End With
  10.     Set dicData = CreateObject("Scripting.Dictionary")
  11.     For nRow = 1 To UBound(vData)
  12.         If vData(nRow, 1) <> "" And vData(nRow, 2) <> "" Then
  13.             If Not dicData.Exists(vData(nRow, 1)) Then Set dicData(vData(nRow, 1)) = CreateObject("Scripting.Dictionary")
  14.             dicData(vData(nRow, 1))(vData(nRow, 2)) = ""
  15.         End If
  16.     Next
  17.     ReDim vData(0)
  18.     nRow = 0
  19.    
  20.     GetLink dicData
  21.     [D:E].ClearContents
  22.     If nRow > 0 Then
  23.         ReDim vSplit(1 To UBound(vData), 1 To 1)
  24.         For nRow = 1 To UBound(vSplit)
  25.             If Trim(vData(nRow)) <> "" Then vSplit(nRow, 1) = vData(nRow) & "∮"
  26.         Next
  27.         [D1].Resize(UBound(vSplit)) = vSplit
  28.         Set dicData = CreateObject("Scripting.Dictionary")
  29.         For nRow = 1 To UBound(vData)
  30.             sLink = vData(nRow)
  31.             vSplit = Split(sLink, "→")
  32.             sFirst = vSplit(0) & "→"
  33.             vLen = UBound(vSplit) + 1
  34.             If Not dicData.Exists(vLen) Then Set dicData(vLen) = CreateObject("Scripting.Dictionary")
  35.             For Each vLink In dicData(vLen).Keys
  36.                 nBit = InStr(vLink & "→", sFirst)
  37.                 If nBit > 1 Then
  38.                     sStr = Right(vLink & "→", Len(vLink & "→") - nBit + 1) & Left(vLink, nBit - 2)
  39.                     bIsSame = sStr = sLink
  40.                     If bIsSame Then Exit For
  41.                 End If
  42.             Next
  43.             If Not bIsSame Then
  44.                 dicData(vLen)(sLink) = 0
  45.                 nI = nI + 1
  46.                 If nI <> nRow Then vData(nI) = vLink
  47.             End If
  48.             bIsSame = False
  49.         Next
  50.         If nI = 1 Then
  51.             [E1] = vData(1) & "∮"
  52.         Else
  53.             ReDim vSplit(1 To nI, 1 To 1)
  54.             For nRow = 1 To UBound(vSplit)
  55.                 If Trim(vData(nRow)) <> "" Then vSplit(nRow, 1) = vData(nRow) & "∮"
  56.             Next
  57.             [E1].Resize(nI) = vSplit
  58.         End If
  59.     End If
  60. End Sub

  61. Private Function GetLink(ByVal oDic As Object, Optional ByVal sFirst As String, Optional ByVal sLink As String)
  62.     Dim vKey As Variant, vDataKey As Variant
  63.    
  64.     For Each vKey In oDic.Keys
  65.         If vKey = sFirst And UBound(Split(sLink & "→" & vKey, "→")) > 1 Then
  66.             nRow = nRow + 1
  67.             ReDim Preserve vData(1 To nRow)
  68.             vData(nRow) = sLink
  69.         ElseIf Not ("→" & sLink & "→" Like "*→" & vKey & "→*") Then
  70.             If dicData.Exists(vKey) Then GetLink dicData(vKey), IIf(sFirst = "", vKey, sFirst), IIf(sLink = "", "", sLink & "→") & vKey
  71.         End If
  72.     Next
  73. End Function
复制代码

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2022-3-23 20:51 | 显示全部楼层
只能把已经运行的结果附上,至于优化问题,有空再研究

VBA编写程序,寻找所有闭环(by.micro)V1.1.part1.rar

2 MB, 下载次数: 3

VBA编写程序,寻找所有闭环(by.micro)V1.1.part2.rar

2 MB, 下载次数: 3

VBA编写程序,寻找所有闭环(by.micro)V1.1.part3.rar

68.3 KB, 下载次数: 3

TA的精华主题

TA的得分主题

发表于 2022-3-24 11:02 | 显示全部楼层
调整算法,从6小时缩减到3小时了
  1. Private vData As Variant, nRow As Long, dicData As Object, dicCloseLink As Object, dicMinFirst As Object

  2. Sub CloseLink()
  3.     Dim vSplit As Variant, vSplitLink As Variant
  4.     Dim vLen As Variant, sLink As String, vLink As Variant
  5.     Dim sFirst As String, nBit As Long, sMid As String, bIsSame As Boolean, sStr As String
  6.     Dim nI As Long
  7.    
  8.     [G1] = Now()
  9.     With [A1].CurrentRegion
  10.         vData = .Offset(1).Resize(.Rows.Count - 1).Value
  11.     End With
  12.     Set dicData = CreateObject("Scripting.Dictionary")
  13.     For nRow = 1 To UBound(vData)
  14.         If Trim(vData(nRow, 1)) <> "" And Trim(vData(nRow, 2)) <> "" Then
  15.             If Not dicData.Exists(Trim(vData(nRow, 1))) Then Set dicData(Trim(vData(nRow, 1))) = CreateObject("Scripting.Dictionary")
  16.             dicData(Trim(vData(nRow, 1)))(Trim(vData(nRow, 2))) = ""
  17.         End If
  18.     Next
  19.     ReDim vData(0)
  20.     nRow = 0
  21.    
  22.     Set dicCloseLink = CreateObject("Scripting.Dictionary")
  23.     Set dicMinFirst = CreateObject("Scripting.Dictionary")
  24.     GetLink dicData
  25.    
  26.     [D:E].ClearContents
  27.     If nRow > 0 Then
  28.         ReDim vSplit(1 To UBound(vData), 1 To 1)
  29.         For nRow = 1 To UBound(vSplit)
  30.             If Trim(vData(nRow)) <> "" Then vSplit(nRow, 1) = vData(nRow) & "∮"
  31.         Next
  32.         [D1].Resize(UBound(vSplit)) = vSplit
  33.     End If
  34.     [H1] = Now()
  35. End Sub

  36. Private Function GetLink(ByVal oDic As Object, Optional ByVal dicLink As Object)
  37.     Dim vKey As Variant, dicTmp As Object, vTmp As Variant, sMin As String, sMinFirst As String, nI As Long
  38.    
  39.     If dicLink Is Nothing Then Set dicLink = CreateObject("Scripting.Dictionary")
  40.     For Each vKey In oDic.Keys
  41.         If Not dicLink.Exists(vKey) Then
  42.             If dicData.Exists(vKey) Then
  43.                 Set dicTmp = CreateObject("Scripting.Dictionary")
  44.                 For Each vTmp In dicLink.Keys
  45.                     dicTmp(vTmp) = dicTmp.Count
  46.                 Next
  47.                 dicTmp(vKey) = dicTmp.Count
  48.                 GetLink dicData(vKey), dicTmp
  49.             End If
  50.         ElseIf dicLink.Count > 2 Then
  51.             If vKey = dicLink.Keys()(0) Then
  52.                 sMinFirst = FindMin(dicLink.Keys())
  53.                 If dicLink.Keys()(0) = sMinFirst Then
  54.                     sMin = Join(dicLink.Keys(), "→")
  55.                 Else
  56.                     Set dicTmp = CreateObject("Scripting.Dictionary")
  57.                     For nI = dicLink(sMinFirst) To dicLink.Count - 1
  58.                         dicTmp(dicLink.Keys()(nI)) = dicTmp.Count
  59.                     Next
  60.                     For Each vTmp In dicLink.Keys
  61.                         If vTmp = sMinFirst Then Exit For
  62.                         dicTmp(vTmp) = dicTmp.Count
  63.                     Next
  64.                     sMin = Join(dicTmp.Keys(), "→")
  65.                 End If
  66.                 If Not dicMinFirst.Exists(sMin) Then
  67.                     dicMinFirst(sMin) = 0
  68.                     nRow = nRow + 1
  69.                     ReDim Preserve vData(1 To nRow)
  70.                     vData(nRow) = Join(dicLink.Keys(), "→")
  71.                 End If
  72.             End If
  73.         End If
  74.     Next
  75. End Function

  76. Private Function FindMin(ByVal vMin As Variant) As String
  77.     Dim nI As Double, nJ As Double, vTmp As Variant
  78.    
  79.     nJ = LBound(vMin)
  80.     For nI = LBound(vMin) To UBound(vMin) - 1
  81.         If vMin(nI) <= vMin(nI + 1) Then
  82.             If nI > nJ Then
  83.                 nJ = nI
  84.             Else
  85.                 nI = nJ
  86.             End If
  87.         Else
  88.             vTmp = vMin(nI)
  89.             vMin(nI) = vMin(nI + 1)
  90.             vMin(nI + 1) = vTmp
  91.             If nI <> LBound(vMin) Then nI = nI - 2
  92.         End If
  93.     Next nI
  94.     FindMin = vMin(LBound(vMin))
  95. End Function
复制代码
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-9-29 22:28 , Processed in 0.047092 second(s), 9 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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