Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/14.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/65.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
VBA基于父项数量乘以子项数量_Vba_Parent Child_Multiplication - Fatal编程技术网

VBA基于父项数量乘以子项数量

VBA基于父项数量乘以子项数量,vba,parent-child,multiplication,Vba,Parent Child,Multiplication,我正在使用一个表示为ITEM_NO的分支层次结构,其中“1.2”是“1”的第二个子级,因为没有进一步的继承(这个“1”是最顶层的父级)。我有一个代码,可以找到子-父关系,并将某个值从父行复制到子行 Sub subgroup() 'Disable screen update Application.ScreenUpdating = False Application.DisplayAlerts = False 'Main function Dim i As Lon

我正在使用一个表示为ITEM_NO的分支层次结构,其中“1.2”是“1”的第二个子级,因为没有进一步的继承(这个“1”是最顶层的父级)。我有一个代码,可以找到子-父关系,并将某个值从父行复制到子行


Sub subgroup()

'Disable screen update

    Application.ScreenUpdating = False
    Application.DisplayAlerts = False

'Main function

    Dim i As Long
    Dim LastRow As Long
    Dim subgroup As String
    Dim parent As String
    
    With Worksheets("BOM")
        LastRow = .Cells(.Rows.Count, 5).End(xlUp).Row
        
        For i = 2 To LastRow
            If i = 2 Then
                subgroup = .Cells(i, 3).Value
                parent = getParent(.Cells(i, 10))
            ElseIf Left(.Cells(i, 10), Len(parent)) <> parent Then
                subgroup = .Cells(i, 3).Value
                parent = getParent(.Cells(i, 10))
            Else
                .Cells(i, 3).Value = subgroup
            End If
        Next i
    End With
    
'Enable screen update

    Application.ScreenUpdating = True
    Application.DisplayAlerts = True
    
End Sub

Function getParent(cell As Range) As String
    If Not InStr(1, cell.Value, ".") Then
        getParent = cell.Value
    Else
        getParent = Split(cell, ".")(0) & "." & Split(cell.Value, ".")(1)
    End If
End Function

子群()
'禁用屏幕更新
Application.ScreenUpdating=False
Application.DisplayAlerts=False
"主要功能",
我想我会坚持多久
最后一排一样长
作为字符串的Dim子组
将父对象设置为字符串
带有工作表(“BOM”)
LastRow=.Cells(.Rows.Count,5).End(xlUp).Row
对于i=2到最后一行
如果i=2,那么
子组=.Cells(i,3).Value
parent=getParent(.Cells(i,10))
ElseIf左(.Cells(i,10),Len(parent))父
子组=.Cells(i,3).Value
parent=getParent(.Cells(i,10))
其他的
.单元格(i,3).值=子组
如果结束
接下来我
以
'启用屏幕更新
Application.ScreenUpdating=True
Application.DisplayAlerts=True
端接头
函数getParent(单元格作为范围)作为字符串
如果不是InStr(1,单元格值“.”),则
getParent=cell.Value
其他的
getParent=Split(cell,“.”(0)和“.”&Split(cell.Value,“.”(1)
如果结束
端函数
现在,我正试图找出如何修改它,使列“I”中的子数量乘以它的父数量,无论子-父级别出现多少次。因此,如果“child 1.2.1”
QTY=1
与“child 1.2”
QTY=2
相乘,现在是“child 1.2.1”
QTY=1*2=2
,我们更高一级,看到“child 1
QTY=3
所以现在是初始值”child 1.2.1“
数量=2*3=6
。我需要对表中的每一行从下到上做这件事,因为它总是按自上而下的顺序排列,而且每一项都是唯一的

下面是一个示例图像:

我用不同的颜色填充了每个传统级别。因此,在本例中,每个黄色行的数量必须与红色行的数量相乘,然后与灰色行相乘。同样,红色行与灰色行相乘


有人能帮帮我吗?

使用K列中的以下公式生成新数量,如下所示:

自下而上的计算

=IFERROR(INDEX(I:I,MATCH(LEFT(J:J,FIND("#",SUBSTITUTE(J:J,".","#",LEN(J:J)-LEN(SUBSTITUTE(J:J,".",""))))-1),J:J,0))*I:I,I:I)
=IFERROR(IF(INDEX(L:L,MATCH(LEFT(J:J,FIND("#",SUBSTITUTE(J:J,".","#",LEN(J:J)-LEN(SUBSTITUTE(J:J,".",""))))-1),J:J,0))="", INDEX(I:I,MATCH(LEFT(J:J,FIND("#",SUBSTITUTE(J:J,".","#",LEN(J:J)-LEN(SUBSTITUTE(J:J,".",""))))-1),J:J,0)),INDEX(L:L,MATCH(LEFT(J:J,FIND("#",SUBSTITUTE(J:J,".","#",LEN(J:J)-LEN(SUBSTITUTE(J:J,".",""))))-1),J:J,0)))*I:I,I:I)
自上而下计算

=IFERROR(INDEX(I:I,MATCH(LEFT(J:J,FIND("#",SUBSTITUTE(J:J,".","#",LEN(J:J)-LEN(SUBSTITUTE(J:J,".",""))))-1),J:J,0))*I:I,I:I)
=IFERROR(IF(INDEX(L:L,MATCH(LEFT(J:J,FIND("#",SUBSTITUTE(J:J,".","#",LEN(J:J)-LEN(SUBSTITUTE(J:J,".",""))))-1),J:J,0))="", INDEX(I:I,MATCH(LEFT(J:J,FIND("#",SUBSTITUTE(J:J,".","#",LEN(J:J)-LEN(SUBSTITUTE(J:J,".",""))))-1),J:J,0)),INDEX(L:L,MATCH(LEFT(J:J,FIND("#",SUBSTITUTE(J:J,".","#",LEN(J:J)-LEN(SUBSTITUTE(J:J,".",""))))-1),J:J,0)))*I:I,I:I)

这个公式有什么作用? 例如
1.5.3.10

  • 左(J:J,FIND(“#”),替换(J:J,”,“#”,LEN(J:J)-LEN(替换(J:J,”,”))-1)

    去掉最后一组,这样您就可以得到
    1.5.3
  • MATCH(…[1]…,J:J,0)
    1.5.3
    与第J列匹配,以获取
    1.5.3
  • 索引(I:I,…[2]…)
    获取通过匹配找到的行号的第I列中的值
    2
  • *I:I
    并将其与当前行第I列的值相乘,因此
    2*2=4
  • IFERROR(…)
    只返回当前行第I列的值。因为对于
    1.5
    ,它将剥离到
    1
    ,并尝试找到它无法找到的内容。因此,如果没有父项进行切割,则保持质量不变
  • 这就是公式技巧。如果您确实需要在VBA中执行此操作,您可以使用相同的方法执行此操作:
    因此,我将把
    I:J
    的数据读入一个数组,使用
    WorksheetFunctions
    进行所有计算,如公式所示,将结果保存在另一个数组中,并将结果数组写回
    I

    Option Explicit
    
    Public Sub TopToBottomCalculation()
        Dim ws As Worksheet 'define worksheet
        Set ws = ThisWorkbook.Worksheets("Sheet1")
        
        Dim LastRow As Long 'find last row with data in column I
        LastRow = ws.Cells(ws.Rows.Count, "I").End(xlUp).Row
        
        Dim ArrQty() As Variant 'read quantity into array
        ArrQty = ws.Range("I2", "I" & LastRow).Value
        
        Dim ArrItm() As Variant 'read item no into array
        ArrItm = ws.Range("J2", "J" & LastRow).Value
        
        Dim iRow As Long
        For iRow = LBound(ArrQty, 1) To UBound(ArrQty, 1)
            Dim ParentItem As String 'get parent item number
            
            Dim LastDotPosition As Long
            LastDotPosition = InStrRev(ArrItm(iRow, 1), ".")
            
            If LastDotPosition > 0 Then 'if no dot was found there is no parent
                ParentItem = Left$(ArrItm(iRow, 1), LastDotPosition - 1)
                
                Dim ParentMatch As Double
                ParentMatch = 0 'initialize because in loop
                On Error Resume Next 'next line throws error if no parent item is found
                ParentMatch = Application.WorksheetFunction.Match(ParentItem, ArrItm, 0)
                On Error GoTo 0 're-enable error reporting
                
                If Not ParentMatch = 0 Then 'if there was a parent item multiplicate current quantity with parent quantity
                    ArrQty(iRow, 1) = ArrQty(iRow, 1) * ArrQty(ParentMatch, 1)
                End If
            End If
        Next iRow
        
        'write array quantity back to cells
        ws.Range("I2").Resize(RowSize:=UBound(ArrQty, 1)).Value = ArrQty
    End Sub
    
    //根据评论编辑

    要能够跳转不存在的父项,例如存在
    1
    1.2.3
    但不存在
    1.2
    ,则即使没有
    1.2
    ,以下代码仍将与
    1
    相乘

    请注意,如果混合使用数字和字符串,则始终存在
    匹配问题。因此,请确保您输入的所有项目编号都是字符串,否则匹配将失败,并且计算错误。因此,如果您将
    1
    作为项目编号,请确保将其作为
    '1
    输入,撇号不会显示,但确保
    1
    是文本而不是数字,以便匹配可以正常工作。

    Option Explicit
    
    Public Sub TopToBottomCalculation()
        Dim ws As Worksheet 'define worksheet
        Set ws = ThisWorkbook.Worksheets("Sheet1")
    
        Dim LastRow As Long 'find last row with data in column I
        LastRow = ws.Cells(ws.Rows.Count, "I").End(xlUp).Row
        
        Dim ArrQty() As Variant 'read quantity into array
        ArrQty = ws.Range("I2", "I" & LastRow).Value
        
        Dim ArrItm() As Variant 'read item no into array
        ArrItm = ws.Range("J2", "J" & LastRow).Value
        
        Dim iRow As Long
        For iRow = LBound(ArrQty, 1) To UBound(ArrQty, 1)
            Dim ParentItem As String     'get parent item number
            
            Dim CurrentItem As String
            CurrentItem = ArrItm(iRow, 1)
            
            Dim LastDotPosition As Long
            LastDotPosition = InStrRev(CurrentItem, ".")
            
            Dim ParentMatch As Double
            ParentMatch = 0 'initialize because in loop
            
            Do While LastDotPosition > 0 And ParentMatch = 0 'loop through parent levels until parent is found or no parent exists
                ParentItem = Left$(CurrentItem, LastDotPosition - 1)
             
                ParentMatch = 0 'initialize because in loop
                On Error Resume Next 'next line throws error if no parent item is found
                ParentMatch = Application.WorksheetFunction.Match(ParentItem, ArrItm, 0)
                On Error GoTo 0 're-enable error reporting
                
                If Not ParentMatch = 0 Then 'if there was a parent item multiplicate current quantity with parent quantity
                    ArrQty(iRow, 1) = ArrQty(iRow, 1) * ArrQty(ParentMatch, 1)
                Else 'if parent item did not match then try to find the next upper level parent item
                    CurrentItem = ParentItem
                    LastDotPosition = InStrRev(CurrentItem, ".")
                End If
                DoEvents
            Loop
        Next iRow
        
        'write array quantity back to cells
        ws.Range("I2").Resize(RowSize:=UBound(ArrQty, 1)).Value = ArrQty
    End Sub
    

    你到底想把乘法的结果放在哪里?这在图片中并不清楚。您能在示例图像中显示所需的结果吗?这样我们就可以看到您希望在该示例中获得的结果了?当然!乘法的结果应该返回到有问题的初始行的数量。在示例图像中,每个黄色行乘以红色,即“当前行*2”,然后乘以结果*1。因此,在这种情况下,每个黄色的数量将是两倍大,红色的数量将是相同的,因为它乘以灰色,即1。你还想让我做一个想要的结果图像吗?请做这个结果。特别是我不明白为什么
    1.5.3.1.1
    1.5.3.1.2
    是黄色的?我认为它们应该是另一种颜色,因为它们比其他黄色深一层?请澄清并制作结果图,以便更好地理解.OPS!你说得对!谢谢你注意到了!我在乘法之前和之后添加了一个图像,那么您是从上到下计算,而不是像您所说的从下到上。@Eduards您可以在VBA中以相同的方式进行计算(请参见我的编辑)。如何做的想法是一样的。@Eduards我编辑了我的问题并添加了自上而下的计算方法。@Eduards请看我的编辑。示例数据非常重要。您的示例可能没有涵盖所有类型的数据。可能存在一个没有点的
    项目编号
    (因此不存在父项)。查看我的编辑,这将忽略那些没有父项的行。@Eduards查看我的添加。如果