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 |
} |