_comment.setRef(newRef);
_comments.referenceUpdated(oldRef, _comment);
- if(_vmlShape != null) _vmlShape.getClientDataArray(0).setRowArray(0, new BigInteger(String.valueOf(row)));
+ if(_vmlShape != null) {
+ _vmlShape.getClientDataArray(0).setRowArray(0,
+ new BigInteger(String.valueOf(row)));
+
+ // There is a very odd xmlbeans bug when changing the row
+ // arrays which can lead to corrupt pointer
+ // This call seems to fix them again... See bug #50795
+ _vmlShape.getClientDataList().toString();
+ }
}
-
+
/**
* @return the rich text string of the comment
*/
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.SortedMap;
import java.util.TreeMap;
import javax.xml.namespace.QName;
protected CTSheet sheet;
protected CTWorksheet worksheet;
- private TreeMap<Integer, XSSFRow> _rows;
+ private SortedMap<Integer, XSSFRow> _rows;
private List<XSSFHyperlink> hyperlinks;
private ColumnHelper columnHelper;
private CommentsTable sheetComments;
* Master shared formula is the first formula in a group of shared formulas is saved in the f element.
*/
private Map<Integer, CTCellFormula> sharedFormulas;
- private TreeMap<String,XSSFTable> tables;
+ private SortedMap<String,XSSFTable> tables;
private List<CellRangeAddress> arrayFormulas;
private XSSFDataValidationHelper dataValidationHelper;
*/
@Override
@SuppressWarnings("deprecation") //YK: getXYZArray() array accessors are deprecated in xmlbeans with JDK 1.5 support
- public void shiftRows(int startRow, int endRow, int n, boolean copyRowHeight, boolean resetOriginalRowHeight) {
- // first remove all rows which will be overwritten
+ public void shiftRows(int startRow, int endRow, final int n, boolean copyRowHeight, boolean resetOriginalRowHeight) {
+ XSSFVMLDrawing vml = getVMLDrawing(false);
+
+ // first remove all rows which will be overwritten
for (Iterator<Row> it = rowIterator() ; it.hasNext() ; ) {
XSSFRow row = (XSSFRow)it.next();
int rownum = row.getRowNum();
// check if we should remove this row as it will be overwritten by the data later
- if (removeRow(startRow, endRow, n, rownum)) {
+ if (shouldRemoveRow(startRow, endRow, n, rownum)) {
// remove row from worksheet.getSheetData row array
int idx = _rows.headMap(row.getRowNum()).size();
worksheet.getSheetData().removeRow(idx);
+
// remove row from _rows
it.remove();
+
+ // also remove any comments associated with this row
+ if(sheetComments != null){
+ CTCommentList lst = sheetComments.getCTComments().getCommentList();
+ for (CTComment comment : lst.getCommentArray()) {
+ String strRef = comment.getRef();
+ CellReference ref = new CellReference(strRef);
+
+ // is this comment part of the current row?
+ if(ref.getRow() == rownum) {
+ sheetComments.removeComment(strRef);
+ vml.removeCommentShape(ref.getRow(), ref.getCol());
+ }
+ }
+ }
}
}
// then do the actual moving and also adjust comments/rowHeight
+ // we need to sort it in a way so the shifting does not mess up the structures,
+ // i.e. when shifting down, start from down and go up, when shifting up, vice-versa
+ SortedMap<XSSFComment, Integer> commentsToShift = new TreeMap<XSSFComment, Integer>(new Comparator<XSSFComment>() {
+ public int compare(XSSFComment o1, XSSFComment o2) {
+ int row1 = new CellReference(o1.getCTComment().getRef()).getRow();
+ int row2 = new CellReference(o2.getCTComment().getRef()).getRow();
+
+ if(row1 == row2) {
+ return 0;
+ }
+
+ // when shifting down, sort higher row-values first
+ if(n > 0) {
+ return row1 < row2 ? 1 : -1;
+ } else {
+ // sort lower-row values first when shifting up
+ return row1 > row2 ? 1 : -1;
+ }
+ }
+ });
+
for (Iterator<Row> it = rowIterator() ; it.hasNext() ; ) {
XSSFRow row = (XSSFRow)it.next();
int rownum = row.getRowNum();
if(sheetComments != null){
- //TODO shift Note's anchor in the associated /xl/drawing/vmlDrawings#.vml
- CTCommentList lst = sheetComments.getCTComments().getCommentList();
- for (CTComment comment : lst.getCommentArray()) {
- String oldRef = comment.getRef();
- CellReference ref = new CellReference(oldRef);
- if(ref.getRow() == rownum){
- ref = new CellReference(rownum + n, ref.getCol());
- comment.setRef(ref.formatAsString());
- sheetComments.referenceUpdated(oldRef, comment);
- }
+ // calculate the new rownum
+ int newrownum = shiftedRowNum(startRow, endRow, n, rownum);
+
+ // is there a change necessary for the current row?
+ if(newrownum != rownum) {
+ CTCommentList lst = sheetComments.getCTComments().getCommentList();
+ for (CTComment comment : lst.getCommentArray()) {
+ String oldRef = comment.getRef();
+ CellReference ref = new CellReference(oldRef);
+
+ // is this comment part of the current row?
+ if(ref.getRow() == rownum) {
+ XSSFComment xssfComment = new XSSFComment(sheetComments, comment,
+ vml == null ? null : vml.findCommentShape(rownum, ref.getCol()));
+
+ // we should not perform the shifting right here as we would then find
+ // already shifted comments and would shift them again...
+ commentsToShift.put(xssfComment, newrownum);
+ }
+ }
}
}
row.shift(n);
}
+
+ // adjust all the affected comment-structures now
+ // the Map is sorted and thus provides them in the order that we need here,
+ // i.e. from down to up if shifting down, vice-versa otherwise
+ for(Map.Entry<XSSFComment, Integer> entry : commentsToShift.entrySet()) {
+ entry.getKey().setRow(entry.getValue());
+ }
+
XSSFRowShifter rowShifter = new XSSFRowShifter(this);
int sheetIndex = getWorkbook().getSheetIndex(this);
rowShifter.updateConditionalFormatting(shifter);
//rebuild the _rows map
- TreeMap<Integer, XSSFRow> map = new TreeMap<Integer, XSSFRow>();
+ SortedMap<Integer, XSSFRow> map = new TreeMap<Integer, XSSFRow>();
for(XSSFRow r : _rows.values()) {
map.put(r.getRowNum(), r);
}
_rows = map;
}
+ private int shiftedRowNum(int startRow, int endRow, int n, int rownum) {
+ // no change if before any affected row
+ if(rownum < startRow && (n > 0 || (startRow - rownum) > n)) {
+ return rownum;
+ }
+
+ // no change if after any affected row
+ if(rownum > endRow && (n < 0 || (rownum - endRow) > n)) {
+ return rownum;
+ }
+
+ // row before and things are moved up
+ if(rownum < startRow) {
+ // row is moved down by the shifting
+ return rownum + (endRow - startRow);
+ }
+
+ // row is after and things are moved down
+ if(rownum > endRow) {
+ // row is moved up by the shifting
+ return rownum - (endRow - startRow);
+ }
+
+ // row is part of the shifted block
+ return rownum + n;
+ }
+
/**
* Location of the top left visible cell Location of the top left visible cell in the bottom right
* pane (when in Left-to-Right mode).
return sheetPr.isSetPageSetUpPr() ? sheetPr.getPageSetUpPr() : sheetPr.addNewPageSetUpPr();
}
- private boolean removeRow(int startRow, int endRow, int n, int rownum) {
+ private boolean shouldRemoveRow(int startRow, int endRow, int n, int rownum) {
// is this row in the target-window where the moved rows will land?
if (rownum >= (startRow + n) && rownum <= (endRow + n)) {
// only remove it if the current row is not part of the data that is copied
super.bug35084();
}
+ @Test
+ public void getCellComment() throws IOException {
+ // TODO: reading cell comments via Sheet does not work currently as it tries
+ // to access the underlying sheet for this, but comments are stored as
+ // properties on Cells...
+ }
+
@Override
@Test
public void defaultColumnStyle() {
import org.apache.poi.ss.usermodel.AutoFilter;
import org.apache.poi.ss.usermodel.BaseTestSheet;
import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CreationHelper;
-import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.xssf.SXSSFITestDataProvider;
import org.apache.poi.xssf.XSSFITestDataProvider;
import org.apache.poi.xssf.XSSFTestDataSamples;
import org.apache.poi.xssf.model.CalculationChain;
import org.apache.poi.xssf.model.CommentsTable;
import org.apache.poi.xssf.model.StylesTable;
-import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.helpers.ColumnHelper;
import org.junit.Test;
@SuppressWarnings("resource")
public final class TestXSSFSheet extends BaseTestSheet {
- private static final int ROW_COUNT = 40000;
-
public TestXSSFSheet() {
super(XSSFITestDataProvider.instance);
}
assertTrue(col.getBestFit());
}
- /**
- * XSSFSheet autoSizeColumn() on empty RichTextString fails
- */
- @Test
- public void bug48325() {
- XSSFWorkbook wb = new XSSFWorkbook();
- XSSFSheet sheet = wb.createSheet("Test");
- CreationHelper factory = wb.getCreationHelper();
-
- XSSFRow row = sheet.createRow(0);
- XSSFCell cell = row.createCell(0);
-
- XSSFFont font = wb.createFont();
- RichTextString rts = factory.createRichTextString("");
- rts.applyFont(font);
- cell.setCellValue(rts);
-
- sheet.autoSizeColumn(0);
- }
-
- @Test
- public void getCellComment() {
- XSSFWorkbook workbook = new XSSFWorkbook();
- XSSFSheet sheet = workbook.createSheet();
- XSSFDrawing dg = sheet.createDrawingPatriarch();
- XSSFComment comment = dg.createCellComment(new XSSFClientAnchor());
- XSSFCell cell = sheet.createRow(9).createCell(2);
- comment.setAuthor("test C10 author");
- cell.setCellComment(comment);
-
- assertNotNull(sheet.getCellComment(9, 2));
- assertEquals("test C10 author", sheet.getCellComment(9, 2).getAuthor());
- }
@Test
public void setCellComment() {
assertEquals(STPane.BOTTOM_RIGHT, ctWorksheet.getSheetViews().getSheetViewArray(0).getPane().getActivePane());
}
- @Test
- public void newMergedRegionAt() {
- XSSFWorkbook workbook = new XSSFWorkbook();
- XSSFSheet sheet = workbook.createSheet();
- CellRangeAddress region = CellRangeAddress.valueOf("B2:D4");
- sheet.addMergedRegion(region);
- assertEquals("B2:D4", sheet.getMergedRegion(0).formatAsString());
- assertEquals(1, sheet.getNumMergedRegions());
- }
-
@Test
public void removeMergedRegion_lowlevel() {
XSSFWorkbook workbook = new XSSFWorkbook();
}
}
- @Test
- public void showInPaneManyRowsBug55248() {
- XSSFWorkbook workbook = new XSSFWorkbook();
- XSSFSheet sheet = workbook.createSheet("Sheet 1");
-
- sheet.showInPane(0, 0);
-
- for(int i = ROW_COUNT/2;i < ROW_COUNT;i++) {
- sheet.createRow(i);
- sheet.showInPane(i, 0);
- // this one fails: sheet.showInPane((short)i, 0);
- }
-
- int i = 0;
- sheet.showInPane(i, i);
-
- XSSFWorkbook wb = XSSFTestDataSamples.writeOutAndReadBack(workbook);
- checkRowCount(wb);
- }
-
- @Test
- public void showInPaneManyRowsBug55248SXSSF() {
- SXSSFWorkbook workbook = new SXSSFWorkbook(new XSSFWorkbook());
- SXSSFSheet sheet = (SXSSFSheet) workbook.createSheet("Sheet 1");
-
- sheet.showInPane(0, 0);
-
- for(int i = ROW_COUNT/2;i < ROW_COUNT;i++) {
- sheet.createRow(i);
- sheet.showInPane(i, 0);
- // this one fails: sheet.showInPane((short)i, 0);
- }
-
- int i = 0;
- sheet.showInPane(i, i);
-
- Workbook wb = SXSSFITestDataProvider.instance.writeOutAndReadBack(workbook);
- checkRowCount(wb);
- }
-
- private void checkRowCount(Workbook wb) {
- assertNotNull(wb);
- final Sheet sh = wb.getSheet("Sheet 1");
- assertNotNull(sh);
- assertEquals(ROW_COUNT-1, sh.getLastRowNum());
- }
-
@Test
public void bug55745() throws Exception {
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("55745.xlsx");
XSSFSheet sheet = wb.createSheet();
assertNotNull(sheet.createComment());
}
-
- @Test
- public void testRightToLeft() {
- XSSFWorkbook wb = new XSSFWorkbook();
- XSSFSheet sheet = wb.createSheet();
-
- assertFalse(sheet.isRightToLeft());
- sheet.setRightToLeft(true);
- assertTrue(sheet.isRightToLeft());
- sheet.setRightToLeft(false);
- assertFalse(sheet.isRightToLeft());
- }
}
\ No newline at end of file
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellUtil;
import org.apache.poi.xssf.XSSFITestDataProvider;
import org.apache.poi.xssf.XSSFTestDataSamples;
// TODO - support shifting of page breaks
}
- @Override
- public void testShiftWithComments() { // disabled test from superclass
- // TODO - support shifting of comments.
- }
-
public void testBug54524() throws IOException {
XSSFWorkbook workbook = XSSFTestDataSamples.openSampleWorkbook("54524.xlsx");
XSSFSheet sheet = workbook.getSheetAt(0);
cell = CellUtil.getCell(sheet.getRow(3), 0);
assertEquals("X", cell.getStringCellValue());
}
-
public void testBug53798() throws IOException {
// NOTE that for HSSF (.xls) negative shifts combined with positive ones do work as expected
assertEquals("Amdocs:\ntest\n", comment.getString().getString());
}
- public void testBug55280() throws IOException {
- Workbook w = new XSSFWorkbook();
- try {
- Sheet s = w.createSheet();
- for (int row = 0; row < 5000; ++row)
- s.addMergedRegion(new CellRangeAddress(row, row, 0, 3));
-
- s.shiftRows(0, 4999, 1); // takes a long time...
- } finally {
- w.close();
- }
- }
-
public void test57171() throws Exception {
Workbook wb = XSSFTestDataSamples.openSampleWorkbook("57171_57163_57165.xlsx");
assertEquals(5, wb.getActiveSheetIndex());
package org.apache.poi.ss.usermodel;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static junit.framework.TestCase.assertNotNull;
+import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.*;
+import java.io.IOException;
import java.util.Iterator;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.PaneInformation;
import org.apache.poi.ss.ITestDataProvider;
import org.apache.poi.ss.SpreadsheetVersion;
* {@link org.apache.poi.hssf.usermodel.HSSFCell}
*/
public abstract class BaseTestSheet {
+ private static final int ROW_COUNT = 40000;
+
@Rule
public ExpectedException thrown = ExpectedException.none();
private final ITestDataProvider _testDataProvider;
protected BaseTestSheet(ITestDataProvider testDataProvider) {
- _testDataProvider = testDataProvider;
+ _testDataProvider = testDataProvider;
}
@Test
}
@Test
- public void bug55723_Rows() {
- HSSFWorkbook wb = new HSSFWorkbook();
+ public void bug55723_Rows() throws IOException {
+ Workbook wb = _testDataProvider.createWorkbook();
Sheet sheet = wb.createSheet();
CellRangeAddress range = CellRangeAddress.valueOf("A4:B55000");
AutoFilter filter = sheet.setAutoFilter(range);
assertNotNull(filter);
+
+ wb.close();
}
@Test
- public void bug55723d_RowsOver65k() {
- HSSFWorkbook wb = new HSSFWorkbook();
+ public void bug55723d_RowsOver65k() throws IOException {
+ Workbook wb = _testDataProvider.createWorkbook();
Sheet sheet = wb.createSheet();
CellRangeAddress range = CellRangeAddress.valueOf("A4:B75000");
AutoFilter filter = sheet.setAutoFilter(range);
assertNotNull(filter);
+
+ wb.close();
+ }
+
+ /**
+ * XSSFSheet autoSizeColumn() on empty RichTextString fails
+ * @throws IOException
+ */
+ @Test
+ public void bug48325() throws IOException {
+ Workbook wb = _testDataProvider.createWorkbook();
+ Sheet sheet = wb.createSheet("Test");
+ CreationHelper factory = wb.getCreationHelper();
+
+ Row row = sheet.createRow(0);
+ Cell cell = row.createCell(0);
+
+ Font font = wb.createFont();
+ RichTextString rts = factory.createRichTextString("");
+ rts.applyFont(font);
+ cell.setCellValue(rts);
+
+ sheet.autoSizeColumn(0);
+
+ assertNotNull(_testDataProvider.writeOutAndReadBack(wb));
+
+ wb.close();
+ }
+
+ @Test
+ public void getCellComment() throws IOException {
+ Workbook workbook = _testDataProvider.createWorkbook();
+ Sheet sheet = workbook.createSheet();
+ Drawing dg = sheet.createDrawingPatriarch();
+ Comment comment = dg.createCellComment(workbook.getCreationHelper().createClientAnchor());
+ Cell cell = sheet.createRow(9).createCell(2);
+ comment.setAuthor("test C10 author");
+ cell.setCellComment(comment);
+
+ assertNotNull(sheet.getCellComment(9, 2));
+ assertEquals("test C10 author", sheet.getCellComment(9, 2).getAuthor());
+
+ assertNotNull(_testDataProvider.writeOutAndReadBack(workbook));
+
+ workbook.close();
+ }
+
+
+ @Test
+ public void newMergedRegionAt() throws IOException {
+ Workbook workbook = _testDataProvider.createWorkbook();
+ Sheet sheet = workbook.createSheet();
+ CellRangeAddress region = CellRangeAddress.valueOf("B2:D4");
+ sheet.addMergedRegion(region);
+ assertEquals("B2:D4", sheet.getMergedRegion(0).formatAsString());
+ assertEquals(1, sheet.getNumMergedRegions());
+
+ assertNotNull(_testDataProvider.writeOutAndReadBack(workbook));
+
+ workbook.close();
+ }
+
+ @Test
+ public void showInPaneManyRowsBug55248() {
+ Workbook workbook = _testDataProvider.createWorkbook();
+ Sheet sheet = workbook.createSheet("Sheet 1");
+
+ sheet.showInPane(0, 0);
+
+ for(int i = ROW_COUNT/2;i < ROW_COUNT;i++) {
+ sheet.createRow(i);
+ sheet.showInPane(i, 0);
+ // this one fails: sheet.showInPane((short)i, 0);
+ }
+
+ int i = 0;
+ sheet.showInPane(i, i);
+
+ Workbook wb = _testDataProvider.writeOutAndReadBack(workbook);
+ checkRowCount(wb);
+ }
+
+ private void checkRowCount(Workbook wb) {
+ assertNotNull(wb);
+ final Sheet sh = wb.getSheet("Sheet 1");
+ assertNotNull(sh);
+ assertEquals(ROW_COUNT-1, sh.getLastRowNum());
+ }
+
+
+ @Test
+ public void testRightToLeft() throws IOException {
+ Workbook wb = _testDataProvider.createWorkbook();
+ Sheet sheet = wb.createSheet();
+
+ assertFalse(sheet.isRightToLeft());
+ sheet.setRightToLeft(true);
+ assertTrue(sheet.isRightToLeft());
+ sheet.setRightToLeft(false);
+ assertFalse(sheet.isRightToLeft());
+
+ wb.close();
}
}
package org.apache.poi.ss.usermodel;
+import java.io.IOException;
+
import junit.framework.TestCase;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.ITestDataProvider;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
assertTrue("Row number 6 should have a pagebreak", s.isRowBroken(6));
}
- public void testShiftWithComments() { // TODO - enable XSSF test
-
+ public void testShiftWithComments() {
Workbook wb = _testDataProvider.openSampleWorkbook("comments." + _testDataProvider.getStandardFileNameExtension());
Sheet sheet = wb.getSheet("Sheet1");
String comment4 = sheet.getCellComment(3,0).getString().getString();
assertEquals(comment4,"comment top row4 (index3)\n");
+ //Workbook wbBack = _testDataProvider.writeOutAndReadBack(wb);
+
// Shifting all but first line down to test comments shifting
sheet.shiftRows(1, sheet.getLastRowNum(), 1, true, true);
assertEquals(comment3,comment3_shifted);
comment4_shifted = sheet.getCellComment(4,0).getString().getString();
assertEquals(comment4,comment4_shifted);
+
+ // Shifting back up again, now two rows
+ sheet.shiftRows(2, sheet.getLastRowNum(), -2, true, true);
+
+ // TODO: it seems HSSFSheet does not correctly remove comments from rows that are overwritten
+ // by shifting rows...
+ if(!(wb instanceof HSSFWorkbook)) {
+ assertEquals(2, sheet.getLastRowNum());
+
+ // Verify comments are in the position expected
+ assertNull("Had: " + (sheet.getCellComment(0,0) == null ? "null" : sheet.getCellComment(0,0).getString()),
+ sheet.getCellComment(0,0));
+ assertNotNull(sheet.getCellComment(1,0));
+ assertNotNull(sheet.getCellComment(2,0));
+ }
+
+ comment1 = sheet.getCellComment(1,0).getString().getString();
+ assertEquals(comment1,"comment top row3 (index2)\n");
+ String comment2 = sheet.getCellComment(2,0).getString().getString();
+ assertEquals(comment2,"comment top row4 (index3)\n");
}
public final void testShiftWithNames() {
assertEquals("SUM(G29:I29)", sheet.getRow(28).getCell(9).getCellFormula());
assertEquals("SUM(G30:I30)", sheet.getRow(29).getCell(9).getCellFormula());
-
}
+
+ public void testBug55280() throws IOException {
+ Workbook w = _testDataProvider.createWorkbook();
+ try {
+ Sheet s = w.createSheet();
+ for (int row = 0; row < 5000; ++row)
+ s.addMergedRegion(new CellRangeAddress(row, row, 0, 3));
+
+ s.shiftRows(0, 4999, 1); // takes a long time...
+ } finally {
+ w.close();
+ }
+ }
+
}
\ No newline at end of file