View | Details | Raw Unified | Return to bug 43901
Collapse All | Expand All

(-)C:\josh\source\poi\subv\trunk/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java (-76 / +79 lines)
Lines 15-25 Link Here
15
   limitations under the License.
15
   limitations under the License.
16
==================================================================== */
16
==================================================================== */
17
17
18
/*
19
 * HSSFRow.java
20
 *
21
 * Created on September 30, 2001, 3:44 PM
22
 */
23
package org.apache.poi.hssf.usermodel;
18
package org.apache.poi.hssf.usermodel;
24
19
25
import java.util.Iterator;
20
import java.util.Iterator;
Lines 38-48 Link Here
38
 * @author  Andrew C. Oliver (acoliver at apache dot org)
33
 * @author  Andrew C. Oliver (acoliver at apache dot org)
39
 * @author Glen Stampoultzis (glens at apache.org)
34
 * @author Glen Stampoultzis (glens at apache.org)
40
 */
35
 */
36
public final class HSSFRow implements Comparable {
41
37
42
public class HSSFRow
43
        implements Comparable
44
{
45
46
    // used for collections
38
    // used for collections
47
    public final static int INITIAL_CAPACITY = 5;
39
    public final static int INITIAL_CAPACITY = 5;
48
    //private short rowNum;
40
    //private short rowNum;
Lines 157-182 Link Here
157
     * @param cell to remove
149
     * @param cell to remove
158
     */
150
     */
159
    public void removeCell(HSSFCell cell) {
151
    public void removeCell(HSSFCell cell) {
160
    	removeCell(cell, true);
152
        if(cell == null) {
153
            throw new IllegalArgumentException("cell must not be null");
154
        }
155
        removeCell(cell, true);
161
    }
156
    }
162
    private void removeCell(HSSFCell cell, boolean alsoRemoveRecords) {
157
    private void removeCell(HSSFCell cell, boolean alsoRemoveRecords) {
163
    	if(alsoRemoveRecords) {
158
        
164
	        CellValueRecordInterface cval = cell.getCellValueRecord();
165
	        sheet.removeValueRecord(getRowNum(), cval);
166
    	}
167
    	
168
        short column=cell.getCellNum();
159
        short column=cell.getCellNum();
169
        if(cell!=null && column<cells.length)
160
        if(column < 0) {
170
        {
161
            throw new RuntimeException("Negative cell indexes not allowed");
171
          cells[column]=null;
172
        }
162
        }
173
163
        if(column >= cells.length || cell != cells[column]) {
174
        if (cell.getCellNum() == row.getLastCol())
164
            throw new RuntimeException("Specified cell is not from this row");
175
        {
176
            row.setLastCol(findLastCell(row.getLastCol()));
177
        }
165
        }
178
        if (cell.getCellNum() == row.getFirstCol())
166
        cells[column]=null;
179
        {
167
        
168
        if(alsoRemoveRecords) {
169
            CellValueRecordInterface cval = cell.getCellValueRecord();
170
            sheet.removeValueRecord(getRowNum(), cval);
171
        }
172
        
173
        if (cell.getCellNum()+1 == row.getLastCol()) {
174
            row.setLastCol((short) (findLastCell(row.getLastCol())+1));
175
        }
176
        if (cell.getCellNum() == row.getFirstCol()) {
180
            row.setFirstCol(findFirstCell(row.getFirstCol()));
177
            row.setFirstCol(findFirstCell(row.getFirstCol()));
181
        }
178
        }
182
    }
179
    }
Lines 234-240 Link Here
234
     * TODO - Should this really be public?
231
     * TODO - Should this really be public?
235
     */
232
     */
236
    protected int getOutlineLevel() {
233
    protected int getOutlineLevel() {
237
    	return row.getOutlineLevel();
234
        return row.getOutlineLevel();
238
    }
235
    }
239
    
236
    
240
    /**
237
    /**
Lines 244-298 Link Here
244
     * @param newColumn The new column number (0 based)
241
     * @param newColumn The new column number (0 based)
245
     */
242
     */
246
    public void moveCell(HSSFCell cell, short newColumn) {
243
    public void moveCell(HSSFCell cell, short newColumn) {
247
    	// Ensure the destination is free
244
        // Ensure the destination is free
248
    	if(cells.length > newColumn && cells[newColumn] != null) {
245
        if(cells.length > newColumn && cells[newColumn] != null) {
249
    		throw new IllegalArgumentException("Asked to move cell to column " + newColumn + " but there's already a cell there");
246
            throw new IllegalArgumentException("Asked to move cell to column " + newColumn + " but there's already a cell there");
250
    	}
247
        }
251
    	
248
        
252
    	// Check it's one of ours
249
        // Check it's one of ours
253
    	if(! cells[cell.getCellNum()].equals(cell)) {
250
        if(! cells[cell.getCellNum()].equals(cell)) {
254
    		throw new IllegalArgumentException("Asked to move a cell, but it didn't belong to our row");
251
            throw new IllegalArgumentException("Asked to move a cell, but it didn't belong to our row");
255
    	}
252
        }
256
    	
253
        
257
    	// Move the cell to the new position
254
        // Move the cell to the new position
258
    	// (Don't remove the records though)
255
        // (Don't remove the records though)
259
    	removeCell(cell, false);
256
        removeCell(cell, false);
260
    	cell.updateCellNum(newColumn);
257
        cell.updateCellNum(newColumn);
261
    	addCell(cell);
258
        addCell(cell);
262
    }
259
    }
263
260
264
    /**
261
    /**
265
     * used internally to add a cell.
262
     * used internally to add a cell.
266
     */
263
     */
267
    private void addCell(HSSFCell cell)
264
    private void addCell(HSSFCell cell) {
268
    {
265
269
        short column=cell.getCellNum();
266
        short column=cell.getCellNum();
270
        if (row.getFirstCol() == -1)
267
        // re-allocate cells array as required.
271
        {
268
        if(column>=cells.length) {
272
            row.setFirstCol(column);
269
            HSSFCell[] oldCells=cells;
270
            int newSize=oldCells.length*2;
271
            if(newSize<column+1) {
272
                newSize=column+1;
273
            }
274
            cells=new HSSFCell[newSize];
275
            System.arraycopy(oldCells,0,cells,0,oldCells.length);
273
        }
276
        }
274
        if (row.getLastCol() == -1)
275
        {
276
            row.setLastCol(column);
277
        }
278
279
        if(column>=cells.length)
280
        {
281
          HSSFCell[] oldCells=cells;
282
          int newSize=oldCells.length*2;
283
          if(newSize<column+1) newSize=column+1;
284
          cells=new HSSFCell[newSize];
285
          System.arraycopy(oldCells,0,cells,0,oldCells.length);
286
        }
287
        cells[column]=cell;
277
        cells[column]=cell;
288
278
        
289
        if (column < row.getFirstCol())
279
        // fix up firstCol and lastCol indexes
290
        {
280
        if (row.getFirstCol() == -1 || column < row.getFirstCol()) {
291
            row.setFirstCol(column);
281
            row.setFirstCol(column);
292
        }
282
        }
293
        if (column > row.getLastCol())
283
        
294
        {
284
        if (row.getLastCol() == -1 || column >= row.getLastCol()) {
295
            row.setLastCol(column);
285
            row.setLastCol((short) (column+1)); // +1 -> for one past the last index 
296
        }
286
        }
297
    }
287
    }
298
288
Lines 324-339 Link Here
324
    }
314
    }
325
315
326
    /**
316
    /**
327
     * gets the number of the last cell contained in this row <b>PLUS ONE</b>. 
317
     * Gets the index of the last cell contained in this row <b>PLUS ONE</b>. The result also 
328
     * @return short representing the last logical cell in the row <b>PLUS ONE</b>, or -1 if the row does not contain any cells.
318
     * happens to be the 1-based column number of the last cell.  This value can be used as a
319
     * standard upper bound when iterating over cells:
320
     * <pre> 
321
     * short minColIx = row.getFirstCellNum();
322
     * short maxColIx = row.getLastCellNum();
323
     * for(short colIx=minColIx; colIx&lt;maxColIx; colIx++) {
324
     *   HSSFCell cell = row.getCell(colIx);
325
     *   if(cell == null) {
326
     *     continue;
327
     *   }
328
     *   //... do something with cell
329
     * }
330
     * </pre>
331
     * 
332
     * @return short representing the last logical cell in the row <b>PLUS ONE</b>, or -1 if the
333
     *  row does not contain any cells.
329
     */
334
     */
330
335
    public short getLastCellNum() {
331
    public short getLastCellNum()
336
        if (getPhysicalNumberOfCells() == 0) {
332
    {
333
        if (getPhysicalNumberOfCells() == 0)
334
            return -1;
337
            return -1;
335
        else
338
        }
336
            return row.getLastCol();
339
        return row.getLastCol();
337
    }
340
    }
338
341
339
342
Lines 493-500 Link Here
493
      }
496
      }
494
497
495
      public Object next() {
498
      public Object next() {
496
    	  if (!hasNext())
499
          if (!hasNext())
497
    		  throw new NoSuchElementException("At last element");
500
              throw new NoSuchElementException("At last element");
498
        HSSFCell cell=cells[nextId];
501
        HSSFCell cell=cells[nextId];
499
        thisId=nextId;
502
        thisId=nextId;
500
        findNext();
503
        findNext();
Lines 502-509 Link Here
502
      }
505
      }
503
506
504
      public void remove() {
507
      public void remove() {
505
    	  if (thisId == -1)
508
          if (thisId == -1)
506
    		  throw new IllegalStateException("remove() called before next()");
509
              throw new IllegalStateException("remove() called before next()");
507
        cells[thisId]=null;
510
        cells[thisId]=null;
508
      }
511
      }
509
      
512
      
(-)C:\josh\source\poi\subv\trunk/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java (-23 lines)
Lines 1104-1132 Link Here
1104
        
1104
        
1105
        assertEquals(1, wb.getNumberOfSheets());
1105
        assertEquals(1, wb.getNumberOfSheets());
1106
    }
1106
    }
1107
    
1108
    /**
1109
     * POI is producing files with the wrong last-column
1110
     *  number on the row
1111
     */
1112
    public void BROKENtest43901() {
1113
		HSSFWorkbook book = new HSSFWorkbook();
1114
		HSSFSheet sheet = book.createSheet("test");
1115
1116
		// New row has last col -1
1117
		HSSFRow row = sheet.createRow(0);
1118
		assertEquals(-1, row.getLastCellNum());
1119
		if(row.getLastCellNum() == 0) {
1120
			fail("Identified bug 43901");
1121
		}
1122
		
1123
		// Create two cells, will return one higher
1124
		//  than that for the last number
1125
		row.createCell((short) 0);
1126
		assertEquals(1, row.getLastCellNum());
1127
		row.createCell((short) 255);
1128
		assertEquals(256, row.getLastCellNum());
1129
	}
1130
}
1107
}
1131
1108
1132
1109
(-)C:\josh\source\poi\subv\trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFRow.java (-77 / +83 lines)
Lines 1-4 Link Here
1
2
/* ====================================================================
1
/* ====================================================================
3
   Licensed to the Apache Software Foundation (ASF) under one or more
2
   Licensed to the Apache Software Foundation (ASF) under one or more
4
   contributor license agreements.  See the NOTICE file distributed with
3
   contributor license agreements.  See the NOTICE file distributed with
Lines 15-48 Link Here
15
   See the License for the specific language governing permissions and
14
   See the License for the specific language governing permissions and
16
   limitations under the License.
15
   limitations under the License.
17
==================================================================== */
16
==================================================================== */
18
        
19
17
20
package org.apache.poi.hssf.usermodel;
18
package org.apache.poi.hssf.usermodel;
21
19
20
import java.io.ByteArrayInputStream;
21
import java.io.ByteArrayOutputStream;
22
22
import junit.framework.TestCase;
23
import junit.framework.TestCase;
23
24
24
import java.io.File;
25
import java.io.FileInputStream;
26
import java.io.FileOutputStream;
27
28
import org.apache.poi.util.TempFile;
29
30
/**
25
/**
31
 * Test HSSFRow is okay.
26
 * Test HSSFRow is okay.
32
 *
27
 *
33
 * @author Glen Stampoultzis (glens at apache.org)
28
 * @author Glen Stampoultzis (glens at apache.org)
34
 */
29
 */
35
public class TestHSSFRow
30
public final class TestHSSFRow extends TestCase {
36
        extends TestCase
37
{
38
    public TestHSSFRow(String s)
39
    {
40
        super(s);
41
    }
42
31
43
    public void testLastAndFirstColumns()
32
    public void testLastAndFirstColumns() {
44
            throws Exception
45
    {
46
        HSSFWorkbook workbook = new HSSFWorkbook();
33
        HSSFWorkbook workbook = new HSSFWorkbook();
47
        HSSFSheet sheet = workbook.createSheet();
34
        HSSFSheet sheet = workbook.createSheet();
48
        HSSFRow row = sheet.createRow((short) 0);
35
        HSSFRow row = sheet.createRow((short) 0);
Lines 51-177 Link Here
51
38
52
        row.createCell((short) 2);
39
        row.createCell((short) 2);
53
        assertEquals(2, row.getFirstCellNum());
40
        assertEquals(2, row.getFirstCellNum());
54
        assertEquals(2, row.getLastCellNum());
41
        assertEquals(3, row.getLastCellNum());
55
42
56
        row.createCell((short) 1);
43
        row.createCell((short) 1);
57
        assertEquals(1, row.getFirstCellNum());
44
        assertEquals(1, row.getFirstCellNum());
58
        assertEquals(2, row.getLastCellNum());
45
        assertEquals(3, row.getLastCellNum());
59
        
46
60
        // check the exact case reported in 'bug' 43901 - notice that the cellNum is '0' based
47
        // check the exact case reported in 'bug' 43901 - notice that the cellNum is '0' based
61
        row.createCell((short) 3);
48
        row.createCell((short) 3);
62
        assertEquals(1, row.getFirstCellNum());
49
        assertEquals(1, row.getFirstCellNum());
63
        assertEquals(3, row.getLastCellNum());
50
        assertEquals(4, row.getLastCellNum());
64
65
    }
51
    }
66
52
67
    public void testRemoveCell()
53
    public void testRemoveCell() throws Exception {
68
            throws Exception
69
    {
70
        HSSFWorkbook workbook = new HSSFWorkbook();
54
        HSSFWorkbook workbook = new HSSFWorkbook();
71
        HSSFSheet sheet = workbook.createSheet();
55
        HSSFSheet sheet = workbook.createSheet();
72
        HSSFRow row = sheet.createRow((short) 0);
56
        HSSFRow row = sheet.createRow((short) 0);
73
        assertEquals(-1, row.getLastCellNum());
57
        assertEquals(-1, row.getLastCellNum());
74
        assertEquals(-1, row.getFirstCellNum());
58
        assertEquals(-1, row.getFirstCellNum());
75
        row.createCell((short) 1);
59
        row.createCell((short) 1);
76
        assertEquals(1, row.getLastCellNum());
60
        assertEquals(2, row.getLastCellNum());
77
        assertEquals(1, row.getFirstCellNum());
61
        assertEquals(1, row.getFirstCellNum());
78
        row.createCell((short) 3);
62
        row.createCell((short) 3);
79
        assertEquals(3, row.getLastCellNum());
63
        assertEquals(4, row.getLastCellNum());
80
        assertEquals(1, row.getFirstCellNum());
64
        assertEquals(1, row.getFirstCellNum());
81
        row.removeCell(row.getCell((short) 3));
65
        row.removeCell(row.getCell((short) 3));
82
        assertEquals(1, row.getLastCellNum());
66
        assertEquals(2, row.getLastCellNum());
83
        assertEquals(1, row.getFirstCellNum());
67
        assertEquals(1, row.getFirstCellNum());
84
        row.removeCell(row.getCell((short) 1));
68
        row.removeCell(row.getCell((short) 1));
85
        assertEquals(-1, row.getLastCellNum());
69
        assertEquals(-1, row.getLastCellNum());
86
        assertEquals(-1, row.getFirstCellNum());
70
        assertEquals(-1, row.getFirstCellNum());
87
71
88
        // check the row record actually writes it out as 0's
72
        // all cells on this row have been removed
73
        // so check the row record actually writes it out as 0's
89
        byte[] data = new byte[100];
74
        byte[] data = new byte[100];
90
        row.getRowRecord().serialize(0, data);
75
        row.getRowRecord().serialize(0, data);
91
        assertEquals(0, data[6]);
76
        assertEquals(0, data[6]);
92
        assertEquals(0, data[8]);
77
        assertEquals(0, data[8]);
93
78
94
        File file = TempFile.createTempFile("XXX", "XLS");
79
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
95
        FileOutputStream stream = new FileOutputStream(file);
80
        workbook.write(baos);
96
        workbook.write(stream);
81
        baos.close();
97
        stream.close();
82
        ByteArrayInputStream inputStream = new ByteArrayInputStream(baos.toByteArray());
98
        FileInputStream inputStream = new FileInputStream(file);
99
        workbook = new HSSFWorkbook(inputStream);
83
        workbook = new HSSFWorkbook(inputStream);
100
        sheet = workbook.getSheetAt(0);
84
        sheet = workbook.getSheetAt(0);
101
        stream.close();
85
        inputStream.close();
102
        file.delete();
86
103
        assertEquals(-1, sheet.getRow((short) 0).getLastCellNum());
87
        assertEquals(-1, sheet.getRow((short) 0).getLastCellNum());
104
        assertEquals(-1, sheet.getRow((short) 0).getFirstCellNum());
88
        assertEquals(-1, sheet.getRow((short) 0).getFirstCellNum());
105
    }
89
    }
106
    
90
107
    public void testMoveCell() throws Exception {
91
    public void testMoveCell() {
108
        HSSFWorkbook workbook = new HSSFWorkbook();
92
        HSSFWorkbook workbook = new HSSFWorkbook();
109
        HSSFSheet sheet = workbook.createSheet();
93
        HSSFSheet sheet = workbook.createSheet();
110
        HSSFRow row = sheet.createRow((short) 0);
94
        HSSFRow row = sheet.createRow((short) 0);
111
        HSSFRow rowB = sheet.createRow((short) 1);
95
        HSSFRow rowB = sheet.createRow((short) 1);
112
        
96
113
        HSSFCell cellA2 = rowB.createCell((short)0);
97
        HSSFCell cellA2 = rowB.createCell((short)0);
114
        assertEquals(0, rowB.getFirstCellNum());
98
        assertEquals(0, rowB.getFirstCellNum());
115
        assertEquals(0, rowB.getFirstCellNum());
99
        assertEquals(0, rowB.getFirstCellNum());
116
        
100
117
        assertEquals(-1, row.getLastCellNum());
101
        assertEquals(-1, row.getLastCellNum());
118
        assertEquals(-1, row.getFirstCellNum());
102
        assertEquals(-1, row.getFirstCellNum());
119
        HSSFCell cellB2 = row.createCell((short) 1);
103
        HSSFCell cellB2 = row.createCell((short) 1);
120
        HSSFCell cellB3 = row.createCell((short) 2);
104
        HSSFCell cellB3 = row.createCell((short) 2);
121
        HSSFCell cellB4 = row.createCell((short) 3);
105
        HSSFCell cellB4 = row.createCell((short) 3);
122
    	
106
123
        assertEquals(1, row.getFirstCellNum());
107
        assertEquals(1, row.getFirstCellNum());
124
        assertEquals(3, row.getLastCellNum());
108
        assertEquals(4, row.getLastCellNum());
125
        
109
126
        // Try to move to somewhere else that's used
110
        // Try to move to somewhere else that's used
127
        try {
111
        try {
128
        	row.moveCell(cellB2, (short)3);
112
            row.moveCell(cellB2, (short)3);
129
        	fail();
113
            fail("IllegalArgumentException should have been thrown");
130
        } catch(IllegalArgumentException e) {}
114
        } catch(IllegalArgumentException e) {
131
        
115
            // expected during successful test
116
        }
117
132
        // Try to move one off a different row
118
        // Try to move one off a different row
133
        try {
119
        try {
134
        	row.moveCell(cellA2, (short)3);
120
            row.moveCell(cellA2, (short)3);
135
        	fail();
121
            fail("IllegalArgumentException should have been thrown");
136
        } catch(IllegalArgumentException e) {}
122
        } catch(IllegalArgumentException e) {
137
        
123
            // expected during successful test
124
        }
125
138
        // Move somewhere spare
126
        // Move somewhere spare
139
        assertNotNull(row.getCell((short)1));
127
        assertNotNull(row.getCell((short)1));
140
    	row.moveCell(cellB2, (short)5);
128
        row.moveCell(cellB2, (short)5);
141
        assertNull(row.getCell((short)1));
129
        assertNull(row.getCell((short)1));
142
        assertNotNull(row.getCell((short)5));
130
        assertNotNull(row.getCell((short)5));
143
    	
131
144
    	assertEquals(5, cellB2.getCellNum());
132
        assertEquals(5, cellB2.getCellNum());
145
        assertEquals(2, row.getFirstCellNum());
133
        assertEquals(2, row.getFirstCellNum());
146
        assertEquals(5, row.getLastCellNum());
134
        assertEquals(6, row.getLastCellNum());
147
        
148
    }
135
    }
149
    
136
150
    public void testRowBounds()
137
    public void testRowBounds() {
151
            throws Exception
152
    {
153
      HSSFWorkbook workbook = new HSSFWorkbook();
138
      HSSFWorkbook workbook = new HSSFWorkbook();
154
      HSSFSheet sheet = workbook.createSheet();
139
      HSSFSheet sheet = workbook.createSheet();
155
      //Test low row bound
140
      //Test low row bound
156
      HSSFRow row = sheet.createRow( (short) 0);
141
      sheet.createRow( (short) 0);
157
      //Test low row bound exception      
142
      //Test low row bound exception
158
      boolean caughtException = false;
159
      try {
143
      try {
160
        row = sheet.createRow(-1);        
144
        sheet.createRow(-1);
145
        fail("IndexOutOfBoundsException should have been thrown");
161
      } catch (IndexOutOfBoundsException ex) {
146
      } catch (IndexOutOfBoundsException ex) {
162
        caughtException = true;
147
        // expected during successful test
163
      }      
148
      }
164
      assertTrue(caughtException);
149
165
      //Test high row bound      
150
      //Test high row bound
166
      row = sheet.createRow(65535);     
151
      sheet.createRow(65535);
167
      //Test high row bound exception           
152
      //Test high row bound exception
168
      caughtException = false;
169
      try {
153
      try {
170
        row = sheet.createRow(65536);        
154
        sheet.createRow(65536);
155
        fail("IndexOutOfBoundsException should have been thrown");
171
      } catch (IndexOutOfBoundsException ex) {
156
      } catch (IndexOutOfBoundsException ex) {
172
        caughtException = true;
157
        // expected during successful test
173
      }      
158
      }
174
      assertTrue(caughtException);
175
    }
159
    }
176
    
160
161
    /**
162
     * Prior to patch 43901, POI was producing files with the wrong last-column
163
     * number on the row
164
     */
165
    public void testLastCellNumIsCorrectAfterAddCell_bug43901(){
166
        HSSFWorkbook book = new HSSFWorkbook();
167
        HSSFSheet sheet = book.createSheet("test");
168
        HSSFRow row = sheet.createRow(0);
169
170
        // New row has last col -1
171
        assertEquals(-1, row.getLastCellNum());
172
        if(row.getLastCellNum() == 0) {
173
            fail("Identified bug 43901");
174
        }
175
176
        // Create two cells, will return one higher
177
        //  than that for the last number
178
        row.createCell((short) 0);
179
        assertEquals(1, row.getLastCellNum());
180
        row.createCell((short) 255);
181
        assertEquals(256, row.getLastCellNum());
182
    }
177
}
183
}

Return to bug 43901