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