Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions main/HSSF/Model/InternalWorkbook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,8 @@ public void RemoveSheet(int sheetnum)
// Bump down by one, so still points
// at the same sheet
nr.SheetNumber=(nr.SheetNumber - 1);
// also update the link-table as otherwise references might point at invalid sheets
linkTable.UpdateIndexToInternalSheet(i, -1);
}
}
}
Expand Down Expand Up @@ -3004,14 +3006,14 @@ public RecalcIdRecord RecalcId
}

/**
* Changes an external referenced file to another file.
* A formular in Excel which refers a cell in another file is saved in two parts:
* The referenced file is stored in an reference table. the row/cell information is saved separate.
* This method invokation will only change the reference in the lookup-table itself.
* @param oldUrl The old URL to search for and which is to be replaced
* @param newUrl The URL replacement
* @return true if the oldUrl was found and replaced with newUrl. Otherwise false
*/
* Changes an external referenced file to another file.
* A formular in Excel which refers a cell in another file is saved in two parts:
* The referenced file is stored in an reference table. the row/cell information is saved separate.
* This method invokation will only change the reference in the lookup-table itself.
* @param oldUrl The old URL to search for and which is to be replaced
* @param newUrl The URL replacement
* @return true if the oldUrl was found and replaced with newUrl. Otherwise false
*/
public bool ChangeExternalReference(String oldUrl, String newUrl)
{
return linkTable.ChangeExternalReference(oldUrl, newUrl);
Expand Down
11 changes: 8 additions & 3 deletions main/HSSF/Model/LinkTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -334,13 +334,18 @@ public void RemoveBuiltinRecord(byte name, int sheetIndex)
// TODO - do we need "Workbook.records.Remove(...);" similar to that in Workbook.RemoveName(int namenum) {}?
}
/**
* @param extRefIndex as from a {@link Ref3DPtg} or {@link Area3DPtg}
* @return -1 if the reference is to an external book
*/
* @param extRefIndex as from a {@link Ref3DPtg} or {@link Area3DPtg}
* @return -1 if the reference is to an external book
*/
public int GetIndexToInternalSheet(int extRefIndex)
{
return _externSheetRecord.GetFirstSheetIndexFromRefIndex(extRefIndex);
}

public void UpdateIndexToInternalSheet(int extRefIndex, int offset)
{
_externSheetRecord.AdjustIndex(extRefIndex, offset);
}
public int NumNames
{
get
Expand Down
15 changes: 12 additions & 3 deletions main/HSSF/Record/ExternSheetRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ public class RefSubRecord
private int _firstSheetIndex; // may be -1 (0xFFFF)
private int _lastSheetIndex; // may be -1 (0xFFFF)


public void AdjustIndex(int offset)
{
_firstSheetIndex += offset;
_lastSheetIndex += offset;
}
/** a Constructor for making new sub record
*/
public RefSubRecord(int extBookIndex, int firstSheetIndex, int lastSheetIndex)
Expand Down Expand Up @@ -172,7 +176,7 @@ public int NumOfREFRecords
return _list.Count;
}
}
/**
* @return number of REF structures
*/
Expand All @@ -196,6 +200,11 @@ private RefSubRecord GetRef(int i)
{
return (RefSubRecord)_list[i];
}

public void AdjustIndex(int extRefIndex, int offset)
{
GetRef(extRefIndex).AdjustIndex(offset);
}
public int GetExtbookIndexFromRefIndex(int refIndex)
{
return GetRef(refIndex).ExtBookIndex;
Expand Down Expand Up @@ -233,7 +242,7 @@ public int GetFirstSheetIndexFromRefIndex(int extRefIndex)
{
return GetRef(extRefIndex).FirstSheetIndex;
}
public override String ToString()
{
StringBuilder sb = new StringBuilder();
Expand Down
2 changes: 1 addition & 1 deletion main/SS/Formula/Atp/AnalysisToolPak.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ private static Hashtable CreateFunctionsMap()
r(m, "NETWORKDAYS", NetworkdaysFunction.instance);
r(m, "NOMINAL", null);
r(m, "OCT2BIN", null);
r(m, "OCT2DEC", null);
r(m, "OCT2DEC", Oct2Dec.instance);
r(m, "OCT2HEX", null);
r(m, "ODDFPRICE", null);
r(m, "ODDFYIELD", null);
Expand Down
4 changes: 2 additions & 2 deletions main/SS/Formula/Eval/FunctionEval.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ private static Function[] ProduceFunctions()
retval[58] = FinanceFunction.NPER; // NPER
retval[59] = FinanceFunction.PMT; // PMT
retval[60] = new Rate(); // RATE
retval[61] = new NotImplementedFunction("MIRR"); // MIRR
retval[61] = new Mirr(); // MIRR
retval[62] = new Irr(); // IRR
retval[63] = new Rand(); // RAND
retval[64] = new Match(); // MATCH
Expand Down Expand Up @@ -407,7 +407,7 @@ private static Function[] ProduceFunctions()
retval[325] = AggregateFunction.LARGE; // LARGE
retval[326] = AggregateFunction.SMALL; // SMALL
retval[327] = new NotImplementedFunction("QUARTILE"); // QUARTILE
retval[328] = new NotImplementedFunction("PERCENTILE"); // PERCENTILE
retval[328] = AggregateFunction.PERCENTILE; // PERCENTILE
retval[329] = new NotImplementedFunction("PERCENTRANK"); // PERCENTRANK
retval[330] = new Mode(); // MODE
retval[331] = new NotImplementedFunction("TRIMMEAN"); // TRIMMEAN
Expand Down
131 changes: 131 additions & 0 deletions main/SS/Formula/Functions/AggregateFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,136 @@ public override bool IsSubtotalCounted
}
}
}


public class LargeSmall : Fixed2ArgFunction
{
private bool _isLarge;
protected LargeSmall(bool isLarge)
{
_isLarge = isLarge;
}

public override ValueEval Evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0,
ValueEval arg1)
{
double dn;
try
{
ValueEval ve1 = OperandResolver.GetSingleValue(arg1, srcRowIndex, srcColumnIndex);
dn = OperandResolver.CoerceValueToDouble(ve1);
}
catch (EvaluationException e1)
{
// all errors in the second arg translate to #VALUE!
return ErrorEval.VALUE_INVALID;
}
// weird Excel behaviour on second arg
if (dn < 1.0)
{
// values between 0.0 and 1.0 result in #NUM!
return ErrorEval.NUM_ERROR;
}
// all other values are rounded up to the next integer
int k = (int)Math.Ceiling(dn);

double result;
try
{
double[] ds = NPOI.SS.Formula.Functions.AggregateFunction.ValueCollector.CollectValues(arg0);
if (k > ds.Length)
{
return ErrorEval.NUM_ERROR;
}
result = _isLarge ? StatsLib.kthLargest(ds, k) : StatsLib.kthSmallest(ds, k);
NumericFunction.CheckValue(result);
}
catch (EvaluationException e)
{
return e.GetErrorEval();
}

return new NumberEval(result);
}
}

/**
* Returns the k-th percentile of values in a range. You can use this function to establish a threshold of
* acceptance. For example, you can decide to examine candidates who score above the 90th percentile.
*
* PERCENTILE(array,k)
* Array is the array or range of data that defines relative standing.
* K is the percentile value in the range 0..1, inclusive.
*
* <strong>Remarks</strong>
* <ul>
* <li>if array is empty or Contains more than 8,191 data points, PERCENTILE returns the #NUM! error value.</li>
* <li>If k is nonnumeric, PERCENTILE returns the #VALUE! error value.</li>
* <li>If k is < 0 or if k > 1, PERCENTILE returns the #NUM! error value.</li>
* <li>If k is not a multiple of 1/(n - 1), PERCENTILE interpolates to determine the value at the k-th percentile.</li>
* </ul>
*/
public class Percentile : Fixed2ArgFunction
{
public override ValueEval Evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0,
ValueEval arg1)
{
double dn;
try
{
ValueEval ve1 = OperandResolver.GetSingleValue(arg1, srcRowIndex, srcColumnIndex);
dn = OperandResolver.CoerceValueToDouble(ve1);
}
catch (EvaluationException e1)
{
// all errors in the second arg translate to #VALUE!
return ErrorEval.VALUE_INVALID;
}
if (dn < 0 || dn > 1)
{ // has to be percentage
return ErrorEval.NUM_ERROR;
}

double result;
try
{
double[] ds = NPOI.SS.Formula.Functions.AggregateFunction.ValueCollector.CollectValues(arg0);
int N = ds.Length;

if (N == 0 || N > 8191)
{
return ErrorEval.NUM_ERROR;
}

double n = (N - 1) * dn + 1;
if (n == 1d)
{
result = StatsLib.kthSmallest(ds, 1);
}
else if (n == N)
{
result = StatsLib.kthLargest(ds, 1);
}
else
{
int k = (int)n;
double d = n - k;
result = StatsLib.kthSmallest(ds, k) + d
* (StatsLib.kthSmallest(ds, k + 1) - StatsLib.kthSmallest(ds, k));
}

NumericFunction.CheckValue(result);
}
catch (EvaluationException e)
{
return e.GetErrorEval();
}

return new NumberEval(result);
}
}


/**
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*
Expand Down Expand Up @@ -220,5 +350,6 @@ protected AggregateFunction()
public static readonly Function SUMSQ = new SUMSQ();
public static readonly Function VAR = new VAR();
public static readonly Function VARP = new VARP();
public static readonly Function PERCENTILE = new Percentile();
}
}
98 changes: 98 additions & 0 deletions main/SS/Formula/Functions/BaseNumberUtils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for Additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
namespace NPOI.SS.Formula.Functions
{
using System;

/**
* <p>Some utils for Converting from and to any base<p/>
*
* @author cedric dot walter @ gmail dot com
*/
public class BaseNumberUtils
{
public static double ConvertToDecimal(String value, int base1, int maxNumberOfPlaces)
{
if (string.IsNullOrEmpty(value))
{
return 0.0;
}

long stringLength = value.Length;
if (stringLength > maxNumberOfPlaces)
{
throw new ArgumentException();
}

double decimalValue = 0.0;

long signedDigit = 0;
bool hasSignedDigit = true;
char[] characters = value.ToCharArray();
foreach (char character in characters)
{
long digit;

if ('0' <= character && character <= '9')
{
digit = character - '0';
}
else if ('A' <= character && character <= 'Z')
{
digit = 10 + (character - 'A');
}
else if ('a' <= character && character <= 'z')
{
digit = 10 + (character - 'a');
}
else
{
digit = base1;
}

if (digit < base1)
{
if (hasSignedDigit)
{
hasSignedDigit = false;
signedDigit = digit;
}
decimalValue = decimalValue * base1 + digit;
}
else
{
throw new ArgumentException("character not allowed");
}
}

bool isNegative = (!hasSignedDigit && stringLength == maxNumberOfPlaces && (signedDigit >= base1 / 2));
if (isNegative)
{
decimalValue = GetTwoComplement(base1, maxNumberOfPlaces, decimalValue);
decimalValue = decimalValue * -1.0;
}

return decimalValue;
}

private static double GetTwoComplement(double base1, double maxNumberOfPlaces, double decimalValue)
{
return (Math.Pow(base1, maxNumberOfPlaces) - decimalValue);
}
}

}
15 changes: 3 additions & 12 deletions main/SS/Formula/Functions/Hex2Dec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,21 +47,12 @@ public class Hex2Dec : Fixed1ArgFunction, FreeRefFunction

public override ValueEval Evaluate(int srcRowIndex, int srcColumnIndex, ValueEval numberVE)
{
String hex;
if (numberVE is RefEval)
{
RefEval re = (RefEval)numberVE;
hex = OperandResolver.CoerceValueToString(re.InnerValueEval);
}
else
{
hex = OperandResolver.CoerceValueToString(numberVE);
}
String hex = OperandResolver.CoerceValueToString(numberVE);
try
{
return new NumberEval(Convert.ToInt64(hex, HEXADECIMAL_BASE));
return new NumberEval(BaseNumberUtils.ConvertToDecimal(hex, HEXADECIMAL_BASE, MAX_NUMBER_OF_PLACES));
}
catch (ArgumentException e)
catch (ArgumentException)
{
return ErrorEval.NUM_ERROR;
}
Expand Down
Loading