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 (-21 / +360 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 908-921 Link Here
908
		private LinkedDataRecord dataValues;
968
		private LinkedDataRecord dataValues;
909
		private LinkedDataRecord dataCategoryLabels;
969
		private LinkedDataRecord dataCategoryLabels;
910
		private LinkedDataRecord dataSecondaryCategoryLabels;
970
		private LinkedDataRecord dataSecondaryCategoryLabels;
911
		private int dataReaded = 0;
912
971
913
		/* package */ HSSFSeries(SeriesRecord series) {
972
		/* package */ HSSFSeries(SeriesRecord series) {
914
			this.series = series;
973
			this.series = series;
915
		}
974
		}
916
975
917
		public void insertData(LinkedDataRecord data){
976
		/* package */ void insertData(LinkedDataRecord data){
918
			switch(dataReaded){
977
			switch(data.getLinkType()){
919
				case 0: dataName = data;
978
				case 0: dataName = data;
920
				break;
979
				break;
921
				case 1: dataValues = data;
980
				case 1: dataValues = data;
Lines 925-933 Link Here
925
				case 3: dataSecondaryCategoryLabels = data;
984
				case 3: dataSecondaryCategoryLabels = data;
926
				break;
985
				break;
927
			}
986
			}
928
			dataReaded++;
929
		}
987
		}
930
		
988
		
989
		/* package */ void setSeriesTitleText(SeriesTextRecord seriesTitleText)
990
		{
991
			this.seriesTitleText = seriesTitleText;
992
		}
993
		
931
		public short getNumValues() {
994
		public short getNumValues() {
932
			return series.getNumValues();
995
			return series.getNumValues();
933
		}
996
		}
Lines 996-1000 Link Here
996
		public SeriesRecord getSeries() {
1059
		public SeriesRecord getSeries() {
997
			return series;
1060
			return series;
998
		}
1061
		}
1062
		
1063
		private CellRangeAddressBase getCellRange(LinkedDataRecord linkedDataRecord) {
1064
			if (linkedDataRecord == null)
1065
			{
1066
				return null ;
1067
			}
1068
			
1069
			int firstRow = 0;
1070
			int lastRow = 0;
1071
			int firstCol = 0;
1072
			int lastCol = 0;
1073
			
1074
			for (Ptg ptg : linkedDataRecord.getFormulaOfLink()) {
1075
				if (ptg instanceof AreaPtgBase) {
1076
					AreaPtgBase areaPtg = (AreaPtgBase) ptg;
1077
					
1078
					firstRow = areaPtg.getFirstRow();
1079
					lastRow = areaPtg.getLastRow();
1080
					
1081
					firstCol = areaPtg.getFirstColumn();
1082
					lastCol = areaPtg.getLastColumn();
1083
				}
1084
			}
1085
			
1086
			return new CellRangeAddressBase(firstRow, lastRow, firstCol, lastCol);
1087
		}
1088
		
1089
		public CellRangeAddressBase getValuesCellRange() {
1090
			return getCellRange(dataValues);
1091
		}
1092
	
1093
		public CellRangeAddressBase getCategoryLabelsCellRange() {
1094
			return getCellRange(dataCategoryLabels);
1095
		}
1096
	
1097
		private Integer setVerticalCellRange(LinkedDataRecord linkedDataRecord,
1098
				                             CellRangeAddressBase range) {
1099
			if (linkedDataRecord == null)
1100
			{
1101
				return null;
1102
			}
1103
			
1104
			List<Ptg> ptgList = new ArrayList<Ptg>();
1105
			
1106
			int rowCount = (range.getLastRow() - range.getFirstRow()) + 1;
1107
			int colCount = (range.getLastColumn() - range.getFirstColumn()) + 1;
1108
			
1109
			for (Ptg ptg : linkedDataRecord.getFormulaOfLink()) {
1110
				if (ptg instanceof AreaPtgBase) {
1111
					AreaPtgBase areaPtg = (AreaPtgBase) ptg;
1112
					
1113
					areaPtg.setFirstRow(range.getFirstRow());
1114
					areaPtg.setLastRow(range.getLastRow());
1115
					
1116
					areaPtg.setFirstColumn(range.getFirstColumn());
1117
					areaPtg.setLastColumn(range.getLastColumn());
1118
					ptgList.add(areaPtg);
1119
				}
1120
			}
1121
			
1122
			linkedDataRecord.setFormulaOfLink(ptgList.toArray(new Ptg[ptgList.size()]));
1123
			
1124
			return rowCount * colCount;
1125
		}
1126
		
1127
		public void setValuesCellRange(CellRangeAddressBase range) {
1128
			Integer count = setVerticalCellRange(dataValues, range);
1129
			if (count == null)
1130
			{
1131
				return;
1132
			}
1133
			
1134
			series.setNumValues((short)(int)count);
1135
		}
1136
		
1137
		public void setCategoryLabelsCellRange(CellRangeAddressBase range) {
1138
			Integer count = setVerticalCellRange(dataCategoryLabels, range);
1139
			if (count == null)
1140
			{
1141
				return;
1142
			}
1143
			
1144
			series.setNumCategories((short)(int)count);
1145
		}
999
	}
1146
	}
1147
	
1148
	public HSSFSeries createSeries() throws Exception {
1149
		ArrayList<RecordBase> seriesTemplate = new ArrayList<RecordBase>();
1150
		boolean seriesTemplateFilled = false;
1151
		
1152
		int idx = 0;
1153
		int deep = 0;
1154
		int chartRecordIdx = -1;
1155
		int chartDeep = -1;
1156
		int lastSeriesDeep = -1;
1157
		int endSeriesRecordIdx = -1;
1158
		int seriesIdx = 0;
1159
		final List<RecordBase> records = sheet.getSheet().getRecords();
1160
		
1161
		/* store first series as template and find last series index */
1162
		for(final RecordBase record : records) {		
1163
			
1164
			idx++;
1165
			
1166
			if (record instanceof BeginRecord) {
1167
				deep++;
1168
			} else if (record instanceof EndRecord) {
1169
				deep--;
1170
				
1171
				if (lastSeriesDeep == deep) {
1172
					lastSeriesDeep = -1;
1173
					endSeriesRecordIdx = idx;
1174
					if (!seriesTemplateFilled) {
1175
						seriesTemplate.add(record);
1176
						seriesTemplateFilled = true;
1177
					}
1178
				}
1179
				
1180
				if (chartDeep == deep) {
1181
					break;
1182
				}
1183
			}
1184
			
1185
			if (record instanceof ChartRecord) {
1186
				if (record == chartRecord) {
1187
					chartRecordIdx = idx;
1188
					chartDeep = deep;
1189
				}
1190
			} else if (record instanceof SeriesRecord) {
1191
				if (chartRecordIdx != -1) {
1192
					seriesIdx++;
1193
					lastSeriesDeep = deep;
1194
				}
1195
			}
1196
			
1197
			if (lastSeriesDeep != -1 && !seriesTemplateFilled) {
1198
				seriesTemplate.add(record) ;
1199
			}
1200
		}
1201
		
1202
		/* check if a series was found */
1203
		if (endSeriesRecordIdx == -1) {
1204
			return null;
1205
		}
1206
		
1207
		/* next index in the records list where the new series can be inserted */
1208
		idx = endSeriesRecordIdx + 1;
1209
1210
		HSSFSeries newSeries = null;
1211
		
1212
		/* duplicate record of the template series */
1213
		ArrayList<RecordBase> clonedRecords = new ArrayList<RecordBase>();
1214
		for(final RecordBase record : seriesTemplate) {		
1215
			
1216
			Record newRecord = null;
1217
			
1218
			if (record instanceof BeginRecord) {
1219
				newRecord = new BeginRecord();
1220
			} else if (record instanceof EndRecord) {
1221
				newRecord = new EndRecord();
1222
			} else if (record instanceof SeriesRecord) {
1223
				SeriesRecord seriesRecord = (SeriesRecord) ((SeriesRecord)record).clone();
1224
				newSeries = new HSSFSeries(seriesRecord);
1225
				newRecord = seriesRecord;
1226
			} else if (record instanceof LinkedDataRecord) {
1227
				LinkedDataRecord linkedDataRecord = (LinkedDataRecord) ((LinkedDataRecord)record).clone();
1228
				if (newSeries != null) {
1229
					newSeries.insertData(linkedDataRecord);
1230
				}
1231
				newRecord = linkedDataRecord;
1232
			} else if (record instanceof DataFormatRecord) {
1233
				DataFormatRecord dataFormatRecord = (DataFormatRecord) ((DataFormatRecord)record).clone();
1234
				
1235
				dataFormatRecord.setSeriesIndex((short)seriesIdx) ;
1236
				dataFormatRecord.setSeriesNumber((short)seriesIdx) ;
1237
				
1238
				newRecord = dataFormatRecord;
1239
			} else if (record instanceof SeriesTextRecord) {
1240
				SeriesTextRecord seriesTextRecord = (SeriesTextRecord) ((SeriesTextRecord)record).clone();
1241
				if (newSeries != null) {
1242
					newSeries.setSeriesTitleText(seriesTextRecord);
1243
				}
1244
				newRecord = seriesTextRecord;
1245
			} else if (record instanceof Record) {
1246
				newRecord = (Record) ((Record)record).clone();
1247
			}
1248
			
1249
			if (newRecord != null)
1250
			{
1251
				clonedRecords.add(newRecord);
1252
			}
1253
		}
1254
		
1255
		/* check if a user model series object was created */
1256
		if (newSeries == null)
1257
		{
1258
			return null;
1259
		}
1260
		
1261
		/* transfer series to record list */
1262
		for(final RecordBase record : clonedRecords) {		
1263
			records.add(idx++, record);
1264
		}
1265
		
1266
		return newSeries;
1267
	}
1268
	
1269
	public boolean removeSeries(HSSFSeries series) {
1270
		int idx = 0;
1271
		int deep = 0;
1272
		int chartDeep = -1;
1273
		int lastSeriesDeep = -1;
1274
		int seriesIdx = -1;
1275
		boolean removeSeries = false;
1276
		boolean chartEntered = false;
1277
		boolean result = false;
1278
		final List<RecordBase> records = sheet.getSheet().getRecords();
1279
		
1280
		/* store first series as template and find last series index */
1281
		Iterator<RecordBase> iter = records.iterator();
1282
		while (iter.hasNext()) {		
1283
			RecordBase record = iter.next();
1284
			idx++;
1285
			
1286
			if (record instanceof BeginRecord) {
1287
				deep++;
1288
			} else if (record instanceof EndRecord) {
1289
				deep--;
1290
				
1291
				if (lastSeriesDeep == deep) {
1292
					lastSeriesDeep = -1;
1293
					
1294
					if (removeSeries) {
1295
						removeSeries = false;
1296
						result = true;
1297
						iter.remove();
1298
					}
1299
				}
1300
				
1301
				if (chartDeep == deep) {
1302
					break;
1303
				}
1304
			}
1305
			
1306
			if (record instanceof ChartRecord) {
1307
				if (record == chartRecord) {
1308
					chartDeep = deep;
1309
					chartEntered = true;
1310
				}
1311
			} else if (record instanceof SeriesRecord) {
1312
				if (chartEntered) {
1313
					if (series.series == record) {
1314
						lastSeriesDeep = deep;
1315
						removeSeries = true;
1316
					} else {
1317
						seriesIdx++;
1318
					}
1319
				}
1320
			} else if (record instanceof DataFormatRecord) {
1321
				if (chartEntered && !removeSeries) {
1322
					DataFormatRecord dataFormatRecord = (DataFormatRecord) record;
1323
					dataFormatRecord.setSeriesIndex((short) seriesIdx);
1324
					dataFormatRecord.setSeriesNumber((short) seriesIdx);
1325
				}
1326
			}
1327
			
1328
			if (removeSeries) {
1329
				iter.remove();
1330
			}
1331
		}
1332
		
1333
		return result;
1334
	}
1335
	
1336
	public HSSFChartType getType() {
1337
		return type;
1338
	}
1000
}
1339
}

Return to bug 49581