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

(-).classpath (-1 / +3 lines)
Lines 23-29 Link Here
23
	<classpathentry kind="lib" path="lib/log4j-1.2.17.jar"/>
23
	<classpathentry kind="lib" path="lib/log4j-1.2.17.jar"/>
24
	<classpathentry kind="lib" path="ooxml-lib/xmlbeans-2.6.0.jar"/>
24
	<classpathentry kind="lib" path="ooxml-lib/xmlbeans-2.6.0.jar"/>
25
	<classpathentry kind="lib" path="lib/hamcrest-core-1.3.jar"/>
25
	<classpathentry kind="lib" path="lib/hamcrest-core-1.3.jar"/>
26
	<classpathentry kind="lib" path="lib/junit-4.12.jar"/>
26
	<classpathentry kind="lib" path="lib/junit-4.12.jar" sourcepath="/home/onealj/.m2/repository/junit/junit/4.12/junit-4.12-sources.jar"/>
27
	<classpathentry kind="lib" path="ooxml-lib/ooxml-schemas-1.1.jar" sourcepath="ooxml-lib/ooxml-schemas-1.1-sources.jar"/>
27
	<classpathentry kind="lib" path="ooxml-lib/ooxml-schemas-1.1.jar" sourcepath="ooxml-lib/ooxml-schemas-1.1-sources.jar"/>
28
	<classpathentry kind="lib" path="ooxml-lib/ooxml-security-1.0.jar" sourcepath="ooxml-lib/ooxml-security-1.0-sources.jar"/>
28
	<classpathentry kind="lib" path="ooxml-lib/ooxml-security-1.0.jar" sourcepath="ooxml-lib/ooxml-security-1.0-sources.jar"/>
29
	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
29
	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
Lines 31-35 Link Here
31
	<classpathentry kind="lib" path="compile-lib/bcpkix-jdk15on-1.51.jar"/>
31
	<classpathentry kind="lib" path="compile-lib/bcpkix-jdk15on-1.51.jar"/>
32
	<classpathentry kind="lib" path="compile-lib/bcprov-ext-jdk15on-1.51.jar"/>
32
	<classpathentry kind="lib" path="compile-lib/bcprov-ext-jdk15on-1.51.jar"/>
33
	<classpathentry kind="lib" path="compile-lib/xmlsec-2.0.1.jar"/>
33
	<classpathentry kind="lib" path="compile-lib/xmlsec-2.0.1.jar"/>
34
	<classpathentry kind="var" path="JUnit_JavaDocs"/>
35
	<classpathentry kind="var" path="JUnit_Source"/>
34
	<classpathentry kind="output" path="build/eclipse"/>
36
	<classpathentry kind="output" path="build/eclipse"/>
35
</classpath>
37
</classpath>
(-)build.xml (-2 / +11 lines)
Lines 73-78 Link Here
73
    <!-- issue warnings if source code contains unmappable characters for encoding ASCII  -->
73
    <!-- issue warnings if source code contains unmappable characters for encoding ASCII  -->
74
    <property name="java.source.encoding" value="ASCII"/>
74
    <property name="java.source.encoding" value="ASCII"/>
75
75
76
  <!--
76
    <scriptdef name="propertyreset" language="javascript"
77
    <scriptdef name="propertyreset" language="javascript"
77
        description="Allows to assign @{property} new value">
78
        description="Allows to assign @{property} new value">
78
        <attribute name="name"/>
79
        <attribute name="name"/>
Lines 79-84 Link Here
79
        <attribute name="value"/>
80
        <attribute name="value"/>
80
            project.setProperty(attributes.get("name"), attributes.get("value"));
81
            project.setProperty(attributes.get("name"), attributes.get("value"));
81
    </scriptdef>
82
    </scriptdef>
83
    -->
82
84
83
    <!--
85
    <!--
84
      JVM system properties for running tests,
86
      JVM system properties for running tests,
Lines 88-95 Link Here
88
    <property name="POI.testdata.path" value="test-data"/>
90
    <property name="POI.testdata.path" value="test-data"/>
89
    <property name="java.awt.headless" value="true"/>
91
    <property name="java.awt.headless" value="true"/>
90
    <property name="additionaljar" value=""/>
92
    <property name="additionaljar" value=""/>
91
    <propertyreset name="user.language" value="en"/>
93
<!--    <propertyreset name="user.language" value="en"/>
92
    <propertyreset name="user.country" value="US"/>
94
    <propertyreset name="user.country" value="US"/> -->
93
    <condition property="http_proxy" value="${env.http_proxy}" else="">
95
    <condition property="http_proxy" value="${env.http_proxy}" else="">
94
        <isset property="env.http_proxy"/>
96
        <isset property="env.http_proxy"/>
95
    </condition>
97
    </condition>
Lines 105-110 Link Here
105
    <property name="main.output.test.dir" location="build/test-classes"/>
107
    <property name="main.output.test.dir" location="build/test-classes"/>
106
    <property name="main.reports.test" location="build/test-results"/>
108
    <property name="main.reports.test" location="build/test-results"/>
107
    <property name="main.testokfile" location="build/main-testokfile.txt"/>
109
    <property name="main.testokfile" location="build/main-testokfile.txt"/>
110
    <property name="junit.results" value="build/test-results"/>
108
111
109
    <!-- Scratchpad: -->
112
    <!-- Scratchpad: -->
110
    <property name="scratchpad.resource1.dir" value="src/resources/scratchpad"/>
113
    <property name="scratchpad.resource1.dir" value="src/resources/scratchpad"/>
Lines 1436-1466 Link Here
1436
            <fileset dir="${main.output.dir}"/>
1439
            <fileset dir="${main.output.dir}"/>
1437
            <metainf dir="legal/"/>
1440
            <metainf dir="legal/"/>
1438
        </jar>
1441
        </jar>
1442
<!--
1439
        <jar destfile="${dist.dir}/${jar.name}-scratchpad-${version.id}-${DSTAMP}.jar"
1443
        <jar destfile="${dist.dir}/${jar.name}-scratchpad-${version.id}-${DSTAMP}.jar"
1440
             manifest="build/poi-manifest.mf">
1444
             manifest="build/poi-manifest.mf">
1441
            <fileset dir="${scratchpad.output.dir}"/>
1445
            <fileset dir="${scratchpad.output.dir}"/>
1442
            <metainf dir="legal/"/>
1446
            <metainf dir="legal/"/>
1443
        </jar>
1447
        </jar>
1448
-->
1444
        <jar destfile="${dist.dir}/${jar.name}-ooxml-${version.id}-${DSTAMP}.jar"
1449
        <jar destfile="${dist.dir}/${jar.name}-ooxml-${version.id}-${DSTAMP}.jar"
1445
             manifest="build/poi-manifest.mf">
1450
             manifest="build/poi-manifest.mf">
1446
            <fileset dir="${ooxml.output.dir}"/>
1451
            <fileset dir="${ooxml.output.dir}"/>
1447
            <metainf dir="legal/"/>
1452
            <metainf dir="legal/"/>
1448
        </jar>
1453
        </jar>
1454
<!--
1449
        <jar destfile="${dist.dir}/${jar.name}-examples-${version.id}-${DSTAMP}.jar"
1455
        <jar destfile="${dist.dir}/${jar.name}-examples-${version.id}-${DSTAMP}.jar"
1450
             manifest="build/poi-manifest.mf">
1456
             manifest="build/poi-manifest.mf">
1451
            <fileset dir="${examples.output.dir}"/>
1457
            <fileset dir="${examples.output.dir}"/>
1452
            <metainf dir="legal/"/>
1458
            <metainf dir="legal/"/>
1453
        </jar>
1459
        </jar>
1460
-->
1454
        <jar destfile="${dist.dir}/${jar.name}-ooxml-schemas-${version.id}-${DSTAMP}.jar"
1461
        <jar destfile="${dist.dir}/${jar.name}-ooxml-schemas-${version.id}-${DSTAMP}.jar"
1455
             manifest="build/poi-manifest.mf">
1462
             manifest="build/poi-manifest.mf">
1456
            <fileset dir="${ooxml.lite.output.dir}"/>
1463
            <fileset dir="${ooxml.lite.output.dir}"/>
1457
            <metainf dir="legal/"/>
1464
            <metainf dir="legal/"/>
1458
        </jar>
1465
        </jar>
1466
<!--
1459
        <jar destfile="${dist.dir}/${jar.name}-excelant-${version.id}-${DSTAMP}.jar"
1467
        <jar destfile="${dist.dir}/${jar.name}-excelant-${version.id}-${DSTAMP}.jar"
1460
             manifest="build/poi-manifest.mf">
1468
             manifest="build/poi-manifest.mf">
1461
            <fileset dir="${excelant.output.dir}"/>
1469
            <fileset dir="${excelant.output.dir}"/>
1462
            <metainf dir="legal/"/>
1470
            <metainf dir="legal/"/>
1463
        </jar>
1471
        </jar>
1472
-->
1464
    </target>
1473
    </target>
1465
1474
1466
    <target name="jar-src" depends="compile-all, compile-version, -manifest" description="Sources for Maven">
1475
    <target name="jar-src" depends="compile-all, compile-version, -manifest" description="Sources for Maven">
(-)src/java/org/apache/poi/hssf/usermodel/HSSFCell.java (+5 lines)
Lines 43-48 Link Here
43
import org.apache.poi.ss.formula.ptg.ExpPtg;
43
import org.apache.poi.ss.formula.ptg.ExpPtg;
44
import org.apache.poi.ss.formula.ptg.Ptg;
44
import org.apache.poi.ss.formula.ptg.Ptg;
45
import org.apache.poi.ss.usermodel.Cell;
45
import org.apache.poi.ss.usermodel.Cell;
46
import org.apache.poi.ss.usermodel.CellCopyPolicy;
46
import org.apache.poi.ss.usermodel.CellStyle;
47
import org.apache.poi.ss.usermodel.CellStyle;
47
import org.apache.poi.ss.usermodel.Comment;
48
import org.apache.poi.ss.usermodel.Comment;
48
import org.apache.poi.ss.usermodel.FormulaError;
49
import org.apache.poi.ss.usermodel.FormulaError;
Lines 882-887 Link Here
882
        checkFormulaCachedValueType(CELL_TYPE_ERROR, fr);
883
        checkFormulaCachedValueType(CELL_TYPE_ERROR, fr);
883
        return (byte) fr.getCachedErrorValue();
884
        return (byte) fr.getCachedErrorValue();
884
    }
885
    }
886
    
887
    public void copyCellFrom(Cell srcCell, CellCopyPolicy policy) {
888
        //TODO: not implemented
889
    }
885
890
886
    /**
891
    /**
887
     * set the style for the cell.  The style should be an HSSFCellStyle created/retreived from
892
     * set the style for the cell.  The style should be an HSSFCellStyle created/retreived from
(-)src/java/org/apache/poi/hssf/usermodel/HSSFRow.java (-1 / +17 lines)
Lines 25-32 Link Here
25
import org.apache.poi.hssf.record.RowRecord;
25
import org.apache.poi.hssf.record.RowRecord;
26
import org.apache.poi.ss.SpreadsheetVersion;
26
import org.apache.poi.ss.SpreadsheetVersion;
27
import org.apache.poi.ss.usermodel.Cell;
27
import org.apache.poi.ss.usermodel.Cell;
28
import org.apache.poi.ss.usermodel.CellCopyPolicy;
28
import org.apache.poi.ss.usermodel.CellStyle;
29
import org.apache.poi.ss.usermodel.CellStyle;
29
import org.apache.poi.ss.usermodel.Row;
30
import org.apache.poi.ss.usermodel.Row;
31
import org.apache.poi.util.Beta;
30
import org.apache.poi.util.Configurator;
32
import org.apache.poi.util.Configurator;
31
33
32
/**
34
/**
Lines 296-303 Link Here
296
        cell.updateCellNum(newColumn);
298
        cell.updateCellNum(newColumn);
297
        addCell(cell);
299
        addCell(cell);
298
    }
300
    }
299
301
    
300
    /**
302
    /**
303
     * copy the cells from srcRow to this row
304
     * If this row is not a blank row, this will merge the two rows, overwriting
305
     * the cells in this row with the cells in srcRow
306
     * srcRow may be from a different sheet in the same workbook
307
     * @param srcRow the rows to copy from
308
     * @param policy the policy to determine what gets copied
309
     */
310
    @Beta
311
    @Override
312
    public void copyRowFrom(Row srcRow, CellCopyPolicy cellCopyPolicy) {
313
        // TODO Auto-generated method stub
314
    }
315
    
316
    /**
301
     * used internally to add a cell.
317
     * used internally to add a cell.
302
     */
318
     */
303
    private void addCell(HSSFCell cell) {
319
    private void addCell(HSSFCell cell) {
(-)src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java (-1 / +46 lines)
Lines 54-59 Link Here
54
import org.apache.poi.ss.formula.ptg.Ptg;
54
import org.apache.poi.ss.formula.ptg.Ptg;
55
import org.apache.poi.ss.formula.ptg.UnionPtg;
55
import org.apache.poi.ss.formula.ptg.UnionPtg;
56
import org.apache.poi.ss.usermodel.Cell;
56
import org.apache.poi.ss.usermodel.Cell;
57
import org.apache.poi.ss.usermodel.CellCopyPolicy;
57
import org.apache.poi.ss.usermodel.CellRange;
58
import org.apache.poi.ss.usermodel.CellRange;
58
import org.apache.poi.ss.usermodel.CellStyle;
59
import org.apache.poi.ss.usermodel.CellStyle;
59
import org.apache.poi.ss.usermodel.DataValidation;
60
import org.apache.poi.ss.usermodel.DataValidation;
Lines 64-69 Link Here
64
import org.apache.poi.ss.util.CellReference;
65
import org.apache.poi.ss.util.CellReference;
65
import org.apache.poi.ss.util.SSCellRange;
66
import org.apache.poi.ss.util.SSCellRange;
66
import org.apache.poi.ss.util.SheetUtil;
67
import org.apache.poi.ss.util.SheetUtil;
68
import org.apache.poi.util.Beta;
67
import org.apache.poi.util.Configurator;
69
import org.apache.poi.util.Configurator;
68
import org.apache.poi.util.POILogFactory;
70
import org.apache.poi.util.POILogFactory;
69
import org.apache.poi.util.POILogger;
71
import org.apache.poi.util.POILogger;
Lines 1390-1395 Link Here
1390
     * @param endRow   the row to end shifting
1392
     * @param endRow   the row to end shifting
1391
     * @param n        the number of rows to shift
1393
     * @param n        the number of rows to shift
1392
     */
1394
     */
1395
    @Override
1393
    public void shiftRows(int startRow, int endRow, int n) {
1396
    public void shiftRows(int startRow, int endRow, int n) {
1394
        shiftRows(startRow, endRow, n, false, false);
1397
        shiftRows(startRow, endRow, n, false, false);
1395
    }
1398
    }
Lines 1411-1416 Link Here
1411
     * @param copyRowHeight          whether to copy the row height during the shift
1414
     * @param copyRowHeight          whether to copy the row height during the shift
1412
     * @param resetOriginalRowHeight whether to set the original row's height to the default
1415
     * @param resetOriginalRowHeight whether to set the original row's height to the default
1413
     */
1416
     */
1417
    @Override
1414
    public void shiftRows(int startRow, int endRow, int n, boolean copyRowHeight, boolean resetOriginalRowHeight) {
1418
    public void shiftRows(int startRow, int endRow, int n, boolean copyRowHeight, boolean resetOriginalRowHeight) {
1415
        shiftRows(startRow, endRow, n, copyRowHeight, resetOriginalRowHeight, true);
1419
        shiftRows(startRow, endRow, n, copyRowHeight, resetOriginalRowHeight, true);
1416
    }
1420
    }
Lines 1563-1569 Link Here
1563
        String sheetName = _workbook.getSheetName(sheetIndex);
1567
        String sheetName = _workbook.getSheetName(sheetIndex);
1564
        short externSheetIndex = _book.checkExternSheet(sheetIndex);
1568
        short externSheetIndex = _book.checkExternSheet(sheetIndex);
1565
        FormulaShifter shifter = FormulaShifter.createForRowShift(
1569
        FormulaShifter shifter = FormulaShifter.createForRowShift(
1566
                         externSheetIndex, sheetName, startRow, endRow, n);
1570
                         externSheetIndex, sheetName, startRow, endRow, n, SpreadsheetVersion.EXCEL97);
1567
        _sheet.updateFormulasAfterCellShift(shifter, externSheetIndex);
1571
        _sheet.updateFormulasAfterCellShift(shifter, externSheetIndex);
1568
1572
1569
        int nSheets = _workbook.getNumberOfSheets();
1573
        int nSheets = _workbook.getNumberOfSheets();
Lines 1577-1583 Link Here
1577
        }
1581
        }
1578
        _workbook.getWorkbook().updateNamesAfterCellShift(shifter);
1582
        _workbook.getWorkbook().updateNamesAfterCellShift(shifter);
1579
    }
1583
    }
1584
    
1580
1585
1586
    /**
1587
     * Copies rows from srcRows to this sheet, starting at destStartRow.
1588
     * srcRows may be rows from a different sheet.
1589
     * Copies features using cellCopyPolicy
1590
     *
1591
     * <p>Additionally copies merged regions that are completely defined in these
1592
     * rows (ie. merged 2 cells on a row to be shifted).</p<
1593
     * 
1594
     * @param startRow the row to start shifting
1595
     * @param endRow the row to end shifting
1596
     * @param n the number of rows to shift
1597
     */
1598
    @Beta
1599
    @Override
1600
    public void copyRows(List<? extends Row> srcRows, int destStartRow, CellCopyPolicy cellCopyPolicy) {
1601
        // TODO Auto-generated method stub
1602
        
1603
    }
1604
1605
    /**
1606
     * Copies rows between startRow and endRow n number of rows.
1607
     * If you use a negative number, it will copy rows up.
1608
     * Code ensures that rows don't wrap around.
1609
     *
1610
     * Calls copyRows(startRow, endRow, n, false, false);
1611
     *
1612
     * <p>
1613
     * Additionally copies merged regions that are completely defined in these
1614
     * rows (ie. merged 2 cells on a row to be shifted).
1615
     * @param startRow the row to start shifting
1616
     * @param endRow the row to end shifting
1617
     * @param n the number of rows to shift
1618
     */
1619
    @Beta
1620
    @Override
1621
    public void copyRows(int srcStartRow, int srcEndRow, int destStartRow, CellCopyPolicy cellCopyPolicy) {
1622
        // TODO Auto-generated method stub
1623
        
1624
    }
1625
1581
    protected void insertChartRecords(List<Record> records) {
1626
    protected void insertChartRecords(List<Record> records) {
1582
        int window2Loc = _sheet.findFirstRecordLocBySid(WindowTwoRecord.sid);
1627
        int window2Loc = _sheet.findFirstRecordLocBySid(WindowTwoRecord.sid);
1583
        _sheet.getRecords().addAll(window2Loc, records);
1628
        _sheet.getRecords().addAll(window2Loc, records);
(-)src/java/org/apache/poi/ss/formula/FormulaShifter.java (-57 / +210 lines)
Lines 17-22 Link Here
17
17
18
package org.apache.poi.ss.formula;
18
package org.apache.poi.ss.formula;
19
19
20
import org.apache.poi.ss.SpreadsheetVersion;
20
import org.apache.poi.ss.formula.ptg.Area2DPtgBase;
21
import org.apache.poi.ss.formula.ptg.Area2DPtgBase;
21
import org.apache.poi.ss.formula.ptg.Area3DPtg;
22
import org.apache.poi.ss.formula.ptg.Area3DPtg;
22
import org.apache.poi.ss.formula.ptg.Area3DPxg;
23
import org.apache.poi.ss.formula.ptg.Area3DPxg;
Lines 39-47 Link Here
39
 */
40
 */
40
public final class FormulaShifter {
41
public final class FormulaShifter {
41
42
42
    static enum ShiftMode {
43
    private static enum ShiftMode {
43
        Row,
44
        RowMove,
44
        Sheet
45
        RowCopy,
46
        SheetMove,
45
    }
47
    }
46
48
47
	/**
49
	/**
Lines 61-66 Link Here
61
63
62
    private final int _srcSheetIndex;
64
    private final int _srcSheetIndex;
63
    private final int _dstSheetIndex;
65
    private final int _dstSheetIndex;
66
    private final SpreadsheetVersion _version;
64
67
65
    private final ShiftMode _mode;
68
    private final ShiftMode _mode;
66
69
Lines 69-75 Link Here
69
     *
72
     *
70
     * For example, this will be called on {@link org.apache.poi.hssf.usermodel.HSSFSheet#shiftRows(int, int, int)} }
73
     * For example, this will be called on {@link org.apache.poi.hssf.usermodel.HSSFSheet#shiftRows(int, int, int)} }
71
     */
74
     */
72
	private FormulaShifter(int externSheetIndex, String sheetName, int firstMovedIndex, int lastMovedIndex, int amountToMove) {
75
	private FormulaShifter(int externSheetIndex, String sheetName, int firstMovedIndex, int lastMovedIndex, int amountToMove, ShiftMode mode, SpreadsheetVersion version) {
73
		if (amountToMove == 0) {
76
		if (amountToMove == 0) {
74
			throw new IllegalArgumentException("amountToMove must not be zero");
77
			throw new IllegalArgumentException("amountToMove must not be zero");
75
		}
78
		}
Lines 81-87 Link Here
81
		_firstMovedIndex = firstMovedIndex;
84
		_firstMovedIndex = firstMovedIndex;
82
		_lastMovedIndex = lastMovedIndex;
85
		_lastMovedIndex = lastMovedIndex;
83
		_amountToMove = amountToMove;
86
		_amountToMove = amountToMove;
84
        _mode = ShiftMode.Row;
87
        _mode = mode;
88
        _version = version;
85
89
86
        _srcSheetIndex = _dstSheetIndex = -1;
90
        _srcSheetIndex = _dstSheetIndex = -1;
87
	}
91
	}
Lines 94-107 Link Here
94
    private FormulaShifter(int srcSheetIndex, int dstSheetIndex) {
98
    private FormulaShifter(int srcSheetIndex, int dstSheetIndex) {
95
        _externSheetIndex = _firstMovedIndex = _lastMovedIndex = _amountToMove = -1;
99
        _externSheetIndex = _firstMovedIndex = _lastMovedIndex = _amountToMove = -1;
96
        _sheetName = null;
100
        _sheetName = null;
101
        _version = null;
97
102
98
        _srcSheetIndex = srcSheetIndex;
103
        _srcSheetIndex = srcSheetIndex;
99
        _dstSheetIndex = dstSheetIndex;
104
        _dstSheetIndex = dstSheetIndex;
100
        _mode = ShiftMode.Sheet;
105
        _mode = ShiftMode.SheetMove;
101
    }
106
    }
102
107
103
	public static FormulaShifter createForRowShift(int externSheetIndex, String sheetName, int firstMovedRowIndex, int lastMovedRowIndex, int numberOfRowsToMove) {
108
    /**
104
		return new FormulaShifter(externSheetIndex, sheetName, firstMovedRowIndex, lastMovedRowIndex, numberOfRowsToMove);
109
     * @deprecated As of 3.13 (September 2015), replaced by {@link #createForRowShift(int, String, int, int, int, SpreadsheetVersion)}
110
     *
111
     * @param externSheetIndex
112
     * @param sheetName
113
     * @param firstMovedRowIndex
114
     * @param lastMovedRowIndex
115
     * @param numberOfRowsToMove
116
     * @return rowFormulaShifter
117
     */
118
    @Deprecated
119
    public static FormulaShifter createForRowShift(int externSheetIndex, String sheetName, int firstMovedRowIndex, int lastMovedRowIndex, int numberOfRowsToMove) {
120
        return createForRowShift(externSheetIndex, sheetName, firstMovedRowIndex, lastMovedRowIndex, numberOfRowsToMove, SpreadsheetVersion.EXCEL97);
121
    }
122
    
123
    public static FormulaShifter createForRowShift(int externSheetIndex, String sheetName, int firstMovedRowIndex, int lastMovedRowIndex, int numberOfRowsToMove, SpreadsheetVersion version) {
124
        return new FormulaShifter(externSheetIndex, sheetName, firstMovedRowIndex, lastMovedRowIndex, numberOfRowsToMove, ShiftMode.RowMove, version);
125
    }
126
    
127
	public static FormulaShifter createForRowCopy(int externSheetIndex, String sheetName, int firstCopiedRowIndex, int lastCopiedRowIndex, int rowOffset, SpreadsheetVersion version) {
128
		return new FormulaShifter(externSheetIndex, sheetName, firstCopiedRowIndex, lastCopiedRowIndex, rowOffset, ShiftMode.RowCopy, version);
105
	}
129
	}
106
130
107
    public static FormulaShifter createForSheetShift(int srcSheetIndex, int dstSheetIndex) {
131
    public static FormulaShifter createForSheetShift(int srcSheetIndex, int dstSheetIndex) {
Lines 139-198 Link Here
139
163
140
	private Ptg adjustPtg(Ptg ptg, int currentExternSheetIx) {
164
	private Ptg adjustPtg(Ptg ptg, int currentExternSheetIx) {
141
		switch(_mode){
165
		switch(_mode){
142
            case Row:
166
            case RowMove:
143
                return adjustPtgDueToRowMove(ptg, currentExternSheetIx);
167
                return adjustPtgDueToRowMove(ptg, currentExternSheetIx);
144
            case Sheet:
168
            case RowCopy:
145
                return adjustPtgDueToShiftMove(ptg);
169
                //Scenarios:
170
                //* row copy on same sheet
171
                //* row copy between different sheets in the same workbook
172
                return adjustPtgDueToRowCopy(ptg, currentExternSheetIx);
173
            case SheetMove:
174
                return adjustPtgDueToSheetMove(ptg);
146
            default:
175
            default:
147
                throw new IllegalStateException("Unsupported shift mode: " + _mode);
176
                throw new IllegalStateException("Unsupported shift mode: " + _mode);
148
        }
177
        }
149
	}
178
	}
179
	
180
	
150
	/**
181
	/**
151
	 * @return <code>true</code> if this Ptg needed to be changed
182
     * @return <code>true</code> if this Ptg needed to be changed
152
	 */
183
     */
153
	private Ptg adjustPtgDueToRowMove(Ptg ptg, int currentExternSheetIx) {
184
    private Ptg adjustPtgDueToRowMove(Ptg ptg, int currentExternSheetIx) {
154
		if(ptg instanceof RefPtg) {
185
        if(ptg instanceof RefPtg) {
155
			if (currentExternSheetIx != _externSheetIndex) {
186
            if (currentExternSheetIx != _externSheetIndex) {
156
				// local refs on other sheets are unaffected
187
                // local refs on other sheets are unaffected
157
				return null;
188
                return null;
158
			}
189
            }
159
			RefPtg rptg = (RefPtg)ptg;
190
            RefPtg rptg = (RefPtg)ptg;
160
			return rowMoveRefPtg(rptg);
191
            return rowMoveRefPtg(rptg);
161
		}
192
        }
162
		if(ptg instanceof Ref3DPtg) {
193
        if(ptg instanceof Ref3DPtg) {
163
			Ref3DPtg rptg = (Ref3DPtg)ptg;
194
            Ref3DPtg rptg = (Ref3DPtg)ptg;
164
			if (_externSheetIndex != rptg.getExternSheetIndex()) {
195
            if (_externSheetIndex != rptg.getExternSheetIndex()) {
165
				// only move 3D refs that refer to the sheet with cells being moved
166
				// (currentExternSheetIx is irrelevant)
167
				return null;
168
			}
169
			return rowMoveRefPtg(rptg);
170
		}
171
		if(ptg instanceof Ref3DPxg) {
172
		    Ref3DPxg rpxg = (Ref3DPxg)ptg;
173
		    if (rpxg.getExternalWorkbookNumber() > 0 ||
174
		           ! _sheetName.equals(rpxg.getSheetName())) {
175
                // only move 3D refs that refer to the sheet with cells being moved
196
                // only move 3D refs that refer to the sheet with cells being moved
176
		        return null;
197
                // (currentExternSheetIx is irrelevant)
177
		    }
198
                return null;
199
            }
200
            return rowMoveRefPtg(rptg);
201
        }
202
        if(ptg instanceof Ref3DPxg) {
203
            Ref3DPxg rpxg = (Ref3DPxg)ptg;
204
            if (rpxg.getExternalWorkbookNumber() > 0 ||
205
                   ! _sheetName.equals(rpxg.getSheetName())) {
206
                // only move 3D refs that refer to the sheet with cells being moved
207
                return null;
208
            }
178
            return rowMoveRefPtg(rpxg);
209
            return rowMoveRefPtg(rpxg);
179
		}
210
        }
180
		if(ptg instanceof Area2DPtgBase) {
211
        if(ptg instanceof Area2DPtgBase) {
181
			if (currentExternSheetIx != _externSheetIndex) {
212
            if (currentExternSheetIx != _externSheetIndex) {
182
				// local refs on other sheets are unaffected
213
                // local refs on other sheets are unaffected
183
				return ptg;
214
                return ptg;
184
			}
215
            }
185
			return rowMoveAreaPtg((Area2DPtgBase)ptg);
216
            return rowMoveAreaPtg((Area2DPtgBase)ptg);
186
		}
217
        }
187
		if(ptg instanceof Area3DPtg) {
218
        if(ptg instanceof Area3DPtg) {
188
			Area3DPtg aptg = (Area3DPtg)ptg;
219
            Area3DPtg aptg = (Area3DPtg)ptg;
189
			if (_externSheetIndex != aptg.getExternSheetIndex()) {
220
            if (_externSheetIndex != aptg.getExternSheetIndex()) {
190
				// only move 3D refs that refer to the sheet with cells being moved
221
                // only move 3D refs that refer to the sheet with cells being moved
191
				// (currentExternSheetIx is irrelevant)
222
                // (currentExternSheetIx is irrelevant)
192
				return null;
223
                return null;
193
			}
224
            }
194
			return rowMoveAreaPtg(aptg);
225
            return rowMoveAreaPtg(aptg);
195
		}
226
        }
196
        if(ptg instanceof Area3DPxg) {
227
        if(ptg instanceof Area3DPxg) {
197
            Area3DPxg apxg = (Area3DPxg)ptg;
228
            Area3DPxg apxg = (Area3DPxg)ptg;
198
            if (apxg.getExternalWorkbookNumber() > 0 ||
229
            if (apxg.getExternalWorkbookNumber() > 0 ||
Lines 202-211 Link Here
202
            }
233
            }
203
            return rowMoveAreaPtg(apxg);
234
            return rowMoveAreaPtg(apxg);
204
        }
235
        }
205
		return null;
236
        return null;
206
	}
237
    }
238
    
239
    
240
    /**
241
     * Call this on any ptg reference contained in a row of cells that was copied
242
     * If the ptg reference is relative, the references will be shifted by the distance
243
     * that the rows were copied.
244
     * In the future similar functions could be written due to column copying or
245
     * individual cell copying. Just make sure to only call adjustPtgDueToRowCopy on
246
     * formula cells that are copied (unless row shifting, where references outside
247
     * of the shifted region need to be updated to reflect the shift, a copy is self-contained).
248
     * @return <code>true</code> if this Ptg needed to be changed
249
     */
250
    private Ptg adjustPtgDueToRowCopy(Ptg ptg, int currentExternSheetIx) {
251
        if(ptg instanceof RefPtg) {
252
            /*if (currentExternSheetIx != _externSheetIndex) {
253
                // local refs on other sheets are unaffected
254
                return null;
255
            }*/
256
            RefPtg rptg = (RefPtg)ptg;
257
            return rowCopyRefPtg(rptg);
258
        }
259
        if(ptg instanceof Ref3DPtg) {
260
            Ref3DPtg rptg = (Ref3DPtg)ptg;
261
            /*if (_externSheetIndex != rptg.getExternSheetIndex()) {
262
                // only move 3D refs that refer to the sheet with cells being moved
263
                // (currentExternSheetIx is irrelevant)
264
                return null;
265
            }*/
266
            return rowCopyRefPtg(rptg);
267
        }
268
        if(ptg instanceof Ref3DPxg) {
269
            Ref3DPxg rpxg = (Ref3DPxg)ptg;
270
            /*if (rpxg.getExternalWorkbookNumber() > 0 ||
271
                   ! _sheetName.equals(rpxg.getSheetName())) {
272
                // only move 3D refs that refer to the sheet with cells being moved
273
                return null;
274
            }*/
275
            return rowCopyRefPtg(rpxg);
276
        }
277
        if(ptg instanceof Area2DPtgBase) {
278
            /*if (currentExternSheetIx != _externSheetIndex) {
279
                // local refs on other sheets are unaffected
280
                return ptg;
281
            }*/
282
            return rowCopyAreaPtg((Area2DPtgBase)ptg);
283
        }
284
        if(ptg instanceof Area3DPtg) {
285
            Area3DPtg aptg = (Area3DPtg)ptg;
286
            /*if (_externSheetIndex != aptg.getExternSheetIndex()) {
287
                // only move 3D refs that refer to the sheet with cells being moved
288
                // (currentExternSheetIx is irrelevant)
289
                return null;
290
            }*/
291
            return rowCopyAreaPtg(aptg);
292
        }
293
        if(ptg instanceof Area3DPxg) {
294
            Area3DPxg apxg = (Area3DPxg)ptg;
295
            /*if (apxg.getExternalWorkbookNumber() > 0 ||
296
                    ! _sheetName.equals(apxg.getSheetName())) {
297
                // only move 3D refs that refer to the sheet with cells being moved
298
                return null;
299
            }*/
300
            return rowCopyAreaPtg(apxg);
301
        }
302
        return null;
303
    }
207
304
208
    private Ptg adjustPtgDueToShiftMove(Ptg ptg) {
305
    private Ptg adjustPtgDueToSheetMove(Ptg ptg) {
209
        Ptg updatedPtg = null;
306
        Ptg updatedPtg = null;
210
        if(ptg instanceof Ref3DPtg) {
307
        if(ptg instanceof Ref3DPtg) {
211
            Ref3DPtg ref = (Ref3DPtg)ptg;
308
            Ref3DPtg ref = (Ref3DPtg)ptg;
Lines 373-379 Link Here
373
		throw new IllegalStateException("Situation not covered: (" + _firstMovedIndex + ", " +
470
		throw new IllegalStateException("Situation not covered: (" + _firstMovedIndex + ", " +
374
					_lastMovedIndex + ", " + _amountToMove + ", " + aFirstRow + ", " + aLastRow + ")");
471
					_lastMovedIndex + ", " + _amountToMove + ", " + aFirstRow + ", " + aLastRow + ")");
375
	}
472
	}
473
	
474
    /**
475
     * Modifies rptg in-place and return a reference to rptg if the cell reference
476
     * would move due to a row copy operation
477
     * Returns null or {#link RefErrorPtg} if no change was made
478
     *
479
     * @param aptg
480
     * @return
481
     */
482
    private Ptg rowCopyRefPtg(RefPtgBase rptg) {
483
        final int refRow = rptg.getRow();
484
        if (rptg.isRowRelative()) {
485
        	final int destRowIndex = _firstMovedIndex + _amountToMove;
486
        	if (destRowIndex < 0 || _version.getLastRowIndex() < destRowIndex)
487
    			return createDeletedRef(rptg);
488
    		rptg.setRow(refRow + _amountToMove);
489
    		return rptg;
490
        }
491
        return null;
492
    }
493
    
494
    /**
495
     * Modifies aptg in-place and return a reference to aptg if the first or last row of
496
     * of the Area reference would move due to a row copy operation
497
     * Returns null or {#link AreaErrPtg} if no change was made
498
     *
499
     * @param aptg
500
     * @return
501
     */
502
    private Ptg rowCopyAreaPtg(AreaPtgBase aptg) {
503
    	boolean changed = false;
504
    	
505
        final int aFirstRow = aptg.getFirstRow();
506
        final int aLastRow = aptg.getLastRow();
507
    	
508
    	if (aptg.isFirstRowRelative()) {
509
    		final int destFirstRowIndex = aFirstRow + _amountToMove;
510
    		if (destFirstRowIndex < 0 || _version.getLastRowIndex() < destFirstRowIndex)
511
    			return createDeletedRef(aptg);
512
    		aptg.setFirstRow(destFirstRowIndex);
513
    		changed = true;
514
    	}
515
    	if (aptg.isLastRowRelative()) {
516
    		final int destLastRowIndex = aLastRow + _amountToMove;
517
    		if (destLastRowIndex < 0 || _version.getLastRowIndex() < destLastRowIndex)
518
    			return createDeletedRef(aptg);
519
    		aptg.setLastRow(destLastRowIndex);
520
    		changed = true;
521
    	}
522
    	if (changed) {
523
    	    aptg.sortTopLeftToBottomRight();
524
    	}
525
    	
526
    	return changed ? aptg : null;
527
    }
376
528
529
377
	private static Ptg createDeletedRef(Ptg ptg) {
530
	private static Ptg createDeletedRef(Ptg ptg) {
378
		if (ptg instanceof RefPtg) {
531
		if (ptg instanceof RefPtg) {
379
			return new RefErrorPtg();
532
			return new RefErrorPtg();
(-)src/java/org/apache/poi/ss/formula/ptg/AreaPtgBase.java (-2 / +31 lines)
Lines 44-52 Link Here
44
	/** zero based, unsigned 16 bit */
44
	/** zero based, unsigned 16 bit */
45
	private int             field_2_last_row;
45
	private int             field_2_last_row;
46
	/** zero based, unsigned 8 bit */
46
	/** zero based, unsigned 8 bit */
47
	private int             field_3_first_column;
47
	private int             field_3_first_column; //BitFields: (first row relative, first col relative, first column number)
48
	/** zero based, unsigned 8 bit */
48
	/** zero based, unsigned 8 bit */
49
	private int             field_4_last_column;
49
	private int             field_4_last_column; //BitFields: (last row relative, last col relative, last column number)
50
50
51
	private final static BitField   rowRelative = BitFieldFactory.getInstance(0x8000);
51
	private final static BitField   rowRelative = BitFieldFactory.getInstance(0x8000);
52
	private final static BitField   colRelative = BitFieldFactory.getInstance(0x4000);
52
	private final static BitField   colRelative = BitFieldFactory.getInstance(0x4000);
Lines 96-101 Link Here
96
			setLastColRelative(firstColRelative);
96
			setLastColRelative(firstColRelative);
97
		}
97
		}
98
	}
98
	}
99
	
100
	/**
101
	 * Sort the first and last row and columns in-place to the preferred (top left:bottom right) order
102
	 * Note: Sort only occurs when an instance is constructed or when this method is called.
103
	 * 
104
	 * <p>For example, <code>$E5:B$10</code> becomes <code>B5:$E$10</code></p>
105
	 */
106
	public void sortTopLeftToBottomRight() {
107
		if (getFirstRow() > getLastRow()) {
108
			//swap first row and last row numbers and relativity
109
			//Note: cannot just swap the fields because row relativity is stored in fields 3 and 4
110
			final int firstRow = getFirstRow();
111
			final boolean firstRowRel = isFirstRowRelative();
112
			setFirstRow(getLastRow());
113
			setFirstRowRelative(isLastRowRelative());
114
			setLastRow(firstRow);
115
			setLastRowRelative(firstRowRel);
116
		}
117
		if (getFirstColumn() > getLastColumn()) {
118
			//swap first column and last column numbers and relativity
119
			//Note: cannot just swap the fields because row relativity is stored in fields 3 and 4
120
			final int firstCol = getFirstColumn();
121
			final boolean firstColRel = isFirstColRelative();
122
			setFirstColumn(getLastColumn());
123
			setFirstColRelative(isLastColRelative());
124
			setLastColumn(firstCol);
125
			setLastColRelative(firstColRel);
126
		}
127
	}
99
128
100
	protected final void readCoordinates(LittleEndianInput in)  {
129
	protected final void readCoordinates(LittleEndianInput in)  {
101
		field_1_first_row = in.readUShort();
130
		field_1_first_row = in.readUShort();
(-)src/java/org/apache/poi/ss/formula/ptg/Ptg.java (+10 lines)
Lines 249-254 Link Here
249
	public String toString(){
249
	public String toString(){
250
		return this.getClass().toString();
250
		return this.getClass().toString();
251
	}
251
	}
252
	
253
	@Override
254
	public boolean equals(Object other) {
255
		return (other instanceof Ptg) && toString().equals(other.toString());
256
	}
257
	
258
	@Override
259
	public int hashCode() {
260
		return toString().hashCode();
261
	}
252
262
253
	public static final byte CLASS_REF = 0x00;
263
	public static final byte CLASS_REF = 0x00;
254
	public static final byte CLASS_VALUE = 0x20;
264
	public static final byte CLASS_VALUE = 0x20;
(-)src/java/org/apache/poi/ss/usermodel/Cell.java (+2 lines)
Lines 324-329 Link Here
324
     * @see FormulaError for error codes
324
     * @see FormulaError for error codes
325
     */
325
     */
326
    byte getErrorCellValue();
326
    byte getErrorCellValue();
327
    
328
    void copyCellFrom(Cell srcCell, CellCopyPolicy policy);
327
329
328
    /**
330
    /**
329
     * Set the style for the cell.  The style should be an CellStyle created/retreived from
331
     * Set the style for the cell.  The style should be an CellStyle created/retreived from
(-)src/java/org/apache/poi/ss/usermodel/CellCopyPolicy.java (+190 lines)
Line 0 Link Here
1
package org.apache.poi.ss.usermodel;
2
3
public class CellCopyPolicy implements Cloneable {
4
    
5
    //FIXME: this class is likely to change in the future (new fields added)
6
    //Builder pattern here used to defensively plan for future to avoid constructor nightmares
7
    //and also to make code more readable (new CellCopyPolicy(true, true, false, true, true, false, true) isn't very readable)
8
    //This has also been made immutable so that all modification happens in the builder
9
    //This class is exposed to POI users as part of the POI API, so its design is more rigid than a private class
10
    //Is the added complexity of an immutable class using builder construction warranted here?
11
    //Are there better implementations?
12
    //Would a mutable class with public fields be acceptable here (which means we could never change attribute access to call a getter/setter function)?
13
14
    public static final boolean DEFAULT_COPY_CELL_VALUE_POLICY = true;
15
    public static final boolean DEFAULT_COPY_CELL_STYLE_POLICY = true;
16
    public static final boolean DEFAULT_COPY_CELL_FORMULA_POLICY = true;
17
    public static final boolean DEFAULT_COPY_MERGED_REGIONS_POLICY = true;
18
    public static final boolean DEFAULT_COPY_ROW_HEIGHT_POLICY = true;
19
    public static final boolean DEFAULT_CONDENSE_ROWS_POLICY = false;
20
    
21
    private boolean copyCellValue = DEFAULT_COPY_CELL_VALUE_POLICY;
22
    private boolean copyCellStyle = DEFAULT_COPY_CELL_STYLE_POLICY;
23
    private boolean copyCellFormula = DEFAULT_COPY_CELL_FORMULA_POLICY;
24
    private boolean copyMergedRegions = DEFAULT_COPY_MERGED_REGIONS_POLICY;
25
    private boolean copyRowHeight = DEFAULT_COPY_ROW_HEIGHT_POLICY;
26
    private boolean condenseRows = DEFAULT_CONDENSE_ROWS_POLICY;
27
    
28
    /** 
29
     * Default CellCopyPolicy, uses default policy
30
     * For custom CellCopyPolicy, use {@link #Builder} class
31
     */
32
    public CellCopyPolicy() { }
33
    
34
    private CellCopyPolicy(Builder builder) {
35
        copyCellValue = builder.copyCellValue;
36
        copyCellStyle = builder.copyCellStyle;
37
        copyCellFormula = builder.copyCellFormula;
38
        copyMergedRegions = builder.copyMergedRegions;
39
        copyRowHeight = builder.copyRowHeight;
40
        condenseRows = builder.condenseRows;
41
    }
42
    
43
    public static class Builder {
44
        private boolean copyCellValue = DEFAULT_COPY_CELL_VALUE_POLICY;
45
        private boolean copyCellStyle = DEFAULT_COPY_CELL_STYLE_POLICY;
46
        private boolean copyCellFormula = DEFAULT_COPY_CELL_FORMULA_POLICY;
47
        private boolean copyMergedRegions = DEFAULT_COPY_MERGED_REGIONS_POLICY;
48
        private boolean copyRowHeight = DEFAULT_COPY_ROW_HEIGHT_POLICY;
49
        private boolean condenseRows = DEFAULT_CONDENSE_ROWS_POLICY;
50
        
51
        /**
52
         * Builder class for CellCopyPolicy
53
         */
54
        public Builder() {
55
        }
56
        
57
        public Builder cellValue(boolean copyCellValue) {
58
            this.copyCellValue = copyCellValue;
59
            return this;
60
        }
61
        public Builder cellStyle(boolean copyCellStyle) {
62
            this.copyCellStyle = copyCellStyle;
63
            return this;
64
        }
65
        public Builder cellFormula(boolean copyCellFormula) {
66
            this.copyCellFormula = copyCellFormula;
67
            return this;
68
        }
69
        public Builder mergedRegions(boolean copyMergedRegions) {
70
            this.copyMergedRegions = copyMergedRegions;
71
            return this;
72
        }
73
        public Builder rowHeight(boolean copyRowHeight) {
74
            this.copyRowHeight = copyRowHeight;
75
            return this;
76
        }
77
        public Builder condenseRows(boolean condenseRows) {
78
            this.condenseRows = condenseRows;
79
            return this;
80
        }
81
        public CellCopyPolicy build() {
82
            return new CellCopyPolicy(this);
83
        }
84
    }
85
    
86
    private Builder createBuilder() {
87
        final Builder builder = new Builder()
88
                .cellValue(copyCellValue)
89
                .cellStyle(copyCellStyle)
90
                .cellFormula(copyCellFormula)
91
                .mergedRegions(copyMergedRegions)
92
                .rowHeight(copyRowHeight)
93
                .condenseRows(condenseRows);
94
        return builder;
95
    }
96
    
97
    @Override
98
    public CellCopyPolicy clone() {
99
        return createBuilder().build();
100
    }
101
    
102
    /**
103
     * @return the copyCellValue
104
     */
105
    public boolean isCopyCellValue() {
106
        return copyCellValue;
107
    }
108
109
    /**
110
     * @param copyCellValue the copyCellValue to set
111
     */
112
    public void setCopyCellValue(boolean copyCellValue) {
113
        this.copyCellValue = copyCellValue;
114
    }
115
116
    /**
117
     * @return the copyCellStyle
118
     */
119
    public boolean isCopyCellStyle() {
120
        return copyCellStyle;
121
    }
122
123
    /**
124
     * @param copyCellStyle the copyCellStyle to set
125
     */
126
    public void setCopyCellStyle(boolean copyCellStyle) {
127
        this.copyCellStyle = copyCellStyle;
128
    }
129
130
    /**
131
     * @return the copyCellFormula
132
     */
133
    public boolean isCopyCellFormula() {
134
        return copyCellFormula;
135
    }
136
137
    /**
138
     * @param copyCellFormula the copyCellFormula to set
139
     */
140
    public void setCopyCellFormula(boolean copyCellFormula) {
141
        this.copyCellFormula = copyCellFormula;
142
    }
143
144
    /**
145
     * @return the copyMergedRegions
146
     */
147
    public boolean isCopyMergedRegions() {
148
        return copyMergedRegions;
149
    }
150
151
    /**
152
     * @param copyMergedRegions the copyMergedRegions to set
153
     */
154
    public void setCopyMergedRegions(boolean copyMergedRegions) {
155
        this.copyMergedRegions = copyMergedRegions;
156
    }
157
158
    /**
159
     * @return the copyRowHeight
160
     */
161
    public boolean isCopyRowHeight() {
162
        return copyRowHeight;
163
    }
164
165
    /**
166
     * @param copyRowHeight the copyRowHeight to set
167
     */
168
    public void setCopyRowHeight(boolean copyRowHeight) {
169
        this.copyRowHeight = copyRowHeight;
170
    }
171
    
172
    /**
173
     * If condenseRows is true, a discontinuities in srcRows will be removed when copied to destination
174
     * For example:
175
     * Sheet.copyRows({Row(1), Row(2), Row(5)}, 11, policy) results in rows 1, 2, and 5
176
     * being copied to rows 11, 12, and 13 if condenseRows is True, or rows 11, 11, 15 if condenseRows is false
177
     * @return the condenseRows
178
     */
179
    public boolean isCondenseRows() {
180
        return condenseRows;
181
    }
182
183
    /**
184
     * @param condenseRows the condenseRows to set
185
     */
186
    public void setCondenseRows(boolean condenseRows) {
187
        this.condenseRows = condenseRows;
188
    }
189
190
}
(-)src/java/org/apache/poi/ss/usermodel/Row.java (+13 lines)
Lines 19-24 Link Here
19
19
20
import java.util.Iterator;
20
import java.util.Iterator;
21
21
22
import org.apache.poi.util.Beta;
23
22
/**
24
/**
23
 * High level representation of a row of a spreadsheet.
25
 * High level representation of a row of a spreadsheet.
24
 */
26
 */
Lines 241-244 Link Here
241
     *  you take it out of them.
243
     *  you take it out of them.
242
     */
244
     */
243
    public int getOutlineLevel();
245
    public int getOutlineLevel();
246
    
247
    /**
248
     * copy the cells from srcRow to this row
249
     * If this row is not a blank row, this will merge the two rows, overwriting
250
     * the cells in this row with the cells in srcRow
251
     * srcRow may be from a different sheet in the same workbook
252
     * @param srcRow the rows to copy from
253
     * @param policy the policy to determine what gets copied
254
     */
255
    @Beta
256
    void copyRowFrom(Row srcRow, CellCopyPolicy cellCopyPolicy);
244
}
257
}
(-)src/java/org/apache/poi/ss/usermodel/Sheet.java (+29 lines)
Lines 22-27 Link Here
22
22
23
import org.apache.poi.hssf.util.PaneInformation;
23
import org.apache.poi.hssf.util.PaneInformation;
24
import org.apache.poi.ss.util.CellRangeAddress;
24
import org.apache.poi.ss.util.CellRangeAddress;
25
import org.apache.poi.util.Beta;
25
26
26
/**
27
/**
27
 * High level representation of a Excel worksheet.
28
 * High level representation of a Excel worksheet.
Lines 650-655 Link Here
650
     * @param resetOriginalRowHeight whether to set the original row's height to the default
651
     * @param resetOriginalRowHeight whether to set the original row's height to the default
651
     */
652
     */
652
    void shiftRows(int startRow, int endRow, int n, boolean copyRowHeight, boolean resetOriginalRowHeight);
653
    void shiftRows(int startRow, int endRow, int n, boolean copyRowHeight, boolean resetOriginalRowHeight);
654
    
655
    /**
656
     * copyRows rows from srcRows to this sheet starting at destStartRow
657
     *
658
     * Additionally copies merged regions that are completely defined in these
659
     * rows (ie. merged 2 cells on a row to be shifted).
660
     * @param srcRows the rows to copy. Formulas will be offset by the difference
661
     * in the row number of the first row in srcRows and destStartRow (even if srcRows
662
     * are from a different sheet).
663
     * @param destStartRow the row in this sheet to paste the first row of srcRows
664
     * the remainder of srcRows will be pasted below destStartRow per the cell copy policy
665
     * @param policy is the cell copy policy, which can be used to merge the source and destination
666
     * when the source is blank, copy styles only, paste as value, etc
667
     */
668
    @Beta
669
    void copyRows(List<? extends Row> srcRows, int destStartRow, CellCopyPolicy cellCopyPolicy);
670
    
671
    /**
672
     * Copies rows between srcStartRow and srcEndRow in this sheet to this sheet
673
     * starting at destStartRow using cellCopyPolicy to choose what to copy
674
     *
675
     * @param srcStartRow
676
     * @param srcEndRow
677
     * @param destStartRow
678
     * @param cellCopyPolicy
679
     */
680
    @Beta
681
    void copyRows(int srcStartRow, int srcEndRow, int destStartRow, CellCopyPolicy cellCopyPolicy);
653
682
654
    /**
683
    /**
655
     * Creates a split (freezepane). Any existing freezepane or split pane is overwritten.
684
     * Creates a split (freezepane). Any existing freezepane or split pane is overwritten.
(-)src/java/org/apache/poi/ss/util/CellRangeAddressBase.java (+32 lines)
Lines 164-167 Link Here
164
		CellReference crB = new CellReference(_lastRow, _lastCol);
164
		CellReference crB = new CellReference(_lastRow, _lastCol);
165
		return getClass().getName() + " [" + crA.formatAsString() + ":" + crB.formatAsString() +"]";
165
		return getClass().getName() + " [" + crA.formatAsString() + ":" + crB.formatAsString() +"]";
166
	}
166
	}
167
	
168
	   // In case _firstRow > _lastRow or _firstCol > _lastCol
169
    protected int getMinRow() {
170
        return Math.min(_firstRow, _lastRow);
171
    }
172
    protected int getMaxRow() {
173
        return Math.max(_firstRow, _lastRow);
174
    }
175
    protected int getMinColumn() {
176
        return Math.min(_firstCol, _lastCol);
177
    }
178
    protected int getMaxColumn() {
179
        return Math.max(_firstCol, _lastCol);
180
    }
181
    
182
    @Override
183
    public boolean equals(Object other) {
184
        if (other instanceof CellRangeAddressBase) {
185
            CellRangeAddressBase o = (CellRangeAddressBase) other;
186
            return ((getMinRow() == o.getMinRow()) &&
187
                    (getMaxRow() == o.getMaxRow()) &&
188
                    (getMinColumn() == o.getMinColumn()) &&
189
                    (getMaxColumn() == o.getMaxColumn()));
190
        }
191
        return false;
192
    }
193
    
194
    @Override
195
    public int hashCode() {
196
        final int[] values = new int[]{getMinRow(), getMaxRow(), getMinColumn(), getMaxColumn()};
197
        return values.hashCode();
198
    }
167
}
199
}
(-)src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCell.java (+5 lines)
Lines 26-31 Link Here
26
import org.apache.poi.ss.formula.FormulaParseException;
26
import org.apache.poi.ss.formula.FormulaParseException;
27
import org.apache.poi.ss.formula.eval.ErrorEval;
27
import org.apache.poi.ss.formula.eval.ErrorEval;
28
import org.apache.poi.ss.usermodel.Cell;
28
import org.apache.poi.ss.usermodel.Cell;
29
import org.apache.poi.ss.usermodel.CellCopyPolicy;
29
import org.apache.poi.ss.usermodel.CellStyle;
30
import org.apache.poi.ss.usermodel.CellStyle;
30
import org.apache.poi.ss.usermodel.Comment;
31
import org.apache.poi.ss.usermodel.Comment;
31
import org.apache.poi.ss.usermodel.DateUtil;
32
import org.apache.poi.ss.usermodel.DateUtil;
Lines 502-507 Link Here
502
                throw typeMismatch(CELL_TYPE_ERROR, cellType, false);
503
                throw typeMismatch(CELL_TYPE_ERROR, cellType, false);
503
        }
504
        }
504
    }
505
    }
506
    
507
    public void copyCellFrom(Cell srcCell, CellCopyPolicy policy) {
508
        //TODO: not implemented
509
    }
505
510
506
    /**
511
    /**
507
     * Set the style for the cell.  The style should be an CellStyle created/retreived from
512
     * Set the style for the cell.  The style should be an CellStyle created/retreived from
(-)src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFRow.java (+9 lines)
Lines 22-30 Link Here
22
22
23
import org.apache.poi.ss.SpreadsheetVersion;
23
import org.apache.poi.ss.SpreadsheetVersion;
24
import org.apache.poi.ss.usermodel.Cell;
24
import org.apache.poi.ss.usermodel.Cell;
25
import org.apache.poi.ss.usermodel.CellCopyPolicy;
25
import org.apache.poi.ss.usermodel.CellStyle;
26
import org.apache.poi.ss.usermodel.CellStyle;
26
import org.apache.poi.ss.usermodel.Row;
27
import org.apache.poi.ss.usermodel.Row;
27
import org.apache.poi.ss.usermodel.Sheet;
28
import org.apache.poi.ss.usermodel.Sheet;
29
import org.apache.poi.util.Beta;
28
30
29
/**
31
/**
30
 * Streaming version of XSSFRow implementing the "BigGridDemo" strategy.
32
 * Streaming version of XSSFRow implementing the "BigGridDemo" strategy.
Lines 488-492 Link Here
488
            throw new UnsupportedOperationException();
490
            throw new UnsupportedOperationException();
489
        }
491
        }
490
    }
492
    }
493
    
494
    @Beta
495
    @Override
496
    public void copyRowFrom(Row srcRow, CellCopyPolicy cellCopyPolicy) {
497
        // TODO Auto-generated method stub
498
        
499
    }
491
}
500
}
492
501
(-)src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java (+13 lines)
Lines 28-33 Link Here
28
import org.apache.poi.ss.SpreadsheetVersion;
28
import org.apache.poi.ss.SpreadsheetVersion;
29
import org.apache.poi.ss.usermodel.AutoFilter;
29
import org.apache.poi.ss.usermodel.AutoFilter;
30
import org.apache.poi.ss.usermodel.Cell;
30
import org.apache.poi.ss.usermodel.Cell;
31
import org.apache.poi.ss.usermodel.CellCopyPolicy;
31
import org.apache.poi.ss.usermodel.CellRange;
32
import org.apache.poi.ss.usermodel.CellRange;
32
import org.apache.poi.ss.usermodel.CellStyle;
33
import org.apache.poi.ss.usermodel.CellStyle;
33
import org.apache.poi.ss.usermodel.Comment;
34
import org.apache.poi.ss.usermodel.Comment;
Lines 883-889 Link Here
883
    {
884
    {
884
        throw new RuntimeException("NotImplemented");
885
        throw new RuntimeException("NotImplemented");
885
    }
886
    }
887
    
888
    public void copyRows(List<? extends Row> srcRows, int destStartRow,
889
            CellCopyPolicy cellCopyPolicy) {
890
        // TODO Auto-generated method stub
891
        
892
    }
886
893
894
    public void copyRows(int srcStartRow, int srcEndRow, int destStartRow,
895
            CellCopyPolicy cellCopyPolicy) {
896
        // TODO Auto-generated method stub
897
        
898
    }
899
887
    /**
900
    /**
888
     * Creates a split (freezepane). Any existing freezepane or split pane is overwritten.
901
     * Creates a split (freezepane). Any existing freezepane or split pane is overwritten.
889
     * @param colSplit      Horizonatal position of split.
902
     * @param colSplit      Horizonatal position of split.
(-)src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java (-1 / +71 lines)
Lines 23-28 Link Here
23
import java.util.Date;
23
import java.util.Date;
24
24
25
import org.apache.poi.ss.SpreadsheetVersion;
25
import org.apache.poi.ss.SpreadsheetVersion;
26
import org.apache.poi.ss.formula.FormulaParseException;
26
import org.apache.poi.ss.formula.FormulaParser;
27
import org.apache.poi.ss.formula.FormulaParser;
27
import org.apache.poi.ss.formula.FormulaRenderer;
28
import org.apache.poi.ss.formula.FormulaRenderer;
28
import org.apache.poi.ss.formula.FormulaType;
29
import org.apache.poi.ss.formula.FormulaType;
Lines 30-35 Link Here
30
import org.apache.poi.ss.formula.eval.ErrorEval;
31
import org.apache.poi.ss.formula.eval.ErrorEval;
31
import org.apache.poi.ss.formula.ptg.Ptg;
32
import org.apache.poi.ss.formula.ptg.Ptg;
32
import org.apache.poi.ss.usermodel.Cell;
33
import org.apache.poi.ss.usermodel.Cell;
34
import org.apache.poi.ss.usermodel.CellCopyPolicy;
33
import org.apache.poi.ss.usermodel.CellStyle;
35
import org.apache.poi.ss.usermodel.CellStyle;
34
import org.apache.poi.ss.usermodel.Comment;
36
import org.apache.poi.ss.usermodel.Comment;
35
import org.apache.poi.ss.usermodel.DataFormatter;
37
import org.apache.poi.ss.usermodel.DataFormatter;
Lines 53-59 Link Here
53
 * High level representation of a cell in a row of a spreadsheet.
55
 * High level representation of a cell in a row of a spreadsheet.
54
 * <p>
56
 * <p>
55
 * Cells can be numeric, formula-based or string-based (text).  The cell type
57
 * Cells can be numeric, formula-based or string-based (text).  The cell type
56
 * specifies this.  String cells cannot conatin numbers and numeric cells cannot
58
 * specifies this.  String cells cannot contain numbers and numeric cells cannot
57
 * contain strings (at least according to our model).  Client apps should do the
59
 * contain strings (at least according to our model).  Client apps should do the
58
 * conversions themselves.  Formula cells have the formula string, as well as
60
 * conversions themselves.  Formula cells have the formula string, as well as
59
 * the formula result, which can be numeric or string.
61
 * the formula result, which can be numeric or string.
Lines 115-120 Link Here
115
        _sharedStringSource = row.getSheet().getWorkbook().getSharedStringSource();
117
        _sharedStringSource = row.getSheet().getWorkbook().getSharedStringSource();
116
        _stylesSource = row.getSheet().getWorkbook().getStylesSource();
118
        _stylesSource = row.getSheet().getWorkbook().getStylesSource();
117
    }
119
    }
120
    
121
    /**
122
     *
123
     * If srcCell is null, clears the cell value and cell style per cell copy policy
124
     * @param srcCell
125
     * @param options
126
     * @throws IllegalArgumentException if copy cell style and srcCell is from a different workbook
127
     */
128
    public void copyCellFrom(Cell srcCell, CellCopyPolicy policy) {
129
        // Copy cell value (cell type is updated implicitly)
130
        if (policy.isCopyCellValue()) {
131
            if (srcCell != null) {
132
                int copyCellType = srcCell.getCellType();
133
                if (copyCellType == Cell.CELL_TYPE_FORMULA && !policy.isCopyCellFormula()) {
134
                    // Copy formula result as value
135
                    // FIXME: Cached value may be stale
136
                    copyCellType = srcCell.getCachedFormulaResultType();
137
                }
138
                switch (copyCellType) {
139
                    case Cell.CELL_TYPE_BOOLEAN:
140
                        setCellValue(srcCell.getBooleanCellValue());
141
                        break;
142
                    case Cell.CELL_TYPE_ERROR:
143
                        setCellErrorValue(srcCell.getErrorCellValue());
144
                        break;
145
                    case Cell.CELL_TYPE_FORMULA:
146
                        setCellFormula(srcCell.getCellFormula());
147
                        break;
148
                    case Cell.CELL_TYPE_NUMERIC:
149
                        if (DateUtil.isCellDateFormatted(srcCell)) {
150
                            setCellValue(srcCell.getDateCellValue());
151
                            if (!policy.isCopyCellStyle()) {
152
                               // don't both modifying just data format if other fields will be copied over as well
153
                                final CellStyle style = (CellStyle) getCellStyle().clone();
154
                                // FIXME: this adds a new style to the stylesSource without checking if the desired style already exists in stylesSource
155
                                style.setDataFormat(srcCell.getCellStyle().getDataFormat());
156
                                setCellStyle(style);
157
                            }
158
                        }
159
                        else {
160
                            setCellValue(srcCell.getNumericCellValue());
161
                        }
162
                        break;
163
                    case Cell.CELL_TYPE_STRING:
164
                        setCellValue(srcCell.getStringCellValue());
165
                        break;
166
                    case Cell.CELL_TYPE_BLANK:
167
                        setBlank();
168
                        break;
169
                    default:
170
                        throw new IllegalArgumentException("Invalid cell type " + srcCell.getCellType());
171
                }
172
            } else {
173
                setBlank();
174
            }
175
        }
176
        
177
        // Copy CellStyle
178
        if (policy.isCopyCellStyle()) {
179
            if (srcCell != null) {
180
                setCellStyle(srcCell.getCellStyle()); //same reference
181
            }
182
            else {
183
                setCellStyle(null);
184
            }
185
        }
186
    }
118
187
119
    /**
188
    /**
120
     * @return table of strings shared across this workbook
189
     * @return table of strings shared across this workbook
Lines 525-530 Link Here
525
     *
594
     *
526
     * @param style  reference contained in the workbook.
595
     * @param style  reference contained in the workbook.
527
     * If the value is null then the style information is removed causing the cell to used the default workbook style.
596
     * If the value is null then the style information is removed causing the cell to used the default workbook style.
597
     * @throws IllegalArgumentException if style belongs to a different styles source (most likely because style is from a different Workbook)
528
     */
598
     */
529
    @Override
599
    @Override
530
    public void setCellStyle(CellStyle style) {
600
    public void setCellStyle(CellStyle style) {
(-)src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java (+79 lines)
Lines 17-33 Link Here
17
17
18
package org.apache.poi.xssf.usermodel;
18
package org.apache.poi.xssf.usermodel;
19
19
20
import java.util.HashSet;
20
import java.util.Iterator;
21
import java.util.Iterator;
22
import java.util.Set;
21
import java.util.TreeMap;
23
import java.util.TreeMap;
22
24
25
import org.apache.poi.ss.formula.FormulaShifter;
23
import org.apache.poi.ss.SpreadsheetVersion;
26
import org.apache.poi.ss.SpreadsheetVersion;
24
import org.apache.poi.ss.usermodel.Cell;
27
import org.apache.poi.ss.usermodel.Cell;
28
import org.apache.poi.ss.usermodel.CellCopyPolicy;
25
import org.apache.poi.ss.usermodel.CellStyle;
29
import org.apache.poi.ss.usermodel.CellStyle;
26
import org.apache.poi.ss.usermodel.Row;
30
import org.apache.poi.ss.usermodel.Row;
31
import org.apache.poi.ss.util.CellRangeAddress;
27
import org.apache.poi.ss.util.CellReference;
32
import org.apache.poi.ss.util.CellReference;
28
import org.apache.poi.util.Internal;
33
import org.apache.poi.util.Internal;
29
import org.apache.poi.xssf.model.CalculationChain;
34
import org.apache.poi.xssf.model.CalculationChain;
30
import org.apache.poi.xssf.model.StylesTable;
35
import org.apache.poi.xssf.model.StylesTable;
36
import org.apache.poi.xssf.usermodel.helpers.XSSFRowShifter;
31
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
37
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
32
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow;
38
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow;
33
39
Lines 513-518 Link Here
513
        }
519
        }
514
        setRowNum(rownum);
520
        setRowNum(rownum);
515
    }
521
    }
522
    
523
    /**
524
     * copy the cells from srcRow to this row
525
     * If this row is not a blank row, this will merge the two rows, overwriting
526
     * the cells in this row with the cells in srcRow
527
     * srcRow may be from a different sheet in the same workbook
528
     * @param srcRow the rows to copy from
529
     * @param policy the policy to determine what gets copied
530
     */
531
    @Override
532
    public void copyRowFrom(Row srcRow, CellCopyPolicy policy) {
533
        if (srcRow == null) {
534
            // srcRow is blank. Overwrite cells with blank values, blank styles, etc per cell copy policy
535
            for (Cell destCell : this) {
536
                final XSSFCell srcCell = null;
537
                // FIXME: undo type casting
538
                ((XSSFCell)destCell).copyCellFrom(srcCell, policy);
539
            }
540
            
541
            if (policy.isCopyMergedRegions()) {
542
                // Remove MergedRegions in dest row
543
                final int destRowNum = getRowNum();
544
                int index = 0;
545
                final Set<Integer> indices = new HashSet<Integer>();
546
                for (CellRangeAddress destRegion : getSheet().getMergedRegions()) {
547
                    if (destRowNum == destRegion.getFirstRow() && destRowNum == destRegion.getLastRow()) {
548
                        indices.add(index);
549
                    }
550
                    index++;
551
                }
552
                getSheet().removeMergedRegions(indices);
553
            }
554
            
555
            if (policy.isCopyRowHeight()) {
556
                // clear row height
557
                setHeight((short)-1);
558
            }
559
                
560
        }
561
        else {
562
            for(Cell c : srcRow){
563
                final XSSFCell srcCell = (XSSFCell)c;
564
                final XSSFCell destCell = createCell(srcCell.getColumnIndex(), srcCell.getCellType());
565
                destCell.copyCellFrom(srcCell, policy);
566
            }
567
            
568
            final XSSFRowShifter rowShifter = new XSSFRowShifter(_sheet);
569
            final int sheetIndex = _sheet.getWorkbook().getSheetIndex(_sheet);
570
            final String sheetName = _sheet.getWorkbook().getSheetName(sheetIndex);
571
            final int srcRowNum = srcRow.getRowNum();
572
            final int destRowNum = getRowNum();
573
            final int rowDifference = destRowNum - srcRowNum;
574
            final FormulaShifter shifter = FormulaShifter.createForRowCopy(sheetIndex, sheetName, srcRowNum, srcRowNum, rowDifference, SpreadsheetVersion.EXCEL2007);
575
            rowShifter.updateRowFormulas(this, shifter);
576
            
577
            // Copy merged regions that are fully contained on the row
578
            // FIXME: is this something that rowShifter could be doing?
579
            if (policy.isCopyMergedRegions()) {
580
                for (CellRangeAddress srcRegion : srcRow.getSheet().getMergedRegions()) {
581
                    if (srcRowNum == srcRegion.getFirstRow() && srcRowNum == srcRegion.getLastRow()) {
582
                        CellRangeAddress destRegion = srcRegion.copy();
583
                        destRegion.setFirstRow(destRowNum);
584
                        destRegion.setLastRow(destRowNum);
585
                        getSheet().addMergedRegion(destRegion);
586
                    }
587
                }
588
            }
589
            
590
            if (policy.isCopyRowHeight()) {
591
                setHeight(srcRow.getHeight());
592
            }
593
        }
594
    }
516
595
517
    public int getOutlineLevel() {
596
    public int getOutlineLevel() {
518
        return _row.getOutlineLevel();
597
        return _row.getOutlineLevel();
(-)src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java (-1 / +174 lines)
Lines 50-55 Link Here
50
import org.apache.poi.ss.formula.FormulaShifter;
50
import org.apache.poi.ss.formula.FormulaShifter;
51
import org.apache.poi.ss.formula.SheetNameFormatter;
51
import org.apache.poi.ss.formula.SheetNameFormatter;
52
import org.apache.poi.ss.usermodel.Cell;
52
import org.apache.poi.ss.usermodel.Cell;
53
import org.apache.poi.ss.usermodel.CellCopyPolicy;
53
import org.apache.poi.ss.usermodel.CellRange;
54
import org.apache.poi.ss.usermodel.CellRange;
54
import org.apache.poi.ss.usermodel.CellStyle;
55
import org.apache.poi.ss.usermodel.CellStyle;
55
import org.apache.poi.ss.usermodel.DataValidation;
56
import org.apache.poi.ss.usermodel.DataValidation;
Lines 323-328 Link Here
323
    /**
324
    /**
324
     * Adds a merged region of cells (hence those cells form one).
325
     * Adds a merged region of cells (hence those cells form one).
325
     *
326
     *
327
     * FIXME: Does this create a corrupt file if two identical merged regions are created?
326
     * @param region (rowfrom/colfrom-rowto/colto) to merge
328
     * @param region (rowfrom/colfrom-rowto/colto) to merge
327
     * @return index of this region
329
     * @return index of this region
328
     */
330
     */
Lines 1235-1240 Link Here
1235
    public XSSFRow getRow(int rownum) {
1237
    public XSSFRow getRow(int rownum) {
1236
        return _rows.get(rownum);
1238
        return _rows.get(rownum);
1237
    }
1239
    }
1240
    
1241
    /**
1242
     * returns all rows between startRow and endRow, inclusive.
1243
     * Rows between startRow and endRow that haven't been created are not included
1244
     * in result unless createRowIfMissing is true
1245
     *
1246
     * @param startRow the first row number in this sheet to return
1247
     * @param endRow the last row number in this sheet to return
1248
     * @param createRowIfMissing
1249
     * @return
1250
     * @throws IllegalArgumentException if startRowNum and endRowNum are not in ascending order
1251
     */
1252
    private List<XSSFRow> getRows(int startRowNum, int endRowNum, boolean createRowIfMissing) {
1253
        if (startRowNum > endRowNum) {
1254
            throw new IllegalArgumentException("getRows: startRowNum must be less than or equal to endRowNum");
1255
        }
1256
        final List<XSSFRow> rows = new ArrayList<XSSFRow>();
1257
        if (createRowIfMissing) {
1258
            for (int i = startRowNum; i <= endRowNum; i++) {
1259
                XSSFRow row = getRow(i);
1260
                if (row == null) {
1261
                    row = createRow(i);
1262
                }
1263
                rows.add(row);
1264
            }
1265
        }
1266
        else {
1267
            rows.addAll(_rows.subMap(startRowNum, endRowNum+1).values());
1268
        }
1269
        return rows;
1270
    }
1238
1271
1239
    /**
1272
    /**
1240
     * Horizontal page break information used for print layout view, page layout view, drawing print breaks in normal
1273
     * Horizontal page break information used for print layout view, page layout view, drawing print breaks in normal
Lines 1703-1708 Link Here
1703
        _rows.remove(row.getRowNum());
1736
        _rows.remove(row.getRowNum());
1704
        worksheet.getSheetData().removeRow(idx);
1737
        worksheet.getSheetData().removeRow(idx);
1705
    }
1738
    }
1739
    
1740
    public void removeRow(int rowNum) {
1741
        final Row row = getRow(rowNum);
1742
        if (row != null)
1743
            removeRow(row);
1744
    }
1706
1745
1707
    /**
1746
    /**
1708
     * Removes the page break at the indicated row
1747
     * Removes the page break at the indicated row
Lines 2554-2561 Link Here
2554
        if(scale < 10 || scale > 400) throw new IllegalArgumentException("Valid scale values range from 10 to 400");
2593
        if(scale < 10 || scale > 400) throw new IllegalArgumentException("Valid scale values range from 10 to 400");
2555
        getSheetTypeSheetView().setZoomScale(scale);
2594
        getSheetTypeSheetView().setZoomScale(scale);
2556
    }
2595
    }
2596
    
2597
    
2598
    private void copyRows_remove(int startRow, int endRow, int n, Map<Integer, Short> rowHeight) {
2599
        // first remove all rows which will be overwritten
2600
        for (Iterator<Row> it = rowIterator() ; it.hasNext() ; ) {
2601
            final XSSFRow row = (XSSFRow)it.next();
2602
            final int rowNum = row.getRowNum();
2603
            if (XSSFSheet.shouldRemoveRow(startRow, endRow, n, rowNum)) {
2604
    
2605
                // check if we should remove this row as it will be overwritten by the data later
2606
                if (rowHeight != null) {
2607
                    rowHeight.put(rowNum, row.getHeight());
2608
                }
2609
                
2610
                // remove row from worksheet.getSheetData row array
2611
                final int idx = _rows.headMap(rowNum).size();
2612
                worksheet.getSheetData().removeRow(idx);
2557
2613
2614
                // remove row from _rows
2615
                it.remove();
2616
            }
2617
        }
2618
    }
2619
    
2620
    
2558
    /**
2621
    /**
2622
     * copyRows rows from srcRows to this sheet starting at destStartRow
2623
     *
2624
     * Additionally copies merged regions that are completely defined in these
2625
     * rows (ie. merged 2 cells on a row to be shifted).
2626
     * @param srcRows the rows to copy. Formulas will be offset by the difference
2627
     * in the row number of the first row in srcRows and destStartRow (even if srcRows
2628
     * are from a different sheet).
2629
     * @param destStartRow the row in this sheet to paste the first row of srcRows
2630
     * the remainder of srcRows will be pasted below destStartRow per the cell copy policy
2631
     * @param policy is the cell copy policy, which can be used to merge the source and destination
2632
     * when the source is blank, copy styles only, paste as value, etc
2633
     */
2634
    @Beta
2635
    @Override
2636
    public void copyRows(List<? extends Row> srcRows, int destStartRow, CellCopyPolicy policy) {
2637
        if (srcRows == null || srcRows.size() == 0) {
2638
            throw new IllegalArgumentException("No rows to copy");
2639
        }
2640
        final Row srcStartRow = srcRows.get(0);
2641
        final Row srcEndRow = srcRows.get(srcRows.size() - 1);
2642
        
2643
        if (srcStartRow == null) {
2644
            throw new IllegalArgumentException("copyRows: First row cannot be null");
2645
        }
2646
        
2647
        final int srcStartRowNum = srcStartRow.getRowNum();
2648
        final int srcEndRowNum = srcEndRow.getRowNum();
2649
        
2650
        // check row numbers to make sure they are continuous and increasing (monotonic)
2651
        // and srcRows does not contain null rows
2652
        for (int index=1; index < srcRows.size(); index++) {
2653
            final Row prevRow = srcRows.get(index-1);
2654
            final Row curRow = srcRows.get(index);
2655
            if (prevRow == null || curRow == null) {
2656
                throw new IllegalArgumentException("srcRows may not contain null rows. Found null row at index " +
2657
                        index + " after Row " + prevRow.getRowNum() + ".");
2658
            //} else if (curRow.getRowNum() != prevRow.getRowNum() + 1) {
2659
            //    throw new IllegalArgumentException("srcRows must contain continuously increasing row numbers. " +
2660
            //            "Got srcRows[" + (index-1) + "]=Row " + prevRow.getRowNum() + ", srcRows[" + index + "]=Row " + curRow.getRowNum() + ".");
2661
            // FIXME: assumes row objects belong to non-null sheets and sheets belong to non-null workbooks.
2662
            } else if (srcStartRow.getSheet().getWorkbook() != curRow.getSheet().getWorkbook()) {
2663
                throw new IllegalArgumentException("All rows in srcRows must belong to the same sheet in the same workbook." +
2664
                        "Expected all rows from same workbook (" + srcStartRow.getSheet().getWorkbook() + "). " +
2665
                        "Got srcRows[" + index + "] from different workbook (" + curRow.getSheet().getWorkbook() + ").");
2666
            } else if (srcStartRow.getSheet() != curRow.getSheet()) {
2667
                throw new IllegalArgumentException("All rows in srcRows must belong to the same sheet. " +
2668
                        "Expected all rows from " + srcStartRow.getSheet().getSheetName() + ". " +
2669
                        "Got srcRows[" + index + "] from " + curRow.getSheet().getSheetName());
2670
            }
2671
        }
2672
        
2673
        // FIXME: is special behavior needed if srcRows and destRows belong to the same sheets and the regions overlap?
2674
        
2675
        final CellCopyPolicy options = policy.clone();
2676
        // avoid O(N^2) performance scanning through all regions for each row
2677
        // merged regions will be copied after all the rows have been copied
2678
        options.setCopyMergedRegions(false);
2679
        
2680
        // FIXME: if srcRows contains gaps or null values, clear out those rows that will be overwritten
2681
        // how will this work with merging (copy just values, leave cell styles in place?)
2682
        
2683
        int r = destStartRow;
2684
        for (Row srcRow : srcRows) {
2685
            int destRowNum;
2686
            if (policy.isCondenseRows()) {
2687
                destRowNum = r++;
2688
            } else {
2689
                final int shift = (srcRow.getRowNum() - srcStartRowNum);
2690
                destRowNum = destStartRow + shift;
2691
            }
2692
            //removeRow(destRowNum); //this probably clears all external formula references to destRow, causing unwanted #REF! errors
2693
            final Row destRow = createRow(destRowNum);
2694
            destRow.copyRowFrom(srcRow, options);
2695
        }
2696
        
2697
        // ======================
2698
        // Only do additional copy operations here that cannot be done with Row.copyFromRow(Row, options)
2699
        // reasons: operation needs to interact with multiple rows or sheets
2700
        
2701
        // Copy merged regions that are contained within the copy region
2702
        if (policy.isCopyMergedRegions()) {
2703
            // FIXME: is this something that rowShifter could be doing?
2704
            final int shift = destStartRow - srcStartRowNum;
2705
            for (CellRangeAddress srcRegion : srcStartRow.getSheet().getMergedRegions()) {
2706
                if (srcStartRowNum <= srcRegion.getFirstRow() && srcRegion.getLastRow() <= srcEndRowNum) {
2707
                    // srcRegion is fully inside the copied rows
2708
                    final CellRangeAddress destRegion = srcRegion.copy();
2709
                    destRegion.setFirstRow(destRegion.getFirstRow() + shift);
2710
                    destRegion.setLastRow(destRegion.getLastRow() + shift);
2711
                    addMergedRegion(destRegion);
2712
                }
2713
            }
2714
        }
2715
    }
2716
    
2717
    /**
2718
     * Copies rows between srcStartRow and srcEndRow to the same sheet, starting at destStartRow
2719
     * Convenience function for {@link #copyRows(List, int, CellCopyPolicy)}
2720
     * 
2721
     * Equivalent to copyRows(getRows(srcStartRow, srcEndRow, false), destStartRow, policy)
2722
     * 
2723
     */
2724
    @Beta
2725
    @Override
2726
    public void copyRows(int srcStartRow, int srcEndRow, int destStartRow, CellCopyPolicy cellCopyPolicy) {
2727
        final List<XSSFRow> srcRows = getRows(srcStartRow, srcEndRow, false); //FIXME: should be false, no need to create rows where src is only to copy them to dest
2728
        copyRows(srcRows, destStartRow, cellCopyPolicy);
2729
    }
2730
    
2731
    /**
2559
     * Shifts rows between startRow and endRow n number of rows.
2732
     * Shifts rows between startRow and endRow n number of rows.
2560
     * If you use a negative number, it will shift rows up.
2733
     * If you use a negative number, it will shift rows up.
2561
     * Code ensures that rows don't wrap around.
2734
     * Code ensures that rows don't wrap around.
Lines 2996-3002 Link Here
2996
        return sheetPr.isSetPageSetUpPr() ? sheetPr.getPageSetUpPr() : sheetPr.addNewPageSetUpPr();
3169
        return sheetPr.isSetPageSetUpPr() ? sheetPr.getPageSetUpPr() : sheetPr.addNewPageSetUpPr();
2997
    }
3170
    }
2998
3171
2999
    private boolean shouldRemoveRow(int startRow, int endRow, int n, int rownum) {
3172
    private static boolean shouldRemoveRow(int startRow, int endRow, int n, int rownum) {
3000
        // is this row in the target-window where the moved rows will land?
3173
        // is this row in the target-window where the moved rows will land?
3001
        if (rownum >= (startRow + n) && rownum <= (endRow + n)) {
3174
        if (rownum >= (startRow + n) && rownum <= (endRow + n)) {
3002
            // only remove it if the current row is not part of the data that is copied
3175
            // only remove it if the current row is not part of the data that is copied
(-)src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java (-1 / +1 lines)
Lines 161-167 Link Here
161
        }
161
        }
162
    }
162
    }
163
163
164
    private void updateRowFormulas(XSSFRow row, FormulaShifter shifter) {
164
    public void updateRowFormulas(XSSFRow row, FormulaShifter shifter) {
165
        for (Cell c : row) {
165
        for (Cell c : row) {
166
            XSSFCell cell = (XSSFCell) c;
166
            XSSFCell cell = (XSSFCell) c;
167
167
(-)src/ooxml/testcases/org/apache/poi/xssf/streaming/TestSXSSFRow.java (-1 / +19 lines)
Lines 22-27 Link Here
22
import org.apache.poi.ss.SpreadsheetVersion;
22
import org.apache.poi.ss.SpreadsheetVersion;
23
import org.apache.poi.ss.usermodel.BaseTestRow;
23
import org.apache.poi.ss.usermodel.BaseTestRow;
24
import org.apache.poi.xssf.SXSSFITestDataProvider;
24
import org.apache.poi.xssf.SXSSFITestDataProvider;
25
import org.junit.Ignore;
25
26
26
/**
27
/**
27
 * Tests for XSSFRow
28
 * Tests for XSSFRow
Lines 45-49 Link Here
45
    public void testCellBounds() {
46
    public void testCellBounds() {
46
        baseTestCellBounds(SpreadsheetVersion.EXCEL2007.getLastColumnIndex());
47
        baseTestCellBounds(SpreadsheetVersion.EXCEL2007.getLastColumnIndex());
47
    }
48
    }
48
49
    
50
    @Ignore
51
    @Override
52
    public void testCopyRowFrom() {
53
        //ignore this test
54
    }
55
    
56
    @Ignore
57
    @Override
58
    public void testCopyRowFromExternalSheet() {
59
        //ignore this test
60
    }
61
    
62
    @Ignore
63
    @Override
64
    public void testCopyRowOverwritesExistingRow() {
65
        //ignore this test
66
    }
49
}
67
}
(-)src/ooxml/testcases/org/apache/poi/xssf/streaming/TestSXSSFSheet.java (+10 lines)
Lines 75-80 Link Here
75
        thrown.expectMessage("NotImplemented");
75
        thrown.expectMessage("NotImplemented");
76
        super.shiftMerged();
76
        super.shiftMerged();
77
    }
77
    }
78
    
79
    @Test
80
    public void testCopyOneRow() {
81
        //TODO: implement this test
82
    }
83
    
84
    @Test
85
    public void testCopyMultipleRows() {
86
        //TODO: implement this test
87
    }
78
88
79
    /**
89
    /**
80
     *  Bug 35084: cloning cells with formula
90
     *  Bug 35084: cloning cells with formula
(-)src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java (-8 / +19 lines)
Lines 33-38 Link Here
33
import org.apache.poi.hssf.HSSFTestDataSamples;
33
import org.apache.poi.hssf.HSSFTestDataSamples;
34
import org.apache.poi.poifs.crypt.CryptoFunctions;
34
import org.apache.poi.poifs.crypt.CryptoFunctions;
35
import org.apache.poi.poifs.crypt.HashAlgorithm;
35
import org.apache.poi.poifs.crypt.HashAlgorithm;
36
import org.apache.poi.ss.SpreadsheetVersion;
36
import org.apache.poi.ss.usermodel.AutoFilter;
37
import org.apache.poi.ss.usermodel.AutoFilter;
37
import org.apache.poi.ss.usermodel.BaseTestSheet;
38
import org.apache.poi.ss.usermodel.BaseTestSheet;
38
import org.apache.poi.ss.usermodel.Cell;
39
import org.apache.poi.ss.usermodel.Cell;
Lines 1279-1288 Link Here
1279
1280
1280
        assertNotNull(wb);
1281
        assertNotNull(wb);
1281
        assertNotNull(sheet);
1282
        assertNotNull(sheet);
1282
        XSSFPivotTable pivotTable = sheet.createPivotTable(new AreaReference("A1:B2"), new CellReference("H5"));
1283
        XSSFPivotTable pivotTable = sheet.createPivotTable(new AreaReference("A1:B2", SpreadsheetVersion.EXCEL2007), new CellReference("H5"));
1283
        assertNotNull(pivotTable);
1284
        assertNotNull(pivotTable);
1284
        assertTrue(wb.getPivotTables().size() > 0);
1285
        assertTrue(wb.getPivotTables().size() > 0);
1285
        XSSFPivotTable pivotTable2 = sheet.createPivotTable(new AreaReference("A1:B2"), new CellReference("L5"), sheet);
1286
        XSSFPivotTable pivotTable2 = sheet.createPivotTable(new AreaReference("A1:B2", SpreadsheetVersion.EXCEL2007), new CellReference("L5"), sheet);
1286
        assertNotNull(pivotTable2);
1287
        assertNotNull(pivotTable2);
1287
        assertTrue(wb.getPivotTables().size() > 1);
1288
        assertTrue(wb.getPivotTables().size() > 1);
1288
    }
1289
    }
Lines 1294-1305 Link Here
1294
1295
1295
        assertNotNull(wb);
1296
        assertNotNull(wb);
1296
        assertNotNull(sheet);
1297
        assertNotNull(sheet);
1297
        XSSFPivotTable pivotTable = sheet.createPivotTable(new AreaReference("A1:B2"), new CellReference("H5"));
1298
        XSSFPivotTable pivotTable = sheet.createPivotTable(new AreaReference("A1:B2", SpreadsheetVersion.EXCEL2007), new CellReference("H5"));
1298
        assertNotNull(pivotTable);
1299
        assertNotNull(pivotTable);
1299
        assertTrue(wb.getPivotTables().size() > 0);
1300
        assertTrue(wb.getPivotTables().size() > 0);
1300
        assertNotNull(wb);
1301
        assertNotNull(wb);
1301
        XSSFSheet sheet2 = wb.createSheet();
1302
        XSSFSheet sheet2 = wb.createSheet();
1302
        XSSFPivotTable pivotTable2 = sheet2.createPivotTable(new AreaReference("A1:B2"), new CellReference("H5"), sheet);
1303
        XSSFPivotTable pivotTable2 = sheet2.createPivotTable(new AreaReference("A1:B2", SpreadsheetVersion.EXCEL2007), new CellReference("H5"), sheet);
1303
        assertNotNull(pivotTable2);
1304
        assertNotNull(pivotTable2);
1304
        assertTrue(wb.getPivotTables().size() > 1);
1305
        assertTrue(wb.getPivotTables().size() > 1);
1305
    }
1306
    }
Lines 1311-1317 Link Here
1311
1312
1312
        assertNotNull(wb);
1313
        assertNotNull(wb);
1313
        assertNotNull(sheet);
1314
        assertNotNull(sheet);
1314
        XSSFPivotTable pivotTable = sheet.createPivotTable(new AreaReference("A1:B2"), new CellReference("H5"));
1315
        XSSFPivotTable pivotTable = sheet.createPivotTable(new AreaReference("A1:B2", SpreadsheetVersion.EXCEL2007), new CellReference("H5"));
1315
        assertNotNull(pivotTable);
1316
        assertNotNull(pivotTable);
1316
        assertTrue(wb.getPivotTables().size() > 0);
1317
        assertTrue(wb.getPivotTables().size() > 0);
1317
    }
1318
    }
Lines 1323-1329 Link Here
1323
        XSSFSheet sheet2 = wb.createSheet();
1324
        XSSFSheet sheet2 = wb.createSheet();
1324
1325
1325
        XSSFPivotTable pivotTable = sheet2.createPivotTable
1326
        XSSFPivotTable pivotTable = sheet2.createPivotTable
1326
                (new AreaReference("A1:B2"), new CellReference("H5"), sheet1);
1327
                (new AreaReference("A1:B2", SpreadsheetVersion.EXCEL2007), new CellReference("H5"), sheet1);
1327
        assertEquals(0, pivotTable.getRowLabelColumns().size());
1328
        assertEquals(0, pivotTable.getRowLabelColumns().size());
1328
        
1329
        
1329
        assertEquals(1, wb.getPivotTables().size());
1330
        assertEquals(1, wb.getPivotTables().size());
Lines 1338-1344 Link Here
1338
        XSSFSheet sheet2 = wb.createSheet();
1339
        XSSFSheet sheet2 = wb.createSheet();
1339
1340
1340
        XSSFPivotTable pivotTable = sheet2.createPivotTable
1341
        XSSFPivotTable pivotTable = sheet2.createPivotTable
1341
                (new AreaReference(sheet.getSheetName()+"!A$1:B$2"), new CellReference("H5"));
1342
                (new AreaReference(sheet.getSheetName()+"!A$1:B$2", SpreadsheetVersion.EXCEL2007), new CellReference("H5"));
1342
        assertEquals(0, pivotTable.getRowLabelColumns().size());
1343
        assertEquals(0, pivotTable.getRowLabelColumns().size());
1343
    }
1344
    }
1344
1345
Lines 1349-1355 Link Here
1349
        XSSFSheet sheet2 = wb.createSheet();
1350
        XSSFSheet sheet2 = wb.createSheet();
1350
1351
1351
        try {
1352
        try {
1352
            sheet2.createPivotTable(new AreaReference(sheet.getSheetName()+"!A$1:B$2"), new CellReference("H5"), sheet2);
1353
            sheet2.createPivotTable(new AreaReference(sheet.getSheetName()+"!A$1:B$2", SpreadsheetVersion.EXCEL2007), new CellReference("H5"), sheet2);
1353
        } catch(IllegalArgumentException e) {
1354
        } catch(IllegalArgumentException e) {
1354
            return;
1355
            return;
1355
        }
1356
        }
Lines 1376-1379 Link Here
1376
        XSSFSheet sheet = wb.createSheet();
1377
        XSSFSheet sheet = wb.createSheet();
1377
        assertNotNull(sheet.createComment());
1378
        assertNotNull(sheet.createComment());
1378
    }
1379
    }
1380
    
1381
    @Test
1382
    public void testCopyOneRow() throws IOException {
1383
        baseTestCopyOneRow("XSSFSheet.copyRows.xlsx");
1384
    }
1385
    
1386
    @Test
1387
    public void testCopyMultipleRows() throws IOException {
1388
        baseTestCopyMultipleRows("XSSFSheet.copyRows.xlsx");
1389
    }
1379
}
1390
}
(-)src/testcases/org/apache/poi/hssf/usermodel/TestHSSFCell.java (+3 lines)
Lines 19-26 Link Here
19
19
20
import static org.junit.Assert.assertEquals;
20
import static org.junit.Assert.assertEquals;
21
import static org.junit.Assert.assertFalse;
21
import static org.junit.Assert.assertFalse;
22
import static org.junit.Assert.assertNotEquals;
22
import static org.junit.Assert.assertNotNull;
23
import static org.junit.Assert.assertNotNull;
23
import static org.junit.Assert.assertNull;
24
import static org.junit.Assert.assertNull;
25
import static org.junit.Assert.assertSame;
24
import static org.junit.Assert.fail;
26
import static org.junit.Assert.fail;
25
27
26
import java.io.IOException;
28
import java.io.IOException;
Lines 36-41 Link Here
36
import org.apache.poi.hssf.record.StringRecord;
38
import org.apache.poi.hssf.record.StringRecord;
37
import org.apache.poi.ss.usermodel.BaseTestCell;
39
import org.apache.poi.ss.usermodel.BaseTestCell;
38
import org.apache.poi.ss.usermodel.Cell;
40
import org.apache.poi.ss.usermodel.Cell;
41
import org.apache.poi.ss.usermodel.CellCopyPolicy;
39
import org.apache.poi.ss.usermodel.FormulaError;
42
import org.apache.poi.ss.usermodel.FormulaError;
40
import org.apache.poi.ss.usermodel.RichTextString;
43
import org.apache.poi.ss.usermodel.RichTextString;
41
import org.apache.poi.ss.usermodel.Row;
44
import org.apache.poi.ss.usermodel.Row;
(-)src/testcases/org/apache/poi/hssf/usermodel/TestHSSFRow.java (+19 lines)
Lines 25-30 Link Here
25
import org.apache.poi.hssf.record.BlankRecord;
25
import org.apache.poi.hssf.record.BlankRecord;
26
import org.apache.poi.hssf.record.RowRecord;
26
import org.apache.poi.hssf.record.RowRecord;
27
import org.apache.poi.ss.usermodel.BaseTestRow;
27
import org.apache.poi.ss.usermodel.BaseTestRow;
28
import org.junit.Ignore;
28
import org.apache.poi.ss.SpreadsheetVersion;
29
import org.apache.poi.ss.SpreadsheetVersion;
29
30
30
/**
31
/**
Lines 139-142 Link Here
139
        
140
        
140
        workbook.close();
141
        workbook.close();
141
    }
142
    }
143
    
144
    @Ignore
145
    @Override
146
    public void testCopyRowFrom() {
147
        //ignore this test
148
    }
149
    
150
    @Ignore
151
    @Override
152
    public void testCopyRowFromExternalSheet() {
153
        //ignore this test
154
    }
155
    
156
    @Ignore
157
    @Override
158
    public void testCopyRowOverwritesExistingRow() {
159
        //ignore this test
160
    }
142
}
161
}
(-)src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java (+10 lines)
Lines 1134-1137 Link Here
1134
        NameRecord record = wb.getWorkbook().getSpecificBuiltinRecord(NameRecord.BUILTIN_FILTER_DB, 1);
1134
        NameRecord record = wb.getWorkbook().getSpecificBuiltinRecord(NameRecord.BUILTIN_FILTER_DB, 1);
1135
        assertNotNull(record);
1135
        assertNotNull(record);
1136
    }
1136
    }
1137
    
1138
    @Test
1139
    public void testCopyOneRow() {
1140
        //TODO: implement this test
1141
    }
1142
1143
    @Test
1144
    public void testCopyMultipleRows() {
1145
        //TODO: implement this test
1146
    }
1137
}
1147
}
(-)src/testcases/org/apache/poi/ss/formula/TestFormulaShifter.java (-2 / +87 lines)
Lines 19-24 Link Here
19
19
20
import junit.framework.TestCase;
20
import junit.framework.TestCase;
21
21
22
import org.apache.poi.ss.SpreadsheetVersion;
22
import org.apache.poi.ss.formula.ptg.AreaErrPtg;
23
import org.apache.poi.ss.formula.ptg.AreaErrPtg;
23
import org.apache.poi.ss.formula.ptg.AreaPtg;
24
import org.apache.poi.ss.formula.ptg.AreaPtg;
24
import org.apache.poi.ss.formula.ptg.Ptg;
25
import org.apache.poi.ss.formula.ptg.Ptg;
Lines 74-79 Link Here
74
75
75
		confirmAreaShift(aptg, 18, 22,  5, 10, 25); // simple expansion at bottom
76
		confirmAreaShift(aptg, 18, 22,  5, 10, 25); // simple expansion at bottom
76
	}
77
	}
78
	
79
	public void testCopyAreasSourceRowsRelRel() {
80
81
		// all these operations are on an area ref spanning rows 10 to 20
82
		final AreaPtg aptg  = createAreaPtg(10, 20, true, true);
83
84
		confirmAreaCopy(aptg,  0, 30, 20, 30, 40, true);
85
		confirmAreaCopy(aptg,  15, 25, -15, -1, -1, true); //DeletedRef
86
	}
87
	
88
	public void testCopyAreasSourceRowsRelAbs() {
89
90
		// all these operations are on an area ref spanning rows 10 to 20
91
		final AreaPtg aptg  = createAreaPtg(10, 20, true, false);
92
93
		// Only first row should move
94
		confirmAreaCopy(aptg,  0, 30, 20, 20, 30, true);
95
		confirmAreaCopy(aptg,  15, 25, -15, -1, -1, true); //DeletedRef
96
	}
97
	
98
	public void testCopyAreasSourceRowsAbsRel() {
99
		// aptg is part of a formula in a cell that was just copied to another row
100
		// aptg row references should be updated by the difference in rows that the cell was copied
101
		// No other references besides the cells that were involved in the copy need to be updated
102
		// this makes the row copy significantly different from the row shift, where all references
103
		// in the workbook need to track the row shift
104
105
		// all these operations are on an area ref spanning rows 10 to 20
106
		final AreaPtg aptg  = createAreaPtg(10, 20, false, true);
107
108
		// Only last row should move
109
		confirmAreaCopy(aptg,  0, 30, 20, 10, 40, true);
110
		confirmAreaCopy(aptg,  15, 25, -15, 5, 10, true); //sortTopLeftToBottomRight swapped firstRow and lastRow because firstRow is absolute
111
	}
112
	
113
	public void testCopyAreasSourceRowsAbsAbs() {
114
		// aptg is part of a formula in a cell that was just copied to another row
115
		// aptg row references should be updated by the difference in rows that the cell was copied
116
		// No other references besides the cells that were involved in the copy need to be updated
117
		// this makes the row copy significantly different from the row shift, where all references
118
		// in the workbook need to track the row shift
119
		
120
		// all these operations are on an area ref spanning rows 10 to 20
121
		final AreaPtg aptg  = createAreaPtg(10, 20, false, false);
122
123
		//AbsFirstRow AbsLastRow references should't change when copied to a different row
124
		confirmAreaCopy(aptg,  0, 30, 20, 10, 20, false);
125
		confirmAreaCopy(aptg,  15, 25, -15, 10, 20, false);
126
	}
127
	
77
	/**
128
	/**
78
	 * Tests what happens to an area ref when some outside rows are moved to overlap
129
	 * Tests what happens to an area ref when some outside rows are moved to overlap
79
	 * that area ref
130
	 * that area ref
Lines 97-103 Link Here
97
			int firstRowMoved, int lastRowMoved, int numberRowsMoved,
148
			int firstRowMoved, int lastRowMoved, int numberRowsMoved,
98
			int expectedAreaFirstRow, int expectedAreaLastRow) {
149
			int expectedAreaFirstRow, int expectedAreaLastRow) {
99
150
100
		FormulaShifter fs = FormulaShifter.createForRowShift(0, "", firstRowMoved, lastRowMoved, numberRowsMoved);
151
		FormulaShifter fs = FormulaShifter.createForRowShift(0, "", firstRowMoved, lastRowMoved, numberRowsMoved, SpreadsheetVersion.EXCEL2007);
101
		boolean expectedChanged = aptg.getFirstRow() != expectedAreaFirstRow || aptg.getLastRow() != expectedAreaLastRow;
152
		boolean expectedChanged = aptg.getFirstRow() != expectedAreaFirstRow || aptg.getLastRow() != expectedAreaLastRow;
102
153
103
		AreaPtg copyPtg = (AreaPtg) aptg.copy(); // clone so we can re-use aptg in calling method
154
		AreaPtg copyPtg = (AreaPtg) aptg.copy(); // clone so we can re-use aptg in calling method
Lines 113-119 Link Here
113
		assertEquals(expectedAreaLastRow, copyPtg.getLastRow());
164
		assertEquals(expectedAreaLastRow, copyPtg.getLastRow());
114
165
115
	}
166
	}
167
	
168
	
169
	private static void confirmAreaCopy(AreaPtg aptg,
170
			int firstRowCopied, int lastRowCopied, int rowOffset,
171
			int expectedFirstRow, int expectedLastRow, boolean expectedChanged) {
172
173
		/*final boolean expectedChanged = (
174
				(aptg.isFirstRowRelative() && (aptg.getFirstRow() != expectedFirstRow)) ||
175
				(aptg.isLastRowRelative()  && (aptg.getLastRow()  != expectedLastRow))
176
		); //absolute row references should not change for row copy*/
177
178
		final AreaPtg copyPtg = (AreaPtg) aptg.copy(); // clone so we can re-use aptg in calling method
179
		final Ptg[] ptgs = { copyPtg, };
180
		final FormulaShifter fs = FormulaShifter.createForRowCopy(0, null, firstRowCopied, lastRowCopied, rowOffset, SpreadsheetVersion.EXCEL2007);
181
		final boolean actualChanged = fs.adjustFormula(ptgs, 0);
182
		
183
		// DeletedAreaRef
184
		if (expectedFirstRow < 0 || expectedLastRow < 0) {
185
			assertEquals("Reference should have shifted off worksheet, producing #REF! error: " + ptgs[0],
186
					AreaErrPtg.class, ptgs[0].getClass());
187
			return;
188
		}
189
		
190
		assertEquals("Should this AreaPtg change due to row copy?", expectedChanged, actualChanged);
191
		assertEquals("AreaPtgs should be modified in-place when a row containing the AreaPtg is copied", copyPtg, ptgs[0]);  // expected to change in place (although this is not a strict requirement)
192
		assertEquals("AreaPtg first row", expectedFirstRow, copyPtg.getFirstRow());
193
		assertEquals("AreaPtg last row", expectedLastRow, copyPtg.getLastRow());
194
195
	}
196
	
116
	private static AreaPtg createAreaPtg(int initialAreaFirstRow, int initialAreaLastRow) {
197
	private static AreaPtg createAreaPtg(int initialAreaFirstRow, int initialAreaLastRow) {
117
		return new AreaPtg(initialAreaFirstRow, initialAreaLastRow, 2, 5, false, false, false, false);
198
		return createAreaPtg(initialAreaFirstRow, initialAreaLastRow, false, false);
118
	}
199
	}
200
	
201
	private static AreaPtg createAreaPtg(int initialAreaFirstRow, int initialAreaLastRow, boolean firstRowRelative, boolean lastRowRelative) {
202
		return new AreaPtg(initialAreaFirstRow, initialAreaLastRow, 2, 5, firstRowRelative, lastRowRelative, false, false);
203
	}
119
}
204
}
(-)src/testcases/org/apache/poi/ss/formula/ptg/TestAreaPtg.java (+12 lines)
Lines 33-38 Link Here
33
	AreaPtg relative;
33
	AreaPtg relative;
34
	AreaPtg absolute;
34
	AreaPtg absolute;
35
	
35
	
36
	@Override
36
	protected void setUp() {
37
	protected void setUp() {
37
		short firstRow=5;
38
		short firstRow=5;
38
		short lastRow=13;
39
		short lastRow=13;
Lines 41-46 Link Here
41
		relative = new AreaPtg(firstRow,lastRow,firstCol,lastCol,true,true,true,true);
42
		relative = new AreaPtg(firstRow,lastRow,firstCol,lastCol,true,true,true,true);
42
		absolute = new AreaPtg(firstRow,lastRow,firstCol,lastCol,false,false,false,false);
43
		absolute = new AreaPtg(firstRow,lastRow,firstCol,lastCol,false,false,false,false);
43
	}
44
	}
45
	
46
	public static void testSortTopLeftToBottomRight() {
47
	    AreaPtg ptg = new AreaPtg("A$1:$B5");
48
	    assertEquals("A$1:$B5", ptg.toFormulaString());
49
	    ptg.setFirstColumn(3);
50
	    assertEquals("Area Ptg should not implicitly re-sort itself (except during construction)",
51
	            "D$1:$B5", ptg.toFormulaString());
52
	    ptg.sortTopLeftToBottomRight();
53
	    assertEquals("Area Ptg should restore itself to top-left to lower-right order when explicitly asked",
54
	            "$B$1:D5", ptg.toFormulaString());
55
	}
44
56
45
	public void testSetColumnsAbsolute()
57
	public void testSetColumnsAbsolute()
46
	{
58
	{
(-)src/testcases/org/apache/poi/ss/usermodel/BaseTestCell.java (+66 lines)
Lines 18-27 Link Here
18
package org.apache.poi.ss.usermodel;
18
package org.apache.poi.ss.usermodel;
19
19
20
import static org.junit.Assert.assertEquals;
20
import static org.junit.Assert.assertEquals;
21
import static org.junit.Assert.assertNotEquals;
21
import static org.junit.Assert.assertFalse;
22
import static org.junit.Assert.assertFalse;
22
import static org.junit.Assert.assertNotNull;
23
import static org.junit.Assert.assertNotNull;
23
import static org.junit.Assert.assertNull;
24
import static org.junit.Assert.assertNull;
24
import static org.junit.Assert.assertTrue;
25
import static org.junit.Assert.assertTrue;
26
import static org.junit.Assert.assertSame;
25
import static org.junit.Assert.fail;
27
import static org.junit.Assert.fail;
26
28
27
import java.io.IOException;
29
import java.io.IOException;
Lines 800-803 Link Here
800
		}
802
		}
801
		wb.close();
803
		wb.close();
802
	}
804
	}
805
	
806
    
807
    private Cell srcCell, destCell; //used for testCopyCellFrom_CellCopyPolicy
808
    
809
    @Test
810
    public final void testCopyCellFrom_CellCopyPolicy_default() {
811
        if (!_testDataProvider.getClass().getName().equals("org.apache.poi.xssf.XSSFITestDataProvider")) return; //TODO: enable this for HSSFCell and SXSSFCell tests
812
        setUp_testCopyCellFrom_CellCopyPolicy();
813
        
814
        // default copy policy
815
        final CellCopyPolicy policy = new CellCopyPolicy();
816
        destCell.copyCellFrom(srcCell, policy);
817
        
818
        assertEquals(Cell.CELL_TYPE_FORMULA, destCell.getCellType());
819
        assertEquals("2+3", destCell.getCellFormula());
820
        assertEquals(srcCell.getCellStyle(), destCell.getCellStyle());
821
    }
822
    
823
    @Test
824
    public final void testCopyCellFrom_CellCopyPolicy_value() {
825
        if (!_testDataProvider.getClass().getName().equals("org.apache.poi.xssf.XSSFITestDataProvider")) return; //TODO: enable this for HSSFCell and SXSSFCell tests
826
        setUp_testCopyCellFrom_CellCopyPolicy();
827
        
828
        // Paste values only
829
        final CellCopyPolicy policy = new CellCopyPolicy.Builder().cellFormula(false).build();
830
        destCell.copyCellFrom(srcCell, policy);
831
        assertEquals(Cell.CELL_TYPE_NUMERIC, destCell.getCellType());
832
        System.out.println("ERROR: fix formula evaluation");
833
        //FIXME: the following assertion currently fails, since getNumericCellValue() returns 0 for unevaluated expressions
834
        //assertEquals(5, (int) destCell.getNumericCellValue());
835
    }
836
    
837
    @Test
838
    public final void testCopyCellFrom_CellCopyPolicy_style() {
839
        if (!_testDataProvider.getClass().getName().equals("org.apache.poi.xssf.XSSFITestDataProvider")) return; //TODO: enable this for HSSFCell and SXSSFCell tests
840
        setUp_testCopyCellFrom_CellCopyPolicy();
841
        srcCell.setCellValue((String) null);
842
        
843
        // Paste styles only
844
        final CellCopyPolicy policy = new CellCopyPolicy.Builder().cellValue(false).build();
845
        destCell.copyCellFrom(srcCell, policy);
846
        assertEquals(srcCell.getCellStyle(), destCell.getCellStyle());
847
        
848
        // Old cell value should not have been overwritten
849
        assertNotEquals(Cell.CELL_TYPE_BLANK, destCell.getCellType());
850
        assertEquals(Cell.CELL_TYPE_BOOLEAN, destCell.getCellType());
851
        assertEquals(true, destCell.getBooleanCellValue());
852
    }
853
    
854
    private final void setUp_testCopyCellFrom_CellCopyPolicy() {
855
        final Workbook wb = _testDataProvider.createWorkbook();
856
        final Row row = wb.createSheet().createRow(0);
857
        srcCell = row.createCell(0);
858
        destCell = row.createCell(1);
859
        
860
        srcCell.setCellFormula("2+3");
861
        
862
        final CellStyle style = wb.createCellStyle();
863
        style.setBorderTop(CellStyle.BORDER_THICK);
864
        style.setFillBackgroundColor((short) 5);
865
        srcCell.setCellStyle(style);
866
        
867
        destCell.setCellValue(true);
868
    }
803
}
869
}
(-)src/testcases/org/apache/poi/ss/usermodel/BaseTestRow.java (+168 lines)
Lines 18-29 Link Here
18
package org.apache.poi.ss.usermodel;
18
package org.apache.poi.ss.usermodel;
19
19
20
import java.io.IOException;
20
import java.io.IOException;
21
import java.util.Calendar;
22
import java.util.Date;
23
import java.util.GregorianCalendar;
21
import java.util.Iterator;
24
import java.util.Iterator;
22
25
23
import junit.framework.TestCase;
26
import junit.framework.TestCase;
24
27
25
import org.apache.poi.ss.ITestDataProvider;
28
import org.apache.poi.ss.ITestDataProvider;
29
import org.apache.poi.ss.util.CellRangeAddress;
30
import org.apache.poi.ss.util.CellReference;
31
import org.apache.poi.ss.util.CellUtil;
26
32
33
27
/**
34
/**
28
 * A base class for testing implementations of
35
 * A base class for testing implementations of
29
 * {@link org.apache.poi.ss.usermodel.Row}
36
 * {@link org.apache.poi.ss.usermodel.Row}
Lines 432-435 Link Here
432
       assertEquals(style, row2.getRowStyle());
439
       assertEquals(style, row2.getRowStyle());
433
       assertEquals(4, style.getDataFormat());
440
       assertEquals(4, style.getDataFormat());
434
    }
441
    }
442
    
443
    public void testCopyRowFrom() {
444
        final Workbook workbook = _testDataProvider.createWorkbook();
445
        final Sheet sheet = workbook.createSheet("test");
446
        final Row srcRow = sheet.createRow(0);
447
        srcRow.createCell(0).setCellValue("Hello");
448
        final Row destRow = sheet.createRow(1);
449
        // FIXME: temporary work-around until bug 58350 is fixed
450
        if (sheet.getNumMergedRegions() == 0) {
451
            // Goal: CTWorksheet.addNewMergeCells()
452
            sheet.addMergedRegion(new CellRangeAddress(10, 11, 0, 0));
453
        }
454
        
455
        destRow.copyRowFrom(srcRow, new CellCopyPolicy());
456
        assertNotNull(destRow.getCell(0));
457
        assertEquals("Hello", destRow.getCell(0).getStringCellValue());
458
    }
459
    
460
    public void testCopyRowFromExternalSheet() {
461
        final Workbook workbook = _testDataProvider.createWorkbook();
462
        final Sheet srcSheet = workbook.createSheet("src");
463
        final Sheet destSheet = workbook.createSheet("dest");
464
        workbook.createSheet("other");
465
        
466
        final Row srcRow = srcSheet.createRow(0);
467
        int col = 0;
468
        //Test 2D and 3D Ref Ptgs (Pxg for OOXML Workbooks)
469
        srcRow.createCell(col++).setCellFormula("B5");
470
        srcRow.createCell(col++).setCellFormula("src!B5");
471
        srcRow.createCell(col++).setCellFormula("dest!B5");
472
        srcRow.createCell(col++).setCellFormula("other!B5");
473
        
474
        //Test 2D and 3D Ref Ptgs with absolute row
475
        srcRow.createCell(col++).setCellFormula("B$5");
476
        srcRow.createCell(col++).setCellFormula("src!B$5");
477
        srcRow.createCell(col++).setCellFormula("dest!B$5");
478
        srcRow.createCell(col++).setCellFormula("other!B$5");
479
        
480
        //Test 2D and 3D Area Ptgs (Pxg for OOXML Workbooks)
481
        srcRow.createCell(col++).setCellFormula("SUM(B5:D$5)");
482
        srcRow.createCell(col++).setCellFormula("SUM(src!B5:D$5)");
483
        srcRow.createCell(col++).setCellFormula("SUM(dest!B5:D$5)");
484
        srcRow.createCell(col++).setCellFormula("SUM(other!B5:D$5)");
485
486
        // FIXME: temporary work-around until bug 58350 is fixed
487
        if (srcSheet.getNumMergedRegions() == 0) {
488
            // Goal: CTWorksheet.addNewMergeCells()
489
            srcSheet.addMergedRegion(new CellRangeAddress(10, 11, 0, 0));
490
        }
491
        
492
        //////////////////
493
494
        final Row destRow = destSheet.createRow(1);
495
        destRow.copyRowFrom(srcRow, new CellCopyPolicy());
496
        
497
        //////////////////
498
        
499
        //Test 2D and 3D Ref Ptgs (Pxg for OOXML Workbooks)
500
        col = 0;
501
        Cell cell = destRow.getCell(col++);
502
        assertNotNull(cell);
503
        assertEquals("RefPtg", "B6", cell.getCellFormula());
504
        
505
        cell = destRow.getCell(col++);
506
        assertNotNull(cell);
507
        assertEquals("Ref3DPtg", "src!B6", cell.getCellFormula());
508
        
509
        cell = destRow.getCell(col++);
510
        assertNotNull(cell);
511
        assertEquals("Ref3DPtg", "dest!B6", cell.getCellFormula());
512
        
513
        cell = destRow.getCell(col++);
514
        assertNotNull(cell);
515
        assertEquals("Ref3DPtg", "other!B6", cell.getCellFormula());
516
        
517
        /////////////////////////////////////////////
518
        
519
        //Test 2D and 3D Ref Ptgs with absolute row (Ptg row number shouldn't change)
520
        cell = destRow.getCell(col++);
521
        assertNotNull(cell);
522
        assertEquals("RefPtg", "B$5", cell.getCellFormula());
523
        
524
        cell = destRow.getCell(col++);
525
        assertNotNull(cell);
526
        assertEquals("Ref3DPtg", "src!B$5", cell.getCellFormula());
527
        
528
        cell = destRow.getCell(col++);
529
        assertNotNull(cell);
530
        assertEquals("Ref3DPtg", "dest!B$5", cell.getCellFormula());
531
        
532
        cell = destRow.getCell(col++);
533
        assertNotNull(cell);
534
        assertEquals("Ref3DPtg", "other!B$5", cell.getCellFormula());
535
        
536
        //////////////////////////////////////////
537
        
538
        //Test 2D and 3D Area Ptgs (Pxg for OOXML Workbooks)
539
        // Note: absolute row changes from last cell to first cell in order
540
        // to maintain topLeft:bottomRight order
541
        cell = destRow.getCell(col++);
542
        assertNotNull(cell);
543
        assertEquals("Area2DPtg", "SUM(B$5:D6)", cell.getCellFormula());
544
        
545
        cell = destRow.getCell(col++);
546
        assertNotNull(cell);
547
        assertEquals("Area3DPtg", "SUM(src!B$5:D6)", cell.getCellFormula());
548
        
549
        cell = destRow.getCell(col++);
550
        assertNotNull(destRow.getCell(6));
551
        assertEquals("Area3DPtg", "SUM(dest!B$5:D6)", cell.getCellFormula());
552
        
553
        cell = destRow.getCell(col++);
554
        assertNotNull(destRow.getCell(7));
555
        assertEquals("Area3DPtg", "SUM(other!B$5:D6)", cell.getCellFormula());
556
    }
557
    
558
    public void testCopyRowOverwritesExistingRow() {
559
        final Workbook workbook = _testDataProvider.createWorkbook();
560
        final Sheet sheet1 = workbook.createSheet("Sheet1");
561
        final Sheet sheet2 = workbook.createSheet("Sheet2");
562
        
563
        final Row srcRow = sheet1.createRow(0);
564
        final Row destRow = sheet1.createRow(1);
565
        final Row observerRow = sheet1.createRow(2);
566
        final Row externObserverRow = sheet2.createRow(0);
567
        
568
        srcRow.createCell(0).setCellValue("hello");
569
        srcRow.createCell(1).setCellValue("world");
570
        destRow.createCell(0).setCellValue(5.0); //A2 -> 5.0
571
        destRow.createCell(1).setCellFormula("A1"); // B2 -> A1 -> "hello"
572
        observerRow.createCell(0).setCellFormula("A2"); // A3 -> A2 -> 5.0
573
        observerRow.createCell(1).setCellFormula("B2"); // B3 -> B2 -> A1 -> "hello"
574
        externObserverRow.createCell(0).setCellFormula("Sheet1!A2"); //Sheet2!A1 -> Sheet1!A2 -> 5.0
575
        
576
        // FIXME: temporary work-around until bug 58350 is fixed
577
        if (sheet1.getNumMergedRegions() == 0) {
578
            // Goal: CTWorksheet.addNewMergeCells()
579
            sheet1.addMergedRegion(new CellRangeAddress(10, 11, 0, 0));
580
        }
581
        
582
        // overwrite existing destRow with row-copy of srcRow
583
        destRow.copyRowFrom(srcRow, new CellCopyPolicy());
584
        
585
        // copyRowFrom should update existing destRow, rather than creating a new row and reassigning the destRow pointer
586
        // to the new row (and allow the old row to be garbage collected)
587
        // this is mostly so existing references to rows that are overwritten are updated
588
        // rather than allowing users to continue updating rows that are no longer part of the sheet
589
        assertSame("existing references to srcRow are still valid", srcRow, sheet1.getRow(0));
590
        assertSame("existing references to destRow are still valid", destRow, sheet1.getRow(1));
591
        assertSame("existing references to observerRow are still valid", observerRow, sheet1.getRow(2));
592
        assertSame("existing references to externObserverRow are still valid", externObserverRow, sheet2.getRow(0));
593
        
594
        // Make sure copyRowFrom actually copied row (this is tested elsewhere)
595
        assertEquals(Cell.CELL_TYPE_STRING, destRow.getCell(0).getCellType());
596
        assertEquals("hello", destRow.getCell(0).getStringCellValue());
597
        
598
        // We don't want #REF! errors if we copy a row that contains cells that are referred to by other cells outside of copied region
599
        assertEquals("references to overwritten cells are unmodified", "A2", observerRow.getCell(0).getCellFormula());
600
        assertEquals("references to overwritten cells are unmodified", "B2", observerRow.getCell(1).getCellFormula());
601
        assertEquals("references to overwritten cells are unmodified", "Sheet1!A2", externObserverRow.getCell(0).getCellFormula());
602
    }
435
}
603
}
(-)src/testcases/org/apache/poi/ss/usermodel/BaseTestSheet.java (+395 lines)
Lines 22-27 Link Here
22
import static org.junit.Assert.*;
22
import static org.junit.Assert.*;
23
23
24
import java.io.IOException;
24
import java.io.IOException;
25
import java.util.Calendar;
26
import java.util.Date;
27
import java.util.GregorianCalendar;
25
import java.util.Iterator;
28
import java.util.Iterator;
26
29
27
import org.apache.poi.hssf.util.PaneInformation;
30
import org.apache.poi.hssf.util.PaneInformation;
Lines 28-33 Link Here
28
import org.apache.poi.ss.ITestDataProvider;
31
import org.apache.poi.ss.ITestDataProvider;
29
import org.apache.poi.ss.SpreadsheetVersion;
32
import org.apache.poi.ss.SpreadsheetVersion;
30
import org.apache.poi.ss.util.CellRangeAddress;
33
import org.apache.poi.ss.util.CellRangeAddress;
34
import org.apache.poi.ss.util.CellReference;
35
import org.apache.poi.ss.util.CellUtil;
31
import org.junit.Rule;
36
import org.junit.Rule;
32
import org.junit.Test;
37
import org.junit.Test;
33
import org.junit.rules.ExpectedException;
38
import org.junit.rules.ExpectedException;
Lines 323-329 Link Here
323
        region = sheet.getMergedRegion(0);
328
        region = sheet.getMergedRegion(0);
324
        assertEquals("Merged region not moved over to row 2", 2, region.getFirstRow());
329
        assertEquals("Merged region not moved over to row 2", 2, region.getFirstRow());
325
    }
330
    }
331
    
332
    protected void baseTestCopyOneRow(String copyRowsTestWorkbook) throws IOException {
333
        final double FLOAT_PRECISION = 1e-9;
334
        final Workbook workbook = _testDataProvider.openSampleWorkbook(copyRowsTestWorkbook);
335
        final Sheet sheet = workbook.getSheetAt(0);
336
        final CellCopyPolicy defaultCopyPolicy = new CellCopyPolicy();
337
        sheet.copyRows(1, 1, 6, defaultCopyPolicy);
326
338
339
        final Row srcRow = sheet.getRow(1);
340
        final Row destRow = sheet.getRow(6);
341
        int col = 0;
342
        Cell cell;
343
344
        cell = CellUtil.getCell(destRow, col++);
345
        assertEquals("Source row ->", cell.getStringCellValue());
346
347
        // Style
348
        cell = CellUtil.getCell(destRow, col++);
349
        assertEquals("[Style] B7 cell value", "Red", cell.getStringCellValue());
350
        assertEquals("[Style] B7 cell style", CellUtil.getCell(srcRow, 1).getCellStyle(), cell.getCellStyle());
351
352
        // Blank
353
        cell = CellUtil.getCell(destRow, col++);
354
        assertEquals("[Blank] C7 cell type", Cell.CELL_TYPE_BLANK, cell.getCellType());
355
356
        // Error
357
        cell = CellUtil.getCell(destRow, col++);
358
        assertEquals("[Error] D7 cell type", Cell.CELL_TYPE_ERROR, cell.getCellType());
359
        final FormulaError error = FormulaError.forInt(cell.getErrorCellValue());
360
        assertEquals("[Error] D7 cell value", FormulaError.NA, error); //FIXME: XSSFCell and HSSFCell expose different interfaces. getErrorCellString would be helpful here
361
362
        // Date
363
        cell = CellUtil.getCell(destRow, col++);
364
        assertEquals("[Date] E7 cell type", Cell.CELL_TYPE_NUMERIC, cell.getCellType());
365
        final Date date = new GregorianCalendar(2000, Calendar.JANUARY, 1).getTime();
366
        assertEquals("[Date] E7 cell value", date, cell.getDateCellValue());
367
368
        // Boolean
369
        cell = CellUtil.getCell(destRow, col++);
370
        assertEquals("[Boolean] F7 cell type", Cell.CELL_TYPE_BOOLEAN, cell.getCellType());
371
        assertEquals("[Boolean] F7 cell value", true, cell.getBooleanCellValue());
372
373
        // String
374
        cell = CellUtil.getCell(destRow, col++);
375
        assertEquals("[String] G7 cell type", Cell.CELL_TYPE_STRING, cell.getCellType());
376
        assertEquals("[String] G7 cell value", "Hello", cell.getStringCellValue());
377
        
378
        // Int
379
        cell = CellUtil.getCell(destRow, col++);
380
        assertEquals("[Int] H7 cell type", Cell.CELL_TYPE_NUMERIC, cell.getCellType());
381
        assertEquals("[Int] H7 cell value", 15, (int) cell.getNumericCellValue());
382
        
383
        // Float
384
        cell = CellUtil.getCell(destRow, col++);
385
        assertEquals("[Float] I7 cell type", Cell.CELL_TYPE_NUMERIC, cell.getCellType());
386
        assertEquals("[Float] I7 cell value", 12.5, cell.getNumericCellValue(), FLOAT_PRECISION);
387
        
388
        // Cell Formula
389
        cell = CellUtil.getCell(destRow, col++);
390
        assertEquals("J7", new CellReference(cell).formatAsString());
391
        assertEquals("[Cell Formula] J7 cell type", Cell.CELL_TYPE_FORMULA, cell.getCellType());
392
        assertEquals("[Cell Formula] J7 cell formula", "5+2", cell.getCellFormula());
393
        System.out.println("Cell formula evaluation currently unsupported");
394
        //assertEquals("[Cell Formula] J7 cell value", 7.0, cell.getNumericCellValue(), FLOAT_PRECISION);
395
        
396
        // Cell Formula with Reference
397
        // Formula row references should be adjusted by destRowNum-srcRowNum
398
        cell = CellUtil.getCell(destRow, col++);
399
        assertEquals("K7", new CellReference(cell).formatAsString());
400
        assertEquals("[Cell Formula with Reference] K7 cell type",
401
                Cell.CELL_TYPE_FORMULA, cell.getCellType());
402
        assertEquals("[Cell Formula with Reference] K7 cell formula",
403
                "J7+H$2", cell.getCellFormula());
404
        //assertEquals("[Cell Formula with Reference] J7 cell value",
405
        //        22.0, cell.getNumericCellValue(), FLOAT_PRECISION);
406
        
407
        // Cell Formula with Reference spanning multiple rows
408
        cell = CellUtil.getCell(destRow, col++);
409
        assertEquals("[Cell Formula with Reference spanning multiple rows] L7 cell type",
410
                Cell.CELL_TYPE_FORMULA, cell.getCellType());
411
        assertEquals("[Cell Formula with Reference spanning multiple rows] L7 cell formula",
412
                "G7&\" \"&G8", cell.getCellFormula());
413
        //assertEquals("[Cell Formula with Reference spanning multiple rows] L7 cell value",
414
        //        "World ", cell.getStringCellValue());
415
        
416
        // Cell Formula with Reference spanning multiple rows
417
        cell = CellUtil.getCell(destRow, col++);
418
        assertEquals("[Cell Formula with Area Reference] M7 cell type",
419
                Cell.CELL_TYPE_FORMULA, cell.getCellType());
420
        assertEquals("[Cell Formula with Area Reference] M7 cell formula",
421
                "SUM(H7:I8)", cell.getCellFormula());
422
        //assertEquals("[Cell Formula with Area Reference] M7 cell value",
423
        //        "75", cell.getStringCellValue());
424
        
425
        // Array Formula
426
        cell = CellUtil.getCell(destRow, col++);
427
        System.out.println("Array formulas currently unsupported");
428
        // FIXME: Array Formula set with Sheet.setArrayFormula() instead of cell.setFormula()
429
        /*
430
        assertEquals("[Array Formula] N7 cell type", Cell.CELL_TYPE_FORMULA, cell.getCellType());
431
        assertEquals("[Array Formula] N7 cell formula", "{SUM(H7:J7*{1,2,3})}", cell.getCellFormula());
432
        */
433
        // Formula should be evaluated
434
        //assertEquals("[Array Formula] N7 cell value", 61.0, cell.getNumericCellValue(), FLOAT_PRECISION);
435
        
436
        // Data Format
437
        cell = CellUtil.getCell(destRow, col++);
438
        assertEquals("[Data Format] O7 cell type;", Cell.CELL_TYPE_NUMERIC, cell.getCellType());
439
        assertEquals("[Data Format] O7 cell value", 100.20, cell.getNumericCellValue(), FLOAT_PRECISION);
440
        //FIXME: currently fails
441
        final String moneyFormat = "\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)";
442
        assertEquals("[Data Format] O7 data format", moneyFormat, cell.getCellStyle().getDataFormatString());
443
        
444
        // Merged
445
        cell = CellUtil.getCell(destRow, col);
446
        assertEquals("[Merged] P7:Q7 cell value",
447
                "Merged cells", cell.getStringCellValue());
448
        assertTrue("[Merged] P7:Q7 merged region",
449
                sheet.getMergedRegions().contains(CellRangeAddress.valueOf("P7:Q7")));
450
        
451
        // Merged across multiple rows
452
        // Microsoft Excel 2013 does not copy a merged region unless all rows of
453
        // the source merged region are selected
454
        // POI's behavior should match this behavior
455
        col += 2;
456
        cell = CellUtil.getCell(destRow, col);
457
        // Note: this behavior deviates from Microsoft Excel,
458
        // which will not overwrite a cell in destination row if merged region extends beyond the copied row.
459
        // The Excel way would require:
460
        //assertEquals("[Merged across multiple rows] R7:S8 merged region", "Should NOT be overwritten", cell.getStringCellValue());
461
        //assertFalse("[Merged across multiple rows] R7:S8 merged region", 
462
        //        sheet.getMergedRegions().contains(CellRangeAddress.valueOf("R7:S8")));
463
        // As currently implemented, cell value is copied but merged region is not copied
464
        assertEquals("[Merged across multiple rows] R7:S8 cell value",
465
                "Merged cells across multiple rows", cell.getStringCellValue());
466
        assertFalse("[Merged across multiple rows] R7:S7 merged region (one row)", 
467
                sheet.getMergedRegions().contains(CellRangeAddress.valueOf("R7:S7"))); //shouldn't do 1-row merge
468
        assertFalse("[Merged across multiple rows] R7:S8 merged region", 
469
                sheet.getMergedRegions().contains(CellRangeAddress.valueOf("R7:S8"))); //shouldn't do 2-row merge
470
        
471
        // Make sure other rows are blank (off-by-one errors)
472
        assertNull(sheet.getRow(5));
473
        assertNull(sheet.getRow(7));
474
    }
475
    
476
    public void baseTestCopyMultipleRows(String copyRowsTestWorkbook) throws IOException {
477
        final double FLOAT_PRECISION = 1e-9;
478
        final Workbook workbook = _testDataProvider.openSampleWorkbook(copyRowsTestWorkbook);
479
        final Sheet sheet = workbook.getSheetAt(0);
480
        final CellCopyPolicy defaultCopyPolicy = new CellCopyPolicy();
481
        sheet.copyRows(0, 3, 8, defaultCopyPolicy);
482
483
        final Row srcHeaderRow = sheet.getRow(0);
484
        final Row srcRow1 = sheet.getRow(1);
485
        final Row srcRow2 = sheet.getRow(2);
486
        final Row srcRow3 = sheet.getRow(3);
487
        final Row destHeaderRow = sheet.getRow(8);
488
        final Row destRow1 = sheet.getRow(9);
489
        final Row destRow2 = sheet.getRow(10);
490
        final Row destRow3 = sheet.getRow(11);
491
        int col = 0;
492
        Cell cell;
493
        
494
        // Header row should be copied
495
        assertNotNull(destHeaderRow);
496
        
497
        // Data rows
498
        cell = CellUtil.getCell(destRow1, col);
499
        assertEquals("Source row ->", cell.getStringCellValue());
500
        
501
        // Style
502
        col++;
503
        cell = CellUtil.getCell(destRow1, col);
504
        assertEquals("[Style] B10 cell value", "Red", cell.getStringCellValue());
505
        assertEquals("[Style] B10 cell style", CellUtil.getCell(srcRow1, 1).getCellStyle(), cell.getCellStyle());
506
        
507
        cell = CellUtil.getCell(destRow2, col);
508
        assertEquals("[Style] B11 cell value", "Blue", cell.getStringCellValue());
509
        assertEquals("[Style] B11 cell style", CellUtil.getCell(srcRow2, 1).getCellStyle(), cell.getCellStyle());
510
        
511
        // Blank
512
        col++;
513
        cell = CellUtil.getCell(destRow1, col);
514
        assertEquals("[Blank] C10 cell type", Cell.CELL_TYPE_BLANK, cell.getCellType());
515
        
516
        cell = CellUtil.getCell(destRow2, col);
517
        assertEquals("[Blank] C11 cell type", Cell.CELL_TYPE_BLANK, cell.getCellType());
518
        
519
        // Error
520
        col++;
521
        cell = CellUtil.getCell(destRow1, col);
522
        assertEquals("[Error] D10 cell type", Cell.CELL_TYPE_ERROR, cell.getCellType());
523
        FormulaError error = FormulaError.forInt(cell.getErrorCellValue());
524
        assertEquals("[Error] D10 cell value", FormulaError.NA, error); //FIXME: XSSFCell and HSSFCell expose different interfaces. getErrorCellString would be helpful here
525
        
526
        cell = CellUtil.getCell(destRow2, col);
527
        assertEquals("[Error] D11 cell type", Cell.CELL_TYPE_ERROR, cell.getCellType());
528
        error = FormulaError.forInt(cell.getErrorCellValue());
529
        assertEquals("[Error] D11 cell value", FormulaError.NAME, error); //FIXME: XSSFCell and HSSFCell expose different interfaces. getErrorCellString would be helpful here
530
        
531
        // Date
532
        col++;
533
        cell = CellUtil.getCell(destRow1, col);
534
        assertEquals("[Date] E10 cell type", Cell.CELL_TYPE_NUMERIC, cell.getCellType());
535
        Date date = new GregorianCalendar(2000, Calendar.JANUARY, 1).getTime();
536
        assertEquals("[Date] E10 cell value", date, cell.getDateCellValue());
537
        
538
        cell = CellUtil.getCell(destRow2, col);
539
        assertEquals("[Date] E11 cell type", Cell.CELL_TYPE_NUMERIC, cell.getCellType());
540
        date = new GregorianCalendar(2000, Calendar.JANUARY, 2).getTime();
541
        assertEquals("[Date] E11 cell value", date, cell.getDateCellValue());
542
        
543
        // Boolean
544
        col++;
545
        cell = CellUtil.getCell(destRow1, col);
546
        assertEquals("[Boolean] F10 cell type", Cell.CELL_TYPE_BOOLEAN, cell.getCellType());
547
        assertEquals("[Boolean] F10 cell value", true, cell.getBooleanCellValue());
548
        
549
        cell = CellUtil.getCell(destRow2, col);
550
        assertEquals("[Boolean] F11 cell type", Cell.CELL_TYPE_BOOLEAN, cell.getCellType());
551
        assertEquals("[Boolean] F11 cell value", false, cell.getBooleanCellValue());
552
        
553
        // String
554
        col++;
555
        cell = CellUtil.getCell(destRow1, col);
556
        assertEquals("[String] G10 cell type", Cell.CELL_TYPE_STRING, cell.getCellType());
557
        assertEquals("[String] G10 cell value", "Hello", cell.getStringCellValue());
558
        
559
        cell = CellUtil.getCell(destRow2, col);
560
        assertEquals("[String] G11 cell type", Cell.CELL_TYPE_STRING, cell.getCellType());
561
        assertEquals("[String] G11 cell value", "World", cell.getStringCellValue());
562
        
563
        // Int
564
        col++;
565
        cell = CellUtil.getCell(destRow1, col);
566
        assertEquals("[Int] H10 cell type", Cell.CELL_TYPE_NUMERIC, cell.getCellType());
567
        assertEquals("[Int] H10 cell value", 15, (int) cell.getNumericCellValue());
568
        
569
        cell = CellUtil.getCell(destRow2, col);
570
        assertEquals("[Int] H11 cell type", Cell.CELL_TYPE_NUMERIC, cell.getCellType());
571
        assertEquals("[Int] H11 cell value", 42, (int) cell.getNumericCellValue());
572
        
573
        // Float
574
        col++;
575
        cell = CellUtil.getCell(destRow1, col);
576
        assertEquals("[Float] I10 cell type", Cell.CELL_TYPE_NUMERIC, cell.getCellType());
577
        assertEquals("[Float] I10 cell value", 12.5, cell.getNumericCellValue(), FLOAT_PRECISION);
578
        
579
        cell = CellUtil.getCell(destRow2, col);
580
        assertEquals("[Float] I11 cell type", Cell.CELL_TYPE_NUMERIC, cell.getCellType());
581
        assertEquals("[Float] I11 cell value", 5.5, cell.getNumericCellValue(), FLOAT_PRECISION);
582
        
583
        // Cell Formula
584
        col++;
585
        cell = CellUtil.getCell(destRow1, col);
586
        assertEquals("[Cell Formula] J10 cell type", Cell.CELL_TYPE_FORMULA, cell.getCellType());
587
        assertEquals("[Cell Formula] J10 cell formula", "5+2", cell.getCellFormula());
588
        // FIXME: formula evaluation
589
        System.out.println("Cell formula evaluation currently unsupported");
590
        //assertEquals(7.0, cell.getNumericCellValue(), FLOAT_PRECISION);
591
        
592
        cell = CellUtil.getCell(destRow2, col);
593
        assertEquals("[Cell Formula] J11 cell type", Cell.CELL_TYPE_FORMULA, cell.getCellType());
594
        assertEquals("[Cell Formula] J11 cell formula", "6+18", cell.getCellFormula());
595
        // FIXME: formula evaluation
596
        //assertEquals("[Cell Formula] J11 cell formula result", 24.0, cell.getNumericCellValue(), FLOAT_PRECISION);
597
        
598
        // Cell Formula with Reference
599
        col++;
600
        // Formula row references should be adjusted by destRowNum-srcRowNum
601
        cell = CellUtil.getCell(destRow1, col);
602
        assertEquals("[Cell Formula with Reference] K10 cell type",
603
                Cell.CELL_TYPE_FORMULA, cell.getCellType());
604
        assertEquals("[Cell Formula with Reference] K10 cell formula",
605
                "J10+H$2", cell.getCellFormula());
606
        // FIXME: formula evaluation
607
        //assertEquals("[Cell Formula with Reference] K10 cell formula result",
608
        //        22.0, cell.getNumericCellValue(), FLOAT_PRECISION);
609
        
610
        cell = CellUtil.getCell(destRow2, col);
611
        assertEquals("[Cell Formula with Reference] K11 cell type", Cell.CELL_TYPE_FORMULA, cell.getCellType());
612
        assertEquals("[Cell Formula with Reference] K11 cell formula", "J11+H$2", cell.getCellFormula());
613
        // FIXME: formula evaluation
614
        //assertEquals("[Cell Formula with Reference] K11 cell formula result",
615
        //        39.0, cell.getNumericCellValue(), FLOAT_PRECISION);
616
        
617
        // Cell Formula with Reference spanning multiple rows
618
        col++;
619
        cell = CellUtil.getCell(destRow1, col);
620
        assertEquals("[Cell Formula with Reference spanning multiple rows] L10 cell type",
621
                Cell.CELL_TYPE_FORMULA, cell.getCellType());
622
        assertEquals("[Cell Formula with Reference spanning multiple rows] L10 cell formula",
623
                "G10&\" \"&G11", cell.getCellFormula());
624
        // FIXME: Formula should be evaluated
625
        //assertEquals("[Cell Formula with Reference spanning multiple rows] L11 cell formula result",
626
        //        "Hello World", cell.getStringCellValue());
627
        
628
        cell = CellUtil.getCell(destRow2, col);
629
        assertEquals("[Cell Formula with Reference spanning multiple rows] L11 cell type",
630
                Cell.CELL_TYPE_FORMULA, cell.getCellType());
631
        assertEquals("[Cell Formula with Reference spanning multiple rows] L11 cell formula",
632
                "G11&\" \"&G12", cell.getCellFormula());
633
        // FIXME: Formula should be evaluated
634
        //assertEquals("[Cell Formula with Reference spanning multiple rows] L11 cell formula result",
635
        //        "World ", cell.getStringCellValue());
636
        
637
        // Cell Formula with Area Reference
638
        col++;
639
        cell = CellUtil.getCell(destRow1, col);
640
        assertEquals("[Cell Formula with Area Reference] M10 cell type",
641
                Cell.CELL_TYPE_FORMULA, cell.getCellType());
642
        assertEquals("[Cell Formula with Area Reference] M10 cell formula",
643
                "SUM(H10:I11)", cell.getCellFormula());
644
        // FIXME: Formula should be evaluated
645
        //assertEquals("[Cell Formula with Area Reference] M10 cell formula result",
646
        //        "Hello World", cell.getStringCellValue());
647
        
648
        cell = CellUtil.getCell(destRow2, col);
649
        assertEquals("[Cell Formula with Area Reference] M11 cell type",
650
                Cell.CELL_TYPE_FORMULA, cell.getCellType());
651
        assertEquals("[Cell Formula with Area Reference] M11 cell formula",
652
                "SUM($H$3:I10)", cell.getCellFormula()); //Also acceptable: SUM($H10:I$3), but this AreaReference isn't in ascending order
653
        // FIXME: Formula should be evaluated
654
        //assertEquals("[Cell Formula with Area Reference] M11 cell formula result",
655
        //        "World ", cell.getStringCellValue());
656
        
657
        // Array Formula
658
        col++;
659
        cell = CellUtil.getCell(destRow1, col);
660
        System.out.println("Array formulas currently unsupported");
661
    /*
662
        // FIXME: Array Formula set with Sheet.setArrayFormula() instead of cell.setFormula()
663
        assertEquals("[Array Formula] N10 cell type", Cell.CELL_TYPE_FORMULA, cell.getCellType());
664
        assertEquals("[Array Formula] N10 cell formula", "{SUM(H10:J10*{1,2,3})}", cell.getCellFormula());
665
        // FIXME: Formula should be evaluated
666
        assertEquals("[Array Formula] N10 cell formula result", 61.0, cell.getNumericCellValue(), FLOAT_PRECISION);
667
        
668
        cell = CellUtil.getCell(destRow2, col);
669
        // FIXME: Array Formula set with Sheet.setArrayFormula() instead of cell.setFormula() 
670
        assertEquals("[Array Formula] N11 cell type", Cell.CELL_TYPE_FORMULA, cell.getCellType());
671
        assertEquals("[Array Formula] N11 cell formula", "{SUM(H11:J11*{1,2,3})}", cell.getCellFormula());
672
        // FIXME: Formula should be evaluated
673
        assertEquals("[Array Formula] N11 cell formula result", 125.0, cell.getNumericCellValue(), FLOAT_PRECISION);
674
     */
675
        
676
        // Data Format
677
        col++;
678
        cell = CellUtil.getCell(destRow2, col);
679
        assertEquals("[Data Format] O10 cell type", Cell.CELL_TYPE_NUMERIC, cell.getCellType());
680
        assertEquals("[Data Format] O10 cell value", 100.20, cell.getNumericCellValue(), FLOAT_PRECISION);
681
        final String moneyFormat = "\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)";
682
        assertEquals("[Data Format] O10 cell data format", moneyFormat, cell.getCellStyle().getDataFormatString());
683
        
684
        // Merged
685
        col++;
686
        cell = CellUtil.getCell(destRow1, col);
687
        assertEquals("[Merged] P10:Q10 cell value",
688
                "Merged cells", cell.getStringCellValue());
689
        assertTrue("[Merged] P10:Q10 merged region",
690
                sheet.getMergedRegions().contains(CellRangeAddress.valueOf("P10:Q10")));
691
        
692
        cell = CellUtil.getCell(destRow2, col);
693
        assertEquals("[Merged] P11:Q11 cell value", "Merged cells", cell.getStringCellValue());
694
        assertTrue("[Merged] P11:Q11 merged region",
695
                sheet.getMergedRegions().contains(CellRangeAddress.valueOf("P11:Q11")));
696
        
697
        // Should Q10/Q11 be checked?
698
        
699
        // Merged across multiple rows
700
        // Microsoft Excel 2013 does not copy a merged region unless all rows of
701
        // the source merged region are selected
702
        // POI's behavior should match this behavior
703
        col += 2;
704
        cell = CellUtil.getCell(destRow1, col);
705
        assertEquals("[Merged across multiple rows] R10:S11 cell value", 
706
                "Merged cells across multiple rows", cell.getStringCellValue());
707
        assertTrue("[Merged across multiple rows] R10:S11 merged region", 
708
                sheet.getMergedRegions().contains(CellRangeAddress.valueOf("R10:S11")));
709
        
710
        // Row 3 (zero-based) was empty, so Row 11 (zero-based) should be empty too.
711
        if (srcRow3 == null) {
712
            assertNull("Row 3 was empty, so Row 11 should be empty", destRow3);
713
        }
714
        
715
        // Make sure other rows are blank (off-by-one errors)
716
        assertNull("Off-by-one lower edge case", sheet.getRow(7)); //one row above destHeaderRow
717
        assertNull("Off-by-one upper edge case", sheet.getRow(12)); //one row below destRow3
718
    }
719
327
    /**
720
    /**
328
     * Tests the display of gridlines, formulas, and rowcolheadings.
721
     * Tests the display of gridlines, formulas, and rowcolheadings.
329
     * @author Shawn Laubach (slaubach at apache dot org)
722
     * @author Shawn Laubach (slaubach at apache dot org)
Lines 971-974 Link Here
971
        
1364
        
972
        wb.close();
1365
        wb.close();
973
    }
1366
    }
1367
    
1368
    
974
}
1369
}

Return to bug 58348