正在根据数据计算期望值 table

Calculating desired value based on data table

我有体积和总浓度的数据 table。我想将一个值输入到一个单元格中,循环遍历数据 table 并从数据 table 中输出所需的总体积来计算我的新混合物。

示例数据table:

sample #    Volume  concentration
1            4000.0    250000
2            4000.0    300000
3            4000.0    650000
4            4000.0    2000000

如果这是我的数据,我想制作一个 8000 体积和 700,000 浓度的新批次,我如何计算要混合的样本数量以及获得新浓度和体积的体积。

我假设公式应该如下:

考虑使用以下 VBA 代码实现的算法,将代码放在 Sheet1 模块中:

Option Explicit

Private Type Solution
    Volume As Variant
    Initial As Variant
    Conc As Variant
End Type

Private Sub Worksheet_Change(ByVal Target As Range)

    Dim Samples() As Solution
    Dim ConcTarget As Double
    Dim ConcMin As Double
    Dim ConcMax As Double
    Dim ConcDelta As Double
    Dim ConcDelta1 As Double
    Dim ConcDelta2 As Double
    Dim VolumeTarget As Double
    Dim VolumeTotal As Double
    Dim VolumeMix As Double
    Dim Volume1 As Double
    Dim Volume2 As Double
    Dim Sample1 As Long
    Dim Sample2 As Long
    Dim Sample1Found As Boolean
    Dim Sample2Found As Boolean
    Dim i As Long

    Application.EnableEvents = False

    ' retrieve initial data and targets from the sheet and clear results
    i = 2
    With Sheets("Sheet1")
        Do While .Cells(i, 1) <> ""
            ReDim Preserve Samples(i - 2)
            Samples(i - 2).Volume = .Cells(i, 2).Value
            Samples(i - 2).Initial = Samples(i - 2).Volume
            Samples(i - 2).Conc = .Cells(i, 3).Value
            .Cells(i, 4).Value = ""
            i = i + 1
        Loop
        ConcTarget = .Cells(2, 7).Value
        VolumeTarget = .Cells(2, 6).Value
    End With

    VolumeTotal = 0
    ' begin of iterations
    Do

        ' min and max concentration available
        ConcMax = 0
        ConcMin = 1.7976931348623E+308
        For i = 0 To UBound(Samples)
            If Samples(i).Conc < ConcMin And Samples(i).Volume > 0 Then
                ConcMin = Samples(i).Conc
                Sample1 = i ' lowest concentration sample
            End If
            If Samples(i).Conc > ConcMax And Samples(i).Volume > 0 Then
                ConcMax = Samples(i).Conc
                Sample2 = i ' highest concentration sample
            End If
        Next

        If ConcMin > 0 Then
            ' zero concentration sample isn't available
            ' choose appropriate samples available to mix
            Sample1Found = False
            Sample2Found = False
            For i = UBound(Samples) To 0 Step -1
                If Samples(i).Volume > 0 Then
                    Select Case True
                        Case Samples(i).Conc <= ConcTarget And Samples(i).Conc >= Samples(Sample1).Conc
                            ' closest less concentrate sample
                            Sample1 = i
                            Sample1Found = True
                        Case Samples(i).Conc >= ConcTarget And Samples(i).Conc <= Samples(Sample2).Conc
                            ' closest more concentrate sample
                            Sample2 = i
                            Sample2Found = True
                    End Select
                End If
            Next

            ' check if necessary samples are available
            If Not (Sample1Found And Sample2Found) Then
                Exit Do
            End If
        End If

        ' calculate delta for chosen samples
        ConcDelta = Samples(Sample2).Conc - Samples(Sample1).Conc
        ConcDelta1 = ConcTarget - Samples(Sample1).Conc
        ConcDelta2 = Samples(Sample2).Conc - ConcTarget

        ' calculate volumes
        Volume1 = (VolumeTarget - VolumeTotal) * ConcDelta2 / ConcDelta
        Volume2 = (VolumeTarget - VolumeTotal) * ConcDelta1 / ConcDelta
        VolumeMix = Volume1 + Volume2

        ' check if volumes are enough and reduce to available volume
        Select Case True
            Case Volume1 > Samples(Sample1).Volume ' sample 1 not enough
                Volume1 = Samples(Sample1).Volume
                VolumeMix = Volume1 * ConcDelta / ConcDelta2
                Volume2 = VolumeMix * ConcDelta1 / ConcDelta
                If Volume2 > Samples(Sample2).Volume Then ' sample 2 not enough
                    Volume2 = Samples(Sample2).Volume
                    VolumeMix = Volume2 * ConcDelta / ConcDelta1
                    Volume1 = VolumeMix * ConcDelta2 / ConcDelta
                End If
            Case Volume2 > Samples(Sample2).Volume ' sample 2 not enough
                Volume2 = Samples(Sample2).Volume
                VolumeMix = Volume2 * ConcDelta / ConcDelta1
                Volume1 = VolumeMix * ConcDelta2 / ConcDelta
                If Volume1 > Samples(Sample1).Volume Then ' sample 1 not enough
                    Volume1 = Samples(Sample1).Volume
                    VolumeMix = Volume1 * ConcDelta / ConcDelta2
                    Volume2 = VolumeMix * ConcDelta1 / ConcDelta
                End If
        End Select

        ' change available volumes
        Samples(Sample1).Volume = Samples(Sample1).Volume - Volume1
        Samples(Sample2).Volume = Samples(Sample2).Volume - Volume2

        ' check if target volume has been mixed
        VolumeTotal = VolumeTotal + VolumeMix
        If VolumeTotal = VolumeTarget Then Exit Do

    Loop

    ' results output
    With Sheets("Sheet1")
        For i = 0 To UBound(Samples)
            .Cells(i + 2, 4).Value = Samples(i).Initial - Samples(i).Volume
        Next
        .Cells(2, 5).Value = VolumeTotal
    End With

    Application.EnableEvents = True

End Sub

我使用源数据填充 Sheet1

之后 Worksheet_Change 事件被触发,结果填充在 "To be mixed" 列和 "Actual volume" 单元格中。 sheet 的任何更改都会立即给出结果:

如果有任何零浓度样品可用,那么将首先使用它: