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

(-)src/java/org/apache/poi/hssf/record/chart/ChartEndBlockRecord.java (+15 lines)
Lines 35-40 Link Here
35
	private short iObjectKind;
35
	private short iObjectKind;
36
	private byte[] unused;
36
	private byte[] unused;
37
37
38
	public ChartEndBlockRecord() {
39
	}
40
	
38
	public ChartEndBlockRecord(RecordInputStream in) {
41
	public ChartEndBlockRecord(RecordInputStream in) {
39
		rt = in.readShort();
42
		rt = in.readShort();
40
		grbitFrt = in.readShort();
43
		grbitFrt = in.readShort();
Lines 80-83 Link Here
80
		buffer.append("[/ENDBLOCK]\n");
83
		buffer.append("[/ENDBLOCK]\n");
81
		return buffer.toString();
84
		return buffer.toString();
82
	}
85
	}
86
	
87
	@Override
88
	public ChartEndBlockRecord clone() {
89
		ChartEndBlockRecord record = new ChartEndBlockRecord();
90
		
91
		record.rt = rt ;
92
		record.grbitFrt = grbitFrt ;
93
		record.iObjectKind = iObjectKind ;
94
		record.unused = unused.clone() ;
95
		
96
		return record;
97
	}
83
}
98
}
(-)src/java/org/apache/poi/hssf/record/chart/ChartStartBlockRecord.java (+17 lines)
Lines 37-42 Link Here
37
	private short iObjectInstance1;
37
	private short iObjectInstance1;
38
	private short iObjectInstance2;
38
	private short iObjectInstance2;
39
39
40
	public ChartStartBlockRecord() {
41
	}
42
	
40
	public ChartStartBlockRecord(RecordInputStream in) {
43
	public ChartStartBlockRecord(RecordInputStream in) {
41
		rt = in.readShort();
44
		rt = in.readShort();
42
		grbitFrt = in.readShort();
45
		grbitFrt = in.readShort();
Lines 80-83 Link Here
80
		buffer.append("[/STARTBLOCK]\n");
83
		buffer.append("[/STARTBLOCK]\n");
81
		return buffer.toString();
84
		return buffer.toString();
82
	}
85
	}
86
	
87
	@Override
88
	public ChartStartBlockRecord clone() {
89
		ChartStartBlockRecord record = new ChartStartBlockRecord();
90
		
91
		record.rt = rt;
92
		record.grbitFrt = grbitFrt;
93
		record.iObjectKind = iObjectKind;
94
		record.iObjectContext = iObjectContext;
95
		record.iObjectInstance1 = iObjectInstance1;
96
		record.iObjectInstance2 = iObjectInstance2;
97
		
98
		return record;
99
	}
83
}
100
}
(-)src/java/org/apache/poi/hssf/record/RecordFactory.java (+1 lines)
Lines 221-226 Link Here
221
		WriteAccessRecord.class,
221
		WriteAccessRecord.class,
222
		WriteProtectRecord.class,
222
		WriteProtectRecord.class,
223
		WSBoolRecord.class,
223
		WSBoolRecord.class,
224
		DataFormatRecord.class,
224
225
225
		// chart records
226
		// chart records
226
		BeginRecord.class,
227
		BeginRecord.class,
(-)src/java/org/apache/poi/ss/util/CellRangeAddressBase.java (-2 / +2 lines)
Lines 27-40 Link Here
27
 *
27
 *
28
 * @author Josh Micich
28
 * @author Josh Micich
29
 */
29
 */
30
public abstract class CellRangeAddressBase {
30
public class CellRangeAddressBase {
31
31
32
	private int _firstRow;
32
	private int _firstRow;
33
	private int _firstCol;
33
	private int _firstCol;
34
	private int _lastRow;
34
	private int _lastRow;
35
	private int _lastCol;
35
	private int _lastCol;
36
36
37
	protected CellRangeAddressBase(int firstRow, int lastRow, int firstCol, int lastCol) {
37
	public CellRangeAddressBase(int firstRow, int lastRow, int firstCol, int lastCol) {
38
		_firstRow = firstRow;
38
		_firstRow = firstRow;
39
		_lastRow = lastRow;
39
		_lastRow = lastRow;
40
		_firstCol = firstCol;
40
		_firstCol = firstCol;
(-)src/scratchpad/src/org/apache/poi/hssf/usermodel/HSSFChart.java (-18 / +359 lines)
Lines 18-23 Link Here
18
package org.apache.poi.hssf.usermodel;
18
package org.apache.poi.hssf.usermodel;
19
19
20
import java.util.ArrayList;
20
import java.util.ArrayList;
21
import java.util.Iterator;
21
import java.util.List;
22
import java.util.List;
22
23
23
import org.apache.poi.hssf.record.chart.*;
24
import org.apache.poi.hssf.record.chart.*;
Lines 35-42 Link Here
35
import org.apache.poi.hssf.record.UnknownRecord;
36
import org.apache.poi.hssf.record.UnknownRecord;
36
import org.apache.poi.hssf.record.VCenterRecord;
37
import org.apache.poi.hssf.record.VCenterRecord;
37
import org.apache.poi.hssf.record.formula.Area3DPtg;
38
import org.apache.poi.hssf.record.formula.Area3DPtg;
39
import org.apache.poi.hssf.record.formula.AreaPtgBase;
38
import org.apache.poi.hssf.record.formula.Ptg;
40
import org.apache.poi.hssf.record.formula.Ptg;
39
import org.apache.poi.hssf.record.chart.LinkedDataRecord;
41
import org.apache.poi.ss.util.CellRangeAddressBase;
40
42
41
/**
43
/**
42
 * Has methods for construction of a chart object.
44
 * Has methods for construction of a chart object.
Lines 44-49 Link Here
44
 * @author Glen Stampoultzis (glens at apache.org)
46
 * @author Glen Stampoultzis (glens at apache.org)
45
 */
47
 */
46
public final class HSSFChart {
48
public final class HSSFChart {
49
	private HSSFSheet sheet;
47
	private ChartRecord chartRecord;
50
	private ChartRecord chartRecord;
48
51
49
	private LegendRecord legendRecord;
52
	private LegendRecord legendRecord;
Lines 51-60 Link Here
51
	private SeriesTextRecord chartTitleText;
54
	private SeriesTextRecord chartTitleText;
52
	private List<ValueRangeRecord> valueRanges = new ArrayList<ValueRangeRecord>(); 
55
	private List<ValueRangeRecord> valueRanges = new ArrayList<ValueRangeRecord>(); 
53
	
56
	
57
	private HSSFChartType type = HSSFChartType.Unknown;
58
	
54
	private List<HSSFSeries> series = new ArrayList<HSSFSeries>();
59
	private List<HSSFSeries> series = new ArrayList<HSSFSeries>();
55
60
56
	private HSSFChart(ChartRecord chartRecord) {
61
	public enum HSSFChartType {
62
		Area {
63
			@Override
64
			public short getSid() {
65
				return 0x101A;
66
			}
67
		},
68
		Bar {
69
			@Override
70
			public short getSid() {
71
				return 0x1017;
72
			}
73
		},
74
		Line {
75
			@Override
76
			public short getSid() {
77
				return 0x1018;
78
			}
79
		},
80
		Pie {
81
			@Override
82
			public short getSid() {
83
				return 0x1019;
84
			}
85
		},
86
		Scatter {
87
			@Override
88
			public short getSid() {
89
				return 0x101B;
90
			}
91
		},
92
		Unknown {
93
			@Override
94
			public short getSid() {
95
				return 0;
96
			}
97
		};
98
		
99
		public abstract short getSid();
100
	}
101
102
	private HSSFChart(HSSFSheet sheet, ChartRecord chartRecord) {
57
		this.chartRecord = chartRecord;
103
		this.chartRecord = chartRecord;
104
		this.sheet = sheet;
58
	}
105
	}
59
106
60
	/**
107
	/**
Lines 146-167 Link Here
146
		for(RecordBase r : records) {
193
		for(RecordBase r : records) {
147
194
148
			if(r instanceof ChartRecord) {
195
			if(r instanceof ChartRecord) {
149
				lastChart = new HSSFChart((ChartRecord)r);
196
				lastSeries = null;
197
				
198
				lastChart = new HSSFChart(sheet,(ChartRecord)r);
150
				charts.add(lastChart);
199
				charts.add(lastChart);
151
			}
200
			} else if(r instanceof LegendRecord) {
152
			if(r instanceof LegendRecord) {
153
				lastChart.legendRecord = (LegendRecord)r;
201
				lastChart.legendRecord = (LegendRecord)r;
154
			}
202
			} else if(r instanceof SeriesRecord) {
155
			if(r instanceof SeriesRecord) {
156
				HSSFSeries series = lastChart.new HSSFSeries( (SeriesRecord)r );
203
				HSSFSeries series = lastChart.new HSSFSeries( (SeriesRecord)r );
157
				lastChart.series.add(series);
204
				lastChart.series.add(series);
158
				lastSeries = series;
205
				lastSeries = series;
159
			}
206
			} else if(r instanceof ChartTitleFormatRecord) {
160
			if(r instanceof ChartTitleFormatRecord) {
161
				lastChart.chartTitleFormat =
207
				lastChart.chartTitleFormat =
162
					(ChartTitleFormatRecord)r;
208
					(ChartTitleFormatRecord)r;
163
			}
209
			} else if(r instanceof SeriesTextRecord) {
164
			if(r instanceof SeriesTextRecord) {
165
				// Applies to a series, unless we've seen
210
				// Applies to a series, unless we've seen
166
				//  a legend already
211
				//  a legend already
167
				SeriesTextRecord str = (SeriesTextRecord)r;
212
				SeriesTextRecord str = (SeriesTextRecord)r;
Lines 173-185 Link Here
173
				} else {
218
				} else {
174
					lastChart.chartTitleText = str;
219
					lastChart.chartTitleText = str;
175
				}
220
				}
176
			}
221
			} else if (r instanceof LinkedDataRecord) {
177
			if(r instanceof LinkedDataRecord) {
222
				LinkedDataRecord linkedDataRecord = (LinkedDataRecord) r;
178
				LinkedDataRecord data = (LinkedDataRecord)r;
223
				if (lastSeries != null) {
179
				lastSeries.insertData( data );
224
					lastSeries.insertData(linkedDataRecord);
180
			}
225
				}
181
			if(r instanceof ValueRangeRecord){
226
			} else if(r instanceof ValueRangeRecord){
182
				lastChart.valueRanges.add((ValueRangeRecord)r);
227
				lastChart.valueRanges.add((ValueRangeRecord)r);
228
			} else if (r instanceof Record) {
229
				if (lastChart != null)
230
				{
231
					Record record = (Record) r;
232
					for (HSSFChartType type : HSSFChartType.values()) {
233
						if (type == HSSFChartType.Unknown)
234
						{
235
							continue;
236
						}
237
						if (record.getSid() == type.getSid()) {
238
							lastChart.type = type ;
239
							break;
240
						}
241
					}
242
				}
183
			}
243
			}
184
		}
244
		}
185
245
Lines 914-920 Link Here
914
			this.series = series;
974
			this.series = series;
915
		}
975
		}
916
976
917
		public void insertData(LinkedDataRecord data){
977
		/* package */ void insertData(LinkedDataRecord data){
918
			switch(dataReaded){
978
			switch(dataReaded){
919
				case 0: dataName = data;
979
				case 0: dataName = data;
920
				break;
980
				break;
Lines 928-933 Link Here
928
			dataReaded++;
988
			dataReaded++;
929
		}
989
		}
930
		
990
		
991
		/* package */ void setSeriesTitleText(SeriesTextRecord seriesTitleText)
992
		{
993
			this.seriesTitleText = seriesTitleText;
994
		}
995
		
931
		public short getNumValues() {
996
		public short getNumValues() {
932
			return series.getNumValues();
997
			return series.getNumValues();
933
		}
998
		}
Lines 996-1000 Link Here
996
		public SeriesRecord getSeries() {
1061
		public SeriesRecord getSeries() {
997
			return series;
1062
			return series;
998
		}
1063
		}
1064
		
1065
		private CellRangeAddressBase getCellRange(LinkedDataRecord linkedDataRecord) {
1066
			if (linkedDataRecord == null)
1067
			{
1068
				return null ;
1069
			}
1070
			
1071
			int firstRow = 0;
1072
			int lastRow = 0;
1073
			int firstCol = 0;
1074
			int lastCol = 0;
1075
			
1076
			for (Ptg ptg : linkedDataRecord.getFormulaOfLink()) {
1077
				if (ptg instanceof AreaPtgBase) {
1078
					AreaPtgBase areaPtg = (AreaPtgBase) ptg;
1079
					
1080
					firstRow = areaPtg.getFirstRow();
1081
					lastRow = areaPtg.getLastRow();
1082
					
1083
					firstCol = areaPtg.getFirstColumn();
1084
					lastCol = areaPtg.getLastColumn();
1085
				}
1086
			}
1087
			
1088
			return new CellRangeAddressBase(firstRow, lastRow, firstCol, lastCol);
1089
		}
1090
		
1091
		public CellRangeAddressBase getValuesCellRange() {
1092
			return getCellRange(dataValues);
1093
		}
1094
	
1095
		public CellRangeAddressBase getCategoryLabelsCellRange() {
1096
			return getCellRange(dataCategoryLabels);
1097
		}
1098
	
1099
		private Integer setVerticalCellRange(LinkedDataRecord linkedDataRecord,
1100
				                             CellRangeAddressBase range) {
1101
			if (linkedDataRecord == null)
1102
			{
1103
				return null;
1104
			}
1105
			
1106
			List<Ptg> ptgList = new ArrayList<Ptg>();
1107
			
1108
			int rowCount = (range.getLastRow() - range.getFirstRow()) + 1;
1109
			int colCount = (range.getLastColumn() - range.getFirstColumn()) + 1;
1110
			
1111
			for (Ptg ptg : linkedDataRecord.getFormulaOfLink()) {
1112
				if (ptg instanceof AreaPtgBase) {
1113
					AreaPtgBase areaPtg = (AreaPtgBase) ptg;
1114
					
1115
					areaPtg.setFirstRow(range.getFirstRow());
1116
					areaPtg.setLastRow(range.getLastRow());
1117
					
1118
					areaPtg.setFirstColumn(range.getFirstColumn());
1119
					areaPtg.setLastColumn(range.getLastColumn());
1120
					ptgList.add(areaPtg);
1121
				}
1122
			}
1123
			
1124
			linkedDataRecord.setFormulaOfLink(ptgList.toArray(new Ptg[ptgList.size()]));
1125
			
1126
			return rowCount * colCount;
1127
		}
1128
		
1129
		public void setValuesCellRange(CellRangeAddressBase range) {
1130
			Integer count = setVerticalCellRange(dataValues, range);
1131
			if (count == null)
1132
			{
1133
				return;
1134
			}
1135
			
1136
			series.setNumValues((short)(int)count);
1137
		}
1138
		
1139
		public void setCategoryLabelsCellRange(CellRangeAddressBase range) {
1140
			Integer count = setVerticalCellRange(dataCategoryLabels, range);
1141
			if (count == null)
1142
			{
1143
				return;
1144
			}
1145
			
1146
			series.setNumCategories((short)(int)count);
1147
		}
999
	}
1148
	}
1149
	
1150
	public HSSFSeries createSeries() throws Exception {
1151
		ArrayList<RecordBase> seriesTemplate = new ArrayList<RecordBase>();
1152
		boolean seriesTemplateFilled = false;
1153
		
1154
		int idx = 0;
1155
		int deep = 0;
1156
		int chartRecordIdx = -1;
1157
		int chartDeep = -1;
1158
		int lastSeriesDeep = -1;
1159
		int endSeriesRecordIdx = -1;
1160
		int seriesIdx = 0;
1161
		final List<RecordBase> records = sheet.getSheet().getRecords();
1162
		
1163
		/* store first series as template and find last series index */
1164
		for(final RecordBase record : records) {		
1165
			
1166
			idx++;
1167
			
1168
			if (record instanceof BeginRecord) {
1169
				deep++;
1170
			} else if (record instanceof EndRecord) {
1171
				deep--;
1172
				
1173
				if (lastSeriesDeep == deep) {
1174
					lastSeriesDeep = -1;
1175
					endSeriesRecordIdx = idx;
1176
					if (!seriesTemplateFilled) {
1177
						seriesTemplate.add(record);
1178
						seriesTemplateFilled = true;
1179
					}
1180
				}
1181
				
1182
				if (chartDeep == deep) {
1183
					break;
1184
				}
1185
			}
1186
			
1187
			if (record instanceof ChartRecord) {
1188
				if (record == chartRecord) {
1189
					chartRecordIdx = idx;
1190
					chartDeep = deep;
1191
				}
1192
			} else if (record instanceof SeriesRecord) {
1193
				if (chartRecordIdx != -1) {
1194
					seriesIdx++;
1195
					lastSeriesDeep = deep;
1196
				}
1197
			}
1198
			
1199
			if (lastSeriesDeep != -1 && !seriesTemplateFilled) {
1200
				seriesTemplate.add(record) ;
1201
			}
1202
		}
1203
		
1204
		/* check if a series was found */
1205
		if (endSeriesRecordIdx == -1) {
1206
			return null;
1207
		}
1208
		
1209
		/* next index in the records list where the new series can be inserted */
1210
		idx = endSeriesRecordIdx + 1;
1211
1212
		HSSFSeries newSeries = null;
1213
		
1214
		/* duplicate record of the template series */
1215
		ArrayList<RecordBase> clonedRecords = new ArrayList<RecordBase>();
1216
		for(final RecordBase record : seriesTemplate) {		
1217
			
1218
			Record newRecord = null;
1219
			
1220
			if (record instanceof BeginRecord) {
1221
				newRecord = new BeginRecord();
1222
			} else if (record instanceof EndRecord) {
1223
				newRecord = new EndRecord();
1224
			} else if (record instanceof SeriesRecord) {
1225
				SeriesRecord seriesRecord = (SeriesRecord) ((SeriesRecord)record).clone();
1226
				newSeries = new HSSFSeries(seriesRecord);
1227
				newRecord = seriesRecord;
1228
			} else if (record instanceof LinkedDataRecord) {
1229
				LinkedDataRecord linkedDataRecord = (LinkedDataRecord) ((LinkedDataRecord)record).clone();
1230
				if (newSeries != null) {
1231
					newSeries.insertData(linkedDataRecord);
1232
				}
1233
				newRecord = linkedDataRecord;
1234
			} else if (record instanceof DataFormatRecord) {
1235
				DataFormatRecord dataFormatRecord = (DataFormatRecord) ((DataFormatRecord)record).clone();
1236
				
1237
				dataFormatRecord.setSeriesIndex((short)seriesIdx) ;
1238
				dataFormatRecord.setSeriesNumber((short)seriesIdx) ;
1239
				
1240
				newRecord = dataFormatRecord;
1241
			} else if (record instanceof SeriesTextRecord) {
1242
				SeriesTextRecord seriesTextRecord = (SeriesTextRecord) ((SeriesTextRecord)record).clone();
1243
				if (newSeries != null) {
1244
					newSeries.setSeriesTitleText(seriesTextRecord);
1245
				}
1246
				newRecord = seriesTextRecord;
1247
			} else if (record instanceof Record) {
1248
				newRecord = (Record) ((Record)record).clone();
1249
			}
1250
			
1251
			if (newRecord != null)
1252
			{
1253
				clonedRecords.add(newRecord);
1254
			}
1255
		}
1256
		
1257
		/* check if a user model series object was created */
1258
		if (newSeries == null)
1259
		{
1260
			return null;
1261
		}
1262
		
1263
		/* transfer series to record list */
1264
		for(final RecordBase record : clonedRecords) {		
1265
			records.add(idx++, record);
1266
		}
1267
		
1268
		return newSeries;
1269
	}
1270
	
1271
	public boolean removeSeries(HSSFSeries series) {
1272
		int idx = 0;
1273
		int deep = 0;
1274
		int chartDeep = -1;
1275
		int lastSeriesDeep = -1;
1276
		int seriesIdx = -1;
1277
		boolean removeSeries = false;
1278
		boolean chartEntered = false;
1279
		boolean result = false;
1280
		final List<RecordBase> records = sheet.getSheet().getRecords();
1281
		
1282
		/* store first series as template and find last series index */
1283
		Iterator<RecordBase> iter = records.iterator();
1284
		while (iter.hasNext()) {		
1285
			RecordBase record = iter.next();
1286
			idx++;
1287
			
1288
			if (record instanceof BeginRecord) {
1289
				deep++;
1290
			} else if (record instanceof EndRecord) {
1291
				deep--;
1292
				
1293
				if (lastSeriesDeep == deep) {
1294
					lastSeriesDeep = -1;
1295
					
1296
					if (removeSeries) {
1297
						removeSeries = false;
1298
						result = true;
1299
						iter.remove();
1300
					}
1301
				}
1302
				
1303
				if (chartDeep == deep) {
1304
					break;
1305
				}
1306
			}
1307
			
1308
			if (record instanceof ChartRecord) {
1309
				if (record == chartRecord) {
1310
					chartDeep = deep;
1311
					chartEntered = true;
1312
				}
1313
			} else if (record instanceof SeriesRecord) {
1314
				if (chartEntered) {
1315
					if (series.series == record) {
1316
						lastSeriesDeep = deep;
1317
						removeSeries = true;
1318
					} else {
1319
						seriesIdx++;
1320
					}
1321
				}
1322
			} else if (record instanceof DataFormatRecord) {
1323
				if (chartEntered && !removeSeries) {
1324
					DataFormatRecord dataFormatRecord = (DataFormatRecord) record;
1325
					dataFormatRecord.setSeriesIndex((short) seriesIdx);
1326
					dataFormatRecord.setSeriesNumber((short) seriesIdx);
1327
				}
1328
			}
1329
			
1330
			if (removeSeries) {
1331
				iter.remove();
1332
			}
1333
		}
1334
		
1335
		return result;
1336
	}
1337
	
1338
	public HSSFChartType getType() {
1339
		return type;
1340
	}
1000
}
1341
}

Return to bug 49581