在VBA Excel中从2d数组构建数字链

如何解决在VBA Excel中从2d数组构建数字链

有一张带数字的桌子。看到 Attachment

第一列用作索引。它的编号为0。 它确定要跳转到的行。 在行中选择一个数字。 通过该编号,转到具有该编号的行。 我们从新行中选择一个数字,依此类推。

限制。 过渡期间不重复数字 返回到初始编号只能是等于表中行数的转换编号。

有必要通过表中的数字构建最长的过渡链。理想情况下,循环,即当初始数量等于最终数量,并且转换数量等于行数时。

例如,让我们从数字1开始。 第一行包含唯一的数字-74。转到第74行。 在第74行中,选择第一列中的数字(第零列是行编号索引)。在第74行的第一列中没有任何内容,因此我们在后面的列中进行进一步研究。在第二列中有一个数字46。转到第46行。 在第46行的第一列中有一个数字19。转到第19行。 等等

如果不可能选择这样的数字以致没有重复,则输出原来是文件的序列。 然后寻找实现最长过渡链的其他方法。

如果代码可以后退一,二,... n步并选择其他路径,那将是很好的。例如,在第一遍中,代码从该行中选择第一个数字并插入死胡同,然后又返回并选择第二个或第三个数字,然后再次重复。 我对如何在代码中执行此操作几乎一无所知。

最好的情况是,我希望代码建议如何修正输入表以获得完整的序列。也就是说,该代码将建议在哪个单元格中更改编号以循环序列。

我手动浏览了这张表,发现至少有两个序列在​​步骤86循环(现在表中有86行),但是所附的代码最多可以执行73步。

我用Excel编写了VBA代码。您可以在下面看到它。

在Drive.Google上完整xls

请告诉我如何解决此问题。 如果使用VBA无法解决此类问题,请给我建议,我应该使用哪种编程语言。

Function IsUnique(ByRef intArr() As Integer,intNum As Integer) As Boolean

    Dim intPart() As Integer
    
    ReDim intPart(1 To UBound(intArr)) As Integer
    
    For i = 1 To UBound(intArr)
        intPart(i) = intArr(i)
    Next
    
    QuickSortInteger intPart
    
    If (BinarySearchInteger(intPart,intNum) = -1) And (intNum <> 0) Then
        IsUnique = True
    Else
        IsUnique = False
    End If
    
End Function
Sub Main()
    Dim varIData() As Variant
    Dim intTemp(1 To 7) As Integer
    
    Dim intTempWOZeros() As Integer
    
    Dim intTempDSC(1 To 7) As Integer
    Dim intTempCount As Integer
    
    Dim intStore() As Integer
    Dim intIData(1 To 86,1 To 7) As Integer

    Dim intBegin As Integer
    Dim intCurr As Integer
    Dim str As String
      
    Sheets("For_Macros").Select
        
' Reads the given Excel table in a two-dimensional array
        
    varIData = Range("B1:H86").Value

' In the cycle,the data from the Variant-array tranfer to Integer-array,empty values is replaced by zeros
    
    For i = 1 To 86
        For j = 1 To 7
            If varIData(i,j) = "" Then
                intIData(i,j) = 0
            Else
                intIData(i,j) = CInt(varIData(i,j))
            End If
        Next
    Next
    
    
'   Searching for other paths of the solution
'   Reverse input array. The fisrt element became the last and the last - the first.

'    For i = 1 To 86
'        For j = 1 To 7
'            intTemp(8 - j) = intIData(i,j)
'        Next
'
'        For j = 1 To 7
'            intIData(i,j) = intTemp(j)
'        Next
'    Next

'   Sort rows entire values - ascending
'   I tried to change an order in numbers in each row

'    For i = 1 To 86
'        For j = 1 To 7
'            intTemp(j) = intIData(i,j)
'        Next
'
'        QuickSortInteger intTemp()
'
'        For j = 1 To 7
'            intIData(i,j) = intTemp(j)
'        Next
'    Next
        
  
'   Sort rows entire values - descending
'   I tried to change an order in numbers in each row

'    For i = 1 To 86
'        For j = 1 To 7
'            intTemp(j) = intIData(i,j)
'        Next
'
'        QuickSortInteger intTemp()
'
'        For j = 1 To 7
'            intTempDSC(8 - j) = intTemp(j)
'        Next
'
'        For j = 1 To 7
'            intIData(i,j) = intTempDSC(j)
'        Next
'    Next
    
' The 1st For
For Z = 1 To 86 ' Top level.
                ' 'For ... next' for each start number
                ' At the first iteration we take the number 1 and begin 
                ' form the 1st row,to build a sequence much posible as can
                ' At the 2nd iteratoin we take number two as the first number and begin
                ' form the 1st row,to build a sequence much posible as can

                ' We try go through the array every time starting with new row
                ' and do until we can add in a sequence new unique number
                

    i = Z
    ReDim Preserve intStore(1) ' Array in which we collect all number in a sequence
    intStore(1) = i ' Array initialization with value = i,just like starting with the i-th line,' and at i-th number we can not returm until amount of collecting number
                    ' will be less than an amount of rows in intIData-array 
                    ' If intIData-array has got 100 row,then we can return
                    ' at the begining row (wherever it be the 1st,the 49th or the 93th) at 100th iteration only
    
    m = 0

' The 2nd For
    For k = 1 To 85
        ReDim Preserve intStore(k + 1)
        intStore(k + 1) = -1
 
        ' We search any non-zero value
        ' We take this number from row selected from intIData
        
        m = 1
        intTempCount = 0
        
        
'       Count amount of zeros
'       Discard zeros
'       Copy one row form 2d-array to 1d-array. 1d-array consists 1 row from intIData data-array

' The 3rd For
        For count = 1 To 7
            intTemp(count) = intIData(i,count)
        Next
' The 3rd For End
'       Count amount of zeros. We arrange the array so that it initially contains non-zero values

        intTempCount = AllZerosAtEnd(intTemp())
              
        ReDim intTempWOZeros(1 To intTempCount)
              
'       Transferring to an array without zeros
' The 4th For
        For count = 1 To intTempCount
            intTempWOZeros(count) = intTemp(count)
        Next
' The 4th For End
        
        intCurr = intTempWOZeros(1)
        m = 1
        
Povtor:
        If IsUnique(intStore,intCurr) Then ' We check the uniqueness of the selected number if unique put it in the output array intStore
            intStore(k + 1) = intCurr
            i = intCurr                     ' and assign the variable i the value of this unique number,the next iteration of the loop will already analyze the string with this number
        Else
            If m <= intTempCount Then ' if there are still numbers in the intTempWOZeros row-array,then view other columns
' The 5th For
                For j = m To intTempCount ' select the next value from the array,increase m by 1 and exit the loop back to check the uniqueness
                    intCurr = intTempWOZeros(j)
                    m = j + 1
                    GoTo Povtor
                Next ' The 5th For End
            Else
                GoTo Metka
            End If
        End If
        

    Next
' The 2nd For End

Metka: ' To fill Excel sheet Search results,sheet created manually
    Sheets("PathOrder").Select
    Range("A1").Select
    ActiveCell.Cells(3,Z).Select ' Applied from the 3rd line,' in the first line is for an amount of found numbers
                                  ' the 2nd line is the blank
    
' The 6th For
    
    For x = 1 To UBound(intStore)
        If intStore(x) = -1 Then Exit For
        ActiveCell.FormulaR1C1 = intStore(x)
        ActiveCell.Cells(2,1).Select
    Next
    
' The 6th For End

    ' Debug in Debug.Print to see what step the code is in
    ' In case of a loop or in case of too long execution,you can interrupt the execution
    
'    Debug.Print "Z: " & Z & vbCrLf
'    Debug.Print x - 1 & " numbers" & vbCrLf
'
    
Next
' The 1st For End
  
    
End Sub

Function AllZerosAtEnd(intArray() As Integer) As Integer
    Dim intNumZeros As Integer
    Dim intTempArray(1 To 7) As Integer
    Dim count As Integer
    Dim i As Byte
    Dim position As Byte
    Dim intTemp As Integer
    
    
    intNumZeros = 0
    
    For i = 1 To 7
        If intArray(i) = 0 Then intNumZeros = intNumZeros + 1
    Next


    position = 1
    
    If intNumZeros <> 0 Then
        For i = 1 To 7
            If intArray(i) <> 0 Then
                intTempArray(position) = intArray(i)
                position = position + 1
            End If
        Next
    For i = 1 To 7
        intArray(i) = intTempArray(i)
    Next
        
    End If

    AllZerosAtEnd = 7 - intNumZeros
    
End Function

解决方法

修改后的答案

我明白了你的意图。请参阅以下新代码。

Sub BuidChains()
    Dim vData As Variant
    Dim Ws As Worksheet,rstWs As Worksheet
    Dim a As Variant
    Dim n As Integer,sNum As Integer
    Dim Dic As Object
    Dim v As Variant
    
    Set Ws = Sheets("For_Macros")
    Set rstWs = Sheets("Sheet3") 'Sheets.Add 'set the result sheet
    
    vData = Ws.Range("B1:H86").Value
    rstWs.UsedRange.Clear
    
    For n = 1 To 86
        'find first value not empty
        For j = 1 To 7
            If vData(n,j) <> "" Then
                sNum = vData(n,j)
                Exit For
            End If
        Next j
        Set Dic = CreateObject("Scripting.Dictionary")
        a = ChainArray(n,vData,Dic,sNum)
        
        Debug.Print n & " : " & Join(a,",")
        
        'Record it on the sheet.
        With rstWs
            .Cells(1,n) = UBound(a) + 1
            .Cells(3,n) = n
            .Cells(4,n).Resize(UBound(a)) = Application.Transpose(a)
            .Range("cj1") = "Max"
            .Range("cj2") = "Min"
            .Range("cM1").Resize(2).Value = "Start number"
            .Range("cK1") = WorksheetFunction.Max(.Range("a1").Resize(1,86))
            .Range("cK2") = WorksheetFunction.Min(.Range("a1").Resize(1,86))
            .Range("cn1") = WorksheetFunction.HLookup(.Range("ck1"),.Range("a1").Resize(3,86),3,0)
            .Range("cn2") = WorksheetFunction.HLookup(.Range("ck2"),0)
        End With
    Next n
End Sub
Static Function ChainArray(k As Integer,v As Variant,Dic As Object,sNum As Integer) As Variant
    Dim vR() As Variant
    Dim i As Integer,j As Integer
    Dim Ws As Worksheet
    Dim n As Integer,cnt As Integer
    
    If n > 100 Then Exit Function
    If n = 0 Then Dic.Add k,k
    cnt = cnt + 1
    If cnt > 100 Then
        cnt = 0
        n = 0
        Exit Function
    End If
    For j = 1 To 7
            If v(k,j) <> "" Then
                If Not Dic.Exists(v(k,j)) Then
                     n = n + 1
                    ReDim Preserve vR(1 To n)
                    vR(n) = v(k,j)
                    i = v(k,j)
                    Dic.Add i,i
                    Exit For
                End If
            End If
    Next j
    
    DoEvents
    
    ChainArray i,v,sNum
    ChainArray = vR

End Function

结果图片

enter image description here

结果调试

我的结果与您介绍的结果有些不同。

1 : 74,46,19,29,43,25,26,57,34,75,35,49,65,44,8,54,77,84,76,10,18,36,40,23,80,17,6,42,81,78,66,56,63,4,83,24,37,11,47,62,2,64,79,41,86,12,31,85,72,68,16,20,61,58,15,5
2 : 64,5
3 : 65,5
4 : 83,63
5 : 84,74,27,28,32,7
6 : 42,7
7 : 63,69,51,53,14,59,70,73,38,9,67,13,5,71,33,50,1
8 : 54,5
9 : 74,5
10 : 18,45,2
11 : 83,63
12 : 31,5
13 : 40,2
14 : 83,48,7
15 : 37,63
16 : 20,60,7,6
17 : 80,7
18 : 57,5
19 : 46,5
20 : 2,1,6
21 : 32,82,5
22 : 18,5
23 : 80,7
24 : 37,63
25 : 26,6
26 : 57,6
27 : 74,5
28 : 32,15
29 : 43,6
30 : 84,5
31 : 84,5
32 : 7,21,20
33 : 86,3
34 : 75,52,22,6
35 : 49,7
36 : 43,6
37 : 11,63
38 : 9,5
39 : 15,63
40 : 10,2
41 : 79,2
42 : 81,6
43 : 74,6
44 : 8,5
45 : 10,5
46 : 19,6
47 : 62,5
48 : 47,5
49 : 3,39,24
50 : 16,6
51 : 63,7
52 : 18,5
53 : 75,68
54 : 77,5
55 : 23,7
56 : 63,7
57 : 34,2
58 : 68,2
59 : 79,6
60 : 36,6
61 : 58,2
62 : 75,5
63 : 65,7
64 : 79,2
65 : 44,7
66 : 56,7
67 : 64,2
68 : 44,63
69 : 27,5
70 : 61,2
71 : 33,3
72 : 68,63
73 : 78,7
74 : 46,5
75 : 35,5
76 : 10,5
77 : 84,5
78 : 66,7
79 : 41,6
80 : 65,7
81 : 78,2
82 : 81,2
83 : 4,1
84 : 76,5
85 : 72,63
86 : 78,3

我不知道你的意图是否正确。试试吧

Sub test()
    Dim vData As Variant
    Dim Ws As Worksheet,rstWs As Worksheet
    Dim a() As Variant
    Dim n As Integer
    Dim Dic As Object
    Dim v As Variant
    
    Set Dic = CreateObject("Scripting.Dictionary")
    Set Ws = Sheets("For_Macros")
    Set rstWs = Sheets.Add 'set the result sheet
    
    vData = Ws.Range("B1:H86").Value
    
    For n = 1 To 86
        a = myArray(n,Dic)
        Debug.Print n & " : " & Join(a,")
        With rstWs
            .Range("a" & n) = n
            .Range("b" & n).Resize(1,UBound(a)) = a
        End With
    Next n
End Sub
Static Function myArray(k As Integer,Dic As Object) As Variant
    Dim vR() As Variant
    Dim i As Integer,j As Integer
    Dim Ws As Worksheet
    Dim n As Integer
    
    If n > 83 Then Exit Function
    For j = 1 To 7
        If v(k,j) <> "" Then
            If Dic.Exists(v(k,j)) Then
                n = 0
                Set Dic = CreateObject("Scripting.Dictionary")
                Exit Function
            Else
                Dic.Add v(k,j),v(k,j)
            End If
            
            n = n + 1
            ReDim Preserve vR(1 To n)
            vR(n) = v(k,j)
            i = v(k,j)
            Exit For
        End If
    Next j
    
    DoEvents
    
    myArray i,Dic
    myArray = vR

End Function

调试结果

1 : 74,19
2 : 64,41
3 : 65,3
4 : 83,4
5 : 84,77
6 : 42,3
7 : 63,3
8 : 54,8
9 : 74,19
10 : 18,10
11 : 83,4
12 : 31,77
13 : 40,76
14 : 83,4
15 : 37,4
16 : 20,41
17 : 80,3
18 : 57,18
19 : 46,19
20 : 2,41
21 : 32,3
22 : 18,10
23 : 80,3
24 : 37,4
25 : 26,18
26 : 57,18
27 : 74,19
28 : 32,3
29 : 43,19
30 : 84,77
31 : 84,77
32 : 7,3
33 : 86,34
35 : 49,35
36 : 43,19
37 : 11,4
38 : 9,19
39 : 15,4
40 : 10,76
41 : 79,41
42 : 81,3
43 : 74,19
44 : 8,44
45 : 10,76
46 : 19,46
47 : 62,34
48 : 47,34
49 : 3,49
50 : 16,41
51 : 63,3
52 : 18,10
53 : 75,34
54 : 77,54
55 : 23,3
56 : 63,3
57 : 34,57
58 : 68,65
59 : 79,41
60 : 36,19
61 : 58,65
62 : 75,34
63 : 65,3
64 : 79,41
65 : 44,65
66 : 56,3
67 : 64,41
68 : 44,65
69 : 27,19
70 : 61,65
71 : 33,65
73 : 78,3
74 : 46,19
75 : 35,75
76 : 10,76
77 : 84,77
78 : 66,3
79 : 41,79
80 : 65,3
81 : 78,3
82 : 81,3
83 : 4,83
84 : 76,84
85 : 72,65
86 : 78,3

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-