From 6f9558674fd809bde35a6cdd2bfaf11942573f4a Mon Sep 17 00:00:00 2001 From: Denis Molony Date: Wed, 8 Mar 2017 20:18:59 +1100 Subject: [PATCH] NPV --- .../diskbrowser/applefile/VisicalcFile.java | 3 +- .../diskbrowser/visicalc/Average.java | 12 +++-- .../bytezone/diskbrowser/visicalc/Cell.java | 47 +++++-------------- .../bytezone/diskbrowser/visicalc/Count.java | 5 +- .../diskbrowser/visicalc/Expression.java | 7 +++ .../bytezone/diskbrowser/visicalc/Format.java | 36 ++++++++++---- .../bytezone/diskbrowser/visicalc/Lookup.java | 6 ++- .../bytezone/diskbrowser/visicalc/Npv.java | 37 ++++++++++----- .../bytezone/diskbrowser/visicalc/Sheet.java | 7 ++- 9 files changed, 89 insertions(+), 71 deletions(-) diff --git a/src/com/bytezone/diskbrowser/applefile/VisicalcFile.java b/src/com/bytezone/diskbrowser/applefile/VisicalcFile.java index 21b031c..b42d5cf 100644 --- a/src/com/bytezone/diskbrowser/applefile/VisicalcFile.java +++ b/src/com/bytezone/diskbrowser/applefile/VisicalcFile.java @@ -20,8 +20,7 @@ public class VisicalcFile extends AbstractFile StringBuilder text = new StringBuilder (); - text.append ("Visicalc : " + name + "\n"); - text.append ("Cells : " + sheet.size () + "\n\n"); + text.append ("Visicalc : " + name + "\n\n"); text.append (sheet.getTextDisplay (debug)); return text.toString (); diff --git a/src/com/bytezone/diskbrowser/visicalc/Average.java b/src/com/bytezone/diskbrowser/visicalc/Average.java index dcdc544..115ad1a 100644 --- a/src/com/bytezone/diskbrowser/visicalc/Average.java +++ b/src/com/bytezone/diskbrowser/visicalc/Average.java @@ -20,13 +20,14 @@ public class Average extends Function for (Address address : range) { Cell cell = parent.getCell (address); + if (cell.isValueType (ValueType.NA)) continue; if (!cell.isValueType (ValueType.VALUE)) { valueType = cell.getValueType (); - break; + return; } total += cell.getValue (); @@ -34,11 +35,12 @@ public class Average extends Function } if (totalChecked == 0) - valueType = ValueType.NA; - else { - value = total / totalChecked; - valueType = ValueType.VALUE; + valueType = ValueType.ERROR; + return; } + + value = total / totalChecked; + valueType = ValueType.VALUE; } } \ No newline at end of file diff --git a/src/com/bytezone/diskbrowser/visicalc/Cell.java b/src/com/bytezone/diskbrowser/visicalc/Cell.java index d1f7d95..6ef184e 100644 --- a/src/com/bytezone/diskbrowser/visicalc/Cell.java +++ b/src/com/bytezone/diskbrowser/visicalc/Cell.java @@ -132,10 +132,14 @@ class Cell extends AbstractValue implements Comparable // format cell value for output String getText (int colWidth, char globalFormat) { + char fmtChar = cellFormat != ' ' ? cellFormat : globalFormat; + switch (cellType) { case LABEL: - return Format.justify (label, colWidth, cellFormat); + if (fmtChar == ' ') + fmtChar = 'L'; + return Format.justify (label, colWidth, fmtChar); case REPEATING_CHARACTER: return Format.justify (repeat, colWidth, ' '); @@ -146,29 +150,23 @@ class Cell extends AbstractValue implements Comparable case VALUE: if (!isValueType (ValueType.VALUE)) { - char fmt = - cellFormat != ' ' ? cellFormat : globalFormat != ' ' ? globalFormat : 'R'; - return Format.justify (value.getText (), colWidth, fmt); + if (fmtChar == ' ') + fmtChar = 'R'; + return " " + Format.justify (value.getText (), colWidth - 1, fmtChar); } - char formatChar = cellFormat != ' ' ? cellFormat : globalFormat; - return " " + Format.format (value, formatChar, colWidth - 1); + return " " + Format.format (value, fmtChar, colWidth - 1); default: assert false; - return getText (); // not possible + return "Impossible"; } } @Override public double getValue () { - // if (value == null) - // calculate (); - if (cellType != CellType.VALUE) - return 0; - - return value.getValue (); + return cellType == CellType.VALUE ? value.getValue () : 0; } @Override @@ -188,39 +186,20 @@ class Cell extends AbstractValue implements Comparable if (cellType == CellType.EMPTY) return ""; + assert cellType == CellType.VALUE; return value.getText (); } @Override public boolean isValueType (ValueType type) { - // if (cellType == CellType.LABEL || cellType == CellType.REPEATING_CHARACTER) - // return type == ValueType.VALUE; - // - // if (cellType == CellType.EMPTY) - // return type == ValueType.NA; - // - // assert value != null : "bollocks " + address; - // return value.isValueType (type); return type == getValueType (); } - public boolean isCellType (CellType type) - { - return cellType == type; - } - @Override public void calculate () { - // if (value != null && value.isValueType (ValueType.VALUE)) - // return; - // - // if (expressionText == null) - // expressionText = ""; - - // value = new Expression (parent, expressionText).reduce (); - if (value != null) + if (cellType == CellType.VALUE) value.calculate (); } diff --git a/src/com/bytezone/diskbrowser/visicalc/Count.java b/src/com/bytezone/diskbrowser/visicalc/Count.java index 3507a29..bd6226c 100644 --- a/src/com/bytezone/diskbrowser/visicalc/Count.java +++ b/src/com/bytezone/diskbrowser/visicalc/Count.java @@ -27,11 +27,10 @@ class Count extends Function if (!cell.isValueType (ValueType.VALUE)) { valueType = cell.getValueType (); - break; + return; } - if (cell.getValue () != 0.0) - value++; + value++; } } } \ No newline at end of file diff --git a/src/com/bytezone/diskbrowser/visicalc/Expression.java b/src/com/bytezone/diskbrowser/visicalc/Expression.java index 656d854..f431471 100644 --- a/src/com/bytezone/diskbrowser/visicalc/Expression.java +++ b/src/com/bytezone/diskbrowser/visicalc/Expression.java @@ -194,7 +194,14 @@ class Expression extends AbstractValue implements Iterable else if (operator.equals ("*")) value *= nextValue; else if (operator.equals ("/")) + { + if (nextValue == 0) + { + valueType = ValueType.ERROR; + return; + } value /= nextValue; + } else if (operator.equals ("^")) value = Math.pow (value, nextValue); } diff --git a/src/com/bytezone/diskbrowser/visicalc/Format.java b/src/com/bytezone/diskbrowser/visicalc/Format.java index b40502e..d94edf2 100644 --- a/src/com/bytezone/diskbrowser/visicalc/Format.java +++ b/src/com/bytezone/diskbrowser/visicalc/Format.java @@ -1,10 +1,8 @@ package com.bytezone.diskbrowser.visicalc; -import java.text.DecimalFormat; - public class Format { - private static final DecimalFormat nf = new DecimalFormat ("#####0.00"); + // private static final DecimalFormat nf = new DecimalFormat ("#####0.00"); private Format () { @@ -23,9 +21,10 @@ public class Format case 'R': case ' ': // this could be improved - String numberFormat = String.format ("%%%d.5f", colWidth + 6); + String numberFormat = String.format ("%%%d.7f", colWidth + 8); String val = String.format (numberFormat, actualValue); + val = val.trim (); while (val.endsWith ("0")) val = val.substring (0, val.length () - 1); if (val.endsWith (".")) @@ -33,15 +32,25 @@ public class Format if (val.startsWith ("0.")) val = val.substring (1); - if (val.length () > colWidth) - val = val.substring (val.length () - colWidth); + if (val.length () > colWidth && val.indexOf ('.') >= 0) + { + val = val.substring (0, colWidth); + } // System.out.printf ("len:%d fmt: %s%n", val.length (), formatChar); - if (val.startsWith (" ") && formatChar == 'L') + if (formatChar == 'L') { String leftFormat = String.format ("%%-%ds", colWidth); - val = String.format (leftFormat, val.trim ()); + val = String.format (leftFormat, val); } + else + { + String rightFormat = String.format ("%%%ds", colWidth); + val = String.format (rightFormat, val); + } + + if (val.length () > colWidth) + return ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>".substring (0, colWidth); return val; @@ -53,8 +62,15 @@ public class Format return result; case '$': - String currencyFormat = String.format ("%%%d.%ds", colWidth, colWidth); - return String.format (currencyFormat, nf.format (actualValue)); + String currencyFormat = String.format ("%%%d.%df", colWidth + 3, 2); + result = String.format (currencyFormat, actualValue).trim (); + String rightFormat = String.format ("%%%ds", colWidth); + val = String.format (rightFormat, result); + // System.out.println (result); + // System.out.println (val); + if (result.length () > colWidth) + return ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>".substring (0, colWidth); + return val; case '*': String graphFormat = String.format ("%%-%d.%ds", colWidth, colWidth); diff --git a/src/com/bytezone/diskbrowser/visicalc/Lookup.java b/src/com/bytezone/diskbrowser/visicalc/Lookup.java index 5fdca09..916e794 100644 --- a/src/com/bytezone/diskbrowser/visicalc/Lookup.java +++ b/src/com/bytezone/diskbrowser/visicalc/Lookup.java @@ -12,8 +12,10 @@ class Lookup extends Function super (parent, text); int pos = text.indexOf (','); + sourceText = text.substring (8, pos); source = new Expression (parent, sourceText); + rangeText = text.substring (pos + 1, text.length () - 1); range = new Range (parent, rangeText); @@ -43,7 +45,9 @@ class Lookup extends Function for (Address address : range) { Cell cell = parent.getCell (address); - if (cell != null && cell.getValue () > sourceValue) // past the value + if (cell.isValueType (ValueType.NA)) + continue; + if (cell.getValue () > sourceValue) // past the value break; target = address; } diff --git a/src/com/bytezone/diskbrowser/visicalc/Npv.java b/src/com/bytezone/diskbrowser/visicalc/Npv.java index b293633..aa467d5 100644 --- a/src/com/bytezone/diskbrowser/visicalc/Npv.java +++ b/src/com/bytezone/diskbrowser/visicalc/Npv.java @@ -2,23 +2,24 @@ package com.bytezone.diskbrowser.visicalc; public class Npv extends Function { - // private final String valueText; - // private final String rangeText; - // - // private final Expression valueExp; + private final String valueText; + private final String rangeText; + + private final Expression rateExp; private final Range range; Npv (Sheet parent, String text) { super (parent, text); - range = new Range (parent, text); + int pos = text.indexOf (','); + valueText = text.substring (5, pos); + rangeText = text.substring (pos + 1, text.length () - 1); - // int pos = text.indexOf (','); - // valueText = text.substring (8, pos); - // rangeText = text.substring (pos + 1, text.length () - 1); - // - // valueExp = new Expression (parent, valueText); + rateExp = new Expression (parent, valueText); + range = new Range (parent, rangeText); + + values.add (rateExp); } @Override @@ -27,8 +28,20 @@ public class Npv extends Function value = 0; valueType = ValueType.VALUE; + rateExp.calculate (); + if (!rateExp.isValueType (ValueType.VALUE)) + { + valueType = rateExp.getValueType (); + return; + } + + double rate = 1 + rateExp.getValue (); + + int period = 0; for (Address address : range) { + ++period; + Cell cell = parent.getCell (address); if (cell.isValueType (ValueType.NA)) continue; @@ -36,10 +49,10 @@ public class Npv extends Function if (!cell.isValueType (ValueType.VALUE)) { valueType = cell.getValueType (); - break; + return; } - double temp = cell.getValue (); + value += cell.getValue () / Math.pow (rate, period); } } } \ No newline at end of file diff --git a/src/com/bytezone/diskbrowser/visicalc/Sheet.java b/src/com/bytezone/diskbrowser/visicalc/Sheet.java index 6ba639a..0782deb 100644 --- a/src/com/bytezone/diskbrowser/visicalc/Sheet.java +++ b/src/com/bytezone/diskbrowser/visicalc/Sheet.java @@ -8,7 +8,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import com.bytezone.diskbrowser.utilities.HexFormatter; -import com.bytezone.diskbrowser.visicalc.Cell.CellType; public class Sheet { @@ -177,8 +176,7 @@ public class Sheet { Map cells = order == 'R' ? rowOrderCells : columnOrderCells; for (Cell cell : cells.values ()) - if (cell.isCellType (CellType.VALUE)) - cell.calculate (); + cell.calculate (); } private int getLineLength (byte[] buffer, int offset) @@ -371,8 +369,9 @@ public class Sheet recalculationOrder == 'R' ? "Row" : "Column")); text.append (String.format ("Recalculation : %s%n", recalculation == 'A' ? "Automatic" : "Manual")); + text.append (String.format ("Cells : %d%n", size ())); - if (rowOrderCells.size () > 0) + if (size () > 0) text.append (String.format ("Range : %s:%s%n%n", Address.getCellName (minRow + 1, minColumn), Address.getCellName (maxRow + 1, maxColumn)));