657 lines
21 KiB
Java
657 lines
21 KiB
Java
|
|
/* ====================================================================
|
|
* The Apache Software License, Version 1.1
|
|
*
|
|
* Copyright (c) 2002 The Apache Software Foundation. All rights
|
|
* reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
*
|
|
* 3. The end-user documentation included with the redistribution,
|
|
* if any, must include the following acknowledgment:
|
|
* "This product includes software developed by the
|
|
* Apache Software Foundation (http://www.apache.org/)."
|
|
* Alternately, this acknowledgment may appear in the software itself,
|
|
* if and wherever such third-party acknowledgments normally appear.
|
|
*
|
|
* 4. The names "Apache" and "Apache Software Foundation" and
|
|
* "Apache POI" must not be used to endorse or promote products
|
|
* derived from this software without prior written permission. For
|
|
* written permission, please contact apache@apache.org.
|
|
*
|
|
* 5. Products derived from this software may not be called "Apache",
|
|
* "Apache POI", nor may "Apache" appear in their name, without
|
|
* prior written permission of the Apache Software Foundation.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
|
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
|
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
* ====================================================================
|
|
*
|
|
* This software consists of voluntary contributions made by many
|
|
* individuals on behalf of the Apache Software Foundation. For more
|
|
* information on the Apache Software Foundation, please see
|
|
* <http://www.apache.org/>.
|
|
*/
|
|
|
|
package org.apache.poi.hssf.record.aggregates;
|
|
|
|
import org.apache.poi.hssf.usermodel.HSSFCell; //kludge shouldn't refer to this
|
|
|
|
import org.apache.poi.hssf.record.*;
|
|
import org.apache.poi.hssf.record.formula.Ptg;
|
|
import org.apache.poi.util.DoubleList;
|
|
import org.apache.poi.util.IntList;
|
|
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.ArrayList;
|
|
|
|
/**
|
|
*
|
|
* Aggregate value records together. Things are easier to handle that way.
|
|
*
|
|
* @author Andrew C. Oliver
|
|
* @author Glen Stampoultzis (glens at apache.org)
|
|
* @author Jason Height (jheight at chariot dot net dot au)
|
|
*/
|
|
|
|
public class ValueRecordsAggregate
|
|
extends Record
|
|
{
|
|
public final static short sid = -1000;
|
|
int firstcell = -1;
|
|
int lastcell = -1;
|
|
//TreeMap records = null;
|
|
|
|
private final static int DEFAULT_ROWS=10000;
|
|
private final static int DEFAULT_COLS=256;
|
|
|
|
List celltype = null; //array of HSSFCEll.CELL_TYPE_XXX tells us which arrays to use
|
|
List xfs = null; // array of style types. Index of XF record
|
|
List numericcells = null; // numeric and Shared string indicies.
|
|
List formulaptgs = null; // array of arrays of PTGS
|
|
List stringvals = null; // array of actual string/formula string vals
|
|
IntList populatedRows = null; //indicies of populated rows
|
|
int physCells; //physical number of cells
|
|
|
|
public CellValueRecordInterface getCell(int row, short col) {
|
|
return constructRecord(row, col);
|
|
|
|
}
|
|
|
|
public int getRecordSize() {
|
|
//throw new RuntimeException("Not Implemented getRecordSize");
|
|
|
|
int size = 0;
|
|
Iterator irecs = getIterator();
|
|
|
|
while (irecs.hasNext()) {
|
|
size += (( Record ) irecs.next()).getRecordSize();
|
|
}
|
|
|
|
return size;
|
|
// return size;
|
|
}
|
|
|
|
public int serialize(int offset, byte [] data)
|
|
{
|
|
throw new RuntimeException("This method shouldnt be called. ValueRecordsAggregate.serializeCellRow() should be called from RowRecordsAggregate.");
|
|
}
|
|
|
|
public ValueRecordsAggregate() {
|
|
celltype = new ArrayList(DEFAULT_ROWS);
|
|
xfs = new ArrayList(DEFAULT_ROWS);
|
|
numericcells = new ArrayList(DEFAULT_ROWS);
|
|
formulaptgs = new ArrayList(DEFAULT_ROWS);
|
|
stringvals = new ArrayList(DEFAULT_ROWS);
|
|
populatedRows = new IntList(DEFAULT_ROWS);
|
|
physCells = 0;
|
|
}
|
|
|
|
public Iterator getIterator() {
|
|
return new VRAIterator(this);
|
|
}
|
|
|
|
/** Tallies a count of the size of the cell records
|
|
* that are attached to the rows in the range specified.
|
|
*/
|
|
public int getRowCellBlockSize(int startRow, int endRow) {
|
|
Iterator cellRec = new VRAIterator(this, startRow, endRow);;
|
|
int size = 0;
|
|
while (cellRec.hasNext()) {
|
|
CellValueRecordInterface cell = (CellValueRecordInterface)cellRec.next();
|
|
int row = cell.getRow();
|
|
if ((row >=startRow) && (row <= endRow))
|
|
size += ((Record)cell).getRecordSize();
|
|
}
|
|
return size;
|
|
}
|
|
|
|
/** Returns true if the row has cells attached to it */
|
|
public boolean rowHasCells(int row) {
|
|
IntList ctRow = (IntList) celltype.get(row);
|
|
return ((ctRow != null) && (ctRow.size() > 0));
|
|
}
|
|
|
|
/** Serializes the cells that are allocated to a certain row range*/
|
|
public int serializeCellRow(final int row, int offset, byte [] data)
|
|
{
|
|
Iterator itr = new VRAIterator(this, row);
|
|
int pos = offset;
|
|
|
|
while (itr.hasNext())
|
|
{
|
|
CellValueRecordInterface cell = (CellValueRecordInterface)itr.next();
|
|
pos += (( Record ) cell).serialize(pos, data);
|
|
}
|
|
return pos - offset;
|
|
}
|
|
|
|
|
|
|
|
public int construct(int offset, List records)
|
|
{
|
|
int k = 0;
|
|
|
|
FormulaRecordAggregate lastFormulaAggregate = null;
|
|
|
|
for (k = offset; k < records.size(); k++)
|
|
{
|
|
Record rec = ( Record ) records.get(k);
|
|
|
|
if (rec instanceof StringRecord == false && !rec.isInValueSection() && !(rec instanceof UnknownRecord))
|
|
{
|
|
break;
|
|
}
|
|
if (rec instanceof FormulaRecord)
|
|
{
|
|
lastFormulaAggregate = new FormulaRecordAggregate((FormulaRecord)rec, null);
|
|
insertCell( lastFormulaAggregate );
|
|
}
|
|
else if (rec instanceof StringRecord)
|
|
{
|
|
lastFormulaAggregate.setStringRecord((StringRecord)rec);
|
|
}
|
|
else if (rec instanceof SharedFormulaRecord) {
|
|
lastFormulaAggregate.setSharedFormulaRecord((SharedFormulaRecord)rec);
|
|
}
|
|
else if (rec.isValue())
|
|
{
|
|
insertCell(( CellValueRecordInterface ) rec);
|
|
}
|
|
}
|
|
return k;
|
|
}
|
|
|
|
public int getPhysicalNumberOfCells() {
|
|
return physCells;
|
|
}
|
|
|
|
public int getPhysicalNumberOfCellsInRow(int row) {
|
|
int count = -1;
|
|
int col = -1;
|
|
boolean firsttime = true;
|
|
|
|
while (col > 0 || count == -1) {
|
|
col = findNextPopulatedCell(row,col);
|
|
count++;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
public void setValue(int row, short cell, double val) {
|
|
((DoubleList)numericcells.get(row)).set(cell, val);
|
|
}
|
|
|
|
public void setStyle(int row, short cell, short xf) {
|
|
((IntList)xfs.get(row)).set(cell, xf);
|
|
}
|
|
|
|
|
|
public Iterator getRowCellIterator(int row) {
|
|
return new VRAIterator(this, row);
|
|
}
|
|
|
|
public void removeRow(int row) {
|
|
Iterator iterator = this.getRowCellIterator(row);
|
|
while(iterator.hasNext()) {
|
|
iterator.next();
|
|
iterator.remove();
|
|
}
|
|
}
|
|
|
|
public void removeCell(CellValueRecordInterface cell) {
|
|
int rownum = cell.getRow();
|
|
int colnum = cell.getColumn();
|
|
int xf = cell.getXFIndex();
|
|
int type = determineType(cell);
|
|
|
|
if (rownum < celltype.size() && colnum < ((IntList)celltype.get(rownum)).size()) {
|
|
IntList ctRow = (IntList)celltype.get(rownum);
|
|
if (ctRow.size()-1 == colnum) {
|
|
ctRow.remove(colnum);
|
|
if (ctRow.size() == 0 && celltype.size()-1 == rownum) {
|
|
celltype.remove(rownum);
|
|
int remp = populatedRows.indexOf(rownum);
|
|
System.err.println("remp == "+remp);
|
|
populatedRows.removeValue(rownum);
|
|
}
|
|
} else {
|
|
ctRow.set(colnum,-1);
|
|
}
|
|
physCells--;
|
|
} else {
|
|
//this cell doesn't exist...
|
|
throw new RuntimeException("Tried to remove a cell that does not exist r,c="+rownum+","+colnum);
|
|
}
|
|
}
|
|
|
|
public void insertCell(CellValueRecordInterface cell) {
|
|
int rownum = cell.getRow();
|
|
int colnum = cell.getColumn();
|
|
int xf = cell.getXFIndex();
|
|
int type = determineType(cell);
|
|
|
|
if (celltype.size() < rownum+1) {
|
|
populatedRows.add(rownum); //this means we must never have had this row inserted
|
|
}
|
|
|
|
ensureRows(rownum);
|
|
|
|
IntList ctRow = (IntList)celltype.get(rownum);
|
|
IntList xfRow = (IntList)xfs.get(rownum);
|
|
|
|
|
|
adjustIntList(ctRow, colnum+1);
|
|
adjustIntList(xfRow, colnum+1);
|
|
|
|
ctRow.set(colnum, type);
|
|
xfRow.set(colnum, xf);
|
|
|
|
insertCell(cell, type);
|
|
}
|
|
|
|
CellValueRecordInterface constructRecord(int row, int col) {
|
|
if (celltype.size() < row || ((IntList)celltype.get(row)).size() < col) {
|
|
throw new ArrayIndexOutOfBoundsException("constructRecord called with row = "+row+
|
|
"and col ="+col+" but there are only "+celltype.size()+" rows and "+
|
|
((IntList)celltype.get(row)).size()+" cols!!");
|
|
}
|
|
|
|
CellValueRecordInterface retval = null;
|
|
int type = ((IntList)celltype.get(row)).get(col);
|
|
|
|
|
|
switch (type) {
|
|
case HSSFCell.CELL_TYPE_NUMERIC:
|
|
NumberRecord nrecord = new NumberRecord();
|
|
nrecord.setColumn((short)col);
|
|
nrecord.setRow(row);
|
|
nrecord.setValue(((DoubleList)numericcells.get(row)).get(col));
|
|
nrecord.setXFIndex((short)((IntList)xfs.get(row)).get(col));
|
|
retval = nrecord;
|
|
break;
|
|
case HSSFCell.CELL_TYPE_STRING:
|
|
LabelSSTRecord srecord = new LabelSSTRecord();
|
|
srecord.setColumn((short)col);
|
|
srecord.setRow(row);
|
|
srecord.setSSTIndex((int)((DoubleList)numericcells.get(row)).get(col));
|
|
srecord.setXFIndex((short)((IntList)xfs.get(row)).get(col));
|
|
retval=srecord;
|
|
break;
|
|
case HSSFCell.CELL_TYPE_BLANK:
|
|
BlankRecord brecord = new BlankRecord();
|
|
brecord.setColumn((short)col);
|
|
brecord.setRow(row);
|
|
brecord.setXFIndex((short)((IntList)xfs.get(row)).get(col));
|
|
retval=brecord;
|
|
break;
|
|
case HSSFCell.CELL_TYPE_FORMULA:
|
|
FormulaRecord fr = new FormulaRecord();
|
|
fr.setColumn((short)col);
|
|
fr.setOptions((short)2);
|
|
|
|
fr.setRow(row);
|
|
fr.setXFIndex((short)((IntList)xfs.get(row)).get(col));
|
|
StringRecord st = null;
|
|
String strval = (String)((List)stringvals.get(row)).get(col);
|
|
List expressionlist = (List)((List)formulaptgs.get(row)).get(col);
|
|
fr.setParsedExpression(expressionlist);
|
|
fr.setExpressionLength(calculatePtgSize(expressionlist));
|
|
if (strval != null) {
|
|
st = new StringRecord();
|
|
st.setString(strval);
|
|
}
|
|
FormulaRecordAggregate frarecord = new FormulaRecordAggregate(fr,st);
|
|
|
|
retval= frarecord;
|
|
break;
|
|
|
|
default:
|
|
throw new RuntimeException("UnImplemented Celltype "+type);
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
private short calculatePtgSize(List expressionlist) {
|
|
short retval = 0;
|
|
Iterator iter = expressionlist.iterator();
|
|
while (iter.hasNext()) {
|
|
retval += (short)((Ptg)iter.next()).getSize();
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
private void insertCell(CellValueRecordInterface cell, int type) {
|
|
int rownum = cell.getRow();
|
|
int colnum = cell.getColumn();
|
|
|
|
DoubleList nmRow = (DoubleList)numericcells.get(rownum);
|
|
|
|
switch (type) {
|
|
case HSSFCell.CELL_TYPE_NUMERIC:
|
|
NumberRecord nrecord = (NumberRecord)cell;
|
|
adjustDoubleList(nmRow, colnum+1);
|
|
nmRow.set(colnum,nrecord.getValue());
|
|
physCells++;
|
|
break;
|
|
case HSSFCell.CELL_TYPE_STRING:
|
|
LabelSSTRecord srecord = (LabelSSTRecord)cell;
|
|
adjustDoubleList(nmRow, colnum+1);
|
|
nmRow.set(colnum,srecord.getSSTIndex());
|
|
physCells++;
|
|
break;
|
|
case HSSFCell.CELL_TYPE_FORMULA:
|
|
List ptRow = (List)formulaptgs.get(rownum);
|
|
List stRow = (List)stringvals.get(rownum);
|
|
FormulaRecordAggregate frarecord = (FormulaRecordAggregate)cell;
|
|
adjustDoubleList(nmRow, colnum+1);
|
|
adjustObjectList(ptRow, colnum+1);
|
|
adjustStringList(stRow, colnum+1);
|
|
nmRow.set(colnum,frarecord.getFormulaRecord().getValue());
|
|
ptRow.set(colnum,frarecord.getFormulaRecord().getParsedExpression());
|
|
StringRecord str = frarecord.getStringRecord();
|
|
if (str != null) {
|
|
stRow.set(colnum,str.getString());
|
|
} else {
|
|
stRow.set(colnum,null);
|
|
}
|
|
physCells++;
|
|
break;
|
|
case HSSFCell.CELL_TYPE_BLANK:
|
|
//BlankRecord brecord = (BlankRecord)cell;
|
|
physCells++;
|
|
break;
|
|
|
|
default:
|
|
throw new RuntimeException("UnImplemented Celltype "+cell.toString());
|
|
}
|
|
}
|
|
|
|
private int determineType(CellValueRecordInterface cval)
|
|
{
|
|
Record record = ( Record ) cval;
|
|
int sid = record.getSid();
|
|
int retval = 0;
|
|
|
|
switch (sid)
|
|
{
|
|
|
|
case NumberRecord.sid :
|
|
retval = HSSFCell.CELL_TYPE_NUMERIC;
|
|
break;
|
|
|
|
case BlankRecord.sid :
|
|
retval = HSSFCell.CELL_TYPE_BLANK;
|
|
break;
|
|
|
|
case LabelSSTRecord.sid :
|
|
retval = HSSFCell.CELL_TYPE_STRING;
|
|
break;
|
|
|
|
case FormulaRecordAggregate.sid :
|
|
retval = HSSFCell.CELL_TYPE_FORMULA;
|
|
break;
|
|
|
|
case BoolErrRecord.sid :
|
|
BoolErrRecord boolErrRecord = ( BoolErrRecord ) record;
|
|
|
|
retval = (boolErrRecord.isBoolean())
|
|
? HSSFCell.CELL_TYPE_BOOLEAN
|
|
: HSSFCell.CELL_TYPE_ERROR;
|
|
break;
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
private void ensureRows(int rownum) {
|
|
adjustRows(celltype, rownum+1, IntList.class);
|
|
adjustRows(xfs, rownum+1, IntList.class);
|
|
adjustRows(numericcells, rownum+1, DoubleList.class);
|
|
adjustRows(formulaptgs, rownum+1, ArrayList.class);
|
|
adjustRows(stringvals, rownum+1, ArrayList.class);
|
|
|
|
}
|
|
|
|
private void adjustRows(List list, int size, Class theclass) {
|
|
while (list.size() < size) {
|
|
try {
|
|
list.add(theclass.newInstance());
|
|
} catch (Exception e) {
|
|
throw new RuntimeException("Could Not Instantiate Row in adjustRows");
|
|
}
|
|
}
|
|
}
|
|
|
|
private void adjustIntList(IntList list, int size) {
|
|
while (list.size() < size) {
|
|
list.add(-1);
|
|
}
|
|
}
|
|
|
|
private void adjustDoubleList(DoubleList list, int size) {
|
|
while (list.size() < size) {
|
|
list.add(-1);
|
|
}
|
|
}
|
|
|
|
private void adjustObjectList(List list, int size) {
|
|
while (list.size() < size) {
|
|
list.add(new ArrayList());
|
|
}
|
|
}
|
|
|
|
private void adjustStringList(List list, int size) {
|
|
while (list.size() < size) {
|
|
list.add(new String());
|
|
}
|
|
}
|
|
|
|
|
|
protected int findNextPopulatedCell(int row, int col) {
|
|
|
|
IntList ctRow = (IntList) celltype.get(row);
|
|
int retval = -1;
|
|
if (ctRow.size() > col+1) {
|
|
for (int k = col+1; k < ctRow.size() +1; k++) {
|
|
|
|
if (k != ctRow.size()) {
|
|
int val = ctRow.get(k);
|
|
|
|
if (val != -1) {
|
|
retval = k;
|
|
break;
|
|
} // end if (val !=...
|
|
|
|
} //end if (k !=..
|
|
|
|
} //end for
|
|
|
|
} //end if (ctRow.size()...
|
|
return retval;
|
|
}
|
|
|
|
|
|
|
|
public short getSid() {
|
|
return sid;
|
|
}
|
|
|
|
|
|
public void fillFields(byte[] data, short size, int offset) {
|
|
|
|
}
|
|
|
|
protected void validateSid(short sid) {
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
class VRAIterator implements Iterator {
|
|
private boolean hasNext;
|
|
private ValueRecordsAggregate vra;
|
|
private int popindex;
|
|
private int row;
|
|
private int rowlimit;
|
|
private int col;
|
|
CellValueRecordInterface current = null;
|
|
CellValueRecordInterface next = null;
|
|
|
|
public VRAIterator(ValueRecordsAggregate vra) {
|
|
this(vra, 0, -1);
|
|
}
|
|
|
|
public VRAIterator(ValueRecordsAggregate vra, int row) {
|
|
this(vra, row, row);
|
|
}
|
|
|
|
public VRAIterator(ValueRecordsAggregate vra, int startRow, int endRow) {
|
|
this.vra = vra;
|
|
this.row = startRow;
|
|
this.rowlimit = endRow;
|
|
this.popindex = vra.populatedRows.indexOf(row);
|
|
if (vra.getPhysicalNumberOfCells() > 0) {
|
|
next = findNextCell(null);
|
|
hasNext = (next != null);
|
|
}
|
|
}
|
|
|
|
|
|
public boolean hasNext() {
|
|
return hasNext;
|
|
}
|
|
|
|
public Object next() {
|
|
current = next;
|
|
next = findNextCell(current);
|
|
if (next == null) {
|
|
hasNext = false;
|
|
}
|
|
return current;
|
|
}
|
|
|
|
public void remove() {
|
|
vra.removeCell(current);
|
|
}
|
|
|
|
private CellValueRecordInterface findNextCell(CellValueRecordInterface current) {
|
|
IntList ctRow = null;
|
|
int rowNum = -1;
|
|
int colNum = -1;
|
|
int newCol = -1;
|
|
boolean wasntFirst = false;
|
|
|
|
if (current != null) {
|
|
wasntFirst = true;
|
|
rowNum = current.getRow();
|
|
colNum = current.getColumn();
|
|
ctRow = ((IntList)vra.celltype.get(rowNum));
|
|
}
|
|
|
|
//if popindex = row iwth no cells, fast forward till we get to one with size > 0
|
|
while ((ctRow == null || ctRow.size() == 0) && vra.populatedRows.size() > popindex) {
|
|
if (wasntFirst == true) {
|
|
throw new RuntimeException("CANT HAPPEN WASNTFIRST BUT WE'RE FASTFORWARDING!");
|
|
}
|
|
rowNum = vra.populatedRows.get(popindex);
|
|
ctRow = (IntList)vra.celltype.get(rowNum);
|
|
if (ctRow.size() == 0) {
|
|
if ((rowlimit == -1)||(rowNum<=rowlimit)) {
|
|
popindex++;
|
|
} else {
|
|
this.hasNext = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (rowNum == -1) {
|
|
return null;
|
|
}
|
|
|
|
while (newCol == -1) {
|
|
newCol = findNextPopulatedCell(rowNum,colNum);
|
|
colNum = newCol;
|
|
if (colNum == -1) { //end of row, forward one row
|
|
popindex++;
|
|
if (popindex < vra.populatedRows.size() && ((rowlimit == -1)||(rowNum<=rowlimit))) {
|
|
rowNum = vra.populatedRows.get(popindex);
|
|
//Return null if the row is out of range
|
|
if ((rowlimit != -1) &&( rowNum > rowlimit))
|
|
return null;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
return vra.constructRecord(rowNum,colNum);
|
|
}
|
|
|
|
private int findNextPopulatedCell(int row, int col) {
|
|
|
|
/*IntList ctRow = (IntList) vra.celltype.get(row);
|
|
int retval = -1;
|
|
if (ctRow.size() > col+1) {
|
|
for (int k = col+1; k < ctRow.size() +1; k++) {
|
|
|
|
if (k != ctRow.size()) {
|
|
int val = ctRow.get(k);
|
|
|
|
if (val != -1) {
|
|
retval = k;
|
|
break;
|
|
} // end if (val !=...
|
|
|
|
} //end if (k !=..
|
|
|
|
} //end for
|
|
|
|
} //end if (ctRow.size()...
|
|
return retval;*/
|
|
return vra.findNextPopulatedCell(row, col);
|
|
}
|
|
|
|
} |