2016-04-04 5 views
1

У меня есть таблица данных объемов и общей концентрации. Я хочу ввести значение в ячейку и пропустить таблицу данных и вывести общий объем, необходимый из таблицы данных, чтобы вычислить мою новую смесь.Расчет желаемого значения на основе таблицы данных

Пример таблицы данных:

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

Если это мои данные, и я хочу, чтобы сделать новую партию, которая 8000 объем и 700000 для концентрации, как можно вычислить, какой образец номера смешивать и в каких объемы, чтобы получить новую концентрацию и объем.

+0

Это звучит как то, что вы ищете это скорее алгоритм, чем помощь с конкретным кодом. У вас есть уравнение/формула, которую вы использовали бы для вычисления желаемого ответа? – leowyn

+0

Если вы ищете способ найти решение, надстройка Solver будет намного проще, чем кодирование в VBA. Я бы предложил изучить это. – OpiesDad

ответ

0

Я предполагаю, что формула должна выглядеть следующим образом:

dilution formula

Рассмотрим алгоритм, реализованный с ниже 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 с исходными кодом:

initial data

После этого Worksheet_Change событие уволено, а результаты заселены в столбцы «Будет смешанным» и ячейка «Фактический объем». Любые изменения на листе бумаги дают результаты сразу:

results

Если какой-либо образец нулевой концентрации доступен, то он будет использоваться в первую очередь:

zero concentration sample

+0

@CPowers, я переработал алгоритм для вывода результатов непосредственно на листе, проверьте код. – omegastripes

+0

Ничего себе, это отличное спасибо. Работает очень хорошо, за исключением случаев, когда я должен добавить 20 образцов, я бы хотел отредактировать их, так что максимум всего сказать, что 2-3 образца необходимо объединить, чтобы их можно было смешивать. Как ограничить количество выбранных образцов? –

+0

Или я могу добавить строку вверху, чтобы иметь большой объем, но 0 концентрация, чтобы достичь желаемого общего объема, но не добавлять больше к концентрации. –

Смежные вопросы