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

(-)src/java/org/apache/poi/ss/usermodel/Sheet.java (+34 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
     * Copies rows from srcRows to this sheet starting at destStartRow
657
     * Additionally copies merged regions that are completely defined in these rows
658
     * 
659
     * @param srcRows the rows to copy. Formulas with relative cell and area
660
     * references will be offset by the distance between the first row in srcRows
661
     * and destStartRow (even if srcRows are from a different sheet).
662
     * @param destStartRow the row in this sheet to paste the first row of srcRows
663
     * the remainder of srcRows will be pasted below destStartRow per the cell copy policy
664
     * @param cellCopyPolicy is the cell copy policy, which can be used to copy styles only,
665
     * paste values only, merge the source and destination when the source is
666
     * blank, 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
     * Equivalent to sheet.copyRows(sheet.getRows(srcStartRow, srcEndRow), destStartRow, cellCopyPolicy)
676
     *
677
     * @param srcStartRow the first row in this sheet to copy
678
     * @param srcEndRow the last row in this sheet to copy
679
     * @param destStartRow destStartRow the row in this sheet to paste the first row of srcRows
680
     * the remainder of srcRows will be pasted below destStartRow per the cell copy policy
681
     * @param cellCopyPolicy is the cell copy policy, which can be used to copy styles only,
682
     * paste values only, merge the source and destination when the source is
683
     * blank, etc.
684
     */
685
    @Beta
686
    void copyRows(int srcStartRow, int srcEndRow, int destStartRow, CellCopyPolicy cellCopyPolicy);
653
687
654
    /**
688
    /**
655
     * Creates a split (freezepane). Any existing freezepane or split pane is overwritten.
689
     * Creates a split (freezepane). Any existing freezepane or split pane is overwritten.
(-)src/java/org/apache/poi/ss/usermodel/CellCopyPolicy.java (+186 lines)
Line 0 Link Here
1
package org.apache.poi.ss.usermodel;
2
3
import org.apache.poi.util.Beta;
4
5
@Beta
6
public class CellCopyPolicy implements Cloneable {
7
    public static final boolean DEFAULT_COPY_CELL_VALUE_POLICY = true;
8
    public static final boolean DEFAULT_COPY_CELL_STYLE_POLICY = true;
9
    public static final boolean DEFAULT_COPY_CELL_FORMULA_POLICY = true;
10
    public static final boolean DEFAULT_COPY_MERGED_REGIONS_POLICY = true;
11
    public static final boolean DEFAULT_COPY_ROW_HEIGHT_POLICY = true;
12
    public static final boolean DEFAULT_CONDENSE_ROWS_POLICY = false;
13
    
14
    private boolean copyCellValue = DEFAULT_COPY_CELL_VALUE_POLICY;
15
    private boolean copyCellStyle = DEFAULT_COPY_CELL_STYLE_POLICY;
16
    private boolean copyCellFormula = DEFAULT_COPY_CELL_FORMULA_POLICY;
17
    private boolean copyMergedRegions = DEFAULT_COPY_MERGED_REGIONS_POLICY;
18
    private boolean copyRowHeight = DEFAULT_COPY_ROW_HEIGHT_POLICY;
19
    private boolean condenseRows = DEFAULT_CONDENSE_ROWS_POLICY;
20
    
21
    /** 
22
     * Default CellCopyPolicy, uses default policy
23
     * For custom CellCopyPolicy, use {@link #Builder} class
24
     */
25
    public CellCopyPolicy() { }
26
    
27
    // should builder be replaced with CellCopyPolicy setters that return the object
28
    // to allow setters to be chained together?
29
    // policy.setCopyCellValue(true).setCopyCellStyle(true)
30
    private CellCopyPolicy(Builder builder) {
31
        copyCellValue = builder.copyCellValue;
32
        copyCellStyle = builder.copyCellStyle;
33
        copyCellFormula = builder.copyCellFormula;
34
        copyMergedRegions = builder.copyMergedRegions;
35
        copyRowHeight = builder.copyRowHeight;
36
        condenseRows = builder.condenseRows;
37
    }
38
    
39
    public static class Builder {
40
        private boolean copyCellValue = DEFAULT_COPY_CELL_VALUE_POLICY;
41
        private boolean copyCellStyle = DEFAULT_COPY_CELL_STYLE_POLICY;
42
        private boolean copyCellFormula = DEFAULT_COPY_CELL_FORMULA_POLICY;
43
        private boolean copyMergedRegions = DEFAULT_COPY_MERGED_REGIONS_POLICY;
44
        private boolean copyRowHeight = DEFAULT_COPY_ROW_HEIGHT_POLICY;
45
        private boolean condenseRows = DEFAULT_CONDENSE_ROWS_POLICY;
46
        
47
        /**
48
         * Builder class for CellCopyPolicy
49
         */
50
        public Builder() {
51
        }
52
        
53
        public Builder cellValue(boolean copyCellValue) {
54
            this.copyCellValue = copyCellValue;
55
            return this;
56
        }
57
        public Builder cellStyle(boolean copyCellStyle) {
58
            this.copyCellStyle = copyCellStyle;
59
            return this;
60
        }
61
        public Builder cellFormula(boolean copyCellFormula) {
62
            this.copyCellFormula = copyCellFormula;
63
            return this;
64
        }
65
        public Builder mergedRegions(boolean copyMergedRegions) {
66
            this.copyMergedRegions = copyMergedRegions;
67
            return this;
68
        }
69
        public Builder rowHeight(boolean copyRowHeight) {
70
            this.copyRowHeight = copyRowHeight;
71
            return this;
72
        }
73
        public Builder condenseRows(boolean condenseRows) {
74
            this.condenseRows = condenseRows;
75
            return this;
76
        }
77
        public CellCopyPolicy build() {
78
            return new CellCopyPolicy(this);
79
        }
80
    }
81
    
82
    private Builder createBuilder() {
83
        final Builder builder = new Builder()
84
                .cellValue(copyCellValue)
85
                .cellStyle(copyCellStyle)
86
                .cellFormula(copyCellFormula)
87
                .mergedRegions(copyMergedRegions)
88
                .rowHeight(copyRowHeight)
89
                .condenseRows(condenseRows);
90
        return builder;
91
    }
92
    
93
    @Override
94
    public CellCopyPolicy clone() {
95
        return createBuilder().build();
96
    }
97
    
98
    /**
99
     * @return the copyCellValue
100
     */
101
    public boolean isCopyCellValue() {
102
        return copyCellValue;
103
    }
104
105
    /**
106
     * @param copyCellValue the copyCellValue to set
107
     */
108
    public void setCopyCellValue(boolean copyCellValue) {
109
        this.copyCellValue = copyCellValue;
110
    }
111
112
    /**
113
     * @return the copyCellStyle
114
     */
115
    public boolean isCopyCellStyle() {
116
        return copyCellStyle;
117
    }
118
119
    /**
120
     * @param copyCellStyle the copyCellStyle to set
121
     */
122
    public void setCopyCellStyle(boolean copyCellStyle) {
123
        this.copyCellStyle = copyCellStyle;
124
    }
125
126
    /**
127
     * @return the copyCellFormula
128
     */
129
    public boolean isCopyCellFormula() {
130
        return copyCellFormula;
131
    }
132
133
    /**
134
     * @param copyCellFormula the copyCellFormula to set
135
     */
136
    public void setCopyCellFormula(boolean copyCellFormula) {
137
        this.copyCellFormula = copyCellFormula;
138
    }
139
140
    /**
141
     * @return the copyMergedRegions
142
     */
143
    public boolean isCopyMergedRegions() {
144
        return copyMergedRegions;
145
    }
146
147
    /**
148
     * @param copyMergedRegions the copyMergedRegions to set
149
     */
150
    public void setCopyMergedRegions(boolean copyMergedRegions) {
151
        this.copyMergedRegions = copyMergedRegions;
152
    }
153
154
    /**
155
     * @return the copyRowHeight
156
     */
157
    public boolean isCopyRowHeight() {
158
        return copyRowHeight;
159
    }
160
161
    /**
162
     * @param copyRowHeight the copyRowHeight to set
163
     */
164
    public void setCopyRowHeight(boolean copyRowHeight) {
165
        this.copyRowHeight = copyRowHeight;
166
    }
167
    
168
    /**
169
     * If condenseRows is true, a discontinuities in srcRows will be removed when copied to destination
170
     * For example:
171
     * Sheet.copyRows({Row(1), Row(2), Row(5)}, 11, policy) results in rows 1, 2, and 5
172
     * being copied to rows 11, 12, and 13 if condenseRows is True, or rows 11, 11, 15 if condenseRows is false
173
     * @return the condenseRows
174
     */
175
    public boolean isCondenseRows() {
176
        return condenseRows;
177
    }
178
179
    /**
180
     * @param condenseRows the condenseRows to set
181
     */
182
    public void setCondenseRows(boolean condenseRows) {
183
        this.condenseRows = condenseRows;
184
    }
185
186
}
(-)src/java/org/apache/poi/ss/usermodel/Row.java (+15 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
import org.apache.poi.util.Internal;
24
22
/**
25
/**
23
 * High level representation of a row of a spreadsheet.
26
 * High level representation of a row of a spreadsheet.
24
 */
27
 */
Lines 241-244 Link Here
241
     *  you take it out of them.
244
     *  you take it out of them.
242
     */
245
     */
243
    public int getOutlineLevel();
246
    public int getOutlineLevel();
247
    
248
    /**
249
     * copy the cells from srcRow to this row
250
     * If this row is not a blank row, this will merge the two rows, overwriting
251
     * the cells in this row with the values/styles/formulas/etc of the cells in
252
     * srcRow per cellCopyPolicy.
253
     * @param srcRow the row to copy from (may be from a different sheet)
254
     * @param policy the policy to determine what gets copied
255
     */
256
    @Beta
257
    @Internal
258
    void copyRowFrom(Row srcRow, CellCopyPolicy cellCopyPolicy);
244
}
259
}
(-)src/java/org/apache/poi/ss/usermodel/Cell.java (+13 lines)
Lines 22-27 Link Here
22
22
23
import org.apache.poi.ss.formula.FormulaParseException;
23
import org.apache.poi.ss.formula.FormulaParseException;
24
import org.apache.poi.ss.util.CellRangeAddress;
24
import org.apache.poi.ss.util.CellRangeAddress;
25
import org.apache.poi.util.Beta;
26
import org.apache.poi.util.Internal;
25
27
26
/**
28
/**
27
 * High level representation of a cell in a row of a spreadsheet.
29
 * High level representation of a cell in a row of a spreadsheet.
Lines 324-329 Link Here
324
     * @see FormulaError for error codes
326
     * @see FormulaError for error codes
325
     */
327
     */
326
    byte getErrorCellValue();
328
    byte getErrorCellValue();
329
    
330
    /**
331
     * Copy cell value, formula, and style, from srcCell per cell copy policy
332
     * If srcCell is null, clears the cell value and cell style per cell copy policy
333
     *
334
     * @param srcCell
335
     * @param policy
336
     */
337
    @Beta
338
    @Internal
339
    void copyCellFrom(Cell srcCell, CellCopyPolicy policy);
327
340
328
    /**
341
    /**
329
     * Set the style for the cell.  The style should be an CellStyle created/retreived from
342
     * Set the style for the cell.  The style should be an CellStyle created/retreived from
(-)src/java/org/apache/poi/ss/formula/FormulaShifter.java (-60 / +190 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-108 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.14 (September 2015), replaced by {@link #createForRowShift(int, String, int, int, int, SpreadsheetVersion)}
105
	}
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);
129
    }
106
130
107
    public static FormulaShifter createForSheetShift(int srcSheetIndex, int dstSheetIndex) {
131
    public static FormulaShifter createForSheetShift(int srcSheetIndex, int dstSheetIndex) {
108
        return new FormulaShifter(srcSheetIndex, dstSheetIndex);
132
        return new FormulaShifter(srcSheetIndex, dstSheetIndex);
Lines 137-198 Link Here
137
		return refsWereChanged;
161
		return refsWereChanged;
138
	}
162
	}
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:
169
                //Scenarios:
170
                //* row copy on same sheet
171
                //* row copy between different sheets in the same workbook
172
                return adjustPtgDueToRowCopy(ptg);
173
            case SheetMove:
145
                return adjustPtgDueToShiftMove(ptg);
174
                return adjustPtgDueToShiftMove(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
    }
150
	/**
179
151
	 * @return <code>true</code> if this Ptg needed to be changed
180
152
	 */
181
    /**
153
	private Ptg adjustPtgDueToRowMove(Ptg ptg, int currentExternSheetIx) {
182
     * @return deleted ref ptg, in-place modified ptg, or null
154
		if(ptg instanceof RefPtg) {
183
     */
155
			if (currentExternSheetIx != _externSheetIndex) {
184
    private Ptg adjustPtgDueToRowMove(Ptg ptg, int currentExternSheetIx) {
156
				// local refs on other sheets are unaffected
185
        if(ptg instanceof RefPtg) {
157
				return null;
186
            if (currentExternSheetIx != _externSheetIndex) {
158
			}
187
                // local refs on other sheets are unaffected
159
			RefPtg rptg = (RefPtg)ptg;
188
                return null;
160
			return rowMoveRefPtg(rptg);
189
            }
161
		}
190
            RefPtg rptg = (RefPtg)ptg;
162
		if(ptg instanceof Ref3DPtg) {
191
            return rowMoveRefPtg(rptg);
163
			Ref3DPtg rptg = (Ref3DPtg)ptg;
192
        }
164
			if (_externSheetIndex != rptg.getExternSheetIndex()) {
193
        if(ptg instanceof Ref3DPtg) {
165
				// only move 3D refs that refer to the sheet with cells being moved
194
            Ref3DPtg rptg = (Ref3DPtg)ptg;
166
				// (currentExternSheetIx is irrelevant)
195
            if (_externSheetIndex != rptg.getExternSheetIndex()) {
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-209 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
     * 
249
     * @param ptg the ptg to shift
250
     * @return deleted ref ptg, in-place modified ptg, or null
251
     * If Ptg would be shifted off the first or last row of a sheet, return deleted ref
252
     * If Ptg needs to be changed, modifies Ptg in-place
253
     * If Ptg doesn't need to be changed, returns <code>null</code>
254
     */
255
    private Ptg adjustPtgDueToRowCopy(Ptg ptg) {
256
        if(ptg instanceof RefPtg) {
257
            RefPtg rptg = (RefPtg)ptg;
258
            return rowCopyRefPtg(rptg);
259
        }
260
        if(ptg instanceof Ref3DPtg) {
261
            Ref3DPtg rptg = (Ref3DPtg)ptg;
262
            return rowCopyRefPtg(rptg);
263
        }
264
        if(ptg instanceof Ref3DPxg) {
265
            Ref3DPxg rpxg = (Ref3DPxg)ptg;
266
            return rowCopyRefPtg(rpxg);
267
        }
268
        if(ptg instanceof Area2DPtgBase) {
269
            return rowCopyAreaPtg((Area2DPtgBase)ptg);
270
        }
271
        if(ptg instanceof Area3DPtg) {
272
            Area3DPtg aptg = (Area3DPtg)ptg;
273
            return rowCopyAreaPtg(aptg);
274
        }
275
        if(ptg instanceof Area3DPxg) {
276
            Area3DPxg apxg = (Area3DPxg)ptg;
277
            return rowCopyAreaPtg(apxg);
278
        }
279
        return null;
280
    }
207
281
208
    private Ptg adjustPtgDueToShiftMove(Ptg ptg) {
282
    private Ptg adjustPtgDueToShiftMove(Ptg ptg) {
209
        Ptg updatedPtg = null;
283
        Ptg updatedPtg = null;
Lines 373-379 Link Here
373
		throw new IllegalStateException("Situation not covered: (" + _firstMovedIndex + ", " +
447
		throw new IllegalStateException("Situation not covered: (" + _firstMovedIndex + ", " +
374
					_lastMovedIndex + ", " + _amountToMove + ", " + aFirstRow + ", " + aLastRow + ")");
448
					_lastMovedIndex + ", " + _amountToMove + ", " + aFirstRow + ", " + aLastRow + ")");
375
	}
449
	}
450
	
451
	/**
452
	 * Modifies rptg in-place and return a reference to rptg if the cell reference
453
	 * would move due to a row copy operation
454
	 * Returns <code>null</code> or {@link #RefErrorPtg} if no change was made
455
	 *
456
	 * @param aptg
457
	 * @return
458
	 */
459
	private Ptg rowCopyRefPtg(RefPtgBase rptg) {
460
		final int refRow = rptg.getRow();
461
		if (rptg.isRowRelative()) {
462
			final int destRowIndex = _firstMovedIndex + _amountToMove;
463
			if (destRowIndex < 0 || _version.getLastRowIndex() < destRowIndex)
464
				return createDeletedRef(rptg);
465
			rptg.setRow(refRow + _amountToMove);
466
			return rptg;
467
		}
468
		return null;
469
	}
470
	
471
	/**
472
	 * Modifies aptg in-place and return a reference to aptg if the first or last row of
473
	 * of the Area reference would move due to a row copy operation
474
	 * Returns <code>null</code> or {@link #AreaErrPtg} if no change was made
475
	 *
476
	 * @param aptg
477
	 * @return null, AreaErrPtg, or modified aptg
478
	 */
479
	private Ptg rowCopyAreaPtg(AreaPtgBase aptg) {
480
		boolean changed = false;
481
		
482
		final int aFirstRow = aptg.getFirstRow();
483
		final int aLastRow = aptg.getLastRow();
484
		
485
		if (aptg.isFirstRowRelative()) {
486
			final int destFirstRowIndex = aFirstRow + _amountToMove;
487
			if (destFirstRowIndex < 0 || _version.getLastRowIndex() < destFirstRowIndex)
488
				return createDeletedRef(aptg);
489
			aptg.setFirstRow(destFirstRowIndex);
490
			changed = true;
491
		}
492
		if (aptg.isLastRowRelative()) {
493
			final int destLastRowIndex = aLastRow + _amountToMove;
494
			if (destLastRowIndex < 0 || _version.getLastRowIndex() < destLastRowIndex)
495
				return createDeletedRef(aptg);
496
			aptg.setLastRow(destLastRowIndex);
497
			changed = true;
498
		}
499
		if (changed) {
500
			aptg.sortTopLeftToBottomRight();
501
		}
502
		
503
		return changed ? aptg : null;
504
	}
376
505
506
377
	private static Ptg createDeletedRef(Ptg ptg) {
507
	private static Ptg createDeletedRef(Ptg ptg) {
378
		if (ptg instanceof RefPtg) {
508
		if (ptg instanceof RefPtg) {
379
			return new RefErrorPtg();
509
			return new RefErrorPtg();
(-)src/java/org/apache/poi/hssf/usermodel/HSSFCell.java (+17 lines)
Lines 43-56 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;
49
import org.apache.poi.ss.usermodel.DateUtil;
48
import org.apache.poi.ss.usermodel.FormulaError;
50
import org.apache.poi.ss.usermodel.FormulaError;
49
import org.apache.poi.ss.usermodel.Hyperlink;
51
import org.apache.poi.ss.usermodel.Hyperlink;
50
import org.apache.poi.ss.usermodel.RichTextString;
52
import org.apache.poi.ss.usermodel.RichTextString;
51
import org.apache.poi.ss.util.CellRangeAddress;
53
import org.apache.poi.ss.util.CellRangeAddress;
52
import org.apache.poi.ss.util.CellReference;
54
import org.apache.poi.ss.util.CellReference;
53
import org.apache.poi.ss.util.NumberToTextConverter;
55
import org.apache.poi.ss.util.NumberToTextConverter;
56
import org.apache.poi.util.Beta;
57
import org.apache.poi.util.Internal;
54
import org.apache.poi.util.LocaleUtil;
58
import org.apache.poi.util.LocaleUtil;
55
59
56
/**
60
/**
Lines 884-889 Link Here
884
    }
888
    }
885
889
886
    /**
890
    /**
891
     * Copy cell value, formula, and style, from srcCell per cell copy policy
892
     * If srcCell is null, clears the cell value and cell style per cell copy policy
893
     *
894
     * @param srcCell
895
     * @param policy
896
     */
897
    @Beta
898
    @Internal
899
    public void copyCellFrom(Cell srcCell, CellCopyPolicy policy) {
900
        throw new UnsupportedOperationException();
901
    }
902
903
    /**
887
     * set the style for the cell.  The style should be an HSSFCellStyle created/retreived from
904
     * set the style for the cell.  The style should be an HSSFCellStyle created/retreived from
888
     * the HSSFWorkbook.
905
     * the HSSFWorkbook.
889
     *
906
     *
(-)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/hssf/usermodel/HSSFRow.java (+18 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 298-303 Link Here
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
     * If srcRow is null, overwrite cells in destination row with blank values, styles, etc per cell copy policy
307
     * srcRow may be from a different sheet in the same workbook
308
     * @param srcRow the rows to copy from
309
     * @param cellCopyPolicy the policy to determine what gets copied
310
     */
311
    @Beta
312
    @Override
313
    public void copyRowFrom(Row srcRow, CellCopyPolicy cellCopyPolicy) {
314
        // TODO Auto-generated method stub
315
        throw new UnsupportedOperationException();
316
    }
317
    
318
    /**
301
     * used internally to add a cell.
319
     * used internally to add a cell.
302
     */
320
     */
303
    private void addCell(HSSFCell cell) {
321
    private void addCell(HSSFCell cell) {
(-)src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java (+82 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;
33
import org.apache.poi.util.Beta;
28
import org.apache.poi.util.Internal;
34
import org.apache.poi.util.Internal;
29
import org.apache.poi.xssf.model.CalculationChain;
35
import org.apache.poi.xssf.model.CalculationChain;
30
import org.apache.poi.xssf.model.StylesTable;
36
import org.apache.poi.xssf.model.StylesTable;
37
import org.apache.poi.xssf.usermodel.helpers.XSSFRowShifter;
31
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
38
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
32
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow;
39
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow;
33
40
Lines 513-519 Link Here
513
        }
520
        }
514
        setRowNum(rownum);
521
        setRowNum(rownum);
515
    }
522
    }
523
    
524
    /**
525
     * Copy the cells from srcRow to this row
526
     * If this row is not a blank row, this will merge the two rows, overwriting
527
     * the cells in this row with the cells in srcRow
528
     * If srcRow is null, overwrite cells in destination row with blank values, styles, etc per cell copy policy
529
     * srcRow may be from a different sheet in the same workbook
530
     * @param srcRow the rows to copy from
531
     * @param policy the policy to determine what gets copied
532
     */
533
    @Beta
534
    @Override
535
    public void copyRowFrom(Row srcRow, CellCopyPolicy policy) {
536
        if (srcRow == null) {
537
            // srcRow is blank. Overwrite cells with blank values, blank styles, etc per cell copy policy
538
            for (Cell destCell : this) {
539
                final XSSFCell srcCell = null;
540
                // FIXME: undo type casting
541
                ((XSSFCell)destCell).copyCellFrom(srcCell, policy);
542
            }
516
543
544
            if (policy.isCopyMergedRegions()) {
545
                // Remove MergedRegions in dest row
546
                final int destRowNum = getRowNum();
547
                int index = 0;
548
                final Set<Integer> indices = new HashSet<Integer>();
549
                for (CellRangeAddress destRegion : getSheet().getMergedRegions()) {
550
                    if (destRowNum == destRegion.getFirstRow() && destRowNum == destRegion.getLastRow()) {
551
                        indices.add(index);
552
                    }
553
                    index++;
554
                }
555
                getSheet().removeMergedRegions(indices);
556
            }
557
558
            if (policy.isCopyRowHeight()) {
559
                // clear row height
560
                setHeight((short)-1);
561
            }
562
563
        }
564
        else {
565
            for(Cell c : srcRow){
566
                final XSSFCell srcCell = (XSSFCell)c;
567
                final XSSFCell destCell = createCell(srcCell.getColumnIndex(), srcCell.getCellType());
568
                destCell.copyCellFrom(srcCell, policy);
569
            }
570
571
            final XSSFRowShifter rowShifter = new XSSFRowShifter(_sheet);
572
            final int sheetIndex = _sheet.getWorkbook().getSheetIndex(_sheet);
573
            final String sheetName = _sheet.getWorkbook().getSheetName(sheetIndex);
574
            final int srcRowNum = srcRow.getRowNum();
575
            final int destRowNum = getRowNum();
576
            final int rowDifference = destRowNum - srcRowNum;
577
            final FormulaShifter shifter = FormulaShifter.createForRowCopy(sheetIndex, sheetName, srcRowNum, srcRowNum, rowDifference, SpreadsheetVersion.EXCEL2007);
578
            rowShifter.updateRowFormulas(this, shifter);
579
580
            // Copy merged regions that are fully contained on the row
581
            // FIXME: is this something that rowShifter could be doing?
582
            if (policy.isCopyMergedRegions()) {
583
                for (CellRangeAddress srcRegion : srcRow.getSheet().getMergedRegions()) {
584
                    if (srcRowNum == srcRegion.getFirstRow() && srcRowNum == srcRegion.getLastRow()) {
585
                        CellRangeAddress destRegion = srcRegion.copy();
586
                        destRegion.setFirstRow(destRowNum);
587
                        destRegion.setLastRow(destRowNum);
588
                        getSheet().addMergedRegion(destRegion);
589
                    }
590
                }
591
            }
592
593
            if (policy.isCopyRowHeight()) {
594
                setHeight(srcRow.getHeight());
595
            }
596
        }
597
    }
598
517
    public int getOutlineLevel() {
599
    public int getOutlineLevel() {
518
        return _row.getOutlineLevel();
600
        return _row.getOutlineLevel();
519
    }
601
    }
(-)src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java (-1 / +1 lines)
Lines 162-168 Link Here
162
        }
162
        }
163
    }
163
    }
164
164
165
    private void updateRowFormulas(XSSFRow row, FormulaShifter shifter) {
165
    public void updateRowFormulas(XSSFRow row, FormulaShifter shifter) {
166
        for (Cell c : row) {
166
        for (Cell c : row) {
167
            XSSFCell cell = (XSSFCell) c;
167
            XSSFCell cell = (XSSFCell) c;
168
168
(-)src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java (-2 / +69 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 40-45 Link Here
40
import org.apache.poi.ss.usermodel.Row;
42
import org.apache.poi.ss.usermodel.Row;
41
import org.apache.poi.ss.util.CellRangeAddress;
43
import org.apache.poi.ss.util.CellRangeAddress;
42
import org.apache.poi.ss.util.CellReference;
44
import org.apache.poi.ss.util.CellReference;
45
import org.apache.poi.util.Beta;
43
import org.apache.poi.util.Internal;
46
import org.apache.poi.util.Internal;
44
import org.apache.poi.util.LocaleUtil;
47
import org.apache.poi.util.LocaleUtil;
45
import org.apache.poi.xssf.model.SharedStringsTable;
48
import org.apache.poi.xssf.model.SharedStringsTable;
Lines 53-59 Link Here
53
 * High level representation of a cell in a row of a spreadsheet.
56
 * High level representation of a cell in a row of a spreadsheet.
54
 * <p>
57
 * <p>
55
 * Cells can be numeric, formula-based or string-based (text).  The cell type
58
 * 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
59
 * 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
60
 * 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
61
 * conversions themselves.  Formula cells have the formula string, as well as
59
 * the formula result, which can be numeric or string.
62
 * the formula result, which can be numeric or string.
Lines 115-120 Link Here
115
        _sharedStringSource = row.getSheet().getWorkbook().getSharedStringSource();
118
        _sharedStringSource = row.getSheet().getWorkbook().getSharedStringSource();
116
        _stylesSource = row.getSheet().getWorkbook().getStylesSource();
119
        _stylesSource = row.getSheet().getWorkbook().getStylesSource();
117
    }
120
    }
121
    
122
    /**
123
     * Copy cell value, formula, and style, from srcCell per cell copy policy
124
     * If srcCell is null, clears the cell value and cell style per cell copy policy
125
     * @param srcCell
126
     * @param policy
127
     * @throws IllegalArgumentException if copy cell style and srcCell is from a different workbook
128
     */
129
    @Beta
130
    @Internal
131
    public void copyCellFrom(Cell srcCell, CellCopyPolicy policy) {
132
        // Copy cell value (cell type is updated implicitly)
133
        if (policy.isCopyCellValue()) {
134
            if (srcCell != null) {
135
                int copyCellType = srcCell.getCellType();
136
                if (copyCellType == Cell.CELL_TYPE_FORMULA && !policy.isCopyCellFormula()) {
137
                    // Copy formula result as value
138
                    // FIXME: Cached value may be stale
139
                    copyCellType = srcCell.getCachedFormulaResultType();
140
                }
141
                switch (copyCellType) {
142
                    case Cell.CELL_TYPE_BOOLEAN:
143
                        setCellValue(srcCell.getBooleanCellValue());
144
                        break;
145
                    case Cell.CELL_TYPE_ERROR:
146
                        setCellErrorValue(srcCell.getErrorCellValue());
147
                        break;
148
                    case Cell.CELL_TYPE_FORMULA:
149
                        setCellFormula(srcCell.getCellFormula());
150
                        break;
151
                    case Cell.CELL_TYPE_NUMERIC:
152
                        // DataFormat is not copied unless policy.isCopyCellStyle is true
153
                        if (DateUtil.isCellDateFormatted(srcCell)) {
154
                            setCellValue(srcCell.getDateCellValue());
155
                        }
156
                        else {
157
                            setCellValue(srcCell.getNumericCellValue());
158
                        }
159
                        break;
160
                    case Cell.CELL_TYPE_STRING:
161
                        setCellValue(srcCell.getStringCellValue());
162
                        break;
163
                    case Cell.CELL_TYPE_BLANK:
164
                        setBlank();
165
                        break;
166
                    default:
167
                        throw new IllegalArgumentException("Invalid cell type " + srcCell.getCellType());
168
                }
169
            } else { //srcCell is null
170
                setBlank();
171
            }
172
        }
173
        
174
        // Copy CellStyle
175
        if (policy.isCopyCellStyle()) {
176
            if (srcCell != null) {
177
                setCellStyle(srcCell.getCellStyle());
178
            }
179
            else {
180
                // clear cell style
181
                setCellStyle(null);
182
            }
183
        }
184
    }
118
185
119
    /**
186
    /**
120
     * @return table of strings shared across this workbook
187
     * @return table of strings shared across this workbook
Lines 452-458 Link Here
452
        cellFormula.setRef(range.formatAsString());
519
        cellFormula.setRef(range.formatAsString());
453
    }
520
    }
454
521
455
    @SuppressWarnings("resource")
456
    private void setFormula(String formula, int formulaType) {
522
    private void setFormula(String formula, int formulaType) {
457
        XSSFWorkbook wb = _row.getSheet().getWorkbook();
523
        XSSFWorkbook wb = _row.getSheet().getWorkbook();
458
        if (formula == null) {
524
        if (formula == null) {
Lines 525-530 Link Here
525
     *
591
     *
526
     * @param style  reference contained in the workbook.
592
     * @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.
593
     * If the value is null then the style information is removed causing the cell to used the default workbook style.
594
     * @throws IllegalArgumentException if style belongs to a different styles source (most likely because style is from a different Workbook)
528
     */
595
     */
529
    @Override
596
    @Override
530
    public void setCellStyle(CellStyle style) {
597
    public void setCellStyle(CellStyle style) {
(-)src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java (-2 / +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 1238-1243 Link Here
1238
    public XSSFRow getRow(int rownum) {
1239
    public XSSFRow getRow(int rownum) {
1239
        return _rows.get(rownum);
1240
        return _rows.get(rownum);
1240
    }
1241
    }
1242
    
1243
    /**
1244
     * returns all rows between startRow and endRow, inclusive.
1245
     * Rows between startRow and endRow that haven't been created are not included
1246
     * in result unless createRowIfMissing is true
1247
     *
1248
     * @param startRow the first row number in this sheet to return
1249
     * @param endRow the last row number in this sheet to return
1250
     * @param createRowIfMissing
1251
     * @return
1252
     * @throws IllegalArgumentException if startRowNum and endRowNum are not in ascending order
1253
     */
1254
    private List<XSSFRow> getRows(int startRowNum, int endRowNum, boolean createRowIfMissing) {
1255
        if (startRowNum > endRowNum) {
1256
            throw new IllegalArgumentException("getRows: startRowNum must be less than or equal to endRowNum");
1257
        }
1258
        final List<XSSFRow> rows = new ArrayList<XSSFRow>();
1259
        if (createRowIfMissing) {
1260
            for (int i = startRowNum; i <= endRowNum; i++) {
1261
                XSSFRow row = getRow(i);
1262
                if (row == null) {
1263
                    row = createRow(i);
1264
                }
1265
                rows.add(row);
1266
            }
1267
        }
1268
        else {
1269
            rows.addAll(_rows.subMap(startRowNum, endRowNum+1).values());
1270
        }
1271
        return rows;
1272
    }
1241
1273
1242
    /**
1274
    /**
1243
     * Horizontal page break information used for print layout view, page layout view, drawing print breaks in normal
1275
     * Horizontal page break information used for print layout view, page layout view, drawing print breaks in normal
Lines 1706-1711 Link Here
1706
        _rows.remove(row.getRowNum());
1738
        _rows.remove(row.getRowNum());
1707
        worksheet.getSheetData().removeRow(idx);
1739
        worksheet.getSheetData().removeRow(idx);
1708
    }
1740
    }
1741
    
1742
    public void removeRow(int rowNum) {
1743
        final Row row = getRow(rowNum);
1744
        if (row != null)
1745
            removeRow(row);
1746
    }
1709
1747
1710
    /**
1748
    /**
1711
     * Removes the page break at the indicated row
1749
     * Removes the page break at the indicated row
Lines 2557-2564 Link Here
2557
        if(scale < 10 || scale > 400) throw new IllegalArgumentException("Valid scale values range from 10 to 400");
2595
        if(scale < 10 || scale > 400) throw new IllegalArgumentException("Valid scale values range from 10 to 400");
2558
        getSheetTypeSheetView().setZoomScale(scale);
2596
        getSheetTypeSheetView().setZoomScale(scale);
2559
    }
2597
    }
2598
    
2599
    
2600
    private void copyRows_remove(int startRow, int endRow, int n, Map<Integer, Short> rowHeight) {
2601
        // first remove all rows which will be overwritten
2602
        for (Iterator<Row> it = rowIterator() ; it.hasNext() ; ) {
2603
            final XSSFRow row = (XSSFRow)it.next();
2604
            final int rowNum = row.getRowNum();
2605
            if (XSSFSheet.shouldRemoveRow(startRow, endRow, n, rowNum)) {
2606
    
2607
                // check if we should remove this row as it will be overwritten by the data later
2608
                if (rowHeight != null) {
2609
                    rowHeight.put(rowNum, row.getHeight());
2610
                }
2611
                
2612
                // remove row from worksheet.getSheetData row array
2613
                final int idx = _rows.headMap(rowNum).size();
2614
                worksheet.getSheetData().removeRow(idx);
2560
2615
2616
                // remove row from _rows
2617
                it.remove();
2618
            }
2619
        }
2620
    }
2621
    
2622
    
2561
    /**
2623
    /**
2624
     * copyRows rows from srcRows to this sheet starting at destStartRow
2625
     *
2626
     * Additionally copies merged regions that are completely defined in these
2627
     * rows (ie. merged 2 cells on a row to be shifted).
2628
     * @param srcRows the rows to copy. Formulas will be offset by the difference
2629
     * in the row number of the first row in srcRows and destStartRow (even if srcRows
2630
     * are from a different sheet).
2631
     * @param destStartRow the row in this sheet to paste the first row of srcRows
2632
     * the remainder of srcRows will be pasted below destStartRow per the cell copy policy
2633
     * @param policy is the cell copy policy, which can be used to merge the source and destination
2634
     * when the source is blank, copy styles only, paste as value, etc
2635
     */
2636
    @Beta
2637
    @Override
2638
    public void copyRows(List<? extends Row> srcRows, int destStartRow, CellCopyPolicy policy) {
2639
        if (srcRows == null || srcRows.size() == 0) {
2640
            throw new IllegalArgumentException("No rows to copy");
2641
        }
2642
        final Row srcStartRow = srcRows.get(0);
2643
        final Row srcEndRow = srcRows.get(srcRows.size() - 1);
2644
        
2645
        if (srcStartRow == null) {
2646
            throw new IllegalArgumentException("copyRows: First row cannot be null");
2647
        }
2648
        
2649
        final int srcStartRowNum = srcStartRow.getRowNum();
2650
        final int srcEndRowNum = srcEndRow.getRowNum();
2651
        
2652
        // check row numbers to make sure they are continuous and increasing (monotonic)
2653
        // and srcRows does not contain null rows
2654
        for (int index=1; index < srcRows.size(); index++) {
2655
            final Row prevRow = srcRows.get(index-1);
2656
            final Row curRow = srcRows.get(index);
2657
            if (prevRow == null || curRow == null) {
2658
                throw new IllegalArgumentException("srcRows may not contain null rows. Found null row at index " +
2659
                        index + " after Row " + prevRow.getRowNum() + ".");
2660
            //} else if (curRow.getRowNum() != prevRow.getRowNum() + 1) {
2661
            //    throw new IllegalArgumentException("srcRows must contain continuously increasing row numbers. " +
2662
            //            "Got srcRows[" + (index-1) + "]=Row " + prevRow.getRowNum() + ", srcRows[" + index + "]=Row " + curRow.getRowNum() + ".");
2663
            // FIXME: assumes row objects belong to non-null sheets and sheets belong to non-null workbooks.
2664
            } else if (srcStartRow.getSheet().getWorkbook() != curRow.getSheet().getWorkbook()) {
2665
                throw new IllegalArgumentException("All rows in srcRows must belong to the same sheet in the same workbook." +
2666
                        "Expected all rows from same workbook (" + srcStartRow.getSheet().getWorkbook() + "). " +
2667
                        "Got srcRows[" + index + "] from different workbook (" + curRow.getSheet().getWorkbook() + ").");
2668
            } else if (srcStartRow.getSheet() != curRow.getSheet()) {
2669
                throw new IllegalArgumentException("All rows in srcRows must belong to the same sheet. " +
2670
                        "Expected all rows from " + srcStartRow.getSheet().getSheetName() + ". " +
2671
                        "Got srcRows[" + index + "] from " + curRow.getSheet().getSheetName());
2672
            }
2673
        }
2674
        
2675
        // FIXME: is special behavior needed if srcRows and destRows belong to the same sheets and the regions overlap?
2676
        
2677
        final CellCopyPolicy options = policy.clone();
2678
        // avoid O(N^2) performance scanning through all regions for each row
2679
        // merged regions will be copied after all the rows have been copied
2680
        options.setCopyMergedRegions(false);
2681
        
2682
        // FIXME: if srcRows contains gaps or null values, clear out those rows that will be overwritten
2683
        // how will this work with merging (copy just values, leave cell styles in place?)
2684
        
2685
        int r = destStartRow;
2686
        for (Row srcRow : srcRows) {
2687
            int destRowNum;
2688
            if (policy.isCondenseRows()) {
2689
                destRowNum = r++;
2690
            } else {
2691
                final int shift = (srcRow.getRowNum() - srcStartRowNum);
2692
                destRowNum = destStartRow + shift;
2693
            }
2694
            //removeRow(destRowNum); //this probably clears all external formula references to destRow, causing unwanted #REF! errors
2695
            final Row destRow = createRow(destRowNum);
2696
            destRow.copyRowFrom(srcRow, options);
2697
        }
2698
        
2699
        // ======================
2700
        // Only do additional copy operations here that cannot be done with Row.copyFromRow(Row, options)
2701
        // reasons: operation needs to interact with multiple rows or sheets
2702
        
2703
        // Copy merged regions that are contained within the copy region
2704
        if (policy.isCopyMergedRegions()) {
2705
            // FIXME: is this something that rowShifter could be doing?
2706
            final int shift = destStartRow - srcStartRowNum;
2707
            for (CellRangeAddress srcRegion : srcStartRow.getSheet().getMergedRegions()) {
2708
                if (srcStartRowNum <= srcRegion.getFirstRow() && srcRegion.getLastRow() <= srcEndRowNum) {
2709
                    // srcRegion is fully inside the copied rows
2710
                    final CellRangeAddress destRegion = srcRegion.copy();
2711
                    destRegion.setFirstRow(destRegion.getFirstRow() + shift);
2712
                    destRegion.setLastRow(destRegion.getLastRow() + shift);
2713
                    addMergedRegion(destRegion);
2714
                }
2715
            }
2716
        }
2717
    }
2718
    
2719
    /**
2720
     * Copies rows between srcStartRow and srcEndRow to the same sheet, starting at destStartRow
2721
     * Convenience function for {@link #copyRows(List, int, CellCopyPolicy)}
2722
     * 
2723
     * Equivalent to copyRows(getRows(srcStartRow, srcEndRow, false), destStartRow, policy)
2724
     * 
2725
     */
2726
    @Beta
2727
    @Override
2728
    public void copyRows(int srcStartRow, int srcEndRow, int destStartRow, CellCopyPolicy cellCopyPolicy) {
2729
        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
2730
        copyRows(srcRows, destStartRow, cellCopyPolicy);
2731
    }
2732
    
2733
    /**
2562
     * Shifts rows between startRow and endRow n number of rows.
2734
     * Shifts rows between startRow and endRow n number of rows.
2563
     * If you use a negative number, it will shift rows up.
2735
     * If you use a negative number, it will shift rows up.
2564
     * Code ensures that rows don't wrap around.
2736
     * Code ensures that rows don't wrap around.
Lines 2603-2609 Link Here
2603
            int rownum = row.getRowNum();
2775
            int rownum = row.getRowNum();
2604
2776
2605
            // check if we should remove this row as it will be overwritten by the data later
2777
            // check if we should remove this row as it will be overwritten by the data later
2606
            if (shouldRemoveRow(startRow, endRow, n, rownum)) {
2778
            if (XSSFSheet.shouldRemoveRow(startRow, endRow, n, rownum)) {
2607
                // remove row from worksheet.getSheetData row array
2779
                // remove row from worksheet.getSheetData row array
2608
                int idx = _rows.headMap(row.getRowNum()).size();
2780
                int idx = _rows.headMap(row.getRowNum()).size();
2609
                worksheet.getSheetData().removeRow(idx);
2781
                worksheet.getSheetData().removeRow(idx);
Lines 2999-3005 Link Here
2999
        return sheetPr.isSetPageSetUpPr() ? sheetPr.getPageSetUpPr() : sheetPr.addNewPageSetUpPr();
3171
        return sheetPr.isSetPageSetUpPr() ? sheetPr.getPageSetUpPr() : sheetPr.addNewPageSetUpPr();
3000
    }
3172
    }
3001
3173
3002
    private boolean shouldRemoveRow(int startRow, int endRow, int n, int rownum) {
3174
    private static final boolean shouldRemoveRow(int startRow, int endRow, int n, int rownum) {
3003
        // is this row in the target-window where the moved rows will land?
3175
        // is this row in the target-window where the moved rows will land?
3004
        if (rownum >= (startRow + n) && rownum <= (endRow + n)) {
3176
        if (rownum >= (startRow + n) && rownum <= (endRow + n)) {
3005
            // only remove it if the current row is not part of the data that is copied
3177
            // only remove it if the current row is not part of the data that is copied
(-)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/streaming/SXSSFCell.java (+16 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 35-40 Link Here
35
import org.apache.poi.ss.usermodel.Row;
36
import org.apache.poi.ss.usermodel.Row;
36
import org.apache.poi.ss.util.CellRangeAddress;
37
import org.apache.poi.ss.util.CellRangeAddress;
37
import org.apache.poi.ss.util.CellReference;
38
import org.apache.poi.ss.util.CellReference;
39
import org.apache.poi.util.Beta;
40
import org.apache.poi.util.Internal;
38
import org.apache.poi.util.LocaleUtil;
41
import org.apache.poi.util.LocaleUtil;
39
import org.apache.poi.util.POILogFactory;
42
import org.apache.poi.util.POILogFactory;
40
import org.apache.poi.util.POILogger;
43
import org.apache.poi.util.POILogger;
Lines 502-507 Link Here
502
                throw typeMismatch(CELL_TYPE_ERROR, cellType, false);
505
                throw typeMismatch(CELL_TYPE_ERROR, cellType, false);
503
        }
506
        }
504
    }
507
    }
508
    
509
    /**
510
     * Copy cell value, formula, and style, from srcCell per cell copy policy
511
     * If srcCell is null, clears the cell value and cell style per cell copy policy
512
     * @param srcCell
513
     * @param policy
514
     * @throws IllegalArgumentException if copy cell style and srcCell is from a different workbook
515
     */
516
    @Beta
517
    @Internal
518
    public void copyCellFrom(Cell srcCell, CellCopyPolicy policy) {
519
        throw new UnsupportedOperationException();
520
    }
505
521
506
    /**
522
    /**
507
     * Set the style for the cell.  The style should be an CellStyle created/retreived from
523
     * 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
        throw new UnsupportedOperationException();
499
    }
491
}
500
}
492
501
(-)src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java (-8 / +18 lines)
Lines 1285-1294 Link Here
1285
1285
1286
        assertNotNull(wb);
1286
        assertNotNull(wb);
1287
        assertNotNull(sheet);
1287
        assertNotNull(sheet);
1288
        XSSFPivotTable pivotTable = sheet.createPivotTable(new AreaReference("A1:B2"), new CellReference("H5"));
1288
        XSSFPivotTable pivotTable = sheet.createPivotTable(new AreaReference("A1:B2", SpreadsheetVersion.EXCEL2007), new CellReference("H5"));
1289
        assertNotNull(pivotTable);
1289
        assertNotNull(pivotTable);
1290
        assertTrue(wb.getPivotTables().size() > 0);
1290
        assertTrue(wb.getPivotTables().size() > 0);
1291
        XSSFPivotTable pivotTable2 = sheet.createPivotTable(new AreaReference("A1:B2"), new CellReference("L5"), sheet);
1291
        XSSFPivotTable pivotTable2 = sheet.createPivotTable(new AreaReference("A1:B2", SpreadsheetVersion.EXCEL2007), new CellReference("L5"), sheet);
1292
        assertNotNull(pivotTable2);
1292
        assertNotNull(pivotTable2);
1293
        assertTrue(wb.getPivotTables().size() > 1);
1293
        assertTrue(wb.getPivotTables().size() > 1);
1294
    }
1294
    }
Lines 1300-1311 Link Here
1300
1300
1301
        assertNotNull(wb);
1301
        assertNotNull(wb);
1302
        assertNotNull(sheet);
1302
        assertNotNull(sheet);
1303
        XSSFPivotTable pivotTable = sheet.createPivotTable(new AreaReference("A1:B2"), new CellReference("H5"));
1303
        XSSFPivotTable pivotTable = sheet.createPivotTable(new AreaReference("A1:B2", SpreadsheetVersion.EXCEL2007), new CellReference("H5"));
1304
        assertNotNull(pivotTable);
1304
        assertNotNull(pivotTable);
1305
        assertTrue(wb.getPivotTables().size() > 0);
1305
        assertTrue(wb.getPivotTables().size() > 0);
1306
        assertNotNull(wb);
1306
        assertNotNull(wb);
1307
        XSSFSheet sheet2 = wb.createSheet();
1307
        XSSFSheet sheet2 = wb.createSheet();
1308
        XSSFPivotTable pivotTable2 = sheet2.createPivotTable(new AreaReference("A1:B2"), new CellReference("H5"), sheet);
1308
        XSSFPivotTable pivotTable2 = sheet2.createPivotTable(new AreaReference("A1:B2", SpreadsheetVersion.EXCEL2007), new CellReference("H5"), sheet);
1309
        assertNotNull(pivotTable2);
1309
        assertNotNull(pivotTable2);
1310
        assertTrue(wb.getPivotTables().size() > 1);
1310
        assertTrue(wb.getPivotTables().size() > 1);
1311
    }
1311
    }
Lines 1317-1323 Link Here
1317
1317
1318
        assertNotNull(wb);
1318
        assertNotNull(wb);
1319
        assertNotNull(sheet);
1319
        assertNotNull(sheet);
1320
        XSSFPivotTable pivotTable = sheet.createPivotTable(new AreaReference("A1:B2"), new CellReference("H5"));
1320
        XSSFPivotTable pivotTable = sheet.createPivotTable(new AreaReference("A1:B2", SpreadsheetVersion.EXCEL2007), new CellReference("H5"));
1321
        assertNotNull(pivotTable);
1321
        assertNotNull(pivotTable);
1322
        assertTrue(wb.getPivotTables().size() > 0);
1322
        assertTrue(wb.getPivotTables().size() > 0);
1323
    }
1323
    }
Lines 1329-1335 Link Here
1329
        XSSFSheet sheet2 = wb.createSheet();
1329
        XSSFSheet sheet2 = wb.createSheet();
1330
1330
1331
        XSSFPivotTable pivotTable = sheet2.createPivotTable
1331
        XSSFPivotTable pivotTable = sheet2.createPivotTable
1332
                (new AreaReference("A1:B2"), new CellReference("H5"), sheet1);
1332
                (new AreaReference("A1:B2", SpreadsheetVersion.EXCEL2007), new CellReference("H5"), sheet1);
1333
        assertEquals(0, pivotTable.getRowLabelColumns().size());
1333
        assertEquals(0, pivotTable.getRowLabelColumns().size());
1334
        
1334
        
1335
        assertEquals(1, wb.getPivotTables().size());
1335
        assertEquals(1, wb.getPivotTables().size());
Lines 1344-1350 Link Here
1344
        XSSFSheet sheet2 = wb.createSheet();
1344
        XSSFSheet sheet2 = wb.createSheet();
1345
1345
1346
        XSSFPivotTable pivotTable = sheet2.createPivotTable
1346
        XSSFPivotTable pivotTable = sheet2.createPivotTable
1347
                (new AreaReference(sheet.getSheetName()+"!A$1:B$2"), new CellReference("H5"));
1347
                (new AreaReference(sheet.getSheetName()+"!A$1:B$2", SpreadsheetVersion.EXCEL2007), new CellReference("H5"));
1348
        assertEquals(0, pivotTable.getRowLabelColumns().size());
1348
        assertEquals(0, pivotTable.getRowLabelColumns().size());
1349
    }
1349
    }
1350
1350
Lines 1355-1361 Link Here
1355
        XSSFSheet sheet2 = wb.createSheet();
1355
        XSSFSheet sheet2 = wb.createSheet();
1356
1356
1357
        try {
1357
        try {
1358
            sheet2.createPivotTable(new AreaReference(sheet.getSheetName()+"!A$1:B$2"), new CellReference("H5"), sheet2);
1358
            sheet2.createPivotTable(new AreaReference(sheet.getSheetName()+"!A$1:B$2", SpreadsheetVersion.EXCEL2007), new CellReference("H5"), sheet2);
1359
        } catch(IllegalArgumentException e) {
1359
        } catch(IllegalArgumentException e) {
1360
            return;
1360
            return;
1361
        }
1361
        }
Lines 1382-1385 Link Here
1382
        XSSFSheet sheet = wb.createSheet();
1382
        XSSFSheet sheet = wb.createSheet();
1383
        assertNotNull(sheet.createComment());
1383
        assertNotNull(sheet.createComment());
1384
    }
1384
    }
1385
    
1386
    @Test
1387
    public void testCopyOneRow() throws IOException {
1388
        baseTestCopyOneRow("XSSFSheet.copyRows.xlsx");
1389
    }
1390
    
1391
    @Test
1392
    public void testCopyMultipleRows() throws IOException {
1393
        baseTestCopyMultipleRows("XSSFSheet.copyRows.xlsx");
1394
    }
1385
}
1395
}
(-)src/ooxml/testcases/org/apache/poi/xssf/streaming/TestSXSSFSheet.java (+10 lines)
Lines 76-81 Link Here
76
        thrown.expectMessage("NotImplemented");
76
        thrown.expectMessage("NotImplemented");
77
        super.shiftMerged();
77
        super.shiftMerged();
78
    }
78
    }
79
    
80
    @Test
81
    public void testCopyOneRow() {
82
        //TODO: implement this test
83
    }
84
    
85
    @Test
86
    public void testCopyMultipleRows() {
87
        //TODO: implement this test
88
    }
79
89
80
    /**
90
    /**
81
     *  Bug 35084: cloning cells with formula
91
     *  Bug 35084: cloning cells with formula
(-)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/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/TestHSSFSheet.java (+10 lines)
Lines 1139-1142 Link Here
1139
        NameRecord record = wb.getWorkbook().getSpecificBuiltinRecord(NameRecord.BUILTIN_FILTER_DB, 1);
1139
        NameRecord record = wb.getWorkbook().getSpecificBuiltinRecord(NameRecord.BUILTIN_FILTER_DB, 1);
1140
        assertNotNull(record);
1140
        assertNotNull(record);
1141
    }
1141
    }
1142
    
1143
    @Test
1144
    public void testCopyOneRow() {
1145
        //TODO: implement this test
1146
    }
1147
1148
    @Test
1149
    public void testCopyMultipleRows() {
1150
        //TODO: implement this test
1151
    }
1142
}
1152
}
(-)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/ss/usermodel/BaseTestRow.java (+163 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
        
450
        destRow.copyRowFrom(srcRow, new CellCopyPolicy());
451
        assertNotNull(destRow.getCell(0));
452
        assertEquals("Hello", destRow.getCell(0).getStringCellValue());
453
    }
454
    
455
    public void testCopyRowFromExternalSheet() {
456
        final Workbook workbook = _testDataProvider.createWorkbook();
457
        final Sheet srcSheet = workbook.createSheet("src");
458
        final Sheet destSheet = workbook.createSheet("dest");
459
        workbook.createSheet("other");
460
        
461
        final Row srcRow = srcSheet.createRow(0);
462
        int col = 0;
463
        //Test 2D and 3D Ref Ptgs (Pxg for OOXML Workbooks)
464
        srcRow.createCell(col++).setCellFormula("B5");
465
        srcRow.createCell(col++).setCellFormula("src!B5");
466
        srcRow.createCell(col++).setCellFormula("dest!B5");
467
        srcRow.createCell(col++).setCellFormula("other!B5");
468
        
469
        //Test 2D and 3D Ref Ptgs with absolute row
470
        srcRow.createCell(col++).setCellFormula("B$5");
471
        srcRow.createCell(col++).setCellFormula("src!B$5");
472
        srcRow.createCell(col++).setCellFormula("dest!B$5");
473
        srcRow.createCell(col++).setCellFormula("other!B$5");
474
        
475
        //Test 2D and 3D Area Ptgs (Pxg for OOXML Workbooks)
476
        srcRow.createCell(col++).setCellFormula("SUM(B5:D$5)");
477
        srcRow.createCell(col++).setCellFormula("SUM(src!B5:D$5)");
478
        srcRow.createCell(col++).setCellFormula("SUM(dest!B5:D$5)");
479
        srcRow.createCell(col++).setCellFormula("SUM(other!B5:D$5)");
480
481
        // FIXME: temporary work-around until bug 58350 is fixed
482
        if (srcSheet.getNumMergedRegions() == 0) {
483
            // Goal: CTWorksheet.addNewMergeCells()
484
            srcSheet.addMergedRegion(new CellRangeAddress(10, 11, 0, 0));
485
        }
486
        
487
        //////////////////
488
489
        final Row destRow = destSheet.createRow(1);
490
        destRow.copyRowFrom(srcRow, new CellCopyPolicy());
491
        
492
        //////////////////
493
        
494
        //Test 2D and 3D Ref Ptgs (Pxg for OOXML Workbooks)
495
        col = 0;
496
        Cell cell = destRow.getCell(col++);
497
        assertNotNull(cell);
498
        assertEquals("RefPtg", "B6", cell.getCellFormula());
499
        
500
        cell = destRow.getCell(col++);
501
        assertNotNull(cell);
502
        assertEquals("Ref3DPtg", "src!B6", cell.getCellFormula());
503
        
504
        cell = destRow.getCell(col++);
505
        assertNotNull(cell);
506
        assertEquals("Ref3DPtg", "dest!B6", cell.getCellFormula());
507
        
508
        cell = destRow.getCell(col++);
509
        assertNotNull(cell);
510
        assertEquals("Ref3DPtg", "other!B6", cell.getCellFormula());
511
        
512
        /////////////////////////////////////////////
513
        
514
        //Test 2D and 3D Ref Ptgs with absolute row (Ptg row number shouldn't change)
515
        cell = destRow.getCell(col++);
516
        assertNotNull(cell);
517
        assertEquals("RefPtg", "B$5", cell.getCellFormula());
518
        
519
        cell = destRow.getCell(col++);
520
        assertNotNull(cell);
521
        assertEquals("Ref3DPtg", "src!B$5", cell.getCellFormula());
522
        
523
        cell = destRow.getCell(col++);
524
        assertNotNull(cell);
525
        assertEquals("Ref3DPtg", "dest!B$5", cell.getCellFormula());
526
        
527
        cell = destRow.getCell(col++);
528
        assertNotNull(cell);
529
        assertEquals("Ref3DPtg", "other!B$5", cell.getCellFormula());
530
        
531
        //////////////////////////////////////////
532
        
533
        //Test 2D and 3D Area Ptgs (Pxg for OOXML Workbooks)
534
        // Note: absolute row changes from last cell to first cell in order
535
        // to maintain topLeft:bottomRight order
536
        cell = destRow.getCell(col++);
537
        assertNotNull(cell);
538
        assertEquals("Area2DPtg", "SUM(B$5:D6)", cell.getCellFormula());
539
        
540
        cell = destRow.getCell(col++);
541
        assertNotNull(cell);
542
        assertEquals("Area3DPtg", "SUM(src!B$5:D6)", cell.getCellFormula());
543
        
544
        cell = destRow.getCell(col++);
545
        assertNotNull(destRow.getCell(6));
546
        assertEquals("Area3DPtg", "SUM(dest!B$5:D6)", cell.getCellFormula());
547
        
548
        cell = destRow.getCell(col++);
549
        assertNotNull(destRow.getCell(7));
550
        assertEquals("Area3DPtg", "SUM(other!B$5:D6)", cell.getCellFormula());
551
    }
552
    
553
    public void testCopyRowOverwritesExistingRow() {
554
        final Workbook workbook = _testDataProvider.createWorkbook();
555
        final Sheet sheet1 = workbook.createSheet("Sheet1");
556
        final Sheet sheet2 = workbook.createSheet("Sheet2");
557
        
558
        final Row srcRow = sheet1.createRow(0);
559
        final Row destRow = sheet1.createRow(1);
560
        final Row observerRow = sheet1.createRow(2);
561
        final Row externObserverRow = sheet2.createRow(0);
562
        
563
        srcRow.createCell(0).setCellValue("hello");
564
        srcRow.createCell(1).setCellValue("world");
565
        destRow.createCell(0).setCellValue(5.0); //A2 -> 5.0
566
        destRow.createCell(1).setCellFormula("A1"); // B2 -> A1 -> "hello"
567
        observerRow.createCell(0).setCellFormula("A2"); // A3 -> A2 -> 5.0
568
        observerRow.createCell(1).setCellFormula("B2"); // B3 -> B2 -> A1 -> "hello"
569
        externObserverRow.createCell(0).setCellFormula("Sheet1!A2"); //Sheet2!A1 -> Sheet1!A2 -> 5.0
570
        
571
        // FIXME: temporary work-around until bug 58350 is fixed
572
        if (sheet1.getNumMergedRegions() == 0) {
573
            // Goal: CTWorksheet.addNewMergeCells()
574
            sheet1.addMergedRegion(new CellRangeAddress(10, 11, 0, 0));
575
        }
576
        
577
        // overwrite existing destRow with row-copy of srcRow
578
        destRow.copyRowFrom(srcRow, new CellCopyPolicy());
579
        
580
        // copyRowFrom should update existing destRow, rather than creating a new row and reassigning the destRow pointer
581
        // to the new row (and allow the old row to be garbage collected)
582
        // this is mostly so existing references to rows that are overwritten are updated
583
        // rather than allowing users to continue updating rows that are no longer part of the sheet
584
        assertSame("existing references to srcRow are still valid", srcRow, sheet1.getRow(0));
585
        assertSame("existing references to destRow are still valid", destRow, sheet1.getRow(1));
586
        assertSame("existing references to observerRow are still valid", observerRow, sheet1.getRow(2));
587
        assertSame("existing references to externObserverRow are still valid", externObserverRow, sheet2.getRow(0));
588
        
589
        // Make sure copyRowFrom actually copied row (this is tested elsewhere)
590
        assertEquals(Cell.CELL_TYPE_STRING, destRow.getCell(0).getCellType());
591
        assertEquals("hello", destRow.getCell(0).getStringCellValue());
592
        
593
        // 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
594
        assertEquals("references to overwritten cells are unmodified", "A2", observerRow.getCell(0).getCellFormula());
595
        assertEquals("references to overwritten cells are unmodified", "B2", observerRow.getCell(1).getCellFormula());
596
        assertEquals("references to overwritten cells are unmodified", "Sheet1!A2", externObserverRow.getCell(0).getCellFormula());
597
    }
435
}
598
}
(-)src/testcases/org/apache/poi/ss/usermodel/BaseTestSheet.java (+395 lines)
Lines 22-33 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;
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 348-354 Link Here
348
        region = sheet.getMergedRegion(0);
353
        region = sheet.getMergedRegion(0);
349
        assertEquals("Merged region not moved over to row 2", 2, region.getFirstRow());
354
        assertEquals("Merged region not moved over to row 2", 2, region.getFirstRow());
350
    }
355
    }
356
    
357
    protected void baseTestCopyOneRow(String copyRowsTestWorkbook) throws IOException {
358
        final double FLOAT_PRECISION = 1e-9;
359
        final Workbook workbook = _testDataProvider.openSampleWorkbook(copyRowsTestWorkbook);
360
        final Sheet sheet = workbook.getSheetAt(0);
361
        final CellCopyPolicy defaultCopyPolicy = new CellCopyPolicy();
362
        sheet.copyRows(1, 1, 6, defaultCopyPolicy);
351
363
364
        final Row srcRow = sheet.getRow(1);
365
        final Row destRow = sheet.getRow(6);
366
        int col = 0;
367
        Cell cell;
368
369
        cell = CellUtil.getCell(destRow, col++);
370
        assertEquals("Source row ->", cell.getStringCellValue());
371
372
        // Style
373
        cell = CellUtil.getCell(destRow, col++);
374
        assertEquals("[Style] B7 cell value", "Red", cell.getStringCellValue());
375
        assertEquals("[Style] B7 cell style", CellUtil.getCell(srcRow, 1).getCellStyle(), cell.getCellStyle());
376
377
        // Blank
378
        cell = CellUtil.getCell(destRow, col++);
379
        assertEquals("[Blank] C7 cell type", Cell.CELL_TYPE_BLANK, cell.getCellType());
380
381
        // Error
382
        cell = CellUtil.getCell(destRow, col++);
383
        assertEquals("[Error] D7 cell type", Cell.CELL_TYPE_ERROR, cell.getCellType());
384
        final FormulaError error = FormulaError.forInt(cell.getErrorCellValue());
385
        assertEquals("[Error] D7 cell value", FormulaError.NA, error); //FIXME: XSSFCell and HSSFCell expose different interfaces. getErrorCellString would be helpful here
386
387
        // Date
388
        cell = CellUtil.getCell(destRow, col++);
389
        assertEquals("[Date] E7 cell type", Cell.CELL_TYPE_NUMERIC, cell.getCellType());
390
        final Date date = new GregorianCalendar(2000, Calendar.JANUARY, 1).getTime();
391
        assertEquals("[Date] E7 cell value", date, cell.getDateCellValue());
392
393
        // Boolean
394
        cell = CellUtil.getCell(destRow, col++);
395
        assertEquals("[Boolean] F7 cell type", Cell.CELL_TYPE_BOOLEAN, cell.getCellType());
396
        assertEquals("[Boolean] F7 cell value", true, cell.getBooleanCellValue());
397
398
        // String
399
        cell = CellUtil.getCell(destRow, col++);
400
        assertEquals("[String] G7 cell type", Cell.CELL_TYPE_STRING, cell.getCellType());
401
        assertEquals("[String] G7 cell value", "Hello", cell.getStringCellValue());
402
        
403
        // Int
404
        cell = CellUtil.getCell(destRow, col++);
405
        assertEquals("[Int] H7 cell type", Cell.CELL_TYPE_NUMERIC, cell.getCellType());
406
        assertEquals("[Int] H7 cell value", 15, (int) cell.getNumericCellValue());
407
        
408
        // Float
409
        cell = CellUtil.getCell(destRow, col++);
410
        assertEquals("[Float] I7 cell type", Cell.CELL_TYPE_NUMERIC, cell.getCellType());
411
        assertEquals("[Float] I7 cell value", 12.5, cell.getNumericCellValue(), FLOAT_PRECISION);
412
        
413
        // Cell Formula
414
        cell = CellUtil.getCell(destRow, col++);
415
        assertEquals("J7", new CellReference(cell).formatAsString());
416
        assertEquals("[Cell Formula] J7 cell type", Cell.CELL_TYPE_FORMULA, cell.getCellType());
417
        assertEquals("[Cell Formula] J7 cell formula", "5+2", cell.getCellFormula());
418
        System.out.println("Cell formula evaluation currently unsupported");
419
        //assertEquals("[Cell Formula] J7 cell value", 7.0, cell.getNumericCellValue(), FLOAT_PRECISION);
420
        
421
        // Cell Formula with Reference
422
        // Formula row references should be adjusted by destRowNum-srcRowNum
423
        cell = CellUtil.getCell(destRow, col++);
424
        assertEquals("K7", new CellReference(cell).formatAsString());
425
        assertEquals("[Cell Formula with Reference] K7 cell type",
426
                Cell.CELL_TYPE_FORMULA, cell.getCellType());
427
        assertEquals("[Cell Formula with Reference] K7 cell formula",
428
                "J7+H$2", cell.getCellFormula());
429
        //assertEquals("[Cell Formula with Reference] J7 cell value",
430
        //        22.0, cell.getNumericCellValue(), FLOAT_PRECISION);
431
        
432
        // Cell Formula with Reference spanning multiple rows
433
        cell = CellUtil.getCell(destRow, col++);
434
        assertEquals("[Cell Formula with Reference spanning multiple rows] L7 cell type",
435
                Cell.CELL_TYPE_FORMULA, cell.getCellType());
436
        assertEquals("[Cell Formula with Reference spanning multiple rows] L7 cell formula",
437
                "G7&\" \"&G8", cell.getCellFormula());
438
        //assertEquals("[Cell Formula with Reference spanning multiple rows] L7 cell value",
439
        //        "World ", cell.getStringCellValue());
440
        
441
        // Cell Formula with Reference spanning multiple rows
442
        cell = CellUtil.getCell(destRow, col++);
443
        assertEquals("[Cell Formula with Area Reference] M7 cell type",
444
                Cell.CELL_TYPE_FORMULA, cell.getCellType());
445
        assertEquals("[Cell Formula with Area Reference] M7 cell formula",
446
                "SUM(H7:I8)", cell.getCellFormula());
447
        //assertEquals("[Cell Formula with Area Reference] M7 cell value",
448
        //        "75", cell.getStringCellValue());
449
        
450
        // Array Formula
451
        cell = CellUtil.getCell(destRow, col++);
452
        System.out.println("Array formulas currently unsupported");
453
        // FIXME: Array Formula set with Sheet.setArrayFormula() instead of cell.setFormula()
454
        /*
455
        assertEquals("[Array Formula] N7 cell type", Cell.CELL_TYPE_FORMULA, cell.getCellType());
456
        assertEquals("[Array Formula] N7 cell formula", "{SUM(H7:J7*{1,2,3})}", cell.getCellFormula());
457
        */
458
        // Formula should be evaluated
459
        //assertEquals("[Array Formula] N7 cell value", 61.0, cell.getNumericCellValue(), FLOAT_PRECISION);
460
        
461
        // Data Format
462
        cell = CellUtil.getCell(destRow, col++);
463
        assertEquals("[Data Format] O7 cell type;", Cell.CELL_TYPE_NUMERIC, cell.getCellType());
464
        assertEquals("[Data Format] O7 cell value", 100.20, cell.getNumericCellValue(), FLOAT_PRECISION);
465
        //FIXME: currently fails
466
        final String moneyFormat = "\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)";
467
        assertEquals("[Data Format] O7 data format", moneyFormat, cell.getCellStyle().getDataFormatString());
468
        
469
        // Merged
470
        cell = CellUtil.getCell(destRow, col);
471
        assertEquals("[Merged] P7:Q7 cell value",
472
                "Merged cells", cell.getStringCellValue());
473
        assertTrue("[Merged] P7:Q7 merged region",
474
                sheet.getMergedRegions().contains(CellRangeAddress.valueOf("P7:Q7")));
475
        
476
        // Merged across multiple rows
477
        // Microsoft Excel 2013 does not copy a merged region unless all rows of
478
        // the source merged region are selected
479
        // POI's behavior should match this behavior
480
        col += 2;
481
        cell = CellUtil.getCell(destRow, col);
482
        // Note: this behavior deviates from Microsoft Excel,
483
        // which will not overwrite a cell in destination row if merged region extends beyond the copied row.
484
        // The Excel way would require:
485
        //assertEquals("[Merged across multiple rows] R7:S8 merged region", "Should NOT be overwritten", cell.getStringCellValue());
486
        //assertFalse("[Merged across multiple rows] R7:S8 merged region", 
487
        //        sheet.getMergedRegions().contains(CellRangeAddress.valueOf("R7:S8")));
488
        // As currently implemented, cell value is copied but merged region is not copied
489
        assertEquals("[Merged across multiple rows] R7:S8 cell value",
490
                "Merged cells across multiple rows", cell.getStringCellValue());
491
        assertFalse("[Merged across multiple rows] R7:S7 merged region (one row)", 
492
                sheet.getMergedRegions().contains(CellRangeAddress.valueOf("R7:S7"))); //shouldn't do 1-row merge
493
        assertFalse("[Merged across multiple rows] R7:S8 merged region", 
494
                sheet.getMergedRegions().contains(CellRangeAddress.valueOf("R7:S8"))); //shouldn't do 2-row merge
495
        
496
        // Make sure other rows are blank (off-by-one errors)
497
        assertNull(sheet.getRow(5));
498
        assertNull(sheet.getRow(7));
499
    }
500
    
501
    public void baseTestCopyMultipleRows(String copyRowsTestWorkbook) throws IOException {
502
        final double FLOAT_PRECISION = 1e-9;
503
        final Workbook workbook = _testDataProvider.openSampleWorkbook(copyRowsTestWorkbook);
504
        final Sheet sheet = workbook.getSheetAt(0);
505
        final CellCopyPolicy defaultCopyPolicy = new CellCopyPolicy();
506
        sheet.copyRows(0, 3, 8, defaultCopyPolicy);
507
508
        final Row srcHeaderRow = sheet.getRow(0);
509
        final Row srcRow1 = sheet.getRow(1);
510
        final Row srcRow2 = sheet.getRow(2);
511
        final Row srcRow3 = sheet.getRow(3);
512
        final Row destHeaderRow = sheet.getRow(8);
513
        final Row destRow1 = sheet.getRow(9);
514
        final Row destRow2 = sheet.getRow(10);
515
        final Row destRow3 = sheet.getRow(11);
516
        int col = 0;
517
        Cell cell;
518
        
519
        // Header row should be copied
520
        assertNotNull(destHeaderRow);
521
        
522
        // Data rows
523
        cell = CellUtil.getCell(destRow1, col);
524
        assertEquals("Source row ->", cell.getStringCellValue());
525
        
526
        // Style
527
        col++;
528
        cell = CellUtil.getCell(destRow1, col);
529
        assertEquals("[Style] B10 cell value", "Red", cell.getStringCellValue());
530
        assertEquals("[Style] B10 cell style", CellUtil.getCell(srcRow1, 1).getCellStyle(), cell.getCellStyle());
531
        
532
        cell = CellUtil.getCell(destRow2, col);
533
        assertEquals("[Style] B11 cell value", "Blue", cell.getStringCellValue());
534
        assertEquals("[Style] B11 cell style", CellUtil.getCell(srcRow2, 1).getCellStyle(), cell.getCellStyle());
535
        
536
        // Blank
537
        col++;
538
        cell = CellUtil.getCell(destRow1, col);
539
        assertEquals("[Blank] C10 cell type", Cell.CELL_TYPE_BLANK, cell.getCellType());
540
        
541
        cell = CellUtil.getCell(destRow2, col);
542
        assertEquals("[Blank] C11 cell type", Cell.CELL_TYPE_BLANK, cell.getCellType());
543
        
544
        // Error
545
        col++;
546
        cell = CellUtil.getCell(destRow1, col);
547
        assertEquals("[Error] D10 cell type", Cell.CELL_TYPE_ERROR, cell.getCellType());
548
        FormulaError error = FormulaError.forInt(cell.getErrorCellValue());
549
        assertEquals("[Error] D10 cell value", FormulaError.NA, error); //FIXME: XSSFCell and HSSFCell expose different interfaces. getErrorCellString would be helpful here
550
        
551
        cell = CellUtil.getCell(destRow2, col);
552
        assertEquals("[Error] D11 cell type", Cell.CELL_TYPE_ERROR, cell.getCellType());
553
        error = FormulaError.forInt(cell.getErrorCellValue());
554
        assertEquals("[Error] D11 cell value", FormulaError.NAME, error); //FIXME: XSSFCell and HSSFCell expose different interfaces. getErrorCellString would be helpful here
555
        
556
        // Date
557
        col++;
558
        cell = CellUtil.getCell(destRow1, col);
559
        assertEquals("[Date] E10 cell type", Cell.CELL_TYPE_NUMERIC, cell.getCellType());
560
        Date date = new GregorianCalendar(2000, Calendar.JANUARY, 1).getTime();
561
        assertEquals("[Date] E10 cell value", date, cell.getDateCellValue());
562
        
563
        cell = CellUtil.getCell(destRow2, col);
564
        assertEquals("[Date] E11 cell type", Cell.CELL_TYPE_NUMERIC, cell.getCellType());
565
        date = new GregorianCalendar(2000, Calendar.JANUARY, 2).getTime();
566
        assertEquals("[Date] E11 cell value", date, cell.getDateCellValue());
567
        
568
        // Boolean
569
        col++;
570
        cell = CellUtil.getCell(destRow1, col);
571
        assertEquals("[Boolean] F10 cell type", Cell.CELL_TYPE_BOOLEAN, cell.getCellType());
572
        assertEquals("[Boolean] F10 cell value", true, cell.getBooleanCellValue());
573
        
574
        cell = CellUtil.getCell(destRow2, col);
575
        assertEquals("[Boolean] F11 cell type", Cell.CELL_TYPE_BOOLEAN, cell.getCellType());
576
        assertEquals("[Boolean] F11 cell value", false, cell.getBooleanCellValue());
577
        
578
        // String
579
        col++;
580
        cell = CellUtil.getCell(destRow1, col);
581
        assertEquals("[String] G10 cell type", Cell.CELL_TYPE_STRING, cell.getCellType());
582
        assertEquals("[String] G10 cell value", "Hello", cell.getStringCellValue());
583
        
584
        cell = CellUtil.getCell(destRow2, col);
585
        assertEquals("[String] G11 cell type", Cell.CELL_TYPE_STRING, cell.getCellType());
586
        assertEquals("[String] G11 cell value", "World", cell.getStringCellValue());
587
        
588
        // Int
589
        col++;
590
        cell = CellUtil.getCell(destRow1, col);
591
        assertEquals("[Int] H10 cell type", Cell.CELL_TYPE_NUMERIC, cell.getCellType());
592
        assertEquals("[Int] H10 cell value", 15, (int) cell.getNumericCellValue());
593
        
594
        cell = CellUtil.getCell(destRow2, col);
595
        assertEquals("[Int] H11 cell type", Cell.CELL_TYPE_NUMERIC, cell.getCellType());
596
        assertEquals("[Int] H11 cell value", 42, (int) cell.getNumericCellValue());
597
        
598
        // Float
599
        col++;
600
        cell = CellUtil.getCell(destRow1, col);
601
        assertEquals("[Float] I10 cell type", Cell.CELL_TYPE_NUMERIC, cell.getCellType());
602
        assertEquals("[Float] I10 cell value", 12.5, cell.getNumericCellValue(), FLOAT_PRECISION);
603
        
604
        cell = CellUtil.getCell(destRow2, col);
605
        assertEquals("[Float] I11 cell type", Cell.CELL_TYPE_NUMERIC, cell.getCellType());
606
        assertEquals("[Float] I11 cell value", 5.5, cell.getNumericCellValue(), FLOAT_PRECISION);
607
        
608
        // Cell Formula
609
        col++;
610
        cell = CellUtil.getCell(destRow1, col);
611
        assertEquals("[Cell Formula] J10 cell type", Cell.CELL_TYPE_FORMULA, cell.getCellType());
612
        assertEquals("[Cell Formula] J10 cell formula", "5+2", cell.getCellFormula());
613
        // FIXME: formula evaluation
614
        System.out.println("Cell formula evaluation currently unsupported");
615
        //assertEquals(7.0, cell.getNumericCellValue(), FLOAT_PRECISION);
616
        
617
        cell = CellUtil.getCell(destRow2, col);
618
        assertEquals("[Cell Formula] J11 cell type", Cell.CELL_TYPE_FORMULA, cell.getCellType());
619
        assertEquals("[Cell Formula] J11 cell formula", "6+18", cell.getCellFormula());
620
        // FIXME: formula evaluation
621
        //assertEquals("[Cell Formula] J11 cell formula result", 24.0, cell.getNumericCellValue(), FLOAT_PRECISION);
622
        
623
        // Cell Formula with Reference
624
        col++;
625
        // Formula row references should be adjusted by destRowNum-srcRowNum
626
        cell = CellUtil.getCell(destRow1, col);
627
        assertEquals("[Cell Formula with Reference] K10 cell type",
628
                Cell.CELL_TYPE_FORMULA, cell.getCellType());
629
        assertEquals("[Cell Formula with Reference] K10 cell formula",
630
                "J10+H$2", cell.getCellFormula());
631
        // FIXME: formula evaluation
632
        //assertEquals("[Cell Formula with Reference] K10 cell formula result",
633
        //        22.0, cell.getNumericCellValue(), FLOAT_PRECISION);
634
        
635
        cell = CellUtil.getCell(destRow2, col);
636
        assertEquals("[Cell Formula with Reference] K11 cell type", Cell.CELL_TYPE_FORMULA, cell.getCellType());
637
        assertEquals("[Cell Formula with Reference] K11 cell formula", "J11+H$2", cell.getCellFormula());
638
        // FIXME: formula evaluation
639
        //assertEquals("[Cell Formula with Reference] K11 cell formula result",
640
        //        39.0, cell.getNumericCellValue(), FLOAT_PRECISION);
641
        
642
        // Cell Formula with Reference spanning multiple rows
643
        col++;
644
        cell = CellUtil.getCell(destRow1, col);
645
        assertEquals("[Cell Formula with Reference spanning multiple rows] L10 cell type",
646
                Cell.CELL_TYPE_FORMULA, cell.getCellType());
647
        assertEquals("[Cell Formula with Reference spanning multiple rows] L10 cell formula",
648
                "G10&\" \"&G11", cell.getCellFormula());
649
        // FIXME: Formula should be evaluated
650
        //assertEquals("[Cell Formula with Reference spanning multiple rows] L11 cell formula result",
651
        //        "Hello World", cell.getStringCellValue());
652
        
653
        cell = CellUtil.getCell(destRow2, col);
654
        assertEquals("[Cell Formula with Reference spanning multiple rows] L11 cell type",
655
                Cell.CELL_TYPE_FORMULA, cell.getCellType());
656
        assertEquals("[Cell Formula with Reference spanning multiple rows] L11 cell formula",
657
                "G11&\" \"&G12", cell.getCellFormula());
658
        // FIXME: Formula should be evaluated
659
        //assertEquals("[Cell Formula with Reference spanning multiple rows] L11 cell formula result",
660
        //        "World ", cell.getStringCellValue());
661
        
662
        // Cell Formula with Area Reference
663
        col++;
664
        cell = CellUtil.getCell(destRow1, col);
665
        assertEquals("[Cell Formula with Area Reference] M10 cell type",
666
                Cell.CELL_TYPE_FORMULA, cell.getCellType());
667
        assertEquals("[Cell Formula with Area Reference] M10 cell formula",
668
                "SUM(H10:I11)", cell.getCellFormula());
669
        // FIXME: Formula should be evaluated
670
        //assertEquals("[Cell Formula with Area Reference] M10 cell formula result",
671
        //        "Hello World", cell.getStringCellValue());
672
        
673
        cell = CellUtil.getCell(destRow2, col);
674
        assertEquals("[Cell Formula with Area Reference] M11 cell type",
675
                Cell.CELL_TYPE_FORMULA, cell.getCellType());
676
        assertEquals("[Cell Formula with Area Reference] M11 cell formula",
677
                "SUM($H$3:I10)", cell.getCellFormula()); //Also acceptable: SUM($H10:I$3), but this AreaReference isn't in ascending order
678
        // FIXME: Formula should be evaluated
679
        //assertEquals("[Cell Formula with Area Reference] M11 cell formula result",
680
        //        "World ", cell.getStringCellValue());
681
        
682
        // Array Formula
683
        col++;
684
        cell = CellUtil.getCell(destRow1, col);
685
        System.out.println("Array formulas currently unsupported");
686
    /*
687
        // FIXME: Array Formula set with Sheet.setArrayFormula() instead of cell.setFormula()
688
        assertEquals("[Array Formula] N10 cell type", Cell.CELL_TYPE_FORMULA, cell.getCellType());
689
        assertEquals("[Array Formula] N10 cell formula", "{SUM(H10:J10*{1,2,3})}", cell.getCellFormula());
690
        // FIXME: Formula should be evaluated
691
        assertEquals("[Array Formula] N10 cell formula result", 61.0, cell.getNumericCellValue(), FLOAT_PRECISION);
692
        
693
        cell = CellUtil.getCell(destRow2, col);
694
        // FIXME: Array Formula set with Sheet.setArrayFormula() instead of cell.setFormula() 
695
        assertEquals("[Array Formula] N11 cell type", Cell.CELL_TYPE_FORMULA, cell.getCellType());
696
        assertEquals("[Array Formula] N11 cell formula", "{SUM(H11:J11*{1,2,3})}", cell.getCellFormula());
697
        // FIXME: Formula should be evaluated
698
        assertEquals("[Array Formula] N11 cell formula result", 125.0, cell.getNumericCellValue(), FLOAT_PRECISION);
699
     */
700
        
701
        // Data Format
702
        col++;
703
        cell = CellUtil.getCell(destRow2, col);
704
        assertEquals("[Data Format] O10 cell type", Cell.CELL_TYPE_NUMERIC, cell.getCellType());
705
        assertEquals("[Data Format] O10 cell value", 100.20, cell.getNumericCellValue(), FLOAT_PRECISION);
706
        final String moneyFormat = "\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)";
707
        assertEquals("[Data Format] O10 cell data format", moneyFormat, cell.getCellStyle().getDataFormatString());
708
        
709
        // Merged
710
        col++;
711
        cell = CellUtil.getCell(destRow1, col);
712
        assertEquals("[Merged] P10:Q10 cell value",
713
                "Merged cells", cell.getStringCellValue());
714
        assertTrue("[Merged] P10:Q10 merged region",
715
                sheet.getMergedRegions().contains(CellRangeAddress.valueOf("P10:Q10")));
716
        
717
        cell = CellUtil.getCell(destRow2, col);
718
        assertEquals("[Merged] P11:Q11 cell value", "Merged cells", cell.getStringCellValue());
719
        assertTrue("[Merged] P11:Q11 merged region",
720
                sheet.getMergedRegions().contains(CellRangeAddress.valueOf("P11:Q11")));
721
        
722
        // Should Q10/Q11 be checked?
723
        
724
        // Merged across multiple rows
725
        // Microsoft Excel 2013 does not copy a merged region unless all rows of
726
        // the source merged region are selected
727
        // POI's behavior should match this behavior
728
        col += 2;
729
        cell = CellUtil.getCell(destRow1, col);
730
        assertEquals("[Merged across multiple rows] R10:S11 cell value", 
731
                "Merged cells across multiple rows", cell.getStringCellValue());
732
        assertTrue("[Merged across multiple rows] R10:S11 merged region", 
733
                sheet.getMergedRegions().contains(CellRangeAddress.valueOf("R10:S11")));
734
        
735
        // Row 3 (zero-based) was empty, so Row 11 (zero-based) should be empty too.
736
        if (srcRow3 == null) {
737
            assertNull("Row 3 was empty, so Row 11 should be empty", destRow3);
738
        }
739
        
740
        // Make sure other rows are blank (off-by-one errors)
741
        assertNull("Off-by-one lower edge case", sheet.getRow(7)); //one row above destHeaderRow
742
        assertNull("Off-by-one upper edge case", sheet.getRow(12)); //one row below destRow3
743
    }
744
352
    /**
745
    /**
353
     * Tests the display of gridlines, formulas, and rowcolheadings.
746
     * Tests the display of gridlines, formulas, and rowcolheadings.
354
     * @author Shawn Laubach (slaubach at apache dot org)
747
     * @author Shawn Laubach (slaubach at apache dot org)
Lines 996-999 Link Here
996
        
1389
        
997
        wb.close();
1390
        wb.close();
998
    }
1391
    }
1392
    
1393
    
999
}
1394
}
(-)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 810-813 Link Here
810
		}
812
		}
811
		wb.close();
813
		wb.close();
812
	}
814
	}
815
	
816
    
817
    private Cell srcCell, destCell; //used for testCopyCellFrom_CellCopyPolicy
818
    
819
    @Test
820
    public final void testCopyCellFrom_CellCopyPolicy_default() {
821
        if (!_testDataProvider.getClass().getName().equals("org.apache.poi.xssf.XSSFITestDataProvider")) return; //TODO: enable this for HSSFCell and SXSSFCell tests
822
        setUp_testCopyCellFrom_CellCopyPolicy();
823
        
824
        // default copy policy
825
        final CellCopyPolicy policy = new CellCopyPolicy();
826
        destCell.copyCellFrom(srcCell, policy);
827
        
828
        assertEquals(Cell.CELL_TYPE_FORMULA, destCell.getCellType());
829
        assertEquals("2+3", destCell.getCellFormula());
830
        assertEquals(srcCell.getCellStyle(), destCell.getCellStyle());
831
    }
832
    
833
    @Test
834
    public final void testCopyCellFrom_CellCopyPolicy_value() {
835
        if (!_testDataProvider.getClass().getName().equals("org.apache.poi.xssf.XSSFITestDataProvider")) return; //TODO: enable this for HSSFCell and SXSSFCell tests
836
        setUp_testCopyCellFrom_CellCopyPolicy();
837
        
838
        // Paste values only
839
        final CellCopyPolicy policy = new CellCopyPolicy.Builder().cellFormula(false).build();
840
        destCell.copyCellFrom(srcCell, policy);
841
        assertEquals(Cell.CELL_TYPE_NUMERIC, destCell.getCellType());
842
        System.out.println("ERROR: fix formula evaluation");
843
        //FIXME: the following assertion currently fails, since getNumericCellValue() returns 0 for unevaluated expressions
844
        //assertEquals(5, (int) destCell.getNumericCellValue());
845
    }
846
    
847
    @Test
848
    public final void testCopyCellFrom_CellCopyPolicy_style() {
849
        if (!_testDataProvider.getClass().getName().equals("org.apache.poi.xssf.XSSFITestDataProvider")) return; //TODO: enable this for HSSFCell and SXSSFCell tests
850
        setUp_testCopyCellFrom_CellCopyPolicy();
851
        srcCell.setCellValue((String) null);
852
        
853
        // Paste styles only
854
        final CellCopyPolicy policy = new CellCopyPolicy.Builder().cellValue(false).build();
855
        destCell.copyCellFrom(srcCell, policy);
856
        assertEquals(srcCell.getCellStyle(), destCell.getCellStyle());
857
        
858
        // Old cell value should not have been overwritten
859
        assertNotEquals(Cell.CELL_TYPE_BLANK, destCell.getCellType());
860
        assertEquals(Cell.CELL_TYPE_BOOLEAN, destCell.getCellType());
861
        assertEquals(true, destCell.getBooleanCellValue());
862
    }
863
    
864
    private final void setUp_testCopyCellFrom_CellCopyPolicy() {
865
        final Workbook wb = _testDataProvider.createWorkbook();
866
        final Row row = wb.createSheet().createRow(0);
867
        srcCell = row.createCell(0);
868
        destCell = row.createCell(1);
869
        
870
        srcCell.setCellFormula("2+3");
871
        
872
        final CellStyle style = wb.createCellStyle();
873
        style.setBorderTop(CellStyle.BORDER_THICK);
874
        style.setFillBackgroundColor((short) 5);
875
        srcCell.setCellStyle(style);
876
        
877
        destCell.setCellValue(true);
878
    }
813
}
879
}
(-)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
}

Return to bug 58348