variable looping - excel

i am attempting to create a code to help do some design work.
i want my code to be able to read a radius of a circle e.g. 40m
we have rules that say we can use multiples of 12m to achieve this e.g. 12+12+12+12 but this does not satisify the issue so we need to then replace one of those numbers with a smaller number starting at 10m so equation would look like this 12+12+12+10 and if that still doesnt work change a different number so equation will look like this 12+12+10+12 we need this to loop until we can get it to 40m(subject to change could be upwards of 93m just using 40m for simplicity)
is there a way to set up variables that add to each other to get to the desired result but loop through changing the numbers until a desired result is hit.
to add to this the final number can be a a close estimate as long as it is 0.5m long minimum
e.g. if our radius is equal to 41.7 then no whole number will satisfy this so my intention is to have a loop that finds the best close answer and then an additional bit of code that will then adjust the final number
i have no idea where to start so havnt tried much
i expect to be able to input the radius, number of potential numbers to be used aka its not always goign to be 4 different numbers it could be more or less we know roughly how many we need just not the order they need to be in
the output we expect to have the cells on excel filled out with the length per item in a different cell e.g. 12m in one cell , 12m in a different cell, 12m in a different cell and then 4m in a different cell as this will fit our requirements.
if there is a way to loop through numbers until a desired number is hit that would be ideal just not sure how i would write that in code

As others already noted, it's not fully clear what you need.
Anyway, the code below distributes the radius (B1) in the number (B3) of addends that are multiples of the divisor you specify in B2. Until the remainder gets less than the divisor.
Sub distribute()
Dim radius As Integer, divisor As Integer, addends As Integer
Dim times As Integer
Dim i As Integer
radius = Range("B1").Value
divisor = Range("B2").Value
addends = Range("B3").Value
times = WorksheetFunction.Ceiling(radius / divisor / addends, 1)
For i = 1 To addends
If radius > divisor * times Then
Cells(5, i).Value = divisor * times
radius = radius - divisor * times
Else
Cells(5, i).Value = radius
radius = 0
End If
Next
End Sub

Related

New to VBA in Excel. Trying to sum an incremented function

So what I am trying to do is take the difference between two values(x) and (y) to get (n). I then want to run (x) through a formula (n) times incrementing (x) each time. Then I want to output the sum all of those results into a cell. Cant figure out how to do it neatly within one cell like normal, so I've turned to VBA for once.
Here is what I have so far:
Sub Math()
'
'Math
'
Dim i As Integer
i = 0
Do While i < ((E42) - (d42))
cell(h42).Value = ((((d42) + i) ^ 2) * 100) / 3
End Sub
What I'm stuck on is how to get the result of each loop and sum them all together. I expect to have an i value that can range anywhere from 1-100. The only way I can think that would definitely work is messy where i would have a large number of cells in a column set aside that will calculate each of the iterations individually, then sum all of those together.
Alternatively, if theres a way to write a function that can calculate the sum(n) of ((x+n)^2)*100/3 then that would be much nicer but I cant think of how it would be written.
Here is how you can make a function (which can be used directly in worksheet formulas) to form a sum:
Function eval_sum(n As Long, x As Double) As Double
Dim s As Double, i As Long
For i = 0 To n - 1
s = s + (x + i) ^ 2
Next i
eval_sum = s * 100 / 3
End Function
This function evaluates:
100/3 * (x^2 + (x+1)^2 + (x+2)^2 + ... + (x+(n-1))^2)
It wasn't completely clear if this is what you were trying to do. If not, you can tweak the code to fit your needs.
Small point: I used Long rather than Integer. Forget that Integer exists. It is really legacy from the days of limited memory and 16-bit computers. In modern Excel an Integer is stored with 32 bits anyway. You are just risking overflow for no good reason.

Excel VBA / math: count how many groups of n are in a range of numbers

I'm having a bit of a brain freeze, I thought this would be simple but it's not coming to me. I need an equation to calculate the number of groups of 10 in a variable range of variable data. Here's a small example, the real thing has hundreds of numbers with a variable min and max:
Number Rounded number to nearest 10
303.9 300
285 290 - min
443 440
446.8 450
461.1 460 - max
428.83 430
428.545 430
445.835 450
427.215 430
429.97 430
Unique groups of 10
300
290
440
450
460
430
Answer = 6 groups
I don't want to use pivot tables or group functions, I'd rather keep it solely in VBA. Also I don't want to work out the rounded values first and then count the distinct ones because I'd like to use the number to dimension an array, which I'll then populate in a loop. Is there a clever bit of math that can give answer?
I'm not aware of any clever math to do this. You could do this with worksheet formulas:
=SUM(--(FREQUENCY(ROUND(r,dec_places),ROUND(r,dec_places))>0))
where r is the data range and dec_places is the amount of rounding (since you're rounding to the nearest 10s, dec_places = -1).
You could implement this in VBA with something like:
Function CountUniqueRounded(r As Range, dec_places As Double) As Long
' Implement this worksheet formula
' =SUM(--(FREQUENCY(ROUND(r,dec_places),ROUND(r,dec_places))>0))
Dim rAddr As String
Dim rFormula As String
Dim c As Long
' Build up the formula string
rAddr = r.Parent.Name & "!" & r.Address
rFormula = "ROUND(" & rAddr & "," & CStr(dec_places) & ")"
rFormula = "=SUM(--(FREQUENCY(" & rFormula & "," & rFormula & ")>0))"
' Debug.Print rFormula
c = Application.Evaluate(rFormula)
CountUniqueRounded = c
End Function
Hope this helps
I have an Array Formula solution which does not require VBA. Array Formulas take single function which would normally apply only to a single cell, and perform that function over a range of cells, returning an Array of different results (1 for each cell). That Array of results is then collapsed into a single number to give your answer.
Assuming your data is in column A, and goes for less than 1000 rows, this will work:
=SUM(IFERROR(MATCH(10*(ROW(A1:A1000)),ROUND(A1:A1000,-1),0)*0+1,0))
Note that to confirm an Array Formula, you need to press CTRL + SHIFT + ENTER, isntead of just ENTER.
What it does is multiplies 10 by each row from A1 to A1000, and then checks to see if that result can be found when rounding each cell present in A1 to A1000. That is, it checks 10, 20, etc. up to 1000, and tries to find it in a range of your rounded values. Whenever it finds a value, it multiplies the row it was found on by 0, and adds 1. Whenever it doesn't find a value (ie: returns an error), it shows 0. The sum of all matches gives you the number of times each rounded number from 10 - 1000 is found.
Caveat - this will not work if you have numbers > 1000; if such numbers would occur you can easily change all instances of 1,000 to 10,000. Likewise if your data sometimes extends further than row 1000, you will need to increase all instances of 1000 to an appropriate number. If data would vary wildly and you can't estimate size / max limit, then there are ways to automate this, but as the formula is already somewhat complex, I left that as a manual process.

Loop through a combination of numbers

I am trying to think of a way to loop through a number of combinations making sure that I go through each available combination without repeat. Let me explain. I have a set of numbers, for example
20,000
25,000
27,000
29,000
and I would like to alter this set of numbers via a loop and copy the new numbers into a different sheet so that my formulas on that sheet can calculate whatever I need them to calculate. For example, the first couple of iterations might look something like this:
1st
20,000 x 1.001
25,000 x 1
27,000 x 1
29,000 x 1
2nd
20,002 x 1.001
25,000 x 1.001
27,000 x 1
29,000 x 1
The first row of numbers should never exceed the second. So 20,000 should only go as high as 25,000.
I was able to set up a system whereby I set up a matrix and then loop through a random set of combinations using =rand() however this does not ensure I hit every combination and also repeats combinations.
Can anyone explain the math behind this and also how I would use a loop to accomplish my goal?
Thank you!
Try starting with smaller numbers.
See if this works for you.
Sub looper()
'First Array
Dim myArray(9) As Double
For i = 1 To 10
myArray(i - 1) = i
Next i
'Second Array
Dim myOtherArray(9) As Double
For i = 1 To 10
myOtherArray(i - 1) = i
Next i
'Loop through each one
For Each slot In myArray
For Each otherSlot In myOtherArray
Debug.Print (slot & " * " & otherSlot & " = " & slot * otherSlot)
Next otherSlot
Next slot
End Sub
GD user1813558,
Your question contains too little detail and is too broadly scoped to be able to provide a accurate answer.
Are your numbers arbitrary (i.e. the ones you provided are 'just'
samples) or will they be fixed as per your indicated numbers ?
Will there always be only 4 numbers ?
Is the distribution of your startnumbers (i.e. their difference
value) always as per your indication 0, +5000, +2000, +2000
Will the results of all 'loops' (or iterations) need to be copied to
a different sheet ? (i.e looping from 20.000 to 25.000 by increments
of 1.001 would require about 223 iterations, and subsequently sheets,
before the result starts exceeding 25.000 ?)
Does a new sheet need to be created for each iteration result or are they
existent or will the result be copied to the same sheet for every iteration ?
In short, please provide a more accurate question.

How to get excel to display a certain number of significant figures?

I am using excel and i want to display a value to a certain number of significant figures.
I tried using the following equation
=ROUND(value,sigfigs-1-INT(LOG10(ABS(value))))
with value replaced by the number I am using and sigfigs replaced with the number of significant figures I want.
This formula works sometimes, but other times it doesn't.
For instance, the value 18.036, will change to 18, which has 2 significant figures. The way around this is to change the source formatting to retain 1 decimal place. But that can introduce an extra significant figure. For instance, if the result was 182 and then the decimal place made it change to 182.0, now I would have 4 sig figs instead of 3.
How do I get excel to set the number of sig figs for me so I don't have to figure it out manually?
The formula (A2 contains the value and B2 sigfigs)
=ROUND(A2/10^(INT(LOG10(A2))+1),B2)*10^(INT(LOG10(A2))+1)
may give you the number you want, say, in C2. But if the last digit is zero, then it will not be shown with a General format. You have then to apply a number format specific for that combination (value,sigfigs), and that is via VBA. The following should work. You have to pass three parameters (val,sigd,trg), trg is the target cell to format, where you already have the number you want.
Sub fmt(val As Range, sigd As Range, trg As Range)
Dim fmtstr As String, fmtstrfrac As String
Dim nint As Integer, nfrac As Integer
nint = Int(Log(val) / Log(10)) + 1
nfrac = sigd - nint
If (sigd - nint) > 0 Then
'fmtstrfrac = "." & WorksheetFunction.Rept("0", nfrac)
fmtstrfrac = "." & String(nfrac, "0")
Else
fmtstrfrac = ""
End If
'fmtstr = WorksheetFunction.Rept("0", nint) & fmtstrfrac
fmtstr = String(nint, "0") & fmtstrfrac
trg.NumberFormat = fmtstr
End Sub
If you don't mind having a string instead of a number, then you can get the format string (in, say, D2) as
=REPT("0",INT(LOG10(A2))+1)&IF(B2-(INT(LOG10(A2))+1)>0,"."&REPT("0",B2-(INT(LOG10(A2))+1)),"")
(this replicates the VBA code) and then use (in, say, E2)
=TEXT(C2,D2).
where cell C2 still has the formula above. You may use cell E2 for visualization purposes, and the number obtained in C2 for other math, if needed.
WARNING: crazy-long excel formula ahead
I was also looking to work with significant figures and I was unable to use VBA as the spreadsheets can't support them. I went to this question/answer and many other sites but all the answers don't seem to deal with all numbers all the time. I was interested in the accepted answer and it got close but as soon as my numbers were < 0.1 I got a #value! error. I'm sure I could have fixed it but I was already down a path and just pressed on.
Problem:
I needed to report a variable number of significant figures in positive and negative mode with numbers from 10^-5 to 10^5. Also, according to the client (and to purple math), if a value of 100 was supplied and was accurate to +/- 1 and we wish to present with 3 sig figs the answer should be '100.' so I included that as well.
Solution:
My solution is for an excel formula that returns the text value with required significant figures for positive and negative numbers.
It's long, but appears to generate the correct results according to my testing (outlined below) regardless of number and significant figures requested. I'm sure it can be simplified but that isn't currently in scope. If anyone wants to suggest a simplification, please leave me a comment!
=TEXT(IF(A1<0,"-","")&LEFT(TEXT(ABS(A1),"0."&REPT("0",sigfigs-1)&"E+00"),sigfigs+1)*10^FLOOR(LOG10(TEXT(ABS(A1),"0."&REPT("0",sigfigs-1)&"E+00")),1),(""&(IF(OR(AND(FLOOR(LOG10(TEXT(ABS(A1),"0."&REPT("0",sigfigs-1)&"E+00")),1)+1=sigfigs,RIGHT(LEFT(TEXT(ABS(A1),"0."&REPT("0",sigfigs-1)&"E+00"),sigfigs+1)*10^FLOOR(LOG10(TEXT(ABS(A1),"0."&REPT("0",sigfigs-1)&"E+00")),1),1)="0"),LOG10(TEXT(ABS(A1),"0."&REPT("0",sigfigs-1)&"E+00"))<=sigfigs-1),"0.","#")&REPT("0",IF(sigfigs-1-(FLOOR(LOG10(TEXT(ABS(A1),"0."&REPT("0",sigfigs-1)&"E+00")),1))>0,sigfigs-1-(FLOOR(LOG10(TEXT(ABS(A1),"0."&REPT("0",sigfigs-1)&"E+00")),1)),0)))))
Note: I have a named range called "sigfigs" and my numbers start in cell A1
Test Results:
I've tested it against the wikipedia list of examples and my own examples so far in positive and negative. I've also tested with a few values that gave me issues early on and all seem to produce the correct results.
I've also tested with a few values that gave me issues early on and all seem to produce the correct results now.
3 Sig Figs Test
99.99 -> 100.
99.9 -> 99.9
100 -> 100.
101 -> 101
Notes:
Treating Negative Numbers
To Treat Negative Numbers, I have included a concatenation with a negative sign if less than 0 and use the absolute value for all other work.
Method of construction:
It was initially divided into about 6 columns in excel that performed the various steps and at the end I merged all of the steps into one formula above.
Use scientific notation, say if you have 180000 and you need 4 sigfigs the only way is to type as 1.800x10^5
I added to your formula so it also automatically displays the correct number of decimal places. In the formula below, replace the digit "2" with the number of decimal places that you want, which means you would need to make four replacements. Here is the updated formula:
=TEXT(ROUND(A1,2-1-INT(LOG10(ABS(A1)))),"0"&IF(INT(LOG10(ABS(ROUND(A1,2-1-INT(LOG10(ABS(A1)))))))<1,"."&REPT("0",2-1-INT(LOG10(ABS(ROUND(A1,2-1-INT(LOG10(ABS(A1)))))))),""))
For example, if cell A1 had the value =1/3000, which is 0.000333333.., the above formula as-written outputs 0.00033.
This is an old question, but I've modified sancho.s' VBA code so that it's a function that takes two arguments: 1) the number you want to display with appropriate sig figs (val), and 2) the number of sig figs (sigd). You can save this as an add-in function in excel for use as a normal function:
Public Function sigFig(val As Range, sigd As Range)
Dim nint As Integer
Dim nfrac As Integer
Dim raisedPower As Double
Dim roundVal As Double
Dim fmtstr As String
Dim fmtstrfrac As String
nint = Int(Log(val) / Log(10)) + 1
nfrac = sigd - nint
raisedPower = 10 ^ (nint)
roundVal = Round(val / raisedPower, sigd) * raisedPower
If (sigd - nint) > 0 Then
fmtstrfrac = "." & String(nfrac, "0")
Else
fmtstrfrac = ""
End If
If nint <= 0 Then
fmtstr = String(1, "0") & fmtstrfrac
Else
fmtstr = String(nint, "0") & fmtstrfrac
End If
sigFig = Format(roundVal, fmtstr)
End Function
It seems to work in all the use cases I've tried so far.
Rounding to significant digits is one thing... addressed above. Formatting to a specific number of digits is another... and I'll post it here for those of you trying to do what I was and ended up here (as I will likely do again in the future)...
Example to display four digits:
.
Use Home > Styles > Conditional Formatting
New Rule > Format only cells that contain
Cell Value > between > -10 > 10 > Format Number 3 decimal places
New Rule > Format only cells that contain
Cell Value > between > -100 > 100 > Format Number 2 decimal places
New Rule > Format only cells that contain
Cell Value > between > -1000 > 1000 > Format Number 1 decimal place
New Rule > Format only cells that contain
Cell Value > not between > -1000 > 1000 > Format Number 0 decimal places
.
Be sure these are in this order and check all of the "Stop If True" boxes.
The formula below works fine. The number of significant figures is set in the first text formula. 0.00 and 4 for 3sf, 0.0 and 3 for 2sf, 0.0000 and 6 for 5sf, etc.
=(LEFT((TEXT(A1,"0.00E+000")),4))*POWER(10,
(RIGHT((TEXT(A1,"0.00E+000")),4)))
The formula is valid for E+/-999, if you have a number beyond this increase the number of the last three zeros, and change the second 4 to the number of zeros +1.
Note that the values displayed are rounded to the significant figures, and should by used for display/output only. If you are doing further calcs, use the original value in A1 to avoid propagating minor errors.
As a very simple display measure, without having to use the rounding function, you can simply change the format of the number and remove 3 significant figures by adding a decimal point after the number.
I.e. #,###. would show the numbers in thousands. #,###.. shows the numbers in millions.
Hope this helps
You could try custom formatting instead.
Here's a crash course: https://support.office.com/en-nz/article/Create-a-custom-number-format-78f2a361-936b-4c03-8772-09fab54be7f4?ui=en-US&rs=en-NZ&ad=NZ.
For three significant figures, I type this in the custom type box:
[>100]##.0;[<=100]#,##0
You could try
=ROUND(value,sigfigs-(1+INT(LOG10(ABS(value)))))
value :: The number you wish to round.
sigfigs :: The number of significant figures you want to round to.

Need to calculate a formula

I need some math help, or some excel help if that works better. I have a set of data points and I need to calculate the intermediate data. The table below are the known data points, what I need to know is if I enter 1200 ft, what MEG is available.
FOOTAGE MEG
1000 19.3
2000 20.66
3000 21.328
4000 21.398
5000 20.976
6000 20.155
7000 19.023
8000 17.658
9000 16.133
10,000 14.513
11,000 12.854
12,000 11.208
13,000 9.617
14,000 8.117
15,000 6.736
16,000 5.493
17,000 4.411
18,000 3.487
19,000 2.724
20,000 2.114
I have entered these into excel and proceded to find a formula that their chart believes to be the answer to my questions. The formula they give is
y = 8E-12x3 - 3E-07x2 + 0.0018x + 18.218
This actually gets me really good results for anything under 12k feet. After that the results stray further and further from accurate until I start getting negative numbers after 18k feet.
I tried entering more orders for it to calculate against, but that just made things worse.
Would I be better off splitting the chart in 2 (>10k ft and <10k ft) and using 2 formulas, or is there a good solution available using the whole chart?
Precision is tremendously important. In fact, there are several serious problems here with what you have done.
Mere use of coefficients with a single digit of precision will cause terrible problems. Remember that x is as large as 20000. Cubing a number of that size will be a huge number. Now, multiply it by a number on the order of 8e-12, and what do you get?
Oh, by the way, the actual value of those coefficients should be closer to
[8.38044124105504e-12 -2.95337111670131e-07 0.00176948515975282 18.2176584107327]
So does this make a difference?
8e-12*20000^3
ans =
64
8.38044124105504e-12*20000^3
ans =
67.0435299284403
It DOES make a difference, a serious one.
You MIGHT choose to use simple linear interpolation, but the cubic is a bit smoother. Beware extrapolation, as a cubic will do strange things if you try it. In fact though, the cubic polynomial has a significant amount of lack of fit. You can do significantly better using a 4th order polynomial, as long as you are careful to scale the independent variable (footage) by dividing by 10000.
a4 = -3.02325078929022
a3 = 21.0780945560741
a2 = -46.9692303618201
a1 = 26.3111163470058
a0 = 17.1162276831784
MEG = a0 + a1*footage/10000 + a2*(footage/10000)^2 +
a3*(footage/10000)^3 + a4*(footage/10000)^4
Note the importance of scaling by 10000 (or at least a number that is chosen to transform your numbers so they are on the order of 1 or so.)
I'd not go much past that point though in terms of increasing the order of the fit.
Can I suggest you use a small VBA script, which uses linear interpolation to pull out a value from your list:
Public Function Linterp(Tbl As Range, x As Double) As Variant
' linear interpolator / extrapolator
' Tbl is a two-column range containing known x, known y, sorted x ascending
Dim nRow As Long
Dim iLo As Long, iHi As Long
nRow = Tbl.Rows.Count
If nRow < 2 Or Tbl.Columns.Count <> 2 Then
Linterp = CVErr(xlErrValue)
Exit Function '-------------------------------------------------------->
End If
If x < Tbl(1, 1) Then ' x < xmin, extrapolate from first two entries
iLo = 1
iHi = 2
ElseIf x > Tbl(nRow, 1) Then ' x > xmax, extrapolate from last two entries
iLo = nRow - 1
iHi = nRow
Else
iLo = Application.Match(x, Application.Index(Tbl, 0, 1), 1)
If Tbl(iLo, 1) = x Then ' x is exact from table
Linterp = Tbl(iLo, 2)
Exit Function '---------------------------------------------------->
Else ' x is between tabulated values, interpolate
iHi = iLo + 1
End If
End If
Linterp = Tbl(iLo, 2) + (Tbl(iHi, 2) - Tbl(iLo, 2)) * (x - Tbl(iLo, 1)) / (Tbl(iHi, 1) - Tbl(iLo, 1))
End Function
You call this from your sheet with something like:
=Linterp(A1:b10, 1200)
You can easily tweak the code to adjust how you want values outside of the range to be handled.
On a slightly different note, you may also be interested in this http://www.codecogs.com/excel_render which can draw out your equations.

Resources