package de.hs_mannheim.informatik.spreadsheet; import java.io.FileNotFoundException; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.ArrayList; import java.util.Scanner; /** * A simplified spreadsheet class for the PR1 programming lab at Hochschule Mannheim. * One aspect worth mentioning is that it only supports long numbers, not doubles. * * @author Oliver Hummel */ public class Spreadsheet { Cell[][] cells; /** * Constructor that creates a Spreadsheet of size rows * cols. * @param rows number of rows * @param cols number of columns */ public Spreadsheet(int rows, int cols) { // TODO limit the maximum size on 99 (1..99) rows and 26 (A..Z) columns //limit maximum size if(rows>99) { rows=99; } if(cols>26) { cols=26; } cells = new Cell[rows][cols]; for (int r = 0; r < rows; r++) for (int c = 0; c < cols; c++) cells[r][c] = new Cell(); } // ----- // retrieve or change values of cells private String get(int row, int col) { return cells[row][col].getValue(); } public String get(String cellName) { cellName = cellName.toUpperCase(); return get(getRow(cellName), getCol(cellName)); } private void put(int row, int col, String value) { if (!value.startsWith("=")) cells[row][col].setValue(value); else { cells[row][col].setFormula(value); evaluateCell(row, col); } } public void put(String cellName, String value) { cellName = cellName.toUpperCase(); put(getRow(cellName), getCol(cellName), value); } private int getCol(String cellName) { return cellName.charAt(0) - 'A'; } private int getRow(String cellName) { return cellName.charAt(1) - '1'; } // ----- // business logic /** * A method for reading in data from a CSV file. * @param path The file to read. * @param separator The char used to split up the input, e.g. a comma or a semicolon. * @param starCellName The upper left cell where data from the CSV file should be inserted. * @return Nothing. * @exception IOException If path does not exist. */ public void readCsv(String filePath, String separator, String startCellName) throws FileNotFoundException { ArrayList fileRows = new ArrayList<>(); Scanner sc = new Scanner(new File(filePath)); while (sc.hasNextLine()) { fileRows.add(sc.nextLine()); } ArrayList formulas = new ArrayList<>(); for (int r = 0; r < fileRows.size(); r++) { String row = fileRows.get(r); String[] cells = row.split(separator); for (int c = 0; c < cells.length; c++) { String cellFill = cells[c].toUpperCase(); if (cellFill.startsWith("=")){ formulas.add(new int[]{r, c}); } else { put(r, c, cellFill); } } } for (int[] formulaAt : formulas){ int r = formulaAt[0]; int c = formulaAt[1]; System.out.printf("Formula at %d-%d %n", r, c); String row = fileRows.get(r); String formulaToFill = row.split(separator)[c]; put(r, c, formulaToFill); } sc.close(); } /** * A method for saving data to a CSV file. * @param path The file to write. * @return Nothing. * @exception IOException If path does not exist. */ public void saveCsv(String path) throws FileNotFoundException { PrintWriter out = new PrintWriter(path); for (Cell[] row : cells) { for (Cell cell : row) { if (!cell.getFormula().isEmpty()) out.print("=" + cell.getFormula()); else out.print(cell.getValue()); if (cell != row[cells[0].length-1]) out.print(","); } out.println(); } out.close(); } /** * This method does the actual evaluation/calcluation of a specific cell * @param cellName the name of the cell to be evaluated * @return Nothing. */ private void evaluateCell(int row, int col) { String formula = cells[row][col].getFormula(); String result = ""; String sum1; String sum2; if (formula.startsWith("SUMME(")) // e.g. SUMME(A3:A8) //SUMME(A13:B22) result = "" + sum(getStartCellName(formula), getEndCellName(formula)); // TODO adapt to cells with two digits else if (formula.startsWith("PRODUKT(")) // e.g. PRODUKT(A3:B9) result = "" + prod(getStartCellName(formula),getEndCellName(formula)); // TODO else if (formula.startsWith("MITTELWERT(")) // e.g. MITTELWERT(A3:A5) result = ""+ average(getStartCellName(formula),getEndCellName(formula)); // TODO else if (formula.startsWith("STABW(")) // e.g. STABW(C6:D8) -> Standardabweichung result = "" + stDev(getStartCellName(formula),getEndCellName(formula)); // TODO else if (formula.startsWith("MIN(")) // e.g. MIN(C13:H13) -> größter Wert result = ""+ min(getStartCellName(formula), getEndCellName(formula)); else if (formula.startsWith("MAX(")) // e.g. MAX(A1:A10) -> Standardabweichung result = ""+ max(getStartCellName(formula), getEndCellName(formula)); // TODO else if (!formula.isEmpty()) { try { result = "" + calculate(formula); } catch(ArithmeticException ae) { result = "exc."; } } cells[row][col].setValue("" + result); } /** * Method for calculating the sum of a rectangular block of cells, such as from A1 to B3. * @param startCellName The name of the cell in the upper left corner of the rectangle. * @param endCellName The name of the cell in the lower right corner ofODO the rectangle. * @return The sum calculated. */ private long sum(String startCellName, String endCellName) { // TODO implement int startRow=0; int startCol=0; int endRow=0; int endCol; long sum=0; int temp; startRow= getRow(startCellName); startCol= getCol(startCellName); endRow= getRow(endCellName); endCol= getCol(endCellName); for(int i= startRow; i<=endRow; i++) { for(int j=startCol; j<=endCol; j++) { temp= Integer.parseInt(cells[i][j].getValue()); sum=sum+temp; } } return sum; } /** * Method for calculating the product of a rectangular block of cells, such as from A1 to B3. * @param startCellName The name of the cell in the upper left corner of the rectangle. * @param endCellName The name of the cell in the lower right corner ofODO the rectangle. * @return The product calculated. */ private long prod(String startCellName, String endCellName) { int startRow=0; int startCol=0; int endRow=0; int endCol; long prod=1; long temp; startRow= getRow(startCellName); startCol= getCol(startCellName); endRow= getRow(endCellName); endCol= getCol(endCellName); for(int i= startRow; i<=endRow; i++) { for(int j=startCol; j<=endCol; j++) { temp= Integer.parseInt(cells[i][j].getValue()); prod=prod*temp; } } return prod; } /** * Method for calculating the average of a rectangular block of cells, such as from A1 to B3. * @param startCellName The name of the cell in the upper left corner of the rectangle. * @param endCellName The name of the cell in the lower right corner ofODO the rectangle. * @return The average calculated. */ private long average(String startCellName, String endCellName) { int startRow=0; int startCol=0; int endRow=0; int endCol; long sum=0; long temp; int part=0; long avg=0;; startRow= getRow(startCellName); startCol= getCol(startCellName); endRow= getRow(endCellName); endCol= getCol(endCellName); for(int i= startRow; i<=endRow; i++) { for(int j=startCol; j<=endCol; j++) { temp= Integer.parseInt(cells[i][j].getValue()); sum=sum+temp; part++; } } avg=sum/part; return avg; } /** * Method for calculating the minimum of a rectangular block of cells * @param startCellName The name of the cell in the upper left corner of the rectangle. * @param endCellName The name of the cell in the lower right corner of the rectangle. * @return The minimum. */ private int min(String startCellName, String endCellName) { int startRow=0; int startCol=0; int endRow=0; int endCol; int min; int temp; startRow= getRow(startCellName); startCol= getCol(startCellName); endRow= getRow(endCellName); endCol= getCol(endCellName); min=Integer.parseInt(cells[startRow][startCol].getValue()); for(int i= startRow; i<=endRow; i++) { for(int j=startCol; j<=endCol; j++) { temp= Integer.parseInt(cells[i][j].getValue()); if(min>temp) { min=temp; } } } return min; } /** * Method for calculating the maximum of a rectangular block of cells * @param startCellName The name of the cell in the upper left corner of the rectangle. * @param endCellName The name of the cell in the lower right corner of the the rectangle. * @return The maximum. */ private int max(String startCellName, String endCellName) { int startRow=0; int startCol=0; int endRow=0; int endCol; int max; int temp; startRow= getRow(startCellName); startCol= getCol(startCellName); endRow= getRow(endCellName); endCol= getCol(endCellName); max=Integer.parseInt(cells[startRow][startCol].getValue()); for(int i= startRow; i<=endRow; i++) { for(int j=startCol; j<=endCol; j++) { temp= Integer.parseInt(cells[i][j].getValue()); if(max elements = new ArrayList<>(); avg= average(startCellName, endCellName); for(int i= startRow; i<=endRow; i++) { for(int j=startCol; j<=endCol; j++) { temp= Integer.parseInt(cells[i][j].getValue()); temp=temp-avg; temp= temp*temp; elements.add(temp); } } avg=0; for(int i=0; i