Merged revisions 638786-638802,638805-638811,638813-638814,638816-639230,639233-639241,639243-639253,639255-639486,639488-639601,639603-639835,639837-639917,639919-640056,640058-640710,640712-641156,641158-641184,641186-641795,641797-641798,641800-641933,641935-641963,641965-641966,641968-641995,641997-642230,642232-642562,642564-642565,642568-642570,642572-642573,642576-642736,642739-642877,642879,642881-642890,642892-642903,642905-642945,642947-645088 via svnmerge from

https://svn.apache.org/repos/asf/poi/trunk

........
  r643625 | josh | 2008-04-01 23:18:25 +0100 (Tue, 01 Apr 2008) | 1 line
  
  Bug #44733 - DPRODUCT function should be index 189, not 191
........
  r643654 | josh | 2008-04-02 00:53:51 +0100 (Wed, 02 Apr 2008) | 1 line
  
  fix for bug 44710 - Incorrect skip() of second formula in DATAVALIDATION record
........
  r643670 | klute | 2008-04-02 01:50:45 +0100 (Wed, 02 Apr 2008) | 1 line
  
  44694 - HPSF: Support for property sets without sections
........
  r643672 | klute | 2008-04-02 01:55:52 +0100 (Wed, 02 Apr 2008) | 1 line
  
  Restored an entry that had been deleted by chance.
........
  r643831 | yegor | 2008-04-02 11:20:31 +0100 (Wed, 02 Apr 2008) | 1 line
  
  added set accessor to indentation level
........
  r643834 | yegor | 2008-04-02 11:25:18 +0100 (Wed, 02 Apr 2008) | 1 line
  
  Fixed inconsistency between HSSFSHeet.getColumnWidth and HSSFSheet.getDefaultColumnWidth: getColumnWidth should always return width measured in 1/256th units.
........
  r644343 | nick | 2008-04-03 16:04:52 +0100 (Thu, 03 Apr 2008) | 1 line
  
  Make a bit of a start on being able to edit chart titles, based on the email to user@poi from Russ on the 2nd of April. Not quite there though
........
  r644473 | josh | 2008-04-03 21:25:53 +0100 (Thu, 03 Apr 2008) | 1 line
  
  Fix for bug 44739 - Conditional formatting (regions with max row/col index)
........
  r644509 | josh | 2008-04-03 22:17:26 +0100 (Thu, 03 Apr 2008) | 1 line
  
  Follow up fix after r644473 (bug 44739) TestHSSFConditionalFormatting had a bug and wasn't yet included in the test suite hierarchy
........


git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@645096 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2008-04-05 13:38:52 +00:00
parent 641ab5bb06
commit 8ff08c1c1a
26 changed files with 487 additions and 162 deletions

View File

@ -37,7 +37,9 @@
<!-- Don't forget to update status.xml too! -->
<release version="3.0.3-beta1" date="2008-04-??">
<action dev="POI-DEVELOPERS" type="fix">44739 - Small fixes for conditional formatting (regions with max row/col index)</action>
<action dev="POI-DEVELOPERS" type="add">Implement Sheet.removeShape(Shape shape) in HSLF</action>
<action dev="RK" type="add">44694 - HPSF: Support for property sets without sections</action>
<action dev="POI-DEVELOPERS" type="add">Various fixes: Recognising var-arg built-in functions #44675, ExternalNameRecord serialisation bug #44695, PMT() bug #44691</action>
<action dev="POI-DEVELOPERS" type="add">30311 - More work on Conditional Formatting</action>
<action dev="POI-DEVELOPERS" type="add">Move the Formula Evaluator code out of scratchpad</action>

View File

@ -34,6 +34,8 @@
<!-- Don't forget to update changes.xml too! -->
<changes>
<release version="3.0.3-beta1" date="2008-04-??">
<action dev="POI-DEVELOPERS" type="fix">44739 - Small fixes for conditional formatting (regions with max row/col index)</action>
<action dev="RK" type="add">44694 - HPSF: Support for property sets without sections</action>
<action dev="POI-DEVELOPERS" type="add">Implement Sheet.removeShape(Shape shape) in HSLF</action>
<action dev="POI-DEVELOPERS" type="add">Various fixes: Recognising var-arg built-in functions #44675, ExternalNameRecord serialisation bug #44695, PMT() bug #44691</action>
<action dev="POI-DEVELOPERS" type="add">30311 - More work on Conditional Formatting</action>

View File

@ -92,6 +92,8 @@ public class MutablePropertySet extends PropertySet
osVersion = ps.getOSVersion();
setClassID(ps.getClassID());
clearSections();
if (sections == null)
sections = new LinkedList();
for (final Iterator i = ps.getSections().iterator(); i.hasNext();)
{
final MutableSection s = new MutableSection((Section) (i.next()));

View File

@ -387,7 +387,7 @@ public class PropertySet
o += ClassID.LENGTH;
final long sectionCount = LittleEndian.getUInt(src, o);
o += LittleEndian.INT_SIZE;
if (sectionCount < 1)
if (sectionCount < 0)
return false;
return true;
}
@ -426,9 +426,9 @@ public class PropertySet
o += ClassID.LENGTH;
final int sectionCount = LittleEndian.getInt(src, o);
o += LittleEndian.INT_SIZE;
if (sectionCount <= 0)
if (sectionCount < 0)
throw new HPSFRuntimeException("Section count " + sectionCount +
" must be greater than 0.");
" is negative.");
/*
* Read the sections, which are following the header. They
@ -468,6 +468,8 @@ public class PropertySet
*/
public boolean isSummaryInformation()
{
if (sections.size() <= 0)
return false;
return Util.equal(((Section) sections.get(0)).getFormatID().getBytes(),
SectionIDMap.SUMMARY_INFORMATION_ID);
}
@ -483,6 +485,8 @@ public class PropertySet
*/
public boolean isDocumentSummaryInformation()
{
if (sections.size() <= 0)
return false;
return Util.equal(((Section) sections.get(0)).getFormatID().getBytes(),
SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID[0]);
}

View File

@ -1879,12 +1879,12 @@ public class Sheet implements Model
}
/**
* get the width of a given column in units of 1/20th of a point width (twips?)
* get the width of a given column in units of 1/256th of a character width
* @param column index
* @see org.apache.poi.hssf.record.DefaultColWidthRecord
* @see org.apache.poi.hssf.record.ColumnInfoRecord
* @see #setColumnWidth(short,short)
* @return column width in units of 1/20th of a point (twips?)
* @return column width in units of 1/256th of a character width
*/
public short getColumnWidth(short column)
@ -1912,7 +1912,9 @@ public class Sheet implements Model
}
else
{
retval = defaultcolwidth.getColWidth();
//default column width is measured in characters
//multiply
retval = (short)(256*defaultcolwidth.getColWidth());
}
return retval;
}
@ -1951,9 +1953,9 @@ public class Sheet implements Model
}
/**
* set the width for a given column in 1/20th of a character width units
* set the width for a given column in 1/256th of a character width units
* @param column - the column number
* @param width (in units of 1/20th of a character width)
* @param width (in units of 1/256th of a character width)
*/
public void setColumnWidth(short column, short width)
{

View File

@ -58,12 +58,12 @@ public final class CFHeaderRecord extends Record
{
field_1_numcf = in.readShort();
field_2_need_recalculation = in.readShort();
field_3_enclosing_cell_range = new CellRange(in.readShort(),in.readShort(),in.readShort(),in.readShort());
field_3_enclosing_cell_range = new CellRange(in.readUShort(), in.readUShort(), in.readUShort(), in.readUShort());
int numCellRanges = in.readShort();
CellRange[] crs = new CellRange[numCellRanges];
for( int i=0; i<numCellRanges; i++)
{
crs[i] = new CellRange(in.readShort(),in.readShort(),in.readShort(),in.readShort());
crs[i] = new CellRange(in.readUShort(),in.readUShort(),in.readUShort(),in.readUShort());
}
field_4_cell_ranges = crs;
}

View File

@ -28,7 +28,7 @@ import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.StringUtil;
/**
* Title: DV Record<P>
* Title: DATAVALIDATION Record (0x01BE)<p/>
* Description: This record stores data validation settings and a list of cell ranges
* which contain these settings. The data validation settings of a sheet
* are stored in a sequential list of DV records. This list is followed by
@ -36,7 +36,7 @@ import org.apache.poi.util.StringUtil;
* @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
* @version 2.0-pre
*/
public class DVRecord extends Record
public final class DVRecord extends Record
{
public final static short sid = 0x01BE;
@ -170,11 +170,6 @@ public class DVRecord extends Record
this.field_not_used_1 = in.readShort();
//read first formula data condition
// Not sure if this was needed or not...
// try {
// in.skip(this.field_size_first_formula);
// } catch(IOException e) { throw new IllegalStateException(e); }
int token_pos = 0;
while (token_pos < this.field_size_first_formula)
{
@ -187,14 +182,14 @@ public class DVRecord extends Record
this.field_not_used_2 = in.readShort();
//read sec formula data condition
//Not sure if this was needed or not...
if (false) { // TODO - prior to bug 44710 this 'skip' was being executed. write a junit to confirm this fix
try {
in.skip(this.field_size_sec_formula);
} catch(IOException e) {
e.printStackTrace();
throw new IllegalStateException(e.getMessage());
}
}
token_pos = 0;
while (token_pos < this.field_size_sec_formula)
{
@ -516,7 +511,7 @@ public class DVRecord extends Record
/**@todo DVRecord = Serializare */
private class StringHandler
private static final class StringHandler
{
private int _string_length = 0x0001;
private byte _string_unicode_flag = 0x00;

View File

@ -29,12 +29,10 @@ import org.apache.poi.hssf.util.Region;
*/
public final class CellRange
{
/**
* max index for both row and column<p/>
*
* Note - this value converts to <tt>-1</tt> when cast to a <tt>short</tt>
*/
private static final int MAX_INDEX = Integer.MAX_VALUE;
/** max 65536 rows in BIFF8 */
private static final int LAST_ROW_INDEX = 0x00FFFF;
/** max 256 columns in BIFF8 */
private static final int LAST_COLUMN_INDEX = 0x00FF;
private static final Region[] EMPTY_REGION_ARRAY = { };
@ -57,54 +55,46 @@ public final class CellRange
+ ", " + firstColumn + ", " + lastColumn + ")");
}
_firstRow = firstRow;
_lastRow = convertM1ToMax(lastRow);
_lastRow = convertM1ToMax(lastRow, LAST_ROW_INDEX);
_firstColumn = firstColumn;
_lastColumn = convertM1ToMax(lastColumn);
_lastColumn = convertM1ToMax(lastColumn, LAST_COLUMN_INDEX);
}
private static int convertM1ToMax(int lastIx) {
/**
* Range arithmetic is easier when using a large positive number for 'max row or column'
* instead of <tt>-1</tt>.
*/
private static int convertM1ToMax(int lastIx, int maxIndex) {
if(lastIx < 0) {
return MAX_INDEX;
}
return lastIx;
}
private static int convertMaxToM1(int lastIx) {
if(lastIx == MAX_INDEX) {
return -1;
return maxIndex;
}
return lastIx;
}
public boolean isFullColumnRange() {
return _firstColumn == 0 && _lastColumn == MAX_INDEX;
return _firstRow == 0 && _lastRow == LAST_ROW_INDEX;
}
public boolean isFullRowRange() {
return _firstRow == 0 && _lastRow == MAX_INDEX;
return _firstColumn == 0 && _lastColumn == LAST_COLUMN_INDEX;
}
public CellRange(Region r) {
this(r.getRowFrom(), r.getRowTo(), r.getColumnFrom(), r.getColumnTo());
private static CellRange createFromRegion(Region r) {
return new CellRange(r.getRowFrom(), r.getRowTo(), r.getColumnFrom(), r.getColumnTo());
}
private static boolean isValid(int firstRow, int lastRow, int firstColumn, int lastColumn)
{
if(lastRow == -1) {
if(firstRow !=0) {
if(lastRow < 0 || lastRow > LAST_ROW_INDEX) {
return false;
}
}
if(firstRow < 0 || lastRow < -1) {
if(firstRow < 0 || firstRow > LAST_ROW_INDEX) {
return false;
}
if(lastColumn == -1) {
if(firstColumn !=0) {
if(lastColumn < 0 || lastColumn > LAST_COLUMN_INDEX) {
return false;
}
}
if(firstColumn < 0 || lastColumn < -1) {
if(firstColumn < 0 || firstColumn > LAST_COLUMN_INDEX) {
return false;
}
return true;
@ -114,23 +104,17 @@ public final class CellRange
{
return _firstRow;
}
/**
* @return <tt>-1</tt> for whole column ranges
*/
public int getLastRow()
{
return convertMaxToM1(_lastRow);
return _lastRow;
}
public int getFirstColumn()
{
return _firstColumn;
}
/**
* @return <tt>-1</tt> for whole row ranges
*/
public int getLastColumn()
{
return convertMaxToM1(_lastColumn);
return _lastColumn;
}
public static final int NO_INTERSECTION = 1;
@ -374,7 +358,7 @@ public final class CellRange
CellRange[] result = new CellRange[regions.length];
for( int i=0; i<regions.length; i++)
{
result[i] = new CellRange(regions[i]);
result[i] = createFromRegion(regions[i]);
}
return result;
}
@ -404,10 +388,8 @@ public final class CellRange
private Region convertToRegion() {
int lastRow = convertMaxToM1(_lastRow);
int lastColumn = convertMaxToM1(_lastColumn);
return new Region(_firstRow, (short)_firstColumn, lastRow, (short)lastColumn);
return new Region(_firstRow, (short)_firstColumn, _lastRow, (short)_lastColumn);
}

View File

@ -143,8 +143,8 @@
169 COUNTA 0 30 V R
183 PRODUCT 0 30 V R
184 FACT 1 1 V V
189 DPRODUCT 3 3 V R R R
190 ISNONTEXT 1 1 V V
191 DPRODUCT 3 3 V R R R
193 STDEVP 1 30 V R
194 VARP 1 30 V R
195 DSTDEVP 3 3 V R R R

View File

@ -424,6 +424,15 @@ public class RichTextRun {
return paragraphStyle == null ? 0 : paragraphStyle.getReservedField();
}
/**
* Sets indentation level
*
* @param level indentation level. Must be in the range [0, 5]
*/
public void setIndentLevel(int level) {
if(paragraphStyle != null ) paragraphStyle.setReservedField((short)level);
}
/**
* Sets whether this rich text run has bullets
*/

View File

@ -23,6 +23,7 @@ import org.apache.poi.hssf.record.*;
import org.apache.poi.hssf.record.formula.Area3DPtg;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
@ -33,6 +34,15 @@ import java.util.Stack;
*/
public class HSSFChart
{
private ChartRecord chartRecord;
private SeriesRecord seriesRecord;
private ChartTitleFormatRecord chartTitleFormat;
private SeriesTextRecord chartTitleText;
private HSSFChart(ChartRecord chartRecord) {
this.chartRecord = chartRecord;
}
/**
* Creates a bar chart. API needs some work. :)
@ -108,6 +118,74 @@ public class HSSFChart
workbook.insertChartRecord();
}
/**
* Returns all the charts for the given sheet.
*
* NOTE: Does not yet work... checking it in just so others
* can take a look.
*/
public static HSSFChart[] getSheetCharts(HSSFSheet sheet) {
List charts = new ArrayList();
HSSFChart lastChart = null;
// Find records of interest
List records = sheet.getSheet().getRecords();
for(Iterator it = records.iterator(); it.hasNext();) {
Record r = (Record)it.next();
System.err.println(r);
if(r instanceof DrawingRecord) {
DrawingRecord dr = (DrawingRecord)r;
}
if(r instanceof ChartRecord) {
lastChart = new HSSFChart((ChartRecord)r);
charts.add(lastChart);
}
if(r instanceof SeriesRecord) {
lastChart.seriesRecord = (SeriesRecord)r;
}
if(r instanceof ChartTitleFormatRecord) {
lastChart.chartTitleFormat =
(ChartTitleFormatRecord)r;
}
if(r instanceof SeriesTextRecord) {
lastChart.chartTitleText =
(SeriesTextRecord)r;
}
}
return (HSSFChart[])
charts.toArray( new HSSFChart[charts.size()] );
}
/**
* Returns the chart's title, if there is one,
* or null if not
*/
public String getChartTitle() {
if(chartTitleText != null) {
return chartTitleText.getText();
}
return null;
}
/**
* Changes the chart's title, but only if there
* was one already.
* TODO - add in the records if not
*/
public void setChartTitle(String title) {
if(chartTitleText != null) {
chartTitleText.setText(title);
} else {
throw new IllegalStateException("No chart title found to change");
}
}
private EOFRecord createEOFRecord()
{
return new EOFRecord();

View File

@ -0,0 +1,61 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.usermodel;
import java.io.File;
import java.io.FileInputStream;
import junit.framework.TestCase;
public class TestHSSFChart extends TestCase {
private String dirName;
protected void setUp() throws Exception {
dirName = System.getProperty("HSSF.testdata.path");
}
public void testSingleChart() throws Exception {
}
public void testTwoCharts() throws Exception {
}
public void BROKENtestThreeCharts() throws Exception {
HSSFWorkbook wb = new HSSFWorkbook(
new FileInputStream(new File(dirName, "WithThreeCharts.xls"))
);
HSSFSheet s1 = wb.getSheetAt(0);
HSSFSheet s2 = wb.getSheetAt(1);
HSSFSheet s3 = wb.getSheetAt(2);
assertEquals(0, HSSFChart.getSheetCharts(s1).length);
assertEquals(2, HSSFChart.getSheetCharts(s2).length);
assertEquals(1, HSSFChart.getSheetCharts(s3).length);
HSSFChart[] charts;
charts = HSSFChart.getSheetCharts(s2);
assertNull(charts[0].getChartTitle());
assertEquals("Pie Chart Title Thingy", charts[1].getChartTitle());
charts = HSSFChart.getSheetCharts(s3);
assertEquals("Sheet 3 Chart with Title", charts[1].getChartTitle());
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -17,13 +17,13 @@
package org.apache.poi.hssf.record;
import org.apache.poi.hssf.record.aggregates.AllRecordAggregateTests;
import org.apache.poi.hssf.record.formula.AllFormulaTests;
import org.apache.poi.hssf.record.formula.functions.AllIndividualFunctionEvaluationTests;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.apache.poi.hssf.record.aggregates.AllRecordAggregateTests;
import org.apache.poi.hssf.record.cf.TestCellRange;
import org.apache.poi.hssf.record.formula.AllFormulaTests;
/**
* Collects all tests for package <tt>org.apache.poi.hssf.record</tt>.
*
@ -104,6 +104,7 @@ public final class AllRecordTests {
result.addTestSuite(TestUnicodeString.class);
result.addTestSuite(TestUnitsRecord.class);
result.addTestSuite(TestValueRangeRecord.class);
result.addTestSuite(TestCellRange.class);
return result;
}
}

View File

@ -17,6 +17,7 @@
package org.apache.poi.hssf.record;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.apache.poi.hssf.record.cf.CellRange;
@ -34,8 +35,8 @@ public final class TestCFHeaderRecord extends TestCase
{
CFHeaderRecord record = new CFHeaderRecord();
CellRange[] ranges = {
new CellRange(0,-1,5,5),
new CellRange(0,-1,6,6),
new CellRange(0,0xFFFF,5,5),
new CellRange(0,0xFFFF,6,6),
new CellRange(0,1,0,1),
new CellRange(0,1,2,3),
new CellRange(2,3,0,1),
@ -46,7 +47,7 @@ public final class TestCFHeaderRecord extends TestCase
assertEquals(6,ranges.length);
CellRange enclosingCellRange = record.getEnclosingCellRange();
assertEquals(0, enclosingCellRange.getFirstRow());
assertEquals(-1, enclosingCellRange.getLastRow());
assertEquals(65535, enclosingCellRange.getLastRow());
assertEquals(0, enclosingCellRange.getFirstColumn());
assertEquals(6, enclosingCellRange.getLastColumn());
record.setNeedRecalculation(true);
@ -56,7 +57,7 @@ public final class TestCFHeaderRecord extends TestCase
}
public void testSerialization() {
byte[] recordData = new byte[]
byte[] recordData =
{
(byte)0x03, (byte)0x00,
(byte)0x01, (byte)0x00,
@ -66,7 +67,7 @@ public final class TestCFHeaderRecord extends TestCase
(byte)0x00, (byte)0x00,
(byte)0x03, (byte)0x00,
(byte)0x04, (byte)0x00,
(byte)0x04, (byte)0x00, // nRegions
(byte)0x00, (byte)0x00,
(byte)0x01, (byte)0x00,
@ -93,44 +94,88 @@ public final class TestCFHeaderRecord extends TestCase
assertEquals("#CFRULES", 3, record.getNumberOfConditionalFormats());
assertTrue(record.getNeedRecalculation());
CellRange enclosingCellRange = record.getEnclosingCellRange();
assertEquals(0, enclosingCellRange.getFirstRow());
assertEquals(3, enclosingCellRange.getLastRow());
assertEquals(0, enclosingCellRange.getFirstColumn());
assertEquals(3, enclosingCellRange.getLastColumn());
confirm(record.getEnclosingCellRange(), 0, 3, 0, 3);
CellRange[] ranges = record.getCellRanges();
CellRange range0 = ranges[0];
assertEquals(0, range0.getFirstRow());
assertEquals(1, range0.getLastRow());
assertEquals(0, range0.getFirstColumn());
assertEquals(1, range0.getLastColumn());
CellRange range1 = ranges[1];
assertEquals(0, range1.getFirstRow());
assertEquals(1, range1.getLastRow());
assertEquals(2, range1.getFirstColumn());
assertEquals(3, range1.getLastColumn());
CellRange range2 = ranges[2];
assertEquals(2, range2.getFirstRow());
assertEquals(3, range2.getLastRow());
assertEquals(0, range2.getFirstColumn());
assertEquals(1, range2.getLastColumn());
CellRange range3 = ranges[3];
assertEquals(2, range3.getFirstRow());
assertEquals(3, range3.getLastRow());
assertEquals(2, range3.getFirstColumn());
assertEquals(3, range3.getLastColumn());
assertEquals(4, ranges.length);
confirm(ranges[0], 0, 1, 0, 1);
confirm(ranges[1], 0, 1, 2, 3);
confirm(ranges[2], 2, 3, 0, 1);
confirm(ranges[3], 2, 3, 2, 3);
assertEquals(recordData.length+4, record.getRecordSize());
byte[] output = record.serialize();
assertEquals("Output size", recordData.length+4, output.length); //includes sid+recordlength
for (int i = 0; i < recordData.length;i++)
for (int i = 0; i < recordData.length; i++)
{
assertEquals("CFHeaderRecord doesn't match", recordData[i], output[i+4]);
}
}
public void testExtremeRows() {
byte[] recordData = {
(byte)0x13, (byte)0x00, // nFormats
(byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x00,
(byte)0xFF, (byte)0xFF,
(byte)0x00, (byte)0x00,
(byte)0xFF, (byte)0x00,
(byte)0x03, (byte)0x00, // nRegions
(byte)0x40, (byte)0x9C,
(byte)0x50, (byte)0xC3,
(byte)0x02, (byte)0x00,
(byte)0x02, (byte)0x00,
(byte)0x00, (byte)0x00,
(byte)0xFF, (byte)0xFF,
(byte)0x05, (byte)0x00,
(byte)0x05, (byte)0x00,
(byte)0x07, (byte)0x00,
(byte)0x07, (byte)0x00,
(byte)0x00, (byte)0x00,
(byte)0xFF, (byte)0x00,
};
CFHeaderRecord record;
try {
record = new CFHeaderRecord(new TestcaseRecordInputStream(CFHeaderRecord.sid, (short)recordData.length, recordData));
} catch (IllegalArgumentException e) {
if(e.getMessage().equals("invalid cell range (-25536, 2, -15536, 2)")) {
throw new AssertionFailedError("Identified bug 44739b");
}
throw e;
}
assertEquals("#CFRULES", 19, record.getNumberOfConditionalFormats());
assertFalse(record.getNeedRecalculation());
confirm(record.getEnclosingCellRange(), 0, 65535, 0, 255);
CellRange[] ranges = record.getCellRanges();
assertEquals(3, ranges.length);
confirm(ranges[0], 40000, 50000, 2, 2);
confirm(ranges[1], 0, 65535, 5, 5);
confirm(ranges[2], 7, 7, 0, 255);
byte[] output = record.serialize();
assertEquals("Output size", recordData.length+4, output.length); //includes sid+recordlength
for (int i = 0; i < recordData.length;i++) {
assertEquals("CFHeaderRecord doesn't match", recordData[i], output[i+4]);
}
}
private static void confirm(CellRange cr, int expFirstRow, int expLastRow, int expFirstCol, int expLastColumn) {
assertEquals("first row", expFirstRow, cr.getFirstRow());
assertEquals("last row", expLastRow, cr.getLastRow());
assertEquals("first column", expFirstCol, cr.getFirstColumn());
assertEquals("last column", expLastColumn, cr.getLastColumn());
}
public static void main(String[] ignored_args)
{

View File

@ -17,62 +17,76 @@ limitations under the License.
package org.apache.poi.hssf.record.cf;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
/**
* Tests CellRange operations.
*/
public class TestCellRange extends TestCase
public final class TestCellRange extends TestCase
{
private static final CellRange biggest = new CellRange( 0, -1, 0,-1);
private static final CellRange tenthColumn = new CellRange( 0, -1,10,10);
private static final CellRange tenthRow = new CellRange(10, 10, 0,-1);
private static final CellRange box10x10 = new CellRange( 0, 10, 0,10);
private static final CellRange box9x9 = new CellRange( 0, 9, 0, 9);
private static final CellRange box10to20c = new CellRange( 0, 10,10,20);
private static final CellRange oneCell = new CellRange(10, 10,10,10);
private static final CellRange biggest = createCR( 0, -1, 0,-1);
private static final CellRange tenthColumn = createCR( 0, -1,10,10);
private static final CellRange tenthRow = createCR(10, 10, 0,-1);
private static final CellRange box10x10 = createCR( 0, 10, 0,10);
private static final CellRange box9x9 = createCR( 0, 9, 0, 9);
private static final CellRange box10to20c = createCR( 0, 10,10,20);
private static final CellRange oneCell = createCR(10, 10,10,10);
boolean [][] contanis = new boolean[][]
private static final CellRange[] sampleRanges = {
biggest, tenthColumn, tenthRow, box10x10, box9x9, box10to20c, oneCell,
};
/** cross-reference of <tt>contains()</tt> operations for sampleRanges against itself */
private static final boolean [][] containsExpectedResults =
{
// biggest, tenthColumn, tenthRow, box10x10, box9x9, box10to20c, oneCell
/*biggest */ new boolean[]{true, true , true , true , true , true , true},
/*tenthColumn*/ new boolean[]{false, true , false, false, false, false, true},
/*tenthRow */ new boolean[]{false, false, true , false, false, false, true},
/*box10x10 */ new boolean[]{false, false, false, true , true , false, true},
/*box9x9 */ new boolean[]{false, false, false, false, true , false, false},
/*box10to20c */ new boolean[]{false, false, false, false, false, true , true},
/*oneCell */ new boolean[]{false, false, false, false, false, false, true},
/*biggest */ {true, true , true , true , true , true , true},
/*tenthColumn*/ {false, true , false, false, false, false, true},
/*tenthRow */ {false, false, true , false, false, false, true},
/*box10x10 */ {false, false, false, true , true , false, true},
/*box9x9 */ {false, false, false, false, true , false, false},
/*box10to20c */ {false, false, false, false, false, true , true},
/*oneCell */ {false, false, false, false, false, false, true},
} ;
/**
* @param lastRow pass -1 for max row index
* @param lastCol pass -1 for max col index
*/
private static CellRange createCR(int firstRow, int lastRow, int firstCol, int lastCol) {
// max row & max col limit as per BIFF8
return new CellRange(
firstRow,
lastRow == -1 ? 0xFFFF : lastRow,
firstCol,
lastCol == -1 ? 0x00FF : lastCol);
}
public void testContainsMethod()
{
CellRange [] ranges = new CellRange[]{biggest,tenthColumn,tenthRow,box10x10,box9x9,box10to20c,oneCell};
testContainsMethod(contanis,ranges);
}
private void testContainsMethod(boolean[][]contains,CellRange[] ranges)
{
CellRange [] ranges = sampleRanges;
for(int i=0; i!=ranges.length;i++)
{
for(int j=0; j!=ranges.length;j++)
{
assertEquals("("+i+","+j+"): ",contains[i][j],ranges[i].contains(ranges[j]));
boolean expectedResult = containsExpectedResults[i][j];
assertEquals("("+i+","+j+"): ", expectedResult, ranges[i].contains(ranges[j]));
}
}
}
private static final CellRange col1 = new CellRange( 0, -1, 1,1);
private static final CellRange col2 = new CellRange( 0, -1, 2,2);
private static final CellRange row1 = new CellRange( 1, 1, 0,-1);
private static final CellRange row2 = new CellRange( 2, 2, 0,-1);
private static final CellRange col1 = createCR( 0, -1, 1,1);
private static final CellRange col2 = createCR( 0, -1, 2,2);
private static final CellRange row1 = createCR( 1, 1, 0,-1);
private static final CellRange row2 = createCR( 2, 2, 0,-1);
private static final CellRange box0 = new CellRange( 0, 2, 0,2);
private static final CellRange box1 = new CellRange( 0, 1, 0,1);
private static final CellRange box2 = new CellRange( 0, 1, 2,3);
private static final CellRange box3 = new CellRange( 2, 3, 0,1);
private static final CellRange box4 = new CellRange( 2, 3, 2,3);
private static final CellRange box5 = new CellRange( 1, 3, 1,3);
private static final CellRange box0 = createCR( 0, 2, 0,2);
private static final CellRange box1 = createCR( 0, 1, 0,1);
private static final CellRange box2 = createCR( 0, 1, 2,3);
private static final CellRange box3 = createCR( 2, 3, 0,1);
private static final CellRange box4 = createCR( 2, 3, 2,3);
private static final CellRange box5 = createCR( 1, 3, 1,3);
public void testHasSharedBorderMethod()
{
@ -119,8 +133,8 @@ public class TestCellRange extends TestCase
public void testIntersectMethod()
{
assertEquals( CellRange.OVERLAP,box0.intersect(box5));
assertEquals( CellRange.OVERLAP,box5.intersect(box0));
assertEquals(CellRange.OVERLAP,box0.intersect(box5));
assertEquals(CellRange.OVERLAP,box5.intersect(box0));
assertEquals(CellRange.NO_INTERSECTION,box1.intersect(box4));
assertEquals(CellRange.NO_INTERSECTION,box4.intersect(box1));
assertEquals(CellRange.NO_INTERSECTION,box2.intersect(box3));
@ -135,4 +149,31 @@ public class TestCellRange extends TestCase
assertEquals(CellRange.INSIDE,tenthColumn.intersect(tenthColumn));
assertEquals(CellRange.INSIDE,tenthRow.intersect(tenthRow));
}
/**
* Cell ranges like the following are valid
* =$C:$IV,$B$1:$B$8,$B$10:$B$65536,$A:$A
*/
public void testCreate() {
CellRange cr;
cr = createCR(0, -1, 2, 255); // $C:$IV
confirmRange(cr, false, true);
cr = createCR(0, 7, 1, 1); // $B$1:$B$8
try {
cr = createCR(9, -1, 1, 1); // $B$65536
} catch (IllegalArgumentException e) {
if(e.getMessage().startsWith("invalid cell range")) {
throw new AssertionFailedError("Identified bug 44739");
}
throw e;
}
cr = createCR(0, -1, 0, 0); // $A:$A
}
private static void confirmRange(CellRange cr, boolean isFullRow, boolean isFullColumn) {
assertEquals("isFullRowRange", isFullRow, cr.isFullRowRange());
assertEquals("isFullColumnRange", isFullColumn, cr.isFullColumnRange());
}
}

View File

@ -29,7 +29,7 @@ import junit.framework.TestSuite;
*
* @author Josh Micich
*/
public class AllFormulaTests {
public final class AllFormulaTests {
public static Test suite() {
TestSuite result = new TestSuite(AllFormulaTests.class.getName());
@ -50,7 +50,6 @@ public class AllFormulaTests {
result.addTestSuite(TestReferencePtg.class);
result.addTestSuite(TestSheetNameFormatter.class);
result.addTestSuite(TestUnionPtg.class);
result.addTest(AllFormulaFunctionTests.suite());
return result;
}
}

View File

@ -27,6 +27,9 @@ import org.apache.poi.hssf.record.formula.FuncPtg;
import org.apache.poi.hssf.record.formula.FuncVarPtg;
import org.apache.poi.hssf.record.formula.Ptg;
/**
* Tests parsing of some built-in functions that were not properly
* registered in POI as bug #44675, #44733 (March/April 2008).
*
* @author Josh Micich
*/
public final class TestParseMissingBuiltInFuncs extends TestCase {
@ -39,6 +42,7 @@ public final class TestParseMissingBuiltInFuncs extends TestCase {
Ptg[] ptgs = parse(formula);
Ptg ptgF = ptgs[ptgs.length-1]; // func is last RPN token in all these formulas
// Check critical things in the Ptg array encoding.
if(!(ptgF instanceof AbstractFunctionPtg)) {
throw new RuntimeException("function token missing");
}
@ -47,11 +51,15 @@ public final class TestParseMissingBuiltInFuncs extends TestCase {
throw new AssertionFailedError("Failed to recognise built-in function in formula '"
+ formula + "'");
}
assertEquals(expPtgArraySize, ptgs.length);
assertEquals(funcIx, func.getFunctionIndex());
Class expCls = isVarArgFunc ? FuncVarPtg.class : FuncPtg.class;
assertEquals(expCls, ptgF.getClass());
// check that parsed Ptg array converts back to formula text OK
Workbook book = Workbook.createWorkbook();
String reRenderedFormula = FormulaParser.toFormulaString(book, ptgs);
assertEquals(formula, reRenderedFormula);
}
public void testDatedif() {
@ -76,4 +84,7 @@ public final class TestParseMissingBuiltInFuncs extends TestCase {
public void testIsnontext() {
confirmFunc("ISNONTEXT(\"abc\")", 2, false, 190);
}
public void testDproduct() {
confirmFunc("DPRODUCT(C1:E5,\"HarvestYield\",G1:H2)", 4, false, 189);
}
}

View File

@ -21,7 +21,9 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import org.apache.poi.hssf.record.RecordFormatException;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
@ -29,24 +31,31 @@ import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
/**
* Tests reading from a sample spreadsheet some built-in functions that were not properly
* registered in POI as bug #44675 (March 2008).
* registered in POI as bug #44675, #44733 (March/April 2008).
*
* @author Josh Micich
*/
public final class TestReadMissingBuiltInFuncs extends TestCase {
private HSSFSheet sht;
/**
* This spreadsheet has examples of calls to the interesting built-in functions in cells A1:A7
*/
private static final String SAMPLE_SPREADSHEET_FILE_NAME = "missingFuncs44675.xls";
private static HSSFSheet _sheet;
protected void setUp() {
private static HSSFSheet getSheet() {
if (_sheet == null) {
String cwd = System.getProperty("HSSF.testdata.path");
HSSFWorkbook wb;
try {
InputStream is = new FileInputStream(new File(cwd, "missingFuncs44675.xls"));
InputStream is = new FileInputStream(new File(cwd, SAMPLE_SPREADSHEET_FILE_NAME));
wb = new HSSFWorkbook(is);
} catch (IOException e) {
throw new RuntimeException(e);
}
sht = wb.getSheetAt(0);
_sheet = wb.getSheetAt(0);
}
return _sheet;
}
public void testDatedif() {
@ -128,9 +137,30 @@ public final class TestReadMissingBuiltInFuncs extends TestCase {
}
assertEquals("ISNONTEXT(\"abc\")", formula);
}
public void testDproduct() {
String formula = getCellFormula(6);
assertEquals("DPRODUCT(C1:E5,\"HarvestYield\",G1:H2)", formula);
}
private String getCellFormula(int rowIx) {
String result = sht.getRow(rowIx).getCell((short)0).getCellFormula();
HSSFSheet sheet;
try {
sheet = getSheet();
} catch (RecordFormatException e) {
if(e.getCause() instanceof InvocationTargetException) {
InvocationTargetException ite = (InvocationTargetException) e.getCause();
if(ite.getTargetException() instanceof RuntimeException) {
RuntimeException re = (RuntimeException) ite.getTargetException();
if(re.getMessage().equals("Invalid built-in function index (189)")) {
throw afe("DPRODUCT() registered with wrong index");
}
}
}
// some other unexpected error
throw e;
}
String result = sheet.getRow(rowIx).getCell((short)0).getCellFormula();
if (false) {
System.err.println(result);
}

View File

@ -40,6 +40,7 @@ public class AllUserModelTests {
result.addTestSuite(TestFormulas.class);
result.addTestSuite(TestHSSFCell.class);
result.addTestSuite(TestHSSFClientAnchor.class);
result.addTestSuite(TestHSSFConditionalFormatting.class);
result.addTestSuite(TestHSSFComment.class);
result.addTestSuite(TestHSSFDateUtil.class);
result.addTestSuite(TestHSSFHeaderFooter.class);

View File

@ -26,7 +26,7 @@ import org.apache.poi.hssf.util.Region;
*
* @author Dmitriy Kumshayev
*/
public final class TestHSSFConfditionalFormatting extends TestCase
public final class TestHSSFConditionalFormatting extends TestCase
{
public void testLastAndFirstColumns()
{
@ -55,7 +55,7 @@ public final class TestHSSFConfditionalFormatting extends TestCase
short col = 1;
Region [] regions =
{
new Region(0,col,-1,col)
new Region(0,col,65535,col)
};
sheet.addConditionalFormatting(regions, cfRules);
@ -75,7 +75,7 @@ public final class TestHSSFConfditionalFormatting extends TestCase
assertEquals(1, r.getColumnFrom());
assertEquals(1, r.getColumnTo());
assertEquals(0, r.getRowFrom());
assertEquals(-1, r.getRowTo());
assertEquals(65535, r.getRowTo());
assertEquals(2, cf.getNumberOfRules());

View File

@ -871,4 +871,64 @@ public class TestHSSFSheet
public static void main(java.lang.String[] args) {
junit.textui.TestRunner.run(TestHSSFSheet.class);
}
public void testColumnWidth() throws Exception {
//check we can correctly read column widths from a reference workbook
String filename = System.getProperty("HSSF.testdata.path") + "/colwidth.xls";
HSSFWorkbook wb = new HSSFWorkbook(new FileInputStream(filename));
//reference values
int[] ref = {365, 548, 731, 914, 1097, 1280, 1462, 1645, 1828, 2011, 2194, 2377, 2560, 2742, 2925, 3108, 3291, 3474, 3657};
HSSFSheet sh = wb.getSheetAt(0);
for (char i = 'A'; i <= 'S'; i++) {
int idx = i - 'A';
int w = sh.getColumnWidth((short)idx);
assertEquals(ref[idx], w);
}
//the second sheet doesn't have overridden column widths
sh = wb.getSheetAt(1);
int def_width = sh.getDefaultColumnWidth();
for (char i = 'A'; i <= 'S'; i++) {
int idx = i - 'A';
int w = sh.getColumnWidth((short)idx);
//getDefaultColumnWidth returns width measued in characters
//getColumnWidth returns width measued in 1/256th units
assertEquals(def_width*256, w);
}
//test new workbook
wb = new HSSFWorkbook();
sh = wb.createSheet();
sh.setDefaultColumnWidth((short)10);
assertEquals(10, sh.getDefaultColumnWidth());
assertEquals(256*10, sh.getColumnWidth((short)0));
assertEquals(256*10, sh.getColumnWidth((short)1));
assertEquals(256*10, sh.getColumnWidth((short)2));
for (char i = 'D'; i <= 'F'; i++) {
short w = (short)(256*12);
sh.setColumnWidth((short)i, w);
assertEquals(w, sh.getColumnWidth((short)i));
}
//serialize and read again
ByteArrayOutputStream out = new ByteArrayOutputStream();
wb.write(out);
out.close();
wb = new HSSFWorkbook(new ByteArrayInputStream(out.toByteArray()));
sh = wb.getSheetAt(0);
assertEquals(10, sh.getDefaultColumnWidth());
//columns A-C have default width
assertEquals(256*10, sh.getColumnWidth((short)0));
assertEquals(256*10, sh.getColumnWidth((short)1));
assertEquals(256*10, sh.getColumnWidth((short)2));
//columns D-F have custom wodth
for (char i = 'D'; i <= 'F'; i++) {
short w = (short)(256*12);
assertEquals(w, sh.getColumnWidth((short)i));
}
}
}