mirror of https://github.com/apache/poi.git
Move CellReference from hssf.util into ss.util, but leave a class in the old package to proxy requests on. Also needed tweaks to several things that used it. Finally, add lots more tests, and fix the high column number num<->letter conversion
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@645143 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
ec58464f48
commit
6710416a66
|
@ -20,6 +20,7 @@ import java.io.FileOutputStream;
|
|||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
|
@ -27,6 +28,7 @@ import org.apache.poi.ss.usermodel.CreationHelper;
|
|||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
|
||||
/**
|
||||
|
@ -135,4 +137,20 @@ public class FromQuickGuide {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void getCellContents(Sheet sheet) {
|
||||
for (Row row : sheet) {
|
||||
for (Cell cell : row) {
|
||||
CellReference cellRef = new CellReference(row.getRowNum(), cell.getCellNum());
|
||||
System.out.print(cellRef.formatAsString());
|
||||
|
||||
switch(cell.getCellType()) {
|
||||
case Cell.CELL_TYPE_STRING:
|
||||
System.out.println(cell.getRichStringCellValue().getString());
|
||||
break;
|
||||
case Cell.CELL_TYPE_NUMERIC:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ public class CommentShape extends TextboxShape {
|
|||
private NoteRecord createNoteRecord( HSSFComment shape, int shapeId )
|
||||
{
|
||||
NoteRecord note = new NoteRecord();
|
||||
note.setColumn(shape.getColumn());
|
||||
note.setColumn((short)shape.getColumn());
|
||||
note.setRow((short)shape.getRow());
|
||||
note.setFlags(shape.isVisible() ? NoteRecord.NOTE_VISIBLE : NoteRecord.NOTE_HIDDEN);
|
||||
note.setShapeId((short)shapeId);
|
||||
|
|
|
@ -260,9 +260,9 @@ public class Area3DPtg extends Ptg implements AreaI
|
|||
CellReference lastCell = ar.getLastCell();
|
||||
|
||||
setFirstRow( (short) frstCell.getRow() );
|
||||
setFirstColumn( frstCell.getCol() );
|
||||
setLastRow( (short) lastCell.getRow() );
|
||||
setLastColumn( lastCell.getCol() );
|
||||
setFirstColumn( (short) frstCell.getCol() );
|
||||
setLastRow( (short) lastCell.getRow() );
|
||||
setLastColumn( (short) lastCell.getCol() );
|
||||
setFirstColRelative( !frstCell.isColAbsolute() );
|
||||
setLastColRelative( !lastCell.isColAbsolute() );
|
||||
setFirstRowRelative( !frstCell.isRowAbsolute() );
|
||||
|
|
|
@ -63,7 +63,7 @@ public class Ref3DPtg extends Ptg {
|
|||
public Ref3DPtg(String cellref, short externIdx ) {
|
||||
CellReference c= new CellReference(cellref);
|
||||
setRow(c.getRow());
|
||||
setColumn(c.getCol());
|
||||
setColumn((short)c.getCol());
|
||||
setColRelative(!c.isColAbsolute());
|
||||
setRowRelative(!c.isRowAbsolute());
|
||||
setExternSheetIndex(externIdx);
|
||||
|
|
|
@ -105,7 +105,7 @@ public class HSSFComment extends HSSFTextbox implements Comment {
|
|||
*
|
||||
* @return the 0-based column of the cell that contains the comment
|
||||
*/
|
||||
public short getColumn(){
|
||||
public int getColumn(){
|
||||
return col;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,245 +17,33 @@
|
|||
|
||||
package org.apache.poi.hssf.util;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.SheetNameFormatter;
|
||||
|
||||
/**
|
||||
*
|
||||
* Common convertion functions between Excel style A1, C27 style
|
||||
* cell references, and POI usermodel style row=0, column=0
|
||||
* style references.
|
||||
* @author Avik Sengupta
|
||||
* @author Dennis Doubleday (patch to seperateRowColumns())
|
||||
*/
|
||||
public final class CellReference {
|
||||
/** The character ($) that signifies a row or column value is absolute instead of relative */
|
||||
private static final char ABSOLUTE_REFERENCE_MARKER = '$';
|
||||
/** The character (!) that separates sheet names from cell references */
|
||||
private static final char SHEET_NAME_DELIMITER = '!';
|
||||
/** The character (') used to quote sheet names when they contain special characters */
|
||||
private static final char SPECIAL_NAME_DELIMITER = '\'';
|
||||
|
||||
|
||||
private final int _rowIndex;
|
||||
private final int _colIndex;
|
||||
private final String _sheetName;
|
||||
private final boolean _isRowAbs;
|
||||
private final boolean _isColAbs;
|
||||
|
||||
public final class CellReference extends org.apache.poi.ss.util.CellReference {
|
||||
/**
|
||||
* Create an cell ref from a string representation. Sheet names containing special characters should be
|
||||
* delimited and escaped as per normal syntax rules for formulas.
|
||||
*/
|
||||
public CellReference(String cellRef) {
|
||||
String[] parts = separateRefParts(cellRef);
|
||||
_sheetName = parts[0];
|
||||
String colRef = parts[1];
|
||||
if (colRef.length() < 1) {
|
||||
throw new IllegalArgumentException("Invalid Formula cell reference: '"+cellRef+"'");
|
||||
}
|
||||
_isColAbs = colRef.charAt(0) == '$';
|
||||
if (_isColAbs) {
|
||||
colRef=colRef.substring(1);
|
||||
}
|
||||
_colIndex = convertColStringToNum(colRef);
|
||||
|
||||
String rowRef=parts[2];
|
||||
if (rowRef.length() < 1) {
|
||||
throw new IllegalArgumentException("Invalid Formula cell reference: '"+cellRef+"'");
|
||||
}
|
||||
_isRowAbs = rowRef.charAt(0) == '$';
|
||||
if (_isRowAbs) {
|
||||
rowRef=rowRef.substring(1);
|
||||
}
|
||||
_rowIndex = Integer.parseInt(rowRef)-1; // -1 to convert 1-based to zero-based
|
||||
super(cellRef);
|
||||
}
|
||||
|
||||
public CellReference(int pRow, int pCol, boolean pAbsRow, boolean pAbsCol) {
|
||||
this(null, pRow, pCol, pAbsRow, pAbsCol);
|
||||
}
|
||||
public CellReference(String pSheetName, int pRow, int pCol, boolean pAbsRow, boolean pAbsCol) {
|
||||
// TODO - "-1" is a special value being temporarily used for whole row and whole column area references.
|
||||
// so these checks are currently N.Q.R.
|
||||
if(pRow < -1) {
|
||||
throw new IllegalArgumentException("row index may not be negative");
|
||||
}
|
||||
if(pCol < -1) {
|
||||
throw new IllegalArgumentException("column index may not be negative");
|
||||
}
|
||||
_sheetName = pSheetName;
|
||||
_rowIndex=pRow;
|
||||
_colIndex=pCol;
|
||||
_isRowAbs = pAbsRow;
|
||||
_isColAbs=pAbsCol;
|
||||
}
|
||||
|
||||
public int getRow(){return _rowIndex;}
|
||||
public short getCol(){return (short) _colIndex;}
|
||||
public boolean isRowAbsolute(){return _isRowAbs;}
|
||||
public boolean isColAbsolute(){return _isColAbs;}
|
||||
/**
|
||||
* @return possibly <code>null</code> if this is a 2D reference. Special characters are not
|
||||
* escaped or delimited
|
||||
*/
|
||||
public String getSheetName(){
|
||||
return _sheetName;
|
||||
super(pSheetName, pRow, pCol, pAbsRow, pAbsCol);
|
||||
}
|
||||
|
||||
/**
|
||||
* takes in a column reference portion of a CellRef and converts it from
|
||||
* ALPHA-26 number format to 0-based base 10.
|
||||
*/
|
||||
private int convertColStringToNum(String ref) {
|
||||
int lastIx = ref.length()-1;
|
||||
int retval=0;
|
||||
int pos = 0;
|
||||
|
||||
for (int k = lastIx; k > -1; k--) {
|
||||
char thechar = ref.charAt(k);
|
||||
if ( pos == 0) {
|
||||
retval += (Character.getNumericValue(thechar)-9);
|
||||
} else {
|
||||
retval += (Character.getNumericValue(thechar)-9) * (pos * 26);
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
return retval-1;
|
||||
protected void appendCellReference(StringBuffer sb) {
|
||||
super.appendCellReference(sb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Separates the row from the columns and returns an array of three Strings. The first element
|
||||
* is the sheet name. Only the first element may be null. The second element in is the column
|
||||
* name still in ALPHA-26 number format. The third element is the row.
|
||||
*/
|
||||
private static String[] separateRefParts(String reference) {
|
||||
|
||||
int plingPos = reference.lastIndexOf(SHEET_NAME_DELIMITER);
|
||||
String sheetName = parseSheetName(reference, plingPos);
|
||||
int start = plingPos+1;
|
||||
|
||||
int length = reference.length();
|
||||
|
||||
|
||||
int loc = start;
|
||||
// skip initial dollars
|
||||
if (reference.charAt(loc)==ABSOLUTE_REFERENCE_MARKER) {
|
||||
loc++;
|
||||
}
|
||||
// step over column name chars until first digit (or dollars) for row number.
|
||||
for (; loc < length; loc++) {
|
||||
char ch = reference.charAt(loc);
|
||||
if (Character.isDigit(ch) || ch == ABSOLUTE_REFERENCE_MARKER) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new String[] {
|
||||
sheetName,
|
||||
reference.substring(start,loc),
|
||||
reference.substring(loc),
|
||||
};
|
||||
}
|
||||
|
||||
private static String parseSheetName(String reference, int indexOfSheetNameDelimiter) {
|
||||
if(indexOfSheetNameDelimiter < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean isQuoted = reference.charAt(0) == SPECIAL_NAME_DELIMITER;
|
||||
if(!isQuoted) {
|
||||
return reference.substring(0, indexOfSheetNameDelimiter);
|
||||
}
|
||||
int lastQuotePos = indexOfSheetNameDelimiter-1;
|
||||
if(reference.charAt(lastQuotePos) != SPECIAL_NAME_DELIMITER) {
|
||||
throw new RuntimeException("Mismatched quotes: (" + reference + ")");
|
||||
}
|
||||
|
||||
// TODO - refactor cell reference parsing logic to one place.
|
||||
// Current known incarnations:
|
||||
// FormulaParser.GetName()
|
||||
// CellReference.parseSheetName() (here)
|
||||
// AreaReference.separateAreaRefs()
|
||||
// SheetNameFormatter.format() (inverse)
|
||||
|
||||
StringBuffer sb = new StringBuffer(indexOfSheetNameDelimiter);
|
||||
|
||||
for(int i=1; i<lastQuotePos; i++) { // Note boundaries - skip outer quotes
|
||||
char ch = reference.charAt(i);
|
||||
if(ch != SPECIAL_NAME_DELIMITER) {
|
||||
sb.append(ch);
|
||||
continue;
|
||||
}
|
||||
if(i < lastQuotePos) {
|
||||
if(reference.charAt(i+1) == SPECIAL_NAME_DELIMITER) {
|
||||
// two consecutive quotes is the escape sequence for a single one
|
||||
i++; // skip this and keep parsing the special name
|
||||
sb.append(ch);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("Bad sheet name quote escaping: (" + reference + ")");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes in a 0-based base-10 column and returns a ALPHA-26
|
||||
* representation.
|
||||
* eg column #3 -> D
|
||||
*/
|
||||
protected static String convertNumToColString(int col) {
|
||||
String retval = null;
|
||||
int mod = col % 26;
|
||||
int div = col / 26;
|
||||
char small=(char)(mod + 65);
|
||||
char big = (char)(div + 64);
|
||||
|
||||
if (div == 0) {
|
||||
retval = ""+small;
|
||||
} else {
|
||||
retval = ""+big+""+small;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Example return values:
|
||||
* <table border="0" cellpadding="1" cellspacing="0" summary="Example return values">
|
||||
* <tr><th align='left'>Result</th><th align='left'>Comment</th></tr>
|
||||
* <tr><td>A1</td><td>Cell reference without sheet</td></tr>
|
||||
* <tr><td>Sheet1!A1</td><td>Standard sheet name</td></tr>
|
||||
* <tr><td>'O''Brien''s Sales'!A1' </td><td>Sheet name with special characters</td></tr>
|
||||
* </table>
|
||||
* @return the text representation of this cell reference as it would appear in a formula.
|
||||
*/
|
||||
public String formatAsString() {
|
||||
StringBuffer sb = new StringBuffer(32);
|
||||
if(_sheetName != null) {
|
||||
SheetNameFormatter.appendFormat(sb, _sheetName);
|
||||
sb.append(SHEET_NAME_DELIMITER);
|
||||
}
|
||||
appendCellReference(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer(64);
|
||||
sb.append(getClass().getName()).append(" [");
|
||||
sb.append(formatAsString());
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends cell reference with '$' markers for absolute values as required.
|
||||
* Sheet name is not included.
|
||||
*/
|
||||
/* package */ void appendCellReference(StringBuffer sb) {
|
||||
if(_isColAbs) {
|
||||
sb.append(ABSOLUTE_REFERENCE_MARKER);
|
||||
}
|
||||
sb.append( convertNumToColString(_colIndex));
|
||||
if(_isRowAbs) {
|
||||
sb.append(ABSOLUTE_REFERENCE_MARKER);
|
||||
}
|
||||
sb.append(_rowIndex+1);
|
||||
return org.apache.poi.ss.util.CellReference.convertNumToColString(col);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,293 @@
|
|||
/* ====================================================================
|
||||
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.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ss.util;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.SheetNameFormatter;
|
||||
|
||||
/**
|
||||
* Common convertion functions between Excel style A1, C27 style
|
||||
* cell references, and POI usermodel style row=0, column=0
|
||||
* style references.
|
||||
* Applys for both HSSF and XSSF.
|
||||
* @author Avik Sengupta
|
||||
* @author Dennis Doubleday (patch to seperateRowColumns())
|
||||
*/
|
||||
public class CellReference {
|
||||
/** The character ($) that signifies a row or column value is absolute instead of relative */
|
||||
private static final char ABSOLUTE_REFERENCE_MARKER = '$';
|
||||
/** The character (!) that separates sheet names from cell references */
|
||||
private static final char SHEET_NAME_DELIMITER = '!';
|
||||
/** The character (') used to quote sheet names when they contain special characters */
|
||||
private static final char SPECIAL_NAME_DELIMITER = '\'';
|
||||
|
||||
|
||||
private final int _rowIndex;
|
||||
private final int _colIndex;
|
||||
private final String _sheetName;
|
||||
private final boolean _isRowAbs;
|
||||
private final boolean _isColAbs;
|
||||
|
||||
/**
|
||||
* Create an cell ref from a string representation. Sheet names containing special characters should be
|
||||
* delimited and escaped as per normal syntax rules for formulas.
|
||||
*/
|
||||
public CellReference(String cellRef) {
|
||||
String[] parts = separateRefParts(cellRef);
|
||||
_sheetName = parts[0];
|
||||
String colRef = parts[1];
|
||||
if (colRef.length() < 1) {
|
||||
throw new IllegalArgumentException("Invalid Formula cell reference: '"+cellRef+"'");
|
||||
}
|
||||
_isColAbs = colRef.charAt(0) == '$';
|
||||
if (_isColAbs) {
|
||||
colRef=colRef.substring(1);
|
||||
}
|
||||
_colIndex = convertColStringToNum(colRef);
|
||||
|
||||
String rowRef=parts[2];
|
||||
if (rowRef.length() < 1) {
|
||||
throw new IllegalArgumentException("Invalid Formula cell reference: '"+cellRef+"'");
|
||||
}
|
||||
_isRowAbs = rowRef.charAt(0) == '$';
|
||||
if (_isRowAbs) {
|
||||
rowRef=rowRef.substring(1);
|
||||
}
|
||||
_rowIndex = Integer.parseInt(rowRef)-1; // -1 to convert 1-based to zero-based
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a cell reference for the given row and cell.
|
||||
* Assumes these references are relative
|
||||
*/
|
||||
public CellReference(int row, int col) {
|
||||
this(row, col, false, false);
|
||||
}
|
||||
public CellReference(int pRow, int pCol, boolean pAbsRow, boolean pAbsCol) {
|
||||
this(null, pRow, pCol, pAbsRow, pAbsCol);
|
||||
}
|
||||
public CellReference(String pSheetName, int pRow, int pCol, boolean pAbsRow, boolean pAbsCol) {
|
||||
// TODO - "-1" is a special value being temporarily used for whole row and whole column area references.
|
||||
// so these checks are currently N.Q.R.
|
||||
if(pRow < -1) {
|
||||
throw new IllegalArgumentException("row index may not be negative");
|
||||
}
|
||||
if(pCol < -1) {
|
||||
throw new IllegalArgumentException("column index may not be negative");
|
||||
}
|
||||
_sheetName = pSheetName;
|
||||
_rowIndex=pRow;
|
||||
_colIndex=pCol;
|
||||
_isRowAbs = pAbsRow;
|
||||
_isColAbs=pAbsCol;
|
||||
}
|
||||
|
||||
public int getRow(){return _rowIndex;}
|
||||
public int getCol(){return _colIndex;}
|
||||
public boolean isRowAbsolute(){return _isRowAbs;}
|
||||
public boolean isColAbsolute(){return _isColAbs;}
|
||||
/**
|
||||
* @return possibly <code>null</code> if this is a 2D reference. Special characters are not
|
||||
* escaped or delimited
|
||||
*/
|
||||
public String getSheetName(){
|
||||
return _sheetName;
|
||||
}
|
||||
|
||||
/**
|
||||
* takes in a column reference portion of a CellRef and converts it from
|
||||
* ALPHA-26 number format to 0-based base 10.
|
||||
* ALPHA-26 goes A to Z, then AA to AZ, BA to BZ, ..., ZA to ZZ,
|
||||
* AAA to AAZ, ABA to ABZ, ..., AZA to AZZ, BAA to BAZ etc
|
||||
*/
|
||||
private int convertColStringToNum(String ref) {
|
||||
int lastIx = ref.length()-1;
|
||||
int retval=0;
|
||||
int pos = 0;
|
||||
|
||||
for (int k = lastIx; k > -1; k--) {
|
||||
char thechar = ref.charAt(k);
|
||||
// Character.getNumericValue() returns the values
|
||||
// 10-35 for the letter A-Z
|
||||
int shift = (int)Math.pow(26, pos);
|
||||
retval += (Character.getNumericValue(thechar)-9) * shift;
|
||||
pos++;
|
||||
}
|
||||
return retval-1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Separates the row from the columns and returns an array of three Strings. The first element
|
||||
* is the sheet name. Only the first element may be null. The second element in is the column
|
||||
* name still in ALPHA-26 number format. The third element is the row.
|
||||
*/
|
||||
private static String[] separateRefParts(String reference) {
|
||||
|
||||
int plingPos = reference.lastIndexOf(SHEET_NAME_DELIMITER);
|
||||
String sheetName = parseSheetName(reference, plingPos);
|
||||
int start = plingPos+1;
|
||||
|
||||
int length = reference.length();
|
||||
|
||||
|
||||
int loc = start;
|
||||
// skip initial dollars
|
||||
if (reference.charAt(loc)==ABSOLUTE_REFERENCE_MARKER) {
|
||||
loc++;
|
||||
}
|
||||
// step over column name chars until first digit (or dollars) for row number.
|
||||
for (; loc < length; loc++) {
|
||||
char ch = reference.charAt(loc);
|
||||
if (Character.isDigit(ch) || ch == ABSOLUTE_REFERENCE_MARKER) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new String[] {
|
||||
sheetName,
|
||||
reference.substring(start,loc),
|
||||
reference.substring(loc),
|
||||
};
|
||||
}
|
||||
|
||||
private static String parseSheetName(String reference, int indexOfSheetNameDelimiter) {
|
||||
if(indexOfSheetNameDelimiter < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean isQuoted = reference.charAt(0) == SPECIAL_NAME_DELIMITER;
|
||||
if(!isQuoted) {
|
||||
return reference.substring(0, indexOfSheetNameDelimiter);
|
||||
}
|
||||
int lastQuotePos = indexOfSheetNameDelimiter-1;
|
||||
if(reference.charAt(lastQuotePos) != SPECIAL_NAME_DELIMITER) {
|
||||
throw new RuntimeException("Mismatched quotes: (" + reference + ")");
|
||||
}
|
||||
|
||||
// TODO - refactor cell reference parsing logic to one place.
|
||||
// Current known incarnations:
|
||||
// FormulaParser.GetName()
|
||||
// CellReference.parseSheetName() (here)
|
||||
// AreaReference.separateAreaRefs()
|
||||
// SheetNameFormatter.format() (inverse)
|
||||
|
||||
StringBuffer sb = new StringBuffer(indexOfSheetNameDelimiter);
|
||||
|
||||
for(int i=1; i<lastQuotePos; i++) { // Note boundaries - skip outer quotes
|
||||
char ch = reference.charAt(i);
|
||||
if(ch != SPECIAL_NAME_DELIMITER) {
|
||||
sb.append(ch);
|
||||
continue;
|
||||
}
|
||||
if(i < lastQuotePos) {
|
||||
if(reference.charAt(i+1) == SPECIAL_NAME_DELIMITER) {
|
||||
// two consecutive quotes is the escape sequence for a single one
|
||||
i++; // skip this and keep parsing the special name
|
||||
sb.append(ch);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("Bad sheet name quote escaping: (" + reference + ")");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes in a 0-based base-10 column and returns a ALPHA-26
|
||||
* representation.
|
||||
* eg column #3 -> D
|
||||
*/
|
||||
protected static String convertNumToColString(int col) {
|
||||
// Excel counts column A as the 1st column, we
|
||||
// treat it as the 0th one
|
||||
int excelColNum = col + 1;
|
||||
|
||||
String colRef = "";
|
||||
int colRemain = excelColNum;
|
||||
|
||||
while(colRemain > 0) {
|
||||
int thisPart = colRemain % 26;
|
||||
if(thisPart == 0) { thisPart = 26; }
|
||||
colRemain = (colRemain - thisPart) / 26;
|
||||
|
||||
// The letter A is at 65
|
||||
char colChar = (char)(thisPart+64);
|
||||
colRef = colChar + colRef;
|
||||
}
|
||||
|
||||
return colRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Example return values:
|
||||
* <table border="0" cellpadding="1" cellspacing="0" summary="Example return values">
|
||||
* <tr><th align='left'>Result</th><th align='left'>Comment</th></tr>
|
||||
* <tr><td>A1</td><td>Cell reference without sheet</td></tr>
|
||||
* <tr><td>Sheet1!A1</td><td>Standard sheet name</td></tr>
|
||||
* <tr><td>'O''Brien''s Sales'!A1' </td><td>Sheet name with special characters</td></tr>
|
||||
* </table>
|
||||
* @return the text representation of this cell reference as it would appear in a formula.
|
||||
*/
|
||||
public String formatAsString() {
|
||||
StringBuffer sb = new StringBuffer(32);
|
||||
if(_sheetName != null) {
|
||||
SheetNameFormatter.appendFormat(sb, _sheetName);
|
||||
sb.append(SHEET_NAME_DELIMITER);
|
||||
}
|
||||
appendCellReference(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer(64);
|
||||
sb.append(getClass().getName()).append(" [");
|
||||
sb.append(formatAsString());
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the three parts of the cell reference, the
|
||||
* Sheet name (or null if none supplied), the 1 based
|
||||
* row number, and the A based column letter.
|
||||
* This will not include any markers for absolute
|
||||
* references, so use {@link #formatAsString()}
|
||||
* to properly turn references into strings.
|
||||
*/
|
||||
public String[] getCellRefParts() {
|
||||
return new String[] {
|
||||
_sheetName,
|
||||
Integer.toString(_rowIndex+1),
|
||||
convertNumToColString(_colIndex)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends cell reference with '$' markers for absolute values as required.
|
||||
* Sheet name is not included.
|
||||
*/
|
||||
protected void appendCellReference(StringBuffer sb) {
|
||||
if(_isColAbs) {
|
||||
sb.append(ABSOLUTE_REFERENCE_MARKER);
|
||||
}
|
||||
sb.append( convertNumToColString(_colIndex));
|
||||
if(_isRowAbs) {
|
||||
sb.append(ABSOLUTE_REFERENCE_MARKER);
|
||||
}
|
||||
sb.append(_rowIndex+1);
|
||||
}
|
||||
}
|
|
@ -52,7 +52,7 @@ public interface Comment {
|
|||
*
|
||||
* @return the 0-based column of the cell that contains the comment
|
||||
*/
|
||||
short getColumn();
|
||||
int getColumn();
|
||||
|
||||
/**
|
||||
* Set the column of the cell that contains the comment
|
||||
|
|
|
@ -22,8 +22,8 @@ import java.io.OutputStream;
|
|||
|
||||
import org.apache.poi.ss.usermodel.Comment;
|
||||
import org.apache.poi.ss.usermodel.CommentsSource;
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
import org.apache.poi.xssf.usermodel.XSSFComment;
|
||||
import org.apache.poi.xssf.util.CellReference;
|
||||
import org.apache.xmlbeans.XmlException;
|
||||
import org.apache.xmlbeans.XmlOptions;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTAuthors;
|
||||
|
@ -90,7 +90,8 @@ public class CommentsTable implements CommentsSource, XSSFModel {
|
|||
}
|
||||
|
||||
public XSSFComment findCellComment(int row, int column) {
|
||||
return findCellComment(new CellReference().convertRowColToString((short)row, (short)column));
|
||||
return findCellComment(
|
||||
(new CellReference(row, column)).formatAsString() );
|
||||
}
|
||||
|
||||
public XSSFComment findCellComment(String cellRef) {
|
||||
|
|
|
@ -29,7 +29,7 @@ import org.apache.poi.ss.usermodel.SharedStringSource;
|
|||
import org.apache.poi.ss.usermodel.StylesSource;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
import org.apache.poi.xssf.util.CellReference;
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellType;
|
||||
|
@ -222,7 +222,8 @@ public class XSSFCell implements Cell {
|
|||
}
|
||||
|
||||
public void setCellComment(Comment comment) {
|
||||
String cellRef = new CellReference().convertRowColToString((short) row.getRowNum(), getCellNum());
|
||||
String cellRef =
|
||||
new CellReference(row.getRowNum(), getCellNum()).formatAsString();
|
||||
row.getSheet().setCellComment(cellRef, (XSSFComment)comment);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ import org.apache.poi.ss.usermodel.Comment;
|
|||
import org.apache.poi.ss.usermodel.CommentsSource;
|
||||
import org.apache.poi.ss.usermodel.RichTextString;
|
||||
import org.apache.poi.xssf.usermodel.helpers.RichTextStringHelper;
|
||||
import org.apache.poi.xssf.util.CellReference;
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst;
|
||||
|
||||
|
@ -42,7 +42,7 @@ public class XSSFComment implements Comment {
|
|||
return comments.getAuthor(comment.getAuthorId());
|
||||
}
|
||||
|
||||
public short getColumn() {
|
||||
public int getColumn() {
|
||||
return (new CellReference(comment.getRef())).getCol();
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,8 @@ public class XSSFComment implements Comment {
|
|||
|
||||
public void setColumn(short col) {
|
||||
initializeRef();
|
||||
String newRef = (new CellReference(comment.getRef())).convertRowColToString((short) getRow(), col);
|
||||
String newRef =
|
||||
(new CellReference(getRow(), col)).formatAsString();
|
||||
comment.setRef(newRef);
|
||||
}
|
||||
|
||||
|
@ -75,7 +76,8 @@ public class XSSFComment implements Comment {
|
|||
|
||||
public void setRow(int row) {
|
||||
initializeRef();
|
||||
String newRef = (new CellReference(comment.getRef())).convertRowColToString((short) row, getColumn());
|
||||
String newRef =
|
||||
(new CellReference(row, getColumn())).formatAsString();
|
||||
comment.setRef(newRef);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,9 +34,9 @@ import org.apache.poi.ss.usermodel.Patriarch;
|
|||
import org.apache.poi.ss.usermodel.PrintSetup;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
import org.apache.poi.xssf.model.CommentsTable;
|
||||
import org.apache.poi.xssf.usermodel.helpers.ColumnHelper;
|
||||
import org.apache.poi.xssf.util.CellReference;
|
||||
import org.apache.xmlbeans.XmlOptions;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBreak;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCols;
|
||||
|
@ -377,7 +377,7 @@ public class XSSFSheet implements Sheet {
|
|||
public short getLeftCol() {
|
||||
String cellRef = worksheet.getSheetViews().getSheetViewArray(0).getTopLeftCell();
|
||||
CellReference cellReference = new CellReference(cellRef);
|
||||
return cellReference.getCol();
|
||||
return (short)cellReference.getCol();
|
||||
}
|
||||
|
||||
public double getMargin(short margin) {
|
||||
|
@ -832,8 +832,8 @@ public class XSSFSheet implements Sheet {
|
|||
}
|
||||
|
||||
public void showInPane(short toprow, short leftcol) {
|
||||
CellReference cellReference = new CellReference();
|
||||
String cellRef = cellReference.convertRowColToString(toprow, leftcol);
|
||||
CellReference cellReference = new CellReference(toprow, leftcol);
|
||||
String cellRef = cellReference.formatAsString();
|
||||
getSheetTypeSheetView().setTopLeftCell(cellRef);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,102 +0,0 @@
|
|||
/* ====================================================================
|
||||
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.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.xssf.util;
|
||||
|
||||
public class CellReference {
|
||||
|
||||
private int row;
|
||||
private short col;
|
||||
|
||||
public CellReference() {
|
||||
}
|
||||
|
||||
public CellReference(String cellRef) {
|
||||
if (cellRef == null || "".equals(cellRef)) {
|
||||
throw new IllegalArgumentException("Invalid Formula cell reference: '"+cellRef+"'");
|
||||
}
|
||||
String[] parts = getCellRefParts(cellRef);
|
||||
col = getColNumFromRef(parts[0]);
|
||||
row = getRowNumFromRef(parts[1]);
|
||||
}
|
||||
|
||||
public CellReference(short col, int row) {
|
||||
this.col = col;
|
||||
this.row = row;
|
||||
}
|
||||
|
||||
public int getRow() {
|
||||
return this.row;
|
||||
}
|
||||
|
||||
public short getCol() {
|
||||
return this.col;
|
||||
}
|
||||
|
||||
public String[] getCellRefParts(String cellRef) {
|
||||
StringBuffer sb0 = new StringBuffer("");
|
||||
StringBuffer sb1 = new StringBuffer("");
|
||||
String[] parts = new String[2];
|
||||
for (int i = 0 ; i < cellRef.length() ; i++) {
|
||||
char item = cellRef.charAt(i);
|
||||
if ((int)item >= 65 && (int)item <= 90) {
|
||||
sb0.append(item);
|
||||
}
|
||||
else {
|
||||
sb1.append(item);
|
||||
}
|
||||
}
|
||||
parts[0] = sb0.toString();
|
||||
parts[1] = sb1.toString();
|
||||
return parts;
|
||||
}
|
||||
|
||||
public int getRowNumFromRef(String rowRef) {
|
||||
return (new Integer(rowRef).intValue()) - 1;
|
||||
}
|
||||
|
||||
public short getColNumFromRef(String colRef) {
|
||||
double columnIndex = -1;
|
||||
for (int i = (colRef.length() - 1) ; i >= 0 ; i--) {
|
||||
char numericCharValue = colRef.charAt(colRef.length() - (i + 1));
|
||||
int convertedNumericCharValue = (numericCharValue - 64);
|
||||
double indexIncrement = (convertedNumericCharValue * Math.pow(26, i));
|
||||
columnIndex = columnIndex + indexIncrement;
|
||||
}
|
||||
return (short)columnIndex;
|
||||
}
|
||||
|
||||
public String convertNumToColString(short col) {
|
||||
String colRef = "";
|
||||
double div = 1;
|
||||
double mod = 0;
|
||||
for (int i = 0 ; div >= 1 ; i ++) {
|
||||
mod = col % 26;
|
||||
div = col / 26;
|
||||
int AsciiIncrement = (i != 0 ? 64 : 65);
|
||||
char modToChar = (char)(mod + AsciiIncrement);
|
||||
colRef = modToChar + colRef;
|
||||
col = (short) ((col - mod) / 26);
|
||||
}
|
||||
return colRef;
|
||||
}
|
||||
|
||||
public String convertRowColToString(short row, short col) {
|
||||
return convertNumToColString(col) + ((short) (row + 1));
|
||||
}
|
||||
|
||||
}
|
|
@ -19,8 +19,8 @@ package org.apache.poi.xssf.usermodel;
|
|||
|
||||
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
|
||||
import org.apache.poi.ss.usermodel.RichTextString;
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
import org.apache.poi.xssf.model.CommentsTable;
|
||||
import org.apache.poi.xssf.util.CellReference;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTAuthors;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComments;
|
||||
|
|
|
@ -17,101 +17,155 @@
|
|||
|
||||
package org.apache.poi.xssf.util;
|
||||
|
||||
import org.apache.poi.xssf.util.CellReference;
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
|
||||
/**
|
||||
* Tests that the common CellReference works as we need it to
|
||||
*/
|
||||
public class TestCellReference extends TestCase {
|
||||
|
||||
public void testGetCellRefParts() {
|
||||
CellReference cellReference;
|
||||
String[] parts;
|
||||
|
||||
String cellRef = "A1";
|
||||
CellReference cellReference = new CellReference(cellRef);
|
||||
String[] parts = cellReference.getCellRefParts(cellRef);
|
||||
cellReference = new CellReference(cellRef);
|
||||
assertEquals(0, cellReference.getCol());
|
||||
parts = cellReference.getCellRefParts();
|
||||
assertNotNull(parts);
|
||||
assertEquals("A", parts[0]);
|
||||
assertEquals(null, parts[0]);
|
||||
assertEquals("1", parts[1]);
|
||||
assertEquals("A", parts[2]);
|
||||
|
||||
cellRef = "AA1";
|
||||
cellReference = new CellReference(cellRef);
|
||||
parts = cellReference.getCellRefParts(cellRef);
|
||||
assertEquals(26, cellReference.getCol());
|
||||
parts = cellReference.getCellRefParts();
|
||||
assertNotNull(parts);
|
||||
assertEquals("AA", parts[0]);
|
||||
assertEquals(null, parts[0]);
|
||||
assertEquals("1", parts[1]);
|
||||
assertEquals("AA", parts[2]);
|
||||
|
||||
cellRef = "AA100";
|
||||
cellReference = new CellReference(cellRef);
|
||||
parts = cellReference.getCellRefParts(cellRef);
|
||||
assertEquals(26, cellReference.getCol());
|
||||
parts = cellReference.getCellRefParts();
|
||||
assertNotNull(parts);
|
||||
assertEquals("AA", parts[0]);
|
||||
assertEquals(null, parts[0]);
|
||||
assertEquals("100", parts[1]);
|
||||
assertEquals("AA", parts[2]);
|
||||
|
||||
cellRef = "AAA300";
|
||||
cellReference = new CellReference(cellRef);
|
||||
assertEquals(702, cellReference.getCol());
|
||||
parts = cellReference.getCellRefParts();
|
||||
assertNotNull(parts);
|
||||
assertEquals(null, parts[0]);
|
||||
assertEquals("300", parts[1]);
|
||||
assertEquals("AAA", parts[2]);
|
||||
|
||||
cellRef = "ZZ100521";
|
||||
cellReference = new CellReference(cellRef);
|
||||
assertEquals(26*26+25, cellReference.getCol());
|
||||
parts = cellReference.getCellRefParts();
|
||||
assertNotNull(parts);
|
||||
assertEquals(null, parts[0]);
|
||||
assertEquals("100521", parts[1]);
|
||||
assertEquals("ZZ", parts[2]);
|
||||
|
||||
cellRef = "ZYX987";
|
||||
cellReference = new CellReference(cellRef);
|
||||
assertEquals(26*26*26 + 25*26 + 24 - 1, cellReference.getCol());
|
||||
parts = cellReference.getCellRefParts();
|
||||
assertNotNull(parts);
|
||||
assertEquals(null, parts[0]);
|
||||
assertEquals("987", parts[1]);
|
||||
assertEquals("ZYX", parts[2]);
|
||||
|
||||
cellRef = "AABC10065";
|
||||
cellReference = new CellReference(cellRef);
|
||||
parts = cellReference.getCellRefParts(cellRef);
|
||||
parts = cellReference.getCellRefParts();
|
||||
assertNotNull(parts);
|
||||
assertEquals("AABC", parts[0]);
|
||||
assertEquals(null, parts[0]);
|
||||
assertEquals("10065", parts[1]);
|
||||
assertEquals("AABC", parts[2]);
|
||||
}
|
||||
|
||||
public void testGetColNumFromRef() {
|
||||
String cellRef = "A1";
|
||||
CellReference cellReference = new CellReference(cellRef);
|
||||
String[] parts = cellReference.getCellRefParts(cellRef);
|
||||
short col = cellReference.getColNumFromRef(parts[0]);
|
||||
assertEquals(0, col);
|
||||
assertEquals(0, cellReference.getCol());
|
||||
|
||||
cellRef = "AA1";
|
||||
cellReference = new CellReference(cellRef);
|
||||
assertEquals(26, cellReference.getCol());
|
||||
|
||||
cellRef = "AB1";
|
||||
cellReference = new CellReference(cellRef);
|
||||
parts = cellReference.getCellRefParts(cellRef);
|
||||
col = cellReference.getColNumFromRef(parts[0]);
|
||||
assertEquals(27, col);
|
||||
assertEquals(27, cellReference.getCol());
|
||||
|
||||
cellRef = "BA1";
|
||||
cellReference = new CellReference(cellRef);
|
||||
assertEquals(26+26, cellReference.getCol());
|
||||
|
||||
cellRef = "CA1";
|
||||
cellReference = new CellReference(cellRef);
|
||||
assertEquals(26+26+26, cellReference.getCol());
|
||||
|
||||
cellRef = "ZA1";
|
||||
cellReference = new CellReference(cellRef);
|
||||
assertEquals(26*26, cellReference.getCol());
|
||||
|
||||
cellRef = "ZZ1";
|
||||
cellReference = new CellReference(cellRef);
|
||||
assertEquals(26*26+25, cellReference.getCol());
|
||||
|
||||
cellRef = "AAA1";
|
||||
cellReference = new CellReference(cellRef);
|
||||
assertEquals(26*26+26, cellReference.getCol());
|
||||
|
||||
|
||||
cellRef = "A1100";
|
||||
cellReference = new CellReference(cellRef);
|
||||
parts = cellReference.getCellRefParts(cellRef);
|
||||
col = cellReference.getColNumFromRef(parts[0]);
|
||||
assertEquals(0, col);
|
||||
assertEquals(0, cellReference.getCol());
|
||||
|
||||
cellRef = "BC15";
|
||||
cellReference = new CellReference(cellRef);
|
||||
parts = cellReference.getCellRefParts(cellRef);
|
||||
col = cellReference.getColNumFromRef(parts[0]);
|
||||
assertEquals(54, col);
|
||||
assertEquals(54, cellReference.getCol());
|
||||
}
|
||||
|
||||
public void testGetRowNumFromRef() {
|
||||
String cellRef = "A1";
|
||||
CellReference cellReference = new CellReference(cellRef);
|
||||
String[] parts = cellReference.getCellRefParts(cellRef);
|
||||
int row = cellReference.getRowNumFromRef(parts[1]);
|
||||
assertEquals(0, row);
|
||||
assertEquals(0, cellReference.getRow());
|
||||
|
||||
cellRef = "A12";
|
||||
cellReference = new CellReference(cellRef);
|
||||
parts = cellReference.getCellRefParts(cellRef);
|
||||
row = cellReference.getRowNumFromRef(parts[1]);
|
||||
assertEquals(11, row);
|
||||
assertEquals(11, cellReference.getRow());
|
||||
|
||||
cellRef = "AS121";
|
||||
cellReference = new CellReference(cellRef);
|
||||
parts = cellReference.getCellRefParts(cellRef);
|
||||
row = cellReference.getRowNumFromRef(parts[1]);
|
||||
assertEquals(120, row);
|
||||
assertEquals(120, cellReference.getRow());
|
||||
}
|
||||
|
||||
public void testConvertNumToColString() {
|
||||
short col = 702;
|
||||
String collRef = new CellReference().convertNumToColString(col);
|
||||
assertEquals("AAA", collRef);
|
||||
System.err.println("***");
|
||||
String collRef = new CellReference(0, col).formatAsString();
|
||||
assertEquals("AAA1", collRef);
|
||||
|
||||
short col2 = 0;
|
||||
String collRef2 = new CellReference().convertNumToColString(col2);
|
||||
assertEquals("A", collRef2);
|
||||
String collRef2 = new CellReference(0, col2).formatAsString();
|
||||
assertEquals("A1", collRef2);
|
||||
|
||||
short col3 = 27;
|
||||
String collRef3 = new CellReference().convertNumToColString(col3);
|
||||
assertEquals("AB", collRef3);
|
||||
String collRef3 = new CellReference(0, col3).formatAsString();
|
||||
assertEquals("AB1", collRef3);
|
||||
|
||||
short col4 = 2080;
|
||||
String collRef4 = new CellReference(0, col4).formatAsString();
|
||||
assertEquals("CBA1", collRef4);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue