Using named cells in a VBA function - function

I have a worksheet where I have defined names for certain cells. These cells will be used in the function and I am calling them using their names.
However, I get 0 as a return of the function when I call it with Excel, as if the names were not linked or had a 0 value.
Below is the code I wrote. "Sum_Len_1", "L_W_2" ans "L_W_1" are the names I gave to the source cells.
Function min_w(depth)
If depth < Sum_Len_1 Then
min_w = L_W_1 * 0.868 * depth / 1000
Else
min_w = L_W_1 * 0.868 * Sum_Len_1 / 1000 + L_W_2 * 0.868 * (depth - Sum_Len_1) / 1000
End If
End Function
How can I solve the problem?

If you just write min_w = L_W_1 * 0.868 * depth / 1000 vba thinks L_W_1 it's variable (of the type variant with value=0).
You have to do it like this Range("L_W_1").Value to reference the named cell.
It should work if you change it to:
Function min_w(depth As Long)
If depth < Range("SUM_LEN_1").Value Then
min_w = Range("L_W_1").Value * 0.868 * depth / 1000
Else
min_w = Range("L_W_1").Value * 0.868 * Range("SUM_LEN_1").Value / 1000 + Range("L_W_2").Value * 0.868 * (depth - Range("SUM_LEN_1").Value) / 1000
End If
End Function

You can just put them in brackets to mark them as a range:
[Sum_Len_1].Value, [L_W_2].Value and [L_W_1].Value

Related

Apache POI rate formula not working if data is big

Rate Formula is not working as expected for big values...
RATE(85.77534246575343, -1589.0, -18664.0, 5855586.0) in physical file it returns 0.05819488005
if the same formula we tried to set through POI returns 0.009056339275922086..
Even we tried to save the excel and open same 0.009056339275922086 is returned..
Code used to set in POI :
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFRow row = sheet.createRow(1);
XSSFCell cell = row.createCell(1);
cell.setCellType(CellType.NUMERIC);
cell.setCellFormula("RATE(85.77534246575343, -1589.0, -18664.0, 5855586.0)");
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
evaluator.evaluateInCell(cell);
cell.getNumericCellValue();
The Rate function of apache poi states that it "// find root by Newton secant method". That's nonsense since Secant method is only a Quasi-Newton method. And "If the initial values are not close enough to the root, then there is no guarantee that the secant method converges.".
So the default guess of 0.1 seems not "close enough" and so if we are using cell.setCellFormula("RATE(85.77534246575343, -1589.0, -18664.0, 5855586.0, 0, 0.06)"); - note the explicit setting of type and guess properties and having the guess property "close enough" to the result of 0.05819488005- then the formula evaluates properly.
If apache poi really would use Newton's method, then the function would evaluate properly also using the default guess of 0.1. The disadvantage of Newton's method is that it requires the evaluation of both f and its derivative f′ at every step. So it may be slower than the Secant method in some cases.
Example:
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
public class ExcelRATEFunction {
private static double calculateRateNewton(double nper, double pmt, double pv, double fv, double type, double guess) {
int FINANCIAL_MAX_ITERATIONS = 20;
double FINANCIAL_PRECISION = 0.0000001;
double y, y1, xN = 0, f = 0, i = 0;
double rate = guess;
//find root by Newtons method (https://en.wikipedia.org/wiki/Newton%27s_method), not secant method!
//Formula see: https://wiki.openoffice.org/wiki/Documentation/How_Tos/Calc:_Derivation_of_Financial_Formulas#PV.2C_FV.2C_PMT.2C_NPER.2C_RATE
f = Math.pow(1 + rate, nper);
y = pv * f + pmt * ((f - 1) / rate) * (1 + rate * type) + fv;
//first derivative:
//y1 = (pmt * nper * type * Math.pow(rate,2) * f - pmt * f - pmt * rate * f + pmt * nper * rate * f + pmt * rate + pmt + nper * pv * Math.pow(rate,2) * f) / (Math.pow(rate,2) * (rate+1));
y1 = (f * ((pmt * nper * type + nper * pv) * Math.pow(rate,2) + (pmt * nper - pmt) * rate - pmt) + pmt * rate + pmt) / (Math.pow(rate,3) + Math.pow(rate,2));
xN = rate - y/y1;
while ((Math.abs(rate - xN) > FINANCIAL_PRECISION) && (i < FINANCIAL_MAX_ITERATIONS)) {
rate = xN;
f = Math.pow(1 + rate, nper);
y = pv * f + pmt * ((f - 1) / rate) * (1 + rate * type) + fv;
//first derivative:
//y1 = (pmt * nper * type * Math.pow(rate,2) * f - pmt * f - pmt * rate * f + pmt * nper * rate * f + pmt * rate + pmt + nper * pv * Math.pow(rate,2) * f) / (Math.pow(rate,2) * (rate+1));
y1 = (f * ((pmt * nper * type + nper * pv) * Math.pow(rate,2) + (pmt * nper - pmt) * rate - pmt) + pmt * rate + pmt) / (Math.pow(rate,3) + Math.pow(rate,2));
xN = rate - y/y1;
++i;
System.out.println(rate+", "+xN+", "+y+", "+y1);
}
rate = xN;
return rate;
}
public static void main(String[] args) throws Exception {
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet();
Row row = sheet.createRow(1);
Cell cell = row.createCell(1);
cell.setCellFormula("RATE(85.77534246575343, -1589.0, -18664.0, 5855586.0, 0, 0.06)");
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
CellType celltype = evaluator.evaluateFormulaCellEnum(cell);
double value = 0.0;
if (celltype == CellType.NUMERIC) {
value = cell.getNumericCellValue();
System.out.println(value);
}
workbook.setForceFormulaRecalculation(true);
value = calculateRateNewton(85.77534246575343, -1589.0, -18664.0, 5855586.0, 0, 0.1);
System.out.println(value);
workbook.write(new FileOutputStream("ExcelRATEFunction.xlsx"));
workbook.close();
}
}

Octave variable definition error

I'm trying to generate Blackman-Harris window coefficients in Octave. I have declared a function in a .m file like so:
function result = BlackmanHarris(window_size)
a0 = 0.35875
a1 = 0.48829
a2 = 0.14128
a3 = 0.01168
result = [0:window_size - 1];
if(nargin != 1)
print_usage("BlackmanHarris(int window_size)");
endif
if(isinteger(window_size))
for n = 0:window_size - 1
result(n) = a0 - (a1 * cos((2 * pi * n)/(window_size - 1))) + (a2 * cos((4 * pi * n)/(window_size - 1))) - (a3 * cos((6 * pi * n)/(window_size - 1)));
endfor
else
error("BlackmanHarris: Expecting integer argument.");
endif
endfunction
When I attempt to run this, I get the error:
>> window = BlackmanHarris(window_size);
error: 'a0' undefined near line 15 column 16
error: called from
BlackmanHarris at line 15 column 14
I have tried declaring the variables as 'global' and 'persistent', nether of which solve this issue. I'm sure I'm just doing something slightly wrong, but Google has yielded little help on this.
Thanks in advance.
As #Sardar_Usama said, I was attempting to access element 0 of the result array, which of course will not work.
Changing that to n+1 fixed the issue.

Why the result is not the same?

I don't understand why the result of:
4 / 3 * Math.PI * Math.pow(radio,3)
is different of:
(4 * Math.PI * Math.pow(radio,3)) / 3
I use this in a program to calculate the sphere's volume.
First, lets insert some extra brackets ... for illustrative purposes:
This code:
4 / 3 * Math.PI * Math.pow(radio,3)
is equivalent to
((4 / 3) * Math.PI) * Math.pow(radio,3)
In words ... first we divide 4 by 3, then we multiply it by Pi, then we multiply by radio to the power of 3.
Now lets look at the first sub-expression (4 / 3). Since the operands are both integers, this is an integer division, and it produces an integer answer. And that answer is 1. The answer you really need there is 1.33333... but that isn't an integer.
How to fix it? Changing either or both of the numbers to double literals will cause the division to be treated as a floating point (double) division, and that will you the best possible approximation to 4 thirds.
4.0 / 3.0 * Math.PI * Math.pow(radio,3)
First of all check for precedence of operator.
In your case precedence order is :
() > * > / (Note : this precedence is for C operators)
So for above operations result must be same for both cases.
Let's take
Case 1 :
4 / 3 * Math.PI * Math.pow(radio,3)
Here Math.PI = 3.14
Suppose Math.pow(radio , 3) = 10
In this scenario first multiplication will happen
result = 4*3.14*10 = 125.60000000000001
125.600/3 = 41.86666666666667
Case 2 :
'(4 * Math.PI * Math.pow(radio,3)) / 3'
Here first it will calculate () block then / operator
i.e (4 * Math.PI * Math.pow(radio,3))
Here again result will be same as before

MySQL convert legacy decimal to milliseconds

I am working with some legacy tables that represent time as a decimal representating time like this:
74447.548 = 7:44:47.548
I am moving this to a table where time is stored as (int) milliseconds. I want to create a function for this conversion.. The following works, but is there a more efficient way??
CREATE FUNCTION `test`.`decimalToMilli` (bigTime decimal)
RETURNS INTEGER
BEGIN
return (floor(mod(bigTime,floor(bigTime))*1000) -- milliseconds
+ (floor(bigTime) MOD 100) * 1000 -- seconds
+ ((((floor(bigTime) - floor(bigTime) MOD 100) MOD 10000))/100) * 1000*60 -- minutes
+ ((((floor(bigTime) - floor(bigTime) MOD 10000) MOD 1000000))/10000) * 1000*60*60 --hrs
);
END
Suggestions for a better way?
What about this?
CREATE FUNCTION `test`.`decimalToMilli` (bigTime decimal)
RETURNS INTEGER
BEGIN
return ((bigTime * 1000) MOD 100000 -- seconds and milliseconds
+ (floor(bigTime / 100) MOD 100) * 60000 --minutes
+ (floor(bigTime / 10000)) * 3600000 -- hours
);
END

Decimals to one decimal place in as3?

I randomly generate a decimal using:
private function randomNumber(min:Number, max:Number):Number
{
return Math.random() * (max - min) + min;
}
It comes out with something like 1.34235346435.
How can I convert it so that its 1.3.
You can round to one decimal place like this;
var newValue:Number = Math.round(oldValue * 10)/10
Or an arbitrary number of decimal places like this:
function round2(num:Number, decimals:int):Number
{
var m:int = Math.pow(10, decimals);
return Math.round(num * m) / m;
}
trace(round2(1.3231321321, 3)); //1.323
Just use the .toFixed or .toPrecision method, it doesn't have to be complicated (note that the number will become a string so you'll need to assign it to such or convert it back).
eg.
var numb:Number = 4.3265891;
var newnumb;
newnumb=numb.toFixed(2);//rounds to two decimal places, can be any number up to 20
trace(newnumb);//traces 4.33
newnumb=numb.toPrecision(3);//the 3 means round to the first 3 numbers, can be any number from 1 to 20
trace(newnumb);//traces 4.33
If you need Number as result and performance, I would say this solution is more efficient than the Math.pow()/Math.round() one. If you need 3 decimals just change 100 by 1000.
var myNumber:Number = 3.553366582;
myNumber = (( myNumber * 100 + 0.5) >> 0) / 100;
//trace = 3.55
demonstrating the rounding :
var myNumber:Number = 3.557366582;
myNumber = (( myNumber * 100 + 0.5) >> 0) / 100;
//trace = 3.56
use this instead
return Math.Round((Math.random() * (max - min) + min),1);
,1 will round up till 1 place
for 2 places of decimal you can use
return Math.Round((Math.random() * (max - min) + min),2);
I hope this helps now.