From: Nick Burch Date: Sat, 8 Mar 2008 16:08:49 +0000 (+0000) Subject: Tweak documentation for ss instead of hssf X-Git-Tag: REL_3_5_BETA2~202 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=b7ffac2c6dd472c0bee28123c6be8aaa1f3e9853;p=poi.git Tweak documentation for ss instead of hssf git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@634998 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/documentation/content/xdocs/book.xml b/src/documentation/content/xdocs/book.xml index e8e6eb6741..c02fcd6302 100644 --- a/src/documentation/content/xdocs/book.xml +++ b/src/documentation/content/xdocs/book.xml @@ -35,7 +35,7 @@ - + diff --git a/src/documentation/content/xdocs/hssf/book.xml b/src/documentation/content/xdocs/hssf/book.xml deleted file mode 100644 index 015904923d..0000000000 --- a/src/documentation/content/xdocs/hssf/book.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/documentation/content/xdocs/hssf/chart.xml b/src/documentation/content/xdocs/hssf/chart.xml deleted file mode 100644 index 3dd3371287..0000000000 --- a/src/documentation/content/xdocs/hssf/chart.xml +++ /dev/null @@ -1,1532 +0,0 @@ - - - - - -
- Chart record information - - - -
- -
Introduction -

- This document is intended as a work in progress for describing - our current understanding of how the chart records are are - written to produce a valid chart. -

-
-
Bar chart -

- The following records detail the records written for a - 'simple' bar chart. -

- - - ============================================ - rectype = 0xec, recsize = 0xc8 - -BEGIN DUMP--------------------------------- - 00000000 0F 00 02 F0 C0 00 00 00 10 00 08 F0 08 00 00 00 ................ - 00000010 02 00 00 00 02 04 00 00 0F 00 03 F0 A8 00 00 00 ................ - 00000020 0F 00 04 F0 28 00 00 00 01 00 09 F0 10 00 00 00 ....(........... - 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ - 00000040 02 00 0A F0 08 00 00 00 00 04 00 00 05 00 00 00 ................ - 00000050 0F 00 04 F0 70 00 00 00 92 0C 0A F0 08 00 00 00 ....p........... - 00000060 02 04 00 00 00 0A 00 00 93 00 0B F0 36 00 00 00 ............6... - 00000070 7F 00 04 01 04 01 BF 00 08 00 08 00 81 01 4E 00 ..............N. - 00000080 00 08 83 01 4D 00 00 08 BF 01 10 00 11 00 C0 01 ....M........... - 00000090 4D 00 00 08 FF 01 08 00 08 00 3F 02 00 00 02 00 M.........?..... - 000000A0 BF 03 00 00 08 00 00 00 10 F0 12 00 00 00 00 00 ................ - 000000B0 04 00 C0 02 0A 00 F4 00 0E 00 66 01 20 00 E9 00 ..........f. ... - 000000C0 00 00 11 F0 00 00 00 00 ........ - -END DUMP----------------------------------- - recordid = 0xec, size =200 - [UNKNOWN RECORD:ec] - .id = ec - [/UNKNOWN RECORD] - - ============================================ - rectype = 0x5d, recsize = 0x1a - -BEGIN DUMP--------------------------------- - 00000000 15 00 12 00 05 00 02 00 11 60 00 00 00 00 B8 03 .........`...... - 00000010 87 03 00 00 00 00 00 00 00 00 .......... - -END DUMP----------------------------------- - recordid = 0x5d, size =26 - [UNKNOWN RECORD:5d] - .id = 5d - [/UNKNOWN RECORD] - - ============================================ - rectype = 0x809, recsize = 0x10 - -BEGIN DUMP--------------------------------- - 00000000 00 06 20 00 FE 1C CD 07 C9 40 00 00 06 01 00 00 .. ......@...... - -END DUMP----------------------------------- - recordid = 0x809, size =16 - [BOF RECORD] - .version = 600 - .type = 20 - .build = 1cfe - .buildyear = 1997 - .history = 40c9 - .requiredversion = 106 - [/BOF RECORD] - - ============================================ - rectype = 0x14, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x14, size =0 - [HEADER] - .length = 0 - .header = null - [/HEADER] - - ============================================ - rectype = 0x15, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x15, size =0 - [FOOTER] - .footerlen = 0 - .footer = null - [/FOOTER] - - ============================================ - rectype = 0x83, recsize = 0x2 - -BEGIN DUMP--------------------------------- - 00000000 00 00 .. - -END DUMP----------------------------------- - recordid = 0x83, size =2 - [HCENTER] - .hcenter = false - [/HCENTER] - - ============================================ - rectype = 0x84, recsize = 0x2 - -BEGIN DUMP--------------------------------- - 00000000 00 00 .. - -END DUMP----------------------------------- - recordid = 0x84, size =2 - [VCENTER] - .vcenter = false - [/VCENTER] - - ============================================ - rectype = 0xa1, recsize = 0x22 - -BEGIN DUMP--------------------------------- - 00000000 00 00 12 00 01 00 01 00 01 00 04 00 00 00 B8 03 ................ - 00000010 00 00 00 00 00 00 E0 3F 00 00 00 00 00 00 E0 3F .......?.......? - 00000020 0F 00 .. - -END DUMP----------------------------------- - recordid = 0xa1, size =34 - [PRINTSETUP] - .papersize = 0 - .scale = 18 - .pagestart = 1 - .fitwidth = 1 - .fitheight = 1 - .options = 4 - .ltor = false - .landscape = false - .valid = true - .mono = false - .draft = false - .notes = false - .noOrientat = false - .usepage = false - .hresolution = 0 - .vresolution = 952 - .headermargin = 0.5 - .footermargin = 0.5 - .copies = 15 - [/PRINTSETUP] - - - ============================================ - rectype = 0x33, recsize = 0x2 - -BEGIN DUMP--------------------------------- - 00000000 03 00 .. - -END DUMP----------------------------------- - recordid = 0x33, size =2 - [UNKNOWN RECORD:33] - .id = 33 - [/UNKNOWN RECORD] - - ============================================ - rectype = 0x1060, recsize = 0xa - -BEGIN DUMP--------------------------------- - 00000000 A0 23 08 16 C8 00 00 00 05 00 .#........ - -END DUMP----------------------------------- - recordid = 0x1060, size =10 - [FBI] - .xBasis = 0x23A0 (9120 ) - .yBasis = 0x1608 (5640 ) - .heightBasis = 0x00C8 (200 ) - .scale = 0x0000 (0 ) - .indexToFontTable = 0x0005 (5 ) - [/FBI] - - ============================================ - rectype = 0x1060, recsize = 0xa - -BEGIN DUMP--------------------------------- - 00000000 A0 23 08 16 C8 00 01 00 06 00 .#........ - -END DUMP----------------------------------- - recordid = 0x1060, size =10 - [FBI] - .xBasis = 0x23A0 (9120 ) - .yBasis = 0x1608 (5640 ) - .heightBasis = 0x00C8 (200 ) - .scale = 0x0001 (1 ) - .indexToFontTable = 0x0006 (6 ) - [/FBI] - - ============================================ - rectype = 0x12, recsize = 0x2 - -BEGIN DUMP--------------------------------- - 00000000 00 00 .. - -END DUMP----------------------------------- - recordid = 0x12, size =2 - [PROTECT] - .rowheight = 0 - [/PROTECT] - - ============================================ - Offset 0xf22 (3874) - rectype = 0x1001, recsize = 0x2 - -BEGIN DUMP--------------------------------- - 00000000 00 00 .. - -END DUMP----------------------------------- - recordid = 0x1001, size =2 - [UNITS] - .units = 0x0000 (0 ) - [/UNITS] - - ============================================ - Offset 0xf28 (3880) - rectype = 0x1002, recsize = 0x10 - -BEGIN DUMP--------------------------------- - 00000000 00 00 00 00 00 00 00 00 58 66 D0 01 40 66 22 01 ........Xf..@f". - -END DUMP----------------------------------- - recordid = 0x1002, size =16 - [CHART] - .x = 0x00000000 (0 ) - .y = 0x00000000 (0 ) - .width = 0x01D06658 (30434904 ) - .height = 0x01226640 (19031616 ) - [/CHART] - - ============================================ - Offset 0xf3c (3900) - rectype = 0x1033, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1033, size =0 - [BEGIN] - [/BEGIN] - - ============================================ - Offset 0xf40 (3904) - rectype = 0xa0, recsize = 0x4 - -BEGIN DUMP--------------------------------- - 00000000 01 00 01 00 .... - -END DUMP----------------------------------- - recordid = 0xa0, size =4 - [SCL] - .numerator = 0x0001 (1 ) - .denominator = 0x0001 (1 ) - [/SCL] - - - ============================================ - Offset 0xf48 (3912) - rectype = 0x1064, recsize = 0x8 - -BEGIN DUMP--------------------------------- - 00000000 00 00 01 00 00 00 01 00 ........ - -END DUMP----------------------------------- - recordid = 0x1064, size =8 - [PLOTGROWTH] - .horizontalScale = 0x00010000 (65536 ) - .verticalScale = 0x00010000 (65536 ) - [/PLOTGROWTH] - - ============================================ - Offset 0xf54 (3924) - rectype = 0x1032, recsize = 0x4 - -BEGIN DUMP--------------------------------- - 00000000 00 00 02 00 .... - -END DUMP----------------------------------- - recordid = 0x1032, size =4 - [FRAME] - .borderType = 0x0000 (0 ) - .options = 0x0002 (2 ) - .autoSize = false - .autoPosition = true - [/FRAME] - - ============================================ - Offset 0xf5c (3932) - rectype = 0x1033, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1033, size =0 - [BEGIN] - [/BEGIN] - - ============================================ - Offset 0xf60 (3936) - rectype = 0x1007, recsize = 0xc - -BEGIN DUMP--------------------------------- - 00000000 00 00 00 00 00 00 FF FF 09 00 4D 00 ..........M. - -END DUMP----------------------------------- - recordid = 0x1007, size =12 - [LINEFORMAT] - .lineColor = 0x00000000 (0 ) - .linePattern = 0x0000 (0 ) - .weight = 0xFFFF (-1 ) - .format = 0x0009 (9 ) - .auto = true - .drawTicks = false - .unknown = false - .colourPaletteIndex = 0x004D (77 ) - [/LINEFORMAT] - - ============================================ - Offset 0xf70 (3952) - rectype = 0x100a, recsize = 0x10 - -BEGIN DUMP--------------------------------- - 00000000 FF FF FF 00 00 00 00 00 01 00 01 00 4E 00 4D 00 ............N.M. - -END DUMP----------------------------------- - recordid = 0x100a, size =16 - [AREAFORMAT] - .foregroundColor = 0x00FFFFFF (16777215 ) - .backgroundColor = 0x00000000 (0 ) - .pattern = 0x0001 (1 ) - .formatFlags = 0x0001 (1 ) - .automatic = true - .invert = false - .forecolorIndex = 0x004E (78 ) - .backcolorIndex = 0x004D (77 ) - [/AREAFORMAT] - - ============================================ - Offset 0xf84 (3972) - rectype = 0x1034, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1034, size =0 - [END] - [/END] - - ============================================ - Offset 0xf88 (3976) - rectype = 0x1003, recsize = 0xc - -BEGIN DUMP--------------------------------- - 00000000 01 00 01 00 20 00 1F 00 01 00 00 00 .... ....... - -END DUMP----------------------------------- - recordid = 0x1003, size =12 - [SERIES] - .categoryDataType = 0x0001 (1 ) - .valuesDataType = 0x0001 (1 ) - .numCategories = 0x0020 (32 ) - .numValues = 0x001F (31 ) - .bubbleSeriesType = 0x0001 (1 ) - .numBubbleValues = 0x0000 (0 ) - [/SERIES] - - ============================================ - Offset 0xf98 (3992) - rectype = 0x1033, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1033, size =0 - [BEGIN] - [/BEGIN] - - - ============================================ - Offset 0xf9c (3996) - rectype = 0x1051, recsize = 0x8 - -BEGIN DUMP--------------------------------- - 00000000 00 01 00 00 00 00 00 00 ........ - -END DUMP----------------------------------- - recordid = 0x1051, size =8 - [AI] - .linkType = 0x00 (0 ) - .referenceType = 0x01 (1 ) - .options = 0x0000 (0 ) - .customNumberFormat = false - .indexNumberFmtRecord = 0x0000 (0 ) - .formulaOfLink = (org.apache.poi.hssf.record.LinkedDataFormulaField@1ee3914 ) - [/AI] - - ============================================ - Offset 0xfa8 (4008) - rectype = 0x1051, recsize = 0x13 - -BEGIN DUMP--------------------------------- - 00000000 01 02 00 00 00 00 0B 00 3B 00 00 00 00 1E 00 01 ........;....... - 00000010 00 01 00 ... - -END DUMP----------------------------------- - recordid = 0x1051, size =19 - [AI] - .linkType = 0x01 (1 ) - .referenceType = 0x02 (2 ) - .options = 0x0000 (0 ) - .customNumberFormat = false - .indexNumberFmtRecord = 0x0000 (0 ) - .formulaOfLink = (org.apache.poi.hssf.record.LinkedDataFormulaField@e5855a ) - [/AI] - - ============================================ - Offset 0xfbf (4031) - rectype = 0x1051, recsize = 0x13 - -BEGIN DUMP--------------------------------- - 00000000 02 02 00 00 69 01 0B 00 3B 00 00 00 00 1F 00 00 ....i...;....... - 00000010 00 00 00 ... - -END DUMP----------------------------------- - recordid = 0x1051, size =19 - [AI] - .linkType = 0x02 (2 ) - .referenceType = 0x02 (2 ) - .options = 0x0000 (0 ) - .customNumberFormat = false - .indexNumberFmtRecord = 0x0169 (361 ) - .formulaOfLink = (org.apache.poi.hssf.record.LinkedDataFormulaField@95fd19 ) - [/AI] - - ============================================ - Offset 0xfd6 (4054) - rectype = 0x1051, recsize = 0x8 - -BEGIN DUMP--------------------------------- - 00000000 03 01 00 00 00 00 00 00 ........ - -END DUMP----------------------------------- - recordid = 0x1051, size =8 - [AI] - .linkType = 0x03 (3 ) - .referenceType = 0x01 (1 ) - .options = 0x0000 (0 ) - .customNumberFormat = false - .indexNumberFmtRecord = 0x0000 (0 ) - .formulaOfLink = (org.apache.poi.hssf.record.LinkedDataFormulaField@11b9fb1 ) - [/AI] - - ============================================ - Offset 0xfe2 (4066) - rectype = 0x1006, recsize = 0x8 - -BEGIN DUMP--------------------------------- - 00000000 FF FF 00 00 00 00 00 00 ........ - -END DUMP----------------------------------- - recordid = 0x1006, size =8 - [DATAFORMAT] - .pointNumber = 0xFFFF (-1 ) - .seriesIndex = 0x0000 (0 ) - .seriesNumber = 0x0000 (0 ) - .formatFlags = 0x0000 (0 ) - .useExcel4Colors = false - [/DATAFORMAT] - - ============================================ - Offset 0xfee (4078) - rectype = 0x1033, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1033, size =0 - [BEGIN] - [/BEGIN] - - ============================================ - Offset 0xff2 (4082) - rectype = 0x105f, recsize = 0x2 - -BEGIN DUMP--------------------------------- - 00000000 00 00 .. - -END DUMP----------------------------------- - recordid = 0x105f, size =2 - [UNKNOWN RECORD] - .id = 105f - [/UNKNOWN RECORD] - - ============================================ - Offset 0xff8 (4088) - rectype = 0x1034, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1034, size =0 - [END] - [/END] - - ============================================ - Offset 0xffc (4092) - rectype = 0x1045, recsize = 0x2 - -BEGIN DUMP--------------------------------- - 00000000 00 00 .. - -END DUMP----------------------------------- - recordid = 0x1045, size =2 - [SeriesToChartGroup] - .chartGroupIndex = 0x0000 (0 ) - [/SeriesToChartGroup] - - ============================================ - Offset 0x1002 (4098) - rectype = 0x1034, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1034, size =0 - [END] - [/END] - - ============================================ - Offset 0x1006 (4102) - rectype = 0x1044, recsize = 0x4 - -BEGIN DUMP--------------------------------- - 00000000 0A 00 00 00 .... - -END DUMP----------------------------------- - recordid = 0x1044, size =4 - [SHTPROPS] - .flags = 0x000A (10 ) - .chartTypeManuallyFormatted = false - .plotVisibleOnly = true - .doNotSizeWithWindow = false - .defaultPlotDimensions = true - .autoPlotArea = false - .empty = 0x00 (0 ) - [/SHTPROPS] - - ============================================ - Offset 0x100e (4110) - rectype = 0x1024, recsize = 0x2 - -BEGIN DUMP--------------------------------- - 00000000 02 00 .. - -END DUMP----------------------------------- - recordid = 0x1024, size =2 - [DEFAULTTEXT] - .categoryDataType = 0x0002 (2 ) - [/DEFAULTTEXT] - - ============================================ - Offset 0x1014 (4116) - rectype = 0x1025, recsize = 0x20 - -BEGIN DUMP--------------------------------- - 00000000 02 02 01 00 00 00 00 00 DB FF FF FF C4 FF FF FF ................ - 00000010 00 00 00 00 00 00 00 00 B1 00 4D 00 50 2B 00 00 ..........M.P+.. - -END DUMP----------------------------------- - recordid = 0x1025, size =32 - [TEXT] - .horizontalAlignment = 0x02 (2 ) - .verticalAlignment = 0x02 (2 ) - .displayMode = 0x0001 (1 ) - .rgbColor = 0x00000000 (0 ) - .x = 0xFFFFFFDB (-37 ) - .y = 0xFFFFFFC4 (-60 ) - .width = 0x00000000 (0 ) - .height = 0x00000000 (0 ) - .options1 = 0x00B1 (177 ) - .autoColor = true - .showKey = false - .showValue = false - .vertical = false - .autoGeneratedText = true - .generated = true - .autoLabelDeleted = false - .autoBackground = true - .rotation = 0 - .showCategoryLabelAsPercentage = false - .showValueAsPercentage = false - .showBubbleSizes = false - .showLabel = false - .indexOfColorValue = 0x004D (77 ) - .options2 = 0x2B50 (11088 ) - .dataLabelPlacement = 0 - .textRotation = 0x0000 (0 ) - [/TEXT] - - ============================================ - Offset 0x1038 (4152) - rectype = 0x1033, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1033, size =0 - [BEGIN] - [/BEGIN] - - - ============================================ - Offset 0x103c (4156) - rectype = 0x104f, recsize = 0x14 - -BEGIN DUMP--------------------------------- - 00000000 02 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ - 00000010 00 00 00 00 .... - -END DUMP----------------------------------- - recordid = 0x104f, size =20 - [UNKNOWN RECORD] - .id = 104f - [/UNKNOWN RECORD] - - ============================================ - Offset 0x1054 (4180) - rectype = 0x1026, recsize = 0x2 - -BEGIN DUMP--------------------------------- - 00000000 05 00 .. - -END DUMP----------------------------------- - recordid = 0x1026, size =2 - [FONTX] - .fontIndex = 0x0005 (5 ) - [/FONTX] - - ============================================ - Offset 0x105a (4186) - rectype = 0x1051, recsize = 0x8 - -BEGIN DUMP--------------------------------- - 00000000 00 01 00 00 00 00 00 00 ........ - -END DUMP----------------------------------- - recordid = 0x1051, size =8 - [AI] - .linkType = 0x00 (0 ) - .referenceType = 0x01 (1 ) - .options = 0x0000 (0 ) - .customNumberFormat = false - .indexNumberFmtRecord = 0x0000 (0 ) - .formulaOfLink = (org.apache.poi.hssf.record.LinkedDataFormulaField@913fe2 ) - [/AI] - - ============================================ - Offset 0x1066 (4198) - rectype = 0x1034, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1034, size =0 - [END] - [/END] - - ============================================ - Offset 0x106a (4202) - rectype = 0x1024, recsize = 0x2 - -BEGIN DUMP--------------------------------- - 00000000 03 00 .. - -END DUMP----------------------------------- - recordid = 0x1024, size =2 - [DEFAULTTEXT] - .categoryDataType = 0x0003 (3 ) - [/DEFAULTTEXT] - - ============================================ - Offset 0x1070 (4208) - rectype = 0x1025, recsize = 0x20 - -BEGIN DUMP--------------------------------- - 00000000 02 02 01 00 00 00 00 00 DB FF FF FF C4 FF FF FF ................ - 00000010 00 00 00 00 00 00 00 00 B1 00 4D 00 50 2B 00 00 ..........M.P+.. - -END DUMP----------------------------------- - recordid = 0x1025, size =32 - [TEXT] - .horizontalAlignment = 0x02 (2 ) - .verticalAlignment = 0x02 (2 ) - .displayMode = 0x0001 (1 ) - .rgbColor = 0x00000000 (0 ) - .x = 0xFFFFFFDB (-37 ) - .y = 0xFFFFFFC4 (-60 ) - .width = 0x00000000 (0 ) - .height = 0x00000000 (0 ) - .options1 = 0x00B1 (177 ) - .autoColor = true - .showKey = false - .showValue = false - .vertical = false - .autoGeneratedText = true - .generated = true - .autoLabelDeleted = false - .autoBackground = true - .rotation = 0 - .showCategoryLabelAsPercentage = false - .showValueAsPercentage = false - .showBubbleSizes = false - .showLabel = false - .indexOfColorValue = 0x004D (77 ) - .options2 = 0x2B50 (11088 ) - .dataLabelPlacement = 0 - .textRotation = 0x0000 (0 ) - [/TEXT] - - ============================================ - Offset 0x1094 (4244) - rectype = 0x1033, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1033, size =0 - [BEGIN] - [/BEGIN] - - ============================================ - Offset 0x1098 (4248) - rectype = 0x104f, recsize = 0x14 - -BEGIN DUMP--------------------------------- - 00000000 02 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ - 00000010 00 00 00 00 .... - -END DUMP----------------------------------- - recordid = 0x104f, size =20 - [UNKNOWN RECORD] - .id = 104f - [/UNKNOWN RECORD] - - ============================================ - Offset 0x10b0 (4272) - rectype = 0x1026, recsize = 0x2 - -BEGIN DUMP--------------------------------- - 00000000 06 00 .. - -END DUMP----------------------------------- - recordid = 0x1026, size =2 - [FONTX] - .fontIndex = 0x0006 (6 ) - [/FONTX] - - ============================================ - Offset 0x10b6 (4278) - rectype = 0x1051, recsize = 0x8 - -BEGIN DUMP--------------------------------- - 00000000 00 01 00 00 00 00 00 00 ........ - -END DUMP----------------------------------- - recordid = 0x1051, size =8 - [AI] - .linkType = 0x00 (0 ) - .referenceType = 0x01 (1 ) - .options = 0x0000 (0 ) - .customNumberFormat = false - .indexNumberFmtRecord = 0x0000 (0 ) - .formulaOfLink = (org.apache.poi.hssf.record.LinkedDataFormulaField@1f934ad ) - [/AI] - - ============================================ - Offset 0x10c2 (4290) - rectype = 0x1034, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1034, size =0 - [END] - [/END] - - ============================================ - Offset 0x10c6 (4294) - rectype = 0x1046, recsize = 0x2 - -BEGIN DUMP--------------------------------- - 00000000 01 00 .. - -END DUMP----------------------------------- - recordid = 0x1046, size =2 - [AXISUSED] - .numAxis = 0x0001 (1 ) - [/AXISUSED] - - ============================================ - Offset 0x10cc (4300) - rectype = 0x1041, recsize = 0x12 - -BEGIN DUMP--------------------------------- - 00000000 00 00 DF 01 00 00 DD 00 00 00 B3 0B 00 00 56 0B ..............V. - 00000010 00 00 .. - -END DUMP----------------------------------- - recordid = 0x1041, size =18 - [AXISPARENT] - .axisType = 0x0000 (0 ) - .x = 0x000001DF (479 ) - .y = 0x000000DD (221 ) - .width = 0x00000BB3 (2995 ) - .height = 0x00000B56 (2902 ) - [/AXISPARENT] - - ============================================ - Offset 0x10e2 (4322) - rectype = 0x1033, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1033, size =0 - [BEGIN] - [/BEGIN] - - ============================================ - Offset 0x10e6 (4326) - rectype = 0x104f, recsize = 0x14 - -BEGIN DUMP--------------------------------- - 00000000 02 00 02 00 3A 00 00 00 5E 00 00 00 58 0D 00 00 ....:...^...X... - 00000010 E5 0E 00 00 .... - -END DUMP----------------------------------- - recordid = 0x104f, size =20 - [UNKNOWN RECORD] - .id = 104f - [/UNKNOWN RECORD] - - ============================================ - Offset 0x10fe (4350) - rectype = 0x101d, recsize = 0x12 - -BEGIN DUMP--------------------------------- - 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ - 00000010 00 00 .. - -END DUMP----------------------------------- - recordid = 0x101d, size =18 - [AXIS] - .axisType = 0x0000 (0 ) - .reserved1 = 0x00000000 (0 ) - .reserved2 = 0x00000000 (0 ) - .reserved3 = 0x00000000 (0 ) - .reserved4 = 0x00000000 (0 ) - [/AXIS] - - ============================================ - Offset 0x1114 (4372) - rectype = 0x1033, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1033, size =0 - [BEGIN] - [/BEGIN] - - ============================================ - Offset 0x1118 (4376) - rectype = 0x1020, recsize = 0x8 - -BEGIN DUMP--------------------------------- - 00000000 01 00 01 00 01 00 01 00 ........ - -END DUMP----------------------------------- - recordid = 0x1020, size =8 - [CATSERRANGE] - .crossingPoint = 0x0001 (1 ) - .labelFrequency = 0x0001 (1 ) - .tickMarkFrequency = 0x0001 (1 ) - .options = 0x0001 (1 ) - .valueAxisCrossing = true - .crossesFarRight = false - .reversed = false - [/CATSERRANGE] - - ============================================ - Offset 0x1124 (4388) - rectype = 0x1062, recsize = 0x12 - -BEGIN DUMP--------------------------------- - 00000000 1C 90 39 90 02 00 00 00 01 00 00 00 00 00 1C 90 ..9............. - 00000010 FF 00 .. - -END DUMP----------------------------------- - recordid = 0x1062, size =18 - [AXCEXT] - .minimumCategory = 0x901C (-28644 ) - .maximumCategory = 0x9039 (-28615 ) - .majorUnitValue = 0x0002 (2 ) - .majorUnit = 0x0000 (0 ) - .minorUnitValue = 0x0001 (1 ) - .minorUnit = 0x0000 (0 ) - .baseUnit = 0x0000 (0 ) - .crossingPoint = 0x901C (-28644 ) - .options = 0x00FF (255 ) - .defaultMinimum = true - .defaultMaximum = true - .defaultMajor = true - .defaultMinorUnit = true - .isDate = true - .defaultBase = true - .defaultCross = true - .defaultDateSettings = true - [/AXCEXT] - - ============================================ - Offset 0x113a (4410) - rectype = 0x101e, recsize = 0x1e - -BEGIN DUMP--------------------------------- - 00000000 02 00 03 01 00 00 00 00 00 00 00 00 00 00 00 00 ................ - 00000010 00 00 00 00 00 00 00 00 23 00 4D 00 2D 00 ........#.M.-. - -END DUMP----------------------------------- - recordid = 0x101e, size =30 - [TICK] - .majorTickType = 0x02 (2 ) - .minorTickType = 0x00 (0 ) - .labelPosition = 0x03 (3 ) - .background = 0x01 (1 ) - .labelColorRgb = 0x00000000 (0 ) - .zero1 = 0x0000 (0 ) - .zero2 = 0x0000 (0 ) - .options = 0x0023 (35 ) - .autoTextColor = true - .autoTextBackground = true - .rotation = 0 - .autorotate = true - .tickColor = 0x004D (77 ) - .zero3 = 0x002D (45 ) - [/TICK] - - ============================================ - Offset 0x115c (4444) - rectype = 0x1034, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1034, size =0 - [END] - [/END] - - ============================================ - Offset 0x1160 (4448) - rectype = 0x101d, recsize = 0x12 - -BEGIN DUMP--------------------------------- - 00000000 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ - 00000010 00 00 .. - -END DUMP----------------------------------- - recordid = 0x101d, size =18 - [AXIS] - .axisType = 0x0001 (1 ) - .reserved1 = 0x00000000 (0 ) - .reserved2 = 0x00000000 (0 ) - .reserved3 = 0x00000000 (0 ) - .reserved4 = 0x00000000 (0 ) - [/AXIS] - - - ============================================ - Offset 0x1176 (4470) - rectype = 0x1033, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1033, size =0 - [BEGIN] - [/BEGIN] - - ============================================ - Offset 0x117a (4474) - rectype = 0x101f, recsize = 0x2a - -BEGIN DUMP--------------------------------- - 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ - 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ - 00000020 00 00 00 00 00 00 00 00 1F 01 .......... - -END DUMP----------------------------------- - recordid = 0x101f, size =42 - [VALUERANGE] - .minimumAxisValue = (0.0 ) - .maximumAxisValue = (0.0 ) - .majorIncrement = (0.0 ) - .minorIncrement = (0.0 ) - .categoryAxisCross = (0.0 ) - .options = 0x011F (287 ) - .automaticMinimum = true - .automaticMaximum = true - .automaticMajor = true - .automaticMinor = true - .automaticCategoryCrossing = true - .logarithmicScale = false - .valuesInReverse = false - .crossCategoryAxisAtMaximum = false - .reserved = true - [/VALUERANGE] - - ============================================ - Offset 0x11a8 (4520) - rectype = 0x101e, recsize = 0x1e - -BEGIN DUMP--------------------------------- - 00000000 02 00 03 01 00 00 00 00 00 00 00 00 00 00 00 00 ................ - 00000010 00 00 00 00 00 00 00 00 23 00 4D 00 00 00 ........#.M... - -END DUMP----------------------------------- - recordid = 0x101e, size =30 - [TICK] - .majorTickType = 0x02 (2 ) - .minorTickType = 0x00 (0 ) - .labelPosition = 0x03 (3 ) - .background = 0x01 (1 ) - .labelColorRgb = 0x00000000 (0 ) - .zero1 = 0x0000 (0 ) - .zero2 = 0x0000 (0 ) - .options = 0x0023 (35 ) - .autoTextColor = true - .autoTextBackground = true - .rotation = 0 - .autorotate = true - .tickColor = 0x004D (77 ) - .zero3 = 0x0000 (0 ) - [/TICK] - - ============================================ - Offset 0x11ca (4554) - rectype = 0x1021, recsize = 0x2 - -BEGIN DUMP--------------------------------- - 00000000 01 00 .. - -END DUMP----------------------------------- - recordid = 0x1021, size =2 - [AXISLINEFORMAT] - .axisType = 0x0001 (1 ) - [/AXISLINEFORMAT] - - ============================================ - Offset 0x11d0 (4560) - rectype = 0x1007, recsize = 0xc - -BEGIN DUMP--------------------------------- - 00000000 00 00 00 00 00 00 FF FF 09 00 4D 00 ..........M. - -END DUMP----------------------------------- - recordid = 0x1007, size =12 - [LINEFORMAT] - .lineColor = 0x00000000 (0 ) - .linePattern = 0x0000 (0 ) - .weight = 0xFFFF (-1 ) - .format = 0x0009 (9 ) - .auto = true - .drawTicks = false - .unknown = false - .colourPaletteIndex = 0x004D (77 ) - [/LINEFORMAT] - - ============================================ - Offset 0x11e0 (4576) - rectype = 0x1034, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1034, size =0 - [END] - [/END] - - ============================================ - Offset 0x11e4 (4580) - rectype = 0x1035, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1035, size =0 - [PLOTAREA] - [/PLOTAREA] - - ============================================ - Offset 0x11e8 (4584) - rectype = 0x1032, recsize = 0x4 - -BEGIN DUMP--------------------------------- - 00000000 00 00 03 00 .... - -END DUMP----------------------------------- - recordid = 0x1032, size =4 - [FRAME] - .borderType = 0x0000 (0 ) - .options = 0x0003 (3 ) - .autoSize = true - .autoPosition = true - [/FRAME] - - ============================================ - Offset 0x11f0 (4592) - rectype = 0x1033, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1033, size =0 - [BEGIN] - [/BEGIN] - - ============================================ - Offset 0x11f4 (4596) - rectype = 0x1007, recsize = 0xc - -BEGIN DUMP--------------------------------- - 00000000 80 80 80 00 00 00 00 00 00 00 17 00 ............ - -END DUMP----------------------------------- - recordid = 0x1007, size =12 - [LINEFORMAT] - .lineColor = 0x00808080 (8421504 ) - .linePattern = 0x0000 (0 ) - .weight = 0x0000 (0 ) - .format = 0x0000 (0 ) - .auto = false - .drawTicks = false - .unknown = false - .colourPaletteIndex = 0x0017 (23 ) - [/LINEFORMAT] - - ============================================ - Offset 0x1204 (4612) - rectype = 0x100a, recsize = 0x10 - -BEGIN DUMP--------------------------------- - 00000000 C0 C0 C0 00 00 00 00 00 01 00 00 00 16 00 4F 00 ..............O. - -END DUMP----------------------------------- - recordid = 0x100a, size =16 - [AREAFORMAT] - .foregroundColor = 0x00C0C0C0 (12632256 ) - .backgroundColor = 0x00000000 (0 ) - .pattern = 0x0001 (1 ) - .formatFlags = 0x0000 (0 ) - .automatic = false - .invert = false - .forecolorIndex = 0x0016 (22 ) - .backcolorIndex = 0x004F (79 ) - [/AREAFORMAT] - - ============================================ - Offset 0x1218 (4632) - rectype = 0x1034, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1034, size =0 - [END] - [/END] - - ============================================ - Offset 0x121c (4636) - rectype = 0x1014, recsize = 0x14 - -BEGIN DUMP--------------------------------- - 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ - 00000010 00 00 00 00 .... - -END DUMP----------------------------------- - recordid = 0x1014, size =20 - [CHARTFORMAT] - .xPosition = 0 - .yPosition = 0 - .width = 0 - .height = 0 - .grBit = 0 - [/CHARTFORMAT] - - ============================================ - Offset 0x1234 (4660) - rectype = 0x1033, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1033, size =0 - [BEGIN] - [/BEGIN] - - ============================================ - Offset 0x1238 (4664) - rectype = 0x1017, recsize = 0x6 - -BEGIN DUMP--------------------------------- - 00000000 00 00 96 00 00 00 ...... - -END DUMP----------------------------------- - recordid = 0x1017, size =6 - [BAR] - .barSpace = 0x0000 (0 ) - .categorySpace = 0x0096 (150 ) - .formatFlags = 0x0000 (0 ) - .horizontal = false - .stacked = false - .displayAsPercentage = false - .shadow = false - [/BAR] - - ============================================ - Offset 0x1242 (4674) - rectype = 0x1022, recsize = 0xa - -BEGIN DUMP--------------------------------- - 00000000 00 00 00 00 00 00 00 00 0F 00 .......... - -END DUMP----------------------------------- - recordid = 0x1022, size =10 - [UNKNOWN RECORD] - .id = 1022 - [/UNKNOWN RECORD] - - ============================================ - Offset 0x1250 (4688) - rectype = 0x1015, recsize = 0x14 - -BEGIN DUMP--------------------------------- - 00000000 D6 0D 00 00 1E 06 00 00 B5 01 00 00 D5 00 00 00 ................ - 00000010 03 01 1F 00 .... - -END DUMP----------------------------------- - recordid = 0x1015, size =20 - [LEGEND] - .xAxisUpperLeft = 0x00000DD6 (3542 ) - .yAxisUpperLeft = 0x0000061E (1566 ) - .xSize = 0x000001B5 (437 ) - .ySize = 0x000000D5 (213 ) - .type = 0x03 (3 ) - .spacing = 0x01 (1 ) - .options = 0x001F (31 ) - .autoPosition = true - .autoSeries = true - .autoXPositioning = true - .autoYPositioning = true - .vertical = true - .dataTable = false - [/LEGEND] - - ============================================ - Offset 0x1268 (4712) - rectype = 0x1033, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1033, size =0 - [BEGIN] - [/BEGIN] - - ============================================ - Offset 0x126c (4716) - rectype = 0x104f, recsize = 0x14 - -BEGIN DUMP--------------------------------- - 00000000 05 00 02 00 D6 0D 00 00 1E 06 00 00 00 00 00 00 ................ - 00000010 00 00 00 00 .... - -END DUMP----------------------------------- - recordid = 0x104f, size =20 - [UNKNOWN RECORD] - .id = 104f - [/UNKNOWN RECORD] - - ============================================ - Offset 0x1284 (4740) - rectype = 0x1025, recsize = 0x20 - -BEGIN DUMP--------------------------------- - 00000000 02 02 01 00 00 00 00 00 DB FF FF FF C4 FF FF FF ................ - 00000010 00 00 00 00 00 00 00 00 B1 00 4D 00 70 37 00 00 ..........M.p7.. - -END DUMP----------------------------------- - recordid = 0x1025, size =32 - [TEXT] - .horizontalAlignment = 0x02 (2 ) - .verticalAlignment = 0x02 (2 ) - .displayMode = 0x0001 (1 ) - .rgbColor = 0x00000000 (0 ) - .x = 0xFFFFFFDB (-37 ) - .y = 0xFFFFFFC4 (-60 ) - .width = 0x00000000 (0 ) - .height = 0x00000000 (0 ) - .options1 = 0x00B1 (177 ) - .autoColor = true - .showKey = false - .showValue = false - .vertical = false - .autoGeneratedText = true - .generated = true - .autoLabelDeleted = false - .autoBackground = true - .rotation = 0 - .showCategoryLabelAsPercentage = false - .showValueAsPercentage = false - .showBubbleSizes = false - .showLabel = false - .indexOfColorValue = 0x004D (77 ) - .options2 = 0x3770 (14192 ) - .dataLabelPlacement = 0 - .textRotation = 0x0000 (0 ) - [/TEXT] - - ============================================ - Offset 0x12a8 (4776) - rectype = 0x1033, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1033, size =0 - [BEGIN] - [/BEGIN] - - ============================================ - Offset 0x12ac (4780) - rectype = 0x104f, recsize = 0x14 - -BEGIN DUMP--------------------------------- - 00000000 02 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ - 00000010 00 00 00 00 .... - -END DUMP----------------------------------- - recordid = 0x104f, size =20 - [UNKNOWN RECORD] - .id = 104f - [/UNKNOWN RECORD] - - ============================================ - Offset 0x12c4 (4804) - rectype = 0x1051, recsize = 0x8 - -BEGIN DUMP--------------------------------- - 00000000 00 01 00 00 00 00 00 00 ........ - -END DUMP----------------------------------- - recordid = 0x1051, size =8 - [AI] - .linkType = 0x00 (0 ) - .referenceType = 0x01 (1 ) - .options = 0x0000 (0 ) - .customNumberFormat = false - .indexNumberFmtRecord = 0x0000 (0 ) - .formulaOfLink = (org.apache.poi.hssf.record.LinkedDataFormulaField@1d05c81 ) - [/AI] - - ============================================ - Offset 0x12d0 (4816) - rectype = 0x1034, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1034, size =0 - [END] - [/END] - - - ============================================ - Offset 0x12d4 (4820) - rectype = 0x1034, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1034, size =0 - [END] - [/END] - - ============================================ - Offset 0x12d8 (4824) - rectype = 0x1034, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1034, size =0 - [END] - [/END] - - ============================================ - Offset 0x12dc (4828) - rectype = 0x1034, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1034, size =0 - [END] - [/END] - - ============================================ - Offset 0x12e0 (4832) - rectype = 0x1034, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0x1034, size =0 - [END] - [/END] - - ============================================ - rectype = 0x200, recsize = 0xe - -BEGIN DUMP--------------------------------- - 00000000 00 00 00 00 1F 00 00 00 00 00 01 00 00 00 .............. - -END DUMP----------------------------------- - recordid = 0x200, size =14 - [DIMENSIONS] - .firstrow = 0 - .lastrow = 1f - .firstcol = 0 - .lastcol = 1 - .zero = 0 - [/DIMENSIONS] - - ============================================ - rectype = 0x1065, recsize = 0x2 - -BEGIN DUMP--------------------------------- - 00000000 02 00 .. - -END DUMP----------------------------------- - recordid = 0x1065, size =2 - [SINDEX] - .index = 0x0002 (2 ) - [/SINDEX] - - ============================================ - rectype = 0x1065, recsize = 0x2 - -BEGIN DUMP--------------------------------- - 00000000 01 00 .. - -END DUMP----------------------------------- - recordid = 0x1065, size =2 - [SINDEX] - .index = 0x0001 (1 ) - [/SINDEX] - - ============================================ - rectype = 0x1065, recsize = 0x2 - -BEGIN DUMP--------------------------------- - 00000000 03 00 .. - -END DUMP----------------------------------- - recordid = 0x1065, size =2 - [SINDEX] - .index = 0x0003 (3 ) - [/SINDEX] - - ============================================ - rectype = 0xa, recsize = 0x0 - -BEGIN DUMP--------------------------------- - **NO RECORD DATA** - -END DUMP----------------------------------- - recordid = 0xa, size =0 - [EOF] - [/EOF] - - - -

- The next section breaks those records down into an easier - to read format: -

- -[UNKNOWN RECORD:ec] -[UNKNOWN RECORD:5d] -[BOF RECORD] - [HEADER] - [FOOTER] - [HCENTER] - [VCENTER] - [PRINTSETUP] - [UNKNOWN RECORD:33] - [FBI] - [FBI] - [PROTECT] - [UNITS] - [CHART] - [BEGIN] - [SCL] // zoom magnification - [PLOTGROWTH] // font scaling - [FRAME] // border around text - [BEGIN] // default line and area format - [LINEFORMAT] - [AREAFORMAT] - [END] - [SERIES] // start of series - [BEGIN] - [AI] // LINK_TYPE_TITLE_OR_TEXT - [AI] // LINK_TYPE_VALUES - [AI] // LINK_TYPE_CATEGORIES - [AI] // ?? - [DATAFORMAT] // Formatting applies to series? - [BEGIN] // ?? - [UNKNOWN RECORD] - [END] - [SeriesToChartGroup] // Used to support > 1 chart? - [END] - [SHTPROPS] // Some defaults for how chart is displayed. - [DEFAULTTEXT] // Describes the characteristics of the next - // record - [TEXT] // Details of the text that follows in the - // next section - [BEGIN] - [UNKNOWN RECORD] // POS record... looks like I missed this one. - // docs seem to indicate it's better to use - // defaults... - [FONTX] // index to font record. - [AI] // link to text? seems to be linking to nothing - [END] - [DEFAULTTEXT] // contains a category type of 3 which is not - // documented (sigh). - [TEXT] // defines position, color etc for text on chart. - [BEGIN] - [UNKNOWN RECORD] // Another pos record - [FONTX] // font - [AI] // reference type is DIRECT (not sure what this - // means) - [END] - [AXISUSED] // number of axis on the chart. - [AXISPARENT] // axis size and location - [BEGIN] // beginning of axis details - [UNKNOWN RECORD] // Another pos record. - [AXIS] // Category axis - [BEGIN] - [CATSERRANGE] // defines tick marks and other stuff - [AXCEXT] // unit information - [TICK] // tick formating characteristics - [END] - [AXIS] // Value axis - [BEGIN] - [VALUERANGE] // defines tick marks and other stuff - [TICK] // tick formating characteristics - [AXISLINEFORMAT] // major grid line axis format - [LINEFORMAT] // what do the lines look like? - [END] - [PLOTAREA] // marks that the frame following belongs - // to the frame. - [FRAME] // border - [BEGIN] - [LINEFORMAT] // border line - [AREAFORMAT] // border area - [END] - [CHARTFORMAT] // marks a chart group - [BEGIN] - [BAR] // indicates a bar chart - [UNKNOWN RECORD] // apparently this record is ignoreable - [LEGEND] // positioning for the legend - [BEGIN] - [UNKNOWN RECORD] // another position record. - [TEXT] // details of the text that follows - // in the next section - [BEGIN] - [UNKNOWN RECORD] // yet another pos record - [AI] // another link (of type direct) - [END] - [END] - [END] - [END] - [END] - [DIMENSIONS] - [SINDEX] - [SINDEX] - [SINDEX] -[EOF] - -

- Just a quick note on some of the unknown records: -

-
    -
  • EC: MSODRAWING - A Microsoft drawing record. (Need to - track down where this is documented).
  • -
  • 5D: OBJ: Description of a drawing object. (This is going to - be a PITA to implement).
  • -
  • 33: Not documented. :-(
  • -
  • 105f: Not documented. :-(
  • -
  • 104f: POS: Position record (should be able to safely leave this out).
  • -
  • 1022: CHARTFORMATLINK: Can be left out.
  • -
-

- It is currently suspected that many of those records could be - left out when generating a bar chart from scratch. The way - we will be proceeding with this is to write code that generates - most of these records and then start removing them to see - how this effects the chart in excel. -

-
-
Inserting the Chart into the Workbook -
    -
  • - Unknown record (sid=00eb) is inserted before the SST - record. -
  • -
- - ============================================ - rectype = 0xeb, recsize = 0x5a - -BEGIN DUMP--------------------------------- - 00000000 0F 00 00 F0 52 00 00 00 00 00 06 F0 18 00 00 00 ....R........... - 00000010 01 08 00 00 02 00 00 00 02 00 00 00 01 00 00 00 ................ - 00000020 01 00 00 00 03 00 00 00 33 00 0B F0 12 00 00 00 ........3....... - 00000030 BF 00 08 00 08 00 81 01 09 00 00 08 C0 01 40 00 ..............@. - 00000040 00 08 40 00 1E F1 10 00 00 00 0D 00 00 08 0C 00 ..@............. - 00000050 00 08 17 00 00 08 F7 00 00 10 .......... - -END DUMP----------------------------------- - recordid = 0xeb, size =90 - [UNKNOWN RECORD:eb] - .id = eb - [/UNKNOWN RECORD] - - ============================================ - -
    -
  • - Any extra font records are inserted as needed -
  • -
  • - Chart records inserted after DBCell records. -
  • -
-
- -
diff --git a/src/documentation/content/xdocs/hssf/diagram1.xml b/src/documentation/content/xdocs/hssf/diagram1.xml deleted file mode 100644 index fbbe1f66c3..0000000000 --- a/src/documentation/content/xdocs/hssf/diagram1.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - -
- HSSF - Overview - - - - -
- - -
- Usermodel Class Diagram by Matthew Young -

- Usermodel -

-
- -
diff --git a/src/documentation/content/xdocs/hssf/diagrams.xml b/src/documentation/content/xdocs/hssf/diagrams.xml deleted file mode 100644 index 1c1f2a76f9..0000000000 --- a/src/documentation/content/xdocs/hssf/diagrams.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - -
- HSSF - Overview - - - - -
- - -
Overview -

- This section is intended for diagrams (UML/etc) that help - explain HSSF. -

-
    -
  • - HSSF usermodel class diagram - - by Matthew Young (myoung at westernasset dot com) -
  • -
-

- Have more? Add a new "bug" to the bug database with [DOCUMENTATION] - prefacing the description and a link to the file on an http server - somewhere. If you don't have your own webserver, then you can email it - to (acoliver at apache dot org) provided its < 5MB. Diagrams should be - in some format that can be read at least on Linux and Windows. Diagrams - that can be edited are preferrable, but lets face it, there aren't too - many good affordable UML tools yet! And no they don't HAVE to be UML... - just useful. -

-
- -
diff --git a/src/documentation/content/xdocs/hssf/eval-devguide.xml b/src/documentation/content/xdocs/hssf/eval-devguide.xml deleted file mode 100644 index 29c33b8a20..0000000000 --- a/src/documentation/content/xdocs/hssf/eval-devguide.xml +++ /dev/null @@ -1,204 +0,0 @@ - - - - - -
- Developing Formula Evaluation - - -
- -
Introduction -

This document is for developers wishing to contribute to the - FormulaEvaluator API functionality.

-

Currently, contribution is desired for implementing the standard MS - excel functions. Place holder classes for these have been created, - contributors only need to insert implementation for the - individual "evaluate()" methods that do the actual evaluation.

-
-
Overview of FormulaEvaluator -

Briefly, a formula string (along with the sheet and workbook that - form the context in which the formula is evaluated) is first parsed - into RPN tokens using the FormulaParser class in POI-HSSF main. - (If you dont know what RPN tokens are, now is a good time to - read - this.) -

-
The big picture -

RPN tokens are mapped to Eval classes. (Class hierarchy for the Evals - is best understood if you view the class diagram in a class diagram - viewer.) Depending on the type of RPN token (also called as Ptgs - henceforth since that is what the FormulaParser calls the classes) a - specific type of Eval wrapper is constructed to wrap the RPN token and - is pushed on the stack.... UNLESS the Ptg is an OperationPtg. If it is an - OperationPtg, an OperationEval instance is created for the specific - type of OperationPtg. And depending on how many operands it takes, - that many Evals are popped of the stack and passed in an array to - the OperationEval instance's evaluate method which returns an Eval - of subtype ValueEval.Thus an operation in the formula is evaluated.

- An Eval is of subinterface ValueEval or OperationEval. - Operands are always ValueEvals, Operations are always OperationEvals. -

OperationEval.evaluate(Eval[]) returns an Eval which is supposed - to be of type ValueEval (actually since ValueEval is an interface, - the return value is instance of one of the implementations of - ValueEval). The valueEval resulting from evaluate() is pushed on the - stack and the next RPN token is evaluated.... this continues till - eventually there are no more RPN tokens at which point, if the formula - string was correctly parsed, there should be just one Eval on the - stack - which contains the result of evaluating the formula.

-

Ofcourse I glossed over the details of how AreaPtg and ReferencePtg - are handled a little differently, but the code should be self - explanatory for that. Very briefly, the cells included in AreaPtg and - RefPtg are examined and their values are populated in individual - ValueEval objects which are set into the AreaEval and RefEval (ok, - since AreaEval and RefEval are interfaces, the implementations of - AreaEval and RefEval - but you'll figure all that out from the code)

-

OperationEvals for the standard operators have been implemented and tested.

-
-
FunctionEval and FuncVarEval -

FunctionEval is an abstract super class of FuncVarEval. The reason for this is that in the FormulaParser Ptg classes, there are two Ptgs, FuncPtg and FuncVarPtg. In my tests, I did not see FuncPtg being used so there is no corresponding FuncEval right now. But in case the need arises for a FuncVal class, FuncEval and FuncVarEval need to be isolated with a common interface/abstract class, hence FunctionEval.

-

FunctionEval also contains the mapping of which function class maps to which function index. This mapping has been done for all the functions, so all you really have to do is implement the evaluate method in the function class that has not already been implemented. The Function indexes are defined in AbstractFunctionPtg class in POI main.

-
-
-
Walkthrough of an "evaluate()" implementation. -

So here is the fun part - lets walk through the implementation of the excel - function... SQRT()

-
The Code - -public class Sqrt extends NumericFunction { - - private static final ValueEvalToNumericXlator NUM_XLATOR = - new ValueEvalToNumericXlator((short) - ( ValueEvalToNumericXlator.BOOL_IS_PARSED - | ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED - | ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED - | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED - | ValueEvalToNumericXlator.STRING_IS_PARSED - )); - - protected ValueEvalToNumericXlator getXlator() { - return NUM_XLATOR; - } - - public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { - double d = 0; - ValueEval retval = null; - - switch (operands.length) { - default: - retval = ErrorEval.VALUE_INVALID; - break; - case 1: - ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol); - if (ve instanceof NumericValueEval) { - NumericValueEval ne = (NumericValueEval) ve; - d = ne.getNumberValue(); - } - else if (ve instanceof BlankEval) { - // do nothing - } - else { - retval = ErrorEval.NUM_ERROR; - } - } - - if (retval == null) { - d = Math.sqrt(d); - retval = (Double.isNaN(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d); - } - return retval; - } - -} - -
-
Implementation Details -
    -
  • The first thing to realise is that classes already exist, even for functions that are not yet implemented. - Just that they extend from DefaultFunctionImpl whose behaviour is to return an ErrorEval.FUNCTION_NOT_IMPLEMENTED value.
  • -
  • In order to implement SQRT(..), we need to: a. Extend from the correct Abstract super class; b. implement the evaluate(..) method
  • -
  • Hence we extend SQRT(..) from the predefined class NumericFunction
  • -
  • Since SQRT(..) takes a single argument, we verify the length of the operands array else set the return value to ErrorEval.VALUE_INVALID
  • -
  • Next we normalize each operand to a limited set of ValueEval subtypes, specifically, we call the function - singleOperandEvaluate(..) to do conversions of different value eval types to one of: NumericValueEval, - BlankEval and ErrorEval. The conversion logic is configured by a ValueEvalToNumericXlator instance which - is returned by the Factory method: getXlator(..) The flags used to create the ValueEvalToNumericXlator - instance are briefly explained as follows: - BOOL_IS_PARSED means whether this function treats Boolean values as 1, - REF_BOOL_IS_PARSED means whether Boolean values in cell references are parsed or not. - So also, EVALUATED_REF_BOOL_IS_PARSED means if the operand was a RefEval that was assigned a - Boolean value as a result of evaluation of the formula that it contained. - eg. SQRT(TRUE) returns 1: This means BOOL_IS_PARSED should be set. - SQRT(A1) returns 1 when A1 has TRUE: This means REF_BOOL_IS_PARSED should be set. - SQRT(A1) returns 1 when A1 has a formula that evaluates to TRUE: This means EVALUATED_REF_BOOL_IS_PARSED should be set. - If the flag is not set for a particular case, that case is ignored (treated as if the cell is blank) _unless_ - there is a flag like: STRING_IS_INVALID_VALUE (which means that Strings should be treated as resulting in VALUE_INVALID ErrorEval) -
  • -
  • Next perform the appropriate Math function on the double value (if an error didnt occur already).
  • -
  • Finally before returning the NumberEval wrapping the double value that - you computed, do one final check to see if the double is a NaN, (or if it is "Infinite") - If it is return the appropriate ErrorEval instance. Note: The OpenOffice.org error codes - should NOT be preferred. Instead use the excel specific error codes like VALUE_INVALID, NUM_ERROR, DIV_ZERO etc. - (Thanks to Avik for bringing this issue up early!) The Oo.o ErrorCodes will be removed (if they havent already been :)
  • -
-
-
Modelling Excel Semantics -

Strings are ignored. Booleans are ignored!!!. Actually here's the info on Bools: - if you have formula: "=TRUE+1", it evaluates to 2. - So also, when you use TRUE like this: "=SUM(1,TRUE)", you see the result is: 2. - So TRUE means 1 when doing numeric calculations, right? - Wrong! - Because when you use TRUE in referenced cells with arithmetic functions, it evaluates to blank - meaning it is not evaluated - as if it was string or a blank cell. - eg. "=SUM(1,A1)" when A1 is TRUE evaluates to 1. - This behaviour changes depending on which function you are using. eg. SQRT(..) that was - described earlier treats a TRUE as 1 in all cases. This is why the configurable ValueEvalToNumericXlator - class had to be written. -

-

Note that when you are extending from an abstract function class like - NumericFunction (rather than implementing the interface o.a.p.hssf.record.formula.eval.Function directly) - you can use the utility methods in the super class - singleOperandEvaluate(..) - to quickly - reduce the different ValueEval subtypes to a small set of possible types. However when - implemenitng the Function interface directly, you will have to handle the possiblity - of all different ValueEval subtypes being sent in as 'operands'. (Hard to put this in - word, please have a look at the code for NumericFunction for an example of - how/why different ValueEvals need to be handled) -

-
-
-
Testing Framework -

Automated testing of the implemented Function is easy. - The source code for this is in the file: o.a.p.h.record.formula.GenericFormulaTestCase.java - This class has a reference to the test xls file (not /a/ test xls, /the/ test xls :) - which may need to be changed for your environment. Once you do that, in the test xls, - locate the entry for the function that you have implemented and enter different tests - in a cell in the FORMULA row. Then copy the "value of" the formula that you entered in the - cell just below it (this is easily done in excel as: - [copy the formula cell] > [go to cell below] > Edit > Paste Special > Values > "ok"). - You can enter multiple such formulas and paste their values in the cell below and the - test framework will automatically test if the formula evaluation matches the expected - value (Again, hard to put in words, so if you will, please take time to quickly look - at the code and the currently entered tests in the patch attachment "FormulaEvalTestData.xls" - file). -

-
- -
\ No newline at end of file diff --git a/src/documentation/content/xdocs/hssf/eval.xml b/src/documentation/content/xdocs/hssf/eval.xml deleted file mode 100644 index 8d63512173..0000000000 --- a/src/documentation/content/xdocs/hssf/eval.xml +++ /dev/null @@ -1,248 +0,0 @@ - - - - - -
- Formula Evaluation - - -
- -
Introduction -

The POI formula evaluation code enables you to calculate the result of - formulas in Excels sheets read-in, or created in POI. This document explains - how to use the API to evaluate your formulas. -

- This code currently lives the scratchpad area of the POI SVN repository. - Ensure that you have the scratchpad jar or the scratchpad build area in your - classpath before experimenting with this code. You are advised - to make use of a recent SVN checkout, as new functions are - being supported fairly frequently. - -
- - -
Status -

The code currently provides implementations for all the arithmatic operators. - It also provides implementations for approx. 100 built in - functions in Excel. The framework however makes is easy to add - implementation of new functions. See the Formula - evaluation development guide for details.

-

Note that user-defined functions are not supported, and is not likely to done - any time soon... at least, not till there is a VB implementation in Java! -

-
-
User API How-TO -

The following code demonstrates how to use the HSSFFormulaEvaluator - in the context of other POI excel reading code. -

-

There are several ways in which you can use the HSSFFormulaEvalutator API.

- - -
Using HSSFFormulaEvaluator.<strong>evaluate</strong>(HSSFCell cell) -

This evaluates a given cell, and returns the new value, - without affecting the cell

- -FileInputStream fis = new FileInputStream("c:/temp/test.xls"); -HSSFWorkbook wb = new HSSFWorkbook(fis); -HSSFSheet sheet = wb.getSheetAt(0); -HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb); - -// suppose your formula is in B3 -CellReference cellReference = new CellReference("B3"); -HSSFRow row = sheet.getRow(cellReference.getRow()); -HSSFCell cell = row.getCell(cellReference.getCol()); - -evaluator.setCurrentRow(row); -HSSFFormulaEvaluator.CellValue cellValue = evaluator.evaluate(cell); - -switch (cellValue.getCellType()) { - case HSSFCell.CELL_TYPE_BOOLEAN: - System.out.println(cellValue.getBooleanValue()); - break; - case HSSFCell.CELL_TYPE_NUMERIC: - System.out.println(cellValue.getNumberValue()); - break; - case HSSFCell.CELL_TYPE_STRING: - System.out.println(cellValue.getStringValue()); - break; - case HSSFCell.CELL_TYPE_BLANK: - break; - case HSSFCell.CELL_TYPE_ERROR: - break; - - // CELL_TYPE_FORMULA will never happen - case HSSFCell.CELL_TYPE_FORMULA: - break; -} - -

Thus using the retrieved value (of type - HSSFFormulaEvaluator.CellValue - a nested class) returned - by HSSFFormulaEvaluator is similar to using a HSSFCell object - containing the value of the formula evaluation. CellValue is - a simple value object and does not maintain reference - to the original cell. -

-
- - -
Using HSSFFormulaEvaluator.<strong>evaluateFormulaCell</strong>(HSSFCell cell) -

evaluateFormulaCell(HSSFCell cell) - will check to see if the supplied cell is a formula cell. - If it isn't, then no changes will be made to it. If it is, - then the formula is evaluated. The value for the formula - is saved alongside it, to be displayed in excel. The - formula remains in the cell, just with a new value

-

The return of the function is the type of the - formula result, such as HSSFCell.CELL_TYPE_BOOLEAN

- -FileInputStream fis = new FileInputStream("/somepath/test.xls"); -HSSFWorkbook wb = new HSSFWorkbook(fis); -HSSFSheet sheet = wb.getSheetAt(0); -HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb); - -// suppose your formula is in B3 -CellReference cellReference = new CellReference("B3"); -HSSFRow row = sheet.getRow(cellReference.getRow()); -HSSFCell cell = row.getCell(cellReference.getCol()); -evaluator.setCurrentRow(row); - -if (cell!=null) { - switch (evaluator.evaluateFormulaCell(cell)) { - case HSSFCell.CELL_TYPE_BOOLEAN: - System.out.println(cell.getBooleanCellValue()); - break; - case HSSFCell.CELL_TYPE_NUMERIC: - System.out.println(cell.getNumberCellValue()); - break; - case HSSFCell.CELL_TYPE_STRING: - System.out.println(cell.getStringCellValue()); - break; - case HSSFCell.CELL_TYPE_BLANK: - break; - case HSSFCell.CELL_TYPE_ERROR: - System.out.println(cell.getErrorCellValue()); - break; - - // CELL_TYPE_FORMULA will never occur - case HSSFCell.CELL_TYPE_FORMULA: - break; - } -} - -
- - -
Using HSSFFormulaEvaluator.<strong>evaluateInCell</strong>(HSSFCell cell) -

evaluateInCell(HSSFCell cell) will check to - see if the supplied cell is a formula cell. If it isn't, - then no changes will be made to it. If it is, then the - formula is evaluated, and the new value saved into the cell, - in place of the old formula.

- -FileInputStream fis = new FileInputStream("/somepath/test.xls"); -HSSFWorkbook wb = new HSSFWorkbook(fis); -HSSFSheet sheet = wb.getSheetAt(0); -HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb); - -// suppose your formula is in B3 -CellReference cellReference = new CellReference("B3"); -HSSFRow row = sheet.getRow(cellReference.getRow()); -HSSFCell cell = row.getCell(cellReference.getCol()); -evaluator.setCurrentRow(row); - -if (cell!=null) { - switch (evaluator.evaluateInCell(cell).getCellType()) { - case HSSFCell.CELL_TYPE_BOOLEAN: - System.out.println(cell.getBooleanCellValue()); - break; - case HSSFCell.CELL_TYPE_NUMERIC: - System.out.println(cell.getNumberCellValue()); - break; - case HSSFCell.CELL_TYPE_STRING: - System.out.println(cell.getStringCellValue()); - break; - case HSSFCell.CELL_TYPE_BLANK: - break; - case HSSFCell.CELL_TYPE_ERROR: - System.out.println(cell.getErrorCellValue()); - break; - - // CELL_TYPE_FORMULA will never occur - case HSSFCell.CELL_TYPE_FORMULA: - break; - } -} - -
- - -
Re-calculating all formulas in a Workbook - -FileInputStream fis = new FileInputStream("/somepath/test.xls"); -HSSFWorkbook wb = new HSSFWorkbook(fis); -for(int sheetNum = 0; sheetNum < wb.getNumberOfSheets(); sheetNum++) { - HSSFSheet sheet = wb.getSheetAt(sheetNum); - HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb); - - for(Iterator rit = sheet.rowIterator(); rit.hasNext();) { - HSSFRow r = (HSSFRow)rit.next(); - evaluator.setCurrentRow(r); - - for(Iterator cit = r.cellIterator(); cit.hasNext();) { - HSSFCell c = (HSSFCell)cit.next(); - if(c.getCellType() == HSSFCell.CELL_TYPE_FORMULA) { - evaluator.evaluateFormulaCell(c); - } - } - } -} -wb.write(new FileOutputStream("/somepath/changed.xls")); - -
-
- - -
Performance Notes -
    -
  • Generally you should have to create only one HSSFFormulaEvaluator - instance per sheet, but there really is no overhead in creating - multiple HSSFFormulaEvaluators per sheet other than that of the - HSSFFormulaEvaluator object creation. -
  • -
  • Also note that HSSFFormulaEvaluator maintains a reference to - the sheet and workbook, so ensure that the evaluator instance - is available for garbage collection when you are done with it - (in other words don't maintain long lived reference to - HSSFFormulaEvaluator if you don't really need to - unless - all references to the sheet and workbook are removed, these - don't get garbage collected and continue to occupy potentially - large amounts of memory). -
  • -
  • CellValue instances however do not maintain reference to the - HSSFCell or the sheet or workbook, so these can be long-lived - objects without any adverse effect on performance. -
  • -
-
- -
diff --git a/src/documentation/content/xdocs/hssf/formula.xml b/src/documentation/content/xdocs/hssf/formula.xml deleted file mode 100644 index d8ced8fb20..0000000000 --- a/src/documentation/content/xdocs/hssf/formula.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - - -
- Formula Support - - - -
- -
Introduction -

- This document describes the current state of formula support in POI. - The information in this document currently applies to the 2.0 version of POI. - Since this area is a work in progress, this document will be updated with new features as and - when they are added. -

- -
-
The basics -

- In org.apache.poi.hssf.usermodel.HSSFCell - setCellFormula("formulaString") is used to add a formula to sheet and - getCellFormula() is used to retrieve the string representation of a formula. -

-

- We aim to support the complete excel grammer for formulas. Thus, the string that you pass in - to the setCellFormula call should be what you expect to type into excel. Also, note - that you should NOT add a "=" to the front of the string. -

-
-
Supported Features -
    -
  • Cell References
  • -
  • String, integer and floating point literals
  • -
  • Area references
  • -
  • Relative or absolute references
  • -
  • Arithmetic and logical operators
  • -
  • Sheet or Macro Functions (inlcuding logical functions)
  • -
  • Sheet References
  • -
  • Formual return values (number or string)
  • -
-
-
Partially supported -
    -
  • Formula tokens in Excel are stored in one of three possible classes : - Reference, Value and Array. Based on the location of a token, its class can change - in complicated and undocumented ways. While we have support for most cases, we - are not sure if we have covered all bases (since there is no documentation for this area.) - We would therefore like you to report any - occurence of #VALUE! in a cell upon opening a POI generated workbook in excel. (Check that - typing the formula into Excel directly gives a valid result.) -
  • - -
-
-
Not yet supported -
    -
  • Array formulas
  • -
  • Unary Operators
  • -
  • 3D References
  • -
  • Error Values (cells containing #REF's or #VALUE's)
  • -
  • Everything else :)
  • -
-
- -
Internals -

- Formulas in Excel are stored as sequences of tokens in Reverse Polish Notation order. The - open office XLS spec is the best - documentation you will find for the format. -

- -

- The tokens used by excel are modelled as individual *Ptg classes in the - org.apache.poi.hssf.record.formula package. -

-

- The task of parsing a formula string into an array of RPN ordered tokens is done by the - org.apache.poi.hssf.record.formula.FormulaParser class. This class implements a hand - written recursive descent parser. -

-

Check out the javadocs for details. -

-
- - -
diff --git a/src/documentation/content/xdocs/hssf/hacking-hssf.xml b/src/documentation/content/xdocs/hssf/hacking-hssf.xml deleted file mode 100644 index 7247ad0ee7..0000000000 --- a/src/documentation/content/xdocs/hssf/hacking-hssf.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - - - -
- Hacking HSSF - - - - -
- -
Where Can I Find Documentation on Feature X -

- You might find the - 'Excel 97 Developer's Kit' (out of print, Microsoft Press, no - restrictive covenants, available on Amazon.com) helpful for - understanding the file format. -

-

- Also useful is the open office XLS spec. We - are collaborating with the maintainer of the spec so if you think you can add something to their - document just send through your changes. -

-
-
Help, I Can't Find Feature X Documented Anywhere -
    -
  1. - Look at OpenOffice.org or Gnumeric sources if its implemented there. -
  2. -
  3. - Use org.apache.poi.hssf.dev.BiffViewer to view the structure of the - file. Experiment by adding one criteria entry at a time. See what it - does to the structure, infer behavior and structure from it. Using the - unix diff command (or get cygwin from www.cygwin.com for windows) you - can figure out a lot very quickly. Unimplemented records show up as - 'UNKNOWN' and prints a hex dump. -
  4. -
-
-
Low-level Record Generation -

- Low level records can be time consuming to created. We created a record - generator to help generate some of the simpler tasks. -

-

- We use XML - descriptors to generate the Java code (which sure beats the heck out of - the PERL scripts originally used ;-) for low level records. The - generator is kinda alpha-ish right now and could use some enhancement, - so you may find that to be about 1/2 of the work. Notice this is in - org.apache.poi.hssf.record.definitions. -

-
-
Important Notice -

One thing to note: If you are making a large code contribution we need to ensure - any participants in this process have never - signed a "Non Disclosure Agreement" with Microsoft, and have not - received any information covered by such an agreement. If they have - they'll not be able to participate in the POI project. For large contributions we - may ask you to sign an agreement.

-
-
What Can I Work On? -

Check our todo list or simply look for missing functionality. Start small - and work your way up.

-
-
What Else Should I Know? -

Make sure you read the contributing section - as it contains more generation information about contributing to POI in general.

-
- -
diff --git a/src/documentation/content/xdocs/hssf/how-to.xml b/src/documentation/content/xdocs/hssf/how-to.xml deleted file mode 100644 index a4ac41209d..0000000000 --- a/src/documentation/content/xdocs/hssf/how-to.xml +++ /dev/null @@ -1,591 +0,0 @@ - - - - - -
- The New Halloween Document - - - - - - -
- -
How to use the HSSF API - -
Capabilities -

This release of the how-to outlines functionality for the CVS HEAD. - Those looking for information on previous releases should - look in the documentation distributed with that release.

-

- HSSF allows numeric, string, date or formuala cell values to be written to - or read from an XLS file. Also - in this release is row and column sizing, cell styling (bold, - italics, borders,etc), and support for both built-in and user - defined data formats. Also available is - an event-based API for reading XLS files. - It differs greatly from the read/write API - and is intended for intermediate developers who need a smaller - memory footprint. -

-
-
Different APIs -

There are a few different ways to access the HSSF API. These - have different characteristics, so you should read up on - all to select the best for you.

-
    -
  • User API
  • -
  • Event API
  • -
  • Event API with extensions to be Record Aware
  • -
  • Low Level API
  • -
-
-
-
General Use - -
User API -
Writing a new file - -

The high level API (package: org.apache.poi.hssf.usermodel) - is what most people should use. Usage is very simple. -

-

Workbooks are created by creating an instance of - org.apache.poi.hssf.usermodel.HSSFWorkbook. -

-

Sheets are created by calling createSheet() from an existing - instance of HSSFWorkbook, the created sheet is automatically added in - sequence to the workbook. Sheets do not in themselves have a sheet - name (the tab at the bottom); you set - the name associated with a sheet by calling - HSSFWorkbook.setSheetName(sheetindex,"SheetName",encoding). - The name may be in 8bit format (HSSFWorkbook.ENCODING_COMPRESSED_UNICODE) - or Unicode (HSSFWorkbook.ENCODING_UTF_16). Default encoding is 8bit per char. -

-

Rows are created by calling createRow(rowNumber) from an existing - instance of HSSFSheet. Only rows that have cell values should be - added to the sheet. To set the row's height, you just call - setRowHeight(height) on the row object. The height must be given in - twips, or 1/20th of a point. If you prefer, there is also a - setRowHeightInPoints method. -

-

Cells are created by calling createCell(column, type) from an - existing HSSFRow. Only cells that have values should be added to the - row. Cells should have their cell type set to either - HSSFCell.CELL_TYPE_NUMERIC or HSSFCell.CELL_TYPE_STRING depending on - whether they contain a numeric or textual value. Cells must also have - a value set. Set the value by calling setCellValue with either a - String or double as a parameter. Individual cells do not have a - width; you must call setColumnWidth(colindex, width) (use units of - 1/256th of a character) on the HSSFSheet object. (You can't do it on - an individual basis in the GUI either).

-

Cells are styled with HSSFCellStyle objects which in turn contain - a reference to an HSSFFont object. These are created via the - HSSFWorkbook object by calling createCellStyle() and createFont(). - Once you create the object you must set its parameters (colors, - borders, etc). To set a font for an HSSFCellStyle call - setFont(fontobj). -

-

Once you have generated your workbook, you can write it out by - calling write(outputStream) from your instance of Workbook, passing - it an OutputStream (for instance, a FileOutputStream or - ServletOutputStream). You must close the OutputStream yourself. HSSF - does not close it for you. -

-

Here is some example code (excerpted and adapted from - org.apache.poi.hssf.dev.HSSF test class):

- -
-
Reading or modifying an existing file - -

Reading in a file is equally simple. To read in a file, create a -new instance of org.apache.poi.poifs.Filesystem, passing in an open InputStream, such as a FileInputStream -for your XLS, to the constructor. Construct a new instance of -org.apache.poi.hssf.usermodel.HSSFWorkbook passing the -Filesystem instance to the constructor. From there you have access to -all of the high level model objects through their assessor methods -(workbook.getSheet(sheetNum), sheet.getRow(rownum), etc). -

-

Modifying the file you have read in is simple. You retrieve the -object via an assessor method, remove it via a parent object's remove -method (sheet.removeRow(hssfrow)) and create objects just as you -would if creating a new xls. When you are done modifying cells just -call workbook.write(outputstream) just as you did above.

-

An example of this can be seen in -org.apache.poi.hssf.dev.HSSF.

-
-
- - -
Event API - -

The event API is newer than the User API. It is intended for intermediate - developers who are willing to learn a little bit of the low level API - structures. Its relatively simple to use, but requires a basic - understanding of the parts of an Excel file (or willingness to - learn). The advantage provided is that you can read an XLS with a - relatively small memory footprint. -

-

One important thing to note with the basic Event API is that it - triggers events only for things actually stored within the file. - With the XLS file format, it is quite common for things that - have yet to be edited to simply not exist in the file. This means - there may well be apparent "gaps" in the record stream, which - you either need to work around, or use the - Record Aware extension - to the Event API.

-

To use this API you construct an instance of - org.apache.poi.hssf.eventmodel.HSSFRequest. Register a class you - create that supports the - org.apache.poi.hssf.eventmodel.HSSFListener interface using the - HSSFRequest.addListener(yourlistener, recordsid). The recordsid - should be a static reference number (such as BOFRecord.sid) contained - in the classes in org.apache.poi.hssf.record. The trick is you - have to know what these records are. Alternatively you can call - HSSFRequest.addListenerForAllRecords(mylistener). In order to learn - about these records you can either read all of the javadoc in the - org.apache.poi.hssf.record package or you can just hack up a - copy of org.apache.poi.hssf.dev.EFHSSF and adapt it to your - needs. TODO: better documentation on records.

-

Once you've registered your listeners in the HSSFRequest object - you can construct an instance of - org.apache.poi.poifs.filesystem.FileSystem (see POIFS howto) and - pass it your XLS file inputstream. You can either pass this, along - with the request you constructed, to an instance of HSSFEventFactory - via the HSSFEventFactory.processWorkbookEvents(request, Filesystem) - method, or you can get an instance of DocumentInputStream from - Filesystem.createDocumentInputStream("Workbook") and pass - it to HSSFEventFactory.processEvents(request, inputStream). Once you - make this call, the listeners that you constructed receive calls to - their processRecord(Record) methods with each Record they are - registered to listen for until the file has been completely read. -

-

A code excerpt from org.apache.poi.hssf.dev.EFHSSF (which is - in CVS or the source distribution) is reprinted below with excessive - comments:

- -
- - -
Record Aware Event API -

-This is an experimental extension to the normal -Event API. With this, your listener -will be called with extra, dummy records. These dummy records should -alert you to records which aren't present in the file (eg cells that have -yet to be edited), and allow you to handle these. -

-

-There are three dummy records that your HSSFListener will be called with: -

-
    -
  • org.apache.poi.hssf.eventusermodel.dummyrecord.MissingRowDummyRecord -
    - This is called during the row record phase (which typically occurs before - the cell records), and indicates that the row record for the given - row is not present in the file.
  • -
  • org.apache.poi.hssf.eventusermodel.dummyrecord.MissingCellDummyRecord -
    - This is called during the cell record phase. It is called when a cell - record is encountered which leaves a gap between it an the previous one. - You can get multiple of these, before the real cell record.
  • -
  • org.apache.poi.hssf.eventusermodel.dummyrecord.LastCellOfRowDummyRecord -
    - This is called after the last cell of a given row. It indicates that there - are no more cells for the row, and also tells you how many cells you have - had. For a row with no cells, this will be the only record you get.
  • -
-

-To use the Record Aware Event API, you should create an -org.apache.poi.hssf.eventusermodel.MissingRecordAwareHSSFListener, and pass -it your HSSFListener. Then, register the MissingRecordAwareHSSFListener -to the event model, and start that as normal. -

-

-One example use for this API is to write a CSV outputter, which always -outputs a minimum number of columns, even where the file doesn't contain -some of the rows or cells. It can be found at -/src/scratchpad/examples/src/org/apache/poi/hssf/eventusermodel/examples/XLS2CSVmra.java, -and may be called on the command line, or from within your own code. -The latest version is always available from -subversion. -

-

-This code is currently in the scratchpad section, so you will either - need to include the scratchpad jar on your classpath, or build from a - subversion checkout. -

-
- - -
Low Level APIs - -

The low level API is not much to look at. It consists of lots of -"Records" in the org.apache.poi.hssf.record.* package, -and set of helper classes in org.apache.poi.hssf.model.*. The -record classes are consistent with the low level binary structures -inside a BIFF8 file (which is embedded in a POIFS file system). You -probably need the book: "Microsoft Excel 97 Developer's Kit" -from Microsoft Press in order to understand how these fit together -(out of print but easily obtainable from Amazon's used books). In -order to gain a good understanding of how to use the low level APIs -should view the source in org.apache.poi.hssf.usermodel.* and -the classes in org.apache.poi.hssf.model.*. You should read the -documentation for the POIFS libraries as well.

-
-
Generating XLS from XML -

If you wish to generate an XLS file from some XML, it is possible to -write your own XML processing code, then use the User API to write out -the document.

-

The other option is to use Cocoon. -In Cocoon, there is the HSSF Serializer, -which takes in XML (in the gnumeric format), and outputs an XLS file for you.

-
-
HSSF Class/Test Application - -

The HSSF application is nothing more than a test for the high -level API (and indirectly the low level support). The main body of -its code is repeated above. To run it: -

-
    -
  • download the poi-alpha build and untar it (tar xvzf - tarball.tar.gz) -
  • -
  • set up your classpath as follows: - export HSSFDIR={wherever you put HSSF's jar files} -export LOG4JDIR={wherever you put LOG4J's jar files} -export CLASSPATH=$CLASSPATH:$HSSFDIR/hssf.jar:$HSSFDIR/poi-poifs.jar:$HSSFDIR/poi-util.jar:$LOG4JDIR/jog4j.jar -
  • type: - java org.apache.poi.hssf.dev.HSSF ~/myxls.xls write
  • -
-

-

This should generate a test sheet in your home directory called "myxls.xls".

-
    -
  • Type: - java org.apache.poi.hssf.dev.HSSF ~/input.xls output.xls -
    -
    -This is the read/write/modify test. It reads in the spreadsheet, modifies a cell, and writes it back out. -Failing this test is not necessarily a bad thing. If HSSF tries to modify a non-existant sheet then this will -most likely fail. No big deal.
  • -
-
-
Logging facility -

POI can dynamically select its logging implementation. POI tries to - create a logger using the System property named "org.apache.poi.util.POILogger". - Out of the box this can be set to one of three values: -

-
    -
  • org.apache.poi.util.CommonsLogger
  • -
  • org.apache.poi.util.NullLogger
  • -
  • org.apache.poi.util.SystemOutLogger
  • -
-

- If the property is not defined or points to an invalid classthen the NullLogger is used. -

-

- Refer to the commons logging package level javadoc for more information concerning how to - configure commons logging. -

-
-
HSSF Developer's Tools - -

HSSF has a number of tools useful for developers to debug/develop -stuff using HSSF (and more generally XLS files). We've already -discussed the app for testing HSSF read/write/modify capabilities; -now we'll talk a bit about BiffViewer. Early on in the development of -HSSF, it was decided that knowing what was in a record, what was -wrong with it, etc. was virtually impossible with the available -tools. So we developed BiffViewer. You can find it at -org.apache.poi.hssf.dev.BiffViewer. It performs two basic -functions and a derivative. -

-

The first is "biffview". To do this you run it (assumes -you have everything setup in your classpath and that you know what -you're doing enough to be thinking about this) with an xls file as a -parameter. It will give you a listing of all understood records with -their data and a list of not-yet-understood records with no data -(because it doesn't know how to interpret them). This listing is -useful for several things. First, you can look at the values and SEE -what is wrong in quasi-English. Second, you can send the output to a -file and compare it. -

-

The second function is "big freakin dump", just pass a -file and a second argument matching "bfd" exactly. This -will just make a big hexdump of the file. -

-

Lastly, there is "mixed" mode which does the same as -regular biffview, only it includes hex dumps of certain records -intertwined. To use that just pass a file with a second argument -matching "on" exactly.

-

In the next release cycle we'll also have something called a -FormulaViewer. The class is already there, but its not very useful -yet. When it does something, we'll document it.

- -
-
What's Next? - -

Further effort on HSSF is going to focus on the following major areas:

-
    -
  • Performance: POI currently uses a lot of memory for large sheets.
  • -
  • Charts: This is a hard problem, with very little documentation.
  • -
-

So jump in!

- -
- -
- -
diff --git a/src/documentation/content/xdocs/hssf/index.xml b/src/documentation/content/xdocs/hssf/index.xml deleted file mode 100644 index 69accc624f..0000000000 --- a/src/documentation/content/xdocs/hssf/index.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - -
- POI-HSSF - Java API To Access Microsoft Excel Format Files - Overview - - - - -
- - -
- Overview - -

HSSF is the POI Project's pure Java implementation of the Excel - '97(-2007) file format. It does not support the new - Excel 2007 .xlsx OOXML file format, which is not OLE2 based.

-

HSSF provides a way to read spreadsheets create, modify, read and write XLS spreadsheets - It provides: -

-
    -
  • low level structures for those with special needs
  • -
  • an eventmodel api for efficient read-only access
  • -
  • a full usermodel api for creating, reading and modifying XLS files
  • -
-

- An alternate way of generating a spreadsheet is via the Cocoon serializer (yet you'll still be using HSSF indirectly). - With Cocoon you can serialize any XML datasource (which might be a ESQL page outputting in SQL for instance) by simply - applying the stylesheet and designating the serializer. -

-

- If you're merely reading spreadsheet data, then use the eventmodel api - in the org.apache.poi.hssf.eventusermodel package. -

-

- If you're modifying spreadsheet data then use the usermodel api. You - can also generate spreadsheets this way. -

- -
- -
diff --git a/src/documentation/content/xdocs/hssf/limitations.xml b/src/documentation/content/xdocs/hssf/limitations.xml deleted file mode 100644 index 8dad71e172..0000000000 --- a/src/documentation/content/xdocs/hssf/limitations.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - -
- Limitations - - - -
- -
Version 2.5 limitations -

- The intent of this document is to outline some of the known limitations of the - POI HSSF API's. It is not intended to be complete list of every bug or missing - feature of HSSF, rather it's purpose is to provide a broad feel for some of the - functionality that is missing or broken. -

-
    -
  • - Charts

    - You can not currently create charts. You can - however create a chart in Excel, modify the chart data values using HSSF and write - a new spreadsheet out. This is possible because POI attempts to keep existing records - intact as far as possible.

    -
  • -
  • - Macros

    - Macros can not be created. However, reading and re-writing files containing macros will - safely preserve the macros.

    -
  • -
  • - Pivot Tables

    - Generating pivot tables is not supported. It has been reported that files containing pivot - tables can be read and re-written safely. -
  • -
-
- -
diff --git a/src/documentation/content/xdocs/hssf/quick-guide.xml b/src/documentation/content/xdocs/hssf/quick-guide.xml deleted file mode 100644 index 66da604892..0000000000 --- a/src/documentation/content/xdocs/hssf/quick-guide.xml +++ /dev/null @@ -1,1398 +0,0 @@ - - - - - -
- Busy Developers' Guide to HSSF Features - - - - -
- -
Busy Developers' Guide to Features -

- Want to use HSSF read and write spreadsheets in a hurry? This guide is for you. If you're after - more in-depth coverage of the HSSF user-API please consult the HOWTO - guide as it contains actual descriptions of how to use this stuff. -

-
Index of Features -
    -
  • How to create a new workbook
  • -
  • How to create a sheet
  • -
  • How to create cells
  • -
  • How to create date cells
  • -
  • Working with different types of cells
  • -
  • Iterate over rows and cells
  • -
  • Text Extraction
  • -
  • Aligning cells
  • -
  • Working with borders
  • -
  • Fills and color
  • -
  • Merging cells
  • -
  • Working with fonts
  • -
  • Custom colors
  • -
  • Reading and writing
  • -
  • Use newlines in cells.
  • -
  • Create user defined data formats
  • -
  • Fit Sheet to One Page
  • -
  • Set print area for a sheet
  • -
  • Set page numbers on the footer of a sheet
  • -
  • Shift rows
  • -
  • Set a sheet as selected
  • -
  • Set the zoom magnification for a sheet
  • -
  • Create split and freeze panes
  • -
  • Repeating rows and columns
  • -
  • Headers and Footers
  • -
  • Drawing Shapes
  • -
  • Styling Shapes
  • -
  • Shapes and Graphics2d
  • -
  • Outlining
  • -
  • Images
  • -
  • Named Ranges and Named Cells
  • -
  • How to set cell comments
  • -
  • How to adjust column width to fit the contents
  • -
  • Hyperlinks
  • -
-
-
Features - -
New Workbook - - HSSFWorkbook wb = new HSSFWorkbook(); - FileOutputStream fileOut = new FileOutputStream("workbook.xls"); - wb.write(fileOut); - fileOut.close(); - -
- -
New Sheet - - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet1 = wb.createSheet("new sheet"); - HSSFSheet sheet2 = wb.createSheet("second sheet"); - FileOutputStream fileOut = new FileOutputStream("workbook.xls"); - wb.write(fileOut); - fileOut.close(); - -
- -
Creating Cells - - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet("new sheet"); - - // Create a row and put some cells in it. Rows are 0 based. - HSSFRow row = sheet.createRow((short)0); - // Create a cell and put a value in it. - HSSFCell cell = row.createCell((short)0); - cell.setCellValue(1); - - // Or do it on one line. - row.createCell((short)1).setCellValue(1.2); - row.createCell((short)2).setCellValue("This is a string"); - row.createCell((short)3).setCellValue(true); - - // Write the output to a file - FileOutputStream fileOut = new FileOutputStream("workbook.xls"); - wb.write(fileOut); - fileOut.close(); - -
- -
Creating Date Cells - - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet("new sheet"); - - // Create a row and put some cells in it. Rows are 0 based. - HSSFRow row = sheet.createRow((short)0); - - // Create a cell and put a date value in it. The first cell is not styled - // as a date. - HSSFCell cell = row.createCell((short)0); - cell.setCellValue(new Date()); - - // we style the second cell as a date (and time). It is important to - // create a new cell style from the workbook otherwise you can end up - // modifying the built in style and effecting not only this cell but other cells. - HSSFCellStyle cellStyle = wb.createCellStyle(); - cellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("m/d/yy h:mm")); - cell = row.createCell((short)1); - cell.setCellValue(new Date()); - cell.setCellStyle(cellStyle); - - // Write the output to a file - FileOutputStream fileOut = new FileOutputStream("workbook.xls"); - wb.write(fileOut); - fileOut.close(); - -
- -
Working with different types of cells - - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet("new sheet"); - HSSFRow row = sheet.createRow((short)2); - row.createCell((short) 0).setCellValue(1.1); - row.createCell((short) 1).setCellValue(new Date()); - row.createCell((short) 2).setCellValue("a string"); - row.createCell((short) 3).setCellValue(true); - row.createCell((short) 4).setCellType(HSSFCell.CELL_TYPE_ERROR); - - // Write the output to a file - FileOutputStream fileOut = new FileOutputStream("workbook.xls"); - wb.write(fileOut); - fileOut.close(); - -
- -
Demonstrates various alignment options - - public static void main(String[] args) - throws IOException - { - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet("new sheet"); - HSSFRow row = sheet.createRow((short) 2); - createCell(wb, row, (short) 0, HSSFCellStyle.ALIGN_CENTER); - createCell(wb, row, (short) 1, HSSFCellStyle.ALIGN_CENTER_SELECTION); - createCell(wb, row, (short) 2, HSSFCellStyle.ALIGN_FILL); - createCell(wb, row, (short) 3, HSSFCellStyle.ALIGN_GENERAL); - createCell(wb, row, (short) 4, HSSFCellStyle.ALIGN_JUSTIFY); - createCell(wb, row, (short) 5, HSSFCellStyle.ALIGN_LEFT); - createCell(wb, row, (short) 6, HSSFCellStyle.ALIGN_RIGHT); - - // Write the output to a file - FileOutputStream fileOut = new FileOutputStream("workbook.xls"); - wb.write(fileOut); - fileOut.close(); - - } - - /** - * Creates a cell and aligns it a certain way. - * - * @param wb the workbook - * @param row the row to create the cell in - * @param column the column number to create the cell in - * @param align the alignment for the cell. - */ - private static void createCell(HSSFWorkbook wb, HSSFRow row, short column, short align) - { - HSSFCell cell = row.createCell(column); - cell.setCellValue("Align It"); - HSSFCellStyle cellStyle = wb.createCellStyle(); - cellStyle.setAlignment(align); - cell.setCellStyle(cellStyle); - } - -
- -
Working with borders - - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet("new sheet"); - - // Create a row and put some cells in it. Rows are 0 based. - HSSFRow row = sheet.createRow((short) 1); - - // Create a cell and put a value in it. - HSSFCell cell = row.createCell((short) 1); - cell.setCellValue(4); - - // Style the cell with borders all around. - HSSFCellStyle style = wb.createCellStyle(); - style.setBorderBottom(HSSFCellStyle.BORDER_THIN); - style.setBottomBorderColor(HSSFColor.BLACK.index); - style.setBorderLeft(HSSFCellStyle.BORDER_THIN); - style.setLeftBorderColor(HSSFColor.GREEN.index); - style.setBorderRight(HSSFCellStyle.BORDER_THIN); - style.setRightBorderColor(HSSFColor.BLUE.index); - style.setBorderTop(HSSFCellStyle.BORDER_MEDIUM_DASHED); - style.setTopBorderColor(HSSFColor.BLACK.index); - cell.setCellStyle(style); - - // Write the output to a file - FileOutputStream fileOut = new FileOutputStream("workbook.xls"); - wb.write(fileOut); - fileOut.close(); - -
- -
Iterate over rows and cells -

Sometimes, you'd like to just iterate over all the rows in - a sheet, or all the cells in a row. This is possible with - a simple for loop.

-

Luckily, this is very easy. HSSFRow defines a - CellIterator inner class to handle iterating over - the cells (get one with a call to row.cellIterator()), - and HSSFSheet provides a rowIterator() method to - give an iterator over all the rows.

-

(Unfortunately, due to the broken and - backwards-incompatible way that Java 5 foreach loops were - implemented, it isn't possible to use them on a codebase - that supports Java 1.4, as POI does)

- - HSSFSheet sheet = wb.getSheetAt(0); - for (Iterator rit = sheet.rowIterator(); rit.hasNext(); ) { - HSSFRow row = (HSSFRow)rit.next(); - for (Iterator cit = row.cellIterator(); cit.hasNext(); ) { - HSSFCell cell = (HSSFCell)cit.next(); - // Do something here - } - } - - - HSSFSheet sheet = wb.getSheetAt(0); - for (Iterator<HSSFRow> rit = (Iterator<HSSFRow>)sheet.rowIterator(); rit.hasNext(); ) { - HSSFRow row = rit.next(); - for (Iterator<HSSFCell> cit = (Iterator<HSSFCell>)row.cellIterator(); cit.hasNext(); ) { - HSSFCell cell = cit.next(); - // Do something here - } - } - -
-
Iterate over rows and cells using Java 1.5 foreach loops - OOXML Branch Only -

Sometimes, you'd like to just iterate over all the rows in - a sheet, or all the cells in a row. If you are using Java - 5 or later, then this is especially handy, as it'll allow the - new foreach loop support to work.

-

Luckily, this is very easy. Both HSSFSheet and HSSFRow - implement java.lang.Iterable to allow foreach - loops. For HSSFRow this allows access to the - CellIterator inner class to handle iterating over - the cells, and for HSSFSheet gives the - rowIterator() to iterator over all the rows.

- - HSSFSheet sheet = wb.getSheetAt(0); - for (HSSFRow row : sheet.rowIterator()) { - for (HSSFCell cell : row.cellIterator()) { - // Do something here - } - } - - This only works on the OOXML branch of POI -
- -
Text Extraction -

For most text extraction requirements, the standard - ExcelExtractor class should provide all you need.

- - InputStream inp = new FileInputStream("workbook.xls"); - HSSFWorkbook wb = new HSSFWorkbook(new POIFSFileSystem(inp)); - ExcelExtractor extractor = new ExcelExtractor(wb); - - extractor.setFormulasNotResults(true); - extractor.setIncludeSheetNames(false); - String text = extractor.getText(); - -

For very fancy text extraction, XLS to CSV etc, - take a look at - /src/scratchpad/examples/src/org/apache/poi/hssf/eventusermodel/examples/XLS2CSVmra.java -

-
- -
Fills and colors - - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet("new sheet"); - - // Create a row and put some cells in it. Rows are 0 based. - HSSFRow row = sheet.createRow((short) 1); - - // Aqua background - HSSFCellStyle style = wb.createCellStyle(); - style.setFillBackgroundColor(HSSFColor.AQUA.index); - style.setFillPattern(HSSFCellStyle.BIG_SPOTS); - HSSFCell cell = row.createCell((short) 1); - cell.setCellValue("X"); - cell.setCellStyle(style); - - // Orange "foreground", foreground being the fill foreground not the font color. - style = wb.createCellStyle(); - style.setFillForegroundColor(HSSFColor.ORANGE.index); - style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); - cell = row.createCell((short) 2); - cell.setCellValue("X"); - cell.setCellStyle(style); - - // Write the output to a file - FileOutputStream fileOut = new FileOutputStream("workbook.xls"); - wb.write(fileOut); - fileOut.close(); - -
- -
Merging cells - - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet("new sheet"); - - HSSFRow row = sheet.createRow((short) 1); - HSSFCell cell = row.createCell((short) 1); - cell.setCellValue("This is a test of merging"); - - sheet.addMergedRegion(new Region(1,(short)1,1,(short)2)); - - // Write the output to a file - FileOutputStream fileOut = new FileOutputStream("workbook.xls"); - wb.write(fileOut); - fileOut.close(); - -
- -
Working with fonts - - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet("new sheet"); - - // Create a row and put some cells in it. Rows are 0 based. - HSSFRow row = sheet.createRow((short) 1); - - // Create a new font and alter it. - HSSFFont font = wb.createFont(); - font.setFontHeightInPoints((short)24); - font.setFontName("Courier New"); - font.setItalic(true); - font.setStrikeout(true); - - // Fonts are set into a style so create a new one to use. - HSSFCellStyle style = wb.createCellStyle(); - style.setFont(font); - - // Create a cell and put a value in it. - HSSFCell cell = row.createCell((short) 1); - cell.setCellValue("This is a test of fonts"); - cell.setCellStyle(style); - - // Write the output to a file - FileOutputStream fileOut = new FileOutputStream("workbook.xls"); - wb.write(fileOut); - fileOut.close(); - -

- Note, the maximum number of unique fonts in a workbook is limited to 32767 ( - the maximum positive short). You should re-use fonts in your apllications instead of - creating a font for each cell. -Examples: -

-

Wrong:

- - for (int i = 0; i < 10000; i++) { - HSSFRow row = sheet.createRow(i); - HSSFCell cell = row.createCell((short) 0); - - HSSFCellStyle style = workbook.createCellStyle(); - HSSFFont font = workbook.createFont(); - font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); - style.setFont(font); - cell.setCellStyle(style); - } - -

Correct:

- - - HSSFCellStyle style = workbook.createCellStyle(); - HSSFFont font = workbook.createFont(); - font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); - style.setFont(font); - for (int i = 0; i < 10000; i++) { - HSSFRow row = sheet.createRow(i); - HSSFCell cell = row.createCell((short) 0); - cell.setCellStyle(style); - } - - -
- -
Custom colors - - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet(); - HSSFRow row = sheet.createRow((short) 0); - HSSFCell cell = row.createCell((short) 0); - cell.setCellValue("Default Palette"); - - //apply some colors from the standard palette, - // as in the previous examples. - //we'll use red text on a lime background - - HSSFCellStyle style = wb.createCellStyle(); - style.setFillForegroundColor(HSSFColor.LIME.index); - style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); - - HSSFFont font = wb.createFont(); - font.setColor(HSSFColor.RED.index); - style.setFont(font); - - cell.setCellStyle(style); - - //save with the default palette - FileOutputStream out = new FileOutputStream("default_palette.xls"); - wb.write(out); - out.close(); - - //now, let's replace RED and LIME in the palette - // with a more attractive combination - // (lovingly borrowed from freebsd.org) - - cell.setCellValue("Modified Palette"); - - //creating a custom palette for the workbook - HSSFPalette palette = wb.getCustomPalette(); - - //replacing the standard red with freebsd.org red - palette.setColorAtIndex(HSSFColor.RED.index, - (byte) 153, //RGB red (0-255) - (byte) 0, //RGB green - (byte) 0 //RGB blue - ); - //replacing lime with freebsd.org gold - palette.setColorAtIndex(HSSFColor.LIME.index, (byte) 255, (byte) 204, (byte) 102); - - //save with the modified palette - // note that wherever we have previously used RED or LIME, the - // new colors magically appear - out = new FileOutputStream("modified_palette.xls"); - wb.write(out); - out.close(); - -
- -
Reading and Rewriting Workbooks - - POIFSFileSystem fs = - new POIFSFileSystem(new FileInputStream("workbook.xls")); - HSSFWorkbook wb = new HSSFWorkbook(fs); - HSSFSheet sheet = wb.getSheetAt(0); - HSSFRow row = sheet.getRow(2); - HSSFCell cell = row.getCell((short)3); - if (cell == null) - cell = row.createCell((short)3); - cell.setCellType(HSSFCell.CELL_TYPE_STRING); - cell.setCellValue("a test"); - - // Write the output to a file - FileOutputStream fileOut = new FileOutputStream("workbook.xls"); - wb.write(fileOut); - fileOut.close(); - -
- -
Using newlines in cells - - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet s = wb.createSheet(); - HSSFRow r = null; - HSSFCell c = null; - HSSFCellStyle cs = wb.createCellStyle(); - HSSFFont f = wb.createFont(); - HSSFFont f2 = wb.createFont(); - - cs = wb.createCellStyle(); - - cs.setFont( f2 ); - //Word Wrap MUST be turned on - cs.setWrapText( true ); - - r = s.createRow( (short) 2 ); - r.setHeight( (short) 0x349 ); - c = r.createCell( (short) 2 ); - c.setCellType( HSSFCell.CELL_TYPE_STRING ); - c.setCellValue( "Use \n with word wrap on to create a new line" ); - c.setCellStyle( cs ); - s.setColumnWidth( (short) 2, (short) ( ( 50 * 8 ) / ( (double) 1 / 20 ) ) ); - - FileOutputStream fileOut = new FileOutputStream( "workbook.xls" ); - wb.write( fileOut ); - fileOut.close(); -
- -
Data Formats - - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet("format sheet"); - HSSFCellStyle style; - HSSFDataFormat format = wb.createDataFormat(); - HSSFRow row; - HSSFCell cell; - short rowNum = 0; - short colNum = 0; - - row = sheet.createRow(rowNum++); - cell = row.createCell(colNum); - cell.setCellValue(11111.25); - style = wb.createCellStyle(); - style.setDataFormat(format.getFormat("0.0")); - cell.setCellStyle(style); - - row = sheet.createRow(rowNum++); - cell = row.createCell(colNum); - cell.setCellValue(11111.25); - style = wb.createCellStyle(); - style.setDataFormat(format.getFormat("#,##0.0000")); - cell.setCellStyle(style); - - FileOutputStream fileOut = new FileOutputStream("workbook.xls"); - wb.write(fileOut); - fileOut.close(); - -
- -
Fit Sheet to One Page - - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet("format sheet"); - HSSFPrintSetup ps = sheet.getPrintSetup(); - - sheet.setAutobreaks(true); - - ps.setFitHeight((short)1); - ps.setFitWidth((short)1); - - - // Create various cells and rows for spreadsheet. - - FileOutputStream fileOut = new FileOutputStream("workbook.xls"); - wb.write(fileOut); - fileOut.close(); - -
- -
Set Print Area - - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet("Sheet1"); - wb.setPrintArea(0, "$A$1:$C$2"); - //sets the print area for the first sheet - //Alternatively: - //wb.setPrintArea(0, 0, 1, 0, 0) is equivalent to using the name reference (See the JavaDocs for more details) - - // Create various cells and rows for spreadsheet. - - FileOutputStream fileOut = new FileOutputStream("workbook.xls"); - wb.write(fileOut); - fileOut.close(); - - - -
- - -
Set Page Numbers on Footer - - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet("format sheet"); - HSSFFooter footer = sheet.getFooter() - - footer.setRight( "Page " + HSSFFooter.page() + " of " + HSSFFooter.numPages() ); - - - - // Create various cells and rows for spreadsheet. - - FileOutputStream fileOut = new FileOutputStream("workbook.xls"); - wb.write(fileOut); - fileOut.close(); - -
- - -
Using the Convenience Functions -

- The convenience functions live in contrib and provide - utility features such as setting borders around merged - regions and changing style attributes without explicitly - creating new styles. -

- - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet1 = wb.createSheet( "new sheet" ); - - // Create a merged region - HSSFRow row = sheet1.createRow( (short) 1 ); - HSSFRow row2 = sheet1.createRow( (short) 2 ); - HSSFCell cell = row.createCell( (short) 1 ); - cell.setCellValue( "This is a test of merging" ); - Region region = new Region( 1, (short) 1, 4, (short) 4 ); - sheet1.addMergedRegion( region ); - - // Set the border and border colors. - final short borderMediumDashed = HSSFCellStyle.BORDER_MEDIUM_DASHED; - HSSFRegionUtil.setBorderBottom( borderMediumDashed, - region, sheet1, wb ); - HSSFRegionUtil.setBorderTop( borderMediumDashed, - region, sheet1, wb ); - HSSFRegionUtil.setBorderLeft( borderMediumDashed, - region, sheet1, wb ); - HSSFRegionUtil.setBorderRight( borderMediumDashed, - region, sheet1, wb ); - HSSFRegionUtil.setBottomBorderColor(HSSFColor.AQUA.index, region, sheet1, wb); - HSSFRegionUtil.setTopBorderColor(HSSFColor.AQUA.index, region, sheet1, wb); - HSSFRegionUtil.setLeftBorderColor(HSSFColor.AQUA.index, region, sheet1, wb); - HSSFRegionUtil.setRightBorderColor(HSSFColor.AQUA.index, region, sheet1, wb); - - // Shows some usages of HSSFCellUtil - HSSFCellStyle style = wb.createCellStyle(); - style.setIndention((short)4); - HSSFCellUtil.createCell(row, 8, "This is the value of the cell", style); - HSSFCell cell2 = HSSFCellUtil.createCell( row2, 8, "This is the value of the cell"); - HSSFCellUtil.setAlignment(cell2, wb, HSSFCellStyle.ALIGN_CENTER); - - // Write out the workbook - FileOutputStream fileOut = new FileOutputStream( "workbook.xls" ); - wb.write( fileOut ); - fileOut.close(); - -
- - -
Shift rows up or down on a sheet - - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet("row sheet"); - - // Create various cells and rows for spreadsheet. - - // Shift rows 6 - 11 on the spreadsheet to the top (rows 0 - 5) - sheet.shiftRows(5, 10, -5); - - FileOutputStream fileOut = new FileOutputStream("workbook.xls"); - wb.write(fileOut); - fileOut.close(); - -
- - -
Set a sheet as selected - - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet("row sheet"); - sheet.setSelected(true); - - // Create various cells and rows for spreadsheet. - - FileOutputStream fileOut = new FileOutputStream("workbook.xls"); - wb.write(fileOut); - fileOut.close(); - -
- - -
Set the zoom magnification -

- The zoom is expressed as a fraction. For example to - express a zoom of 75% use 3 for the numerator and - 4 for the denominator. -

- - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet1 = wb.createSheet("new sheet"); - sheet1.setZoom(3,4); // 75 percent magnification - FileOutputStream fileOut = new FileOutputStream("workbook.xls"); - wb.write(fileOut); - fileOut.close(); - -
- - -
Splits and freeze panes -

- There are two types of panes you can create; freeze panes and split panes. -

-

- A freeze pane is split by columns and rows. You create - a freeze pane using the following mechanism: -

-

- sheet1.createFreezePane( 3, 2, 3, 2 ); -

-

- The first two parameters are the columns and rows you - wish to split by. The second two parameters indicate - the cells that are visible in the bottom right quadrant. -

-

- - Split pains appear differently. The split area is - divided into four separate work area's. The split - occurs at the pixel level and the user is able to - adjust the split by dragging it to a new position. -

-

- - Split panes are created with the following call: -

-

- sheet2.createSplitPane( 2000, 2000, 0, 0, HSSFSheet.PANE_LOWER_LEFT ); -

-

- - The first parameter is the x position of the split. - This is in 1/20th of a point. A point in this case - seems to equate to a pixel. The second parameter is - the y position of the split. Again in 1/20th of a point. -

-

- The last parameter indicates which pane currently has - the focus. This will be one of HSSFSheet.PANE_LOWER_LEFT, - PANE_LOWER_RIGHT, PANE_UPPER_RIGHT or PANE_UPPER_LEFT. -

- - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet1 = wb.createSheet("new sheet"); - HSSFSheet sheet2 = wb.createSheet("second sheet"); - HSSFSheet sheet3 = wb.createSheet("third sheet"); - HSSFSheet sheet4 = wb.createSheet("fourth sheet"); - - // Freeze just one row - sheet1.createFreezePane( 0, 1, 0, 1 ); - // Freeze just one column - sheet2.createFreezePane( 1, 0, 1, 0 ); - // Freeze the columns and rows (forget about scrolling position of the lower right quadrant). - sheet3.createFreezePane( 2, 2 ); - // Create a split with the lower left side being the active quadrant - sheet4.createSplitPane( 2000, 2000, 0, 0, HSSFSheet.PANE_LOWER_LEFT ); - - FileOutputStream fileOut = new FileOutputStream("workbook.xls"); - wb.write(fileOut); - fileOut.close(); - -
- - -
Repeating rows and columns -

- It's possible to set up repeating rows and columns in - your printouts by using the setRepeatingRowsAndColumns() - function in the HSSFWorkbook class. -

-

- This function Contains 5 parameters. - The first parameter is the index to the sheet (0 = first sheet). - The second and third parameters specify the range for the columns to repreat. - To stop the columns from repeating pass in -1 as the start and end column. - The fourth and fifth parameters specify the range for the rows to repeat. - To stop the columns from repeating pass in -1 as the start and end rows. -

- - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet1 = wb.createSheet("new sheet"); - HSSFSheet sheet2 = wb.createSheet("second sheet"); - - // Set the columns to repeat from column 0 to 2 on the first sheet - wb.setRepeatingRowsAndColumns(0,0,2,-1,-1); - // Set the the repeating rows and columns on the second sheet. - wb.setRepeatingRowsAndColumns(1,4,5,1,2); - - FileOutputStream fileOut = new FileOutputStream("workbook.xls"); - wb.write(fileOut); - fileOut.close(); - -
- -
Headers and Footers -

- Example is for headers but applies directly to footers. -

- - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet("new sheet"); - - HSSFHeader header = sheet.getHeader(); - header.setCenter("Center Header"); - header.setLeft("Left Header"); - header.setRight(HSSFHeader.font("Stencil-Normal", "Italic") + - HSSFHeader.fontSize((short) 16) + "Right w/ Stencil-Normal Italic font and size 16"); - - FileOutputStream fileOut = new FileOutputStream("workbook.xls"); - wb.write(fileOut); - fileOut.close(); - -
- - -
Drawing Shapes -

- POI supports drawing shapes using the Microsoft Office - drawing tools. Shapes on a sheet are organized in a - hiearchy of groups and and shapes. The top-most shape - is the patriarch. This is not visisble on the sheet - at all. To start drawing you need to call createPatriarch - on the HSSFSheet class. This has the - effect erasing any other shape information stored - in that sheet. By default POI will leave shape - records alone in the sheet unless you make a call to - this method. -

-

- To create a shape you have to go through the following - steps: -

-
    -
  1. Create the patriarch.
  2. -
  3. Create an anchor to position the shape on the sheet.
  4. -
  5. Ask the patriarch to create the shape.
  6. -
  7. Set the shape type (line, oval, rectangle etc...)
  8. -
  9. Set any other style details converning the shape. (eg: - line thickness, etc...)
  10. -
- - HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); - a = new HSSFClientAnchor( 0, 0, 1023, 255, (short) 1, 0, (short) 1, 0 ); - HSSFSimpleShape shape1 = patriarch.createSimpleShape(a1); - shape1.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE); - -

- Text boxes are created using a different call: -

- - HSSFTextbox textbox1 = patriarch.createTextbox( - new HSSFClientAnchor(0,0,0,0,(short)1,1,(short)2,2)); - textbox1.setString(new HSSFRichTextString("This is a test") ); - -

- It's possible to use different fonts to style parts of - the text in the textbox. Here's how: -

- - HSSFFont font = wb.createFont(); - font.setItalic(true); - font.setUnderline(HSSFFont.U_DOUBLE); - HSSFRichTextString string = new HSSFRichTextString("Woo!!!"); - string.applyFont(2,5,font); - textbox.setString(string ); - -

- Just as can be done manually using Excel, it is possible - to group shapes together. This is done by calling - createGroup() and then creating the shapes - using those groups. -

-

- It's also possible to create groups within groups. -

- Any group you create should contain at least two - other shapes or subgroups. -

- Here's how to create a shape group: -

- - // Create a shape group. - HSSFShapeGroup group = patriarch.createGroup( - new HSSFClientAnchor(0,0,900,200,(short)2,2,(short)2,2)); - - // Create a couple of lines in the group. - HSSFSimpleShape shape1 = group.createShape(new HSSFChildAnchor(3,3,500,500)); - shape1.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE); - ( (HSSFChildAnchor) shape1.getAnchor() ).setAnchor((short)3,3,500,500); - HSSFSimpleShape shape2 = group.createShape(new HSSFChildAnchor((short)1,200,400,600)); - shape2.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE); - -

- If you're being observant you'll noticed that the shapes - that are added to the group use a new type of anchor: - the HSSFChildAnchor. What happens is that - the created group has it's own coordinate space for - shapes that are placed into it. POI defaults this to - (0,0,1023,255) but you are able to change it as desired. - Here's how: -

- - myGroup.setCoordinates(10,10,20,20); // top-left, bottom-right - -

- If you create a group within a group it's also going - to have it's own coordinate space. -

-
- - -
Styling Shapes -

- By default shapes can look a little plain. It's possible - to apply different styles to the shapes however. The - sorts of things that can currently be done are: -

-
    -
  • Change the fill color.
  • -
  • Make a shape with no fill color.
  • -
  • Change the thickness of the lines.
  • -
  • Change the style of the lines. Eg: dashed, dotted.
  • -
  • Change the line color.
  • -
-

- Here's an examples of how this is done: -

- - HSSFSimpleShape s = patriarch.createSimpleShape(a); - s.setShapeType(HSSFSimpleShape.OBJECT_TYPE_OVAL); - s.setLineStyleColor(10,10,10); - s.setFillColor(90,10,200); - s.setLineWidth(HSSFShape.LINEWIDTH_ONE_PT * 3); - s.setLineStyle(HSSFShape.LINESTYLE_DOTSYS); - -
- -
Shapes and Graphics2d -

- While the native POI shape drawing commands are the - recommended way to draw shapes in a shape it's sometimes - desirable to use a standard API for compatibility with - external libraries. With this in mind we created some - wrappers for Graphics and Graphics2d. -

- - It's important to not however before continuing that - Graphics2d is a poor match to the capabilities - of the Microsoft Office drawing commands. The older - Graphics class offers a closer match but is - still a square peg in a round hole. - -

- All Graphics commands are issued into an HSSFShapeGroup. - Here's how it's done: -

- - a = new HSSFClientAnchor( 0, 0, 1023, 255, (short) 1, 0, (short) 1, 0 ); - group = patriarch.createGroup( a ); - group.setCoordinates( 0, 0, 80 * 4 , 12 * 23 ); - float verticalPointsPerPixel = a.getAnchorHeightInPoints(sheet) / (float)Math.abs(group.getY2() - group.getY1()); - g = new EscherGraphics( group, wb, Color.black, verticalPointsPerPixel ); - g2d = new EscherGraphics2d( g ); - drawChemicalStructure( g2d ); - -

- The first thing we do is create the group and set it's coordinates - to match what we plan to draw. Next we calculate a reasonable - fontSizeMultipler then create the EscherGraphics object. - Since what we really want is a Graphics2d - object we create an EscherGraphics2d object and pass in - the graphics object we created. Finally we call a routine - that draws into the EscherGraphics2d object. -

-

- The vertical points per pixel deserves some more explanation. - One of the difficulties in converting Graphics calls - into escher drawing calls is that Excel does not have - the concept of absolute pixel positions. It measures - it's cell widths in 'characters' and the cell heights in points. - Unfortunately it's not defined exactly what type of character it's - measuring. Presumably this is due to the fact that the Excel will be - using different fonts on different platforms or even within the same - platform. -

-

- Because of this constraint we've had to implement the concept of a - verticalPointsPerPixel. This the amount the font should be scaled by when - you issue commands such as drawString(). To calculate this value - use the follow formula: -

- - multipler = groupHeightInPoints / heightOfGroup - -

- The height of the group is calculated fairly simply by calculating the - difference between the y coordinates of the bounding box of the shape. The - height of the group can be calculated by using a convenience called - HSSFClientAnchor.getAnchorHeightInPoints(). -

-

- Many of the functions supported by the graphics classes - are not complete. Here's some of the functions that are known - to work. -

-
    -
  • fillRect()
  • -
  • fillOval()
  • -
  • drawString()
  • -
  • drawOval()
  • -
  • drawLine()
  • -
  • clearRect()
  • -
-

- Functions that are not supported will return and log a message - using the POI logging infrastructure (disabled by default). -

-
- -
- Outlining -

- Outlines are great for grouping sections of information - together and can be added easily to columns and rows - using the POI API. Here's how: -

- - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet1 = wb.createSheet("new sheet"); - - sheet1.groupRow( 5, 14 ); - sheet1.groupRow( 7, 14 ); - sheet1.groupRow( 16, 19 ); - - sheet1.groupColumn( (short)4, (short)7 ); - sheet1.groupColumn( (short)9, (short)12 ); - sheet1.groupColumn( (short)10, (short)11 ); - - FileOutputStream fileOut = new FileOutputStream(filename); - wb.write(fileOut); - fileOut.close(); - -

- To collapse (or expand) an outline use the following calls: -

- - sheet1.setRowGroupCollapsed( 7, true ); - sheet1.setColumnGroupCollapsed( (short)4, true ); - -

- The row/column you choose should contain an already - created group. It can be anywhere within the group. -

-
-
-
- -
- Images -

- Images are part of the drawing support. To add an image just - call createPicture() on the drawing patriarch. - At the time of writing the following types are supported: -

-
    -
  • PNG
  • -
  • JPG
  • -
  • DIB
  • -
-

- It should be noted that any existing drawings may be erased - once you add a image to a sheet. -

- - // Create the drawing patriarch. This is the top level container for - // all shapes. This will clear out any existing shapes for that sheet. - HSSFPatriarch patriarch = sheet5.createDrawingPatriarch(); - - HSSFClientAnchor anchor; - anchor = new HSSFClientAnchor(0,0,0,255,(short)2,2,(short)4,7); - anchor.setAnchorType( 2 ); - patriarch.createPicture(anchor, loadPicture( "src/resources/logos/logoKarmokar4.png", wb )); - -

Creating an image and setting its anchor to the actual width and height:

- - HSSFPatriarch patriarch = sheet5.createDrawingPatriarch(); - - HSSFPicture picture = patriarch.createPicture(new HSSFClientAnchor(), loadPicture( "src/resources/logos/logoKarmokar4.png", wb )); - picture.resize(); - -

or

- - HSSFPatriarch patriarch = sheet5.createDrawingPatriarch(); - - HSSFPicture picture = patriarch.createPicture(new HSSFClientAnchor(), loadPicture( "src/resources/logos/logoKarmokar4.png", wb )); - HSSFClientAnchor preferredSize = picture.getPreferredSize(); - picture.setAnchor(preferredSize); - - - HSSFPicture.resize() works only for JPEG and PNG. Other formats are not yet supported. - - -

Reading images from a workbook:

- - HSSFWorkbook wb; - - List lst = wb.getAllPictures(); - for (Iterator it = lst.iterator(); it.hasNext(); ) { - HSSFPictureData pict = (HSSFPictureData)it.next(); - String ext = pict.suggestFileExtension(); - byte[] data = pict.getData(); - if (ext.equals("jpeg")){ - FileOutputStream out = new FileOutputStream("pict.jpg"); - out.write(data); - out.close(); - } - } - -
- -
- Named Ranges and Named Cells -

- Named Range is a way to refer to a group of cells by a name. Named Cell is a - degenerate case of Named Range in that the 'group of cells' contains exactly one - cell. You can create as well as refer to cells in a workbook by their named range. - When working with Named Ranges, the classes: org.apache.poi.hssf.util.CellReference and - & org.apache.poi.hssf.util.AreaReference are used. -

-

- Creating Named Range / Named Cell -

- - // setup code - String sname = "TestSheet", cname = "TestName", cvalue = "TestVal"; - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet(sname); - sheet.createRow(0).createCell((short) 0).setCellValue(cvalue); - - // 1. create named range for a single cell using areareference - HSSFName namedCell = wb.createName(); - namedCell.setNameName(cname); - String reference = sname+"!A1:A1"; // area reference - namedCell.setReference(reference); - - // 2. create named range for a single cell using cellreference - HSSFName namedCell = wb.createName(); - namedCell.setNameName(cname); - String reference = sname+"!A1"; // cell reference - namedCell.setReference(reference); - - // 3. create named range for an area using AreaReference - HSSFName namedCell = wb.createName(); - namedCell.setNameName(cname); - String reference = sname+"!A1:C5"; // area reference - namedCell.setReference(reference); - - -

- Reading from Named Range / Named Cell -

- - // setup code - String cname = "TestName"; - HSSFWorkbook wb = getMyWorkbook(); // retrieve workbook - - // retrieve the named range - int namedCellIdx = wb.getNameIndex(cellName); - HSSFName aNamedCell = wb.getNameAt(namedCellIdx); - - // retrieve the cell at the named range and test its contents - AreaReference aref = new AreaReference(aNamedCell.getReference()); - CellReference[] crefs = aref.getAllReferencedCells(); - for (int i=0; i<crefs.length; i++) { - HSSFSheet s = wb.getSheet(crefs[i].getSheetName()); - HSSFRow r = sheet.getRow(crefs[i].getRow()); - HSSFCell c = r.getCell(crefs[i].getCol()); - // extract the cell contents based on cell type etc. - } - -

- Reading from non-contiguous Named Ranges -

- - // Setup code - String cname = "TestName"; - HSSFWorkbook wb = getMyWorkbook(); // retrieve workbook - - // Retrieve the named range - // Will be something like "$C$10,$D$12:$D$14"; - int namedCellIdx = wb.getNameIndex(cellName); - HSSFName aNamedCell = wb.getNameAt(namedCellIdx); - - // Retrieve the cell at the named range and test its contents - // Will get back one AreaReference for C10, and - // another for D12 to D14 - AreaReference[] arefs = AreaReference.generateContiguous(aNamedCell.getReference()); - for (int i=0; i<arefs.length; i++) { - // Only get the corners of the Area - // (use arefs[i].getAllReferencedCells() to get all cells) - CellReference[] crefs = arefs[i].getCells(); - for (int j=0; j<crefs.length; j++) { - // Check it turns into real stuff - HSSFSheet s = wb.getSheet(crefs[j].getSheetName()); - HSSFRow r = s.getRow(crefs[j].getRow()); - HSSFCell c = r.getCell(crefs[j].getCol()); - // Do something with this corner cell - } - } - -
- -
Cell Comments -

- In Excel a comment is a kind of a text shape, - so inserting a comment is very similar to placing a text box in a worksheet: -

- - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet("Cell comments in POI HSSF"); - - // Create the drawing patriarch. This is the top level container for all shapes including cell comments. - HSSFPatriarch patr = sheet.createDrawingPatriarch(); - - //create a cell in row 3 - HSSFCell cell1 = sheet.createRow(3).createCell((short)1); - cell1.setCellValue(new HSSFRichTextString("Hello, World")); - - //anchor defines size and position of the comment in worksheet - HSSFComment comment1 = patr.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short)4, 2, (short) 6, 5)); - - // set text in the comment - comment1.setString(new HSSFRichTextString("We can set comments in POI")); - - //set comment author. - //you can see it in the status bar when moving mouse over the commented cell - comment1.setAuthor("Apache Software Foundation"); - - // The first way to assign comment to a cell is via HSSFCell.setCellComment method - cell1.setCellComment(comment1); - - //create another cell in row 6 - HSSFCell cell2 = sheet.createRow(6).createCell((short)1); - cell2.setCellValue(36.6); - - - HSSFComment comment2 = patr.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short)4, 8, (short) 6, 11)); - //modify background color of the comment - comment2.setFillColor(204, 236, 255); - - HSSFRichTextString string = new HSSFRichTextString("Normal body temperature"); - - //apply custom font to the text in the comment - HSSFFont font = wb.createFont(); - font.setFontName("Arial"); - font.setFontHeightInPoints((short)10); - font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); - font.setColor(HSSFColor.RED.index); - string.applyFont(font); - - comment2.setString(string); - //by default comments are hidden. This one is always visible. - comment2.setVisible(true); - - comment2.setAuthor("Bill Gates"); - - /** - * The second way to assign comment to a cell is to implicitly specify its row and column. - * Note, it is possible to set row and column of a non-existing cell. - * It works, the commnet is visible. - */ - comment2.setRow(6); - comment2.setColumn((short)1); - - FileOutputStream out = new FileOutputStream("poi_comment.xls"); - wb.write(out); - out.close(); - -

- Reading cell comments -

- - HSSFCell cell = sheet.get(3).getColumn((short)1); - HSSFComment comment = cell.getCellComment(); - if (comment != null) { - HSSFRichTextString str = comment.getString(); - String author = comment.getAuthor(); - } - // alternatively you can retrieve cell comments by (row, column) - comment = sheet.getCellComment(3, 1); - -
- -
Adjust column width to fit the contents - - HSSFSheet sheet = workbook.getSheetAt(0); - sheet.autoSizeColumn((short)0); //adjust width of the first column - sheet.autoSizeColumn((short)1); //adjust width of the second column - - - To calculate column width HSSFSheet.autoSizeColumn uses Java2D classes - that throw exception if graphical environment is not available. In case if graphical environment - is not available, you must tell Java that you are running in headless mode and - set the following system property: java.awt.headless=true - (either via -Djava.awt.headless=true startup parameter or via System.setProperty("java.awt.headless", "true")). - -
- -
How to read hyperlinks - - HSSFSheet sheet = workbook.getSheetAt(0); - - HSSFCell cell = sheet.getRow(0).getCell((short)0); - HSSFHyperlink link = cell.getHyperlink(); - if(link != null){ - System.out.println(link.getAddress()); - } - -
-
How to create hyperlinks - - HSSFWorkbook wb = new HSSFWorkbook(); - - //cell style for hyperlinks - //by default hypelrinks are blue and underlined - HSSFCellStyle hlink_style = wb.createCellStyle(); - HSSFFont hlink_font = wb.createFont(); - hlink_font.setUnderline(HSSFFont.U_SINGLE); - hlink_font.setColor(HSSFColor.BLUE.index); - hlink_style.setFont(hlink_font); - - HSSFCell cell; - HSSFSheet sheet = wb.createSheet("Hyperlinks"); - - //URL - cell = sheet.createRow(0).createCell((short)0); - cell.setCellValue("URL Link"); - HSSFHyperlink link = new HSSFHyperlink(HSSFHyperlink.LINK_URL); - link.setAddress("http://poi.apache.org/"); - cell.setHyperlink(link); - cell.setCellStyle(hlink_style); - - //link to a file in the current directory - cell = sheet.createRow(1).createCell((short)0); - cell.setCellValue("File Link"); - link = new HSSFHyperlink(HSSFHyperlink.LINK_FILE); - link.setAddress("link1.xls"); - cell.setHyperlink(link); - cell.setCellStyle(hlink_style); - - //e-mail link - cell = sheet.createRow(2).createCell((short)0); - cell.setCellValue("Email Link"); - link = new HSSFHyperlink(HSSFHyperlink.LINK_EMAIL); - //note, if subject contains white spaces, make sure they are url-encoded - link.setAddress("mailto:poi@apache.org?subject=Hyperlinks"); - cell.setHyperlink(link); - cell.setCellStyle(hlink_style); - - //link to a place in this workbook - - //create a target sheet and cell - HSSFSheet sheet2 = wb.createSheet("Target Sheet"); - sheet2.createRow(0).createCell((short)0).setCellValue("Target Cell"); - - cell = sheet.createRow(3).createCell((short)0); - cell.setCellValue("Worksheet Link"); - link = new HSSFHyperlink(HSSFHyperlink.LINK_DOCUMENT); - link.setAddress("'Target Sheet'!A1"); - cell.setHyperlink(link); - cell.setCellStyle(hlink_style); - - FileOutputStream out = new FileOutputStream("hssf-links.xls"); - wb.write(out); - out.close(); - -
- - -
diff --git a/src/documentation/content/xdocs/hssf/record-generator.xml b/src/documentation/content/xdocs/hssf/record-generator.xml deleted file mode 100644 index 8ce8fe5d89..0000000000 --- a/src/documentation/content/xdocs/hssf/record-generator.xml +++ /dev/null @@ -1,212 +0,0 @@ - - - - - -
- Record Generator HOWTO - - - - -
- -
How to Use the Record Generator - -
History -

- The record generator was born from frustration with translating - the Excel records to Java classes. Doing this manually is a time - consuming process. It's also very easy to make mistakes. -

-

- A utility was needed to take the defintition of what a - record looked like and do all the boring and repetitive work. -

-
- -
Capabilities -

- The record generator takes XML as input and produces the following - output: -

-
    -
  • A Java file capabile of decoding and encoding the record.
  • -
  • A test class that provides a fill-in-the-blanks implementation - of a test case for ensuring the record operates as - designed.
  • -
-
-
Usage -

- The record generator is invoked as an Ant target - (generate-records). It goes through looking for all files in - src/records/defintitions ending with _record.xml. - It then creates two files; the Java record definition and the - Java test case template. -

-

- The records themselves have the following general layout: -

- - The frame record indicates whether there is a border - around the displayed text of a chart. - Glen Stampoultzis (glens at apache.org) - - - - - - - - - - - - ]]> -

- The following table details the allowable types and sizes for - the fields. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TypeSizeJava Type
int1byte
int2short
int4int
int8long
intvarwordarray of shorts
bits1A byte comprising of a bits (defined by the bit element) -
bits2An short comprising of a bits
bits4A int comprising of a bits
float8double
hbstringjava expressionString
-

- The Java records are regenerated each time the record generator is - run, however the test stubs are only created if the test stub does - not already exist. What this means is that you may change test - stubs but not the generated records. -

-
-
Custom Field Types -

- Occationally the builtin types are not enough. More control - over the encoding and decoding of the streams is required. This - can be achieved using a custom type. -

-

- A custom type lets you escape to java to define the way in which - the field encodes and decodes. To code a custom type you - declare your field like this: -

- - ]]> -

- Where the class name specified after custom: is a - class implementing the interface CustomField. -

-

- You can then implement the encoding yourself. -

-
-
How it Works -

- The record generation works by taking an XML file and styling it - using XLST. Given that XSLT is a little limited in some ways it was - necessary to add a little Java code to the mix. -

-

- See record.xsl, record_test.xsl, FieldIterator.java, - RecordUtil.java, RecordGenerator.java -

-

- There is a corresponding "type" generator for HWPF. - See the HWPF documentation for details. -

-
-
Limitations -

- The record generator does not handle all possible record types and - goes not intend to perform this function. When dealing with a - non-standard record sometimes the cost-benifit of coding the - record by hand will be greater than attempting modify the - generator. The main point of the record generator is to save - time, so keep that in mind. -

-

- Currently the the XSL file that generates the record calls out to - Java objects. The Java code for the record generation is - currently quite messy with minimal comments. -

-
-
- -
diff --git a/src/documentation/content/xdocs/hssf/use-case.xml b/src/documentation/content/xdocs/hssf/use-case.xml deleted file mode 100644 index acd66fc6e1..0000000000 --- a/src/documentation/content/xdocs/hssf/use-case.xml +++ /dev/null @@ -1,200 +0,0 @@ - - - - - -
- HSSF Use Cases - - - -
- -
HSSF Use Cases -
Use Case 1: Read existing HSSF - -

Primary Actor: HSSF client

-

Scope: HSSF

-

Level: Summary

-

Stakeholders and Interests:

-
    -
  • HSSF client- wants to read content - of HSSF file
  • -
  • HSSF - understands HSSF file
  • -
  • POIFS - understands underlying POI - file system
  • -
-

Precondition: None

-

Minimal Guarantee: None

-

Main Success Guarantee:

-
    -
  1. HSSF client requests HSSF to read - a HSSF file, providing an InputStream - containing HSSF file in question.
  2. -
  3. HSSF requests POIFS to read the HSSF - file, passing the InputStream - object to POIFS (POIFS use case 1, read existing file system)
  4. -
  5. HSSF reads the "Workbook" - file (use case 4, read workbook entry)
  6. -
-

Extensions:

-

2a. Exceptions -thrown by POIFS will be passed on to the HSSF client.

-
-
Use Case 2: Write HSSF file - -

Primary Actor: HSSF client

-

Scope: HSSF

-

Level: Summary

-

Stakeholders and Interests:

-
    -
  • HSSF client- wants to write file - out.
  • -
  • HSSF - knows how to write file - out.
  • -
  • POIFS - knows how to write file - system out.
  • -
-

Precondition:

-
    -
  • File has been - read (use case 1, read existing HSSF file) and subsequently modified - or file has been created (use case 3, create HSSF file)
  • -
-

Minimal Guarantee: None

-

Main Success Guarantee:

-
    -
  1. HSSF client - provides an OutputStream to - write the file to.
  2. -
  3. HSSF writes - the "Workbook" to its associated POIFS file system (use case - 5, write workbook entry)
  4. -
  5. HSSF - requests POIFS to write its file system out, using the OutputStream - obtained from the HSSF client (POIFS use case 2, write file system).
  6. -
-

Extensions:

-

3a. Exceptions -from POIFS are passed to the HSSF client.

- -
-
Use Case 3:Create HSSF file - -

Primary Actor: HSSF client

-

Scope: HSSF

-

-Level: Summary

-

Stakeholders and Interests:

-
    -
  • HSSF client- wants to create a new - file.
  • -
  • HSSF - knows how to create a new - file.
  • -
  • POIFS - knows how to creat a new - file system.
  • -
-

Precondition:

-

Minimal Guarantee: None

-

Main Success Guarantee:

-
    -
  1. HSSF requests - POIFS to create a new file system (POIFS use case 3, create new file - system)
  2. -
-

Extensions: -None

- -
-
Use Case 4: Read workbook entry -

Primary Actor: HSSF

-

Scope: HSSF

-

-Level: Summary

-

Stakeholders and Interests:

-
    -
  • HSSF - knows how to read the - workbook entry
  • -
  • POIFS - knows how to manage the file - system.
  • -
-

Precondition:

-
    -
  • The file - system has been read (use case 1, read existing HSSF file) or has - been created and written to (use case 3, create HSSF file system; - use case 5, write workbook entry).
  • -
-

Minimal -Guarantee: None

-

Main Success Guarantee:

-
    -
  1. - HSSF requests POIFS for the "Workbook" file
  2. -
  3. POIFS returns - an InputStream for the file.
  4. -
  5. HSSF reads - from the InputStream provided by POIFS
  6. -
  7. HSSF closes - the InputStream provided by POIFS
  8. -
-

Extensions:

-

3a. Exceptions -thrown by POIFS will be passed on

-
-
Use Case 5: Write workbook entry - - -

Primary Actor: HSSF

-

Scope: HSSF

-

-Level: Summary

-

Stakeholders and Interests:

-
    -
  • HSSF - knows how to manage the - write the workbook entry.
  • -
  • POIFS - knows how to manage the file - system.
  • -
-

Precondition: -

-
    -
  • Either an existing HSSF file has - been read (use case 1, read existing HSSF file) or an HSSF file has - been created (use case 3, create HSSF file).
  • -
-

Minimal Guarantee: None

-

Main Success Guarantee:

-
    -
  1. HSSF - checks the POIFS file system directory for the "Workbook" - file (POIFS use case 8, read file system directory)
  2. -
  3. If "Workbook" is in the directory, HSSF requests POIFS to - replace it with the new workbook entry (POIFS use case 4, replace file - in file system). Otherwise, HSSF requests POIFS to write the new - workbook file, with the name "Workbook" (POIFS use case 6, - write new file to file system)
  4. -
-

Extensions:None

-
- -
- -
diff --git a/src/documentation/content/xdocs/index.xml b/src/documentation/content/xdocs/index.xml index f8faa7826a..4157286c89 100644 --- a/src/documentation/content/xdocs/index.xml +++ b/src/documentation/content/xdocs/index.xml @@ -123,7 +123,7 @@

HSSF is our port of the Microsoft Excel 97(-2007) file format (BIFF8) to pure Java. XSSF is our port of the Microsoft Excel XML (2007+) file format (OOXML) to pure Java. They both supports read and write capability. Please see - the HSSF+XSSF project page for more + the HSSF+XSSF project page for more information.

HWPF for Word Documents diff --git a/src/documentation/content/xdocs/ss/book.xml b/src/documentation/content/xdocs/ss/book.xml new file mode 100644 index 0000000000..483b46e2f5 --- /dev/null +++ b/src/documentation/content/xdocs/ss/book.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/documentation/content/xdocs/ss/chart.xml b/src/documentation/content/xdocs/ss/chart.xml new file mode 100644 index 0000000000..3dd3371287 --- /dev/null +++ b/src/documentation/content/xdocs/ss/chart.xml @@ -0,0 +1,1532 @@ + + + + + +
+ Chart record information + + + +
+ +
Introduction +

+ This document is intended as a work in progress for describing + our current understanding of how the chart records are are + written to produce a valid chart. +

+
+
Bar chart +

+ The following records detail the records written for a + 'simple' bar chart. +

+ + + ============================================ + rectype = 0xec, recsize = 0xc8 + -BEGIN DUMP--------------------------------- + 00000000 0F 00 02 F0 C0 00 00 00 10 00 08 F0 08 00 00 00 ................ + 00000010 02 00 00 00 02 04 00 00 0F 00 03 F0 A8 00 00 00 ................ + 00000020 0F 00 04 F0 28 00 00 00 01 00 09 F0 10 00 00 00 ....(........... + 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00000040 02 00 0A F0 08 00 00 00 00 04 00 00 05 00 00 00 ................ + 00000050 0F 00 04 F0 70 00 00 00 92 0C 0A F0 08 00 00 00 ....p........... + 00000060 02 04 00 00 00 0A 00 00 93 00 0B F0 36 00 00 00 ............6... + 00000070 7F 00 04 01 04 01 BF 00 08 00 08 00 81 01 4E 00 ..............N. + 00000080 00 08 83 01 4D 00 00 08 BF 01 10 00 11 00 C0 01 ....M........... + 00000090 4D 00 00 08 FF 01 08 00 08 00 3F 02 00 00 02 00 M.........?..... + 000000A0 BF 03 00 00 08 00 00 00 10 F0 12 00 00 00 00 00 ................ + 000000B0 04 00 C0 02 0A 00 F4 00 0E 00 66 01 20 00 E9 00 ..........f. ... + 000000C0 00 00 11 F0 00 00 00 00 ........ + -END DUMP----------------------------------- + recordid = 0xec, size =200 + [UNKNOWN RECORD:ec] + .id = ec + [/UNKNOWN RECORD] + + ============================================ + rectype = 0x5d, recsize = 0x1a + -BEGIN DUMP--------------------------------- + 00000000 15 00 12 00 05 00 02 00 11 60 00 00 00 00 B8 03 .........`...... + 00000010 87 03 00 00 00 00 00 00 00 00 .......... + -END DUMP----------------------------------- + recordid = 0x5d, size =26 + [UNKNOWN RECORD:5d] + .id = 5d + [/UNKNOWN RECORD] + + ============================================ + rectype = 0x809, recsize = 0x10 + -BEGIN DUMP--------------------------------- + 00000000 00 06 20 00 FE 1C CD 07 C9 40 00 00 06 01 00 00 .. ......@...... + -END DUMP----------------------------------- + recordid = 0x809, size =16 + [BOF RECORD] + .version = 600 + .type = 20 + .build = 1cfe + .buildyear = 1997 + .history = 40c9 + .requiredversion = 106 + [/BOF RECORD] + + ============================================ + rectype = 0x14, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x14, size =0 + [HEADER] + .length = 0 + .header = null + [/HEADER] + + ============================================ + rectype = 0x15, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x15, size =0 + [FOOTER] + .footerlen = 0 + .footer = null + [/FOOTER] + + ============================================ + rectype = 0x83, recsize = 0x2 + -BEGIN DUMP--------------------------------- + 00000000 00 00 .. + -END DUMP----------------------------------- + recordid = 0x83, size =2 + [HCENTER] + .hcenter = false + [/HCENTER] + + ============================================ + rectype = 0x84, recsize = 0x2 + -BEGIN DUMP--------------------------------- + 00000000 00 00 .. + -END DUMP----------------------------------- + recordid = 0x84, size =2 + [VCENTER] + .vcenter = false + [/VCENTER] + + ============================================ + rectype = 0xa1, recsize = 0x22 + -BEGIN DUMP--------------------------------- + 00000000 00 00 12 00 01 00 01 00 01 00 04 00 00 00 B8 03 ................ + 00000010 00 00 00 00 00 00 E0 3F 00 00 00 00 00 00 E0 3F .......?.......? + 00000020 0F 00 .. + -END DUMP----------------------------------- + recordid = 0xa1, size =34 + [PRINTSETUP] + .papersize = 0 + .scale = 18 + .pagestart = 1 + .fitwidth = 1 + .fitheight = 1 + .options = 4 + .ltor = false + .landscape = false + .valid = true + .mono = false + .draft = false + .notes = false + .noOrientat = false + .usepage = false + .hresolution = 0 + .vresolution = 952 + .headermargin = 0.5 + .footermargin = 0.5 + .copies = 15 + [/PRINTSETUP] + + + ============================================ + rectype = 0x33, recsize = 0x2 + -BEGIN DUMP--------------------------------- + 00000000 03 00 .. + -END DUMP----------------------------------- + recordid = 0x33, size =2 + [UNKNOWN RECORD:33] + .id = 33 + [/UNKNOWN RECORD] + + ============================================ + rectype = 0x1060, recsize = 0xa + -BEGIN DUMP--------------------------------- + 00000000 A0 23 08 16 C8 00 00 00 05 00 .#........ + -END DUMP----------------------------------- + recordid = 0x1060, size =10 + [FBI] + .xBasis = 0x23A0 (9120 ) + .yBasis = 0x1608 (5640 ) + .heightBasis = 0x00C8 (200 ) + .scale = 0x0000 (0 ) + .indexToFontTable = 0x0005 (5 ) + [/FBI] + + ============================================ + rectype = 0x1060, recsize = 0xa + -BEGIN DUMP--------------------------------- + 00000000 A0 23 08 16 C8 00 01 00 06 00 .#........ + -END DUMP----------------------------------- + recordid = 0x1060, size =10 + [FBI] + .xBasis = 0x23A0 (9120 ) + .yBasis = 0x1608 (5640 ) + .heightBasis = 0x00C8 (200 ) + .scale = 0x0001 (1 ) + .indexToFontTable = 0x0006 (6 ) + [/FBI] + + ============================================ + rectype = 0x12, recsize = 0x2 + -BEGIN DUMP--------------------------------- + 00000000 00 00 .. + -END DUMP----------------------------------- + recordid = 0x12, size =2 + [PROTECT] + .rowheight = 0 + [/PROTECT] + + ============================================ + Offset 0xf22 (3874) + rectype = 0x1001, recsize = 0x2 + -BEGIN DUMP--------------------------------- + 00000000 00 00 .. + -END DUMP----------------------------------- + recordid = 0x1001, size =2 + [UNITS] + .units = 0x0000 (0 ) + [/UNITS] + + ============================================ + Offset 0xf28 (3880) + rectype = 0x1002, recsize = 0x10 + -BEGIN DUMP--------------------------------- + 00000000 00 00 00 00 00 00 00 00 58 66 D0 01 40 66 22 01 ........Xf..@f". + -END DUMP----------------------------------- + recordid = 0x1002, size =16 + [CHART] + .x = 0x00000000 (0 ) + .y = 0x00000000 (0 ) + .width = 0x01D06658 (30434904 ) + .height = 0x01226640 (19031616 ) + [/CHART] + + ============================================ + Offset 0xf3c (3900) + rectype = 0x1033, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1033, size =0 + [BEGIN] + [/BEGIN] + + ============================================ + Offset 0xf40 (3904) + rectype = 0xa0, recsize = 0x4 + -BEGIN DUMP--------------------------------- + 00000000 01 00 01 00 .... + -END DUMP----------------------------------- + recordid = 0xa0, size =4 + [SCL] + .numerator = 0x0001 (1 ) + .denominator = 0x0001 (1 ) + [/SCL] + + + ============================================ + Offset 0xf48 (3912) + rectype = 0x1064, recsize = 0x8 + -BEGIN DUMP--------------------------------- + 00000000 00 00 01 00 00 00 01 00 ........ + -END DUMP----------------------------------- + recordid = 0x1064, size =8 + [PLOTGROWTH] + .horizontalScale = 0x00010000 (65536 ) + .verticalScale = 0x00010000 (65536 ) + [/PLOTGROWTH] + + ============================================ + Offset 0xf54 (3924) + rectype = 0x1032, recsize = 0x4 + -BEGIN DUMP--------------------------------- + 00000000 00 00 02 00 .... + -END DUMP----------------------------------- + recordid = 0x1032, size =4 + [FRAME] + .borderType = 0x0000 (0 ) + .options = 0x0002 (2 ) + .autoSize = false + .autoPosition = true + [/FRAME] + + ============================================ + Offset 0xf5c (3932) + rectype = 0x1033, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1033, size =0 + [BEGIN] + [/BEGIN] + + ============================================ + Offset 0xf60 (3936) + rectype = 0x1007, recsize = 0xc + -BEGIN DUMP--------------------------------- + 00000000 00 00 00 00 00 00 FF FF 09 00 4D 00 ..........M. + -END DUMP----------------------------------- + recordid = 0x1007, size =12 + [LINEFORMAT] + .lineColor = 0x00000000 (0 ) + .linePattern = 0x0000 (0 ) + .weight = 0xFFFF (-1 ) + .format = 0x0009 (9 ) + .auto = true + .drawTicks = false + .unknown = false + .colourPaletteIndex = 0x004D (77 ) + [/LINEFORMAT] + + ============================================ + Offset 0xf70 (3952) + rectype = 0x100a, recsize = 0x10 + -BEGIN DUMP--------------------------------- + 00000000 FF FF FF 00 00 00 00 00 01 00 01 00 4E 00 4D 00 ............N.M. + -END DUMP----------------------------------- + recordid = 0x100a, size =16 + [AREAFORMAT] + .foregroundColor = 0x00FFFFFF (16777215 ) + .backgroundColor = 0x00000000 (0 ) + .pattern = 0x0001 (1 ) + .formatFlags = 0x0001 (1 ) + .automatic = true + .invert = false + .forecolorIndex = 0x004E (78 ) + .backcolorIndex = 0x004D (77 ) + [/AREAFORMAT] + + ============================================ + Offset 0xf84 (3972) + rectype = 0x1034, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1034, size =0 + [END] + [/END] + + ============================================ + Offset 0xf88 (3976) + rectype = 0x1003, recsize = 0xc + -BEGIN DUMP--------------------------------- + 00000000 01 00 01 00 20 00 1F 00 01 00 00 00 .... ....... + -END DUMP----------------------------------- + recordid = 0x1003, size =12 + [SERIES] + .categoryDataType = 0x0001 (1 ) + .valuesDataType = 0x0001 (1 ) + .numCategories = 0x0020 (32 ) + .numValues = 0x001F (31 ) + .bubbleSeriesType = 0x0001 (1 ) + .numBubbleValues = 0x0000 (0 ) + [/SERIES] + + ============================================ + Offset 0xf98 (3992) + rectype = 0x1033, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1033, size =0 + [BEGIN] + [/BEGIN] + + + ============================================ + Offset 0xf9c (3996) + rectype = 0x1051, recsize = 0x8 + -BEGIN DUMP--------------------------------- + 00000000 00 01 00 00 00 00 00 00 ........ + -END DUMP----------------------------------- + recordid = 0x1051, size =8 + [AI] + .linkType = 0x00 (0 ) + .referenceType = 0x01 (1 ) + .options = 0x0000 (0 ) + .customNumberFormat = false + .indexNumberFmtRecord = 0x0000 (0 ) + .formulaOfLink = (org.apache.poi.hssf.record.LinkedDataFormulaField@1ee3914 ) + [/AI] + + ============================================ + Offset 0xfa8 (4008) + rectype = 0x1051, recsize = 0x13 + -BEGIN DUMP--------------------------------- + 00000000 01 02 00 00 00 00 0B 00 3B 00 00 00 00 1E 00 01 ........;....... + 00000010 00 01 00 ... + -END DUMP----------------------------------- + recordid = 0x1051, size =19 + [AI] + .linkType = 0x01 (1 ) + .referenceType = 0x02 (2 ) + .options = 0x0000 (0 ) + .customNumberFormat = false + .indexNumberFmtRecord = 0x0000 (0 ) + .formulaOfLink = (org.apache.poi.hssf.record.LinkedDataFormulaField@e5855a ) + [/AI] + + ============================================ + Offset 0xfbf (4031) + rectype = 0x1051, recsize = 0x13 + -BEGIN DUMP--------------------------------- + 00000000 02 02 00 00 69 01 0B 00 3B 00 00 00 00 1F 00 00 ....i...;....... + 00000010 00 00 00 ... + -END DUMP----------------------------------- + recordid = 0x1051, size =19 + [AI] + .linkType = 0x02 (2 ) + .referenceType = 0x02 (2 ) + .options = 0x0000 (0 ) + .customNumberFormat = false + .indexNumberFmtRecord = 0x0169 (361 ) + .formulaOfLink = (org.apache.poi.hssf.record.LinkedDataFormulaField@95fd19 ) + [/AI] + + ============================================ + Offset 0xfd6 (4054) + rectype = 0x1051, recsize = 0x8 + -BEGIN DUMP--------------------------------- + 00000000 03 01 00 00 00 00 00 00 ........ + -END DUMP----------------------------------- + recordid = 0x1051, size =8 + [AI] + .linkType = 0x03 (3 ) + .referenceType = 0x01 (1 ) + .options = 0x0000 (0 ) + .customNumberFormat = false + .indexNumberFmtRecord = 0x0000 (0 ) + .formulaOfLink = (org.apache.poi.hssf.record.LinkedDataFormulaField@11b9fb1 ) + [/AI] + + ============================================ + Offset 0xfe2 (4066) + rectype = 0x1006, recsize = 0x8 + -BEGIN DUMP--------------------------------- + 00000000 FF FF 00 00 00 00 00 00 ........ + -END DUMP----------------------------------- + recordid = 0x1006, size =8 + [DATAFORMAT] + .pointNumber = 0xFFFF (-1 ) + .seriesIndex = 0x0000 (0 ) + .seriesNumber = 0x0000 (0 ) + .formatFlags = 0x0000 (0 ) + .useExcel4Colors = false + [/DATAFORMAT] + + ============================================ + Offset 0xfee (4078) + rectype = 0x1033, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1033, size =0 + [BEGIN] + [/BEGIN] + + ============================================ + Offset 0xff2 (4082) + rectype = 0x105f, recsize = 0x2 + -BEGIN DUMP--------------------------------- + 00000000 00 00 .. + -END DUMP----------------------------------- + recordid = 0x105f, size =2 + [UNKNOWN RECORD] + .id = 105f + [/UNKNOWN RECORD] + + ============================================ + Offset 0xff8 (4088) + rectype = 0x1034, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1034, size =0 + [END] + [/END] + + ============================================ + Offset 0xffc (4092) + rectype = 0x1045, recsize = 0x2 + -BEGIN DUMP--------------------------------- + 00000000 00 00 .. + -END DUMP----------------------------------- + recordid = 0x1045, size =2 + [SeriesToChartGroup] + .chartGroupIndex = 0x0000 (0 ) + [/SeriesToChartGroup] + + ============================================ + Offset 0x1002 (4098) + rectype = 0x1034, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1034, size =0 + [END] + [/END] + + ============================================ + Offset 0x1006 (4102) + rectype = 0x1044, recsize = 0x4 + -BEGIN DUMP--------------------------------- + 00000000 0A 00 00 00 .... + -END DUMP----------------------------------- + recordid = 0x1044, size =4 + [SHTPROPS] + .flags = 0x000A (10 ) + .chartTypeManuallyFormatted = false + .plotVisibleOnly = true + .doNotSizeWithWindow = false + .defaultPlotDimensions = true + .autoPlotArea = false + .empty = 0x00 (0 ) + [/SHTPROPS] + + ============================================ + Offset 0x100e (4110) + rectype = 0x1024, recsize = 0x2 + -BEGIN DUMP--------------------------------- + 00000000 02 00 .. + -END DUMP----------------------------------- + recordid = 0x1024, size =2 + [DEFAULTTEXT] + .categoryDataType = 0x0002 (2 ) + [/DEFAULTTEXT] + + ============================================ + Offset 0x1014 (4116) + rectype = 0x1025, recsize = 0x20 + -BEGIN DUMP--------------------------------- + 00000000 02 02 01 00 00 00 00 00 DB FF FF FF C4 FF FF FF ................ + 00000010 00 00 00 00 00 00 00 00 B1 00 4D 00 50 2B 00 00 ..........M.P+.. + -END DUMP----------------------------------- + recordid = 0x1025, size =32 + [TEXT] + .horizontalAlignment = 0x02 (2 ) + .verticalAlignment = 0x02 (2 ) + .displayMode = 0x0001 (1 ) + .rgbColor = 0x00000000 (0 ) + .x = 0xFFFFFFDB (-37 ) + .y = 0xFFFFFFC4 (-60 ) + .width = 0x00000000 (0 ) + .height = 0x00000000 (0 ) + .options1 = 0x00B1 (177 ) + .autoColor = true + .showKey = false + .showValue = false + .vertical = false + .autoGeneratedText = true + .generated = true + .autoLabelDeleted = false + .autoBackground = true + .rotation = 0 + .showCategoryLabelAsPercentage = false + .showValueAsPercentage = false + .showBubbleSizes = false + .showLabel = false + .indexOfColorValue = 0x004D (77 ) + .options2 = 0x2B50 (11088 ) + .dataLabelPlacement = 0 + .textRotation = 0x0000 (0 ) + [/TEXT] + + ============================================ + Offset 0x1038 (4152) + rectype = 0x1033, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1033, size =0 + [BEGIN] + [/BEGIN] + + + ============================================ + Offset 0x103c (4156) + rectype = 0x104f, recsize = 0x14 + -BEGIN DUMP--------------------------------- + 00000000 02 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00000010 00 00 00 00 .... + -END DUMP----------------------------------- + recordid = 0x104f, size =20 + [UNKNOWN RECORD] + .id = 104f + [/UNKNOWN RECORD] + + ============================================ + Offset 0x1054 (4180) + rectype = 0x1026, recsize = 0x2 + -BEGIN DUMP--------------------------------- + 00000000 05 00 .. + -END DUMP----------------------------------- + recordid = 0x1026, size =2 + [FONTX] + .fontIndex = 0x0005 (5 ) + [/FONTX] + + ============================================ + Offset 0x105a (4186) + rectype = 0x1051, recsize = 0x8 + -BEGIN DUMP--------------------------------- + 00000000 00 01 00 00 00 00 00 00 ........ + -END DUMP----------------------------------- + recordid = 0x1051, size =8 + [AI] + .linkType = 0x00 (0 ) + .referenceType = 0x01 (1 ) + .options = 0x0000 (0 ) + .customNumberFormat = false + .indexNumberFmtRecord = 0x0000 (0 ) + .formulaOfLink = (org.apache.poi.hssf.record.LinkedDataFormulaField@913fe2 ) + [/AI] + + ============================================ + Offset 0x1066 (4198) + rectype = 0x1034, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1034, size =0 + [END] + [/END] + + ============================================ + Offset 0x106a (4202) + rectype = 0x1024, recsize = 0x2 + -BEGIN DUMP--------------------------------- + 00000000 03 00 .. + -END DUMP----------------------------------- + recordid = 0x1024, size =2 + [DEFAULTTEXT] + .categoryDataType = 0x0003 (3 ) + [/DEFAULTTEXT] + + ============================================ + Offset 0x1070 (4208) + rectype = 0x1025, recsize = 0x20 + -BEGIN DUMP--------------------------------- + 00000000 02 02 01 00 00 00 00 00 DB FF FF FF C4 FF FF FF ................ + 00000010 00 00 00 00 00 00 00 00 B1 00 4D 00 50 2B 00 00 ..........M.P+.. + -END DUMP----------------------------------- + recordid = 0x1025, size =32 + [TEXT] + .horizontalAlignment = 0x02 (2 ) + .verticalAlignment = 0x02 (2 ) + .displayMode = 0x0001 (1 ) + .rgbColor = 0x00000000 (0 ) + .x = 0xFFFFFFDB (-37 ) + .y = 0xFFFFFFC4 (-60 ) + .width = 0x00000000 (0 ) + .height = 0x00000000 (0 ) + .options1 = 0x00B1 (177 ) + .autoColor = true + .showKey = false + .showValue = false + .vertical = false + .autoGeneratedText = true + .generated = true + .autoLabelDeleted = false + .autoBackground = true + .rotation = 0 + .showCategoryLabelAsPercentage = false + .showValueAsPercentage = false + .showBubbleSizes = false + .showLabel = false + .indexOfColorValue = 0x004D (77 ) + .options2 = 0x2B50 (11088 ) + .dataLabelPlacement = 0 + .textRotation = 0x0000 (0 ) + [/TEXT] + + ============================================ + Offset 0x1094 (4244) + rectype = 0x1033, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1033, size =0 + [BEGIN] + [/BEGIN] + + ============================================ + Offset 0x1098 (4248) + rectype = 0x104f, recsize = 0x14 + -BEGIN DUMP--------------------------------- + 00000000 02 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00000010 00 00 00 00 .... + -END DUMP----------------------------------- + recordid = 0x104f, size =20 + [UNKNOWN RECORD] + .id = 104f + [/UNKNOWN RECORD] + + ============================================ + Offset 0x10b0 (4272) + rectype = 0x1026, recsize = 0x2 + -BEGIN DUMP--------------------------------- + 00000000 06 00 .. + -END DUMP----------------------------------- + recordid = 0x1026, size =2 + [FONTX] + .fontIndex = 0x0006 (6 ) + [/FONTX] + + ============================================ + Offset 0x10b6 (4278) + rectype = 0x1051, recsize = 0x8 + -BEGIN DUMP--------------------------------- + 00000000 00 01 00 00 00 00 00 00 ........ + -END DUMP----------------------------------- + recordid = 0x1051, size =8 + [AI] + .linkType = 0x00 (0 ) + .referenceType = 0x01 (1 ) + .options = 0x0000 (0 ) + .customNumberFormat = false + .indexNumberFmtRecord = 0x0000 (0 ) + .formulaOfLink = (org.apache.poi.hssf.record.LinkedDataFormulaField@1f934ad ) + [/AI] + + ============================================ + Offset 0x10c2 (4290) + rectype = 0x1034, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1034, size =0 + [END] + [/END] + + ============================================ + Offset 0x10c6 (4294) + rectype = 0x1046, recsize = 0x2 + -BEGIN DUMP--------------------------------- + 00000000 01 00 .. + -END DUMP----------------------------------- + recordid = 0x1046, size =2 + [AXISUSED] + .numAxis = 0x0001 (1 ) + [/AXISUSED] + + ============================================ + Offset 0x10cc (4300) + rectype = 0x1041, recsize = 0x12 + -BEGIN DUMP--------------------------------- + 00000000 00 00 DF 01 00 00 DD 00 00 00 B3 0B 00 00 56 0B ..............V. + 00000010 00 00 .. + -END DUMP----------------------------------- + recordid = 0x1041, size =18 + [AXISPARENT] + .axisType = 0x0000 (0 ) + .x = 0x000001DF (479 ) + .y = 0x000000DD (221 ) + .width = 0x00000BB3 (2995 ) + .height = 0x00000B56 (2902 ) + [/AXISPARENT] + + ============================================ + Offset 0x10e2 (4322) + rectype = 0x1033, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1033, size =0 + [BEGIN] + [/BEGIN] + + ============================================ + Offset 0x10e6 (4326) + rectype = 0x104f, recsize = 0x14 + -BEGIN DUMP--------------------------------- + 00000000 02 00 02 00 3A 00 00 00 5E 00 00 00 58 0D 00 00 ....:...^...X... + 00000010 E5 0E 00 00 .... + -END DUMP----------------------------------- + recordid = 0x104f, size =20 + [UNKNOWN RECORD] + .id = 104f + [/UNKNOWN RECORD] + + ============================================ + Offset 0x10fe (4350) + rectype = 0x101d, recsize = 0x12 + -BEGIN DUMP--------------------------------- + 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00000010 00 00 .. + -END DUMP----------------------------------- + recordid = 0x101d, size =18 + [AXIS] + .axisType = 0x0000 (0 ) + .reserved1 = 0x00000000 (0 ) + .reserved2 = 0x00000000 (0 ) + .reserved3 = 0x00000000 (0 ) + .reserved4 = 0x00000000 (0 ) + [/AXIS] + + ============================================ + Offset 0x1114 (4372) + rectype = 0x1033, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1033, size =0 + [BEGIN] + [/BEGIN] + + ============================================ + Offset 0x1118 (4376) + rectype = 0x1020, recsize = 0x8 + -BEGIN DUMP--------------------------------- + 00000000 01 00 01 00 01 00 01 00 ........ + -END DUMP----------------------------------- + recordid = 0x1020, size =8 + [CATSERRANGE] + .crossingPoint = 0x0001 (1 ) + .labelFrequency = 0x0001 (1 ) + .tickMarkFrequency = 0x0001 (1 ) + .options = 0x0001 (1 ) + .valueAxisCrossing = true + .crossesFarRight = false + .reversed = false + [/CATSERRANGE] + + ============================================ + Offset 0x1124 (4388) + rectype = 0x1062, recsize = 0x12 + -BEGIN DUMP--------------------------------- + 00000000 1C 90 39 90 02 00 00 00 01 00 00 00 00 00 1C 90 ..9............. + 00000010 FF 00 .. + -END DUMP----------------------------------- + recordid = 0x1062, size =18 + [AXCEXT] + .minimumCategory = 0x901C (-28644 ) + .maximumCategory = 0x9039 (-28615 ) + .majorUnitValue = 0x0002 (2 ) + .majorUnit = 0x0000 (0 ) + .minorUnitValue = 0x0001 (1 ) + .minorUnit = 0x0000 (0 ) + .baseUnit = 0x0000 (0 ) + .crossingPoint = 0x901C (-28644 ) + .options = 0x00FF (255 ) + .defaultMinimum = true + .defaultMaximum = true + .defaultMajor = true + .defaultMinorUnit = true + .isDate = true + .defaultBase = true + .defaultCross = true + .defaultDateSettings = true + [/AXCEXT] + + ============================================ + Offset 0x113a (4410) + rectype = 0x101e, recsize = 0x1e + -BEGIN DUMP--------------------------------- + 00000000 02 00 03 01 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00000010 00 00 00 00 00 00 00 00 23 00 4D 00 2D 00 ........#.M.-. + -END DUMP----------------------------------- + recordid = 0x101e, size =30 + [TICK] + .majorTickType = 0x02 (2 ) + .minorTickType = 0x00 (0 ) + .labelPosition = 0x03 (3 ) + .background = 0x01 (1 ) + .labelColorRgb = 0x00000000 (0 ) + .zero1 = 0x0000 (0 ) + .zero2 = 0x0000 (0 ) + .options = 0x0023 (35 ) + .autoTextColor = true + .autoTextBackground = true + .rotation = 0 + .autorotate = true + .tickColor = 0x004D (77 ) + .zero3 = 0x002D (45 ) + [/TICK] + + ============================================ + Offset 0x115c (4444) + rectype = 0x1034, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1034, size =0 + [END] + [/END] + + ============================================ + Offset 0x1160 (4448) + rectype = 0x101d, recsize = 0x12 + -BEGIN DUMP--------------------------------- + 00000000 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00000010 00 00 .. + -END DUMP----------------------------------- + recordid = 0x101d, size =18 + [AXIS] + .axisType = 0x0001 (1 ) + .reserved1 = 0x00000000 (0 ) + .reserved2 = 0x00000000 (0 ) + .reserved3 = 0x00000000 (0 ) + .reserved4 = 0x00000000 (0 ) + [/AXIS] + + + ============================================ + Offset 0x1176 (4470) + rectype = 0x1033, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1033, size =0 + [BEGIN] + [/BEGIN] + + ============================================ + Offset 0x117a (4474) + rectype = 0x101f, recsize = 0x2a + -BEGIN DUMP--------------------------------- + 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00000020 00 00 00 00 00 00 00 00 1F 01 .......... + -END DUMP----------------------------------- + recordid = 0x101f, size =42 + [VALUERANGE] + .minimumAxisValue = (0.0 ) + .maximumAxisValue = (0.0 ) + .majorIncrement = (0.0 ) + .minorIncrement = (0.0 ) + .categoryAxisCross = (0.0 ) + .options = 0x011F (287 ) + .automaticMinimum = true + .automaticMaximum = true + .automaticMajor = true + .automaticMinor = true + .automaticCategoryCrossing = true + .logarithmicScale = false + .valuesInReverse = false + .crossCategoryAxisAtMaximum = false + .reserved = true + [/VALUERANGE] + + ============================================ + Offset 0x11a8 (4520) + rectype = 0x101e, recsize = 0x1e + -BEGIN DUMP--------------------------------- + 00000000 02 00 03 01 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00000010 00 00 00 00 00 00 00 00 23 00 4D 00 00 00 ........#.M... + -END DUMP----------------------------------- + recordid = 0x101e, size =30 + [TICK] + .majorTickType = 0x02 (2 ) + .minorTickType = 0x00 (0 ) + .labelPosition = 0x03 (3 ) + .background = 0x01 (1 ) + .labelColorRgb = 0x00000000 (0 ) + .zero1 = 0x0000 (0 ) + .zero2 = 0x0000 (0 ) + .options = 0x0023 (35 ) + .autoTextColor = true + .autoTextBackground = true + .rotation = 0 + .autorotate = true + .tickColor = 0x004D (77 ) + .zero3 = 0x0000 (0 ) + [/TICK] + + ============================================ + Offset 0x11ca (4554) + rectype = 0x1021, recsize = 0x2 + -BEGIN DUMP--------------------------------- + 00000000 01 00 .. + -END DUMP----------------------------------- + recordid = 0x1021, size =2 + [AXISLINEFORMAT] + .axisType = 0x0001 (1 ) + [/AXISLINEFORMAT] + + ============================================ + Offset 0x11d0 (4560) + rectype = 0x1007, recsize = 0xc + -BEGIN DUMP--------------------------------- + 00000000 00 00 00 00 00 00 FF FF 09 00 4D 00 ..........M. + -END DUMP----------------------------------- + recordid = 0x1007, size =12 + [LINEFORMAT] + .lineColor = 0x00000000 (0 ) + .linePattern = 0x0000 (0 ) + .weight = 0xFFFF (-1 ) + .format = 0x0009 (9 ) + .auto = true + .drawTicks = false + .unknown = false + .colourPaletteIndex = 0x004D (77 ) + [/LINEFORMAT] + + ============================================ + Offset 0x11e0 (4576) + rectype = 0x1034, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1034, size =0 + [END] + [/END] + + ============================================ + Offset 0x11e4 (4580) + rectype = 0x1035, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1035, size =0 + [PLOTAREA] + [/PLOTAREA] + + ============================================ + Offset 0x11e8 (4584) + rectype = 0x1032, recsize = 0x4 + -BEGIN DUMP--------------------------------- + 00000000 00 00 03 00 .... + -END DUMP----------------------------------- + recordid = 0x1032, size =4 + [FRAME] + .borderType = 0x0000 (0 ) + .options = 0x0003 (3 ) + .autoSize = true + .autoPosition = true + [/FRAME] + + ============================================ + Offset 0x11f0 (4592) + rectype = 0x1033, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1033, size =0 + [BEGIN] + [/BEGIN] + + ============================================ + Offset 0x11f4 (4596) + rectype = 0x1007, recsize = 0xc + -BEGIN DUMP--------------------------------- + 00000000 80 80 80 00 00 00 00 00 00 00 17 00 ............ + -END DUMP----------------------------------- + recordid = 0x1007, size =12 + [LINEFORMAT] + .lineColor = 0x00808080 (8421504 ) + .linePattern = 0x0000 (0 ) + .weight = 0x0000 (0 ) + .format = 0x0000 (0 ) + .auto = false + .drawTicks = false + .unknown = false + .colourPaletteIndex = 0x0017 (23 ) + [/LINEFORMAT] + + ============================================ + Offset 0x1204 (4612) + rectype = 0x100a, recsize = 0x10 + -BEGIN DUMP--------------------------------- + 00000000 C0 C0 C0 00 00 00 00 00 01 00 00 00 16 00 4F 00 ..............O. + -END DUMP----------------------------------- + recordid = 0x100a, size =16 + [AREAFORMAT] + .foregroundColor = 0x00C0C0C0 (12632256 ) + .backgroundColor = 0x00000000 (0 ) + .pattern = 0x0001 (1 ) + .formatFlags = 0x0000 (0 ) + .automatic = false + .invert = false + .forecolorIndex = 0x0016 (22 ) + .backcolorIndex = 0x004F (79 ) + [/AREAFORMAT] + + ============================================ + Offset 0x1218 (4632) + rectype = 0x1034, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1034, size =0 + [END] + [/END] + + ============================================ + Offset 0x121c (4636) + rectype = 0x1014, recsize = 0x14 + -BEGIN DUMP--------------------------------- + 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00000010 00 00 00 00 .... + -END DUMP----------------------------------- + recordid = 0x1014, size =20 + [CHARTFORMAT] + .xPosition = 0 + .yPosition = 0 + .width = 0 + .height = 0 + .grBit = 0 + [/CHARTFORMAT] + + ============================================ + Offset 0x1234 (4660) + rectype = 0x1033, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1033, size =0 + [BEGIN] + [/BEGIN] + + ============================================ + Offset 0x1238 (4664) + rectype = 0x1017, recsize = 0x6 + -BEGIN DUMP--------------------------------- + 00000000 00 00 96 00 00 00 ...... + -END DUMP----------------------------------- + recordid = 0x1017, size =6 + [BAR] + .barSpace = 0x0000 (0 ) + .categorySpace = 0x0096 (150 ) + .formatFlags = 0x0000 (0 ) + .horizontal = false + .stacked = false + .displayAsPercentage = false + .shadow = false + [/BAR] + + ============================================ + Offset 0x1242 (4674) + rectype = 0x1022, recsize = 0xa + -BEGIN DUMP--------------------------------- + 00000000 00 00 00 00 00 00 00 00 0F 00 .......... + -END DUMP----------------------------------- + recordid = 0x1022, size =10 + [UNKNOWN RECORD] + .id = 1022 + [/UNKNOWN RECORD] + + ============================================ + Offset 0x1250 (4688) + rectype = 0x1015, recsize = 0x14 + -BEGIN DUMP--------------------------------- + 00000000 D6 0D 00 00 1E 06 00 00 B5 01 00 00 D5 00 00 00 ................ + 00000010 03 01 1F 00 .... + -END DUMP----------------------------------- + recordid = 0x1015, size =20 + [LEGEND] + .xAxisUpperLeft = 0x00000DD6 (3542 ) + .yAxisUpperLeft = 0x0000061E (1566 ) + .xSize = 0x000001B5 (437 ) + .ySize = 0x000000D5 (213 ) + .type = 0x03 (3 ) + .spacing = 0x01 (1 ) + .options = 0x001F (31 ) + .autoPosition = true + .autoSeries = true + .autoXPositioning = true + .autoYPositioning = true + .vertical = true + .dataTable = false + [/LEGEND] + + ============================================ + Offset 0x1268 (4712) + rectype = 0x1033, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1033, size =0 + [BEGIN] + [/BEGIN] + + ============================================ + Offset 0x126c (4716) + rectype = 0x104f, recsize = 0x14 + -BEGIN DUMP--------------------------------- + 00000000 05 00 02 00 D6 0D 00 00 1E 06 00 00 00 00 00 00 ................ + 00000010 00 00 00 00 .... + -END DUMP----------------------------------- + recordid = 0x104f, size =20 + [UNKNOWN RECORD] + .id = 104f + [/UNKNOWN RECORD] + + ============================================ + Offset 0x1284 (4740) + rectype = 0x1025, recsize = 0x20 + -BEGIN DUMP--------------------------------- + 00000000 02 02 01 00 00 00 00 00 DB FF FF FF C4 FF FF FF ................ + 00000010 00 00 00 00 00 00 00 00 B1 00 4D 00 70 37 00 00 ..........M.p7.. + -END DUMP----------------------------------- + recordid = 0x1025, size =32 + [TEXT] + .horizontalAlignment = 0x02 (2 ) + .verticalAlignment = 0x02 (2 ) + .displayMode = 0x0001 (1 ) + .rgbColor = 0x00000000 (0 ) + .x = 0xFFFFFFDB (-37 ) + .y = 0xFFFFFFC4 (-60 ) + .width = 0x00000000 (0 ) + .height = 0x00000000 (0 ) + .options1 = 0x00B1 (177 ) + .autoColor = true + .showKey = false + .showValue = false + .vertical = false + .autoGeneratedText = true + .generated = true + .autoLabelDeleted = false + .autoBackground = true + .rotation = 0 + .showCategoryLabelAsPercentage = false + .showValueAsPercentage = false + .showBubbleSizes = false + .showLabel = false + .indexOfColorValue = 0x004D (77 ) + .options2 = 0x3770 (14192 ) + .dataLabelPlacement = 0 + .textRotation = 0x0000 (0 ) + [/TEXT] + + ============================================ + Offset 0x12a8 (4776) + rectype = 0x1033, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1033, size =0 + [BEGIN] + [/BEGIN] + + ============================================ + Offset 0x12ac (4780) + rectype = 0x104f, recsize = 0x14 + -BEGIN DUMP--------------------------------- + 00000000 02 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00000010 00 00 00 00 .... + -END DUMP----------------------------------- + recordid = 0x104f, size =20 + [UNKNOWN RECORD] + .id = 104f + [/UNKNOWN RECORD] + + ============================================ + Offset 0x12c4 (4804) + rectype = 0x1051, recsize = 0x8 + -BEGIN DUMP--------------------------------- + 00000000 00 01 00 00 00 00 00 00 ........ + -END DUMP----------------------------------- + recordid = 0x1051, size =8 + [AI] + .linkType = 0x00 (0 ) + .referenceType = 0x01 (1 ) + .options = 0x0000 (0 ) + .customNumberFormat = false + .indexNumberFmtRecord = 0x0000 (0 ) + .formulaOfLink = (org.apache.poi.hssf.record.LinkedDataFormulaField@1d05c81 ) + [/AI] + + ============================================ + Offset 0x12d0 (4816) + rectype = 0x1034, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1034, size =0 + [END] + [/END] + + + ============================================ + Offset 0x12d4 (4820) + rectype = 0x1034, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1034, size =0 + [END] + [/END] + + ============================================ + Offset 0x12d8 (4824) + rectype = 0x1034, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1034, size =0 + [END] + [/END] + + ============================================ + Offset 0x12dc (4828) + rectype = 0x1034, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1034, size =0 + [END] + [/END] + + ============================================ + Offset 0x12e0 (4832) + rectype = 0x1034, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0x1034, size =0 + [END] + [/END] + + ============================================ + rectype = 0x200, recsize = 0xe + -BEGIN DUMP--------------------------------- + 00000000 00 00 00 00 1F 00 00 00 00 00 01 00 00 00 .............. + -END DUMP----------------------------------- + recordid = 0x200, size =14 + [DIMENSIONS] + .firstrow = 0 + .lastrow = 1f + .firstcol = 0 + .lastcol = 1 + .zero = 0 + [/DIMENSIONS] + + ============================================ + rectype = 0x1065, recsize = 0x2 + -BEGIN DUMP--------------------------------- + 00000000 02 00 .. + -END DUMP----------------------------------- + recordid = 0x1065, size =2 + [SINDEX] + .index = 0x0002 (2 ) + [/SINDEX] + + ============================================ + rectype = 0x1065, recsize = 0x2 + -BEGIN DUMP--------------------------------- + 00000000 01 00 .. + -END DUMP----------------------------------- + recordid = 0x1065, size =2 + [SINDEX] + .index = 0x0001 (1 ) + [/SINDEX] + + ============================================ + rectype = 0x1065, recsize = 0x2 + -BEGIN DUMP--------------------------------- + 00000000 03 00 .. + -END DUMP----------------------------------- + recordid = 0x1065, size =2 + [SINDEX] + .index = 0x0003 (3 ) + [/SINDEX] + + ============================================ + rectype = 0xa, recsize = 0x0 + -BEGIN DUMP--------------------------------- + **NO RECORD DATA** + -END DUMP----------------------------------- + recordid = 0xa, size =0 + [EOF] + [/EOF] + + + +

+ The next section breaks those records down into an easier + to read format: +

+ +[UNKNOWN RECORD:ec] +[UNKNOWN RECORD:5d] +[BOF RECORD] + [HEADER] + [FOOTER] + [HCENTER] + [VCENTER] + [PRINTSETUP] + [UNKNOWN RECORD:33] + [FBI] + [FBI] + [PROTECT] + [UNITS] + [CHART] + [BEGIN] + [SCL] // zoom magnification + [PLOTGROWTH] // font scaling + [FRAME] // border around text + [BEGIN] // default line and area format + [LINEFORMAT] + [AREAFORMAT] + [END] + [SERIES] // start of series + [BEGIN] + [AI] // LINK_TYPE_TITLE_OR_TEXT + [AI] // LINK_TYPE_VALUES + [AI] // LINK_TYPE_CATEGORIES + [AI] // ?? + [DATAFORMAT] // Formatting applies to series? + [BEGIN] // ?? + [UNKNOWN RECORD] + [END] + [SeriesToChartGroup] // Used to support > 1 chart? + [END] + [SHTPROPS] // Some defaults for how chart is displayed. + [DEFAULTTEXT] // Describes the characteristics of the next + // record + [TEXT] // Details of the text that follows in the + // next section + [BEGIN] + [UNKNOWN RECORD] // POS record... looks like I missed this one. + // docs seem to indicate it's better to use + // defaults... + [FONTX] // index to font record. + [AI] // link to text? seems to be linking to nothing + [END] + [DEFAULTTEXT] // contains a category type of 3 which is not + // documented (sigh). + [TEXT] // defines position, color etc for text on chart. + [BEGIN] + [UNKNOWN RECORD] // Another pos record + [FONTX] // font + [AI] // reference type is DIRECT (not sure what this + // means) + [END] + [AXISUSED] // number of axis on the chart. + [AXISPARENT] // axis size and location + [BEGIN] // beginning of axis details + [UNKNOWN RECORD] // Another pos record. + [AXIS] // Category axis + [BEGIN] + [CATSERRANGE] // defines tick marks and other stuff + [AXCEXT] // unit information + [TICK] // tick formating characteristics + [END] + [AXIS] // Value axis + [BEGIN] + [VALUERANGE] // defines tick marks and other stuff + [TICK] // tick formating characteristics + [AXISLINEFORMAT] // major grid line axis format + [LINEFORMAT] // what do the lines look like? + [END] + [PLOTAREA] // marks that the frame following belongs + // to the frame. + [FRAME] // border + [BEGIN] + [LINEFORMAT] // border line + [AREAFORMAT] // border area + [END] + [CHARTFORMAT] // marks a chart group + [BEGIN] + [BAR] // indicates a bar chart + [UNKNOWN RECORD] // apparently this record is ignoreable + [LEGEND] // positioning for the legend + [BEGIN] + [UNKNOWN RECORD] // another position record. + [TEXT] // details of the text that follows + // in the next section + [BEGIN] + [UNKNOWN RECORD] // yet another pos record + [AI] // another link (of type direct) + [END] + [END] + [END] + [END] + [END] + [DIMENSIONS] + [SINDEX] + [SINDEX] + [SINDEX] +[EOF] + +

+ Just a quick note on some of the unknown records: +

+
    +
  • EC: MSODRAWING - A Microsoft drawing record. (Need to + track down where this is documented).
  • +
  • 5D: OBJ: Description of a drawing object. (This is going to + be a PITA to implement).
  • +
  • 33: Not documented. :-(
  • +
  • 105f: Not documented. :-(
  • +
  • 104f: POS: Position record (should be able to safely leave this out).
  • +
  • 1022: CHARTFORMATLINK: Can be left out.
  • +
+

+ It is currently suspected that many of those records could be + left out when generating a bar chart from scratch. The way + we will be proceeding with this is to write code that generates + most of these records and then start removing them to see + how this effects the chart in excel. +

+
+
Inserting the Chart into the Workbook +
    +
  • + Unknown record (sid=00eb) is inserted before the SST + record. +
  • +
+ + ============================================ + rectype = 0xeb, recsize = 0x5a + -BEGIN DUMP--------------------------------- + 00000000 0F 00 00 F0 52 00 00 00 00 00 06 F0 18 00 00 00 ....R........... + 00000010 01 08 00 00 02 00 00 00 02 00 00 00 01 00 00 00 ................ + 00000020 01 00 00 00 03 00 00 00 33 00 0B F0 12 00 00 00 ........3....... + 00000030 BF 00 08 00 08 00 81 01 09 00 00 08 C0 01 40 00 ..............@. + 00000040 00 08 40 00 1E F1 10 00 00 00 0D 00 00 08 0C 00 ..@............. + 00000050 00 08 17 00 00 08 F7 00 00 10 .......... + -END DUMP----------------------------------- + recordid = 0xeb, size =90 + [UNKNOWN RECORD:eb] + .id = eb + [/UNKNOWN RECORD] + + ============================================ + +
    +
  • + Any extra font records are inserted as needed +
  • +
  • + Chart records inserted after DBCell records. +
  • +
+
+ +
diff --git a/src/documentation/content/xdocs/ss/diagram1.xml b/src/documentation/content/xdocs/ss/diagram1.xml new file mode 100644 index 0000000000..fbbe1f66c3 --- /dev/null +++ b/src/documentation/content/xdocs/ss/diagram1.xml @@ -0,0 +1,40 @@ + + + + + +
+ HSSF + Overview + + + + +
+ + +
+ Usermodel Class Diagram by Matthew Young +

+ Usermodel +

+
+ +
diff --git a/src/documentation/content/xdocs/ss/diagrams.xml b/src/documentation/content/xdocs/ss/diagrams.xml new file mode 100644 index 0000000000..1c1f2a76f9 --- /dev/null +++ b/src/documentation/content/xdocs/ss/diagrams.xml @@ -0,0 +1,56 @@ + + + + + +
+ HSSF + Overview + + + + +
+ + +
Overview +

+ This section is intended for diagrams (UML/etc) that help + explain HSSF. +

+
    +
  • + HSSF usermodel class diagram - + by Matthew Young (myoung at westernasset dot com) +
  • +
+

+ Have more? Add a new "bug" to the bug database with [DOCUMENTATION] + prefacing the description and a link to the file on an http server + somewhere. If you don't have your own webserver, then you can email it + to (acoliver at apache dot org) provided its < 5MB. Diagrams should be + in some format that can be read at least on Linux and Windows. Diagrams + that can be edited are preferrable, but lets face it, there aren't too + many good affordable UML tools yet! And no they don't HAVE to be UML... + just useful. +

+
+ +
diff --git a/src/documentation/content/xdocs/ss/eval-devguide.xml b/src/documentation/content/xdocs/ss/eval-devguide.xml new file mode 100644 index 0000000000..29c33b8a20 --- /dev/null +++ b/src/documentation/content/xdocs/ss/eval-devguide.xml @@ -0,0 +1,204 @@ + + + + + +
+ Developing Formula Evaluation + + +
+ +
Introduction +

This document is for developers wishing to contribute to the + FormulaEvaluator API functionality.

+

Currently, contribution is desired for implementing the standard MS + excel functions. Place holder classes for these have been created, + contributors only need to insert implementation for the + individual "evaluate()" methods that do the actual evaluation.

+
+
Overview of FormulaEvaluator +

Briefly, a formula string (along with the sheet and workbook that + form the context in which the formula is evaluated) is first parsed + into RPN tokens using the FormulaParser class in POI-HSSF main. + (If you dont know what RPN tokens are, now is a good time to + read + this.) +

+
The big picture +

RPN tokens are mapped to Eval classes. (Class hierarchy for the Evals + is best understood if you view the class diagram in a class diagram + viewer.) Depending on the type of RPN token (also called as Ptgs + henceforth since that is what the FormulaParser calls the classes) a + specific type of Eval wrapper is constructed to wrap the RPN token and + is pushed on the stack.... UNLESS the Ptg is an OperationPtg. If it is an + OperationPtg, an OperationEval instance is created for the specific + type of OperationPtg. And depending on how many operands it takes, + that many Evals are popped of the stack and passed in an array to + the OperationEval instance's evaluate method which returns an Eval + of subtype ValueEval.Thus an operation in the formula is evaluated.

+ An Eval is of subinterface ValueEval or OperationEval. + Operands are always ValueEvals, Operations are always OperationEvals. +

OperationEval.evaluate(Eval[]) returns an Eval which is supposed + to be of type ValueEval (actually since ValueEval is an interface, + the return value is instance of one of the implementations of + ValueEval). The valueEval resulting from evaluate() is pushed on the + stack and the next RPN token is evaluated.... this continues till + eventually there are no more RPN tokens at which point, if the formula + string was correctly parsed, there should be just one Eval on the + stack - which contains the result of evaluating the formula.

+

Ofcourse I glossed over the details of how AreaPtg and ReferencePtg + are handled a little differently, but the code should be self + explanatory for that. Very briefly, the cells included in AreaPtg and + RefPtg are examined and their values are populated in individual + ValueEval objects which are set into the AreaEval and RefEval (ok, + since AreaEval and RefEval are interfaces, the implementations of + AreaEval and RefEval - but you'll figure all that out from the code)

+

OperationEvals for the standard operators have been implemented and tested.

+
+
FunctionEval and FuncVarEval +

FunctionEval is an abstract super class of FuncVarEval. The reason for this is that in the FormulaParser Ptg classes, there are two Ptgs, FuncPtg and FuncVarPtg. In my tests, I did not see FuncPtg being used so there is no corresponding FuncEval right now. But in case the need arises for a FuncVal class, FuncEval and FuncVarEval need to be isolated with a common interface/abstract class, hence FunctionEval.

+

FunctionEval also contains the mapping of which function class maps to which function index. This mapping has been done for all the functions, so all you really have to do is implement the evaluate method in the function class that has not already been implemented. The Function indexes are defined in AbstractFunctionPtg class in POI main.

+
+
+
Walkthrough of an "evaluate()" implementation. +

So here is the fun part - lets walk through the implementation of the excel + function... SQRT()

+
The Code + +public class Sqrt extends NumericFunction { + + private static final ValueEvalToNumericXlator NUM_XLATOR = + new ValueEvalToNumericXlator((short) + ( ValueEvalToNumericXlator.BOOL_IS_PARSED + | ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED + | ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED + | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED + | ValueEvalToNumericXlator.STRING_IS_PARSED + )); + + protected ValueEvalToNumericXlator getXlator() { + return NUM_XLATOR; + } + + public Eval evaluate(Eval[] operands, int srcRow, short srcCol) { + double d = 0; + ValueEval retval = null; + + switch (operands.length) { + default: + retval = ErrorEval.VALUE_INVALID; + break; + case 1: + ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol); + if (ve instanceof NumericValueEval) { + NumericValueEval ne = (NumericValueEval) ve; + d = ne.getNumberValue(); + } + else if (ve instanceof BlankEval) { + // do nothing + } + else { + retval = ErrorEval.NUM_ERROR; + } + } + + if (retval == null) { + d = Math.sqrt(d); + retval = (Double.isNaN(d)) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d); + } + return retval; + } + +} + +
+
Implementation Details +
    +
  • The first thing to realise is that classes already exist, even for functions that are not yet implemented. + Just that they extend from DefaultFunctionImpl whose behaviour is to return an ErrorEval.FUNCTION_NOT_IMPLEMENTED value.
  • +
  • In order to implement SQRT(..), we need to: a. Extend from the correct Abstract super class; b. implement the evaluate(..) method
  • +
  • Hence we extend SQRT(..) from the predefined class NumericFunction
  • +
  • Since SQRT(..) takes a single argument, we verify the length of the operands array else set the return value to ErrorEval.VALUE_INVALID
  • +
  • Next we normalize each operand to a limited set of ValueEval subtypes, specifically, we call the function + singleOperandEvaluate(..) to do conversions of different value eval types to one of: NumericValueEval, + BlankEval and ErrorEval. The conversion logic is configured by a ValueEvalToNumericXlator instance which + is returned by the Factory method: getXlator(..) The flags used to create the ValueEvalToNumericXlator + instance are briefly explained as follows: + BOOL_IS_PARSED means whether this function treats Boolean values as 1, + REF_BOOL_IS_PARSED means whether Boolean values in cell references are parsed or not. + So also, EVALUATED_REF_BOOL_IS_PARSED means if the operand was a RefEval that was assigned a + Boolean value as a result of evaluation of the formula that it contained. + eg. SQRT(TRUE) returns 1: This means BOOL_IS_PARSED should be set. + SQRT(A1) returns 1 when A1 has TRUE: This means REF_BOOL_IS_PARSED should be set. + SQRT(A1) returns 1 when A1 has a formula that evaluates to TRUE: This means EVALUATED_REF_BOOL_IS_PARSED should be set. + If the flag is not set for a particular case, that case is ignored (treated as if the cell is blank) _unless_ + there is a flag like: STRING_IS_INVALID_VALUE (which means that Strings should be treated as resulting in VALUE_INVALID ErrorEval) +
  • +
  • Next perform the appropriate Math function on the double value (if an error didnt occur already).
  • +
  • Finally before returning the NumberEval wrapping the double value that + you computed, do one final check to see if the double is a NaN, (or if it is "Infinite") + If it is return the appropriate ErrorEval instance. Note: The OpenOffice.org error codes + should NOT be preferred. Instead use the excel specific error codes like VALUE_INVALID, NUM_ERROR, DIV_ZERO etc. + (Thanks to Avik for bringing this issue up early!) The Oo.o ErrorCodes will be removed (if they havent already been :)
  • +
+
+
Modelling Excel Semantics +

Strings are ignored. Booleans are ignored!!!. Actually here's the info on Bools: + if you have formula: "=TRUE+1", it evaluates to 2. + So also, when you use TRUE like this: "=SUM(1,TRUE)", you see the result is: 2. + So TRUE means 1 when doing numeric calculations, right? + Wrong! + Because when you use TRUE in referenced cells with arithmetic functions, it evaluates to blank - meaning it is not evaluated - as if it was string or a blank cell. + eg. "=SUM(1,A1)" when A1 is TRUE evaluates to 1. + This behaviour changes depending on which function you are using. eg. SQRT(..) that was + described earlier treats a TRUE as 1 in all cases. This is why the configurable ValueEvalToNumericXlator + class had to be written. +

+

Note that when you are extending from an abstract function class like + NumericFunction (rather than implementing the interface o.a.p.hssf.record.formula.eval.Function directly) + you can use the utility methods in the super class - singleOperandEvaluate(..) - to quickly + reduce the different ValueEval subtypes to a small set of possible types. However when + implemenitng the Function interface directly, you will have to handle the possiblity + of all different ValueEval subtypes being sent in as 'operands'. (Hard to put this in + word, please have a look at the code for NumericFunction for an example of + how/why different ValueEvals need to be handled) +

+
+
+
Testing Framework +

Automated testing of the implemented Function is easy. + The source code for this is in the file: o.a.p.h.record.formula.GenericFormulaTestCase.java + This class has a reference to the test xls file (not /a/ test xls, /the/ test xls :) + which may need to be changed for your environment. Once you do that, in the test xls, + locate the entry for the function that you have implemented and enter different tests + in a cell in the FORMULA row. Then copy the "value of" the formula that you entered in the + cell just below it (this is easily done in excel as: + [copy the formula cell] > [go to cell below] > Edit > Paste Special > Values > "ok"). + You can enter multiple such formulas and paste their values in the cell below and the + test framework will automatically test if the formula evaluation matches the expected + value (Again, hard to put in words, so if you will, please take time to quickly look + at the code and the currently entered tests in the patch attachment "FormulaEvalTestData.xls" + file). +

+
+ +
\ No newline at end of file diff --git a/src/documentation/content/xdocs/ss/eval.xml b/src/documentation/content/xdocs/ss/eval.xml new file mode 100644 index 0000000000..8d63512173 --- /dev/null +++ b/src/documentation/content/xdocs/ss/eval.xml @@ -0,0 +1,248 @@ + + + + + +
+ Formula Evaluation + + +
+ +
Introduction +

The POI formula evaluation code enables you to calculate the result of + formulas in Excels sheets read-in, or created in POI. This document explains + how to use the API to evaluate your formulas. +

+ This code currently lives the scratchpad area of the POI SVN repository. + Ensure that you have the scratchpad jar or the scratchpad build area in your + classpath before experimenting with this code. You are advised + to make use of a recent SVN checkout, as new functions are + being supported fairly frequently. + +
+ + +
Status +

The code currently provides implementations for all the arithmatic operators. + It also provides implementations for approx. 100 built in + functions in Excel. The framework however makes is easy to add + implementation of new functions. See the Formula + evaluation development guide for details.

+

Note that user-defined functions are not supported, and is not likely to done + any time soon... at least, not till there is a VB implementation in Java! +

+
+
User API How-TO +

The following code demonstrates how to use the HSSFFormulaEvaluator + in the context of other POI excel reading code. +

+

There are several ways in which you can use the HSSFFormulaEvalutator API.

+ + +
Using HSSFFormulaEvaluator.<strong>evaluate</strong>(HSSFCell cell) +

This evaluates a given cell, and returns the new value, + without affecting the cell

+ +FileInputStream fis = new FileInputStream("c:/temp/test.xls"); +HSSFWorkbook wb = new HSSFWorkbook(fis); +HSSFSheet sheet = wb.getSheetAt(0); +HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb); + +// suppose your formula is in B3 +CellReference cellReference = new CellReference("B3"); +HSSFRow row = sheet.getRow(cellReference.getRow()); +HSSFCell cell = row.getCell(cellReference.getCol()); + +evaluator.setCurrentRow(row); +HSSFFormulaEvaluator.CellValue cellValue = evaluator.evaluate(cell); + +switch (cellValue.getCellType()) { + case HSSFCell.CELL_TYPE_BOOLEAN: + System.out.println(cellValue.getBooleanValue()); + break; + case HSSFCell.CELL_TYPE_NUMERIC: + System.out.println(cellValue.getNumberValue()); + break; + case HSSFCell.CELL_TYPE_STRING: + System.out.println(cellValue.getStringValue()); + break; + case HSSFCell.CELL_TYPE_BLANK: + break; + case HSSFCell.CELL_TYPE_ERROR: + break; + + // CELL_TYPE_FORMULA will never happen + case HSSFCell.CELL_TYPE_FORMULA: + break; +} + +

Thus using the retrieved value (of type + HSSFFormulaEvaluator.CellValue - a nested class) returned + by HSSFFormulaEvaluator is similar to using a HSSFCell object + containing the value of the formula evaluation. CellValue is + a simple value object and does not maintain reference + to the original cell. +

+
+ + +
Using HSSFFormulaEvaluator.<strong>evaluateFormulaCell</strong>(HSSFCell cell) +

evaluateFormulaCell(HSSFCell cell) + will check to see if the supplied cell is a formula cell. + If it isn't, then no changes will be made to it. If it is, + then the formula is evaluated. The value for the formula + is saved alongside it, to be displayed in excel. The + formula remains in the cell, just with a new value

+

The return of the function is the type of the + formula result, such as HSSFCell.CELL_TYPE_BOOLEAN

+ +FileInputStream fis = new FileInputStream("/somepath/test.xls"); +HSSFWorkbook wb = new HSSFWorkbook(fis); +HSSFSheet sheet = wb.getSheetAt(0); +HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb); + +// suppose your formula is in B3 +CellReference cellReference = new CellReference("B3"); +HSSFRow row = sheet.getRow(cellReference.getRow()); +HSSFCell cell = row.getCell(cellReference.getCol()); +evaluator.setCurrentRow(row); + +if (cell!=null) { + switch (evaluator.evaluateFormulaCell(cell)) { + case HSSFCell.CELL_TYPE_BOOLEAN: + System.out.println(cell.getBooleanCellValue()); + break; + case HSSFCell.CELL_TYPE_NUMERIC: + System.out.println(cell.getNumberCellValue()); + break; + case HSSFCell.CELL_TYPE_STRING: + System.out.println(cell.getStringCellValue()); + break; + case HSSFCell.CELL_TYPE_BLANK: + break; + case HSSFCell.CELL_TYPE_ERROR: + System.out.println(cell.getErrorCellValue()); + break; + + // CELL_TYPE_FORMULA will never occur + case HSSFCell.CELL_TYPE_FORMULA: + break; + } +} + +
+ + +
Using HSSFFormulaEvaluator.<strong>evaluateInCell</strong>(HSSFCell cell) +

evaluateInCell(HSSFCell cell) will check to + see if the supplied cell is a formula cell. If it isn't, + then no changes will be made to it. If it is, then the + formula is evaluated, and the new value saved into the cell, + in place of the old formula.

+ +FileInputStream fis = new FileInputStream("/somepath/test.xls"); +HSSFWorkbook wb = new HSSFWorkbook(fis); +HSSFSheet sheet = wb.getSheetAt(0); +HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb); + +// suppose your formula is in B3 +CellReference cellReference = new CellReference("B3"); +HSSFRow row = sheet.getRow(cellReference.getRow()); +HSSFCell cell = row.getCell(cellReference.getCol()); +evaluator.setCurrentRow(row); + +if (cell!=null) { + switch (evaluator.evaluateInCell(cell).getCellType()) { + case HSSFCell.CELL_TYPE_BOOLEAN: + System.out.println(cell.getBooleanCellValue()); + break; + case HSSFCell.CELL_TYPE_NUMERIC: + System.out.println(cell.getNumberCellValue()); + break; + case HSSFCell.CELL_TYPE_STRING: + System.out.println(cell.getStringCellValue()); + break; + case HSSFCell.CELL_TYPE_BLANK: + break; + case HSSFCell.CELL_TYPE_ERROR: + System.out.println(cell.getErrorCellValue()); + break; + + // CELL_TYPE_FORMULA will never occur + case HSSFCell.CELL_TYPE_FORMULA: + break; + } +} + +
+ + +
Re-calculating all formulas in a Workbook + +FileInputStream fis = new FileInputStream("/somepath/test.xls"); +HSSFWorkbook wb = new HSSFWorkbook(fis); +for(int sheetNum = 0; sheetNum < wb.getNumberOfSheets(); sheetNum++) { + HSSFSheet sheet = wb.getSheetAt(sheetNum); + HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb); + + for(Iterator rit = sheet.rowIterator(); rit.hasNext();) { + HSSFRow r = (HSSFRow)rit.next(); + evaluator.setCurrentRow(r); + + for(Iterator cit = r.cellIterator(); cit.hasNext();) { + HSSFCell c = (HSSFCell)cit.next(); + if(c.getCellType() == HSSFCell.CELL_TYPE_FORMULA) { + evaluator.evaluateFormulaCell(c); + } + } + } +} +wb.write(new FileOutputStream("/somepath/changed.xls")); + +
+
+ + +
Performance Notes +
    +
  • Generally you should have to create only one HSSFFormulaEvaluator + instance per sheet, but there really is no overhead in creating + multiple HSSFFormulaEvaluators per sheet other than that of the + HSSFFormulaEvaluator object creation. +
  • +
  • Also note that HSSFFormulaEvaluator maintains a reference to + the sheet and workbook, so ensure that the evaluator instance + is available for garbage collection when you are done with it + (in other words don't maintain long lived reference to + HSSFFormulaEvaluator if you don't really need to - unless + all references to the sheet and workbook are removed, these + don't get garbage collected and continue to occupy potentially + large amounts of memory). +
  • +
  • CellValue instances however do not maintain reference to the + HSSFCell or the sheet or workbook, so these can be long-lived + objects without any adverse effect on performance. +
  • +
+
+ +
diff --git a/src/documentation/content/xdocs/ss/formula.xml b/src/documentation/content/xdocs/ss/formula.xml new file mode 100644 index 0000000000..d8ced8fb20 --- /dev/null +++ b/src/documentation/content/xdocs/ss/formula.xml @@ -0,0 +1,107 @@ + + + + + +
+ Formula Support + + + +
+ +
Introduction +

+ This document describes the current state of formula support in POI. + The information in this document currently applies to the 2.0 version of POI. + Since this area is a work in progress, this document will be updated with new features as and + when they are added. +

+ +
+
The basics +

+ In org.apache.poi.hssf.usermodel.HSSFCell + setCellFormula("formulaString") is used to add a formula to sheet and + getCellFormula() is used to retrieve the string representation of a formula. +

+

+ We aim to support the complete excel grammer for formulas. Thus, the string that you pass in + to the setCellFormula call should be what you expect to type into excel. Also, note + that you should NOT add a "=" to the front of the string. +

+
+
Supported Features +
    +
  • Cell References
  • +
  • String, integer and floating point literals
  • +
  • Area references
  • +
  • Relative or absolute references
  • +
  • Arithmetic and logical operators
  • +
  • Sheet or Macro Functions (inlcuding logical functions)
  • +
  • Sheet References
  • +
  • Formual return values (number or string)
  • +
+
+
Partially supported +
    +
  • Formula tokens in Excel are stored in one of three possible classes : + Reference, Value and Array. Based on the location of a token, its class can change + in complicated and undocumented ways. While we have support for most cases, we + are not sure if we have covered all bases (since there is no documentation for this area.) + We would therefore like you to report any + occurence of #VALUE! in a cell upon opening a POI generated workbook in excel. (Check that + typing the formula into Excel directly gives a valid result.) +
  • + +
+
+
Not yet supported +
    +
  • Array formulas
  • +
  • Unary Operators
  • +
  • 3D References
  • +
  • Error Values (cells containing #REF's or #VALUE's)
  • +
  • Everything else :)
  • +
+
+ +
Internals +

+ Formulas in Excel are stored as sequences of tokens in Reverse Polish Notation order. The + open office XLS spec is the best + documentation you will find for the format. +

+ +

+ The tokens used by excel are modelled as individual *Ptg classes in the + org.apache.poi.hssf.record.formula package. +

+

+ The task of parsing a formula string into an array of RPN ordered tokens is done by the + org.apache.poi.hssf.record.formula.FormulaParser class. This class implements a hand + written recursive descent parser. +

+

Check out the javadocs for details. +

+
+ + +
diff --git a/src/documentation/content/xdocs/ss/hacking-hssf.xml b/src/documentation/content/xdocs/ss/hacking-hssf.xml new file mode 100644 index 0000000000..7247ad0ee7 --- /dev/null +++ b/src/documentation/content/xdocs/ss/hacking-hssf.xml @@ -0,0 +1,90 @@ + + + + + +
+ Hacking HSSF + + + + +
+ +
Where Can I Find Documentation on Feature X +

+ You might find the + 'Excel 97 Developer's Kit' (out of print, Microsoft Press, no + restrictive covenants, available on Amazon.com) helpful for + understanding the file format. +

+

+ Also useful is the open office XLS spec. We + are collaborating with the maintainer of the spec so if you think you can add something to their + document just send through your changes. +

+
+
Help, I Can't Find Feature X Documented Anywhere +
    +
  1. + Look at OpenOffice.org or Gnumeric sources if its implemented there. +
  2. +
  3. + Use org.apache.poi.hssf.dev.BiffViewer to view the structure of the + file. Experiment by adding one criteria entry at a time. See what it + does to the structure, infer behavior and structure from it. Using the + unix diff command (or get cygwin from www.cygwin.com for windows) you + can figure out a lot very quickly. Unimplemented records show up as + 'UNKNOWN' and prints a hex dump. +
  4. +
+
+
Low-level Record Generation +

+ Low level records can be time consuming to created. We created a record + generator to help generate some of the simpler tasks. +

+

+ We use XML + descriptors to generate the Java code (which sure beats the heck out of + the PERL scripts originally used ;-) for low level records. The + generator is kinda alpha-ish right now and could use some enhancement, + so you may find that to be about 1/2 of the work. Notice this is in + org.apache.poi.hssf.record.definitions. +

+
+
Important Notice +

One thing to note: If you are making a large code contribution we need to ensure + any participants in this process have never + signed a "Non Disclosure Agreement" with Microsoft, and have not + received any information covered by such an agreement. If they have + they'll not be able to participate in the POI project. For large contributions we + may ask you to sign an agreement.

+
+
What Can I Work On? +

Check our todo list or simply look for missing functionality. Start small + and work your way up.

+
+
What Else Should I Know? +

Make sure you read the contributing section + as it contains more generation information about contributing to POI in general.

+
+ +
diff --git a/src/documentation/content/xdocs/ss/how-to.xml b/src/documentation/content/xdocs/ss/how-to.xml new file mode 100644 index 0000000000..a4ac41209d --- /dev/null +++ b/src/documentation/content/xdocs/ss/how-to.xml @@ -0,0 +1,591 @@ + + + + + +
+ The New Halloween Document + + + + + + +
+ +
How to use the HSSF API + +
Capabilities +

This release of the how-to outlines functionality for the CVS HEAD. + Those looking for information on previous releases should + look in the documentation distributed with that release.

+

+ HSSF allows numeric, string, date or formuala cell values to be written to + or read from an XLS file. Also + in this release is row and column sizing, cell styling (bold, + italics, borders,etc), and support for both built-in and user + defined data formats. Also available is + an event-based API for reading XLS files. + It differs greatly from the read/write API + and is intended for intermediate developers who need a smaller + memory footprint. +

+
+
Different APIs +

There are a few different ways to access the HSSF API. These + have different characteristics, so you should read up on + all to select the best for you.

+
    +
  • User API
  • +
  • Event API
  • +
  • Event API with extensions to be Record Aware
  • +
  • Low Level API
  • +
+
+
+
General Use + +
User API +
Writing a new file + +

The high level API (package: org.apache.poi.hssf.usermodel) + is what most people should use. Usage is very simple. +

+

Workbooks are created by creating an instance of + org.apache.poi.hssf.usermodel.HSSFWorkbook. +

+

Sheets are created by calling createSheet() from an existing + instance of HSSFWorkbook, the created sheet is automatically added in + sequence to the workbook. Sheets do not in themselves have a sheet + name (the tab at the bottom); you set + the name associated with a sheet by calling + HSSFWorkbook.setSheetName(sheetindex,"SheetName",encoding). + The name may be in 8bit format (HSSFWorkbook.ENCODING_COMPRESSED_UNICODE) + or Unicode (HSSFWorkbook.ENCODING_UTF_16). Default encoding is 8bit per char. +

+

Rows are created by calling createRow(rowNumber) from an existing + instance of HSSFSheet. Only rows that have cell values should be + added to the sheet. To set the row's height, you just call + setRowHeight(height) on the row object. The height must be given in + twips, or 1/20th of a point. If you prefer, there is also a + setRowHeightInPoints method. +

+

Cells are created by calling createCell(column, type) from an + existing HSSFRow. Only cells that have values should be added to the + row. Cells should have their cell type set to either + HSSFCell.CELL_TYPE_NUMERIC or HSSFCell.CELL_TYPE_STRING depending on + whether they contain a numeric or textual value. Cells must also have + a value set. Set the value by calling setCellValue with either a + String or double as a parameter. Individual cells do not have a + width; you must call setColumnWidth(colindex, width) (use units of + 1/256th of a character) on the HSSFSheet object. (You can't do it on + an individual basis in the GUI either).

+

Cells are styled with HSSFCellStyle objects which in turn contain + a reference to an HSSFFont object. These are created via the + HSSFWorkbook object by calling createCellStyle() and createFont(). + Once you create the object you must set its parameters (colors, + borders, etc). To set a font for an HSSFCellStyle call + setFont(fontobj). +

+

Once you have generated your workbook, you can write it out by + calling write(outputStream) from your instance of Workbook, passing + it an OutputStream (for instance, a FileOutputStream or + ServletOutputStream). You must close the OutputStream yourself. HSSF + does not close it for you. +

+

Here is some example code (excerpted and adapted from + org.apache.poi.hssf.dev.HSSF test class):

+ +
+
Reading or modifying an existing file + +

Reading in a file is equally simple. To read in a file, create a +new instance of org.apache.poi.poifs.Filesystem, passing in an open InputStream, such as a FileInputStream +for your XLS, to the constructor. Construct a new instance of +org.apache.poi.hssf.usermodel.HSSFWorkbook passing the +Filesystem instance to the constructor. From there you have access to +all of the high level model objects through their assessor methods +(workbook.getSheet(sheetNum), sheet.getRow(rownum), etc). +

+

Modifying the file you have read in is simple. You retrieve the +object via an assessor method, remove it via a parent object's remove +method (sheet.removeRow(hssfrow)) and create objects just as you +would if creating a new xls. When you are done modifying cells just +call workbook.write(outputstream) just as you did above.

+

An example of this can be seen in +org.apache.poi.hssf.dev.HSSF.

+
+
+ + +
Event API + +

The event API is newer than the User API. It is intended for intermediate + developers who are willing to learn a little bit of the low level API + structures. Its relatively simple to use, but requires a basic + understanding of the parts of an Excel file (or willingness to + learn). The advantage provided is that you can read an XLS with a + relatively small memory footprint. +

+

One important thing to note with the basic Event API is that it + triggers events only for things actually stored within the file. + With the XLS file format, it is quite common for things that + have yet to be edited to simply not exist in the file. This means + there may well be apparent "gaps" in the record stream, which + you either need to work around, or use the + Record Aware extension + to the Event API.

+

To use this API you construct an instance of + org.apache.poi.hssf.eventmodel.HSSFRequest. Register a class you + create that supports the + org.apache.poi.hssf.eventmodel.HSSFListener interface using the + HSSFRequest.addListener(yourlistener, recordsid). The recordsid + should be a static reference number (such as BOFRecord.sid) contained + in the classes in org.apache.poi.hssf.record. The trick is you + have to know what these records are. Alternatively you can call + HSSFRequest.addListenerForAllRecords(mylistener). In order to learn + about these records you can either read all of the javadoc in the + org.apache.poi.hssf.record package or you can just hack up a + copy of org.apache.poi.hssf.dev.EFHSSF and adapt it to your + needs. TODO: better documentation on records.

+

Once you've registered your listeners in the HSSFRequest object + you can construct an instance of + org.apache.poi.poifs.filesystem.FileSystem (see POIFS howto) and + pass it your XLS file inputstream. You can either pass this, along + with the request you constructed, to an instance of HSSFEventFactory + via the HSSFEventFactory.processWorkbookEvents(request, Filesystem) + method, or you can get an instance of DocumentInputStream from + Filesystem.createDocumentInputStream("Workbook") and pass + it to HSSFEventFactory.processEvents(request, inputStream). Once you + make this call, the listeners that you constructed receive calls to + their processRecord(Record) methods with each Record they are + registered to listen for until the file has been completely read. +

+

A code excerpt from org.apache.poi.hssf.dev.EFHSSF (which is + in CVS or the source distribution) is reprinted below with excessive + comments:

+ +
+ + +
Record Aware Event API +

+This is an experimental extension to the normal +Event API. With this, your listener +will be called with extra, dummy records. These dummy records should +alert you to records which aren't present in the file (eg cells that have +yet to be edited), and allow you to handle these. +

+

+There are three dummy records that your HSSFListener will be called with: +

+
    +
  • org.apache.poi.hssf.eventusermodel.dummyrecord.MissingRowDummyRecord +
    + This is called during the row record phase (which typically occurs before + the cell records), and indicates that the row record for the given + row is not present in the file.
  • +
  • org.apache.poi.hssf.eventusermodel.dummyrecord.MissingCellDummyRecord +
    + This is called during the cell record phase. It is called when a cell + record is encountered which leaves a gap between it an the previous one. + You can get multiple of these, before the real cell record.
  • +
  • org.apache.poi.hssf.eventusermodel.dummyrecord.LastCellOfRowDummyRecord +
    + This is called after the last cell of a given row. It indicates that there + are no more cells for the row, and also tells you how many cells you have + had. For a row with no cells, this will be the only record you get.
  • +
+

+To use the Record Aware Event API, you should create an +org.apache.poi.hssf.eventusermodel.MissingRecordAwareHSSFListener, and pass +it your HSSFListener. Then, register the MissingRecordAwareHSSFListener +to the event model, and start that as normal. +

+

+One example use for this API is to write a CSV outputter, which always +outputs a minimum number of columns, even where the file doesn't contain +some of the rows or cells. It can be found at +/src/scratchpad/examples/src/org/apache/poi/hssf/eventusermodel/examples/XLS2CSVmra.java, +and may be called on the command line, or from within your own code. +The latest version is always available from +subversion. +

+

+This code is currently in the scratchpad section, so you will either + need to include the scratchpad jar on your classpath, or build from a + subversion checkout. +

+
+ + +
Low Level APIs + +

The low level API is not much to look at. It consists of lots of +"Records" in the org.apache.poi.hssf.record.* package, +and set of helper classes in org.apache.poi.hssf.model.*. The +record classes are consistent with the low level binary structures +inside a BIFF8 file (which is embedded in a POIFS file system). You +probably need the book: "Microsoft Excel 97 Developer's Kit" +from Microsoft Press in order to understand how these fit together +(out of print but easily obtainable from Amazon's used books). In +order to gain a good understanding of how to use the low level APIs +should view the source in org.apache.poi.hssf.usermodel.* and +the classes in org.apache.poi.hssf.model.*. You should read the +documentation for the POIFS libraries as well.

+
+
Generating XLS from XML +

If you wish to generate an XLS file from some XML, it is possible to +write your own XML processing code, then use the User API to write out +the document.

+

The other option is to use Cocoon. +In Cocoon, there is the HSSF Serializer, +which takes in XML (in the gnumeric format), and outputs an XLS file for you.

+
+
HSSF Class/Test Application + +

The HSSF application is nothing more than a test for the high +level API (and indirectly the low level support). The main body of +its code is repeated above. To run it: +

+
    +
  • download the poi-alpha build and untar it (tar xvzf + tarball.tar.gz) +
  • +
  • set up your classpath as follows: + export HSSFDIR={wherever you put HSSF's jar files} +export LOG4JDIR={wherever you put LOG4J's jar files} +export CLASSPATH=$CLASSPATH:$HSSFDIR/hssf.jar:$HSSFDIR/poi-poifs.jar:$HSSFDIR/poi-util.jar:$LOG4JDIR/jog4j.jar +
  • type: + java org.apache.poi.hssf.dev.HSSF ~/myxls.xls write
  • +
+

+

This should generate a test sheet in your home directory called "myxls.xls".

+
    +
  • Type: + java org.apache.poi.hssf.dev.HSSF ~/input.xls output.xls +
    +
    +This is the read/write/modify test. It reads in the spreadsheet, modifies a cell, and writes it back out. +Failing this test is not necessarily a bad thing. If HSSF tries to modify a non-existant sheet then this will +most likely fail. No big deal.
  • +
+
+
Logging facility +

POI can dynamically select its logging implementation. POI tries to + create a logger using the System property named "org.apache.poi.util.POILogger". + Out of the box this can be set to one of three values: +

+
    +
  • org.apache.poi.util.CommonsLogger
  • +
  • org.apache.poi.util.NullLogger
  • +
  • org.apache.poi.util.SystemOutLogger
  • +
+

+ If the property is not defined or points to an invalid classthen the NullLogger is used. +

+

+ Refer to the commons logging package level javadoc for more information concerning how to + configure commons logging. +

+
+
HSSF Developer's Tools + +

HSSF has a number of tools useful for developers to debug/develop +stuff using HSSF (and more generally XLS files). We've already +discussed the app for testing HSSF read/write/modify capabilities; +now we'll talk a bit about BiffViewer. Early on in the development of +HSSF, it was decided that knowing what was in a record, what was +wrong with it, etc. was virtually impossible with the available +tools. So we developed BiffViewer. You can find it at +org.apache.poi.hssf.dev.BiffViewer. It performs two basic +functions and a derivative. +

+

The first is "biffview". To do this you run it (assumes +you have everything setup in your classpath and that you know what +you're doing enough to be thinking about this) with an xls file as a +parameter. It will give you a listing of all understood records with +their data and a list of not-yet-understood records with no data +(because it doesn't know how to interpret them). This listing is +useful for several things. First, you can look at the values and SEE +what is wrong in quasi-English. Second, you can send the output to a +file and compare it. +

+

The second function is "big freakin dump", just pass a +file and a second argument matching "bfd" exactly. This +will just make a big hexdump of the file. +

+

Lastly, there is "mixed" mode which does the same as +regular biffview, only it includes hex dumps of certain records +intertwined. To use that just pass a file with a second argument +matching "on" exactly.

+

In the next release cycle we'll also have something called a +FormulaViewer. The class is already there, but its not very useful +yet. When it does something, we'll document it.

+ +
+
What's Next? + +

Further effort on HSSF is going to focus on the following major areas:

+
    +
  • Performance: POI currently uses a lot of memory for large sheets.
  • +
  • Charts: This is a hard problem, with very little documentation.
  • +
+

So jump in!

+ +
+ +
+ +
diff --git a/src/documentation/content/xdocs/ss/index.xml b/src/documentation/content/xdocs/ss/index.xml new file mode 100644 index 0000000000..4560d82d83 --- /dev/null +++ b/src/documentation/content/xdocs/ss/index.xml @@ -0,0 +1,64 @@ + + + + + +
+ POI-HSSF and POI-XSSF - Java API To Access Microsoft Excel Format Files + Overview + + + + +
+ + +
+ Overview + +

HSSF is the POI Project's pure Java implementation of the + Excel '97(-2007) file format. XSSF is the POI Project's pure + Java implementation of the Excel 2007 OOXML (.xlsx) file + format.

+

HSSF and XSSF provides ways to read spreadsheets create, + modify, read and write XLS spreadsheets. They provide: +

+
    +
  • low level structures for those with special needs
  • +
  • an eventmodel api for efficient read-only access
  • +
  • a full usermodel api for creating, reading and modifying XLS files
  • +
+

+ An alternate way of generating a spreadsheet is via the Cocoon serializer (yet you'll still be using HSSF indirectly). + With Cocoon you can serialize any XML datasource (which might be a ESQL page outputting in SQL for instance) by simply + applying the stylesheet and designating the serializer. +

+

+ If you're merely reading spreadsheet data, then use the eventmodel api + in the org.apache.poi.hssf.eventusermodel package. +

+

+ If you're modifying spreadsheet data then use the usermodel api. You + can also generate spreadsheets this way. +

+ +
+ +
diff --git a/src/documentation/content/xdocs/ss/limitations.xml b/src/documentation/content/xdocs/ss/limitations.xml new file mode 100644 index 0000000000..8dad71e172 --- /dev/null +++ b/src/documentation/content/xdocs/ss/limitations.xml @@ -0,0 +1,58 @@ + + + + + +
+ Limitations + + + +
+ +
Version 2.5 limitations +

+ The intent of this document is to outline some of the known limitations of the + POI HSSF API's. It is not intended to be complete list of every bug or missing + feature of HSSF, rather it's purpose is to provide a broad feel for some of the + functionality that is missing or broken. +

+
    +
  • + Charts

    + You can not currently create charts. You can + however create a chart in Excel, modify the chart data values using HSSF and write + a new spreadsheet out. This is possible because POI attempts to keep existing records + intact as far as possible.

    +
  • +
  • + Macros

    + Macros can not be created. However, reading and re-writing files containing macros will + safely preserve the macros.

    +
  • +
  • + Pivot Tables

    + Generating pivot tables is not supported. It has been reported that files containing pivot + tables can be read and re-written safely. +
  • +
+
+ +
diff --git a/src/documentation/content/xdocs/ss/quick-guide.xml b/src/documentation/content/xdocs/ss/quick-guide.xml new file mode 100644 index 0000000000..66da604892 --- /dev/null +++ b/src/documentation/content/xdocs/ss/quick-guide.xml @@ -0,0 +1,1398 @@ + + + + + +
+ Busy Developers' Guide to HSSF Features + + + + +
+ +
Busy Developers' Guide to Features +

+ Want to use HSSF read and write spreadsheets in a hurry? This guide is for you. If you're after + more in-depth coverage of the HSSF user-API please consult the HOWTO + guide as it contains actual descriptions of how to use this stuff. +

+
Index of Features +
    +
  • How to create a new workbook
  • +
  • How to create a sheet
  • +
  • How to create cells
  • +
  • How to create date cells
  • +
  • Working with different types of cells
  • +
  • Iterate over rows and cells
  • +
  • Text Extraction
  • +
  • Aligning cells
  • +
  • Working with borders
  • +
  • Fills and color
  • +
  • Merging cells
  • +
  • Working with fonts
  • +
  • Custom colors
  • +
  • Reading and writing
  • +
  • Use newlines in cells.
  • +
  • Create user defined data formats
  • +
  • Fit Sheet to One Page
  • +
  • Set print area for a sheet
  • +
  • Set page numbers on the footer of a sheet
  • +
  • Shift rows
  • +
  • Set a sheet as selected
  • +
  • Set the zoom magnification for a sheet
  • +
  • Create split and freeze panes
  • +
  • Repeating rows and columns
  • +
  • Headers and Footers
  • +
  • Drawing Shapes
  • +
  • Styling Shapes
  • +
  • Shapes and Graphics2d
  • +
  • Outlining
  • +
  • Images
  • +
  • Named Ranges and Named Cells
  • +
  • How to set cell comments
  • +
  • How to adjust column width to fit the contents
  • +
  • Hyperlinks
  • +
+
+
Features + +
New Workbook + + HSSFWorkbook wb = new HSSFWorkbook(); + FileOutputStream fileOut = new FileOutputStream("workbook.xls"); + wb.write(fileOut); + fileOut.close(); + +
+ +
New Sheet + + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet1 = wb.createSheet("new sheet"); + HSSFSheet sheet2 = wb.createSheet("second sheet"); + FileOutputStream fileOut = new FileOutputStream("workbook.xls"); + wb.write(fileOut); + fileOut.close(); + +
+ +
Creating Cells + + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet("new sheet"); + + // Create a row and put some cells in it. Rows are 0 based. + HSSFRow row = sheet.createRow((short)0); + // Create a cell and put a value in it. + HSSFCell cell = row.createCell((short)0); + cell.setCellValue(1); + + // Or do it on one line. + row.createCell((short)1).setCellValue(1.2); + row.createCell((short)2).setCellValue("This is a string"); + row.createCell((short)3).setCellValue(true); + + // Write the output to a file + FileOutputStream fileOut = new FileOutputStream("workbook.xls"); + wb.write(fileOut); + fileOut.close(); + +
+ +
Creating Date Cells + + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet("new sheet"); + + // Create a row and put some cells in it. Rows are 0 based. + HSSFRow row = sheet.createRow((short)0); + + // Create a cell and put a date value in it. The first cell is not styled + // as a date. + HSSFCell cell = row.createCell((short)0); + cell.setCellValue(new Date()); + + // we style the second cell as a date (and time). It is important to + // create a new cell style from the workbook otherwise you can end up + // modifying the built in style and effecting not only this cell but other cells. + HSSFCellStyle cellStyle = wb.createCellStyle(); + cellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("m/d/yy h:mm")); + cell = row.createCell((short)1); + cell.setCellValue(new Date()); + cell.setCellStyle(cellStyle); + + // Write the output to a file + FileOutputStream fileOut = new FileOutputStream("workbook.xls"); + wb.write(fileOut); + fileOut.close(); + +
+ +
Working with different types of cells + + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet("new sheet"); + HSSFRow row = sheet.createRow((short)2); + row.createCell((short) 0).setCellValue(1.1); + row.createCell((short) 1).setCellValue(new Date()); + row.createCell((short) 2).setCellValue("a string"); + row.createCell((short) 3).setCellValue(true); + row.createCell((short) 4).setCellType(HSSFCell.CELL_TYPE_ERROR); + + // Write the output to a file + FileOutputStream fileOut = new FileOutputStream("workbook.xls"); + wb.write(fileOut); + fileOut.close(); + +
+ +
Demonstrates various alignment options + + public static void main(String[] args) + throws IOException + { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet("new sheet"); + HSSFRow row = sheet.createRow((short) 2); + createCell(wb, row, (short) 0, HSSFCellStyle.ALIGN_CENTER); + createCell(wb, row, (short) 1, HSSFCellStyle.ALIGN_CENTER_SELECTION); + createCell(wb, row, (short) 2, HSSFCellStyle.ALIGN_FILL); + createCell(wb, row, (short) 3, HSSFCellStyle.ALIGN_GENERAL); + createCell(wb, row, (short) 4, HSSFCellStyle.ALIGN_JUSTIFY); + createCell(wb, row, (short) 5, HSSFCellStyle.ALIGN_LEFT); + createCell(wb, row, (short) 6, HSSFCellStyle.ALIGN_RIGHT); + + // Write the output to a file + FileOutputStream fileOut = new FileOutputStream("workbook.xls"); + wb.write(fileOut); + fileOut.close(); + + } + + /** + * Creates a cell and aligns it a certain way. + * + * @param wb the workbook + * @param row the row to create the cell in + * @param column the column number to create the cell in + * @param align the alignment for the cell. + */ + private static void createCell(HSSFWorkbook wb, HSSFRow row, short column, short align) + { + HSSFCell cell = row.createCell(column); + cell.setCellValue("Align It"); + HSSFCellStyle cellStyle = wb.createCellStyle(); + cellStyle.setAlignment(align); + cell.setCellStyle(cellStyle); + } + +
+ +
Working with borders + + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet("new sheet"); + + // Create a row and put some cells in it. Rows are 0 based. + HSSFRow row = sheet.createRow((short) 1); + + // Create a cell and put a value in it. + HSSFCell cell = row.createCell((short) 1); + cell.setCellValue(4); + + // Style the cell with borders all around. + HSSFCellStyle style = wb.createCellStyle(); + style.setBorderBottom(HSSFCellStyle.BORDER_THIN); + style.setBottomBorderColor(HSSFColor.BLACK.index); + style.setBorderLeft(HSSFCellStyle.BORDER_THIN); + style.setLeftBorderColor(HSSFColor.GREEN.index); + style.setBorderRight(HSSFCellStyle.BORDER_THIN); + style.setRightBorderColor(HSSFColor.BLUE.index); + style.setBorderTop(HSSFCellStyle.BORDER_MEDIUM_DASHED); + style.setTopBorderColor(HSSFColor.BLACK.index); + cell.setCellStyle(style); + + // Write the output to a file + FileOutputStream fileOut = new FileOutputStream("workbook.xls"); + wb.write(fileOut); + fileOut.close(); + +
+ +
Iterate over rows and cells +

Sometimes, you'd like to just iterate over all the rows in + a sheet, or all the cells in a row. This is possible with + a simple for loop.

+

Luckily, this is very easy. HSSFRow defines a + CellIterator inner class to handle iterating over + the cells (get one with a call to row.cellIterator()), + and HSSFSheet provides a rowIterator() method to + give an iterator over all the rows.

+

(Unfortunately, due to the broken and + backwards-incompatible way that Java 5 foreach loops were + implemented, it isn't possible to use them on a codebase + that supports Java 1.4, as POI does)

+ + HSSFSheet sheet = wb.getSheetAt(0); + for (Iterator rit = sheet.rowIterator(); rit.hasNext(); ) { + HSSFRow row = (HSSFRow)rit.next(); + for (Iterator cit = row.cellIterator(); cit.hasNext(); ) { + HSSFCell cell = (HSSFCell)cit.next(); + // Do something here + } + } + + + HSSFSheet sheet = wb.getSheetAt(0); + for (Iterator<HSSFRow> rit = (Iterator<HSSFRow>)sheet.rowIterator(); rit.hasNext(); ) { + HSSFRow row = rit.next(); + for (Iterator<HSSFCell> cit = (Iterator<HSSFCell>)row.cellIterator(); cit.hasNext(); ) { + HSSFCell cell = cit.next(); + // Do something here + } + } + +
+
Iterate over rows and cells using Java 1.5 foreach loops - OOXML Branch Only +

Sometimes, you'd like to just iterate over all the rows in + a sheet, or all the cells in a row. If you are using Java + 5 or later, then this is especially handy, as it'll allow the + new foreach loop support to work.

+

Luckily, this is very easy. Both HSSFSheet and HSSFRow + implement java.lang.Iterable to allow foreach + loops. For HSSFRow this allows access to the + CellIterator inner class to handle iterating over + the cells, and for HSSFSheet gives the + rowIterator() to iterator over all the rows.

+ + HSSFSheet sheet = wb.getSheetAt(0); + for (HSSFRow row : sheet.rowIterator()) { + for (HSSFCell cell : row.cellIterator()) { + // Do something here + } + } + + This only works on the OOXML branch of POI +
+ +
Text Extraction +

For most text extraction requirements, the standard + ExcelExtractor class should provide all you need.

+ + InputStream inp = new FileInputStream("workbook.xls"); + HSSFWorkbook wb = new HSSFWorkbook(new POIFSFileSystem(inp)); + ExcelExtractor extractor = new ExcelExtractor(wb); + + extractor.setFormulasNotResults(true); + extractor.setIncludeSheetNames(false); + String text = extractor.getText(); + +

For very fancy text extraction, XLS to CSV etc, + take a look at + /src/scratchpad/examples/src/org/apache/poi/hssf/eventusermodel/examples/XLS2CSVmra.java +

+
+ +
Fills and colors + + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet("new sheet"); + + // Create a row and put some cells in it. Rows are 0 based. + HSSFRow row = sheet.createRow((short) 1); + + // Aqua background + HSSFCellStyle style = wb.createCellStyle(); + style.setFillBackgroundColor(HSSFColor.AQUA.index); + style.setFillPattern(HSSFCellStyle.BIG_SPOTS); + HSSFCell cell = row.createCell((short) 1); + cell.setCellValue("X"); + cell.setCellStyle(style); + + // Orange "foreground", foreground being the fill foreground not the font color. + style = wb.createCellStyle(); + style.setFillForegroundColor(HSSFColor.ORANGE.index); + style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); + cell = row.createCell((short) 2); + cell.setCellValue("X"); + cell.setCellStyle(style); + + // Write the output to a file + FileOutputStream fileOut = new FileOutputStream("workbook.xls"); + wb.write(fileOut); + fileOut.close(); + +
+ +
Merging cells + + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet("new sheet"); + + HSSFRow row = sheet.createRow((short) 1); + HSSFCell cell = row.createCell((short) 1); + cell.setCellValue("This is a test of merging"); + + sheet.addMergedRegion(new Region(1,(short)1,1,(short)2)); + + // Write the output to a file + FileOutputStream fileOut = new FileOutputStream("workbook.xls"); + wb.write(fileOut); + fileOut.close(); + +
+ +
Working with fonts + + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet("new sheet"); + + // Create a row and put some cells in it. Rows are 0 based. + HSSFRow row = sheet.createRow((short) 1); + + // Create a new font and alter it. + HSSFFont font = wb.createFont(); + font.setFontHeightInPoints((short)24); + font.setFontName("Courier New"); + font.setItalic(true); + font.setStrikeout(true); + + // Fonts are set into a style so create a new one to use. + HSSFCellStyle style = wb.createCellStyle(); + style.setFont(font); + + // Create a cell and put a value in it. + HSSFCell cell = row.createCell((short) 1); + cell.setCellValue("This is a test of fonts"); + cell.setCellStyle(style); + + // Write the output to a file + FileOutputStream fileOut = new FileOutputStream("workbook.xls"); + wb.write(fileOut); + fileOut.close(); + +

+ Note, the maximum number of unique fonts in a workbook is limited to 32767 ( + the maximum positive short). You should re-use fonts in your apllications instead of + creating a font for each cell. +Examples: +

+

Wrong:

+ + for (int i = 0; i < 10000; i++) { + HSSFRow row = sheet.createRow(i); + HSSFCell cell = row.createCell((short) 0); + + HSSFCellStyle style = workbook.createCellStyle(); + HSSFFont font = workbook.createFont(); + font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); + style.setFont(font); + cell.setCellStyle(style); + } + +

Correct:

+ + + HSSFCellStyle style = workbook.createCellStyle(); + HSSFFont font = workbook.createFont(); + font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); + style.setFont(font); + for (int i = 0; i < 10000; i++) { + HSSFRow row = sheet.createRow(i); + HSSFCell cell = row.createCell((short) 0); + cell.setCellStyle(style); + } + + +
+ +
Custom colors + + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(); + HSSFRow row = sheet.createRow((short) 0); + HSSFCell cell = row.createCell((short) 0); + cell.setCellValue("Default Palette"); + + //apply some colors from the standard palette, + // as in the previous examples. + //we'll use red text on a lime background + + HSSFCellStyle style = wb.createCellStyle(); + style.setFillForegroundColor(HSSFColor.LIME.index); + style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); + + HSSFFont font = wb.createFont(); + font.setColor(HSSFColor.RED.index); + style.setFont(font); + + cell.setCellStyle(style); + + //save with the default palette + FileOutputStream out = new FileOutputStream("default_palette.xls"); + wb.write(out); + out.close(); + + //now, let's replace RED and LIME in the palette + // with a more attractive combination + // (lovingly borrowed from freebsd.org) + + cell.setCellValue("Modified Palette"); + + //creating a custom palette for the workbook + HSSFPalette palette = wb.getCustomPalette(); + + //replacing the standard red with freebsd.org red + palette.setColorAtIndex(HSSFColor.RED.index, + (byte) 153, //RGB red (0-255) + (byte) 0, //RGB green + (byte) 0 //RGB blue + ); + //replacing lime with freebsd.org gold + palette.setColorAtIndex(HSSFColor.LIME.index, (byte) 255, (byte) 204, (byte) 102); + + //save with the modified palette + // note that wherever we have previously used RED or LIME, the + // new colors magically appear + out = new FileOutputStream("modified_palette.xls"); + wb.write(out); + out.close(); + +
+ +
Reading and Rewriting Workbooks + + POIFSFileSystem fs = + new POIFSFileSystem(new FileInputStream("workbook.xls")); + HSSFWorkbook wb = new HSSFWorkbook(fs); + HSSFSheet sheet = wb.getSheetAt(0); + HSSFRow row = sheet.getRow(2); + HSSFCell cell = row.getCell((short)3); + if (cell == null) + cell = row.createCell((short)3); + cell.setCellType(HSSFCell.CELL_TYPE_STRING); + cell.setCellValue("a test"); + + // Write the output to a file + FileOutputStream fileOut = new FileOutputStream("workbook.xls"); + wb.write(fileOut); + fileOut.close(); + +
+ +
Using newlines in cells + + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet s = wb.createSheet(); + HSSFRow r = null; + HSSFCell c = null; + HSSFCellStyle cs = wb.createCellStyle(); + HSSFFont f = wb.createFont(); + HSSFFont f2 = wb.createFont(); + + cs = wb.createCellStyle(); + + cs.setFont( f2 ); + //Word Wrap MUST be turned on + cs.setWrapText( true ); + + r = s.createRow( (short) 2 ); + r.setHeight( (short) 0x349 ); + c = r.createCell( (short) 2 ); + c.setCellType( HSSFCell.CELL_TYPE_STRING ); + c.setCellValue( "Use \n with word wrap on to create a new line" ); + c.setCellStyle( cs ); + s.setColumnWidth( (short) 2, (short) ( ( 50 * 8 ) / ( (double) 1 / 20 ) ) ); + + FileOutputStream fileOut = new FileOutputStream( "workbook.xls" ); + wb.write( fileOut ); + fileOut.close(); +
+ +
Data Formats + + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet("format sheet"); + HSSFCellStyle style; + HSSFDataFormat format = wb.createDataFormat(); + HSSFRow row; + HSSFCell cell; + short rowNum = 0; + short colNum = 0; + + row = sheet.createRow(rowNum++); + cell = row.createCell(colNum); + cell.setCellValue(11111.25); + style = wb.createCellStyle(); + style.setDataFormat(format.getFormat("0.0")); + cell.setCellStyle(style); + + row = sheet.createRow(rowNum++); + cell = row.createCell(colNum); + cell.setCellValue(11111.25); + style = wb.createCellStyle(); + style.setDataFormat(format.getFormat("#,##0.0000")); + cell.setCellStyle(style); + + FileOutputStream fileOut = new FileOutputStream("workbook.xls"); + wb.write(fileOut); + fileOut.close(); + +
+ +
Fit Sheet to One Page + + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet("format sheet"); + HSSFPrintSetup ps = sheet.getPrintSetup(); + + sheet.setAutobreaks(true); + + ps.setFitHeight((short)1); + ps.setFitWidth((short)1); + + + // Create various cells and rows for spreadsheet. + + FileOutputStream fileOut = new FileOutputStream("workbook.xls"); + wb.write(fileOut); + fileOut.close(); + +
+ +
Set Print Area + + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet("Sheet1"); + wb.setPrintArea(0, "$A$1:$C$2"); + //sets the print area for the first sheet + //Alternatively: + //wb.setPrintArea(0, 0, 1, 0, 0) is equivalent to using the name reference (See the JavaDocs for more details) + + // Create various cells and rows for spreadsheet. + + FileOutputStream fileOut = new FileOutputStream("workbook.xls"); + wb.write(fileOut); + fileOut.close(); + + + +
+ + +
Set Page Numbers on Footer + + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet("format sheet"); + HSSFFooter footer = sheet.getFooter() + + footer.setRight( "Page " + HSSFFooter.page() + " of " + HSSFFooter.numPages() ); + + + + // Create various cells and rows for spreadsheet. + + FileOutputStream fileOut = new FileOutputStream("workbook.xls"); + wb.write(fileOut); + fileOut.close(); + +
+ + +
Using the Convenience Functions +

+ The convenience functions live in contrib and provide + utility features such as setting borders around merged + regions and changing style attributes without explicitly + creating new styles. +

+ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet1 = wb.createSheet( "new sheet" ); + + // Create a merged region + HSSFRow row = sheet1.createRow( (short) 1 ); + HSSFRow row2 = sheet1.createRow( (short) 2 ); + HSSFCell cell = row.createCell( (short) 1 ); + cell.setCellValue( "This is a test of merging" ); + Region region = new Region( 1, (short) 1, 4, (short) 4 ); + sheet1.addMergedRegion( region ); + + // Set the border and border colors. + final short borderMediumDashed = HSSFCellStyle.BORDER_MEDIUM_DASHED; + HSSFRegionUtil.setBorderBottom( borderMediumDashed, + region, sheet1, wb ); + HSSFRegionUtil.setBorderTop( borderMediumDashed, + region, sheet1, wb ); + HSSFRegionUtil.setBorderLeft( borderMediumDashed, + region, sheet1, wb ); + HSSFRegionUtil.setBorderRight( borderMediumDashed, + region, sheet1, wb ); + HSSFRegionUtil.setBottomBorderColor(HSSFColor.AQUA.index, region, sheet1, wb); + HSSFRegionUtil.setTopBorderColor(HSSFColor.AQUA.index, region, sheet1, wb); + HSSFRegionUtil.setLeftBorderColor(HSSFColor.AQUA.index, region, sheet1, wb); + HSSFRegionUtil.setRightBorderColor(HSSFColor.AQUA.index, region, sheet1, wb); + + // Shows some usages of HSSFCellUtil + HSSFCellStyle style = wb.createCellStyle(); + style.setIndention((short)4); + HSSFCellUtil.createCell(row, 8, "This is the value of the cell", style); + HSSFCell cell2 = HSSFCellUtil.createCell( row2, 8, "This is the value of the cell"); + HSSFCellUtil.setAlignment(cell2, wb, HSSFCellStyle.ALIGN_CENTER); + + // Write out the workbook + FileOutputStream fileOut = new FileOutputStream( "workbook.xls" ); + wb.write( fileOut ); + fileOut.close(); + +
+ + +
Shift rows up or down on a sheet + + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet("row sheet"); + + // Create various cells and rows for spreadsheet. + + // Shift rows 6 - 11 on the spreadsheet to the top (rows 0 - 5) + sheet.shiftRows(5, 10, -5); + + FileOutputStream fileOut = new FileOutputStream("workbook.xls"); + wb.write(fileOut); + fileOut.close(); + +
+ + +
Set a sheet as selected + + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet("row sheet"); + sheet.setSelected(true); + + // Create various cells and rows for spreadsheet. + + FileOutputStream fileOut = new FileOutputStream("workbook.xls"); + wb.write(fileOut); + fileOut.close(); + +
+ + +
Set the zoom magnification +

+ The zoom is expressed as a fraction. For example to + express a zoom of 75% use 3 for the numerator and + 4 for the denominator. +

+ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet1 = wb.createSheet("new sheet"); + sheet1.setZoom(3,4); // 75 percent magnification + FileOutputStream fileOut = new FileOutputStream("workbook.xls"); + wb.write(fileOut); + fileOut.close(); + +
+ + +
Splits and freeze panes +

+ There are two types of panes you can create; freeze panes and split panes. +

+

+ A freeze pane is split by columns and rows. You create + a freeze pane using the following mechanism: +

+

+ sheet1.createFreezePane( 3, 2, 3, 2 ); +

+

+ The first two parameters are the columns and rows you + wish to split by. The second two parameters indicate + the cells that are visible in the bottom right quadrant. +

+

+ + Split pains appear differently. The split area is + divided into four separate work area's. The split + occurs at the pixel level and the user is able to + adjust the split by dragging it to a new position. +

+

+ + Split panes are created with the following call: +

+

+ sheet2.createSplitPane( 2000, 2000, 0, 0, HSSFSheet.PANE_LOWER_LEFT ); +

+

+ + The first parameter is the x position of the split. + This is in 1/20th of a point. A point in this case + seems to equate to a pixel. The second parameter is + the y position of the split. Again in 1/20th of a point. +

+

+ The last parameter indicates which pane currently has + the focus. This will be one of HSSFSheet.PANE_LOWER_LEFT, + PANE_LOWER_RIGHT, PANE_UPPER_RIGHT or PANE_UPPER_LEFT. +

+ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet1 = wb.createSheet("new sheet"); + HSSFSheet sheet2 = wb.createSheet("second sheet"); + HSSFSheet sheet3 = wb.createSheet("third sheet"); + HSSFSheet sheet4 = wb.createSheet("fourth sheet"); + + // Freeze just one row + sheet1.createFreezePane( 0, 1, 0, 1 ); + // Freeze just one column + sheet2.createFreezePane( 1, 0, 1, 0 ); + // Freeze the columns and rows (forget about scrolling position of the lower right quadrant). + sheet3.createFreezePane( 2, 2 ); + // Create a split with the lower left side being the active quadrant + sheet4.createSplitPane( 2000, 2000, 0, 0, HSSFSheet.PANE_LOWER_LEFT ); + + FileOutputStream fileOut = new FileOutputStream("workbook.xls"); + wb.write(fileOut); + fileOut.close(); + +
+ + +
Repeating rows and columns +

+ It's possible to set up repeating rows and columns in + your printouts by using the setRepeatingRowsAndColumns() + function in the HSSFWorkbook class. +

+

+ This function Contains 5 parameters. + The first parameter is the index to the sheet (0 = first sheet). + The second and third parameters specify the range for the columns to repreat. + To stop the columns from repeating pass in -1 as the start and end column. + The fourth and fifth parameters specify the range for the rows to repeat. + To stop the columns from repeating pass in -1 as the start and end rows. +

+ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet1 = wb.createSheet("new sheet"); + HSSFSheet sheet2 = wb.createSheet("second sheet"); + + // Set the columns to repeat from column 0 to 2 on the first sheet + wb.setRepeatingRowsAndColumns(0,0,2,-1,-1); + // Set the the repeating rows and columns on the second sheet. + wb.setRepeatingRowsAndColumns(1,4,5,1,2); + + FileOutputStream fileOut = new FileOutputStream("workbook.xls"); + wb.write(fileOut); + fileOut.close(); + +
+ +
Headers and Footers +

+ Example is for headers but applies directly to footers. +

+ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet("new sheet"); + + HSSFHeader header = sheet.getHeader(); + header.setCenter("Center Header"); + header.setLeft("Left Header"); + header.setRight(HSSFHeader.font("Stencil-Normal", "Italic") + + HSSFHeader.fontSize((short) 16) + "Right w/ Stencil-Normal Italic font and size 16"); + + FileOutputStream fileOut = new FileOutputStream("workbook.xls"); + wb.write(fileOut); + fileOut.close(); + +
+ + +
Drawing Shapes +

+ POI supports drawing shapes using the Microsoft Office + drawing tools. Shapes on a sheet are organized in a + hiearchy of groups and and shapes. The top-most shape + is the patriarch. This is not visisble on the sheet + at all. To start drawing you need to call createPatriarch + on the HSSFSheet class. This has the + effect erasing any other shape information stored + in that sheet. By default POI will leave shape + records alone in the sheet unless you make a call to + this method. +

+

+ To create a shape you have to go through the following + steps: +

+
    +
  1. Create the patriarch.
  2. +
  3. Create an anchor to position the shape on the sheet.
  4. +
  5. Ask the patriarch to create the shape.
  6. +
  7. Set the shape type (line, oval, rectangle etc...)
  8. +
  9. Set any other style details converning the shape. (eg: + line thickness, etc...)
  10. +
+ + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + a = new HSSFClientAnchor( 0, 0, 1023, 255, (short) 1, 0, (short) 1, 0 ); + HSSFSimpleShape shape1 = patriarch.createSimpleShape(a1); + shape1.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE); + +

+ Text boxes are created using a different call: +

+ + HSSFTextbox textbox1 = patriarch.createTextbox( + new HSSFClientAnchor(0,0,0,0,(short)1,1,(short)2,2)); + textbox1.setString(new HSSFRichTextString("This is a test") ); + +

+ It's possible to use different fonts to style parts of + the text in the textbox. Here's how: +

+ + HSSFFont font = wb.createFont(); + font.setItalic(true); + font.setUnderline(HSSFFont.U_DOUBLE); + HSSFRichTextString string = new HSSFRichTextString("Woo!!!"); + string.applyFont(2,5,font); + textbox.setString(string ); + +

+ Just as can be done manually using Excel, it is possible + to group shapes together. This is done by calling + createGroup() and then creating the shapes + using those groups. +

+

+ It's also possible to create groups within groups. +

+ Any group you create should contain at least two + other shapes or subgroups. +

+ Here's how to create a shape group: +

+ + // Create a shape group. + HSSFShapeGroup group = patriarch.createGroup( + new HSSFClientAnchor(0,0,900,200,(short)2,2,(short)2,2)); + + // Create a couple of lines in the group. + HSSFSimpleShape shape1 = group.createShape(new HSSFChildAnchor(3,3,500,500)); + shape1.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE); + ( (HSSFChildAnchor) shape1.getAnchor() ).setAnchor((short)3,3,500,500); + HSSFSimpleShape shape2 = group.createShape(new HSSFChildAnchor((short)1,200,400,600)); + shape2.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE); + +

+ If you're being observant you'll noticed that the shapes + that are added to the group use a new type of anchor: + the HSSFChildAnchor. What happens is that + the created group has it's own coordinate space for + shapes that are placed into it. POI defaults this to + (0,0,1023,255) but you are able to change it as desired. + Here's how: +

+ + myGroup.setCoordinates(10,10,20,20); // top-left, bottom-right + +

+ If you create a group within a group it's also going + to have it's own coordinate space. +

+
+ + +
Styling Shapes +

+ By default shapes can look a little plain. It's possible + to apply different styles to the shapes however. The + sorts of things that can currently be done are: +

+
    +
  • Change the fill color.
  • +
  • Make a shape with no fill color.
  • +
  • Change the thickness of the lines.
  • +
  • Change the style of the lines. Eg: dashed, dotted.
  • +
  • Change the line color.
  • +
+

+ Here's an examples of how this is done: +

+ + HSSFSimpleShape s = patriarch.createSimpleShape(a); + s.setShapeType(HSSFSimpleShape.OBJECT_TYPE_OVAL); + s.setLineStyleColor(10,10,10); + s.setFillColor(90,10,200); + s.setLineWidth(HSSFShape.LINEWIDTH_ONE_PT * 3); + s.setLineStyle(HSSFShape.LINESTYLE_DOTSYS); + +
+ +
Shapes and Graphics2d +

+ While the native POI shape drawing commands are the + recommended way to draw shapes in a shape it's sometimes + desirable to use a standard API for compatibility with + external libraries. With this in mind we created some + wrappers for Graphics and Graphics2d. +

+ + It's important to not however before continuing that + Graphics2d is a poor match to the capabilities + of the Microsoft Office drawing commands. The older + Graphics class offers a closer match but is + still a square peg in a round hole. + +

+ All Graphics commands are issued into an HSSFShapeGroup. + Here's how it's done: +

+ + a = new HSSFClientAnchor( 0, 0, 1023, 255, (short) 1, 0, (short) 1, 0 ); + group = patriarch.createGroup( a ); + group.setCoordinates( 0, 0, 80 * 4 , 12 * 23 ); + float verticalPointsPerPixel = a.getAnchorHeightInPoints(sheet) / (float)Math.abs(group.getY2() - group.getY1()); + g = new EscherGraphics( group, wb, Color.black, verticalPointsPerPixel ); + g2d = new EscherGraphics2d( g ); + drawChemicalStructure( g2d ); + +

+ The first thing we do is create the group and set it's coordinates + to match what we plan to draw. Next we calculate a reasonable + fontSizeMultipler then create the EscherGraphics object. + Since what we really want is a Graphics2d + object we create an EscherGraphics2d object and pass in + the graphics object we created. Finally we call a routine + that draws into the EscherGraphics2d object. +

+

+ The vertical points per pixel deserves some more explanation. + One of the difficulties in converting Graphics calls + into escher drawing calls is that Excel does not have + the concept of absolute pixel positions. It measures + it's cell widths in 'characters' and the cell heights in points. + Unfortunately it's not defined exactly what type of character it's + measuring. Presumably this is due to the fact that the Excel will be + using different fonts on different platforms or even within the same + platform. +

+

+ Because of this constraint we've had to implement the concept of a + verticalPointsPerPixel. This the amount the font should be scaled by when + you issue commands such as drawString(). To calculate this value + use the follow formula: +

+ + multipler = groupHeightInPoints / heightOfGroup + +

+ The height of the group is calculated fairly simply by calculating the + difference between the y coordinates of the bounding box of the shape. The + height of the group can be calculated by using a convenience called + HSSFClientAnchor.getAnchorHeightInPoints(). +

+

+ Many of the functions supported by the graphics classes + are not complete. Here's some of the functions that are known + to work. +

+
    +
  • fillRect()
  • +
  • fillOval()
  • +
  • drawString()
  • +
  • drawOval()
  • +
  • drawLine()
  • +
  • clearRect()
  • +
+

+ Functions that are not supported will return and log a message + using the POI logging infrastructure (disabled by default). +

+
+ +
+ Outlining +

+ Outlines are great for grouping sections of information + together and can be added easily to columns and rows + using the POI API. Here's how: +

+ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet1 = wb.createSheet("new sheet"); + + sheet1.groupRow( 5, 14 ); + sheet1.groupRow( 7, 14 ); + sheet1.groupRow( 16, 19 ); + + sheet1.groupColumn( (short)4, (short)7 ); + sheet1.groupColumn( (short)9, (short)12 ); + sheet1.groupColumn( (short)10, (short)11 ); + + FileOutputStream fileOut = new FileOutputStream(filename); + wb.write(fileOut); + fileOut.close(); + +

+ To collapse (or expand) an outline use the following calls: +

+ + sheet1.setRowGroupCollapsed( 7, true ); + sheet1.setColumnGroupCollapsed( (short)4, true ); + +

+ The row/column you choose should contain an already + created group. It can be anywhere within the group. +

+
+
+
+ +
+ Images +

+ Images are part of the drawing support. To add an image just + call createPicture() on the drawing patriarch. + At the time of writing the following types are supported: +

+
    +
  • PNG
  • +
  • JPG
  • +
  • DIB
  • +
+

+ It should be noted that any existing drawings may be erased + once you add a image to a sheet. +

+ + // Create the drawing patriarch. This is the top level container for + // all shapes. This will clear out any existing shapes for that sheet. + HSSFPatriarch patriarch = sheet5.createDrawingPatriarch(); + + HSSFClientAnchor anchor; + anchor = new HSSFClientAnchor(0,0,0,255,(short)2,2,(short)4,7); + anchor.setAnchorType( 2 ); + patriarch.createPicture(anchor, loadPicture( "src/resources/logos/logoKarmokar4.png", wb )); + +

Creating an image and setting its anchor to the actual width and height:

+ + HSSFPatriarch patriarch = sheet5.createDrawingPatriarch(); + + HSSFPicture picture = patriarch.createPicture(new HSSFClientAnchor(), loadPicture( "src/resources/logos/logoKarmokar4.png", wb )); + picture.resize(); + +

or

+ + HSSFPatriarch patriarch = sheet5.createDrawingPatriarch(); + + HSSFPicture picture = patriarch.createPicture(new HSSFClientAnchor(), loadPicture( "src/resources/logos/logoKarmokar4.png", wb )); + HSSFClientAnchor preferredSize = picture.getPreferredSize(); + picture.setAnchor(preferredSize); + + + HSSFPicture.resize() works only for JPEG and PNG. Other formats are not yet supported. + + +

Reading images from a workbook:

+ + HSSFWorkbook wb; + + List lst = wb.getAllPictures(); + for (Iterator it = lst.iterator(); it.hasNext(); ) { + HSSFPictureData pict = (HSSFPictureData)it.next(); + String ext = pict.suggestFileExtension(); + byte[] data = pict.getData(); + if (ext.equals("jpeg")){ + FileOutputStream out = new FileOutputStream("pict.jpg"); + out.write(data); + out.close(); + } + } + +
+ +
+ Named Ranges and Named Cells +

+ Named Range is a way to refer to a group of cells by a name. Named Cell is a + degenerate case of Named Range in that the 'group of cells' contains exactly one + cell. You can create as well as refer to cells in a workbook by their named range. + When working with Named Ranges, the classes: org.apache.poi.hssf.util.CellReference and + & org.apache.poi.hssf.util.AreaReference are used. +

+

+ Creating Named Range / Named Cell +

+ + // setup code + String sname = "TestSheet", cname = "TestName", cvalue = "TestVal"; + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet(sname); + sheet.createRow(0).createCell((short) 0).setCellValue(cvalue); + + // 1. create named range for a single cell using areareference + HSSFName namedCell = wb.createName(); + namedCell.setNameName(cname); + String reference = sname+"!A1:A1"; // area reference + namedCell.setReference(reference); + + // 2. create named range for a single cell using cellreference + HSSFName namedCell = wb.createName(); + namedCell.setNameName(cname); + String reference = sname+"!A1"; // cell reference + namedCell.setReference(reference); + + // 3. create named range for an area using AreaReference + HSSFName namedCell = wb.createName(); + namedCell.setNameName(cname); + String reference = sname+"!A1:C5"; // area reference + namedCell.setReference(reference); + + +

+ Reading from Named Range / Named Cell +

+ + // setup code + String cname = "TestName"; + HSSFWorkbook wb = getMyWorkbook(); // retrieve workbook + + // retrieve the named range + int namedCellIdx = wb.getNameIndex(cellName); + HSSFName aNamedCell = wb.getNameAt(namedCellIdx); + + // retrieve the cell at the named range and test its contents + AreaReference aref = new AreaReference(aNamedCell.getReference()); + CellReference[] crefs = aref.getAllReferencedCells(); + for (int i=0; i<crefs.length; i++) { + HSSFSheet s = wb.getSheet(crefs[i].getSheetName()); + HSSFRow r = sheet.getRow(crefs[i].getRow()); + HSSFCell c = r.getCell(crefs[i].getCol()); + // extract the cell contents based on cell type etc. + } + +

+ Reading from non-contiguous Named Ranges +

+ + // Setup code + String cname = "TestName"; + HSSFWorkbook wb = getMyWorkbook(); // retrieve workbook + + // Retrieve the named range + // Will be something like "$C$10,$D$12:$D$14"; + int namedCellIdx = wb.getNameIndex(cellName); + HSSFName aNamedCell = wb.getNameAt(namedCellIdx); + + // Retrieve the cell at the named range and test its contents + // Will get back one AreaReference for C10, and + // another for D12 to D14 + AreaReference[] arefs = AreaReference.generateContiguous(aNamedCell.getReference()); + for (int i=0; i<arefs.length; i++) { + // Only get the corners of the Area + // (use arefs[i].getAllReferencedCells() to get all cells) + CellReference[] crefs = arefs[i].getCells(); + for (int j=0; j<crefs.length; j++) { + // Check it turns into real stuff + HSSFSheet s = wb.getSheet(crefs[j].getSheetName()); + HSSFRow r = s.getRow(crefs[j].getRow()); + HSSFCell c = r.getCell(crefs[j].getCol()); + // Do something with this corner cell + } + } + +
+ +
Cell Comments +

+ In Excel a comment is a kind of a text shape, + so inserting a comment is very similar to placing a text box in a worksheet: +

+ + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet sheet = wb.createSheet("Cell comments in POI HSSF"); + + // Create the drawing patriarch. This is the top level container for all shapes including cell comments. + HSSFPatriarch patr = sheet.createDrawingPatriarch(); + + //create a cell in row 3 + HSSFCell cell1 = sheet.createRow(3).createCell((short)1); + cell1.setCellValue(new HSSFRichTextString("Hello, World")); + + //anchor defines size and position of the comment in worksheet + HSSFComment comment1 = patr.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short)4, 2, (short) 6, 5)); + + // set text in the comment + comment1.setString(new HSSFRichTextString("We can set comments in POI")); + + //set comment author. + //you can see it in the status bar when moving mouse over the commented cell + comment1.setAuthor("Apache Software Foundation"); + + // The first way to assign comment to a cell is via HSSFCell.setCellComment method + cell1.setCellComment(comment1); + + //create another cell in row 6 + HSSFCell cell2 = sheet.createRow(6).createCell((short)1); + cell2.setCellValue(36.6); + + + HSSFComment comment2 = patr.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short)4, 8, (short) 6, 11)); + //modify background color of the comment + comment2.setFillColor(204, 236, 255); + + HSSFRichTextString string = new HSSFRichTextString("Normal body temperature"); + + //apply custom font to the text in the comment + HSSFFont font = wb.createFont(); + font.setFontName("Arial"); + font.setFontHeightInPoints((short)10); + font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); + font.setColor(HSSFColor.RED.index); + string.applyFont(font); + + comment2.setString(string); + //by default comments are hidden. This one is always visible. + comment2.setVisible(true); + + comment2.setAuthor("Bill Gates"); + + /** + * The second way to assign comment to a cell is to implicitly specify its row and column. + * Note, it is possible to set row and column of a non-existing cell. + * It works, the commnet is visible. + */ + comment2.setRow(6); + comment2.setColumn((short)1); + + FileOutputStream out = new FileOutputStream("poi_comment.xls"); + wb.write(out); + out.close(); + +

+ Reading cell comments +

+ + HSSFCell cell = sheet.get(3).getColumn((short)1); + HSSFComment comment = cell.getCellComment(); + if (comment != null) { + HSSFRichTextString str = comment.getString(); + String author = comment.getAuthor(); + } + // alternatively you can retrieve cell comments by (row, column) + comment = sheet.getCellComment(3, 1); + +
+ +
Adjust column width to fit the contents + + HSSFSheet sheet = workbook.getSheetAt(0); + sheet.autoSizeColumn((short)0); //adjust width of the first column + sheet.autoSizeColumn((short)1); //adjust width of the second column + + + To calculate column width HSSFSheet.autoSizeColumn uses Java2D classes + that throw exception if graphical environment is not available. In case if graphical environment + is not available, you must tell Java that you are running in headless mode and + set the following system property: java.awt.headless=true + (either via -Djava.awt.headless=true startup parameter or via System.setProperty("java.awt.headless", "true")). + +
+ +
How to read hyperlinks + + HSSFSheet sheet = workbook.getSheetAt(0); + + HSSFCell cell = sheet.getRow(0).getCell((short)0); + HSSFHyperlink link = cell.getHyperlink(); + if(link != null){ + System.out.println(link.getAddress()); + } + +
+
How to create hyperlinks + + HSSFWorkbook wb = new HSSFWorkbook(); + + //cell style for hyperlinks + //by default hypelrinks are blue and underlined + HSSFCellStyle hlink_style = wb.createCellStyle(); + HSSFFont hlink_font = wb.createFont(); + hlink_font.setUnderline(HSSFFont.U_SINGLE); + hlink_font.setColor(HSSFColor.BLUE.index); + hlink_style.setFont(hlink_font); + + HSSFCell cell; + HSSFSheet sheet = wb.createSheet("Hyperlinks"); + + //URL + cell = sheet.createRow(0).createCell((short)0); + cell.setCellValue("URL Link"); + HSSFHyperlink link = new HSSFHyperlink(HSSFHyperlink.LINK_URL); + link.setAddress("http://poi.apache.org/"); + cell.setHyperlink(link); + cell.setCellStyle(hlink_style); + + //link to a file in the current directory + cell = sheet.createRow(1).createCell((short)0); + cell.setCellValue("File Link"); + link = new HSSFHyperlink(HSSFHyperlink.LINK_FILE); + link.setAddress("link1.xls"); + cell.setHyperlink(link); + cell.setCellStyle(hlink_style); + + //e-mail link + cell = sheet.createRow(2).createCell((short)0); + cell.setCellValue("Email Link"); + link = new HSSFHyperlink(HSSFHyperlink.LINK_EMAIL); + //note, if subject contains white spaces, make sure they are url-encoded + link.setAddress("mailto:poi@apache.org?subject=Hyperlinks"); + cell.setHyperlink(link); + cell.setCellStyle(hlink_style); + + //link to a place in this workbook + + //create a target sheet and cell + HSSFSheet sheet2 = wb.createSheet("Target Sheet"); + sheet2.createRow(0).createCell((short)0).setCellValue("Target Cell"); + + cell = sheet.createRow(3).createCell((short)0); + cell.setCellValue("Worksheet Link"); + link = new HSSFHyperlink(HSSFHyperlink.LINK_DOCUMENT); + link.setAddress("'Target Sheet'!A1"); + cell.setHyperlink(link); + cell.setCellStyle(hlink_style); + + FileOutputStream out = new FileOutputStream("hssf-links.xls"); + wb.write(out); + out.close(); + +
+ + +
diff --git a/src/documentation/content/xdocs/ss/record-generator.xml b/src/documentation/content/xdocs/ss/record-generator.xml new file mode 100644 index 0000000000..8ce8fe5d89 --- /dev/null +++ b/src/documentation/content/xdocs/ss/record-generator.xml @@ -0,0 +1,212 @@ + + + + + +
+ Record Generator HOWTO + + + + +
+ +
How to Use the Record Generator + +
History +

+ The record generator was born from frustration with translating + the Excel records to Java classes. Doing this manually is a time + consuming process. It's also very easy to make mistakes. +

+

+ A utility was needed to take the defintition of what a + record looked like and do all the boring and repetitive work. +

+
+ +
Capabilities +

+ The record generator takes XML as input and produces the following + output: +

+
    +
  • A Java file capabile of decoding and encoding the record.
  • +
  • A test class that provides a fill-in-the-blanks implementation + of a test case for ensuring the record operates as + designed.
  • +
+
+
Usage +

+ The record generator is invoked as an Ant target + (generate-records). It goes through looking for all files in + src/records/defintitions ending with _record.xml. + It then creates two files; the Java record definition and the + Java test case template. +

+

+ The records themselves have the following general layout: +

+ + The frame record indicates whether there is a border + around the displayed text of a chart. + Glen Stampoultzis (glens at apache.org) + + + + + + + + + + + + ]]> +

+ The following table details the allowable types and sizes for + the fields. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeSizeJava Type
int1byte
int2short
int4int
int8long
intvarwordarray of shorts
bits1A byte comprising of a bits (defined by the bit element) +
bits2An short comprising of a bits
bits4A int comprising of a bits
float8double
hbstringjava expressionString
+

+ The Java records are regenerated each time the record generator is + run, however the test stubs are only created if the test stub does + not already exist. What this means is that you may change test + stubs but not the generated records. +

+
+
Custom Field Types +

+ Occationally the builtin types are not enough. More control + over the encoding and decoding of the streams is required. This + can be achieved using a custom type. +

+

+ A custom type lets you escape to java to define the way in which + the field encodes and decodes. To code a custom type you + declare your field like this: +

+ + ]]> +

+ Where the class name specified after custom: is a + class implementing the interface CustomField. +

+

+ You can then implement the encoding yourself. +

+
+
How it Works +

+ The record generation works by taking an XML file and styling it + using XLST. Given that XSLT is a little limited in some ways it was + necessary to add a little Java code to the mix. +

+

+ See record.xsl, record_test.xsl, FieldIterator.java, + RecordUtil.java, RecordGenerator.java +

+

+ There is a corresponding "type" generator for HWPF. + See the HWPF documentation for details. +

+
+
Limitations +

+ The record generator does not handle all possible record types and + goes not intend to perform this function. When dealing with a + non-standard record sometimes the cost-benifit of coding the + record by hand will be greater than attempting modify the + generator. The main point of the record generator is to save + time, so keep that in mind. +

+

+ Currently the the XSL file that generates the record calls out to + Java objects. The Java code for the record generation is + currently quite messy with minimal comments. +

+
+
+ +
diff --git a/src/documentation/content/xdocs/ss/use-case.xml b/src/documentation/content/xdocs/ss/use-case.xml new file mode 100644 index 0000000000..acd66fc6e1 --- /dev/null +++ b/src/documentation/content/xdocs/ss/use-case.xml @@ -0,0 +1,200 @@ + + + + + +
+ HSSF Use Cases + + + +
+ +
HSSF Use Cases +
Use Case 1: Read existing HSSF + +

Primary Actor: HSSF client

+

Scope: HSSF

+

Level: Summary

+

Stakeholders and Interests:

+
    +
  • HSSF client- wants to read content + of HSSF file
  • +
  • HSSF - understands HSSF file
  • +
  • POIFS - understands underlying POI + file system
  • +
+

Precondition: None

+

Minimal Guarantee: None

+

Main Success Guarantee:

+
    +
  1. HSSF client requests HSSF to read + a HSSF file, providing an InputStream + containing HSSF file in question.
  2. +
  3. HSSF requests POIFS to read the HSSF + file, passing the InputStream + object to POIFS (POIFS use case 1, read existing file system)
  4. +
  5. HSSF reads the "Workbook" + file (use case 4, read workbook entry)
  6. +
+

Extensions:

+

2a. Exceptions +thrown by POIFS will be passed on to the HSSF client.

+
+
Use Case 2: Write HSSF file + +

Primary Actor: HSSF client

+

Scope: HSSF

+

Level: Summary

+

Stakeholders and Interests:

+
    +
  • HSSF client- wants to write file + out.
  • +
  • HSSF - knows how to write file + out.
  • +
  • POIFS - knows how to write file + system out.
  • +
+

Precondition:

+
    +
  • File has been + read (use case 1, read existing HSSF file) and subsequently modified + or file has been created (use case 3, create HSSF file)
  • +
+

Minimal Guarantee: None

+

Main Success Guarantee:

+
    +
  1. HSSF client + provides an OutputStream to + write the file to.
  2. +
  3. HSSF writes + the "Workbook" to its associated POIFS file system (use case + 5, write workbook entry)
  4. +
  5. HSSF + requests POIFS to write its file system out, using the OutputStream + obtained from the HSSF client (POIFS use case 2, write file system).
  6. +
+

Extensions:

+

3a. Exceptions +from POIFS are passed to the HSSF client.

+ +
+
Use Case 3:Create HSSF file + +

Primary Actor: HSSF client

+

Scope: HSSF

+

+Level: Summary

+

Stakeholders and Interests:

+
    +
  • HSSF client- wants to create a new + file.
  • +
  • HSSF - knows how to create a new + file.
  • +
  • POIFS - knows how to creat a new + file system.
  • +
+

Precondition:

+

Minimal Guarantee: None

+

Main Success Guarantee:

+
    +
  1. HSSF requests + POIFS to create a new file system (POIFS use case 3, create new file + system)
  2. +
+

Extensions: +None

+ +
+
Use Case 4: Read workbook entry +

Primary Actor: HSSF

+

Scope: HSSF

+

+Level: Summary

+

Stakeholders and Interests:

+
    +
  • HSSF - knows how to read the + workbook entry
  • +
  • POIFS - knows how to manage the file + system.
  • +
+

Precondition:

+
    +
  • The file + system has been read (use case 1, read existing HSSF file) or has + been created and written to (use case 3, create HSSF file system; + use case 5, write workbook entry).
  • +
+

Minimal +Guarantee: None

+

Main Success Guarantee:

+
    +
  1. + HSSF requests POIFS for the "Workbook" file
  2. +
  3. POIFS returns + an InputStream for the file.
  4. +
  5. HSSF reads + from the InputStream provided by POIFS
  6. +
  7. HSSF closes + the InputStream provided by POIFS
  8. +
+

Extensions:

+

3a. Exceptions +thrown by POIFS will be passed on

+
+
Use Case 5: Write workbook entry + + +

Primary Actor: HSSF

+

Scope: HSSF

+

+Level: Summary

+

Stakeholders and Interests:

+
    +
  • HSSF - knows how to manage the + write the workbook entry.
  • +
  • POIFS - knows how to manage the file + system.
  • +
+

Precondition: +

+
    +
  • Either an existing HSSF file has + been read (use case 1, read existing HSSF file) or an HSSF file has + been created (use case 3, create HSSF file).
  • +
+

Minimal Guarantee: None

+

Main Success Guarantee:

+
    +
  1. HSSF + checks the POIFS file system directory for the "Workbook" + file (POIFS use case 8, read file system directory)
  2. +
  3. If "Workbook" is in the directory, HSSF requests POIFS to + replace it with the new workbook entry (POIFS use case 4, replace file + in file system). Otherwise, HSSF requests POIFS to write the new + workbook file, with the name "Workbook" (POIFS use case 6, + write new file to file system)
  4. +
+

Extensions:None

+
+ +
+ +