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-643624,643626-643653,643655-643669,643671,643673-643830,643832-643833,643835-644342,644344-644472,644474-644508,644510-645347,645349-645351,645353-645559,645561-645565,645568-645951,645953-646193,646195-646311,646313-646404,646406-646665,646667-646853,646855-646869,646871-647151,647153-647185,647187-647579 via svnmerge from

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

........
  r647278 | josh | 2008-04-11 20:36:37 +0100 (Fri, 11 Apr 2008) | 1 line
  
  fixed typo and formatting in class javadoc
........
  r647567 | nick | 2008-04-13 14:16:36 +0100 (Sun, 13 Apr 2008) | 1 line
  
  Various new bits of documentation on embeded files and text extraction
........
  r647574 | nick | 2008-04-13 15:58:27 +0100 (Sun, 13 Apr 2008) | 1 line
  
  Start on a eventusermodel based excel text extractor
........
  r647576 | nick | 2008-04-13 16:09:42 +0100 (Sun, 13 Apr 2008) | 1 line
  
  Finish off eventusermodel based Excel Extractor, and update the xls to csv converter (moved to correct place) based on discoveries for the text extractor
........
  r647577 | nick | 2008-04-13 16:13:17 +0100 (Sun, 13 Apr 2008) | 1 line
  
  Add information of EventBasedExcelExtractor to the documentation
........


git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@647580 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2008-04-13 15:25:33 +00:00
parent 6051677d7b
commit 3e71a7fdc3
10 changed files with 782 additions and 114 deletions

316
KEYS
View File

@ -48,7 +48,7 @@ uid Nick Burch <nick@apache.org>
sub 1024g/5E0E1748 2004-03-24 [expires: 2009-03-23]
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.6 (GNU/Linux)
Version: GnuPG v1.4.7 (GNU/Linux)
mQGiBEBhnKkRBACOPYQoULwS4a37UsNiinwqJ+2XVMal5FQyMOc6hNneyvdau4cO
oSNgdEkNtAN9fecSh06wke9mFBR9iVD4QpCqiRk8s20lr4QAFw4urxbe6iOf/Ytr
@ -58,104 +58,222 @@ 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
vuh58AIoldgrDIeIJA==
=xCFv
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
=j3Fb
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -43,6 +43,7 @@
<menu-item label="HDGF" href="hdgf/index.html"/>
<menu-item label="POI-Ruby" href="poi-ruby.html"/>
<menu-item label="POI-Utils" href="utils/index.html"/>
<menu-item label="Text Extraction" href="text-extraction.html"/>
<menu-item label="Download" href="ext:download"/>
</menu>

View File

@ -30,6 +30,7 @@
<menu label="POIFS">
<menu-item label="Overview" href="index.html"/>
<menu-item label="How To" href="how-to.html"/>
<menu-item label="Embeded Documents" href="embeded.html"/>
<menu-item label="File System Documentation" href="fileformat.html"/>
<menu-item label="Use Cases" href="usecases.html"/>
</menu>

View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
====================================================================
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.
====================================================================
-->
<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "../dtd/document-v11.dtd">
<document>
<header>
<title>Apache POI - POIFS - Documents embeded in other documents</title>
<subtitle>Overview</subtitle>
<authors>
<person name="Nick Burch" email="nick@apache.org"/>
<person name="Yegor Kozlov" email="yegor@apache.org"/>
</authors>
</header>
<body>
<section><title>Overview</title>
<p>It is possible for one OLE 2 based document to have other
OLE 2 documents embeded in it. For example, and Excel file
may have a word document and a powerpoint slideshow
embeded as part of it.</p>
<p>Normally, these other documents are stored in subdirectories
of the OLE 2 (POIFS) filesystem. The exact location of the
embeded documents will vary depending on the type of the
master document, and the exact directory names will differ
each time. To figure out exactly which directory to look
in, you will either need to process the appropriate OLE 2
linking entry in the master document, or simple iterate
over all the directories in the filesystem.</p>
<p>As a general rule, you will find the same OLE 2 entries
in the subdirectories, as you would've found at the root
of the filesystem were a document to not be embeded.</p>
<section><title>Files embeded in Excel</title>
<p>Excel normally stores embeded files in subdirectories
of the filesystem root. Typically these subdirectories
are named starting with MBD, with 8 hex characters following.</p>
</section>
<section><title>Files embeded in Word</title>
<p>Word normally stores embeded files in subdirectories
of the ObjectPool directory, itself a subdirectory of the
filesystem root. Typically these subdirectories and named
starting with an underscore, followed by 10 numbers.</p>
</section>
<section><title>Files embeded in PowerPoint</title>
<p>PowerPoint does not normally store embeded files
in the OLE2 layer. Instead, they are held within records
of the main PowerPoint file. To get at them, you need to
find the appropriate data within the PowerPoint stream,
and work from that.</p>
</section>
</section>
<section><title>Listing POIFS contents</title>
<p>POIFS provides a simple tool for listing the contents of
OLE2 files. This can allow you to see what your POIFS file
contents, and hence if it has any embeded documents in it,
and where.</p>
<p>The tool to use is <em>org.apache.poi.poifs.dev.POIFSLister</em>.
This tool may be run from the command line, and takes a filename
as its parameter. It will print out all the directories and
files contained within the POIFS file.</p>
</section>
<section><title>Opening embeded files</title>
<p>All of the POIDocument classes (HSSFWorkbook, HSLFSlideShow,
HWPFDocument and HDGFDiagram) can either be opened from
a POIFSFileSystem, or from a specific directory within a
POIFSFileSystem. So, to open embeded files, simply locate the
appropriate DirectoryNode that represents the subdirectory
of interest, and pass this + the overall POIFSFileSystem to
the constructor.</p>
<p>I you want to extract the textual contents of the embeded file,
then open the appropriate POIDocument, and then pass this to
the extractor class, instead of simply passing the POIFSFilesystem
to the extractor.</p>
</section>
</body>
</document>

View File

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
====================================================================
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.
====================================================================
-->
<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.3//EN" "./dtd/document-v13.dtd">
<document>
<header>
<title>POI Text Extraction</title>
<authors>
<person id="NB" name="Nick Burch" email="nick@apache.org"/>
</authors>
</header>
<body>
<section><title>Overview</title>
<p>POI provides text extraction for all the supported file
formats. In addition, it provides access to the metadata
associated with a given file, such as title and author.</p>
<p>In addition to providing direct text extraction classes,
POI works closely with the
<link href="http://incubator.apache.org/tika/">Apache Tika</link>
text extraction library. Users may wish to simply utilise
the functionality provided by Tika.</p>
</section>
<section><title>Common functionality</title>
<p>All of the POI text extractors extend from
<em>org.apache.poi.POITextExtractor</em>. This provides a common
method across all extractors, getText(). For many cases, the text
returned will be all you need. However, many extractors do provide
more targetted text extraction methods, so you may wish to use
these in some cases.</p>
<p>All POIFS / OLE 2 based text extractors also extend from
<em>org.apache.poi.POIOLE2TextExtractor</em>. This additionally
provides common methods to get at the <link href="hpfs/">HPFS
document metadata</link>.</p>
<p>All OOXML based text extractors (available in POI 3.5 and later)
also extend from
<em>org.apache.poi.POIOOXMLTextExtractor</em>. This additionally
provides common methods to get at the OOXML metadata.</p>
</section>
<section><title>Text Extractor Factory - POI 3.5 or later</title>
<p>A new class in POI 3.5,
<em>org.apache.poi.extractor.ExtractorFactory</em> provides a
similar function to WorkbookFactory. You simply pass it an
InputStream, a file, a POIFSFileSystem or a OOXML Package. It
figures out the correct text extractor for you, and returns it.</p>
</section>
<section><title>Excel</title>
<p>For .xls files, there is
<em>org.apache.poi.hssf.extractor.ExcelExtractor</em>, which will
return text, optionally with formulas instead of their contents.
Those using POI 3.5 can also use
<em>org.apache.poi.xssf.extractor.XSSFExcelExtractor</em>, to perform
a similar task for .xlsx files.</p>
<p>In addition, there is a second text extractor for .xls files,
<em>org.apache.poi.hssf.extractor.EventBasedExcelExtractor</em>. This
is based on the streaming EventUserModel code, and will generally
deliver a lower memory footprint for extraction. However, it will
have problems correctly outputting more complex formulas, as it
works with records as they pass, and so doesn't have access to all
parts of complex and shared formulas.</p>
</section>
<section><title>Word</title>
<p>For .doc files, in scratchpad there is
<em>org.apache.poi.hwpf.extractor.WordExtractor</em>, which will
return text for your document. Those using POI 3.5 can also use
<em>org.apache.poi.xwpf.extractor.XPFFWordExtractor</em>, to perform
a similar task for .docx files.</p>
</section>
<section><title>PowerPoint</title>
<p>For .ppt files, in scratchpad there is
<em>org.apache.poi.hslf.extractor.PowerPointExtractor</em>, which
will return text for your slideshow, optionally restricted to just
slides text or notes text. Those using POI 3.5 can also use
<em>org.apache.poi.xslf.extractor.XSLFPowerPointExtractor</em>, to
perform a similar task for .pptx files.</p>
</section>
<section><title>Visio</title>
<p>For .vsd files, in scratchpad there is
<em>org.apache.poi.hdgf.extractor.VisioTextExtractor</em>, which
will return text for your file.</p>
</section>
</body>
<footer>
<legal>
Copyright 2005 The Apache Software Foundation or its licensors, as applicable.
$Revision: 639487 $ $Date: 2008-03-20 22:31:15 +0000 (Thu, 20 Mar 2008) $
</legal>
</footer>
</document>

View File

@ -23,11 +23,7 @@ import java.io.PrintStream;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import org.apache.poi.hssf.eventusermodel.FormatTrackingHSSFListener;
import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
@ -36,11 +32,10 @@ import org.apache.poi.hssf.eventusermodel.HSSFRequest;
import org.apache.poi.hssf.eventusermodel.MissingRecordAwareHSSFListener;
import org.apache.poi.hssf.eventusermodel.dummyrecord.LastCellOfRowDummyRecord;
import org.apache.poi.hssf.eventusermodel.dummyrecord.MissingCellDummyRecord;
import org.apache.poi.hssf.model.FormulaParser;
import org.apache.poi.hssf.record.BlankRecord;
import org.apache.poi.hssf.record.BoolErrRecord;
import org.apache.poi.hssf.record.CellValueRecordInterface;
import org.apache.poi.hssf.record.ExtendedFormatRecord;
import org.apache.poi.hssf.record.FormatRecord;
import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.LabelRecord;
import org.apache.poi.hssf.record.LabelSSTRecord;
@ -49,7 +44,7 @@ import org.apache.poi.hssf.record.NumberRecord;
import org.apache.poi.hssf.record.RKRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.SSTRecord;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.record.StringRecord;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
@ -73,6 +68,11 @@ public class XLS2CSVmra implements HSSFListener {
private SSTRecord sstRecord;
private FormatTrackingHSSFListener formatListener;
// For handling formulas with string results
private int nextRow;
private int nextColumn;
private boolean outputNextStringRecord;
/**
* Creates a new XLS -> CSV converter
* @param fs The POIFSFileSystem to process
@ -142,6 +142,7 @@ public class XLS2CSVmra implements HSSFListener {
thisColumn = berec.getColumn();
thisStr = "";
break;
case FormulaRecord.sid:
FormulaRecord frec = (FormulaRecord) record;
@ -149,12 +150,31 @@ public class XLS2CSVmra implements HSSFListener {
thisColumn = frec.getColumn();
if(outputFormulaValues) {
thisStr = formatNumberDateCell(frec, frec.getValue());
if(Double.isNaN( frec.getValue() )) {
// Formula result is a string
// This is stored in the next record
outputNextStringRecord = true;
nextRow = frec.getRow();
nextColumn = frec.getColumn();
} else {
// TODO: Output the formula string
thisStr = '"' + frec.toString() + '"';
thisStr = formatNumberDateCell(frec, frec.getValue());
}
} else {
thisStr = '"' +
FormulaParser.toFormulaString(null, frec.getParsedExpression()) + '"';
}
break;
case StringRecord.sid:
if(outputNextStringRecord) {
// String for formula
StringRecord srec = (StringRecord)record;
thisStr = srec.getString();
thisRow = nextRow;
thisColumn = nextColumn;
outputNextStringRecord = false;
}
break;
case LabelRecord.sid:
LabelRecord lrec = (LabelRecord) record;

View File

@ -0,0 +1,276 @@
/* ====================================================================
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.extractor;
import java.io.IOException;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.poi.POIOLE2TextExtractor;
import org.apache.poi.hpsf.DocumentSummaryInformation;
import org.apache.poi.hpsf.SummaryInformation;
import org.apache.poi.hssf.eventusermodel.FormatTrackingHSSFListener;
import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
import org.apache.poi.hssf.eventusermodel.HSSFListener;
import org.apache.poi.hssf.eventusermodel.HSSFRequest;
import org.apache.poi.hssf.model.FormulaParser;
import org.apache.poi.hssf.record.BOFRecord;
import org.apache.poi.hssf.record.BoundSheetRecord;
import org.apache.poi.hssf.record.CellValueRecordInterface;
import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.LabelRecord;
import org.apache.poi.hssf.record.LabelSSTRecord;
import org.apache.poi.hssf.record.NoteRecord;
import org.apache.poi.hssf.record.NumberRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.SSTRecord;
import org.apache.poi.hssf.record.StringRecord;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
/**
* A text extractor for Excel files, that is based
* on the hssf eventusermodel api.
* It will typically use less memory than
* {@link ExcelExtractor}, but may not provide
* the same richness of formatting.
* Returns the textual content of the file, suitable for
* indexing by something like Lucene, but not really
* intended for display to the user.
* To turn an excel file into a CSV or similar, then see
* the XLS2CSVmra example
* @see org.apache.poi.hssf.eventusermodel.examples.XLS2CSVmra
*/
public class EventBasedExcelExtractor extends POIOLE2TextExtractor {
private POIFSFileSystem fs;
private boolean includeSheetNames = true;
private boolean formulasNotResults = false;
public EventBasedExcelExtractor(POIFSFileSystem fs) throws IOException {
super(null);
this.fs = fs;
}
/**
* Would return the document information metadata for the document,
* if we supported it
*/
public DocumentSummaryInformation getDocSummaryInformation() {
throw new IllegalStateException("Metadata extraction not supported in streaming mode, please use ExcelExtractor");
}
/**
* Would return the summary information metadata for the document,
* if we supported it
*/
public SummaryInformation getSummaryInformation() {
throw new IllegalStateException("Metadata extraction not supported in streaming mode, please use ExcelExtractor");
}
/**
* Should sheet names be included? Default is true
*/
public void setIncludeSheetNames(boolean includeSheetNames) {
this.includeSheetNames = includeSheetNames;
}
/**
* Should we return the formula itself, and not
* the result it produces? Default is false
*/
public void setFormulasNotResults(boolean formulasNotResults) {
this.formulasNotResults = formulasNotResults;
}
/**
* Retreives the text contents of the file
*/
public String getText() {
String text = null;
try {
TextListener tl = triggerExtraction();
text = tl.text.toString();
if(! text.endsWith("\n")) {
text = text + "\n";
}
} catch(IOException e) {
throw new RuntimeException(e);
}
return text;
}
private TextListener triggerExtraction() throws IOException {
TextListener tl = new TextListener();
FormatTrackingHSSFListener ft = new FormatTrackingHSSFListener(tl);
tl.ft = ft;
// Register and process
HSSFEventFactory factory = new HSSFEventFactory();
HSSFRequest request = new HSSFRequest();
request.addListenerForAllRecords(ft);
factory.processWorkbookEvents(request, fs);
return tl;
}
private class TextListener implements HSSFListener {
private FormatTrackingHSSFListener ft;
private SSTRecord sstRecord;
private List sheetNames = new ArrayList();
private StringBuffer text = new StringBuffer();
private int sheetNum = -1;
private int rowNum;
private boolean outputNextStringValue = false;
private int nextRow = -1;
public void processRecord(Record record) {
String thisText = null;
int thisRow = -1;
switch(record.getSid()) {
case BoundSheetRecord.sid:
BoundSheetRecord sr = (BoundSheetRecord)record;
sheetNames.add(sr.getSheetname());
break;
case BOFRecord.sid:
BOFRecord bof = (BOFRecord)record;
if(bof.getType() == BOFRecord.TYPE_WORKSHEET) {
sheetNum++;
rowNum = -1;
if(includeSheetNames) {
if(text.length() > 0) text.append("\n");
text.append(sheetNames.get(sheetNum));
}
}
break;
case SSTRecord.sid:
sstRecord = (SSTRecord)record;
break;
case FormulaRecord.sid:
FormulaRecord frec = (FormulaRecord) record;
thisRow = frec.getRow();
if(formulasNotResults) {
thisText = FormulaParser.toFormulaString(null, frec.getParsedExpression());
} else {
if(Double.isNaN( frec.getValue() )) {
// Formula result is a string
// This is stored in the next record
outputNextStringValue = true;
nextRow = frec.getRow();
} else {
thisText = formatNumberDateCell(frec, frec.getValue());
}
}
break;
case StringRecord.sid:
if(outputNextStringValue) {
// String for formula
StringRecord srec = (StringRecord)record;
thisText = srec.getString();
thisRow = nextRow;
outputNextStringValue = false;
}
break;
case LabelRecord.sid:
LabelRecord lrec = (LabelRecord) record;
thisRow = lrec.getRow();
thisText = lrec.getValue();
break;
case LabelSSTRecord.sid:
LabelSSTRecord lsrec = (LabelSSTRecord) record;
thisRow = lsrec.getRow();
if(sstRecord == null) {
throw new IllegalStateException("No SST record found");
}
thisText = sstRecord.getString(lsrec.getSSTIndex()).toString();
break;
case NoteRecord.sid:
NoteRecord nrec = (NoteRecord) record;
thisRow = nrec.getRow();
// TODO: Find object to match nrec.getShapeId()
break;
case NumberRecord.sid:
NumberRecord numrec = (NumberRecord) record;
thisRow = numrec.getRow();
thisText = formatNumberDateCell(numrec, numrec.getValue());
break;
default:
break;
}
if(thisText != null) {
if(thisRow != rowNum) {
rowNum = thisRow;
if(text.length() > 0)
text.append("\n");
} else {
text.append("\t");
}
text.append(thisText);
}
}
/**
* Formats a number or date cell, be that a real number, or the
* answer to a formula
*/
private String formatNumberDateCell(CellValueRecordInterface cell, double value) {
// Get the built in format, if there is one
int formatIndex = ft.getFormatIndex(cell);
String formatString = ft.getFormatString(cell);
if(formatString == null) {
return Double.toString(value);
} else {
// Is it a date?
if(HSSFDateUtil.isADateFormat(formatIndex,formatString) &&
HSSFDateUtil.isValidExcelDate(value)) {
// Java wants M not m for month
formatString = formatString.replace('m','M');
// Change \- into -, if it's there
formatString = formatString.replaceAll("\\\\-","-");
// Format as a date
Date d = HSSFDateUtil.getJavaDate(value, false);
DateFormat df = new SimpleDateFormat(formatString);
return df.format(d);
} else {
if(formatString == "General") {
// Some sort of wierd default
return Double.toString(value);
}
// Format as a number
DecimalFormat df = new DecimalFormat(formatString);
return df.format(value);
}
}
}
}
}

View File

@ -25,15 +25,15 @@ import org.apache.poi.hssf.record.formula.eval.OperandResolver;
import org.apache.poi.hssf.record.formula.eval.ValueEval;
import org.apache.poi.hssf.record.formula.functions.LookupUtils.ValueVector;
/**
* Implementation of the VLOOKUP() function.<p/>
* Implementation of the HLOOKUP() function.<p/>
*
* HLOOKUP finds a column in a lookup table by the first row value and returns the value from another row.
* HLOOKUP finds a column in a lookup table by the first row value and returns the value from another row.<br/>
*
* <b>Syntax</b>:<br/>
* <b>HLOOKUP</b>(<b>lookup_value</b>, <b>table_array</b>, <b>row_index_num</b>, range_lookup)<p/>
*
* <b>lookup_value</b> The value to be found in the first column of the table array.<br/>
* <b>table_array</> An area reference for the lookup data. <br/>
* <b>table_array</b> An area reference for the lookup data. <br/>
* <b>row_index_num</b> a 1 based index specifying which row value of the lookup data will be returned.<br/>
* <b>range_lookup</b> If TRUE (default), HLOOKUP finds the largest value less than or equal to
* the lookup_value. If FALSE, only exact matches will be considered<br/>

View File

@ -27,13 +27,13 @@ import org.apache.poi.hssf.record.formula.functions.LookupUtils.ValueVector;
/**
* Implementation of the VLOOKUP() function.<p/>
*
* VLOOKUP finds a row in a lookup table by the first column value and returns the value from another column.
* VLOOKUP finds a row in a lookup table by the first column value and returns the value from another column.<br/>
*
* <b>Syntax</b>:<br/>
* <b>VLOOKUP</b>(<b>lookup_value</b>, <b>table_array</b>, <b>col_index_num</b>, range_lookup)<p/>
*
* <b>lookup_value</b> The value to be found in the first column of the table array.<br/>
* <b>table_array</> An area reference for the lookup data. <br/>
* <b>table_array</b> An area reference for the lookup data. <br/>
* <b>col_index_num</b> a 1 based index specifying which column value of the lookup data will be returned.<br/>
* <b>range_lookup</b> If TRUE (default), VLOOKUP finds the largest value less than or equal to
* the lookup_value. If FALSE, only exact matches will be considered<br/>

View File

@ -122,6 +122,50 @@ public final class TestExcelExtractor extends TestCase {
assertEquals("Sheet1\nUPPER(\"xyz\")\nSheet2\nSheet3\n", extractor.getText());
}
public void testEventExtractor() throws Exception {
EventBasedExcelExtractor extractor;
// First up, a simple file with string
// based formulas in it
extractor = new EventBasedExcelExtractor(
new POIFSFileSystem(
HSSFTestDataSamples.openSampleFileStream("SimpleWithFormula.xls")
)
);
extractor.setIncludeSheetNames(true);
String text = extractor.getText();
assertEquals("Sheet1\nreplaceme\nreplaceme\nreplacemereplaceme\nSheet2\nSheet3\n", text);
extractor.setIncludeSheetNames(false);
extractor.setFormulasNotResults(true);
text = extractor.getText();
assertEquals("replaceme\nreplaceme\nCONCATENATE(A1,A2)\n", text);
// Now, a slightly longer file with numeric formulas
extractor = new EventBasedExcelExtractor(
new POIFSFileSystem(
HSSFTestDataSamples.openSampleFileStream("sumifformula.xls")
)
);
extractor.setIncludeSheetNames(false);
extractor.setFormulasNotResults(true);
text = extractor.getText();
assertEquals(
"1000.0\t1.0\tSUMIF(A1:A5,\">4000\",B1:B5)\n" +
"2000.0\t2.0\n" +
"3000.0\t3.0\n" +
"4000.0\t4.0\n" +
"5000.0\t5.0\n",
text
);
}
/**
* Embded in a non-excel file
*/