Browse Source

Consolidating various duplicates of CellRangeAddress

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@682282 13f79535-47bb-0310-9956-ffa450edef68
tags/REL_3_2_FINAL
Josh Micich 16 years ago
parent
commit
ba2c1e7beb
26 changed files with 1229 additions and 1488 deletions
  1. 249
    189
      src/contrib/src/org/apache/poi/hssf/usermodel/contrib/HSSFRegionUtil.java
  2. 13
    8
      src/java/org/apache/poi/hssf/dev/HSSF.java
  3. 10
    21
      src/java/org/apache/poi/hssf/model/Sheet.java
  4. 48
    69
      src/java/org/apache/poi/hssf/record/CFHeaderRecord.java
  5. 1
    1
      src/java/org/apache/poi/hssf/record/DVRecord.java
  6. 50
    178
      src/java/org/apache/poi/hssf/record/MergeCellsRecord.java
  7. 104
    143
      src/java/org/apache/poi/hssf/record/SelectionRecord.java
  8. 2
    2
      src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java
  9. 0
    513
      src/java/org/apache/poi/hssf/record/cf/CellRange.java
  10. 363
    0
      src/java/org/apache/poi/hssf/record/cf/CellRangeUtil.java
  11. 10
    6
      src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormatting.java
  12. 56
    32
      src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
  13. 10
    17
      src/java/org/apache/poi/hssf/usermodel/HSSFSheetConditionalFormatting.java
  14. 63
    15
      src/java/org/apache/poi/hssf/util/CellRangeAddress.java
  15. 32
    4
      src/java/org/apache/poi/hssf/util/CellRangeAddressList.java
  16. 46
    82
      src/java/org/apache/poi/hssf/util/Region.java
  17. 12
    19
      src/testcases/org/apache/poi/hssf/record/TestCFHeaderRecord.java
  18. 9
    10
      src/testcases/org/apache/poi/hssf/record/TestMergeCellsRecord.java
  19. 4
    11
      src/testcases/org/apache/poi/hssf/record/aggregates/TestCFRecordsAggregate.java
  20. 74
    72
      src/testcases/org/apache/poi/hssf/record/cf/TestCellRange.java
  21. 7
    7
      src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
  22. 9
    16
      src/testcases/org/apache/poi/hssf/usermodel/TestCloneSheet.java
  23. 3
    3
      src/testcases/org/apache/poi/hssf/usermodel/TestDataValidation.java
  24. 9
    10
      src/testcases/org/apache/poi/hssf/usermodel/TestHSSFConditionalFormatting.java
  25. 12
    12
      src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java
  26. 33
    48
      src/testcases/org/apache/poi/hssf/usermodel/TestWorkbook.java

+ 249
- 189
src/contrib/src/org/apache/poi/hssf/usermodel/contrib/HSSFRegionUtil.java View File

@@ -21,197 +21,257 @@ import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.hssf.util.Region;

/**
* Various utility functions that make working with a region of cells easier.
*
*@author Eric Pugh epugh@upstate.com
*@since July 29, 2002
* Various utility functions that make working with a region of cells easier.
*
* @author Eric Pugh epugh@upstate.com
*/
public final class HSSFRegionUtil
{

/** Constructor for the HSSFRegionUtil object */
private HSSFRegionUtil() {
// no instances of this class
}

/**
* Sets the left border for a region of cells by manipulating the cell style
* of the individual cells on the left
*
*@param border The new border
*@param region The region that should have the border
*@param workbook The workbook that the region is on.
*@param sheet The sheet that the region is on.
*/
public static void setBorderLeft( short border, Region region, HSSFSheet sheet, HSSFWorkbook workbook )
{
int rowStart = region.getRowFrom();
int rowEnd = region.getRowTo();
int column = region.getColumnFrom();

for ( int i = rowStart; i <= rowEnd; i++ ) {
HSSFRow row = HSSFCellUtil.getRow( i, sheet );
HSSFCell cell = HSSFCellUtil.getCell( row, column );
HSSFCellUtil.setCellStyleProperty(
cell, workbook, HSSFCellUtil.BORDER_LEFT, new Short( border ) );
}
}

/**
* Sets the leftBorderColor attribute of the HSSFRegionUtil object
*
*@param color The color of the border
*@param region The region that should have the border
*@param workbook The workbook that the region is on.
*@param sheet The sheet that the region is on.
*/
public static void setLeftBorderColor( short color, Region region, HSSFSheet sheet, HSSFWorkbook workbook )
{
int rowStart = region.getRowFrom();
int rowEnd = region.getRowTo();
int column = region.getColumnFrom();

for ( int i = rowStart; i <= rowEnd; i++ ) {
HSSFRow row = HSSFCellUtil.getRow( i, sheet );
HSSFCell cell = HSSFCellUtil.getCell( row, column );
HSSFCellUtil.setCellStyleProperty(
cell, workbook, HSSFCellUtil.LEFT_BORDER_COLOR, new Short( color ) );
}
}

/**
* Sets the borderRight attribute of the HSSFRegionUtil object
*
*@param border The new border
*@param region The region that should have the border
*@param workbook The workbook that the region is on.
*@param sheet The sheet that the region is on.
*/
public static void setBorderRight( short border, Region region, HSSFSheet sheet, HSSFWorkbook workbook )
{
int rowStart = region.getRowFrom();
int rowEnd = region.getRowTo();
int column = region.getColumnTo();

for ( int i = rowStart; i <= rowEnd; i++ ) {
HSSFRow row = HSSFCellUtil.getRow( i, sheet );
HSSFCell cell = HSSFCellUtil.getCell( row, column );

HSSFCellUtil.setCellStyleProperty(
cell, workbook, HSSFCellUtil.BORDER_RIGHT, new Short( border ) );
}
}

/**
* Sets the rightBorderColor attribute of the HSSFRegionUtil object
*
*@param color The color of the border
*@param region The region that should have the border
*@param workbook The workbook that the region is on.
*@param sheet The sheet that the region is on.
*/
public static void setRightBorderColor( short color, Region region, HSSFSheet sheet, HSSFWorkbook workbook )
{
int rowStart = region.getRowFrom();
int rowEnd = region.getRowTo();
int column = region.getColumnTo();

for ( int i = rowStart; i <= rowEnd; i++ ) {
HSSFRow row = HSSFCellUtil.getRow( i, sheet );
HSSFCell cell = HSSFCellUtil.getCell( row, column );
HSSFCellUtil.setCellStyleProperty(
cell, workbook, HSSFCellUtil.RIGHT_BORDER_COLOR, new Short( color ) );
}
}

/**
* Sets the borderBottom attribute of the HSSFRegionUtil object
*
*@param border The new border
*@param region The region that should have the border
*@param workbook The workbook that the region is on.
*@param sheet The sheet that the region is on.
*/
public static void setBorderBottom( short border, Region region, HSSFSheet sheet, HSSFWorkbook workbook )
{
int colStart = region.getColumnFrom();
int colEnd = region.getColumnTo();
int rowIndex = region.getRowTo();
HSSFRow row = HSSFCellUtil.getRow( rowIndex, sheet );
for ( int i = colStart; i <= colEnd; i++ ) {

HSSFCell cell = HSSFCellUtil.getCell( row, i );
HSSFCellUtil.setCellStyleProperty(
cell, workbook, HSSFCellUtil.BORDER_BOTTOM, new Short( border ) );
}
}

/**
* Sets the bottomBorderColor attribute of the HSSFRegionUtil object
*
*@param color The color of the border
*@param region The region that should have the border
*@param workbook The workbook that the region is on.
*@param sheet The sheet that the region is on.
*/
public static void setBottomBorderColor( short color, Region region, HSSFSheet sheet, HSSFWorkbook workbook )
{
int colStart = region.getColumnFrom();
int colEnd = region.getColumnTo();
int rowIndex = region.getRowTo();
HSSFRow row = HSSFCellUtil.getRow( rowIndex, sheet );
for ( int i = colStart; i <= colEnd; i++ ) {
HSSFCell cell = HSSFCellUtil.getCell( row, i );
HSSFCellUtil.setCellStyleProperty(
cell, workbook, HSSFCellUtil.BOTTOM_BORDER_COLOR, new Short( color ) );
}
}

/**
* Sets the borderBottom attribute of the HSSFRegionUtil object
*
*@param border The new border
*@param region The region that should have the border
*@param workbook The workbook that the region is on.
*@param sheet The sheet that the region is on.
*/
public static void setBorderTop( short border, Region region, HSSFSheet sheet, HSSFWorkbook workbook )
{
int colStart = region.getColumnFrom();
int colEnd = region.getColumnTo();
int rowIndex = region.getRowFrom();
HSSFRow row = HSSFCellUtil.getRow( rowIndex, sheet );
for ( int i = colStart; i <= colEnd; i++ ) {

HSSFCell cell = HSSFCellUtil.getCell( row, i );
HSSFCellUtil.setCellStyleProperty(
cell, workbook, HSSFCellUtil.BORDER_TOP, new Short( border ) );
}
}

/**
* Sets the topBorderColor attribute of the HSSFRegionUtil object
*
*@param color The color of the border
*@param region The region that should have the border
*@param workbook The workbook that the region is on.
*@param sheet The sheet that the region is on.
*/
public static void setTopBorderColor( short color, Region region, HSSFSheet sheet, HSSFWorkbook workbook )
{
int colStart = region.getColumnFrom();
int colEnd = region.getColumnTo();
int rowIndex = region.getRowFrom();
HSSFRow row = HSSFCellUtil.getRow( rowIndex, sheet );
for ( int i = colStart; i <= colEnd; i++ ) {
HSSFCell cell = HSSFCellUtil.getCell( row, i );
HSSFCellUtil.setCellStyleProperty(
cell, workbook, HSSFCellUtil.TOP_BORDER_COLOR, new Short( color ) );
}
}
}
public final class HSSFRegionUtil {

private HSSFRegionUtil() {
// no instances of this class
}
/**
* For setting the same property on many cells to the same value
*/
private static final class CellPropertySetter {

private final HSSFWorkbook _workbook;
private final String _propertyName;
private final Short _propertyValue;

public CellPropertySetter(HSSFWorkbook workbook, String propertyName, int value) {
_workbook = workbook;
_propertyName = propertyName;
_propertyValue = new Short((short)value);
}
public void setProperty(HSSFRow row, int column) {
HSSFCell cell = HSSFCellUtil.getCell(row, column);
HSSFCellUtil.setCellStyleProperty(cell, _workbook, _propertyName, _propertyValue);
}
}

private static CellRangeAddress toCRA(Region region) {
return Region.convertToCellRangeAddress(region);
}

/**
* @deprecated (Aug 2008) use {@link CellRangeAddress} instead of {@link Region}
*/
public static void setBorderLeft(short border, Region region, HSSFSheet sheet,
HSSFWorkbook workbook) {
setBorderLeft(border, toCRA(region), sheet, workbook);
}
/**
* Sets the left border for a region of cells by manipulating the cell style
* of the individual cells on the left
*
* @param border The new border
* @param region The region that should have the border
* @param workbook The workbook that the region is on.
* @param sheet The sheet that the region is on.
*/
public static void setBorderLeft(int border, CellRangeAddress region, HSSFSheet sheet,
HSSFWorkbook workbook) {
int rowStart = region.getFirstRow();
int rowEnd = region.getLastRow();
int column = region.getFirstColumn();

CellPropertySetter cps = new CellPropertySetter(workbook, HSSFCellUtil.BORDER_LEFT, border);
for (int i = rowStart; i <= rowEnd; i++) {
cps.setProperty(HSSFCellUtil.getRow(i, sheet), column);
}
}

/**
* @deprecated (Aug 2008) use {@link CellRangeAddress} instead of {@link Region}
*/
public static void setLeftBorderColor(short color, Region region, HSSFSheet sheet,
HSSFWorkbook workbook) {
setLeftBorderColor(color, toCRA(region), sheet, workbook);
}
/**
* Sets the leftBorderColor attribute of the HSSFRegionUtil object
*
* @param color The color of the border
* @param region The region that should have the border
* @param workbook The workbook that the region is on.
* @param sheet The sheet that the region is on.
*/
public static void setLeftBorderColor(int color, CellRangeAddress region, HSSFSheet sheet,
HSSFWorkbook workbook) {
int rowStart = region.getFirstRow();
int rowEnd = region.getLastRow();
int column = region.getFirstColumn();

CellPropertySetter cps = new CellPropertySetter(workbook, HSSFCellUtil.LEFT_BORDER_COLOR, color);
for (int i = rowStart; i <= rowEnd; i++) {
cps.setProperty(HSSFCellUtil.getRow(i, sheet), column);
}
}

/**
* @deprecated (Aug 2008) use {@link CellRangeAddress} instead of {@link Region}
*/
public static void setBorderRight(short border, Region region, HSSFSheet sheet,
HSSFWorkbook workbook) {
setBorderRight(border, toCRA(region), sheet, workbook);
}
/**
* Sets the borderRight attribute of the HSSFRegionUtil object
*
* @param border The new border
* @param region The region that should have the border
* @param workbook The workbook that the region is on.
* @param sheet The sheet that the region is on.
*/
public static void setBorderRight(int border, CellRangeAddress region, HSSFSheet sheet,
HSSFWorkbook workbook) {
int rowStart = region.getFirstRow();
int rowEnd = region.getLastRow();
int column = region.getLastColumn();

CellPropertySetter cps = new CellPropertySetter(workbook, HSSFCellUtil.BORDER_RIGHT, border);
for (int i = rowStart; i <= rowEnd; i++) {
cps.setProperty(HSSFCellUtil.getRow(i, sheet), column);
}
}

/**
* @deprecated (Aug 2008) use {@link CellRangeAddress} instead of {@link Region}
*/
public static void setRightBorderColor(short color, Region region, HSSFSheet sheet,
HSSFWorkbook workbook) {
setRightBorderColor(color, toCRA(region), sheet, workbook);
}
/**
* Sets the rightBorderColor attribute of the HSSFRegionUtil object
*
* @param color The color of the border
* @param region The region that should have the border
* @param workbook The workbook that the region is on.
* @param sheet The sheet that the region is on.
*/
public static void setRightBorderColor(int color, CellRangeAddress region, HSSFSheet sheet,
HSSFWorkbook workbook) {
int rowStart = region.getFirstRow();
int rowEnd = region.getLastRow();
int column = region.getLastColumn();

CellPropertySetter cps = new CellPropertySetter(workbook, HSSFCellUtil.RIGHT_BORDER_COLOR, color);
for (int i = rowStart; i <= rowEnd; i++) {
cps.setProperty(HSSFCellUtil.getRow(i, sheet), column);
}
}

/**
* @deprecated (Aug 2008) use {@link CellRangeAddress} instead of {@link Region}
*/
public static void setBorderBottom(short border, Region region, HSSFSheet sheet,
HSSFWorkbook workbook) {
setBorderBottom(border, toCRA(region), sheet, workbook);
}
/**
* Sets the borderBottom attribute of the HSSFRegionUtil object
*
* @param border The new border
* @param region The region that should have the border
* @param workbook The workbook that the region is on.
* @param sheet The sheet that the region is on.
*/
public static void setBorderBottom(int border, CellRangeAddress region, HSSFSheet sheet,
HSSFWorkbook workbook) {
int colStart = region.getFirstColumn();
int colEnd = region.getLastColumn();
int rowIndex = region.getLastRow();
CellPropertySetter cps = new CellPropertySetter(workbook, HSSFCellUtil.BORDER_BOTTOM, border);
HSSFRow row = HSSFCellUtil.getRow(rowIndex, sheet);
for (int i = colStart; i <= colEnd; i++) {
cps.setProperty(row, i);
}
}

/**
* @deprecated (Aug 2008) use {@link CellRangeAddress} instead of {@link Region}
*/
public static void setBottomBorderColor(short color, Region region, HSSFSheet sheet,
HSSFWorkbook workbook) {
setBottomBorderColor(color, toCRA(region), sheet, workbook);
}
/**
* Sets the bottomBorderColor attribute of the HSSFRegionUtil object
*
* @param color The color of the border
* @param region The region that should have the border
* @param workbook The workbook that the region is on.
* @param sheet The sheet that the region is on.
*/
public static void setBottomBorderColor(int color, CellRangeAddress region, HSSFSheet sheet,
HSSFWorkbook workbook) {
int colStart = region.getFirstColumn();
int colEnd = region.getLastColumn();
int rowIndex = region.getLastRow();
CellPropertySetter cps = new CellPropertySetter(workbook, HSSFCellUtil.BOTTOM_BORDER_COLOR, color);
HSSFRow row = HSSFCellUtil.getRow(rowIndex, sheet);
for (int i = colStart; i <= colEnd; i++) {
cps.setProperty(row, i);
}
}

/**
* @deprecated (Aug 2008) use {@link CellRangeAddress} instead of {@link Region}
*/
public static void setBorderTop(short border, Region region, HSSFSheet sheet,
HSSFWorkbook workbook) {
setBorderTop(border, toCRA(region), sheet, workbook);
}
/**
* Sets the borderBottom attribute of the HSSFRegionUtil object
*
* @param border The new border
* @param region The region that should have the border
* @param workbook The workbook that the region is on.
* @param sheet The sheet that the region is on.
*/
public static void setBorderTop(int border, CellRangeAddress region, HSSFSheet sheet,
HSSFWorkbook workbook) {
int colStart = region.getFirstColumn();
int colEnd = region.getLastColumn();
int rowIndex = region.getFirstRow();
CellPropertySetter cps = new CellPropertySetter(workbook, HSSFCellUtil.BORDER_TOP, border);
HSSFRow row = HSSFCellUtil.getRow(rowIndex, sheet);
for (int i = colStart; i <= colEnd; i++) {
cps.setProperty(row, i);
}
}

/**
* @deprecated (Aug 2008) use {@link CellRangeAddress} instead of {@link Region}
*/
public static void setTopBorderColor(short color, Region region, HSSFSheet sheet,
HSSFWorkbook workbook) {
setTopBorderColor(color, toCRA(region), sheet, workbook);
}
/**
* Sets the topBorderColor attribute of the HSSFRegionUtil object
*
* @param color The color of the border
* @param region The region that should have the border
* @param workbook The workbook that the region is on.
* @param sheet The sheet that the region is on.
*/
public static void setTopBorderColor(int color, CellRangeAddress region, HSSFSheet sheet,
HSSFWorkbook workbook) {
int colStart = region.getFirstColumn();
int colEnd = region.getLastColumn();
int rowIndex = region.getFirstRow();
CellPropertySetter cps = new CellPropertySetter(workbook, HSSFCellUtil.TOP_BORDER_COLOR, color);
HSSFRow row = HSSFCellUtil.getRow(rowIndex, sheet);
for (int i = colStart; i <= colEnd; i++) {
cps.setProperty(row, i);
}
}
}

+ 13
- 8
src/java/org/apache/poi/hssf/dev/HSSF.java View File

@@ -18,13 +18,20 @@

package org.apache.poi.hssf.dev;

import java.io.IOException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.*;

/**
* File for HSSF testing/examples
@@ -126,7 +133,7 @@ public class HSSF
}
c = r.createCell(( short ) (cellnum + 1),
HSSFCell.CELL_TYPE_STRING);
c.setCellValue("TEST");
c.setCellValue(new HSSFRichTextString("TEST"));
s.setColumnWidth(( short ) (cellnum + 1),
( short ) ((50 * 8) / (( double ) 1 / 20)));
if ((rownum % 2) == 0)
@@ -148,10 +155,8 @@ public class HSSF
// c.setCellValue(0);
c.setCellStyle(cs3);
}
s.addMergedRegion(new Region(( short ) 0, ( short ) 0, ( short ) 3,
( short ) 3));
s.addMergedRegion(new Region(( short ) 100, ( short ) 100,
( short ) 110, ( short ) 110));
s.addMergedRegion(new CellRangeAddress(0, 3, 0, 3));
s.addMergedRegion(new CellRangeAddress(100, 110, 100, 110));

// end draw thick black border
// create a sheet, set its title then delete it

+ 10
- 21
src/java/org/apache/poi/hssf/model/Sheet.java View File

@@ -24,6 +24,7 @@ import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
import org.apache.poi.hssf.record.aggregates.ValueRecordsAggregate;
import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate;
import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.hssf.util.PaneInformation;

import org.apache.poi.util.POILogFactory;
@@ -515,7 +516,7 @@ public final class Sheet implements Model {
}
}

public int addMergedRegion(int rowFrom, short colFrom, int rowTo, short colTo) {
public int addMergedRegion(int rowFrom, int colFrom, int rowTo, int colTo) {
// Validate input
if (rowTo < rowFrom) {
throw new IllegalArgumentException("The 'to' row (" + rowTo
@@ -585,7 +586,7 @@ public final class Sheet implements Model {
}
}

public MergeCellsRecord.MergedRegion getMergedRegionAt(int index)
public CellRangeAddress getMergedRegionAt(int index)
{
//safety checks
if (index >= numMergedRegions || mergedRecords.size() == 0)
@@ -1634,13 +1635,7 @@ public final class Sheet implements Model {
* Creates the Selection record and sets it to nothing selected
*/
private static SelectionRecord createSelection() {
SelectionRecord retval = new SelectionRecord();

retval.setPane(( byte ) 0x3);
retval.setActiveCellCol(( short ) 0x0);
retval.setActiveCellRow(( short ) 0x0);
retval.setNumRefs(( short ) 0x0);
return retval;
return new SelectionRecord(0, 0);
}

public short getTopRow()
@@ -1701,18 +1696,14 @@ public final class Sheet implements Model {
}

/**
* Returns the active column
*
* @see org.apache.poi.hssf.record.SelectionRecord
* @return row the active column index
* @return column of the active cell
*/
public short getActiveCellCol()
{
if (selection == null)
{
return (short) 0;
public short getActiveCellCol() {
if (selection == null) {
return 0;
}
return selection.getActiveCellCol();
return (short)selection.getActiveCellCol();
}

/**
@@ -1731,9 +1722,7 @@ public final class Sheet implements Model {
}

private static MergeCellsRecord createMergedCells() {
MergeCellsRecord retval = new MergeCellsRecord();
retval.setNumAreas(( short ) 0);
return retval;
return new MergeCellsRecord();
}

/**

+ 48
- 69
src/java/org/apache/poi/hssf/record/CFHeaderRecord.java View File

@@ -17,35 +17,33 @@

package org.apache.poi.hssf.record;

import org.apache.poi.hssf.record.cf.CellRange;
import org.apache.poi.hssf.util.Region;
import org.apache.poi.hssf.record.cf.CellRangeUtil;
import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.hssf.util.CellRangeAddressList;
import org.apache.poi.util.LittleEndian;

/**
* Conditional Formatting Header record (CFHEADER)
* Conditional Formatting Header record CFHEADER (0x1B0)
*
* @author Dmitriy Kumshayev
*/
public final class CFHeaderRecord extends Record
{
public final class CFHeaderRecord extends Record {
public static final short sid = 0x1B0;

private static final CellRange[] EMPTY_CELL_RANGE_ARRAY = { };

private int field_1_numcf;
private int field_2_need_recalculation;
private CellRange field_3_enclosing_cell_range;
private CellRange[] field_4_cell_ranges;
private CellRangeAddress field_3_enclosing_cell_range;
private CellRangeAddressList field_4_cell_ranges;

/** Creates new CFHeaderRecord */
public CFHeaderRecord()
{
field_4_cell_ranges = EMPTY_CELL_RANGE_ARRAY;
field_4_cell_ranges = new CellRangeAddressList();
}
public CFHeaderRecord(Region[] regions)
public CFHeaderRecord(CellRangeAddress[] regions)
{
CellRange[] unmergedRanges = CellRange.convertRegionsToCellRanges(regions);
CellRange[] mergeCellRanges = CellRange.mergeCellRanges(unmergedRanges);
CellRangeAddress[] unmergedRanges = regions;
CellRangeAddress[] mergeCellRanges = CellRangeUtil.mergeCellRanges(unmergedRanges);
setCellRanges(mergeCellRanges);
}

@@ -58,14 +56,8 @@ public final class CFHeaderRecord extends Record
{
field_1_numcf = in.readShort();
field_2_need_recalculation = in.readShort();
field_3_enclosing_cell_range = new CellRange(in.readUShort(), in.readUShort(), in.readUShort(), in.readUShort());
int numCellRanges = in.readShort();
CellRange[] crs = new CellRange[numCellRanges];
for( int i=0; i<numCellRanges; i++)
{
crs[i] = new CellRange(in.readUShort(),in.readUShort(),in.readUShort(),in.readUShort());
}
field_4_cell_ranges = crs;
field_3_enclosing_cell_range = new CellRangeAddress(in);
field_4_cell_ranges = new CellRangeAddressList(in);
}
public int getNumberOfConditionalFormats()
@@ -87,14 +79,14 @@ public final class CFHeaderRecord extends Record
field_2_need_recalculation=b?1:0;
}
public CellRange getEnclosingCellRange()
public CellRangeAddress getEnclosingCellRange()
{
return field_3_enclosing_cell_range;
}

public void setEnclosingCellRange( CellRange cr)
public void setEnclosingCellRange(CellRangeAddress cr)
{
field_3_enclosing_cell_range = cr.cloneCellRange();
field_3_enclosing_cell_range = cr;
}

/**
@@ -102,24 +94,26 @@ public final class CFHeaderRecord extends Record
* modify the enclosing cell range accordingly.
* @param List cellRanges - list of CellRange objects
*/
public void setCellRanges(CellRange[] cellRanges)
public void setCellRanges(CellRangeAddress[] cellRanges)
{
if(cellRanges == null)
{
throw new IllegalArgumentException("cellRanges must not be null");
}
field_4_cell_ranges = (CellRange[]) cellRanges.clone();
CellRange enclosingRange = null;
CellRangeAddressList cral = new CellRangeAddressList();
CellRangeAddress enclosingRange = null;
for (int i = 0; i < cellRanges.length; i++)
{
enclosingRange = cellRanges[i].createEnclosingCellRange(enclosingRange);
CellRangeAddress cr = cellRanges[i];
enclosingRange = CellRangeUtil.createEnclosingCellRange(cr, enclosingRange);
cral.addCellRangeAddress(cr);
}
field_3_enclosing_cell_range=enclosingRange;
field_3_enclosing_cell_range = enclosingRange;
field_4_cell_ranges = cral;
}
public CellRange[] getCellRanges()
{
return (CellRange[]) field_4_cell_ranges.clone();
public CellRangeAddress[] getCellRanges() {
return field_4_cell_ranges.getCellRangeAddresses();
}

public String toString()
@@ -131,50 +125,39 @@ public final class CFHeaderRecord extends Record
buffer.append(" .numCF = ").append(getNumberOfConditionalFormats()).append("\n");
buffer.append(" .needRecalc = ").append(getNeedRecalculation()).append("\n");
buffer.append(" .enclosingCellRange= ").append(getEnclosingCellRange()).append("\n");
if( field_4_cell_ranges.length>0)
buffer.append(" .cfranges=[");
for( int i=0; i<field_4_cell_ranges.countRanges(); i++)
{
buffer.append(" .cfranges=[");
for( int i=0; i<field_4_cell_ranges.length; i++)
{
buffer.append(i==0?"":",").append(field_4_cell_ranges[i].toString());
}
buffer.append("]\n");
buffer.append(i==0?"":",").append(field_4_cell_ranges.getCellRangeAddress(i).toString());
}
buffer.append("]\n");
buffer.append("[/CFHEADER]\n");
return buffer.toString();
}

private int getDataSize() {
return 4 // 2 short fields
+ CellRangeAddress.ENCODED_SIZE
+ field_4_cell_ranges.getSize();
}
/**
* @return byte array containing instance data
*/

public int serialize(int offset, byte[] data)
{
int recordsize = getRecordSize();
public int serialize(int offset, byte[] data) {
int dataSize = getDataSize();
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset, (short) (recordsize-4));
LittleEndian.putShort(data, 4 + offset, (short) field_1_numcf);
LittleEndian.putShort(data, 6 + offset, (short) field_2_need_recalculation);
LittleEndian.putShort(data, 8 + offset, (short) field_3_enclosing_cell_range.getFirstRow());
LittleEndian.putShort(data, 10 + offset, (short) field_3_enclosing_cell_range.getLastRow());
LittleEndian.putShort(data, 12 + offset, (short) field_3_enclosing_cell_range.getFirstColumn());
LittleEndian.putShort(data, 14 + offset, (short) field_3_enclosing_cell_range.getLastColumn());
LittleEndian.putShort(data, 16 + offset, (short) field_4_cell_ranges.length);
for( int i=0 ; i!=field_4_cell_ranges.length; i++)
{
CellRange cr = field_4_cell_ranges[i];
LittleEndian.putShort(data, 18 + 0 + 8 * i + offset, (short) cr.getFirstRow());
LittleEndian.putShort(data, 18 + 2 + 8 * i + offset, (short) cr.getLastRow());
LittleEndian.putShort(data, 18 + 4 + 8 * i + offset, (short) cr.getFirstColumn());
LittleEndian.putShort(data, 18 + 6 + 8 * i + offset, (short) cr.getLastColumn());
}
return getRecordSize();
LittleEndian.putUShort(data, 0 + offset, sid);
LittleEndian.putUShort(data, 2 + offset, dataSize);
LittleEndian.putUShort(data, 4 + offset, field_1_numcf);
LittleEndian.putUShort(data, 6 + offset, field_2_need_recalculation);
field_3_enclosing_cell_range.serialize(8 + offset, data);
field_4_cell_ranges.serialize(16 + offset, data);
return 4 + dataSize;
}

public int getRecordSize()
{
return 18+8*field_4_cell_ranges.length;
public int getRecordSize() {
return 4 + getDataSize();
}

/**
@@ -204,11 +187,7 @@ public final class CFHeaderRecord extends Record
result.field_1_numcf = field_1_numcf;
result.field_2_need_recalculation = field_2_need_recalculation;
result.field_3_enclosing_cell_range = field_3_enclosing_cell_range;
CellRange[] crs = new CellRange[field_4_cell_ranges.length];
for (int i = 0; i < crs.length; i++) {
crs[i] = field_4_cell_ranges[i].cloneCellRange();
}
result.field_4_cell_ranges = crs;
result.field_4_cell_ranges = field_4_cell_ranges.copy();
return result;
}
}

+ 1
- 1
src/java/org/apache/poi/hssf/record/DVRecord.java View File

@@ -227,7 +227,7 @@ public final class DVRecord extends Record {
appendFormula(sb, "Formula 1:", _formula1);
appendFormula(sb, "Formula 2:", _formula2);
sb.append("Regions: ");
int nRegions = _regions.getADDRStructureNumber();
int nRegions = _regions.countRanges();
for(int i=0; i<nRegions; i++) {
if (i>0) {
sb.append(", ");

+ 50
- 178
src/java/org/apache/poi/hssf/record/MergeCellsRecord.java View File

@@ -1,4 +1,3 @@

/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@@ -15,57 +14,43 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */

package org.apache.poi.hssf.record;

import java.util.ArrayList;
import java.util.Iterator;

import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.hssf.util.CellRangeAddressList;
import org.apache.poi.util.LittleEndian;

/**
* Title: Merged Cells Record
* <br>
* Title: Merged Cells Record (0x00E5)
* <br/>
* Description: Optional record defining a square area of cells to "merged" into
* one cell. <br>
* REFERENCE: NONE (UNDOCUMENTED PRESENTLY) <br>
* @author Andrew C. Oliver (acoliver at apache dot org)
* @version 2.0-pre
*/
public class MergeCellsRecord
extends Record
{
public final static short sid = 0xe5;
private ArrayList field_2_regions;
public final class MergeCellsRecord extends Record {
public final static short sid = 0x00E5;
private CellRangeAddressList _regions;

public MergeCellsRecord()
{
/**
* Creates an empty <tt>MergedCellsRecord</tt>
*/
public MergeCellsRecord() {
_regions = new CellRangeAddressList();
}

/**
* Constructs a MergedCellsRecord and sets its fields appropriately
* @param in the RecordInputstream to read the record from
*/

public MergeCellsRecord(RecordInputStream in)
{
public MergeCellsRecord(RecordInputStream in) {
super(in);
}

protected void fillFields(RecordInputStream in)
{
short numAreas = in.readShort();
field_2_regions = new ArrayList(numAreas + 10);

for (int k = 0; k < numAreas; k++)
{
MergedRegion region =
new MergedRegion(in.readShort(), in.readShort(),
in.readShort(), in.readShort());

field_2_regions.add(region);
}
protected void fillFields(RecordInputStream in) {
_regions = new CellRangeAddressList(in);
}

/**
@@ -73,27 +58,8 @@ public class MergeCellsRecord
* ahead and delete the record.
* @return number of areas
*/

public short getNumAreas()
{
//if the array size is larger than a short (65536), the record can't hold that many merges anyway
if (field_2_regions == null) return 0;
return (short)field_2_regions.size();
}

/**
* set the number of merged areas. You do not need to call this if you use addArea,
* it will be incremented automatically or decremented when an area is removed. If
* you are setting this to 0 then you are a terrible person. Just remove the record.
* (just kidding about you being a terrible person..hehe)
* @deprecated We now link the size to the actual array of merged regions
* @see #getNumAreas()
* @param numareas number of areas
*/

public void setNumAreas(short numareas)
{
public short getNumAreas() {
return (short)_regions.countRanges();
}

/**
@@ -101,178 +67,84 @@ public class MergeCellsRecord
* be correct provided you do not add ahead of or remove ahead of it (in which case
* you should increment or decrement appropriately....in other words its an arrayList)
*
* @param rowfrom - the upper left hand corner's row
* @param colfrom - the upper left hand corner's col
* @param rowto - the lower right hand corner's row
* @param colto - the lower right hand corner's col
* @param firstRow - the upper left hand corner's row
* @param firstCol - the upper left hand corner's col
* @param lastRow - the lower right hand corner's row
* @param lastCol - the lower right hand corner's col
* @return new index of said area (don't depend on it if you add/remove)
*/

//public int addArea(short rowfrom, short colfrom, short rowto, short colto)
public int addArea(int rowfrom, short colfrom, int rowto, short colto)
{
if (field_2_regions == null)
{
field_2_regions = new ArrayList(10);
}
MergedRegion region = new MergedRegion(rowfrom, rowto, colfrom,
colto);

field_2_regions.add(region);
return field_2_regions.size() - 1;
public void addArea(int firstRow, int firstCol, int lastRow, int lastCol) {
_regions.addCellRangeAddress(firstRow, firstCol, lastRow, lastCol);
}

/**
* essentially unmerge the cells in the "area" stored at the passed in index
* @param area index
* @param areaIndex
*/

public void removeAreaAt(int area)
{
field_2_regions.remove(area);
public void removeAreaAt(int areaIndex) {
_regions.remove(areaIndex);
}

/**
* return the MergedRegion at the given index.
*
* @return MergedRegion representing the area that is Merged (r1,c1 - r2,c2)
* @return MergedRegion at the given index representing the area that is Merged (r1,c1 - r2,c2)
*/

public MergedRegion getAreaAt(int index)
{
return ( MergedRegion ) field_2_regions.get(index);
public CellRangeAddress getAreaAt(int index) {
return _regions.getCellRangeAddress(index);
}

public int getRecordSize()
{
int retValue;

retValue = 6 + (8 * field_2_regions.size());
return retValue;
public int getRecordSize() {
return 4 + _regions.getSize();
}

public short getSid()
{
public short getSid() {
return sid;
}

public int serialize(int offset, byte [] data)
{
int recordsize = getRecordSize();
int pos = 6;
public int serialize(int offset, byte [] data) {
int dataSize = _regions.getSize();

LittleEndian.putShort(data, offset + 0, sid);
LittleEndian.putShort(data, offset + 2, ( short ) (recordsize - 4));
LittleEndian.putShort(data, offset + 4, getNumAreas());
for (int k = 0; k < getNumAreas(); k++)
{
MergedRegion region = getAreaAt(k);

//LittleEndian.putShort(data, offset + pos, region.row_from);
LittleEndian.putShort(data, offset + pos, ( short ) region.row_from);
pos += 2;
//LittleEndian.putShort(data, offset + pos, region.row_to);
LittleEndian.putShort(data, offset + pos, ( short ) region.row_to);
pos += 2;
LittleEndian.putShort(data, offset + pos, region.col_from);
pos += 2;
LittleEndian.putShort(data, offset + pos, region.col_to);
pos += 2;
}
return recordsize;
LittleEndian.putUShort(data, offset + 2, dataSize);
_regions.serialize(offset + 4, data);
return 4 + dataSize;
}

public String toString()
{
public String toString() {
StringBuffer retval = new StringBuffer();

retval.append("[MERGEDCELLS]").append("\n");
retval.append(" .sid =").append(sid).append("\n");
retval.append(" .numregions =").append(getNumAreas())
.append("\n");
for (int k = 0; k < getNumAreas(); k++)
{
MergedRegion region = ( MergedRegion ) field_2_regions.get(k);
for (int k = 0; k < _regions.countRanges(); k++) {
CellRangeAddress region = _regions.getCellRangeAddress(k);

retval.append(" .rowfrom =").append(region.row_from)
retval.append(" .rowfrom =").append(region.getFirstRow())
.append("\n");
retval.append(" .colfrom =").append(region.col_from)
retval.append(" .colfrom =").append(region.getFirstColumn())
.append("\n");
retval.append(" .rowto =").append(region.row_to)
retval.append(" .rowto =").append(region.getLastRow())
.append("\n");
retval.append(" .colto =").append(region.col_to)
retval.append(" .colto =").append(region.getLastColumn())
.append("\n");
}
retval.append("[MERGEDCELLS]").append("\n");
return retval.toString();
}

protected void validateSid(short id)
{
if (id != sid)
{
protected void validateSid(short id) {
if (id != sid) {
throw new RecordFormatException("NOT A MERGEDCELLS RECORD!! "
+ id);
}
}

/**
* this is a low level representation of a MergedRegion of cells. It is an
* inner class because we do not want it used without reference to this class.
*
*/

public class MergedRegion
{

/**
* create a merged region all in one stroke.
*/

//public MergedRegion(short row_from, short row_to, short col_from,
public MergedRegion(int row_from, int row_to, short col_from,
short col_to)
{
this.row_from = row_from;
this.row_to = row_to;
this.col_from = col_from;
this.col_to = col_to;
}

/**
* upper lefthand corner row
*/

//public short row_from;
public int row_from;

/**
* lower right hand corner row
*/

//public short row_to;
public int row_to;

/**
* upper right hand corner col
*/

public short col_from;

/**
* lower right hand corner col
*/

public short col_to;
}

public Object clone() {
MergeCellsRecord rec = new MergeCellsRecord();
rec.field_2_regions = new ArrayList();
Iterator iterator = field_2_regions.iterator();
while (iterator.hasNext()) {
MergedRegion oldRegion = (MergedRegion)iterator.next();
rec.addArea(oldRegion.row_from, oldRegion.col_from, oldRegion.row_to, oldRegion.col_to);
for (int k = 0; k < _regions.countRanges(); k++) {
CellRangeAddress oldRegion = _regions.getCellRangeAddress(k);
rec.addArea(oldRegion.getFirstRow(), oldRegion.getFirstColumn(),
oldRegion.getLastRow(), oldRegion.getLastColumn());
}
return rec;

+ 104
- 143
src/java/org/apache/poi/hssf/record/SelectionRecord.java View File

@@ -1,4 +1,3 @@

/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@@ -15,70 +14,80 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */

package org.apache.poi.hssf.record;

import java.util.*;

import org.apache.poi.util.LittleEndian;

/**
* Title: Selection Record<P>
* Title: Selection Record (0x001D)<P>
* Description: shows the user's selection on the sheet
* for write set num refs to 0<P>
*
* TODO : Fully implement reference subrecords.
* REFERENCE: PG 291 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
* @author Andrew C. Oliver (acoliver at apache dot org)
* @author Jason Height (jheight at chariot dot net dot au)
* @author Glen Stampoultzis (glens at apache.org)
*/
public final class SelectionRecord extends Record {
public final static short sid = 0x001D;
private byte field_1_pane;
private int field_2_row_active_cell;
private int field_3_col_active_cell;
private int field_4_active_cell_ref_index;
private Reference[] field_6_refs;

public class SelectionRecord
extends Record
{
public final static short sid = 0x1d;
private byte field_1_pane;
//private short field_2_row_active_cell;
private int field_2_row_active_cell;
private short field_3_col_active_cell;
private short field_4_ref_active_cell;
private short field_5_num_refs;
private ArrayList field_6_refs; // not used yet

/**
* Note - column values are 8-bit so cannot use <tt>CellRangeAddressList</tt>
*/
public class Reference {
private short field_1_first_row;
private short field_2_last_row;
private byte field_3_first_column;
private byte field_4_last_column;
Reference(RecordInputStream in) {
field_1_first_row = in.readShort();
field_2_last_row = in.readShort();
field_3_first_column = in.readByte();
field_4_last_column = in.readByte();
}
/* package */ static final int ENCODED_SIZE = 6;
private int _firstRow;
private int _lastRow;
private int _firstCol;
private int _lastCol;
public short getFirstRow() {
return field_1_first_row;
}
public short getLastRow() {
return field_2_last_row;
}
public byte getFirstColumn() {
return field_3_first_column;
}
public byte getLastColumn() {
return field_4_last_column;
}
/* package */ Reference(int firstRow, int lastRow, int firstColumn, int lastColumn) {
_firstRow = firstRow;
_lastRow = lastRow;
_firstCol = firstColumn;
_lastCol = lastColumn;
}
/* package */ Reference(RecordInputStream in) {
this(in.readUShort(), in.readUShort(), in.readUByte(), in.readUByte());
}
public void serialize(int offset, byte[] data) {
LittleEndian.putUShort(data, offset + 0, _firstRow);
LittleEndian.putUShort(data, offset + 2, _lastRow);
LittleEndian.putByte(data, offset + 4, _firstCol);
LittleEndian.putByte(data, offset + 6, _lastCol);
}

public int getFirstRow() {
return _firstRow;
}
public int getLastRow() {
return _lastRow;
}
public int getFirstColumn() {
return _firstCol;
}
public int getLastColumn() {
return _lastCol;
}
}

public SelectionRecord()
{
/**
* Creates a default selection record (cell A1, in pane ID 3)
*/
public SelectionRecord(int activeCellRow, int activeCellCol) {
field_1_pane = 3; // pane id 3 is always present. see OOO sec 5.75 'PANE'
field_2_row_active_cell = activeCellRow;
field_3_col_active_cell = activeCellCol;
field_4_active_cell_ref_index = 0;
field_6_refs = new Reference[] {
new Reference(activeCellRow, activeCellRow, activeCellCol, activeCellCol),
};
}

/**
@@ -86,41 +95,33 @@ public class SelectionRecord
* @param in the RecordInputstream to read the record from
*/

public SelectionRecord(RecordInputStream in)
{
public SelectionRecord(RecordInputStream in) {
super(in);
}

protected void validateSid(short id)
{
if (id != sid)
{
protected void validateSid(short id) {
if (id != sid) {
throw new RecordFormatException("NOT A valid Selection RECORD");
}
}

protected void fillFields(RecordInputStream in)
{
protected void fillFields(RecordInputStream in) {
field_1_pane = in.readByte();
//field_2_row_active_cell = LittleEndian.getShort(data, 1 + offset);
field_2_row_active_cell = in.readUShort();
field_3_col_active_cell = in.readShort();
field_4_ref_active_cell = in.readShort();
field_5_num_refs = in.readShort();
field_4_active_cell_ref_index = in.readShort();
int field_5_num_refs = in.readUShort();
field_6_refs = new ArrayList(field_5_num_refs);
for (int i=0; i<field_5_num_refs; i++) {
field_6_refs.add(new Reference(in));
}
field_6_refs = new Reference[field_5_num_refs];
for (int i = 0; i < field_6_refs.length; i++) {
field_6_refs[i] = new Reference(in);
}
}

/**
* set which window pane this is for
* @param pane
*/

public void setPane(byte pane)
{
public void setPane(byte pane) {
field_1_pane = pane;
}

@@ -128,10 +129,7 @@ public class SelectionRecord
* set the active cell's row
* @param row number of active cell
*/

//public void setActiveCellRow(short row)
public void setActiveCellRow(int row)
{
public void setActiveCellRow(int row) {
field_2_row_active_cell = row;
}

@@ -139,9 +137,7 @@ public class SelectionRecord
* set the active cell's col
* @param col number of active cell
*/

public void setActiveCellCol(short col)
{
public void setActiveCellCol(short col) {
field_3_col_active_cell = col;
}

@@ -149,29 +145,14 @@ public class SelectionRecord
* set the active cell's reference number
* @param ref number of active cell
*/

public void setActiveCellRef(short ref)
{
field_4_ref_active_cell = ref;
}

/**
* set the number of cell refs (we don't support selection so set to 0
* @param refs - number of references
*/

public void setNumRefs(short refs)
{
field_5_num_refs = refs;
public void setActiveCellRef(short ref) {
field_4_active_cell_ref_index = ref;
}

/**
* get which window pane this is for
* @return pane
* @return the pane ID which window pane this is for
*/

public byte getPane()
{
public byte getPane() {
return field_1_pane;
}

@@ -179,10 +160,7 @@ public class SelectionRecord
* get the active cell's row
* @return row number of active cell
*/

//public short getActiveCellRow()
public int getActiveCellRow()
{
public int getActiveCellRow() {
return field_2_row_active_cell;
}

@@ -190,9 +168,7 @@ public class SelectionRecord
* get the active cell's col
* @return col number of active cell
*/

public short getActiveCellCol()
{
public int getActiveCellCol() {
return field_3_col_active_cell;
}

@@ -200,20 +176,8 @@ public class SelectionRecord
* get the active cell's reference number
* @return ref number of active cell
*/

public short getActiveCellRef()
{
return field_4_ref_active_cell;
}

/**
* get the number of cell refs (we don't support selection so set to 0
* @return refs - number of references
*/

public short getNumRefs()
{
return field_5_num_refs;
public int getActiveCellRef() {
return (short)field_4_active_cell_ref_index;
}

public String toString()
@@ -230,47 +194,44 @@ public class SelectionRecord
buffer.append(" .activecellref = ")
.append(Integer.toHexString(getActiveCellRef())).append("\n");
buffer.append(" .numrefs = ")
.append(Integer.toHexString(getNumRefs())).append("\n");
.append(Integer.toHexString(field_6_refs.length)).append("\n");
buffer.append("[/SELECTION]\n");
return buffer.toString();
}

//hacked to provide one cell reference to 0,0 - 0,0
public int serialize(int offset, byte [] data)
{
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset, ( short ) 15);
data[ 4 + offset ] = getPane();
//LittleEndian.putShort(data, 5 + offset, getActiveCellRow());
LittleEndian.putShort(data, 5 + offset, ( short ) getActiveCellRow());
LittleEndian.putShort(data, 7 + offset, getActiveCellCol());
LittleEndian.putShort(data, 9 + offset, getActiveCellRef());
LittleEndian.putShort(data, 11 + offset, ( short ) 1);
LittleEndian.putShort(data, 13 + offset, ( short ) getActiveCellRow());
LittleEndian.putShort(data, 15 + offset, ( short ) getActiveCellRow());
data[ 17 + offset ] = (byte)getActiveCellCol();
data[ 18 + offset ] = (byte)getActiveCellCol();
return getRecordSize();
private int getDataSize() {
return 9 // 1 byte + 4 shorts
+ field_6_refs.length * Reference.ENCODED_SIZE;
}
public int serialize(int offset, byte [] data) {
int dataSize = getDataSize();
LittleEndian.putUShort(data, 0 + offset, sid);
LittleEndian.putUShort(data, 2 + offset, dataSize);
LittleEndian.putByte(data, 4 + offset, getPane());
LittleEndian.putUShort(data, 5 + offset, getActiveCellRow());
LittleEndian.putUShort(data, 7 + offset, getActiveCellCol());
LittleEndian.putUShort(data, 9 + offset, getActiveCellRef());
int nRefs = field_6_refs.length;
LittleEndian.putUShort(data, 11 + offset, nRefs);
for (int i = 0; i < field_6_refs.length; i++) {
Reference r = field_6_refs[i];
r.serialize(offset + 13 + i * Reference.ENCODED_SIZE, data);
}
return 4 + dataSize;
}

public int getRecordSize()
{
return 19;
public int getRecordSize() {
return 4 + getDataSize();
}

public short getSid()
{
public short getSid() {
return sid;
}

public Object clone() {
SelectionRecord rec = new SelectionRecord();
rec.field_1_pane = field_1_pane;
rec.field_2_row_active_cell = field_2_row_active_cell;
rec.field_3_col_active_cell = field_3_col_active_cell;
rec.field_4_ref_active_cell = field_4_ref_active_cell;
rec.field_5_num_refs = field_5_num_refs;
rec.field_6_refs = field_6_refs;
return rec;
SelectionRecord rec = new SelectionRecord(field_2_row_active_cell, field_3_col_active_cell);
rec.field_1_pane = field_1_pane;
rec.field_4_active_cell_ref_index = field_4_active_cell_ref_index;
rec.field_6_refs = field_6_refs;
return rec;
}
}

+ 2
- 2
src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java View File

@@ -24,7 +24,7 @@ import org.apache.poi.hssf.record.CFHeaderRecord;
import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.util.Region;
import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;

@@ -68,7 +68,7 @@ public final class CFRecordsAggregate extends Record
}
}

public CFRecordsAggregate(Region[] regions, CFRuleRecord[] rules) {
public CFRecordsAggregate(CellRangeAddress[] regions, CFRuleRecord[] rules) {
this(new CFHeaderRecord(regions), rules);
}


+ 0
- 513
src/java/org/apache/poi/hssf/record/cf/CellRange.java View File

@@ -1,513 +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.hssf.record.cf;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.poi.hssf.util.Region;

/**
*
* @author Dmitriy Kumshayev
*/
public final class CellRange
{
/** max 65536 rows in BIFF8 */
private static final int LAST_ROW_INDEX = 0x00FFFF;
/** max 256 columns in BIFF8 */
private static final int LAST_COLUMN_INDEX = 0x00FF;

private static final Region[] EMPTY_REGION_ARRAY = { };
private int _firstRow;
private int _lastRow;
private int _firstColumn;
private int _lastColumn;
/**
*
* @param firstRow
* @param lastRow pass <tt>-1</tt> for full column ranges
* @param firstColumn
* @param lastColumn pass <tt>-1</tt> for full row ranges
*/
public CellRange(int firstRow, int lastRow, int firstColumn, int lastColumn)
{
if(!isValid(firstRow, lastRow, firstColumn, lastColumn)) {
throw new IllegalArgumentException("invalid cell range (" + firstRow + ", " + lastRow
+ ", " + firstColumn + ", " + lastColumn + ")");
}
_firstRow = firstRow;
_lastRow = convertM1ToMax(lastRow, LAST_ROW_INDEX);
_firstColumn = firstColumn;
_lastColumn = convertM1ToMax(lastColumn, LAST_COLUMN_INDEX);
}
/**
* Range arithmetic is easier when using a large positive number for 'max row or column'
* instead of <tt>-1</tt>.
*/
private static int convertM1ToMax(int lastIx, int maxIndex) {
if(lastIx < 0) {
return maxIndex;
}
return lastIx;
}

public boolean isFullColumnRange() {
return _firstRow == 0 && _lastRow == LAST_ROW_INDEX;
}
public boolean isFullRowRange() {
return _firstColumn == 0 && _lastColumn == LAST_COLUMN_INDEX;
}
private static CellRange createFromRegion(Region r) {
return new CellRange(r.getRowFrom(), r.getRowTo(), r.getColumnFrom(), r.getColumnTo());
}

private static boolean isValid(int firstRow, int lastRow, int firstColumn, int lastColumn)
{
if(lastRow < 0 || lastRow > LAST_ROW_INDEX) {
return false;
}
if(firstRow < 0 || firstRow > LAST_ROW_INDEX) {
return false;
}
if(lastColumn < 0 || lastColumn > LAST_COLUMN_INDEX) {
return false;
}
if(firstColumn < 0 || firstColumn > LAST_COLUMN_INDEX) {
return false;
}
return true;
}
public int getFirstRow()
{
return _firstRow;
}
public int getLastRow()
{
return _lastRow;
}
public int getFirstColumn()
{
return _firstColumn;
}
public int getLastColumn()
{
return _lastColumn;
}
public static final int NO_INTERSECTION = 1;
public static final int OVERLAP = 2;
/** first range is within the second range */
public static final int INSIDE = 3;
/** first range encloses or is equal to the second */
public static final int ENCLOSES = 4;
/**
* Intersect this range with the specified range.
*
* @param another - the specified range
* @return code which reflects how the specified range is related to this range.<br/>
* Possible return codes are:
* NO_INTERSECTION - the specified range is outside of this range;<br/>
* OVERLAP - both ranges partially overlap;<br/>
* INSIDE - the specified range is inside of this one<br/>
* ENCLOSES - the specified range encloses (possibly exactly the same as) this range<br/>
*/
public int intersect(CellRange another )
{
int firstRow = another.getFirstRow();
int lastRow = another.getLastRow();
int firstCol = another.getFirstColumn();
int lastCol = another.getLastColumn();
if
(
gt(getFirstRow(),lastRow) ||
lt(getLastRow(),firstRow) ||
gt(getFirstColumn(),lastCol) ||
lt(getLastColumn(),firstCol)
)
{
return NO_INTERSECTION;
}
else if( contains(another) )
{
return INSIDE;
}
else if( another.contains(this))
{
return ENCLOSES;
}
else
{
return OVERLAP;
}
}
/**
* Do all possible cell merges between cells of the list so that:<br>
* <li>if a cell range is completely inside of another cell range, it gets removed from the list
* <li>if two cells have a shared border, merge them into one bigger cell range
* @param cellRangeList
* @return updated List of cell ranges
*/
public static CellRange[] mergeCellRanges(CellRange[] cellRanges) {
if(cellRanges.length < 1) {
return cellRanges;
}
List temp = mergeCellRanges(Arrays.asList(cellRanges));
return toArray(temp);
}
private static List mergeCellRanges(List cellRangeList)
{

while(cellRangeList.size() > 1)
{
boolean somethingGotMerged = false;
for( int i=0; i<cellRangeList.size(); i++)
{
CellRange range1 = (CellRange)cellRangeList.get(i);
for( int j=i+1; j<cellRangeList.size(); j++)
{
CellRange range2 = (CellRange)cellRangeList.get(j);
CellRange[] mergeResult = mergeRanges(range1, range2);
if(mergeResult == null) {
continue;
}
somethingGotMerged = true;
// overwrite range1 with first result
cellRangeList.set(i, mergeResult[0]);
// remove range2
cellRangeList.remove(j--);
// add any extra results beyond the first
for(int k=1; k<mergeResult.length; k++) {
j++;
cellRangeList.add(j, mergeResult[k]);
}
}
}
if(!somethingGotMerged) {
break;
}
}

return cellRangeList;
}
/**
* @return the new range(s) to replace the supplied ones. <code>null</code> if no merge is possible
*/
private static CellRange[] mergeRanges(CellRange range1, CellRange range2) {
int x = range1.intersect(range2);
switch(x)
{
case CellRange.NO_INTERSECTION:
if( range1.hasExactSharedBorder(range2))
{
return new CellRange[] { range1.createEnclosingCellRange(range2), };
}
// else - No intersection and no shared border: do nothing
return null;
case CellRange.OVERLAP:
return resolveRangeOverlap(range1, range2);
case CellRange.INSIDE:
// Remove range2, since it is completely inside of range1
return new CellRange[] { range1, };
case CellRange.ENCLOSES:
// range2 encloses range1, so replace it with the enclosing one
return new CellRange[] { range2, };
}
throw new RuntimeException("unexpected intersection result (" + x + ")");
}
// TODO - write junit test for this
static CellRange[] resolveRangeOverlap(CellRange rangeA, CellRange rangeB) {
if(rangeA.isFullColumnRange()) {
if(rangeB.isFullRowRange()) {
// Excel seems to leave these unresolved
return null;
}
return rangeA.sliceUp(rangeB);
}
if(rangeA.isFullRowRange()) {
if(rangeB.isFullColumnRange()) {
// Excel seems to leave these unresolved
return null;
}
return rangeA.sliceUp(rangeB);
}
if(rangeB.isFullColumnRange()) {
return rangeB.sliceUp(rangeA);
}
if(rangeB.isFullRowRange()) {
return rangeB.sliceUp(rangeA);
}
return rangeA.sliceUp(rangeB);
}

/**
* @param range never a full row or full column range
* @return an array including <b>this</b> <tt>CellRange</tt> and all parts of <tt>range</tt>
* outside of this range
*/
private CellRange[] sliceUp(CellRange range) {
List temp = new ArrayList();
// Chop up range horizontally and vertically
temp.add(range);
if(!isFullColumnRange()) {
temp = cutHorizontally(_firstRow, temp);
temp = cutHorizontally(_lastRow+1, temp);
}
if(!isFullRowRange()) {
temp = cutVertically(_firstColumn, temp);
temp = cutVertically(_lastColumn+1, temp);
}
CellRange[] crParts = toArray(temp);

// form result array
temp.clear();
temp.add(this);
for (int i = 0; i < crParts.length; i++) {
CellRange crPart = crParts[i];
// only include parts that are not enclosed by this
if(intersect(crPart) != ENCLOSES) {
temp.add(crPart);
}
}
return toArray(temp);
}

private static List cutHorizontally(int cutRow, List input) {
List result = new ArrayList();
CellRange[] crs = toArray(input);
for (int i = 0; i < crs.length; i++) {
CellRange cr = crs[i];
if(cr._firstRow < cutRow && cutRow < cr._lastRow) {
result.add(new CellRange(cr._firstRow, cutRow, cr._firstColumn, cr._lastColumn));
result.add(new CellRange(cutRow+1, cr._lastRow, cr._firstColumn, cr._lastColumn));
} else {
result.add(cr);
}
}
return result;
}
private static List cutVertically(int cutColumn, List input) {
List result = new ArrayList();
CellRange[] crs = toArray(input);
for (int i = 0; i < crs.length; i++) {
CellRange cr = crs[i];
if(cr._firstColumn < cutColumn && cutColumn < cr._lastColumn) {
result.add(new CellRange(cr._firstRow, cr._lastRow, cr._firstColumn, cutColumn));
result.add(new CellRange(cr._firstRow, cr._lastRow, cutColumn+1, cr._lastColumn));
} else {
result.add(cr);
}
}
return result;
}


private static CellRange[] toArray(List temp) {
CellRange[] result = new CellRange[temp.size()];
temp.toArray(result);
return result;
}

/**
* Convert array of regions to a List of CellRange objects
*
* @param regions
* @return List of CellRange objects
*/
public static CellRange[] convertRegionsToCellRanges(Region[] regions)
{
CellRange[] result = new CellRange[regions.length];
for( int i=0; i<regions.length; i++)
{
result[i] = createFromRegion(regions[i]);
}
return result;
}
/**
* Convert a List of CellRange objects to an array of regions
*
* @param List of CellRange objects
* @return regions
*/
public static Region[] convertCellRangesToRegions(CellRange[] cellRanges)
{
int size = cellRanges.length;
if(size < 1) {
return EMPTY_REGION_ARRAY;
}
Region[] result = new Region[size];

for (int i = 0; i != size; i++)
{
result[i] = cellRanges[i].convertToRegion();
}
return result;
}


private Region convertToRegion() {
return new Region(_firstRow, (short)_firstColumn, _lastRow, (short)_lastColumn);
}


/**
* Check if the specified range is located inside of this cell range.
*
* @param range
* @return true if this cell range contains the argument range inside if it's area
*/
public boolean contains(CellRange range)
{
int firstRow = range.getFirstRow();
int lastRow = range.getLastRow();
int firstCol = range.getFirstColumn();
int lastCol = range.getLastColumn();
return le(getFirstRow(), firstRow) && ge(getLastRow(), lastRow)
&& le(getFirstColumn(), firstCol) && ge(getLastColumn(), lastCol);
}
public boolean contains(int row, short column)
{
return le(getFirstRow(), row) && ge(getLastRow(), row)
&& le(getFirstColumn(), column) && ge(getLastColumn(), column);
}
/**
* Check if the specified cell range has a shared border with the current range.
*
* @return <code>true</code> if the ranges have a complete shared border (i.e.
* the two ranges together make a simple rectangular region.
*/
public boolean hasExactSharedBorder(CellRange range)
{
int oFirstRow = range._firstRow;
int oLastRow = range._lastRow;
int oFirstCol = range._firstColumn;
int oLastCol = range._lastColumn;
if (_firstRow > 0 && _firstRow-1 == oLastRow ||
oFirstRow > 0 && oFirstRow-1 == _lastRow) {
// ranges have a horizontal border in common
// make sure columns are identical:
return _firstColumn == oFirstCol && _lastColumn == oLastCol;
}

if (_firstColumn>0 && _firstColumn - 1 == oLastCol ||
oFirstCol>0 && _lastColumn == oFirstCol -1) {
// ranges have a vertical border in common
// make sure rows are identical:
return _firstRow == oFirstRow && _lastRow == oLastRow;
}
return false;
}
/**
* Create an enclosing CellRange for the two cell ranges.
*
* @return enclosing CellRange
*/
public CellRange createEnclosingCellRange(CellRange range)
{
if( range == null)
{
return cloneCellRange();
}
else
{
CellRange cellRange =
new CellRange(
lt(range.getFirstRow(),getFirstRow())?range.getFirstRow():getFirstRow(),
gt(range.getLastRow(),getLastRow())?range.getLastRow():getLastRow(),
lt(range.getFirstColumn(),getFirstColumn())?range.getFirstColumn():getFirstColumn(),
gt(range.getLastColumn(),getLastColumn())?range.getLastColumn():getLastColumn()
);
return cellRange;
}
}
public CellRange cloneCellRange()
{
return new CellRange(getFirstRow(),getLastRow(),getFirstColumn(),getLastColumn());
}

/**
* @return true if a < b
*/
private static boolean lt(int a, int b)
{
return a == -1 ? false : (b == -1 ? true : a < b);
}
/**
* @return true if a <= b
*/
private static boolean le(int a, int b)
{
return a == b || lt(a,b);
}
/**
* @return true if a > b
*/
private static boolean gt(int a, int b)
{
return lt(b,a);
}

/**
* @return true if a >= b
*/
private static boolean ge(int a, int b)
{
return !lt(a,b);
}
public String toString()
{
return "("+getFirstRow()+","+getLastRow()+","+getFirstColumn()+","+getLastColumn()+")";
}
}

+ 363
- 0
src/java/org/apache/poi/hssf/record/cf/CellRangeUtil.java View File

@@ -0,0 +1,363 @@
/* ====================================================================
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.hssf.record.cf;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.poi.hssf.util.CellRangeAddress;

/**
*
* @author Dmitriy Kumshayev
*/
public final class CellRangeUtil
{
private CellRangeUtil() {
// no instance of this class
}
public static final int NO_INTERSECTION = 1;
public static final int OVERLAP = 2;
/** first range is within the second range */
public static final int INSIDE = 3;
/** first range encloses or is equal to the second */
public static final int ENCLOSES = 4;
/**
* Intersect this range with the specified range.
*
* @param crB - the specified range
* @return code which reflects how the specified range is related to this range.<br/>
* Possible return codes are:
* NO_INTERSECTION - the specified range is outside of this range;<br/>
* OVERLAP - both ranges partially overlap;<br/>
* INSIDE - the specified range is inside of this one<br/>
* ENCLOSES - the specified range encloses (possibly exactly the same as) this range<br/>
*/
public static int intersect(CellRangeAddress crA, CellRangeAddress crB )
{
int firstRow = crB.getFirstRow();
int lastRow = crB.getLastRow();
int firstCol = crB.getFirstColumn();
int lastCol = crB.getLastColumn();
if
(
gt(crA.getFirstRow(),lastRow) ||
lt(crA.getLastRow(),firstRow) ||
gt(crA.getFirstColumn(),lastCol) ||
lt(crA.getLastColumn(),firstCol)
)
{
return NO_INTERSECTION;
}
else if( contains(crA, crB) )
{
return INSIDE;
}
else if( contains(crB, crA))
{
return ENCLOSES;
}
else
{
return OVERLAP;
}
}
/**
* Do all possible cell merges between cells of the list so that:<br>
* <li>if a cell range is completely inside of another cell range, it gets removed from the list
* <li>if two cells have a shared border, merge them into one bigger cell range
* @param cellRangeList
* @return updated List of cell ranges
*/
public static CellRangeAddress[] mergeCellRanges(CellRangeAddress[] cellRanges) {
if(cellRanges.length < 1) {
return cellRanges;
}
List temp = mergeCellRanges(Arrays.asList(cellRanges));
return toArray(temp);
}
private static List mergeCellRanges(List cellRangeList)
{

while(cellRangeList.size() > 1)
{
boolean somethingGotMerged = false;
for( int i=0; i<cellRangeList.size(); i++)
{
CellRangeAddress range1 = (CellRangeAddress)cellRangeList.get(i);
for( int j=i+1; j<cellRangeList.size(); j++)
{
CellRangeAddress range2 = (CellRangeAddress)cellRangeList.get(j);
CellRangeAddress[] mergeResult = mergeRanges(range1, range2);
if(mergeResult == null) {
continue;
}
somethingGotMerged = true;
// overwrite range1 with first result
cellRangeList.set(i, mergeResult[0]);
// remove range2
cellRangeList.remove(j--);
// add any extra results beyond the first
for(int k=1; k<mergeResult.length; k++) {
j++;
cellRangeList.add(j, mergeResult[k]);
}
}
}
if(!somethingGotMerged) {
break;
}
}

return cellRangeList;
}
/**
* @return the new range(s) to replace the supplied ones. <code>null</code> if no merge is possible
*/
private static CellRangeAddress[] mergeRanges(CellRangeAddress range1, CellRangeAddress range2) {
int x = intersect(range1, range2);
switch(x)
{
case CellRangeUtil.NO_INTERSECTION:
if(hasExactSharedBorder(range1, range2)) {
return new CellRangeAddress[] { createEnclosingCellRange(range1, range2), };
}
// else - No intersection and no shared border: do nothing
return null;
case CellRangeUtil.OVERLAP:
return resolveRangeOverlap(range1, range2);
case CellRangeUtil.INSIDE:
// Remove range2, since it is completely inside of range1
return new CellRangeAddress[] { range1, };
case CellRangeUtil.ENCLOSES:
// range2 encloses range1, so replace it with the enclosing one
return new CellRangeAddress[] { range2, };
}
throw new RuntimeException("unexpected intersection result (" + x + ")");
}
// TODO - write junit test for this
static CellRangeAddress[] resolveRangeOverlap(CellRangeAddress rangeA, CellRangeAddress rangeB) {
if(rangeA.isFullColumnRange()) {
if(rangeA.isFullRowRange()) {
// Excel seems to leave these unresolved
return null;
}
return sliceUp(rangeA, rangeB);
}
if(rangeA.isFullRowRange()) {
if(rangeB.isFullColumnRange()) {
// Excel seems to leave these unresolved
return null;
}
return sliceUp(rangeA, rangeB);
}
if(rangeB.isFullColumnRange()) {
return sliceUp(rangeB, rangeA);
}
if(rangeB.isFullRowRange()) {
return sliceUp(rangeB, rangeA);
}
return sliceUp(rangeA, rangeB);
}

/**
* @param crB never a full row or full column range
* @return an array including <b>this</b> <tt>CellRange</tt> and all parts of <tt>range</tt>
* outside of this range
*/
private static CellRangeAddress[] sliceUp(CellRangeAddress crA, CellRangeAddress crB) {
List temp = new ArrayList();
// Chop up range horizontally and vertically
temp.add(crB);
if(!crA.isFullColumnRange()) {
temp = cutHorizontally(crA.getFirstRow(), temp);
temp = cutHorizontally(crA.getLastRow()+1, temp);
}
if(!crA.isFullRowRange()) {
temp = cutVertically(crA.getFirstColumn(), temp);
temp = cutVertically(crA.getLastColumn()+1, temp);
}
CellRangeAddress[] crParts = toArray(temp);

// form result array
temp.clear();
temp.add(crA);
for (int i = 0; i < crParts.length; i++) {
CellRangeAddress crPart = crParts[i];
// only include parts that are not enclosed by this
if(intersect(crA, crPart) != ENCLOSES) {
temp.add(crPart);
}
}
return toArray(temp);
}

private static List cutHorizontally(int cutRow, List input) {
List result = new ArrayList();
CellRangeAddress[] crs = toArray(input);
for (int i = 0; i < crs.length; i++) {
CellRangeAddress cr = crs[i];
if(cr.getFirstRow() < cutRow && cutRow < cr.getLastRow()) {
result.add(new CellRangeAddress(cr.getFirstRow(), cutRow, cr.getFirstColumn(), cr.getLastColumn()));
result.add(new CellRangeAddress(cutRow+1, cr.getLastRow(), cr.getFirstColumn(), cr.getLastColumn()));
} else {
result.add(cr);
}
}
return result;
}
private static List cutVertically(int cutColumn, List input) {
List result = new ArrayList();
CellRangeAddress[] crs = toArray(input);
for (int i = 0; i < crs.length; i++) {
CellRangeAddress cr = crs[i];
if(cr.getFirstColumn() < cutColumn && cutColumn < cr.getLastColumn()) {
result.add(new CellRangeAddress(cr.getFirstRow(), cr.getLastRow(), cr.getFirstColumn(), cutColumn));
result.add(new CellRangeAddress(cr.getFirstRow(), cr.getLastRow(), cutColumn+1, cr.getLastColumn()));
} else {
result.add(cr);
}
}
return result;
}


private static CellRangeAddress[] toArray(List temp) {
CellRangeAddress[] result = new CellRangeAddress[temp.size()];
temp.toArray(result);
return result;
}



/**
* Check if the specified range is located inside of this cell range.
*
* @param crB
* @return true if this cell range contains the argument range inside if it's area
*/
public static boolean contains(CellRangeAddress crA, CellRangeAddress crB)
{
int firstRow = crB.getFirstRow();
int lastRow = crB.getLastRow();
int firstCol = crB.getFirstColumn();
int lastCol = crB.getLastColumn();
return le(crA.getFirstRow(), firstRow) && ge(crA.getLastRow(), lastRow)
&& le(crA.getFirstColumn(), firstCol) && ge(crA.getLastColumn(), lastCol);
}
/**
* Check if the specified cell range has a shared border with the current range.
*
* @return <code>true</code> if the ranges have a complete shared border (i.e.
* the two ranges together make a simple rectangular region.
*/
public static boolean hasExactSharedBorder(CellRangeAddress crA, CellRangeAddress crB) {
int oFirstRow = crB.getFirstRow();
int oLastRow = crB.getLastRow();
int oFirstCol = crB.getFirstColumn();
int oLastCol = crB.getLastColumn();
if (crA.getFirstRow() > 0 && crA.getFirstRow()-1 == oLastRow ||
oFirstRow > 0 && oFirstRow-1 == crA.getLastRow()) {
// ranges have a horizontal border in common
// make sure columns are identical:
return crA.getFirstColumn() == oFirstCol && crA.getLastColumn() == oLastCol;
}

if (crA.getFirstColumn()>0 && crA.getFirstColumn() - 1 == oLastCol ||
oFirstCol>0 && crA.getLastColumn() == oFirstCol -1) {
// ranges have a vertical border in common
// make sure rows are identical:
return crA.getFirstRow() == oFirstRow && crA.getLastRow() == oLastRow;
}
return false;
}
/**
* Create an enclosing CellRange for the two cell ranges.
*
* @return enclosing CellRange
*/
public static CellRangeAddress createEnclosingCellRange(CellRangeAddress crA, CellRangeAddress crB) {
if( crB == null) {
return crA.copy();
}
return
new CellRangeAddress(
lt(crB.getFirstRow(), crA.getFirstRow()) ?crB.getFirstRow() :crA.getFirstRow(),
gt(crB.getLastRow(), crA.getLastRow()) ?crB.getLastRow() :crA.getLastRow(),
lt(crB.getFirstColumn(),crA.getFirstColumn())?crB.getFirstColumn():crA.getFirstColumn(),
gt(crB.getLastColumn(), crA.getLastColumn()) ?crB.getLastColumn() :crA.getLastColumn()
);
}
/**
* @return true if a < b
*/
private static boolean lt(int a, int b)
{
return a == -1 ? false : (b == -1 ? true : a < b);
}
/**
* @return true if a <= b
*/
private static boolean le(int a, int b)
{
return a == b || lt(a,b);
}
/**
* @return true if a > b
*/
private static boolean gt(int a, int b)
{
return lt(b,a);
}

/**
* @return true if a >= b
*/
private static boolean ge(int a, int b)
{
return !lt(a,b);
}
}

+ 10
- 6
src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormatting.java View File

@@ -16,10 +16,9 @@
==================================================================== */
package org.apache.poi.hssf.usermodel;

import org.apache.poi.hssf.record.CFHeaderRecord;
import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate;
import org.apache.poi.hssf.record.cf.CellRange;
import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.hssf.util.Region;

/**
@@ -96,13 +95,18 @@ public final class HSSFConditionalFormatting
}

/**
* @return array of <tt>Region</tt>s. never <code>null</code>
* @deprecated (Aug-2008) use {@link HSSFConditionalFormatting#getFormattingRanges()}
*/
public Region[] getFormattingRegions()
{
CFHeaderRecord cfh = cfAggregate.getHeader();
CellRange[] cellRanges = cfh.getCellRanges();
return CellRange.convertCellRangesToRegions(cellRanges);
CellRangeAddress[] cellRanges = getFormattingRanges();
return Region.convertCellRangesToRegions(cellRanges);
}
/**
* @return array of <tt>CellRangeAddress</tt>s. never <code>null</code>
*/
public CellRangeAddress[] getFormattingRanges() {
return cfAggregate.getHeader().getCellRanges();
}

/**

+ 56
- 32
src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java View File

@@ -38,6 +38,7 @@ import org.apache.poi.hssf.record.*;
import org.apache.poi.hssf.record.aggregates.DataValidityTable;
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.record.formula.RefPtg;
import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.hssf.util.PaneInformation;
import org.apache.poi.hssf.util.Region;
import org.apache.poi.util.POILogFactory;
@@ -517,20 +518,28 @@ public final class HSSFSheet {
}

/**
* adds a merged region of cells (hence those cells form one)
* @param region (rowfrom/colfrom-rowto/colto) to merge
* @return index of this region
* @deprecated (Aug-2008) use <tt>CellRangeAddress</tt> instead of <tt>Region</tt>
*/

public int addMergedRegion(Region region)
{
//return sheet.addMergedRegion((short) region.getRowFrom(),
return sheet.addMergedRegion( region.getRowFrom(),
region.getColumnFrom(),
//(short) region.getRowTo(),
region.getRowTo(),
region.getColumnTo());
}
/**
* adds a merged region of cells (hence those cells form one)
* @param region (rowfrom/colfrom-rowto/colto) to merge
* @return index of this region
*/
public int addMergedRegion(CellRangeAddress region)
{
return sheet.addMergedRegion( region.getFirstRow(),
region.getFirstColumn(),
region.getLastRow(),
region.getLastColumn());
}

/**
* Whether a record must be inserted or not at generation to indicate that
@@ -567,7 +576,7 @@ public final class HSSFSheet {

/**
* TODO: Boolean not needed, remove after next release
* @deprecated use getVerticallyCenter() instead
* @deprecated (Mar-2008) use getVerticallyCenter() instead
*/
public boolean getVerticallyCenter(boolean value) {
return getVerticallyCenter();
@@ -632,14 +641,19 @@ public final class HSSFSheet {
}

/**
* gets the region at a particular index
* @param index of the region to fetch
* @return the merged region (simple eh?)
* @deprecated (Aug-2008) use {@link HSSFSheet#getMergedRegion(int)}
*/

public Region getMergedRegionAt(int index)
{
return new Region(sheet.getMergedRegionAt(index));
public Region getMergedRegionAt(int index) {
CellRangeAddress cra = getMergedRegion(index);
return new Region(cra.getFirstRow(), (short)cra.getFirstColumn(),
cra.getLastRow(), (short)cra.getLastColumn());
}
/**
* @return the merged region at the specified index
*/
public CellRangeAddress getMergedRegion(int index) {
return sheet.getMergedRegionAt(index);
}

/**
@@ -1072,36 +1086,43 @@ public final class HSSFSheet {
protected void shiftMerged(int startRow, int endRow, int n, boolean isRow) {
List shiftedRegions = new ArrayList();
//move merged regions completely if they fall within the new region boundaries when they are shifted
for (int i = 0; i < this.getNumMergedRegions(); i++) {
Region merged = this.getMergedRegionAt(i);
for (int i = 0; i < getNumMergedRegions(); i++) {
CellRangeAddress merged = getMergedRegion(i);

boolean inStart = (merged.getRowFrom() >= startRow || merged.getRowTo() >= startRow);
boolean inEnd = (merged.getRowTo() <= endRow || merged.getRowFrom() <= endRow);
boolean inStart= (merged.getFirstRow() >= startRow || merged.getLastRow() >= startRow);
boolean inEnd = (merged.getFirstRow() <= endRow || merged.getLastRow() <= endRow);

//dont check if it's not within the shifted area
if (! (inStart && inEnd)) continue;
//don't check if it's not within the shifted area
if (!inStart || !inEnd) {
continue;
}

//only shift if the region outside the shifted rows is not merged too
if (!merged.contains(startRow-1, (short)0) && !merged.contains(endRow+1, (short)0)){
merged.setRowFrom(merged.getRowFrom()+n);
merged.setRowTo(merged.getRowTo()+n);
if (!containsCell(merged, startRow-1, 0) && !containsCell(merged, endRow+1, 0)){
merged.setFirstRow(merged.getFirstRow()+n);
merged.setLastRow(merged.getLastRow()+n);
//have to remove/add it back
shiftedRegions.add(merged);
this.removeMergedRegion(i);
removeMergedRegion(i);
i = i -1; // we have to back up now since we removed one

}

}

//readd so it doesn't get shifted again
//read so it doesn't get shifted again
Iterator iterator = shiftedRegions.iterator();
while (iterator.hasNext()) {
Region region = (Region)iterator.next();
CellRangeAddress region = (CellRangeAddress)iterator.next();

this.addMergedRegion(region);
}

}
private static boolean containsCell(CellRangeAddress cr, int rowIx, int colIx) {
if (cr.getFirstRow() <= rowIx && cr.getLastRow() >= rowIx
&& cr.getFirstColumn() <= colIx && cr.getLastColumn() >= colIx)
{
return true;
}
return false;
}

/**
@@ -1720,17 +1741,20 @@ public final class HSSFSheet {
HSSFRow row = (HSSFRow) it.next();
HSSFCell cell = row.getCell(column);

if (cell == null) continue;
if (cell == null) {
continue;
}

int colspan = 1;
for (int i = 0 ; i < getNumMergedRegions(); i++) {
if (getMergedRegionAt(i).contains(row.getRowNum(), column)) {
CellRangeAddress region = getMergedRegion(i);
if (containsCell(region, row.getRowNum(), column)) {
if (!useMergedCells) {
// If we're not using merged cells, skip this one and move on to the next.
continue rows;
}
cell = row.getCell(getMergedRegionAt(i).getColumnFrom());
colspan = 1+ getMergedRegionAt(i).getColumnTo() - getMergedRegionAt(i).getColumnFrom();
cell = row.getCell(region.getFirstColumn());
colspan = 1 + region.getLastColumn() - region.getFirstColumn();
}
}


+ 10
- 17
src/java/org/apache/poi/hssf/usermodel/HSSFSheetConditionalFormatting.java View File

@@ -20,6 +20,7 @@ package org.apache.poi.hssf.usermodel;
import org.apache.poi.hssf.model.Sheet;
import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate;
import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.hssf.util.Region;
/**
@@ -100,7 +101,12 @@ public final class HSSFSheetConditionalFormatting {
return _sheet.addConditionalFormatting(cfraClone);
}
/**
* @deprecated use <tt>CellRangeAddress</tt> instead of <tt>Region</tt>
*/
public int addConditionalFormatting(Region[] regions, HSSFConditionalFormattingRule[] cfRules) {
return addConditionalFormatting(Region.convertRegionsToCellRanges(regions), cfRules);
}
/**
* Allows to add a new Conditional Formatting set to the sheet.
*
@@ -109,8 +115,7 @@ public final class HSSFSheetConditionalFormatting {
*
* @return index of the newly created Conditional Formatting object
*/
public int addConditionalFormatting(Region[] regions, HSSFConditionalFormattingRule[] cfRules) {
public int addConditionalFormatting(CellRangeAddress[] regions, HSSFConditionalFormattingRule[] cfRules) {
if (regions == null) {
throw new IllegalArgumentException("regions must not be null");
}
@@ -132,7 +137,7 @@ public final class HSSFSheetConditionalFormatting {
return _sheet.addConditionalFormatting(cfra);
}
public int addConditionalFormatting(Region[] regions,
public int addConditionalFormatting(CellRangeAddress[] regions,
HSSFConditionalFormattingRule rule1)
{
return addConditionalFormatting(regions,
@@ -142,7 +147,7 @@ public final class HSSFSheetConditionalFormatting {
});
}
public int addConditionalFormatting(Region[] regions,
public int addConditionalFormatting(CellRangeAddress[] regions,
HSSFConditionalFormattingRule rule1,
HSSFConditionalFormattingRule rule2)
{
@@ -153,18 +158,6 @@ public final class HSSFSheetConditionalFormatting {
});
}
public int addConditionalFormatting(Region[] regions,
HSSFConditionalFormattingRule rule1,
HSSFConditionalFormattingRule rule2,
HSSFConditionalFormattingRule rule3)
{
return addConditionalFormatting(regions,
new HSSFConditionalFormattingRule[]
{
rule1, rule2, rule3
});
}
/**
* gets Conditional Formatting object at a particular index
*

+ 63
- 15
src/java/org/apache/poi/hssf/util/CellRangeAddress.java View File

@@ -17,38 +17,72 @@
package org.apache.poi.hssf.util;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.SelectionRecord;
import org.apache.poi.util.LittleEndian;
/**
* See OOO documentation: excelfileformat.pdf sec 2.5.14 - 'Cell Range Address'
* See OOO documentation: excelfileformat.pdf sec 2.5.14 - 'Cell Range Address'<p/>
*
* Note - {@link SelectionRecord} uses the BIFF5 version of this structure
* @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
*/
public final class CellRangeAddress {
private static final int ENCODED_SIZE = 8;
/*
* TODO - replace org.apache.poi.hssf.util.Region
*/
public static final int ENCODED_SIZE = 8;
/** max 65536 rows in BIFF8 */
private static final int LAST_ROW_INDEX = 0x00FFFF;
/** max 256 columns in BIFF8 */
private static final int LAST_COLUMN_INDEX = 0x00FF;
private int _firstRow;
private int _firstCol;
private int _lastRow;
private int _lastCol;
/*
* TODO - replace other incarnations of 'Cell Range Address' throughout POI:
* org.apache.poi.hssf.util.CellRange
* org.apache.poi.hssf.record.cf.CellRange
* org.apache.poi.hssf.util.HSSFCellRangeAddress.AddrStructure
* org.apache.poi.hssf.record.MergeCellsRecord.MergedRegion
* org.apache.poi.hssf.record.SelectionRecord.Reference
*
*/
public CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol) {
if(!isValid(firstRow, lastRow, firstCol, lastCol)) {
throw new IllegalArgumentException("invalid cell range (" + firstRow + ", " + lastRow
+ ", " + firstCol + ", " + lastCol + ")");
}
_firstRow = firstRow;
_lastRow = lastRow;
_lastRow = convertM1ToMax(lastRow, LAST_ROW_INDEX);
_firstCol = firstCol;
_lastCol = lastCol;
_lastCol = convertM1ToMax(lastCol, LAST_COLUMN_INDEX);
}
private static boolean isValid(int firstRow, int lastRow, int firstColumn, int lastColumn)
{
if(lastRow < 0 || lastRow > LAST_ROW_INDEX) {
return false;
}
if(firstRow < 0 || firstRow > LAST_ROW_INDEX) {
return false;
}
if(lastColumn < 0 || lastColumn > LAST_COLUMN_INDEX) {
return false;
}
if(firstColumn < 0 || firstColumn > LAST_COLUMN_INDEX) {
return false;
}
return true;
}
/**
* Range arithmetic is easier when using a large positive number for 'max row or column'
* instead of <tt>-1</tt>.
*/
private static int convertM1ToMax(int lastIx, int maxIndex) {
if(lastIx < 0) {
return maxIndex;
}
return lastIx;
}
public CellRangeAddress(RecordInputStream in) {
if (in.remaining() < ENCODED_SIZE) {
// Ran out of data
@@ -59,6 +93,12 @@ public final class CellRangeAddress {
_firstCol = in.readUShort();
_lastCol = in.readUShort();
}
public boolean isFullColumnRange() {
return _firstRow == 0 && _lastRow == LAST_ROW_INDEX;
}
public boolean isFullRowRange() {
return _firstCol == 0 && _lastCol == LAST_COLUMN_INDEX;
}
/**
* @return column number for the upper left hand corner
@@ -116,15 +156,23 @@ public final class CellRangeAddress {
_lastRow = lastRow;
}
/* package */ int serialize(byte[] data, int offset) {
public int serialize(int offset, byte[] data) {
LittleEndian.putUShort(data, offset + 0, _firstRow);
LittleEndian.putUShort(data, offset + 2, _lastRow);
LittleEndian.putUShort(data, offset + 4, _firstCol);
LittleEndian.putUShort(data, offset + 6, _lastCol);
return ENCODED_SIZE;
}
public CellRangeAddress copy() {
return new CellRangeAddress(_firstRow, _lastRow, _firstCol, _lastCol);
}
public static int getEncodedSize(int numberOfItems) {
return numberOfItems * ENCODED_SIZE;
}
public String toString() {
return getClass().getName() + " ["+_firstRow+", "+_lastRow+", "+_firstCol+", "+_lastCol+"]";
}
}

+ 32
- 4
src/java/org/apache/poi/hssf/util/CellRangeAddressList.java View File

@@ -74,12 +74,12 @@ public final class CellRangeAddressList {
*
* @return number of ADDR structures
*/
public int getADDRStructureNumber() {
public int countRanges() {
return _list.size();
}

/**
* Add an ADDR structure .
* Add a cell range structure.
*
* @param firstRow - the upper left hand corner's row
* @param firstCol - the upper left hand corner's col
@@ -89,7 +89,20 @@ public final class CellRangeAddressList {
*/
public void addCellRangeAddress(int firstRow, int firstCol, int lastRow, int lastCol) {
CellRangeAddress region = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol);
_list.add(region);
addCellRangeAddress(region);
}
public void addCellRangeAddress(CellRangeAddress cra) {
_list.add(cra);
}
public CellRangeAddress remove(int rangeIndex) {
if (_list.isEmpty()) {
throw new RuntimeException("List is empty");
}
if (rangeIndex < 0 || rangeIndex >= _list.size()) {
throw new RuntimeException("Range index (" + rangeIndex
+ ") is outside allowable range (0.." + (_list.size()-1) + ")");
}
return (CellRangeAddress) _list.remove(rangeIndex);
}

/**
@@ -106,7 +119,7 @@ public final class CellRangeAddressList {
LittleEndian.putUShort(data, offset, nItems);
for (int k = 0; k < nItems; k++) {
CellRangeAddress region = (CellRangeAddress) _list.get(k);
pos += region.serialize(data, offset + pos);
pos += region.serialize(offset + pos, data);
}
return getSize();
}
@@ -114,4 +127,19 @@ public final class CellRangeAddressList {
public int getSize() {
return 2 + CellRangeAddress.getEncodedSize(_list.size());
}
public CellRangeAddressList copy() {
CellRangeAddressList result = new CellRangeAddressList();
int nItems = _list.size();
for (int k = 0; k < nItems; k++) {
CellRangeAddress region = (CellRangeAddress) _list.get(k);
result.addCellRangeAddress(region.copy());
}
return result;
}
public CellRangeAddress[] getCellRangeAddresses() {
CellRangeAddress[] result = new CellRangeAddress[_list.size()];
_list.toArray(result);
return result;
}
}

+ 46
- 82
src/java/org/apache/poi/hssf/util/Region.java View File

@@ -15,10 +15,8 @@
limitations under the License.
==================================================================== */


package org.apache.poi.hssf.util;

import org.apache.poi.hssf.record.MergeCellsRecord.MergedRegion;

/**
* Represents a from/to row/col square. This is a object primitive
@@ -26,11 +24,9 @@ import org.apache.poi.hssf.record.MergeCellsRecord.MergedRegion;
* to represent a string of characters. Its really only useful for HSSF though.
*
* @author Andrew C. Oliver acoliver at apache dot org
* @deprecated (Aug-2008) use {@link CellRangeAddress}
*/

public class Region
implements Comparable
{
public class Region {
private int rowFrom;
private short colFrom;
private int rowTo;
@@ -52,15 +48,6 @@ public class Region
this.colTo = colTo;
}

/**
* special constructor (I know this is bad but it is so wrong that its right
* okay) that makes a region from a mergedcells's region subrecord.
*/

public Region(MergedRegion region)
{
this(region.row_from, region.col_from, region.row_to, region.col_to);
}

/**
* get the upper left hand corner column number
@@ -150,72 +137,49 @@ public class Region
this.rowTo = rowTo;
}

/**
* Answers: "is the row/column inside this range?"
*
* @return <code>true</code> if the cell is in the range and
* <code>false</code> if it is not
*/

public boolean contains(int row, short col)
{
if ((this.rowFrom <= row) && (this.rowTo >= row)
&& (this.colFrom <= col) && (this.colTo >= col))
{

// System.out.println("Region ("+rowFrom+","+colFrom+","+rowTo+","+
// colTo+") does contain "+row+","+col);
return true;
}
return false;
}

public boolean equals(Region r)
{
return (compareTo(r) == 0);
}

/**
* Compares that the given region is the same less than or greater than this
* region. If any regional coordiant passed in is less than this regions
* coordinants then a positive integer is returned. Otherwise a negative
* integer is returned.
*
* @param r region
* @see #compareTo(Object)
*/

public int compareTo(Region r)
{
if ((this.getRowFrom() == r.getRowFrom())
&& (this.getColumnFrom() == r.getColumnFrom())
&& (this.getRowTo() == r.getRowTo())
&& (this.getColumnTo() == r.getColumnTo()))
{
return 0;
}
if ((this.getRowFrom() < r.getRowFrom())
|| (this.getColumnFrom() < r.getColumnFrom())
|| (this.getRowTo() < r.getRowTo())
|| (this.getColumnTo() < r.getColumnTo()))
{
return 1;
}
return -1;
}

public int compareTo(Object o)
{
return compareTo(( Region ) o);
}

/**
* @return the area contained by this region (number of cells)
*/

public int getArea()
{
return ((1 + (getRowTo() - getRowFrom()))
* (1 + (getColumnTo() - getColumnFrom())));
}
/**
* Convert a List of CellRange objects to an array of regions
*
* @param List of CellRange objects
* @return regions
*/
public static Region[] convertCellRangesToRegions(CellRangeAddress[] cellRanges) {
int size = cellRanges.length;
if(size < 1) {
return new Region[0];
}
Region[] result = new Region[size];

for (int i = 0; i != size; i++) {
result[i] = convertToRegion(cellRanges[i]);
}
return result;
}


private static Region convertToRegion(CellRangeAddress cr) {
return new Region(cr.getFirstRow(), (short)cr.getFirstColumn(), cr.getLastRow(), (short)cr.getLastColumn());
}

public static CellRangeAddress[] convertRegionsToCellRanges(Region[] regions) {
int size = regions.length;
if(size < 1) {
return new CellRangeAddress[0];
}
CellRangeAddress[] result = new CellRangeAddress[size];

for (int i = 0; i != size; i++) {
result[i] = convertToCellRangeAddress(regions[i]);
}
return result;
}

public static CellRangeAddress convertToCellRangeAddress(Region r) {
return new CellRangeAddress(r.getRowFrom(), r.getRowTo(), r.getColumnFrom(), r.getColumnTo());
}
}

+ 12
- 19
src/testcases/org/apache/poi/hssf/record/TestCFHeaderRecord.java View File

@@ -20,7 +20,7 @@ package org.apache.poi.hssf.record;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;

import org.apache.poi.hssf.record.cf.CellRange;
import org.apache.poi.hssf.util.CellRangeAddress;

/**
* Tests the serialization and deserialization of the TestCFHeaderRecord
@@ -34,18 +34,18 @@ public final class TestCFHeaderRecord extends TestCase
public void testCreateCFHeaderRecord ()
{
CFHeaderRecord record = new CFHeaderRecord();
CellRange[] ranges = {
new CellRange(0,0xFFFF,5,5),
new CellRange(0,0xFFFF,6,6),
new CellRange(0,1,0,1),
new CellRange(0,1,2,3),
new CellRange(2,3,0,1),
new CellRange(2,3,2,3),
CellRangeAddress[] ranges = {
new CellRangeAddress(0,0xFFFF,5,5),
new CellRangeAddress(0,0xFFFF,6,6),
new CellRangeAddress(0,1,0,1),
new CellRangeAddress(0,1,2,3),
new CellRangeAddress(2,3,0,1),
new CellRangeAddress(2,3,2,3),
};
record.setCellRanges(ranges);
ranges = record.getCellRanges();
assertEquals(6,ranges.length);
CellRange enclosingCellRange = record.getEnclosingCellRange();
CellRangeAddress enclosingCellRange = record.getEnclosingCellRange();
assertEquals(0, enclosingCellRange.getFirstRow());
assertEquals(65535, enclosingCellRange.getLastRow());
assertEquals(0, enclosingCellRange.getFirstColumn());
@@ -95,7 +95,7 @@ public final class TestCFHeaderRecord extends TestCase
assertEquals("#CFRULES", 3, record.getNumberOfConditionalFormats());
assertTrue(record.getNeedRecalculation());
confirm(record.getEnclosingCellRange(), 0, 3, 0, 3);
CellRange[] ranges = record.getCellRanges();
CellRangeAddress[] ranges = record.getCellRanges();
assertEquals(4, ranges.length);
confirm(ranges[0], 0, 1, 0, 1);
confirm(ranges[1], 0, 1, 2, 3);
@@ -154,7 +154,7 @@ public final class TestCFHeaderRecord extends TestCase
assertEquals("#CFRULES", 19, record.getNumberOfConditionalFormats());
assertFalse(record.getNeedRecalculation());
confirm(record.getEnclosingCellRange(), 0, 65535, 0, 255);
CellRange[] ranges = record.getCellRanges();
CellRangeAddress[] ranges = record.getCellRanges();
assertEquals(3, ranges.length);
confirm(ranges[0], 40000, 50000, 2, 2);
confirm(ranges[1], 0, 65535, 5, 5);
@@ -168,18 +168,11 @@ public final class TestCFHeaderRecord extends TestCase
assertEquals("CFHeaderRecord doesn't match", recordData[i], output[i+4]);
}
}

private static void confirm(CellRange cr, int expFirstRow, int expLastRow, int expFirstCol, int expLastColumn) {
private static void confirm(CellRangeAddress cr, int expFirstRow, int expLastRow, int expFirstCol, int expLastColumn) {
assertEquals("first row", expFirstRow, cr.getFirstRow());
assertEquals("last row", expLastRow, cr.getLastRow());
assertEquals("first column", expFirstCol, cr.getFirstColumn());
assertEquals("last column", expLastColumn, cr.getLastColumn());
}

public static void main(String[] ignored_args)
{
System.out.println("Testing org.apache.poi.hssf.record.CFHeaderRecord");
junit.textui.TestRunner.run(TestCFHeaderRecord.class);
}
}

+ 9
- 10
src/testcases/org/apache/poi/hssf/record/TestMergeCellsRecord.java View File

@@ -1,4 +1,3 @@

/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@@ -15,19 +14,19 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record;

import junit.framework.TestCase;

import org.apache.poi.hssf.record.MergeCellsRecord.MergedRegion;
import org.apache.poi.hssf.util.CellRangeAddress;

/**
* Make sure the merge cells record behaves
* @author Danny Mui (dmui at apache dot org)
*
*/
public class TestMergeCellsRecord extends TestCase {
public final class TestMergeCellsRecord extends TestCase {
/**
* Make sure when a clone is called, we actually clone it.
@@ -40,13 +39,13 @@ public class TestMergeCellsRecord extends TestCase {
assertNotSame("Merged and cloned objects are the same", merge, clone);
MergedRegion mergeRegion = merge.getAreaAt(0);
MergedRegion cloneRegion = clone.getAreaAt(0);
CellRangeAddress mergeRegion = merge.getAreaAt(0);
CellRangeAddress cloneRegion = clone.getAreaAt(0);
assertNotSame("Should not point to same objects when cloning", mergeRegion, cloneRegion);
assertEquals("New Clone Row From doesnt match", mergeRegion.row_from, cloneRegion.row_from);
assertEquals("New Clone Row To doesnt match", mergeRegion.row_to, cloneRegion.row_to);
assertEquals("New Clone Col From doesnt match", mergeRegion.col_from, cloneRegion.col_from);
assertEquals("New Clone Col To doesnt match", mergeRegion.col_to, cloneRegion.col_to);
assertEquals("New Clone Row From doesnt match", mergeRegion.getFirstRow(), cloneRegion.getFirstRow());
assertEquals("New Clone Row To doesnt match", mergeRegion.getLastRow(), cloneRegion.getLastRow());
assertEquals("New Clone Col From doesnt match", mergeRegion.getFirstColumn(), cloneRegion.getFirstColumn());
assertEquals("New Clone Col To doesnt match", mergeRegion.getLastColumn(), cloneRegion.getLastColumn());
merge.removeAreaAt(0);
assertNotNull("Clone's item not removed", clone.getAreaAt(0));

+ 4
- 11
src/testcases/org/apache/poi/hssf/record/aggregates/TestCFRecordsAggregate.java View File

@@ -28,8 +28,8 @@ import org.apache.poi.hssf.record.CFHeaderRecord;
import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.RecordFactory;
import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator;
import org.apache.poi.hssf.record.cf.CellRange;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.CellRangeAddress;

/**
* Tests the serialization and deserialization of the CFRecordsAggregate
@@ -49,9 +49,9 @@ public final class TestCFRecordsAggregate extends TestCase
CFRuleRecord rule2 = CFRuleRecord.create(workbook, ComparisonOperator.BETWEEN, "2", "5");
CFRuleRecord rule3 = CFRuleRecord.create(workbook, ComparisonOperator.GE, "100", null);
header.setNumberOfConditionalFormats(3);
CellRange[] cellRanges = {
new CellRange(0,1,0,0),
new CellRange(0,1,2,2),
CellRangeAddress[] cellRanges = {
new CellRangeAddress(0,1,0,0),
new CellRangeAddress(0,1,2,2),
};
header.setCellRanges(cellRanges);
recs.add(header);
@@ -97,11 +97,4 @@ public final class TestCFRecordsAggregate extends TestCase
assertEquals(2, cellRanges.length);
assertEquals(3, header.getNumberOfConditionalFormats());
}

public static void main(String[] ignored_args)
{
System.out.println("Testing org.apache.poi.hssf.record.aggregates.CFRecordsAggregate");
junit.textui.TestRunner.run(TestCFRecordsAggregate.class);
}
}

+ 74
- 72
src/testcases/org/apache/poi/hssf/record/cf/TestCellRange.java View File

@@ -17,6 +17,8 @@ limitations under the License.

package org.apache.poi.hssf.record.cf;

import org.apache.poi.hssf.util.CellRangeAddress;

import junit.framework.AssertionFailedError;
import junit.framework.TestCase;

@@ -25,15 +27,15 @@ import junit.framework.TestCase;
*/
public final class TestCellRange extends TestCase
{
private static final CellRange biggest = createCR( 0, -1, 0,-1);
private static final CellRange tenthColumn = createCR( 0, -1,10,10);
private static final CellRange tenthRow = createCR(10, 10, 0,-1);
private static final CellRange box10x10 = createCR( 0, 10, 0,10);
private static final CellRange box9x9 = createCR( 0, 9, 0, 9);
private static final CellRange box10to20c = createCR( 0, 10,10,20);
private static final CellRange oneCell = createCR(10, 10,10,10);
private static final CellRangeAddress biggest = createCR( 0, -1, 0,-1);
private static final CellRangeAddress tenthColumn = createCR( 0, -1,10,10);
private static final CellRangeAddress tenthRow = createCR(10, 10, 0,-1);
private static final CellRangeAddress box10x10 = createCR( 0, 10, 0,10);
private static final CellRangeAddress box9x9 = createCR( 0, 9, 0, 9);
private static final CellRangeAddress box10to20c = createCR( 0, 10,10,20);
private static final CellRangeAddress oneCell = createCR(10, 10,10,10);

private static final CellRange[] sampleRanges = {
private static final CellRangeAddress[] sampleRanges = {
biggest, tenthColumn, tenthRow, box10x10, box9x9, box10to20c, oneCell,
};
@@ -54,9 +56,9 @@ public final class TestCellRange extends TestCase
* @param lastRow pass -1 for max row index
* @param lastCol pass -1 for max col index
*/
private static CellRange createCR(int firstRow, int lastRow, int firstCol, int lastCol) {
private static CellRangeAddress createCR(int firstRow, int lastRow, int firstCol, int lastCol) {
// max row & max col limit as per BIFF8
return new CellRange(
return new CellRangeAddress(
firstRow,
lastRow == -1 ? 0xFFFF : lastRow,
firstCol,
@@ -65,89 +67,89 @@ public final class TestCellRange extends TestCase
public void testContainsMethod()
{
CellRange [] ranges = sampleRanges;
CellRangeAddress [] ranges = sampleRanges;
for(int i=0; i!=ranges.length;i++)
{
for(int j=0; j!=ranges.length;j++)
{
boolean expectedResult = containsExpectedResults[i][j];
assertEquals("("+i+","+j+"): ", expectedResult, ranges[i].contains(ranges[j]));
assertEquals("("+i+","+j+"): ", expectedResult, CellRangeUtil.contains(ranges[i], ranges[j]));
}
}
}

private static final CellRange col1 = createCR( 0, -1, 1,1);
private static final CellRange col2 = createCR( 0, -1, 2,2);
private static final CellRange row1 = createCR( 1, 1, 0,-1);
private static final CellRange row2 = createCR( 2, 2, 0,-1);
private static final CellRangeAddress col1 = createCR( 0, -1, 1,1);
private static final CellRangeAddress col2 = createCR( 0, -1, 2,2);
private static final CellRangeAddress row1 = createCR( 1, 1, 0,-1);
private static final CellRangeAddress row2 = createCR( 2, 2, 0,-1);

private static final CellRange box0 = createCR( 0, 2, 0,2);
private static final CellRange box1 = createCR( 0, 1, 0,1);
private static final CellRange box2 = createCR( 0, 1, 2,3);
private static final CellRange box3 = createCR( 2, 3, 0,1);
private static final CellRange box4 = createCR( 2, 3, 2,3);
private static final CellRange box5 = createCR( 1, 3, 1,3);
private static final CellRangeAddress box0 = createCR( 0, 2, 0,2);
private static final CellRangeAddress box1 = createCR( 0, 1, 0,1);
private static final CellRangeAddress box2 = createCR( 0, 1, 2,3);
private static final CellRangeAddress box3 = createCR( 2, 3, 0,1);
private static final CellRangeAddress box4 = createCR( 2, 3, 2,3);
private static final CellRangeAddress box5 = createCR( 1, 3, 1,3);

public void testHasSharedBorderMethod()
{
assertFalse(col1.hasExactSharedBorder(col1));
assertFalse(col2.hasExactSharedBorder(col2));
assertTrue(col1.hasExactSharedBorder(col2));
assertTrue(col2.hasExactSharedBorder(col1));
assertFalse(CellRangeUtil.hasExactSharedBorder(col1, col1));
assertFalse(CellRangeUtil.hasExactSharedBorder(col2, col2));
assertTrue(CellRangeUtil.hasExactSharedBorder(col1, col2));
assertTrue(CellRangeUtil.hasExactSharedBorder(col2, col1));

assertFalse(row1.hasExactSharedBorder(row1));
assertFalse(row2.hasExactSharedBorder(row2));
assertTrue(row1.hasExactSharedBorder(row2));
assertTrue(row2.hasExactSharedBorder(row1));
assertFalse(CellRangeUtil.hasExactSharedBorder(row1, row1));
assertFalse(CellRangeUtil.hasExactSharedBorder(row2, row2));
assertTrue(CellRangeUtil.hasExactSharedBorder(row1, row2));
assertTrue(CellRangeUtil.hasExactSharedBorder(row2, row1));
assertFalse(row1.hasExactSharedBorder(col1));
assertFalse(row1.hasExactSharedBorder(col2));
assertFalse(col1.hasExactSharedBorder(row1));
assertFalse(col2.hasExactSharedBorder(row1));
assertFalse(row2.hasExactSharedBorder(col1));
assertFalse(row2.hasExactSharedBorder(col2));
assertFalse(col1.hasExactSharedBorder(row2));
assertFalse(col2.hasExactSharedBorder(row2));
assertTrue(col2.hasExactSharedBorder(col1));
assertFalse(CellRangeUtil.hasExactSharedBorder(row1, col1));
assertFalse(CellRangeUtil.hasExactSharedBorder(row1, col2));
assertFalse(CellRangeUtil.hasExactSharedBorder(col1, row1));
assertFalse(CellRangeUtil.hasExactSharedBorder(col2, row1));
assertFalse(CellRangeUtil.hasExactSharedBorder(row2, col1));
assertFalse(CellRangeUtil.hasExactSharedBorder(row2, col2));
assertFalse(CellRangeUtil.hasExactSharedBorder(col1, row2));
assertFalse(CellRangeUtil.hasExactSharedBorder(col2, row2));
assertTrue(CellRangeUtil.hasExactSharedBorder(col2, col1));
assertFalse(box1.hasExactSharedBorder(box1));
assertTrue(box1.hasExactSharedBorder(box2));
assertTrue(box1.hasExactSharedBorder(box3));
assertFalse(box1.hasExactSharedBorder(box4));
assertFalse(CellRangeUtil.hasExactSharedBorder(box1, box1));
assertTrue(CellRangeUtil.hasExactSharedBorder(box1, box2));
assertTrue(CellRangeUtil.hasExactSharedBorder(box1, box3));
assertFalse(CellRangeUtil.hasExactSharedBorder(box1, box4));
assertTrue(box2.hasExactSharedBorder(box1));
assertFalse(box2.hasExactSharedBorder(box2));
assertFalse(box2.hasExactSharedBorder(box3));
assertTrue(box2.hasExactSharedBorder(box4));
assertTrue(CellRangeUtil.hasExactSharedBorder(box2, box1));
assertFalse(CellRangeUtil.hasExactSharedBorder(box2, box2));
assertFalse(CellRangeUtil.hasExactSharedBorder(box2, box3));
assertTrue(CellRangeUtil.hasExactSharedBorder(box2, box4));
assertTrue(box3.hasExactSharedBorder(box1));
assertFalse(box3.hasExactSharedBorder(box2));
assertFalse(box3.hasExactSharedBorder(box3));
assertTrue(box3.hasExactSharedBorder(box4));
assertTrue(CellRangeUtil.hasExactSharedBorder(box3, box1));
assertFalse(CellRangeUtil.hasExactSharedBorder(box3, box2));
assertFalse(CellRangeUtil.hasExactSharedBorder(box3, box3));
assertTrue(CellRangeUtil.hasExactSharedBorder(box3, box4));
assertFalse(box4.hasExactSharedBorder(box1));
assertTrue(box4.hasExactSharedBorder(box2));
assertTrue(box4.hasExactSharedBorder(box3));
assertFalse(box4.hasExactSharedBorder(box4));
assertFalse(CellRangeUtil.hasExactSharedBorder(box4, box1));
assertTrue(CellRangeUtil.hasExactSharedBorder(box4, box2));
assertTrue(CellRangeUtil.hasExactSharedBorder(box4, box3));
assertFalse(CellRangeUtil.hasExactSharedBorder(box4, box4));
}

public void testIntersectMethod()
{
assertEquals(CellRange.OVERLAP,box0.intersect(box5));
assertEquals(CellRange.OVERLAP,box5.intersect(box0));
assertEquals(CellRange.NO_INTERSECTION,box1.intersect(box4));
assertEquals(CellRange.NO_INTERSECTION,box4.intersect(box1));
assertEquals(CellRange.NO_INTERSECTION,box2.intersect(box3));
assertEquals(CellRange.NO_INTERSECTION,box3.intersect(box2));
assertEquals(CellRange.INSIDE,box0.intersect(box1));
assertEquals(CellRange.INSIDE,box0.intersect(box0));
assertEquals(CellRange.ENCLOSES,box1.intersect(box0));
assertEquals(CellRange.INSIDE,tenthColumn.intersect(oneCell));
assertEquals(CellRange.ENCLOSES,oneCell.intersect(tenthColumn));
assertEquals(CellRange.OVERLAP,tenthColumn.intersect(tenthRow));
assertEquals(CellRange.OVERLAP,tenthRow.intersect(tenthColumn));
assertEquals(CellRange.INSIDE,tenthColumn.intersect(tenthColumn));
assertEquals(CellRange.INSIDE,tenthRow.intersect(tenthRow));
assertEquals(CellRangeUtil.OVERLAP, CellRangeUtil.intersect(box0, box5));
assertEquals(CellRangeUtil.OVERLAP, CellRangeUtil.intersect(box5, box0));
assertEquals(CellRangeUtil.NO_INTERSECTION, CellRangeUtil.intersect(box1, box4));
assertEquals(CellRangeUtil.NO_INTERSECTION, CellRangeUtil.intersect(box4, box1));
assertEquals(CellRangeUtil.NO_INTERSECTION, CellRangeUtil.intersect(box2, box3));
assertEquals(CellRangeUtil.NO_INTERSECTION, CellRangeUtil.intersect(box3, box2));
assertEquals(CellRangeUtil.INSIDE, CellRangeUtil.intersect(box0, box1));
assertEquals(CellRangeUtil.INSIDE, CellRangeUtil.intersect(box0, box0));
assertEquals(CellRangeUtil.ENCLOSES, CellRangeUtil.intersect(box1, box0));
assertEquals(CellRangeUtil.INSIDE, CellRangeUtil.intersect(tenthColumn, oneCell));
assertEquals(CellRangeUtil.ENCLOSES, CellRangeUtil.intersect(oneCell, tenthColumn));
assertEquals(CellRangeUtil.OVERLAP, CellRangeUtil.intersect(tenthColumn, tenthRow));
assertEquals(CellRangeUtil.OVERLAP, CellRangeUtil.intersect(tenthRow, tenthColumn));
assertEquals(CellRangeUtil.INSIDE, CellRangeUtil.intersect(tenthColumn, tenthColumn));
assertEquals(CellRangeUtil.INSIDE, CellRangeUtil.intersect(tenthRow, tenthRow));
}
/**
@@ -155,7 +157,7 @@ public final class TestCellRange extends TestCase
* =$C:$IV,$B$1:$B$8,$B$10:$B$65536,$A:$A
*/
public void testCreate() {
CellRange cr;
CellRangeAddress cr;
cr = createCR(0, -1, 2, 255); // $C:$IV
confirmRange(cr, false, true);
@@ -172,7 +174,7 @@ public final class TestCellRange extends TestCase
cr = createCR(0, -1, 0, 0); // $A:$A
}

private static void confirmRange(CellRange cr, boolean isFullRow, boolean isFullColumn) {
private static void confirmRange(CellRangeAddress cr, boolean isFullRow, boolean isFullColumn) {
assertEquals("isFullRowRange", isFullRow, cr.isFullRowRange());
assertEquals("isFullColumnRange", isFullColumn, cr.isFullColumnRange());
}

+ 7
- 7
src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java View File

@@ -35,6 +35,7 @@ import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.NameRecord;
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
import org.apache.poi.hssf.record.formula.DeletedArea3DPtg;
import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.hssf.util.Region;
import org.apache.poi.util.TempFile;

@@ -301,15 +302,14 @@ public final class TestBugs extends TestCase {

/**
* Merged regions were being removed from the parent in cloned sheets
* @throws Exception
*/
public void test22720() {
HSSFWorkbook workBook = new HSSFWorkbook();
workBook.createSheet("TEST");
HSSFSheet template = workBook.getSheetAt(0);

template.addMergedRegion(new Region(0, (short)0, 1, (short)2));
template.addMergedRegion(new Region(1, (short)0, 2, (short)2));
template.addMergedRegion(new CellRangeAddress(0, 1, 0, 2));
template.addMergedRegion(new CellRangeAddress(1, 2, 0, 2));

HSSFSheet clone = workBook.cloneSheet(0);
int originalMerged = template.getNumMergedRegions();
@@ -317,20 +317,20 @@ public final class TestBugs extends TestCase {

// remove merged regions from clone
for (int i=template.getNumMergedRegions()-1; i>=0; i--) {
clone.removeMergedRegion(i);
clone.removeMergedRegion(i);
}

assertEquals("Original Sheet's Merged Regions were removed", originalMerged, template.getNumMergedRegions());
// check if template's merged regions are OK
if (template.getNumMergedRegions()>0) {
// fetch the first merged region...EXCEPTION OCCURS HERE
template.getMergedRegionAt(0);
// fetch the first merged region...EXCEPTION OCCURS HERE
template.getMergedRegion(0);
}
//make sure we dont exception

}

/*Tests read and write of Unicode strings in formula results
/**Tests read and write of Unicode strings in formula results
* bug and testcase submitted by Sompop Kumnoonsate
* The file contains THAI unicode characters.
*/

+ 9
- 16
src/testcases/org/apache/poi/hssf/usermodel/TestCloneSheet.java View File

@@ -20,6 +20,8 @@
package org.apache.poi.hssf.usermodel;

import junit.framework.TestCase;

import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.hssf.util.Region;

/**
@@ -28,23 +30,15 @@ import org.apache.poi.hssf.util.Region;
* add that record to the sheet in the testCloneSheetBasic method.
* @author avik
*/
public class TestCloneSheet extends TestCase {
public final class TestCloneSheet extends TestCase {

public TestCloneSheet(String arg0) {
super(arg0);
}
public void testCloneSheetBasic(){
try{
HSSFWorkbook b = new HSSFWorkbook();
HSSFSheet s = b.createSheet("Test");
s.addMergedRegion(new Region((short)0,(short)0,(short)1,(short)1));
HSSFSheet clonedSheet = b.cloneSheet(0);
assertEquals("One merged area", 1, clonedSheet.getNumMergedRegions());

}
catch(Exception e){e.printStackTrace();fail(e.getMessage());}
HSSFWorkbook b = new HSSFWorkbook();
HSSFSheet s = b.createSheet("Test");
s.addMergedRegion(new CellRangeAddress(0, 1, 0, 1));
HSSFSheet clonedSheet = b.cloneSheet(0);
assertEquals("One merged area", 1, clonedSheet.getNumMergedRegions());
}

/**
@@ -65,5 +59,4 @@ public class TestCloneSheet extends TestCase {
assertTrue("Row 3 still should be broken", clone.isRowBroken(3));
}
}

+ 3
- 3
src/testcases/org/apache/poi/hssf/usermodel/TestDataValidation.java View File

@@ -32,6 +32,7 @@ import org.apache.poi.hssf.eventmodel.ERFListener;
import org.apache.poi.hssf.eventmodel.EventRecordFactory;
import org.apache.poi.hssf.record.DVRecord;
import org.apache.poi.hssf.record.RecordFormatException;
import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.hssf.util.CellRangeAddressList;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.hssf.util.Region;
@@ -254,8 +255,7 @@ public final class TestDataValidation extends TestCase {
HSSFSheet sheet = _currentSheet;
HSSFRow row = sheet.createRow(sheet.getPhysicalNumberOfRows());
row = sheet.createRow(sheet.getPhysicalNumberOfRows());
sheet.addMergedRegion(new Region((short) (sheet.getPhysicalNumberOfRows() - 1),
(short) 0, (short) (sheet.getPhysicalNumberOfRows() - 1), (short) 5));
sheet.addMergedRegion(new CellRangeAddress(sheet.getPhysicalNumberOfRows()-1, sheet.getPhysicalNumberOfRows()-1, 0, 5));
HSSFCell cell = row.createCell((short) 0);
setCellValue(cell, strTypeDescription);
cell.setCellStyle(_style_3);
@@ -297,7 +297,7 @@ public final class TestDataValidation extends TestCase {
public void createDVDescriptionRow(String strTypeDescription) {
HSSFSheet sheet = _currentSheet;
HSSFRow row = sheet.getRow(sheet.getPhysicalNumberOfRows()-1);
sheet.addMergedRegion(new Region((short)(sheet.getPhysicalNumberOfRows()-1),(short)0,(short)(sheet.getPhysicalNumberOfRows()-1),(short)5));
sheet.addMergedRegion(new CellRangeAddress(sheet.getPhysicalNumberOfRows()-1, sheet.getPhysicalNumberOfRows()-1, 0, 5));
HSSFCell cell = row.createCell((short)0);
setCellValue(cell, strTypeDescription);
cell.setCellStyle(_style_3);

+ 9
- 10
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFConditionalFormatting.java View File

@@ -20,8 +20,8 @@ package org.apache.poi.hssf.usermodel;
import junit.framework.TestCase;

import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator;
import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.hssf.util.Region;
/**
*
* @author Dmitriy Kumshayev
@@ -57,9 +57,8 @@ public final class TestHSSFConditionalFormatting extends TestCase
};

short col = 1;
Region [] regions =
{
new Region(0,col,65535,col)
CellRangeAddress [] regions = {
new CellRangeAddress(0, 65535, col, col)
};

sheetCF.addConditionalFormatting(regions, cfRules);
@@ -72,14 +71,14 @@ public final class TestHSSFConditionalFormatting extends TestCase
HSSFConditionalFormatting cf = sheetCF.getConditionalFormattingAt(0);
assertNotNull(cf);

regions = cf.getFormattingRegions();
regions = cf.getFormattingRanges();
assertNotNull(regions);
assertEquals(1, regions.length);
Region r = regions[0];
assertEquals(1, r.getColumnFrom());
assertEquals(1, r.getColumnTo());
assertEquals(0, r.getRowFrom());
assertEquals(65535, r.getRowTo());
CellRangeAddress r = regions[0];
assertEquals(1, r.getFirstColumn());
assertEquals(1, r.getLastColumn());
assertEquals(0, r.getFirstRow());
assertEquals(65535, r.getLastRow());

assertEquals(2, cf.getNumberOfRules());


+ 12
- 12
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java View File

@@ -35,7 +35,7 @@ import org.apache.poi.hssf.record.SCLRecord;
import org.apache.poi.hssf.record.VCenterRecord;
import org.apache.poi.hssf.record.WSBoolRecord;
import org.apache.poi.hssf.record.WindowTwoRecord;
import org.apache.poi.hssf.util.Region;
import org.apache.poi.hssf.util.CellRangeAddress;

/**
* Tests HSSFSheet. This test case is very incomplete at the moment.
@@ -476,15 +476,15 @@ public final class TestHSSFSheet extends TestCase {
public void testRemoveMerged() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
Region region = new Region(0, (short)0, 1, (short)1);
CellRangeAddress region = new CellRangeAddress(0, 1, 0, 1);
sheet.addMergedRegion(region);
region = new Region(1, (short)0, 2, (short)1);
region = new CellRangeAddress(1, 2, 0, 1);
sheet.addMergedRegion(region);

sheet.removeMergedRegion(0);

region = sheet.getMergedRegionAt(0);
assertEquals("Left over region should be starting at row 1", 1, region.getRowFrom());
region = sheet.getMergedRegion(0);
assertEquals("Left over region should be starting at row 1", 1, region.getFirstRow());

sheet.removeMergedRegion(0);

@@ -496,15 +496,15 @@ public final class TestHSSFSheet extends TestCase {
sheet.removeMergedRegion(0);
assertEquals("there should now be zero merged regions!", 0, sheet.getNumMergedRegions());
//add it again!
region.setRowTo(4);
region.setLastRow(4);

sheet.addMergedRegion(region);
assertEquals("there should now be one merged region!", 1, sheet.getNumMergedRegions());

//should exist now!
assertTrue("there isn't more than one merged region in there", 1 <= sheet.getNumMergedRegions());
region = sheet.getMergedRegionAt(0);
assertEquals("the merged row to doesnt match the one we put in ", 4, region.getRowTo());
region = sheet.getMergedRegion(0);
assertEquals("the merged row to doesnt match the one we put in ", 4, region.getLastRow());
}

public void testShiftMerged() {
@@ -518,13 +518,13 @@ public final class TestHSSFSheet extends TestCase {
cell = row.createCell((short)1);
cell.setCellValue(new HSSFRichTextString("second row, second cell"));

Region region = new Region(1, (short)0, 1, (short)1);
CellRangeAddress region = new CellRangeAddress(1, 1, 0, 1);
sheet.addMergedRegion(region);

sheet.shiftRows(1, 1, 1);

region = sheet.getMergedRegionAt(0);
assertEquals("Merged region not moved over to row 2", 2, region.getRowFrom());
region = sheet.getMergedRegion(0);
assertEquals("Merged region not moved over to row 2", 2, region.getFirstRow());
}

/**
@@ -683,7 +683,7 @@ public final class TestHSSFSheet extends TestCase {
assertTrue("Column autosized with only one row: wrong width", sheet.getColumnWidth((short)0) <= maxWithRow1And2);

//create a region over the 2nd row and auto size the first column
sheet.addMergedRegion(new Region(1,(short)0,1,(short)1));
sheet.addMergedRegion(new CellRangeAddress(1,1,0,1));
sheet.autoSizeColumn((short)0);
HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb);


+ 33
- 48
src/testcases/org/apache/poi/hssf/usermodel/TestWorkbook.java View File

@@ -31,7 +31,7 @@ import org.apache.poi.hssf.record.BackupRecord;
import org.apache.poi.hssf.record.LabelSSTRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.aggregates.ValueRecordsAggregate;
import org.apache.poi.hssf.util.Region;
import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.TempFile;

@@ -42,7 +42,7 @@ import org.apache.poi.util.TempFile;
* @author Greg Merrill
* @author Siggi Cherem
*/
public class TestWorkbook extends TestCase {
public final class TestWorkbook extends TestCase {
private static final String LAST_NAME_KEY = "lastName";
private static final String FIRST_NAME_KEY = "firstName";
private static final String SSN_KEY = "ssn";
@@ -260,10 +260,10 @@ public class TestWorkbook extends TestCase {
HSSFWorkbook workbook = openSample("Employee.xls");
HSSFSheet sheet = workbook.getSheetAt(0);

assertEquals(EMPLOYEE_INFORMATION, sheet.getRow(1).getCell(1).getStringCellValue());
assertEquals(LAST_NAME_KEY, sheet.getRow(3).getCell(2).getStringCellValue());
assertEquals(FIRST_NAME_KEY, sheet.getRow(4).getCell(2).getStringCellValue());
assertEquals(SSN_KEY, sheet.getRow(5).getCell(2).getStringCellValue());
assertEquals(EMPLOYEE_INFORMATION, sheet.getRow(1).getCell(1).getRichStringCellValue().getString());
assertEquals(LAST_NAME_KEY, sheet.getRow(3).getCell(2).getRichStringCellValue().getString());
assertEquals(FIRST_NAME_KEY, sheet.getRow(4).getCell(2).getRichStringCellValue().getString());
assertEquals(SSN_KEY, sheet.getRow(5).getCell(2).getRichStringCellValue().getString());
}

/**
@@ -318,13 +318,13 @@ public class TestWorkbook extends TestCase {

sheet = workbook.getSheetAt(0);
cell = sheet.getRow(0).getCell(1);
assertEquals(REPLACED, cell.getStringCellValue());
assertEquals(REPLACED, cell.getRichStringCellValue().getString());
cell = sheet.getRow(0).getCell(0);
assertEquals(DO_NOT_REPLACE, cell.getStringCellValue());
assertEquals(DO_NOT_REPLACE, cell.getRichStringCellValue().getString());
cell = sheet.getRow(1).getCell(0);
assertEquals(REPLACED, cell.getStringCellValue());
assertEquals(REPLACED, cell.getRichStringCellValue().getString());
cell = sheet.getRow(1).getCell(1);
assertEquals(DO_NOT_REPLACE, cell.getStringCellValue());
assertEquals(DO_NOT_REPLACE, cell.getRichStringCellValue().getString());
}

/**
@@ -388,10 +388,10 @@ public class TestWorkbook extends TestCase {

workbook = HSSFTestDataSamples.writeOutAndReadBack(workbook);
sheet = workbook.getSheetAt(0);
assertEquals(EMPLOYEE_INFORMATION, sheet.getRow(1).getCell(1).getStringCellValue());
assertEquals(LAST_NAME_VALUE, sheet.getRow(3).getCell(2).getStringCellValue());
assertEquals(FIRST_NAME_VALUE, sheet.getRow(4).getCell(2).getStringCellValue());
assertEquals(SSN_VALUE, sheet.getRow(5).getCell(2).getStringCellValue());
assertEquals(EMPLOYEE_INFORMATION, sheet.getRow(1).getCell(1).getRichStringCellValue().getString());
assertEquals(LAST_NAME_VALUE, sheet.getRow(3).getCell(2).getRichStringCellValue().getString());
assertEquals(FIRST_NAME_VALUE, sheet.getRow(4).getCell(2).getRichStringCellValue().getString());
assertEquals(SSN_VALUE, sheet.getRow(5).getCell(2).getRichStringCellValue().getString());
}

/**
@@ -421,26 +421,17 @@ public class TestWorkbook extends TestCase {
* HSSFSheet last row or first row is incorrect. <P>
*
*/

public void testWriteModifySheetMerged()
throws IOException
{
File file = TempFile.createTempFile("testWriteSheetMerged",
".xls");
FileOutputStream out = new FileOutputStream(file);
FileInputStream in = null;
public void testWriteModifySheetMerged() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet s = wb.createSheet();
HSSFRow r = null;
HSSFCell c = null;

for (short rownum = ( short ) 0; rownum < 100; rownum++)
{
r = s.createRow(rownum);
HSSFRow r = s.createRow(rownum);

for (short cellnum = ( short ) 0; cellnum < 50; cellnum += 2)
{
c = r.createCell(cellnum);
HSSFCell c = r.createCell(cellnum);
c.setCellValue(rownum * 10000 + cellnum
+ ((( double ) rownum / 1000)
+ (( double ) cellnum / 10000)));
@@ -448,33 +439,27 @@ public class TestWorkbook extends TestCase {
c.setCellValue(new HSSFRichTextString("TEST"));
}
}
s.addMergedRegion(new Region(( short ) 0, ( short ) 0, ( short ) 10,
( short ) 10));
s.addMergedRegion(new Region(( short ) 30, ( short ) 5, ( short ) 40,
( short ) 15));
wb.write(out);
out.close();
s.addMergedRegion(new CellRangeAddress(0, 10, 0, 10));
s.addMergedRegion(new CellRangeAddress(30, 40, 5, 15));
sanityChecker.checkHSSFWorkbook(wb);
in = new FileInputStream(file);
wb = new HSSFWorkbook(new POIFSFileSystem(in));
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
s = wb.getSheetAt(0);
Region r1 = s.getMergedRegionAt(0);
Region r2 = s.getMergedRegionAt(1);
CellRangeAddress r1 = s.getMergedRegion(0);
CellRangeAddress r2 = s.getMergedRegion(1);

in.close();

// System.out.println(file.length());
// assertEquals("FILE LENGTH == 87552",file.length(), 87552);
// System.out.println(s.getLastRowNum());
assertEquals("REGION1 = 0,0,10,10", 0,
new Region(( short ) 0, ( short ) 0, ( short ) 10,
( short ) 10).compareTo(r1));
assertEquals("REGION2 == 30,5,40,15", 0,
new Region(( short ) 30, ( short ) 5, ( short ) 40,
( short ) 15).compareTo(r2));
confirmRegion(new CellRangeAddress(0, 10, 0, 10), r1);
confirmRegion(new CellRangeAddress(30, 40,5, 15), r2);
}

/**
private static void confirmRegion(CellRangeAddress ra, CellRangeAddress rb) {
assertEquals(ra.getFirstRow(), rb.getFirstRow());
assertEquals(ra.getLastRow(), rb.getLastRow());
assertEquals(ra.getFirstColumn(), rb.getFirstColumn());
assertEquals(ra.getLastColumn(), rb.getLastColumn());
}

/**
* Test the backup field gets set as expected.
*/


Loading…
Cancel
Save