0

As painful as it sounds, I've been tasked to implement a spreadsheet to calculate drug absorption and elimination half-life. I actually use LibreOffice Calc, but a solution tested in Excel would also help me (as it'll probably be portable, anyway).

My spreadsheet currently looks like this:

enter image description here

It must account for multiple dose intakes (i.e. arbitrary new entries in column D). As an example, the person who's going to use this spreadsheet needs to take a new 50mg dose of the drug every 56 hours.

In order to write a working formula on column C, I followed many steps:
(all examples are for C3; C2 is manually set to 0)

  1. = ( C2 * 0,5 ^ ( (B3 - B2) / $H$3 ) ) + D2 * J$2 - this does take into consideration multiple dose intakes, but does not account for absorption time. Instead, it returns 50 on C3 (after 8 hours), 48.577 on C4 (16 hours), (...) and 25.000 on C27 (192 hours, or 1 half-life), etc. In other words, the drug concentration on the blood rises immediatelly. Instead, it should rise linearly, according to 'Time to Cmax' in H2.

  2. = IFERROR( ( ( INDEX( $D$2:$D2; MATCH(1E+306; $D$2:$D2; 1) ) * J$2 ) * MIN( ( B3 - ( INDEX( $B$2:$B2; MATCH(1E+306; $D$2:$D2; 1) ) ) ) / $H$2; 1 ) ); 0 ) - this calculates the total absorption over time, it rises linearly until reaching 50 in C16 (112 hours) and stays there afterwards. It is different than the previous formula, as this one finds the last value entered on column D (with a combination of INDEX and MATCH). But, because of that, it no longer accounts for multiple intakes - only the last one.

  3. = IFERROR( ( ( ( INDEX( $D$2:$D2; MATCH(1E+306; $D$2:$D2; 1) ) * J$2 ) * MIN( ( B3 - ( INDEX( $B$2:$B2; MATCH(1E+306; $D$2:$D2; 1) ) ) ) / $H$2; 1 ) ) - ( ( INDEX( $D$2:$D2; MATCH(1E+306; $D$2:$D2; 1) ) * J$2 ) * MIN( ( B2 - ( INDEX( $B$2:$B2; MATCH(1E+306; $D$2:$D2; 1) ) ) ) / $H$2; 1 ) ) ); 0 ) - this returns the amount of the drug that was absorbed over the last 8-hour (1 row) period. I.e., C3 is 3.704, C4 is also 3.704, (...) C15 (104 hours) is also 3.704, while C16 (112 hours) is 1.852 and C17 and below are 0 (assuming there is no other dose intake other than that in D2). It has the same shortcoming as the previous formula.

  4. = ( C2 * 0,5 ^ ( (B3 - B2) / $H$3 ) ) + IFERROR( ( ( ( INDEX( $D$2:$D2; MATCH(1E+306; $D$2:$D2; 1) ) * J$2 ) * MIN( ( B3 - ( INDEX( $B$2:$B2; MATCH(1E+306; $D$2:$D2; 1) ) ) ) / $H$2; 1 ) ) - ( ( INDEX( $D$2:$D2; MATCH(1E+306; $D$2:$D2; 1) ) * J$2 ) * MIN( ( B2 - ( INDEX( $B$2:$B2; MATCH(1E+306; $D$2:$D2; 1) ) ) ) / $H$2; 1 ) ) ); 0 ) - this is was my current state-of-the-art formula. It accounts for both the linear absorption and the logarithmic elimination of the amount absorbed.

  5. 2019-10-11 update: I came up with a performance improvement to step 3 above, in the form of: = IFERROR( ( ( IF( ( B3 - INDEX( $B$2:$B2; MATCH(1E+306; $D$2:$D2; 1) ) ) <= H$2; (B3 - B2); IF( ( ( B3 - INDEX( $B$2:$B2; MATCH(1E+306; $D$2:$D2; 1) ) ) - H$2 ) < (B3 - B2); ( ( B3 - INDEX( $B$2:$B2; MATCH(1E+306; $D$2:$D2; 1) ) ) - H$2 ); 0 ) ) * INDEX( $D$2:$D2; MATCH(1E+306; $D$2:$D2; 1) ) ) / H$2 ); 0 ).

    The updated, complete formula and current state-of-the art, as seen in the screenshot above, is, then: = ( C2 * 0,5 ^ ( (B3 - B2) / $H$3 ) ) + IFERROR( ( ( IF( ( B3 - INDEX( $B$2:$B2; MATCH(1E+306; $D$2:$D2; 1) ) ) <= H$2; (B3 - B2); IF( ( ( B3 - INDEX( $B$2:$B2; MATCH(1E+306; $D$2:$D2; 1) ) ) - H$2 ) < (B3 - B2); ( ( B3 - INDEX( $B$2:$B2; MATCH(1E+306; $D$2:$D2; 1) ) ) - H$2 ); 0 ) ) * INDEX( $D$2:$D2; MATCH(1E+306; $D$2:$D2; 1) ) ) / H$2 ); 0 ).

However, this formula still does not account for subsequent dose intakes, not correctly anyway. I.e. if I type in a new value of 50 in cell D9, the value in cell C10 should increase, but it does not.
After giving it much thought and looking for help elsewhere, I still don't really know how it can be made so.

Can anyone help?


As additional context, the drug in this example is testosterone cypionate (TC), is administered as intramuscular injection, and 'T / TC ratio' refers to the ratio of testosterone (T) that is present on TC, and I don't really know if the ratio is actually 1. 'Time to Cmax' is the amount of time it takes for the drug to reach maximum concentration on the blood.

I was told the absorption might not be entirely linear, and the drug might not be 100% absorbed when Cmax is reached, meaning some of it will continue to be absorbed after that; nevertheless, I'm allowed to assume it is linear and 100% absorbed at Cmax, as that is a good enough approximation for the purposes of the person who is going to use the spreadsheet.

I'm putting the spreadsheet on Google Drive to make it easier for others to assist me.

Thanks.

Marc.2377
  • 7,807
  • 7
  • 51
  • 95
  • Don´t need to use 1E+306. There is something wrong with your formula as ` ( ( INDEX( $D$2:$D3; MATCH(1E+306; $D$2:$D3; 1) ) * J$2 ) * MIN( ( B2 - ( INDEX( $B$2:$B3; MATCH(1E+306; $D$2:$D3; 1) ) ) ) / $H$2; 1 ) ) ` will be always `Intake x Ratio * 0`. It will be more useful if you can bring the formula you need to use and which values should be considered. It seems that this formula is not working as you are expecting – David García Bodego Oct 05 '19 at 07:27
  • 1
    According to your first step, you want the time to rise linearly with the "Time Cmax in cell H2" but that cell is not included in that calculation... – Solar Mike Oct 05 '19 at 10:08
  • @SolarMike It is - I refer to it as `$H$2`. Please double-check – Marc.2377 Oct 05 '19 at 18:37
  • @DavidGarcíaBodego Ah, creating a new column for every new dose intake. I considered that possibility, but found it does not scale well. For example, if I want to use a variation of that spreadsheet to plot the concentration chart for another drug, and a new dose is taken every 8 hours during 6 months. It'll be too unpractical to use. – Marc.2377 Oct 05 '19 at 19:03
  • I have double checked, H2 is not there, but H3 (as $H$3 is...). see = ( C2 * 0,5 ^ ( (B3 - B2) / $H$3 ) ) + D2 * J$2 – Solar Mike Oct 05 '19 at 20:08
  • @SolarMike well, you are focusing on the first iteration of my formula, which indeed does not take the rise time into consideration (I even said so explicitly). But check my latest modifications to the formula. [It is there](https://imgur.com/a/cRztVLv). – Marc.2377 Oct 05 '19 at 21:41
  • @DavidGarcíaBodego Can you clarify on the first part of your comment? The second part is wrong btw. That part of the formula you pasted is equivalent to `( ( D$2 * J$2 ) * MIN( ( B2 - B$2 ) / $H$2; 1 ) )`. You can check its output to be sure. – Marc.2377 Oct 10 '19 at 06:53
  • That is why...`B2-B$2` will always be zero, so the minimum will be zero, so you will get always zero. Anyway, regarding 1E+306 it is not needed, you just need a big value. Above 1E+16 you will get trunc errors, so why to use 1E+306? – David García Bodego Oct 10 '19 at 08:26
  • @DavidGarcíaBodego Thanks for clarifying, I didn't know about that. I got the formula to get the last non-empty entry from [this answer](https://stackoverflow.com/a/37185137/3258851). Regarding the other matter: note that the portion of the formula we are discussing is part of a subtraction, specifically, it is a subtrahend. It corresponds to the amount of the drug that was already absorbed on all previous cells up to the current one (but not including it). It is indeed supposed to be `0` on cell C3, but is `3.704` on C4, `7.407` on C5 and so on. – Marc.2377 Oct 10 '19 at 22:25
  • Noted. With VBA it will be easier. Did you think on it? – David García Bodego Oct 11 '19 at 05:07
  • @DavidGarcíaBodego yes, but not too much (so far). Will have to do more research, because I'm quite clueless when it comes to VBA. – Marc.2377 Oct 11 '19 at 05:11
  • 1
    Today I am on leave. I will try to take a look tomorrow to generate the code according to your original description. – David García Bodego Oct 11 '19 at 05:14
  • @DavidGarcíaBodego Oh, much appreciated! See ya. – Marc.2377 Oct 11 '19 at 06:01

1 Answers1

0

Try this one:

First of all, as there is no way to declare a possible neverending funtion, just make the calculation for 1 mg until the concentration get extinguish.

Keeping that one in one column (I place in column J), you just need to make a loop.

Public Function Concent(Time_Origin As Long)
    Dim Cycle As Long
    Dim i As Long
    Dim j As Long
    Dim Items(10000) As Long
    Dim Intake(10000) As Long
    Dim Concent_1mg(2152) As Double
    
    j = 0
    Cycle = Time_Origin / 8 + 7
    
    For i = 6 To Cycle
        If Cells(i, 4) <> "" Then
            Items(j + 1) = i
            Intake(j + 1) = Cells(i, 4).Value2
            j = j + 1
        End If
    Next
    
    For i = 1 To 2147
        Concent_1mg(i) = Cells(i + 5, 10).Value2
    Next
    
    For i = 1 To j
        Concent = Concent + Intake(i) * Concent_1mg(Cycle - Items(i))
    Next i
End Function

Once this, it is just a matter to call this function that will calculate the concentration with the time since origin.

Hope it helps

David García Bodego
  • 1,058
  • 3
  • 13
  • 21
  • Sorry for taking too long to get back. I did not test, I don't know how to call the function actually (or to write it). Accepting since you made the effort and says it works. Can you upload the example again? It seems to be no longer available. – Marc.2377 Jun 29 '20 at 09:29
  • Ok, figured it out. Having to do some adaptations for it to work on LibreOffice, learning the API along the way. – Marc.2377 Jun 29 '20 at 11:51