Remove any reading/writing to files code from HSSFWorkbook

This commit is contained in:
Travis Burtrum 2019-03-26 14:55:35 -04:00
parent 640c88d640
commit 463e00558d
17 changed files with 9 additions and 3434 deletions

View File

@ -1,164 +0,0 @@
/*
* ====================================================================
* 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.dev;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.hssf.model.InternalWorkbook;
import org.apache.poi.hssf.record.DrawingGroupRecord;
import org.apache.poi.hssf.usermodel.HSSFPatriarch;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.util.StringUtil;
/**
* Utility for representing drawings contained in a binary Excel file as a XML tree
*/
public class BiffDrawingToXml {
private static final String SHEET_NAME_PARAM = "-sheet-name";
private static final String SHEET_INDEXES_PARAM = "-sheet-indexes";
private static final String EXCLUDE_WORKBOOK_RECORDS = "-exclude-workbook";
private static int getAttributeIndex(String attribute, String[] params) {
for (int i = 0; i < params.length; i++) {
String param = params[i];
if (attribute.equals(param)) {
return i;
}
}
return -1;
}
private static boolean isExcludeWorkbookRecords(String[] params) {
return -1 != getAttributeIndex(EXCLUDE_WORKBOOK_RECORDS, params);
}
private static List<Integer> getIndexesByName(String[] params, HSSFWorkbook workbook) {
List<Integer> list = new ArrayList<Integer>();
int pos = getAttributeIndex(SHEET_NAME_PARAM, params);
if (-1 != pos) {
if (pos >= params.length) {
throw new IllegalArgumentException("sheet name param value was not specified");
}
String sheetName = params[pos + 1];
int sheetPos = workbook.getSheetIndex(sheetName);
if (-1 == sheetPos){
throw new IllegalArgumentException("specified sheet name has not been found in xls file");
}
list.add(sheetPos);
}
return list;
}
private static List<Integer> getIndexesByIdArray(String[] params) {
List<Integer> list = new ArrayList<Integer>();
int pos = getAttributeIndex(SHEET_INDEXES_PARAM, params);
if (-1 != pos) {
if (pos >= params.length) {
throw new IllegalArgumentException("sheet list value was not specified");
}
String sheetParam = params[pos + 1];
String[] sheets = sheetParam.split(",");
for (String sheet : sheets) {
list.add(Integer.parseInt(sheet));
}
}
return list;
}
private static List<Integer> getSheetsIndexes(String[] params, HSSFWorkbook workbook) {
List<Integer> list = new ArrayList<Integer>();
list.addAll(getIndexesByIdArray(params));
list.addAll(getIndexesByName(params, workbook));
if (0 == list.size()) {
int size = workbook.getNumberOfSheets();
for (int i = 0; i < size; i++) {
list.add(i);
}
}
return list;
}
private static String getInputFileName(String[] params) {
return params[params.length - 1];
}
private static String getOutputFileName(String input) {
if (input.contains("xls")) {
return input.replace(".xls", ".xml");
}
return input + ".xml";
}
public static void main(String[] params) throws IOException {
if (0 == params.length) {
System.out.println("Usage: BiffDrawingToXml [options] inputWorkbook");
System.out.println("Options:");
System.out.println(" -exclude-workbook exclude workbook-level records");
System.out.println(" -sheet-indexes <indexes> output sheets with specified indexes");
System.out.println(" -sheet-namek <names> output sheets with specified name");
return;
}
String input = getInputFileName(params);
FileInputStream inp = new FileInputStream(input);
String output = getOutputFileName(input);
FileOutputStream outputStream = new FileOutputStream(output);
writeToFile(outputStream, inp, isExcludeWorkbookRecords(params), params);
inp.close();
outputStream.close();
}
public static void writeToFile(OutputStream fos, InputStream xlsWorkbook, boolean excludeWorkbookRecords, String[] params) throws IOException {
HSSFWorkbook workbook = new HSSFWorkbook(xlsWorkbook);
InternalWorkbook internalWorkbook = workbook.getInternalWorkbook();
DrawingGroupRecord r = (DrawingGroupRecord) internalWorkbook.findFirstRecordBySid(DrawingGroupRecord.sid);
StringBuilder builder = new StringBuilder();
builder.append("<workbook>\n");
String tab = "\t";
if (!excludeWorkbookRecords && r != null) {
r.decode();
List<EscherRecord> escherRecords = r.getEscherRecords();
for (EscherRecord record : escherRecords) {
builder.append(record.toXml(tab));
}
}
List<Integer> sheets = getSheetsIndexes(params, workbook);
for (Integer i : sheets) {
HSSFPatriarch p = workbook.getSheetAt(i).getDrawingPatriarch();
if(p != null ) {
builder.append(tab).append("<sheet").append(i).append(">\n");
builder.append(p.getBoundAggregate().toXml(tab + "\t"));
builder.append(tab).append("</sheet").append(i).append(">\n");
}
}
builder.append("</workbook>\n");
fos.write(builder.toString().getBytes(StringUtil.UTF8));
fos.close();
workbook.close();
}
}

View File

@ -1,876 +0,0 @@
/* ====================================================================
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.dev;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.hssf.record.ArrayRecord;
import org.apache.poi.hssf.record.AutoFilterInfoRecord;
import org.apache.poi.hssf.record.BOFRecord;
import org.apache.poi.hssf.record.BackupRecord;
import org.apache.poi.hssf.record.BlankRecord;
import org.apache.poi.hssf.record.BookBoolRecord;
import org.apache.poi.hssf.record.BoolErrRecord;
import org.apache.poi.hssf.record.BottomMarginRecord;
import org.apache.poi.hssf.record.BoundSheetRecord;
import org.apache.poi.hssf.record.CFHeader12Record;
import org.apache.poi.hssf.record.CFHeaderRecord;
import org.apache.poi.hssf.record.CFRule12Record;
import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.CalcCountRecord;
import org.apache.poi.hssf.record.CalcModeRecord;
import org.apache.poi.hssf.record.CodepageRecord;
import org.apache.poi.hssf.record.ColumnInfoRecord;
import org.apache.poi.hssf.record.ContinueRecord;
import org.apache.poi.hssf.record.CountryRecord;
import org.apache.poi.hssf.record.DBCellRecord;
import org.apache.poi.hssf.record.DConRefRecord;
import org.apache.poi.hssf.record.DSFRecord;
import org.apache.poi.hssf.record.DVALRecord;
import org.apache.poi.hssf.record.DVRecord;
import org.apache.poi.hssf.record.DateWindow1904Record;
import org.apache.poi.hssf.record.DefaultColWidthRecord;
import org.apache.poi.hssf.record.DefaultRowHeightRecord;
import org.apache.poi.hssf.record.DeltaRecord;
import org.apache.poi.hssf.record.DimensionsRecord;
import org.apache.poi.hssf.record.DrawingGroupRecord;
import org.apache.poi.hssf.record.DrawingRecordForBiffViewer;
import org.apache.poi.hssf.record.DrawingSelectionRecord;
import org.apache.poi.hssf.record.EOFRecord;
import org.apache.poi.hssf.record.ExtSSTRecord;
import org.apache.poi.hssf.record.ExtendedFormatRecord;
import org.apache.poi.hssf.record.ExternSheetRecord;
import org.apache.poi.hssf.record.ExternalNameRecord;
import org.apache.poi.hssf.record.FeatHdrRecord;
import org.apache.poi.hssf.record.FeatRecord;
import org.apache.poi.hssf.record.FilePassRecord;
import org.apache.poi.hssf.record.FileSharingRecord;
import org.apache.poi.hssf.record.FnGroupCountRecord;
import org.apache.poi.hssf.record.FontRecord;
import org.apache.poi.hssf.record.FooterRecord;
import org.apache.poi.hssf.record.FormatRecord;
import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.GridsetRecord;
import org.apache.poi.hssf.record.GutsRecord;
import org.apache.poi.hssf.record.HCenterRecord;
import org.apache.poi.hssf.record.HeaderRecord;
import org.apache.poi.hssf.record.HideObjRecord;
import org.apache.poi.hssf.record.HorizontalPageBreakRecord;
import org.apache.poi.hssf.record.HyperlinkRecord;
import org.apache.poi.hssf.record.IndexRecord;
import org.apache.poi.hssf.record.InterfaceEndRecord;
import org.apache.poi.hssf.record.InterfaceHdrRecord;
import org.apache.poi.hssf.record.IterationRecord;
import org.apache.poi.hssf.record.LabelRecord;
import org.apache.poi.hssf.record.LabelSSTRecord;
import org.apache.poi.hssf.record.LeftMarginRecord;
import org.apache.poi.hssf.record.MMSRecord;
import org.apache.poi.hssf.record.MergeCellsRecord;
import org.apache.poi.hssf.record.MulBlankRecord;
import org.apache.poi.hssf.record.MulRKRecord;
import org.apache.poi.hssf.record.NameCommentRecord;
import org.apache.poi.hssf.record.NameRecord;
import org.apache.poi.hssf.record.NoteRecord;
import org.apache.poi.hssf.record.NumberRecord;
import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.hssf.record.PaletteRecord;
import org.apache.poi.hssf.record.PaneRecord;
import org.apache.poi.hssf.record.PasswordRecord;
import org.apache.poi.hssf.record.PasswordRev4Record;
import org.apache.poi.hssf.record.PrecisionRecord;
import org.apache.poi.hssf.record.PrintGridlinesRecord;
import org.apache.poi.hssf.record.PrintHeadersRecord;
import org.apache.poi.hssf.record.PrintSetupRecord;
import org.apache.poi.hssf.record.ProtectRecord;
import org.apache.poi.hssf.record.ProtectionRev4Record;
import org.apache.poi.hssf.record.RKRecord;
import org.apache.poi.hssf.record.RecalcIdRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.RecordInputStream.LeftoverDataException;
import org.apache.poi.hssf.record.RefModeRecord;
import org.apache.poi.hssf.record.RefreshAllRecord;
import org.apache.poi.hssf.record.RightMarginRecord;
import org.apache.poi.hssf.record.RowRecord;
import org.apache.poi.hssf.record.SCLRecord;
import org.apache.poi.hssf.record.SSTRecord;
import org.apache.poi.hssf.record.SaveRecalcRecord;
import org.apache.poi.hssf.record.SelectionRecord;
import org.apache.poi.hssf.record.SharedFormulaRecord;
import org.apache.poi.hssf.record.StringRecord;
import org.apache.poi.hssf.record.StyleRecord;
import org.apache.poi.hssf.record.SupBookRecord;
import org.apache.poi.hssf.record.TabIdRecord;
import org.apache.poi.hssf.record.TableRecord;
import org.apache.poi.hssf.record.TableStylesRecord;
import org.apache.poi.hssf.record.TextObjectRecord;
import org.apache.poi.hssf.record.TopMarginRecord;
import org.apache.poi.hssf.record.UncalcedRecord;
import org.apache.poi.hssf.record.UnknownRecord;
import org.apache.poi.hssf.record.UseSelFSRecord;
import org.apache.poi.hssf.record.VCenterRecord;
import org.apache.poi.hssf.record.VerticalPageBreakRecord;
import org.apache.poi.hssf.record.WSBoolRecord;
import org.apache.poi.hssf.record.WindowOneRecord;
import org.apache.poi.hssf.record.WindowProtectRecord;
import org.apache.poi.hssf.record.WindowTwoRecord;
import org.apache.poi.hssf.record.WriteAccessRecord;
import org.apache.poi.hssf.record.WriteProtectRecord;
import org.apache.poi.hssf.record.chart.AreaFormatRecord;
import org.apache.poi.hssf.record.chart.AreaRecord;
import org.apache.poi.hssf.record.chart.AxisLineFormatRecord;
import org.apache.poi.hssf.record.chart.AxisOptionsRecord;
import org.apache.poi.hssf.record.chart.AxisParentRecord;
import org.apache.poi.hssf.record.chart.AxisRecord;
import org.apache.poi.hssf.record.chart.AxisUsedRecord;
import org.apache.poi.hssf.record.chart.BarRecord;
import org.apache.poi.hssf.record.chart.BeginRecord;
import org.apache.poi.hssf.record.chart.CatLabRecord;
import org.apache.poi.hssf.record.chart.CategorySeriesAxisRecord;
import org.apache.poi.hssf.record.chart.ChartEndBlockRecord;
import org.apache.poi.hssf.record.chart.ChartEndObjectRecord;
import org.apache.poi.hssf.record.chart.ChartFRTInfoRecord;
import org.apache.poi.hssf.record.chart.ChartFormatRecord;
import org.apache.poi.hssf.record.chart.ChartRecord;
import org.apache.poi.hssf.record.chart.ChartStartBlockRecord;
import org.apache.poi.hssf.record.chart.ChartStartObjectRecord;
import org.apache.poi.hssf.record.chart.DatRecord;
import org.apache.poi.hssf.record.chart.DataFormatRecord;
import org.apache.poi.hssf.record.chart.DefaultDataLabelTextPropertiesRecord;
import org.apache.poi.hssf.record.chart.EndRecord;
import org.apache.poi.hssf.record.chart.FontBasisRecord;
import org.apache.poi.hssf.record.chart.FontIndexRecord;
import org.apache.poi.hssf.record.chart.FrameRecord;
import org.apache.poi.hssf.record.chart.LegendRecord;
import org.apache.poi.hssf.record.chart.LineFormatRecord;
import org.apache.poi.hssf.record.chart.LinkedDataRecord;
import org.apache.poi.hssf.record.chart.ObjectLinkRecord;
import org.apache.poi.hssf.record.chart.PlotAreaRecord;
import org.apache.poi.hssf.record.chart.PlotGrowthRecord;
import org.apache.poi.hssf.record.chart.SeriesIndexRecord;
import org.apache.poi.hssf.record.chart.SeriesListRecord;
import org.apache.poi.hssf.record.chart.SeriesRecord;
import org.apache.poi.hssf.record.chart.SeriesTextRecord;
import org.apache.poi.hssf.record.chart.SeriesToChartGroupRecord;
import org.apache.poi.hssf.record.chart.SheetPropertiesRecord;
import org.apache.poi.hssf.record.chart.TextRecord;
import org.apache.poi.hssf.record.chart.TickRecord;
import org.apache.poi.hssf.record.chart.UnitsRecord;
import org.apache.poi.hssf.record.chart.ValueRangeRecord;
import org.apache.poi.hssf.record.pivottable.DataItemRecord;
import org.apache.poi.hssf.record.pivottable.ExtendedPivotTableViewFieldsRecord;
import org.apache.poi.hssf.record.pivottable.PageItemRecord;
import org.apache.poi.hssf.record.pivottable.StreamIDRecord;
import org.apache.poi.hssf.record.pivottable.ViewDefinitionRecord;
import org.apache.poi.hssf.record.pivottable.ViewFieldsRecord;
import org.apache.poi.hssf.record.pivottable.ViewSourceRecord;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.StringUtil;
import org.apache.poi.util.SuppressForbidden;
/**
* Utility for reading in BIFF8 records and displaying data from them.
* @see #main
*/
public final class BiffViewer {
private static final char[] NEW_LINE_CHARS = System.getProperty("line.separator").toCharArray();
private static final POILogger logger = POILogFactory.getLogger(BiffViewer.class);
private BiffViewer() {
// no instances of this class
}
/**
* Create an array of records from an input stream
*
* @param is the InputStream from which the records will be obtained
* @param ps the PrintWriter to output the record data
* @param recListener the record listener to notify about read records
* @param dumpInterpretedRecords if {@code true}, the read records will be written to the PrintWriter
*
* @return an array of Records created from the InputStream
* @exception org.apache.poi.util.RecordFormatException on error processing the InputStream
*/
public static Record[] createRecords(InputStream is, PrintWriter ps, BiffRecordListener recListener, boolean dumpInterpretedRecords)
throws org.apache.poi.util.RecordFormatException {
List<Record> temp = new ArrayList<Record>();
RecordInputStream recStream = new RecordInputStream(is);
while (true) {
boolean hasNext;
try {
hasNext = recStream.hasNextRecord();
} catch (LeftoverDataException e) {
logger.log(POILogger.ERROR, "Discarding " + recStream.remaining() + " bytes and continuing", e);
recStream.readRemainder();
hasNext = recStream.hasNextRecord();
}
if (!hasNext) {
break;
}
recStream.nextRecord();
if (recStream.getSid() == 0) {
continue;
}
Record record;
if (dumpInterpretedRecords) {
record = createRecord (recStream);
if (record.getSid() == ContinueRecord.sid) {
continue;
}
temp.add(record);
for (String header : recListener.getRecentHeaders()) {
ps.println(header);
}
ps.print(record.toString());
} else {
recStream.readRemainder();
}
ps.println();
}
Record[] result = new Record[temp.size()];
temp.toArray(result);
return result;
}
/**
* Essentially a duplicate of RecordFactory. Kept separate as not to screw
* up non-debug operations.
*
*/
private static Record createRecord(RecordInputStream in) {
switch (in.getSid()) {
case AreaFormatRecord.sid: return new AreaFormatRecord(in);
case AreaRecord.sid: return new AreaRecord(in);
case ArrayRecord.sid: return new ArrayRecord(in);
case AxisLineFormatRecord.sid: return new AxisLineFormatRecord(in);
case AxisOptionsRecord.sid: return new AxisOptionsRecord(in);
case AxisParentRecord.sid: return new AxisParentRecord(in);
case AxisRecord.sid: return new AxisRecord(in);
case AxisUsedRecord.sid: return new AxisUsedRecord(in);
case AutoFilterInfoRecord.sid: return new AutoFilterInfoRecord(in);
case BOFRecord.sid: return new BOFRecord(in);
case BackupRecord.sid: return new BackupRecord(in);
case BarRecord.sid: return new BarRecord(in);
case BeginRecord.sid: return new BeginRecord(in);
case BlankRecord.sid: return new BlankRecord(in);
case BookBoolRecord.sid: return new BookBoolRecord(in);
case BoolErrRecord.sid: return new BoolErrRecord(in);
case BottomMarginRecord.sid: return new BottomMarginRecord(in);
case BoundSheetRecord.sid: return new BoundSheetRecord(in);
case CFHeaderRecord.sid: return new CFHeaderRecord(in);
case CFHeader12Record.sid: return new CFHeader12Record(in);
case CFRuleRecord.sid: return new CFRuleRecord(in);
case CFRule12Record.sid: return new CFRule12Record(in);
// TODO Add CF Ex, and remove from UnknownRecord
case CalcCountRecord.sid: return new CalcCountRecord(in);
case CalcModeRecord.sid: return new CalcModeRecord(in);
case CategorySeriesAxisRecord.sid:return new CategorySeriesAxisRecord(in);
case ChartFormatRecord.sid: return new ChartFormatRecord(in);
case ChartRecord.sid: return new ChartRecord(in);
case CodepageRecord.sid: return new CodepageRecord(in);
case ColumnInfoRecord.sid: return new ColumnInfoRecord(in);
case ContinueRecord.sid: return new ContinueRecord(in);
case CountryRecord.sid: return new CountryRecord(in);
case DBCellRecord.sid: return new DBCellRecord(in);
case DSFRecord.sid: return new DSFRecord(in);
case DatRecord.sid: return new DatRecord(in);
case DataFormatRecord.sid: return new DataFormatRecord(in);
case DateWindow1904Record.sid: return new DateWindow1904Record(in);
case DConRefRecord.sid: return new DConRefRecord(in);
case DefaultColWidthRecord.sid: return new DefaultColWidthRecord(in);
case DefaultDataLabelTextPropertiesRecord.sid: return new DefaultDataLabelTextPropertiesRecord(in);
case DefaultRowHeightRecord.sid: return new DefaultRowHeightRecord(in);
case DeltaRecord.sid: return new DeltaRecord(in);
case DimensionsRecord.sid: return new DimensionsRecord(in);
case DrawingGroupRecord.sid: return new DrawingGroupRecord(in);
case DrawingRecordForBiffViewer.sid: return new DrawingRecordForBiffViewer(in);
case DrawingSelectionRecord.sid: return new DrawingSelectionRecord(in);
case DVRecord.sid: return new DVRecord(in);
case DVALRecord.sid: return new DVALRecord(in);
case EOFRecord.sid: return new EOFRecord(in);
case EndRecord.sid: return new EndRecord(in);
case ExtSSTRecord.sid: return new ExtSSTRecord(in);
case ExtendedFormatRecord.sid: return new ExtendedFormatRecord(in);
case ExternSheetRecord.sid: return new ExternSheetRecord(in);
case ExternalNameRecord.sid: return new ExternalNameRecord(in);
case FeatRecord.sid: return new FeatRecord(in);
case FeatHdrRecord.sid: return new FeatHdrRecord(in);
case FilePassRecord.sid: return new FilePassRecord(in);
case FileSharingRecord.sid: return new FileSharingRecord(in);
case FnGroupCountRecord.sid: return new FnGroupCountRecord(in);
case FontBasisRecord.sid: return new FontBasisRecord(in);
case FontIndexRecord.sid: return new FontIndexRecord(in);
case FontRecord.sid: return new FontRecord(in);
case FooterRecord.sid: return new FooterRecord(in);
case FormatRecord.sid: return new FormatRecord(in);
case FormulaRecord.sid: return new FormulaRecord(in);
case FrameRecord.sid: return new FrameRecord(in);
case GridsetRecord.sid: return new GridsetRecord(in);
case GutsRecord.sid: return new GutsRecord(in);
case HCenterRecord.sid: return new HCenterRecord(in);
case HeaderRecord.sid: return new HeaderRecord(in);
case HideObjRecord.sid: return new HideObjRecord(in);
case HorizontalPageBreakRecord.sid: return new HorizontalPageBreakRecord(in);
case HyperlinkRecord.sid: return new HyperlinkRecord(in);
case IndexRecord.sid: return new IndexRecord(in);
case InterfaceEndRecord.sid: return InterfaceEndRecord.create(in);
case InterfaceHdrRecord.sid: return new InterfaceHdrRecord(in);
case IterationRecord.sid: return new IterationRecord(in);
case LabelRecord.sid: return new LabelRecord(in);
case LabelSSTRecord.sid: return new LabelSSTRecord(in);
case LeftMarginRecord.sid: return new LeftMarginRecord(in);
case LegendRecord.sid: return new LegendRecord(in);
case LineFormatRecord.sid: return new LineFormatRecord(in);
case LinkedDataRecord.sid: return new LinkedDataRecord(in);
case MMSRecord.sid: return new MMSRecord(in);
case MergeCellsRecord.sid: return new MergeCellsRecord(in);
case MulBlankRecord.sid: return new MulBlankRecord(in);
case MulRKRecord.sid: return new MulRKRecord(in);
case NameRecord.sid: return new NameRecord(in);
case NameCommentRecord.sid: return new NameCommentRecord(in);
case NoteRecord.sid: return new NoteRecord(in);
case NumberRecord.sid: return new NumberRecord(in);
case ObjRecord.sid: return new ObjRecord(in);
case ObjectLinkRecord.sid: return new ObjectLinkRecord(in);
case PaletteRecord.sid: return new PaletteRecord(in);
case PaneRecord.sid: return new PaneRecord(in);
case PasswordRecord.sid: return new PasswordRecord(in);
case PasswordRev4Record.sid: return new PasswordRev4Record(in);
case PlotAreaRecord.sid: return new PlotAreaRecord(in);
case PlotGrowthRecord.sid: return new PlotGrowthRecord(in);
case PrecisionRecord.sid: return new PrecisionRecord(in);
case PrintGridlinesRecord.sid: return new PrintGridlinesRecord(in);
case PrintHeadersRecord.sid: return new PrintHeadersRecord(in);
case PrintSetupRecord.sid: return new PrintSetupRecord(in);
case ProtectRecord.sid: return new ProtectRecord(in);
case ProtectionRev4Record.sid: return new ProtectionRev4Record(in);
case RKRecord.sid: return new RKRecord(in);
case RecalcIdRecord.sid: return new RecalcIdRecord(in);
case RefModeRecord.sid: return new RefModeRecord(in);
case RefreshAllRecord.sid: return new RefreshAllRecord(in);
case RightMarginRecord.sid: return new RightMarginRecord(in);
case RowRecord.sid: return new RowRecord(in);
case SCLRecord.sid: return new SCLRecord(in);
case SSTRecord.sid: return new SSTRecord(in);
case SaveRecalcRecord.sid: return new SaveRecalcRecord(in);
case SelectionRecord.sid: return new SelectionRecord(in);
case SeriesIndexRecord.sid: return new SeriesIndexRecord(in);
case SeriesListRecord.sid: return new SeriesListRecord(in);
case SeriesRecord.sid: return new SeriesRecord(in);
case SeriesTextRecord.sid: return new SeriesTextRecord(in);
case SeriesToChartGroupRecord.sid:return new SeriesToChartGroupRecord(in);
case SharedFormulaRecord.sid: return new SharedFormulaRecord(in);
case SheetPropertiesRecord.sid: return new SheetPropertiesRecord(in);
case StringRecord.sid: return new StringRecord(in);
case StyleRecord.sid: return new StyleRecord(in);
case SupBookRecord.sid: return new SupBookRecord(in);
case TabIdRecord.sid: return new TabIdRecord(in);
case TableStylesRecord.sid: return new TableStylesRecord(in);
case TableRecord.sid: return new TableRecord(in);
case TextObjectRecord.sid: return new TextObjectRecord(in);
case TextRecord.sid: return new TextRecord(in);
case TickRecord.sid: return new TickRecord(in);
case TopMarginRecord.sid: return new TopMarginRecord(in);
case UncalcedRecord.sid: return new UncalcedRecord(in);
case UnitsRecord.sid: return new UnitsRecord(in);
case UseSelFSRecord.sid: return new UseSelFSRecord(in);
case VCenterRecord.sid: return new VCenterRecord(in);
case ValueRangeRecord.sid: return new ValueRangeRecord(in);
case VerticalPageBreakRecord.sid: return new VerticalPageBreakRecord(in);
case WSBoolRecord.sid: return new WSBoolRecord(in);
case WindowOneRecord.sid: return new WindowOneRecord(in);
case WindowProtectRecord.sid: return new WindowProtectRecord(in);
case WindowTwoRecord.sid: return new WindowTwoRecord(in);
case WriteAccessRecord.sid: return new WriteAccessRecord(in);
case WriteProtectRecord.sid: return new WriteProtectRecord(in);
// chart
case CatLabRecord.sid: return new CatLabRecord(in);
case ChartEndBlockRecord.sid: return new ChartEndBlockRecord(in);
case ChartEndObjectRecord.sid: return new ChartEndObjectRecord(in);
case ChartFRTInfoRecord.sid: return new ChartFRTInfoRecord(in);
case ChartStartBlockRecord.sid: return new ChartStartBlockRecord(in);
case ChartStartObjectRecord.sid: return new ChartStartObjectRecord(in);
// pivot table
case StreamIDRecord.sid: return new StreamIDRecord(in);
case ViewSourceRecord.sid: return new ViewSourceRecord(in);
case PageItemRecord.sid: return new PageItemRecord(in);
case ViewDefinitionRecord.sid: return new ViewDefinitionRecord(in);
case ViewFieldsRecord.sid: return new ViewFieldsRecord(in);
case DataItemRecord.sid: return new DataItemRecord(in);
case ExtendedPivotTableViewFieldsRecord.sid: return new ExtendedPivotTableViewFieldsRecord(in);
}
return new UnknownRecord(in);
}
private static final class CommandArgs {
private final boolean _biffhex;
private final boolean _noint;
private final boolean _out;
private final boolean _rawhex;
private final boolean _noHeader;
private final File _file;
private CommandArgs(boolean biffhex, boolean noint, boolean out, boolean rawhex, boolean noHeader, File file) {
_biffhex = biffhex;
_noint = noint;
_out = out;
_rawhex = rawhex;
_file = file;
_noHeader = noHeader;
}
public static CommandArgs parse(String[] args) throws CommandParseException {
int nArgs = args.length;
boolean biffhex = false;
boolean noint = false;
boolean out = false;
boolean rawhex = false;
boolean noheader = false;
File file = null;
for (int i=0; i<nArgs; i++) {
String arg = args[i];
if (arg.startsWith("--")) {
if ("--biffhex".equals(arg)) {
biffhex = true;
} else if ("--noint".equals(arg)) {
noint = true;
} else if ("--out".equals(arg)) {
out = true;
} else if ("--escher".equals(arg)) {
System.setProperty("poi.deserialize.escher", "true");
} else if ("--rawhex".equals(arg)) {
rawhex = true;
} else if ("--noheader".equals(arg)) {
noheader = true;
} else {
throw new CommandParseException("Unexpected option '" + arg + "'");
}
continue;
}
file = new File(arg);
if (!file.exists()) {
throw new CommandParseException("Specified file '" + arg + "' does not exist");
}
if (i+1<nArgs) {
throw new CommandParseException("File name must be the last arg");
}
}
if (file == null) {
throw new CommandParseException("Biff viewer needs a filename");
}
return new CommandArgs(biffhex, noint, out, rawhex, noheader, file);
}
public boolean shouldDumpBiffHex() {
return _biffhex;
}
public boolean shouldDumpRecordInterpretations() {
return !_noint;
}
public boolean shouldOutputToFile() {
return _out;
}
public boolean shouldOutputRawHexOnly() {
return _rawhex;
}
public boolean suppressHeader() {
return _noHeader;
}
public File getFile() {
return _file;
}
}
private static final class CommandParseException extends Exception {
public CommandParseException(String msg) {
super(msg);
}
}
/**
* Method main with 1 argument just run straight biffview against given
* file<p>
*
* <b>Usage</b>:<p>
*
* BiffViewer [--biffhex] [--noint] [--noescher] [--out] &lt;fileName&gt;<p>
* BiffViewer --rawhex [--out] &lt;fileName&gt;
*
* <table summary="BiffViewer options">
* <tr><td>--biffhex</td><td>show hex dump of each BIFF record</td></tr>
* <tr><td>--noint</td><td>do not output interpretation of BIFF records</td></tr>
* <tr><td>--out</td><td>send output to &lt;fileName&gt;.out</td></tr>
* <tr><td>--rawhex</td><td>output raw hex dump of whole workbook stream</td></tr>
* <tr><td>--escher</td><td>turn on deserialization of escher records (default is off)</td></tr>
* <tr><td>--noheader</td><td>do not print record header (default is on)</td></tr>
* </table>
*
* @param args the command line arguments
*
* @throws IOException if the file doesn't exist or contained errors
* @throws CommandParseException if the command line contained errors
*/
public static void main(String[] args) throws IOException, CommandParseException {
// args = new String[] { "--out", "", };
CommandArgs cmdArgs = CommandArgs.parse(args);
PrintWriter pw;
if (cmdArgs.shouldOutputToFile()) {
OutputStream os = new FileOutputStream(cmdArgs.getFile().getAbsolutePath() + ".out");
pw = new PrintWriter(new OutputStreamWriter(os, StringUtil.UTF8));
} else {
// Use the system default encoding when sending to System Out
pw = new PrintWriter(new OutputStreamWriter(System.out, Charset.defaultCharset()));
}
NPOIFSFileSystem fs = null;
InputStream is = null;
try {
fs = new NPOIFSFileSystem(cmdArgs.getFile(), true);
is = getPOIFSInputStream(fs);
if (cmdArgs.shouldOutputRawHexOnly()) {
byte[] data = IOUtils.toByteArray(is);
HexDump.dump(data, 0, System.out, 0);
} else {
boolean dumpInterpretedRecords = cmdArgs.shouldDumpRecordInterpretations();
boolean dumpHex = cmdArgs.shouldDumpBiffHex();
boolean zeroAlignHexDump = dumpInterpretedRecords; // TODO - fix non-zeroAlign
runBiffViewer(pw, is, dumpInterpretedRecords, dumpHex, zeroAlignHexDump,
cmdArgs.suppressHeader());
}
} finally {
IOUtils.closeQuietly(is);
IOUtils.closeQuietly(fs);
IOUtils.closeQuietly(pw);
}
}
protected static InputStream getPOIFSInputStream(NPOIFSFileSystem fs)
throws IOException, FileNotFoundException {
String workbookName = HSSFWorkbook.getWorkbookDirEntryName(fs.getRoot());
return fs.createDocumentInputStream(workbookName);
}
protected static void runBiffViewer(PrintWriter pw, InputStream is,
boolean dumpInterpretedRecords, boolean dumpHex, boolean zeroAlignHexDump,
boolean suppressHeader) {
BiffRecordListener recListener = new BiffRecordListener(dumpHex ? pw : null, zeroAlignHexDump, suppressHeader);
is = new BiffDumpingStream(is, recListener);
createRecords(is, pw, recListener, dumpInterpretedRecords);
}
private static final class BiffRecordListener implements IBiffRecordListener {
private final Writer _hexDumpWriter;
private List<String> _headers;
private final boolean _zeroAlignEachRecord;
private final boolean _noHeader;
public BiffRecordListener(Writer hexDumpWriter, boolean zeroAlignEachRecord, boolean noHeader) {
_hexDumpWriter = hexDumpWriter;
_zeroAlignEachRecord = zeroAlignEachRecord;
_noHeader = noHeader;
_headers = new ArrayList<String>();
}
@Override
public void processRecord(int globalOffset, int recordCounter, int sid, int dataSize,
byte[] data) {
String header = formatRecordDetails(globalOffset, sid, dataSize, recordCounter);
if(!_noHeader) {
_headers.add(header);
}
Writer w = _hexDumpWriter;
if (w != null) {
try {
w.write(header);
w.write(NEW_LINE_CHARS);
hexDumpAligned(w, data, dataSize+4, globalOffset, _zeroAlignEachRecord);
w.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
public List<String> getRecentHeaders() {
List<String> result = _headers;
_headers = new ArrayList<String>();
return result;
}
private static String formatRecordDetails(int globalOffset, int sid, int size, int recordCounter) {
StringBuilder sb = new StringBuilder(64);
sb.append("Offset=").append(HexDump.intToHex(globalOffset)).append("(").append(globalOffset).append(")");
sb.append(" recno=").append(recordCounter);
sb.append( " sid=").append(HexDump.shortToHex(sid));
sb.append( " size=").append(HexDump.shortToHex(size)).append("(").append(size).append(")");
return sb.toString();
}
}
private interface IBiffRecordListener {
void processRecord(int globalOffset, int recordCounter, int sid, int dataSize, byte[] data);
}
/**
* Wraps a plain {@link InputStream} and allows BIFF record information to be tapped off
*
*/
private static final class BiffDumpingStream extends InputStream {
private final DataInputStream _is;
private final IBiffRecordListener _listener;
private final byte[] _data;
private int _recordCounter;
private int _overallStreamPos;
private int _currentPos;
private int _currentSize;
private boolean _innerHasReachedEOF;
public BiffDumpingStream(InputStream is, IBiffRecordListener listener) {
_is = new DataInputStream(is);
_listener = listener;
_data = new byte[RecordInputStream.MAX_RECORD_DATA_SIZE + 4];
_recordCounter = 0;
_overallStreamPos = 0;
_currentSize = 0;
_currentPos = 0;
}
@Override
public int read() throws IOException {
if (_currentPos >= _currentSize) {
fillNextBuffer();
}
if (_currentPos >= _currentSize) {
return -1;
}
int result = _data[_currentPos] & 0x00FF;
_currentPos ++;
_overallStreamPos ++;
formatBufferIfAtEndOfRec();
return result;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (_currentPos >= _currentSize) {
fillNextBuffer();
}
if (_currentPos >= _currentSize) {
return -1;
}
int availSize = _currentSize - _currentPos;
int result;
if (len > availSize) {
System.err.println("Unexpected request to read past end of current biff record");
result = availSize;
} else {
result = len;
}
System.arraycopy(_data, _currentPos, b, off, result);
_currentPos += result;
_overallStreamPos += result;
formatBufferIfAtEndOfRec();
return result;
}
@Override
@SuppressForbidden("just delegating the call")
public int available() throws IOException {
return _currentSize - _currentPos + _is.available();
}
private void fillNextBuffer() throws IOException {
if (_innerHasReachedEOF) {
return;
}
int b0 = _is.read();
if (b0 == -1) {
_innerHasReachedEOF = true;
return;
}
_data[0] = (byte) b0;
_is.readFully(_data, 1, 3);
int len = LittleEndian.getShort(_data, 2);
_is.readFully(_data, 4, len);
_currentPos = 0;
_currentSize = len + 4;
_recordCounter++;
}
private void formatBufferIfAtEndOfRec() {
if (_currentPos != _currentSize) {
return;
}
int dataSize = _currentSize-4;
int sid = LittleEndian.getShort(_data, 0);
int globalOffset = _overallStreamPos-_currentSize;
_listener.processRecord(globalOffset, _recordCounter, sid, dataSize, _data);
}
@Override
public void close() throws IOException {
_is.close();
}
}
private static final int DUMP_LINE_LEN = 16;
private static final char[] COLUMN_SEPARATOR = " | ".toCharArray();
/**
* Hex-dumps a portion of a byte array in typical format, also preserving dump-line alignment
* @param globalOffset (somewhat arbitrary) used to calculate the addresses printed at the
* start of each line
*/
static void hexDumpAligned(Writer w, byte[] data, int dumpLen, int globalOffset,
boolean zeroAlignEachRecord) {
int baseDataOffset = 0;
// perhaps this code should be moved to HexDump
int globalStart = globalOffset + baseDataOffset;
int globalEnd = globalOffset + baseDataOffset + dumpLen;
int startDelta = globalStart % DUMP_LINE_LEN;
int endDelta = globalEnd % DUMP_LINE_LEN;
if (zeroAlignEachRecord) {
endDelta -= startDelta;
if (endDelta < 0) {
endDelta += DUMP_LINE_LEN;
}
startDelta = 0;
}
int startLineAddr;
int endLineAddr;
if (zeroAlignEachRecord) {
endLineAddr = globalEnd - endDelta - (globalStart - startDelta);
startLineAddr = 0;
} else {
startLineAddr = globalStart - startDelta;
endLineAddr = globalEnd - endDelta;
}
int lineDataOffset = baseDataOffset - startDelta;
int lineAddr = startLineAddr;
// output (possibly incomplete) first line
if (startLineAddr == endLineAddr) {
hexDumpLine(w, data, lineAddr, lineDataOffset, startDelta, endDelta);
return;
}
hexDumpLine(w, data, lineAddr, lineDataOffset, startDelta, DUMP_LINE_LEN);
// output all full lines in the middle
while (true) {
lineAddr += DUMP_LINE_LEN;
lineDataOffset += DUMP_LINE_LEN;
if (lineAddr >= endLineAddr) {
break;
}
hexDumpLine(w, data, lineAddr, lineDataOffset, 0, DUMP_LINE_LEN);
}
// output (possibly incomplete) last line
if (endDelta != 0) {
hexDumpLine(w, data, lineAddr, lineDataOffset, 0, endDelta);
}
}
private static void hexDumpLine(Writer w, byte[] data, int lineStartAddress, int lineDataOffset, int startDelta, int endDelta) {
final char[] buf = new char[8+2*COLUMN_SEPARATOR.length+DUMP_LINE_LEN*3-1+DUMP_LINE_LEN+NEW_LINE_CHARS.length];
if (startDelta >= endDelta) {
throw new IllegalArgumentException("Bad start/end delta");
}
int idx=0;
try {
writeHex(buf, idx, lineStartAddress, 8);
idx = arraycopy(COLUMN_SEPARATOR, buf, idx+8);
// raw hex data
for (int i=0; i< DUMP_LINE_LEN; i++) {
if (i>0) {
buf[idx++] = ' ';
}
if (i >= startDelta && i < endDelta) {
writeHex(buf, idx, data[lineDataOffset+i], 2);
} else {
buf[idx] = ' ';
buf[idx+1] = ' ';
}
idx += 2;
}
idx = arraycopy(COLUMN_SEPARATOR, buf, idx);
// interpreted ascii
for (int i=0; i< DUMP_LINE_LEN; i++) {
char ch = ' ';
if (i >= startDelta && i < endDelta) {
ch = getPrintableChar(data[lineDataOffset+i]);
}
buf[idx++] = ch;
}
idx = arraycopy(NEW_LINE_CHARS, buf, idx);
w.write(buf, 0, idx);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static int arraycopy(char[] in, char[] out, int pos) {
int idx = pos;
for (char c : in) {
out[idx++] = c;
}
return idx;
}
private static char getPrintableChar(byte b) {
char ib = (char) (b & 0x00FF);
if (ib < 32 || ib > 126) {
return '.';
}
return ib;
}
private static void writeHex(char buf[], int startInBuf, int value, int nDigits) throws IOException {
int acc = value;
for(int i=nDigits-1; i>=0; i--) {
int digit = acc & 0x0F;
buf[startInBuf+i] = (char) (digit < 10 ? ('0' + digit) : ('A' + digit - 10));
acc >>>= 4;
}
}
}

View File

@ -1,94 +0,0 @@
/* ====================================================================
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.dev;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
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.record.Record;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
/**
*
* @author andy
*/
public class EFBiffViewer
{
String file;
/** Creates a new instance of EFBiffViewer */
public EFBiffViewer()
{
}
public void run() throws IOException {
NPOIFSFileSystem fs = new NPOIFSFileSystem(new File(file), true);
try {
InputStream din = BiffViewer.getPOIFSInputStream(fs);
try {
HSSFRequest req = new HSSFRequest();
req.addListenerForAllRecords(new HSSFListener()
{
public void processRecord(Record rec)
{
System.out.println(rec.toString());
}
});
HSSFEventFactory factory = new HSSFEventFactory();
factory.processEvents(req, din);
} finally {
din.close();
}
} finally {
fs.close();
}
}
public void setFile(String file)
{
this.file = file;
}
public static void main(String [] args) throws IOException
{
if ((args.length == 1) && !args[ 0 ].equals("--help"))
{
EFBiffViewer viewer = new EFBiffViewer();
viewer.setFile(args[ 0 ]);
viewer.run();
}
else
{
System.out.println("EFBiffViewer");
System.out.println(
"Outputs biffview of records based on HSSFEventFactory");
System.out
.println("usage: java org.apache.poi.hssf.dev.EBBiffViewer "
+ "filename");
}
}
}

View File

@ -1,236 +0,0 @@
/* ====================================================================
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.dev;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.poi.hssf.model.HSSFFormulaParser;
import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordFactory;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.ss.formula.ptg.ExpPtg;
import org.apache.poi.ss.formula.ptg.FuncPtg;
import org.apache.poi.ss.formula.ptg.Ptg;
/**
* FormulaViewer - finds formulas in a BIFF8 file and attempts to read them/display
* data from them. Only works if Formulas are enabled in "RecordFactory"
* @author andy
* @author Avik
*/
public class FormulaViewer
{
private String file;
private boolean list=false;
/** Creates new FormulaViewer */
public FormulaViewer()
{
}
/**
* Method run
*
* @throws IOException if the file contained errors
*/
public void run() throws IOException {
NPOIFSFileSystem fs = new NPOIFSFileSystem(new File(file), true);
try {
InputStream is = BiffViewer.getPOIFSInputStream(fs);
try {
List<Record> records = RecordFactory.createRecords(is);
for (Record record : records) {
if (record.getSid() == FormulaRecord.sid) {
if (list) {
listFormula((FormulaRecord) record);
} else {
parseFormulaRecord((FormulaRecord) record);
}
}
}
} finally {
is.close();
}
} finally {
fs.close();
}
}
private void listFormula(FormulaRecord record) {
String sep="~";
Ptg[] tokens= record.getParsedExpression();
Ptg token;
int numptgs = tokens.length;
String numArg;
token = tokens[numptgs-1];
if (token instanceof FuncPtg) {
numArg = String.valueOf(numptgs-1);
} else {
numArg = String.valueOf(-1);
}
StringBuilder buf = new StringBuilder();
if (token instanceof ExpPtg) return;
buf.append(token.toFormulaString());
buf.append(sep);
switch (token.getPtgClass()) {
case Ptg.CLASS_REF :
buf.append("REF");
break;
case Ptg.CLASS_VALUE :
buf.append("VALUE");
break;
case Ptg.CLASS_ARRAY :
buf.append("ARRAY");
break;
default:
throwInvalidRVAToken(token);
}
buf.append(sep);
if (numptgs>1) {
token = tokens[numptgs-2];
switch (token.getPtgClass()) {
case Ptg.CLASS_REF :
buf.append("REF");
break;
case Ptg.CLASS_VALUE :
buf.append("VALUE");
break;
case Ptg.CLASS_ARRAY :
buf.append("ARRAY");
break;
default:
throwInvalidRVAToken(token);
}
}else {
buf.append("VALUE");
}
buf.append(sep);
buf.append(numArg);
System.out.println(buf.toString());
}
/**
* Method parseFormulaRecord
*
* @param record the record to be parsed
*/
public void parseFormulaRecord(FormulaRecord record)
{
System.out.println("==============================");
System.out.print("row = " + record.getRow());
System.out.println(", col = " + record.getColumn());
System.out.println("value = " + record.getValue());
System.out.print("xf = " + record.getXFIndex());
System.out.print(", number of ptgs = "
+ record.getParsedExpression().length);
System.out.println(", options = " + record.getOptions());
System.out.println("RPN List = "+formulaString(record));
System.out.println("Formula text = "+ composeFormula(record));
}
private String formulaString(FormulaRecord record) {
StringBuilder buf = new StringBuilder();
Ptg[] tokens = record.getParsedExpression();
for (Ptg token : tokens) {
buf.append( token.toFormulaString());
switch (token.getPtgClass()) {
case Ptg.CLASS_REF :
buf.append("(R)");
break;
case Ptg.CLASS_VALUE :
buf.append("(V)");
break;
case Ptg.CLASS_ARRAY :
buf.append("(A)");
break;
default:
throwInvalidRVAToken(token);
}
buf.append(' ');
}
return buf.toString();
}
private static void throwInvalidRVAToken(Ptg token) {
throw new IllegalStateException("Invalid RVA type (" + token.getPtgClass() + "). This should never happen.");
}
private static String composeFormula(FormulaRecord record)
{
return HSSFFormulaParser.toFormulaString((HSSFWorkbook)null, record.getParsedExpression());
}
/**
* Method setFile
*
* @param file the file to process
*/
public void setFile(String file)
{
this.file = file;
}
public void setList(boolean list) {
this.list=list;
}
/**
* Method main
*
* pass me a filename and I'll try and parse the formulas from it
*
* @param args pass one argument with the filename or --help
* @throws IOException if the file can't be read or contained errors
*/
public static void main(String args[]) throws IOException
{
if ((args == null) || (args.length >2 )
|| args[ 0 ].equals("--help"))
{
System.out.println(
"FormulaViewer .8 proof that the devil lies in the details (or just in BIFF8 files in general)");
System.out.println("usage: Give me a big fat file name");
} else if (args[0].equals("--listFunctions")) { // undocumented attribute to research functions!~
FormulaViewer viewer = new FormulaViewer();
viewer.setFile(args[1]);
viewer.setList(true);
viewer.run();
}
else
{
FormulaViewer viewer = new FormulaViewer();
viewer.setFile(args[ 0 ]);
viewer.run();
}
}
}

View File

@ -1,83 +0,0 @@
/*
* 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.dev;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
/**
* Utility to test that POI produces readable output
* after re-saving xls files.
*
* Usage: ReSave [-dg] input.xls
* -dg initialize drawings, causes to re-build escher aggregates in all sheets
* -bos only write to memory instead of a file
*/
public class ReSave {
public static void main(String[] args) throws Exception {
boolean initDrawing = false;
boolean saveToMemory = false;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
for(String filename : args) {
if(filename.equals("-dg")) {
initDrawing = true;
} else if(filename.equals("-bos")) {
saveToMemory = true;
} else {
System.out.print("reading " + filename + "...");
FileInputStream is = new FileInputStream(filename);
HSSFWorkbook wb = new HSSFWorkbook(is);
try {
System.out.println("done");
for(int i = 0; i < wb.getNumberOfSheets(); i++){
HSSFSheet sheet = wb.getSheetAt(i);
if(initDrawing) {
/*HSSFPatriarch dg =*/ sheet.getDrawingPatriarch();
}
}
OutputStream os;
if (saveToMemory) {
bos.reset();
os = bos;
} else {
String outputFile = filename.replace(".xls", "-saved.xls");
System.out.print("saving to " + outputFile + "...");
os = new FileOutputStream(outputFile);
}
try {
wb.write(os);
} finally {
os.close();
}
System.out.println("done");
} finally {
wb.close();
is.close();
}
}
}
}
}

View File

@ -1,202 +0,0 @@
/* ====================================================================
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.dev;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import org.apache.poi.hssf.record.ContinueRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordFactory;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
/**
* This is a low-level debugging class, which simply prints
* out what records come in what order.
* Most people will want to use {@link BiffViewer} or
* {@link EFBiffViewer}, but this can be handy when
* trying to make sense of {@link ContinueRecord}
* special cases.
*
* Output is of the form:
* SID - Length - Type (if known)
* byte0 byte1 byte2 byte3 .... byte(n-4) byte(n-3) byte(n-2) byte(n-1)
*/
public class RecordLister
{
String file;
public RecordLister()
{
}
public void run()
throws IOException
{
NPOIFSFileSystem fs = new NPOIFSFileSystem(new File(file), true);
try {
InputStream din = BiffViewer.getPOIFSInputStream(fs);
try {
RecordInputStream rinp = new RecordInputStream(din);
while(rinp.hasNextRecord()) {
int sid = rinp.getNextSid();
rinp.nextRecord();
int size = rinp.available();
Class<? extends Record> clz = RecordFactory.getRecordClass(sid);
System.out.print(
formatSID(sid) +
" - " +
formatSize(size) +
" bytes"
);
if(clz != null) {
System.out.print(" \t");
System.out.print(clz.getName().replace("org.apache.poi.hssf.record.", ""));
}
System.out.println();
byte[] data = rinp.readRemainder();
if(data.length > 0) {
System.out.print(" ");
System.out.println( formatData(data) );
}
}
} finally {
din.close();
}
} finally {
fs.close();
}
}
private static String formatSID(int sid) {
String hex = Integer.toHexString(sid);
String dec = Integer.toString(sid);
StringBuffer s = new StringBuffer();
s.append("0x");
for(int i=hex.length(); i<4; i++) {
s.append('0');
}
s.append(hex);
s.append(" (");
for(int i=dec.length(); i<4; i++) {
s.append('0');
}
s.append(dec);
s.append(")");
return s.toString();
}
private static String formatSize(int size) {
String hex = Integer.toHexString(size);
String dec = Integer.toString(size);
StringBuffer s = new StringBuffer();
for(int i=hex.length(); i<3; i++) {
s.append('0');
}
s.append(hex);
s.append(" (");
for(int i=dec.length(); i<3; i++) {
s.append('0');
}
s.append(dec);
s.append(")");
return s.toString();
}
private static String formatData(byte[] data) {
if(data == null || data.length == 0)
return "";
// If possible, do first 4 and last 4 bytes
StringBuffer s = new StringBuffer();
if(data.length > 9) {
s.append(byteToHex(data[0]));
s.append(' ');
s.append(byteToHex(data[1]));
s.append(' ');
s.append(byteToHex(data[2]));
s.append(' ');
s.append(byteToHex(data[3]));
s.append(' ');
s.append(" .... ");
s.append(' ');
s.append(byteToHex(data[data.length-4]));
s.append(' ');
s.append(byteToHex(data[data.length-3]));
s.append(' ');
s.append(byteToHex(data[data.length-2]));
s.append(' ');
s.append(byteToHex(data[data.length-1]));
} else {
for(int i=0; i<data.length; i++) {
s.append(byteToHex(data[i]));
s.append(' ');
}
}
return s.toString();
}
private static String byteToHex(byte b) {
int i = b;
if(i<0) {
i += 256;
}
String s = Integer.toHexString(i);
if(i < 16) {
return "0" + s;
}
return s;
}
public void setFile(String file)
{
this.file = file;
}
public static void main(String [] args) throws IOException
{
if ((args.length == 1) && !args[ 0 ].equals("--help"))
{
RecordLister viewer = new RecordLister();
viewer.setFile(args[ 0 ]);
viewer.run();
}
else
{
System.out.println("RecordLister");
System.out.println(
"Outputs the summary of the records in file order");
System.out
.println("usage: java org.apache.poi.hssf.dev.RecordLister "
+ "filename");
}
}
}

View File

@ -1,36 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<!--
====================================================================
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.
====================================================================
-->
<html>
<head>
</head>
<body bgcolor="white">
DEV package serves two purposes. 1. Examples for how to use HSSF and 2. tools for developing
and validating HSSF.
<h2>Related Documentation</h2>
For overviews, tutorials, examples, guides, and tool documentation, please see:
<ul>
<li><a href="http://poi.apache.org">Apache POI Project</a>
</ul>
</body>
</html>

View File

@ -1,266 +0,0 @@
/* ====================================================================
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.util.ArrayList;
import java.util.List;
import org.apache.poi.POIDocument;
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.HSSFFormulaParser;
import org.apache.poi.hssf.record.BOFRecord;
import org.apache.poi.hssf.record.BoundSheetRecord;
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.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.DirectoryNode;
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.
* <p>
* To turn an excel file into a CSV or similar, then see
* the XLS2CSVmra example
* </p>
*
* @see <a href="http://svn.apache.org/repos/asf/poi/trunk/src/examples/src/org/apache/poi/hssf/eventusermodel/examples/XLS2CSVmra.java">XLS2CSVmra</a>
*/
public class EventBasedExcelExtractor extends POIOLE2TextExtractor implements org.apache.poi.ss.extractor.ExcelExtractor {
private DirectoryNode _dir;
boolean _includeSheetNames = true;
boolean _formulasNotResults = false;
public EventBasedExcelExtractor( DirectoryNode dir )
{
super( (POIDocument)null );
_dir = dir;
}
public EventBasedExcelExtractor(POIFSFileSystem fs) {
this(fs.getRoot());
super.setFilesystem(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");
}
/**
* Would control the inclusion of cell comments from the document,
* if we supported it
*/
public void setIncludeCellComments(boolean includeComments) {
throw new IllegalStateException("Comment extraction not supported in streaming mode, please use ExcelExtractor");
}
/**
* Would control the inclusion of headers and footers from the document,
* if we supported it
*/
public void setIncludeHeadersFooters(boolean includeHeadersFooters) {
throw new IllegalStateException("Header/Footer extraction not supported in streaming mode, please use ExcelExtractor");
}
/**
* Should sheet names be included? Default is true
*/
public void setIncludeSheetNames(boolean includeSheetNames) {
_includeSheetNames = includeSheetNames;
}
/**
* Should we return the formula itself, and not
* the result it produces? Default is false
*/
public void setFormulasNotResults(boolean formulasNotResults) {
_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, _dir);
return tl;
}
private class TextListener implements HSSFListener {
FormatTrackingHSSFListener _ft;
private SSTRecord sstRecord;
private final List<String> sheetNames;
final StringBuffer _text = new StringBuffer();
private int sheetNum = -1;
private int rowNum;
private boolean outputNextStringValue = false;
private int nextRow = -1;
public TextListener() {
sheetNames = new ArrayList<String>();
}
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 = HSSFFormulaParser.toFormulaString((HSSFWorkbook)null, frec.getParsedExpression());
} else {
if(frec.hasCachedResultString()) {
// Formula result is a string
// This is stored in the next record
outputNextStringValue = true;
nextRow = frec.getRow();
} else {
thisText = _ft.formatNumberDateCell(frec);
}
}
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 = _ft.formatNumberDateCell(numrec);
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);
}
}
}
}

View File

@ -1,421 +0,0 @@
/* ====================================================================
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.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Locale;
import org.apache.poi.POIOLE2TextExtractor;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFComment;
import org.apache.poi.hssf.usermodel.HSSFDataFormatter;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.usermodel.HeaderFooter;
import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
/**
* A text extractor for Excel files.
* <p>
* Returns the textual content of the file, suitable for
* indexing by something like Lucene, but not really
* intended for display to the user.
* </p>
* <p>
* To turn an excel file into a CSV or similar, then see
* the XLS2CSVmra example
* </p>
*
* @see <a href="http://svn.apache.org/repos/asf/poi/trunk/src/examples/src/org/apache/poi/hssf/eventusermodel/examples/XLS2CSVmra.java">XLS2CSVmra</a>
*/
public class ExcelExtractor extends POIOLE2TextExtractor implements org.apache.poi.ss.extractor.ExcelExtractor {
private final HSSFWorkbook _wb;
private final HSSFDataFormatter _formatter;
private boolean _includeSheetNames = true;
private boolean _shouldEvaluateFormulas = true;
private boolean _includeCellComments = false;
private boolean _includeBlankCells = false;
private boolean _includeHeadersFooters = true;
public ExcelExtractor(HSSFWorkbook wb) {
super(wb);
_wb = wb;
_formatter = new HSSFDataFormatter();
}
public ExcelExtractor(POIFSFileSystem fs) throws IOException {
this(fs.getRoot());
}
public ExcelExtractor(DirectoryNode dir) throws IOException {
this(new HSSFWorkbook(dir, true));
}
private static final class CommandParseException extends Exception {
public CommandParseException(String msg) {
super(msg);
}
}
private static final class CommandArgs {
private final boolean _requestHelp;
private final File _inputFile;
private final boolean _showSheetNames;
private final boolean _evaluateFormulas;
private final boolean _showCellComments;
private final boolean _showBlankCells;
private final boolean _headersFooters;
public CommandArgs(String[] args) throws CommandParseException {
int nArgs = args.length;
File inputFile = null;
boolean requestHelp = false;
boolean showSheetNames = true;
boolean evaluateFormulas = true;
boolean showCellComments = false;
boolean showBlankCells = false;
boolean headersFooters = true;
for (int i=0; i<nArgs; i++) {
String arg = args[i];
if ("-help".equalsIgnoreCase(arg)) {
requestHelp = true;
break;
}
if ("-i".equals(arg)) {
// step to next arg
if (++i >= nArgs) {
throw new CommandParseException("Expected filename after '-i'");
}
arg = args[i];
if (inputFile != null) {
throw new CommandParseException("Only one input file can be supplied");
}
inputFile = new File(arg);
if (!inputFile.exists()) {
throw new CommandParseException("Specified input file '" + arg + "' does not exist");
}
if (inputFile.isDirectory()) {
throw new CommandParseException("Specified input file '" + arg + "' is a directory");
}
continue;
}
if ("--show-sheet-names".equals(arg)) {
showSheetNames = parseBoolArg(args, ++i);
continue;
}
if ("--evaluate-formulas".equals(arg)) {
evaluateFormulas = parseBoolArg(args, ++i);
continue;
}
if ("--show-comments".equals(arg)) {
showCellComments = parseBoolArg(args, ++i);
continue;
}
if ("--show-blanks".equals(arg)) {
showBlankCells = parseBoolArg(args, ++i);
continue;
}
if ("--headers-footers".equals(arg)) {
headersFooters = parseBoolArg(args, ++i);
continue;
}
throw new CommandParseException("Invalid argument '" + arg + "'");
}
_requestHelp = requestHelp;
_inputFile = inputFile;
_showSheetNames = showSheetNames;
_evaluateFormulas = evaluateFormulas;
_showCellComments = showCellComments;
_showBlankCells = showBlankCells;
_headersFooters = headersFooters;
}
private static boolean parseBoolArg(String[] args, int i) throws CommandParseException {
if (i >= args.length) {
throw new CommandParseException("Expected value after '" + args[i-1] + "'");
}
String value = args[i].toUpperCase(Locale.ROOT);
if ("Y".equals(value) || "YES".equals(value) || "ON".equals(value) || "TRUE".equals(value)) {
return true;
}
if ("N".equals(value) || "NO".equals(value) || "OFF".equals(value) || "FALSE".equals(value)) {
return false;
}
throw new CommandParseException("Invalid value '" + args[i] + "' for '" + args[i-1] + "'. Expected 'Y' or 'N'");
}
public boolean isRequestHelp() {
return _requestHelp;
}
public File getInputFile() {
return _inputFile;
}
public boolean shouldShowSheetNames() {
return _showSheetNames;
}
public boolean shouldEvaluateFormulas() {
return _evaluateFormulas;
}
public boolean shouldShowCellComments() {
return _showCellComments;
}
public boolean shouldShowBlankCells() {
return _showBlankCells;
}
public boolean shouldIncludeHeadersFooters() {
return _headersFooters;
}
}
private static void printUsageMessage(PrintStream ps) {
ps.println("Use:");
ps.println(" " + ExcelExtractor.class.getName() + " [<flag> <value> [<flag> <value> [...]]] [-i <filename.xls>]");
ps.println(" -i <filename.xls> specifies input file (default is to use stdin)");
ps.println(" Flags can be set on or off by using the values 'Y' or 'N'.");
ps.println(" Following are available flags and their default values:");
ps.println(" --show-sheet-names Y");
ps.println(" --evaluate-formulas Y");
ps.println(" --show-comments N");
ps.println(" --show-blanks Y");
ps.println(" --headers-footers Y");
}
/**
* Command line extractor.
*
* @param args the command line parameters
*
* @throws IOException if the file can't be read or contains errors
*/
public static void main(String[] args) throws IOException {
CommandArgs cmdArgs;
try {
cmdArgs = new CommandArgs(args);
} catch (CommandParseException e) {
System.err.println(e.getMessage());
printUsageMessage(System.err);
System.exit(1);
return; // suppress compiler error
}
if (cmdArgs.isRequestHelp()) {
printUsageMessage(System.out);
return;
}
InputStream is;
if(cmdArgs.getInputFile() == null) {
is = System.in;
} else {
is = new FileInputStream(cmdArgs.getInputFile());
}
HSSFWorkbook wb = new HSSFWorkbook(is);
is.close();
ExcelExtractor extractor = new ExcelExtractor(wb);
extractor.setIncludeSheetNames(cmdArgs.shouldShowSheetNames());
extractor.setFormulasNotResults(!cmdArgs.shouldEvaluateFormulas());
extractor.setIncludeCellComments(cmdArgs.shouldShowCellComments());
extractor.setIncludeBlankCells(cmdArgs.shouldShowBlankCells());
extractor.setIncludeHeadersFooters(cmdArgs.shouldIncludeHeadersFooters());
System.out.println(extractor.getText());
extractor.close();
wb.close();
}
@Override
public void setIncludeSheetNames(boolean includeSheetNames) {
_includeSheetNames = includeSheetNames;
}
@Override
public void setFormulasNotResults(boolean formulasNotResults) {
_shouldEvaluateFormulas = !formulasNotResults;
}
@Override
public void setIncludeCellComments(boolean includeCellComments) {
_includeCellComments = includeCellComments;
}
/**
* Should blank cells be output? Default is to only
* output cells that are present in the file and are
* non-blank.
*
* @param includeBlankCells {@code true} if blank cells should be included
*/
public void setIncludeBlankCells(boolean includeBlankCells) {
_includeBlankCells = includeBlankCells;
}
@Override
public void setIncludeHeadersFooters(boolean includeHeadersFooters) {
_includeHeadersFooters = includeHeadersFooters;
}
@Override
public String getText() {
StringBuffer text = new StringBuffer();
// We don't care about the difference between
// null (missing) and blank cells
_wb.setMissingCellPolicy(MissingCellPolicy.RETURN_BLANK_AS_NULL);
// Process each sheet in turn
for(int i=0;i<_wb.getNumberOfSheets();i++) {
HSSFSheet sheet = _wb.getSheetAt(i);
if(sheet == null) { continue; }
if(_includeSheetNames) {
String name = _wb.getSheetName(i);
if(name != null) {
text.append(name);
text.append("\n");
}
}
// Header text, if there is any
if(_includeHeadersFooters) {
text.append(_extractHeaderFooter(sheet.getHeader()));
}
int firstRow = sheet.getFirstRowNum();
int lastRow = sheet.getLastRowNum();
for(int j=firstRow;j<=lastRow;j++) {
HSSFRow row = sheet.getRow(j);
if(row == null) { continue; }
// Check each cell in turn
int firstCell = row.getFirstCellNum();
int lastCell = row.getLastCellNum();
if(_includeBlankCells) {
firstCell = 0;
}
for(int k=firstCell;k<lastCell;k++) {
HSSFCell cell = row.getCell(k);
boolean outputContents = true;
if(cell == null) {
// Only output if requested
outputContents = _includeBlankCells;
} else {
switch(cell.getCellTypeEnum()) {
case STRING:
text.append(cell.getRichStringCellValue().getString());
break;
case NUMERIC:
text.append(_formatter.formatCellValue(cell));
break;
case BOOLEAN:
text.append(cell.getBooleanCellValue());
break;
case ERROR:
text.append(ErrorEval.getText(cell.getErrorCellValue()));
break;
case FORMULA:
if(!_shouldEvaluateFormulas) {
text.append(cell.getCellFormula());
} else {
switch(cell.getCachedFormulaResultTypeEnum()) {
case STRING:
HSSFRichTextString str = cell.getRichStringCellValue();
if(str != null && str.length() > 0) {
text.append(str.toString());
}
break;
case NUMERIC:
HSSFCellStyle style = cell.getCellStyle();
double nVal = cell.getNumericCellValue();
short df = style.getDataFormat();
String dfs = style.getDataFormatString();
text.append(_formatter.formatRawCellContents(nVal, df, dfs));
break;
case BOOLEAN:
text.append(cell.getBooleanCellValue());
break;
case ERROR:
text.append(ErrorEval.getText(cell.getErrorCellValue()));
break;
default:
throw new IllegalStateException("Unexpected cell cached formula result type: " + cell.getCachedFormulaResultTypeEnum());
}
}
break;
default:
throw new RuntimeException("Unexpected cell type (" + cell.getCellTypeEnum() + ")");
}
// Output the comment, if requested and exists
HSSFComment comment = cell.getCellComment();
if(_includeCellComments && comment != null) {
// Replace any newlines with spaces, otherwise it
// breaks the output
String commentText = comment.getString().getString().replace('\n', ' ');
text.append(" Comment by "+comment.getAuthor()+": "+commentText);
}
}
// Output a tab if we're not on the last cell
if(outputContents && k < (lastCell-1)) {
text.append("\t");
}
}
// Finish off the row
text.append("\n");
}
// Finally Footer text, if there is any
if(_includeHeadersFooters) {
text.append(_extractHeaderFooter(sheet.getFooter()));
}
}
return text.toString();
}
public static String _extractHeaderFooter(HeaderFooter hf) {
StringBuffer text = new StringBuffer();
if(hf.getLeft() != null) {
text.append(hf.getLeft());
}
if(hf.getCenter() != null) {
if(text.length() > 0)
text.append("\t");
text.append(hf.getCenter());
}
if(hf.getRight() != null) {
if(text.length() > 0)
text.append("\t");
text.append(hf.getRight());
}
if(text.length() > 0)
text.append("\n");
return text.toString();
}
}

View File

@ -1,324 +0,0 @@
/* ====================================================================
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 static org.apache.poi.hssf.model.InternalWorkbook.OLD_WORKBOOK_DIR_ENTRY_NAME;
import static org.apache.poi.hssf.model.InternalWorkbook.WORKBOOK_DIR_ENTRY_NAMES;
import java.io.BufferedInputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.hssf.OldExcelFormatException;
import org.apache.poi.hssf.record.BOFRecord;
import org.apache.poi.hssf.record.CodepageRecord;
import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.NumberRecord;
import org.apache.poi.hssf.record.OldFormulaRecord;
import org.apache.poi.hssf.record.OldLabelRecord;
import org.apache.poi.hssf.record.OldSheetRecord;
import org.apache.poi.hssf.record.OldStringRecord;
import org.apache.poi.hssf.record.RKRecord;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.DocumentNode;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.poifs.filesystem.NotOLE2FileException;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.util.IOUtils;
/**
* A text extractor for old Excel files, which are too old for
* HSSFWorkbook to handle. This includes Excel 95, and very old
* (pre-OLE2) Excel files, such as Excel 4 files.
* <p>
* Returns much (but not all) of the textual content of the file,
* suitable for indexing by something like Apache Lucene, or used
* by Apache Tika, but not really intended for display to the user.
* </p>
*/
public class OldExcelExtractor implements Closeable {
private final static int FILE_PASS_RECORD_SID = 0x2f;
private RecordInputStream ris;
// sometimes we hold the stream here and thus need to ensure it is closed at some point
private Closeable toClose;
private int biffVersion;
private int fileType;
public OldExcelExtractor(InputStream input) throws IOException {
open(input);
}
public OldExcelExtractor(File f) throws IOException {
NPOIFSFileSystem poifs = null;
try {
poifs = new NPOIFSFileSystem(f);
open(poifs);
toClose = poifs;
return;
} catch (OldExcelFormatException e) {
// will be handled by workaround below
} catch (NotOLE2FileException e) {
// will be handled by workaround below
} catch (IOException e) {
// ensure streams are closed correctly
throw e;
} catch (RuntimeException e) {
// ensure streams are closed correctly
throw e;
} finally {
if (toClose == null) {
IOUtils.closeQuietly(poifs);
}
}
@SuppressWarnings("resource")
FileInputStream biffStream = new FileInputStream(f); // NOSONAR
try {
open(biffStream);
} catch (IOException e) {
// ensure that the stream is properly closed here if an Exception
// is thrown while opening
biffStream.close();
throw e;
} catch (RuntimeException e) {
// ensure that the stream is properly closed here if an Exception
// is thrown while opening
biffStream.close();
throw e;
}
}
public OldExcelExtractor(NPOIFSFileSystem fs) throws IOException {
open(fs);
}
public OldExcelExtractor(DirectoryNode directory) throws IOException {
open(directory);
}
private void open(InputStream biffStream) throws IOException {
BufferedInputStream bis = (biffStream instanceof BufferedInputStream)
? (BufferedInputStream)biffStream
: new BufferedInputStream(biffStream, 8);
if (NPOIFSFileSystem.hasPOIFSHeader(bis)) {
NPOIFSFileSystem poifs = new NPOIFSFileSystem(bis);
try {
open(poifs);
} finally {
poifs.close();
}
} else {
ris = new RecordInputStream(bis);
toClose = bis;
prepare();
}
}
private void open(NPOIFSFileSystem fs) throws IOException {
open(fs.getRoot());
}
private void open(DirectoryNode directory) throws IOException {
DocumentNode book;
try {
book = (DocumentNode)directory.getEntry(OLD_WORKBOOK_DIR_ENTRY_NAME);
} catch (FileNotFoundException e) {
// some files have "Workbook" instead
book = (DocumentNode)directory.getEntry(WORKBOOK_DIR_ENTRY_NAMES[0]);
}
if (book == null) {
throw new IOException("No Excel 5/95 Book stream found");
}
ris = new RecordInputStream(directory.createDocumentInputStream(book));
prepare();
}
public static void main(String[] args) throws IOException {
if (args.length < 1) {
System.err.println("Use:");
System.err.println(" OldExcelExtractor <filename>");
System.exit(1);
}
OldExcelExtractor extractor = new OldExcelExtractor(new File(args[0]));
System.out.println(extractor.getText());
extractor.close();
}
private void prepare() {
if (! ris.hasNextRecord()) {
throw new IllegalArgumentException("File contains no records!");
}
ris.nextRecord();
// Work out what version we're dealing with
int bofSid = ris.getSid();
switch (bofSid) {
case BOFRecord.biff2_sid:
biffVersion = 2;
break;
case BOFRecord.biff3_sid:
biffVersion = 3;
break;
case BOFRecord.biff4_sid:
biffVersion = 4;
break;
case BOFRecord.biff5_sid:
biffVersion = 5;
break;
default:
throw new IllegalArgumentException("File does not begin with a BOF, found sid of " + bofSid);
}
// Get the type
BOFRecord bof = new BOFRecord(ris);
fileType = bof.getType();
}
/**
* The Biff version, largely corresponding to the Excel version
*
* @return the Biff version
*/
public int getBiffVersion() {
return biffVersion;
}
/**
* The kind of the file, one of {@link BOFRecord#TYPE_WORKSHEET},
* {@link BOFRecord#TYPE_CHART}, {@link BOFRecord#TYPE_EXCEL_4_MACRO}
* or {@link BOFRecord#TYPE_WORKSPACE_FILE}
*
* @return the file type
*/
public int getFileType() {
return fileType;
}
/**
* Retrieves the text contents of the file, as best we can
* for these old file formats
*
* @return the text contents of the file
*/
public String getText() {
StringBuffer text = new StringBuffer();
// To track formats and encodings
CodepageRecord codepage = null;
// TODO track the XFs and Format Strings
// Process each record in turn, looking for interesting ones
while (ris.hasNextRecord()) {
int sid = ris.getNextSid();
ris.nextRecord();
switch (sid) {
case FILE_PASS_RECORD_SID:
throw new EncryptedDocumentException("Encryption not supported for Old Excel files");
case OldSheetRecord.sid:
OldSheetRecord shr = new OldSheetRecord(ris);
shr.setCodePage(codepage);
text.append("Sheet: ");
text.append(shr.getSheetname());
text.append('\n');
break;
case OldLabelRecord.biff2_sid:
case OldLabelRecord.biff345_sid:
OldLabelRecord lr = new OldLabelRecord(ris);
lr.setCodePage(codepage);
text.append(lr.getValue());
text.append('\n');
break;
case OldStringRecord.biff2_sid:
case OldStringRecord.biff345_sid:
OldStringRecord sr = new OldStringRecord(ris);
sr.setCodePage(codepage);
text.append(sr.getString());
text.append('\n');
break;
case NumberRecord.sid:
NumberRecord nr = new NumberRecord(ris);
handleNumericCell(text, nr.getValue());
break;
case OldFormulaRecord.biff2_sid:
case OldFormulaRecord.biff3_sid:
case OldFormulaRecord.biff4_sid:
// Biff 2 and 5+ share the same SID, due to a bug...
if (biffVersion == 5) {
FormulaRecord fr = new FormulaRecord(ris);
if (fr.getCachedResultType() == CellType.NUMERIC.getCode()) {
handleNumericCell(text, fr.getValue());
}
} else {
OldFormulaRecord fr = new OldFormulaRecord(ris);
if (fr.getCachedResultType() == CellType.NUMERIC.getCode()) {
handleNumericCell(text, fr.getValue());
}
}
break;
case RKRecord.sid:
RKRecord rr = new RKRecord(ris);
handleNumericCell(text, rr.getRKNumber());
break;
case CodepageRecord.sid:
codepage = new CodepageRecord(ris);
break;
default:
ris.readFully(new byte[ris.remaining()]);
}
}
close();
ris = null;
return text.toString();
}
@Override
public void close() {
// some cases require this close here
if(toClose != null) {
IOUtils.closeQuietly(toClose);
toClose = null;
}
}
protected void handleNumericCell(StringBuffer text, double value) {
// TODO Need to fetch / use format strings
text.append(value);
text.append('\n');
}
}

View File

@ -42,7 +42,6 @@ import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ddf.EscherSimpleProperty; import org.apache.poi.ddf.EscherSimpleProperty;
import org.apache.poi.ddf.EscherSpRecord; import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.ddf.EscherSplitMenuColorsRecord; import org.apache.poi.ddf.EscherSplitMenuColorsRecord;
import org.apache.poi.hssf.extractor.OldExcelExtractor;
import org.apache.poi.hssf.record.BOFRecord; import org.apache.poi.hssf.record.BOFRecord;
import org.apache.poi.hssf.record.BackupRecord; import org.apache.poi.hssf.record.BackupRecord;
import org.apache.poi.hssf.record.BookBoolRecord; import org.apache.poi.hssf.record.BookBoolRecord;

View File

@ -22,7 +22,6 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Locale; import java.util.Locale;
import org.apache.poi.hssf.dev.BiffViewer;
import org.apache.poi.hssf.record.crypto.Biff8DecryptingStream; import org.apache.poi.hssf.record.crypto.Biff8DecryptingStream;
import org.apache.poi.poifs.crypt.EncryptionInfo; import org.apache.poi.poifs.crypt.EncryptionInfo;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;

View File

@ -80,13 +80,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing<HSSFShap
* @param boundAggregate -low level representation of all binary data inside sheet * @param boundAggregate -low level representation of all binary data inside sheet
*/ */
HSSFPatriarch(HSSFSheet sheet, EscherAggregate boundAggregate) { HSSFPatriarch(HSSFSheet sheet, EscherAggregate boundAggregate) {
_sheet = sheet; throw new IllegalStateException("support for this has been removed in poi-fast-calc");
_boundAggregate = boundAggregate;
_mainSpgrContainer = _boundAggregate.getEscherContainer().getChildContainers().get(0);
EscherContainerRecord spContainer = (EscherContainerRecord) _boundAggregate.getEscherContainer()
.getChildContainers().get(0).getChild(0);
_spgrRecord = spContainer.getChildById(EscherSpgrRecord.RECORD_ID);
buildShapeTree();
} }
/** /**
@ -223,77 +217,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing<HSSFShap
@Override @Override
public HSSFObjectData createObjectData(ClientAnchor anchor, int storageId, int pictureIndex) { public HSSFObjectData createObjectData(ClientAnchor anchor, int storageId, int pictureIndex) {
ObjRecord obj = new ObjRecord(); throw new IllegalStateException("support for this has been removed in poi-fast-calc");
CommonObjectDataSubRecord ftCmo = new CommonObjectDataSubRecord();
ftCmo.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_PICTURE);
// ftCmo.setObjectId(oleShape.getShapeId()); ... will be set by onCreate(...)
ftCmo.setLocked(true);
ftCmo.setPrintable(true);
ftCmo.setAutofill(true);
ftCmo.setAutoline(true);
ftCmo.setReserved1(0);
ftCmo.setReserved2(0);
ftCmo.setReserved3(0);
obj.addSubRecord(ftCmo);
// FtCf (pictFormat)
FtCfSubRecord ftCf = new FtCfSubRecord();
HSSFPictureData pictData = getSheet().getWorkbook().getAllPictures().get(pictureIndex-1);
switch (pictData.getFormat()) {
case Workbook.PICTURE_TYPE_WMF:
case Workbook.PICTURE_TYPE_EMF:
// this needs patch #49658 to be applied to actually work
ftCf.setFlags(FtCfSubRecord.METAFILE_BIT);
break;
case Workbook.PICTURE_TYPE_DIB:
case Workbook.PICTURE_TYPE_PNG:
case Workbook.PICTURE_TYPE_JPEG:
case Workbook.PICTURE_TYPE_PICT:
ftCf.setFlags(FtCfSubRecord.BITMAP_BIT);
break;
default:
throw new IllegalStateException("Invalid picture type: " + pictData.getFormat());
}
obj.addSubRecord(ftCf);
// FtPioGrbit (pictFlags)
FtPioGrbitSubRecord ftPioGrbit = new FtPioGrbitSubRecord();
ftPioGrbit.setFlagByBit(FtPioGrbitSubRecord.AUTO_PICT_BIT, true);
obj.addSubRecord(ftPioGrbit);
EmbeddedObjectRefSubRecord ftPictFmla = new EmbeddedObjectRefSubRecord();
ftPictFmla.setUnknownFormulaData(new byte[]{2, 0, 0, 0, 0});
ftPictFmla.setOleClassname("Paket");
ftPictFmla.setStorageId(storageId);
obj.addSubRecord(ftPictFmla);
obj.addSubRecord(new EndSubRecord());
String entryName = "MBD"+HexDump.toHex(storageId);
DirectoryEntry oleRoot;
try {
DirectoryNode dn = _sheet.getWorkbook().getDirectory();
if (dn == null) {
throw new FileNotFoundException();
}
oleRoot = (DirectoryEntry)dn.getEntry(entryName);
} catch (FileNotFoundException e) {
throw new IllegalStateException("trying to add ole shape without actually adding data first - use HSSFWorkbook.addOlePackage first", e);
}
// create picture shape, which need to be minimal modified for oleshapes
HSSFPicture shape = new HSSFPicture(null, (HSSFClientAnchor)anchor);
shape.setPictureIndex(pictureIndex);
EscherContainerRecord spContainer = shape.getEscherContainer();
EscherSpRecord spRecord = spContainer.getChildById(EscherSpRecord.RECORD_ID);
spRecord.setFlags(spRecord.getFlags() | EscherSpRecord.FLAG_OLESHAPE);
HSSFObjectData oleShape = new HSSFObjectData(spContainer, obj, oleRoot);
addShape(oleShape);
onCreate(oleShape);
return oleShape;
} }
/** /**
@ -532,26 +456,6 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing<HSSFShap
throw new RuntimeException("NotImplemented"); throw new RuntimeException("NotImplemented");
} }
/**
* create shape tree from existing escher records tree
*/
void buildShapeTree() {
EscherContainerRecord dgContainer = _boundAggregate.getEscherContainer();
if (dgContainer == null) {
return;
}
EscherContainerRecord spgrConrainer = dgContainer.getChildContainers().get(0);
List<EscherContainerRecord> spgrChildren = spgrConrainer.getChildContainers();
for (int i = 0; i < spgrChildren.size(); i++) {
EscherContainerRecord spContainer = spgrChildren.get(i);
if (i != 0) {
HSSFShapeFactory.createShapeTree(spContainer, _boundAggregate, this, _sheet.getWorkbook().getDirectory());
}
}
}
private void setFlipFlags(HSSFShape shape){ private void setFlipFlags(HSSFShape shape){
EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
if (shape.getAnchor().isHorizontallyFlipped()) { if (shape.getAnchor().isHorizontallyFlipped()) {

View File

@ -17,16 +17,8 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import static org.apache.poi.hssf.model.InternalWorkbook.OLD_WORKBOOK_DIR_ENTRY_NAME;
import static org.apache.poi.hssf.model.InternalWorkbook.WORKBOOK_DIR_ENTRY_NAMES; import static org.apache.poi.hssf.model.InternalWorkbook.WORKBOOK_DIR_ENTRY_NAMES;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.nio.charset.Charset; import java.nio.charset.Charset;
@ -75,20 +67,7 @@ import org.apache.poi.hssf.record.SSTRecord;
import org.apache.poi.hssf.record.UnknownRecord; import org.apache.poi.hssf.record.UnknownRecord;
import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor; import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor;
import org.apache.poi.hssf.record.common.UnicodeString; import org.apache.poi.hssf.record.common.UnicodeString;
import org.apache.poi.hssf.record.crypto.Biff8DecryptingStream;
import org.apache.poi.hssf.util.CellReference; import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.poifs.crypt.ChunkedCipherOutputStream;
import org.apache.poi.poifs.crypt.Decryptor;
import org.apache.poi.poifs.crypt.Encryptor;
import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.DocumentNode;
import org.apache.poi.poifs.filesystem.EntryUtils;
import org.apache.poi.poifs.filesystem.FilteringDirectoryNode;
import org.apache.poi.poifs.filesystem.NPOIFSDocument;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.poifs.filesystem.Ole10Native;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.formula.FormulaShifter; import org.apache.poi.ss.formula.FormulaShifter;
import org.apache.poi.ss.formula.FormulaType; import org.apache.poi.ss.formula.FormulaType;
@ -104,9 +83,6 @@ import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.Configurator; import org.apache.poi.util.Configurator;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianByteArrayInputStream;
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import org.apache.poi.util.Removal; import org.apache.poi.util.Removal;
@ -119,7 +95,7 @@ import org.apache.poi.util.Removal;
* @see org.apache.poi.hssf.model.InternalWorkbook * @see org.apache.poi.hssf.model.InternalWorkbook
* @see org.apache.poi.hssf.usermodel.HSSFSheet * @see org.apache.poi.hssf.usermodel.HSSFSheet
*/ */
public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.usermodel.Workbook { public final class HSSFWorkbook implements org.apache.poi.ss.usermodel.Workbook {
private static final Pattern COMMA_PATTERN = Pattern.compile(","); private static final Pattern COMMA_PATTERN = Pattern.compile(",");
/** /**
@ -201,14 +177,14 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
private UDFFinder _udfFinder = new IndexedUDFFinder(AggregatingUDFFinder.DEFAULT); private UDFFinder _udfFinder = new IndexedUDFFinder(AggregatingUDFFinder.DEFAULT);
public static HSSFWorkbook create(InternalWorkbook book) { public static HSSFWorkbook create(InternalWorkbook book) {
return new HSSFWorkbook(book); return new HSSFWorkbook(book, SpreadsheetVersion.EXCEL2007);
} }
/** /**
* Creates new HSSFWorkbook from scratch (start here!) * Creates new HSSFWorkbook from scratch (start here!)
* *
*/ */
public HSSFWorkbook() { public HSSFWorkbook() {
this(InternalWorkbook.createWorkbook()); this(InternalWorkbook.createWorkbook(), SpreadsheetVersion.EXCEL2007);
} }
public HSSFWorkbook(final SpreadsheetVersion spreadsheetVersion) { public HSSFWorkbook(final SpreadsheetVersion spreadsheetVersion) {
@ -217,210 +193,13 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
throw new IllegalArgumentException("SpreadsheetVersion must be non-null"); throw new IllegalArgumentException("SpreadsheetVersion must be non-null");
} }
private HSSFWorkbook(InternalWorkbook book) {
this(book, SpreadsheetVersion.EXCEL97);
}
private HSSFWorkbook(InternalWorkbook book, final SpreadsheetVersion spreadsheetVersion) { private HSSFWorkbook(InternalWorkbook book, final SpreadsheetVersion spreadsheetVersion) {
super((DirectoryNode)null);
this.spreadsheetVersion = spreadsheetVersion; this.spreadsheetVersion = spreadsheetVersion;
workbook = book; workbook = book;
_sheets = new ArrayList<HSSFSheet>(INITIAL_CAPACITY); _sheets = new ArrayList<HSSFSheet>(INITIAL_CAPACITY);
names = new ArrayList<HSSFName>(INITIAL_CAPACITY); names = new ArrayList<HSSFName>(INITIAL_CAPACITY);
} }
/**
* Given a POI POIFSFileSystem object, read in its Workbook along
* with all related nodes, and populate the high and low level models.
* <p>This calls {@link #HSSFWorkbook(POIFSFileSystem, boolean)} with
* preserve nodes set to true.
*
* @see #HSSFWorkbook(POIFSFileSystem, boolean)
* @see org.apache.poi.poifs.filesystem.POIFSFileSystem
* @exception IOException if the stream cannot be read
*/
public HSSFWorkbook(POIFSFileSystem fs) throws IOException {
this(fs,true);
}
/**
* Given a POI POIFSFileSystem object, read in its Workbook along
* with all related nodes, and populate the high and low level models.
* <p>This calls {@link #HSSFWorkbook(POIFSFileSystem, boolean)} with
* preserve nodes set to true.
*
* @see #HSSFWorkbook(POIFSFileSystem, boolean)
* @see org.apache.poi.poifs.filesystem.POIFSFileSystem
* @exception IOException if the stream cannot be read
*/
public HSSFWorkbook(NPOIFSFileSystem fs) throws IOException {
this(fs.getRoot(),true);
}
/**
* Given a POI POIFSFileSystem object, read in its Workbook and populate
* the high and low level models. If you're reading in a workbook... start here!
*
* @param fs the POI filesystem that contains the Workbook stream.
* @param preserveNodes whether to preserve other nodes, such as
* macros. This takes more memory, so only say yes if you
* need to. If set, will store all of the POIFSFileSystem
* in memory
* @see org.apache.poi.poifs.filesystem.POIFSFileSystem
* @exception IOException if the stream cannot be read
*/
public HSSFWorkbook(POIFSFileSystem fs, boolean preserveNodes)
throws IOException {
this(fs.getRoot(), fs, preserveNodes);
}
public static String getWorkbookDirEntryName(DirectoryNode directory) {
for (String wbName : WORKBOOK_DIR_ENTRY_NAMES) {
try {
directory.getEntry(wbName);
return wbName;
} catch (FileNotFoundException e) {
// continue - to try other options
}
}
// check for an encrypted .xlsx file - they get OLE2 wrapped
try {
directory.getEntry(Decryptor.DEFAULT_POIFS_ENTRY);
throw new EncryptedDocumentException("The supplied spreadsheet seems to be an Encrypted .xlsx file. " +
"It must be decrypted before use by XSSF, it cannot be used by HSSF");
} catch (FileNotFoundException e) {
// fall through
}
// check for previous version of file format
try {
directory.getEntry(OLD_WORKBOOK_DIR_ENTRY_NAME);
throw new OldExcelFormatException("The supplied spreadsheet seems to be Excel 5.0/7.0 (BIFF5) format. "
+ "POI only supports BIFF8 format (from Excel versions 97/2000/XP/2003)");
} catch (FileNotFoundException e) {
// fall through
}
throw new IllegalArgumentException("The supplied POIFSFileSystem does not contain a BIFF8 'Workbook' entry. "
+ "Is it really an excel file? Had: " + directory.getEntryNames());
}
/**
* given a POI POIFSFileSystem object, and a specific directory
* within it, read in its Workbook and populate the high and
* low level models. If you're reading in a workbook...start here.
*
* @param directory the POI filesystem directory to process from
* @param fs the POI filesystem that contains the Workbook stream.
* @param preserveNodes whether to preserve other nodes, such as
* macros. This takes more memory, so only say yes if you
* need to. If set, will store all of the POIFSFileSystem
* in memory
* @see org.apache.poi.poifs.filesystem.POIFSFileSystem
* @exception IOException if the stream cannot be read
*/
public HSSFWorkbook(DirectoryNode directory, POIFSFileSystem fs, boolean preserveNodes)
throws IOException
{
this(directory, preserveNodes);
}
/**
* given a POI POIFSFileSystem object, and a specific directory
* within it, read in its Workbook and populate the high and
* low level models. If you're reading in a workbook...start here.
*
* @param directory the POI filesystem directory to process from
* @param preserveNodes whether to preserve other nodes, such as
* macros. This takes more memory, so only say yes if you
* need to. If set, will store all of the POIFSFileSystem
* in memory
* @see org.apache.poi.poifs.filesystem.POIFSFileSystem
* @exception IOException if the stream cannot be read
*/
public HSSFWorkbook(DirectoryNode directory, boolean preserveNodes)
throws IOException
{
super(directory);
spreadsheetVersion = SpreadsheetVersion.EXCEL97;
String workbookName = getWorkbookDirEntryName(directory);
this.preserveNodes = preserveNodes;
// If we're not preserving nodes, don't track the
// POIFS any more
if(! preserveNodes) {
clearDirectory();
}
_sheets = new ArrayList<HSSFSheet>(INITIAL_CAPACITY);
names = new ArrayList<HSSFName>(INITIAL_CAPACITY);
// Grab the data from the workbook stream, however
// it happens to be spelled.
InputStream stream = directory.createDocumentInputStream(workbookName);
List<Record> records = RecordFactory.createRecords(stream);
workbook = InternalWorkbook.createWorkbook(records);
setPropertiesFromWorkbook(workbook);
int recOffset = workbook.getNumRecords();
// convert all LabelRecord records to LabelSSTRecord
convertLabelRecords(records, recOffset);
RecordStream rs = new RecordStream(records, recOffset);
while (rs.hasNext()) {
try {
InternalSheet sheet = InternalSheet.createSheet(rs);
_sheets.add(new HSSFSheet(this, sheet));
} catch (UnsupportedBOFType eb) {
// Hopefully there's a supported one after this!
log.log(POILogger.WARN, "Unsupported BOF found of type " + eb.getType());
}
}
for (int i = 0 ; i < workbook.getNumNames() ; ++i){
NameRecord nameRecord = workbook.getNameRecord(i);
HSSFName name = new HSSFName(this, nameRecord, workbook.getNameCommentRecord(nameRecord));
names.add(name);
}
}
/**
* Companion to HSSFWorkbook(POIFSFileSystem), this constructs the
* POI filesystem around your {@link InputStream}, including all nodes.
* <p>This calls {@link #HSSFWorkbook(InputStream, boolean)} with
* preserve nodes set to true.
*
* @see #HSSFWorkbook(InputStream, boolean)
* @see #HSSFWorkbook(POIFSFileSystem)
* @see org.apache.poi.poifs.filesystem.POIFSFileSystem
* @exception IOException if the stream cannot be read
*/
public HSSFWorkbook(InputStream s) throws IOException {
this(s,true);
}
/**
* Companion to HSSFWorkbook(POIFSFileSystem), this constructs the
* POI filesystem around your {@link InputStream}.
*
* @param s the POI filesystem that contains the Workbook stream.
* @param preserveNodes whether to preserve other nodes, such as
* macros. This takes more memory, so only say yes if you
* need to.
* @see org.apache.poi.poifs.filesystem.POIFSFileSystem
* @see #HSSFWorkbook(POIFSFileSystem)
* @exception IOException if the stream cannot be read
*/
@SuppressWarnings("resource") // NPOIFSFileSystem always closes the stream
public HSSFWorkbook(InputStream s, boolean preserveNodes)
throws IOException
{
this(new NPOIFSFileSystem(s).getRoot(), preserveNodes);
}
/** /**
* used internally to set the workbook properties. * used internally to set the workbook properties.
*/ */
@ -1366,139 +1145,12 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
return new HSSFCellStyle((short)idx, xfr, this); return new HSSFCellStyle((short)idx, xfr, this);
} }
/**
* Closes the underlying {@link NPOIFSFileSystem} from which
* the Workbook was read, if any.
*
* <p>Once this has been called, no further
* operations, updates or reads should be performed on the
* Workbook.
*/
@Override
public void close() throws IOException {
super.close();
}
protected void validateSpreadsheetVersionWritePossible() throws IllegalStateException { protected void validateSpreadsheetVersionWritePossible() throws IllegalStateException {
if (this.spreadsheetVersion != SpreadsheetVersion.EXCEL97) { if (this.spreadsheetVersion != SpreadsheetVersion.EXCEL97) {
throw new IllegalStateException("SpreadsheetVersion not EXCEL97, cannot write file meant only for in-memory calculations"); throw new IllegalStateException("SpreadsheetVersion not EXCEL97, cannot write file meant only for in-memory calculations");
} }
} }
/**
* Write out this workbook to the currently open {@link File} via the
* writeable {@link POIFSFileSystem} it was opened as.
*
* <p>This will fail (with an {@link IllegalStateException} if the
* Workbook was opened read-only, opened from an {@link InputStream}
* instead of a File, or if this is not the root document. For those cases,
* you must use {@link #write(OutputStream)} or {@link #write(File)} to
* write to a brand new document.
*/
@Override
public void write() throws IOException {
validateSpreadsheetVersionWritePossible();
validateInPlaceWritePossible();
final DirectoryNode dir = getDirectory();
// Update the Workbook stream in the file
DocumentNode workbookNode = (DocumentNode)dir.getEntry(
getWorkbookDirEntryName(dir));
NPOIFSDocument workbookDoc = new NPOIFSDocument(workbookNode);
workbookDoc.replaceContents(new ByteArrayInputStream(getBytes()));
// Update the properties streams in the file
writeProperties();
// Sync with the File on disk
dir.getFileSystem().writeFilesystem();
}
/**
* Method write - write out this workbook to a new {@link File}. Constructs
* a new POI POIFSFileSystem, passes in the workbook binary representation and
* writes it out. If the file exists, it will be replaced, otherwise a new one
* will be created.
*
* Note that you cannot write to the currently open File using this method.
* If you opened your Workbook from a File, you <i>must</i> use the {@link #write()}
* method instead!
*
* @param newFile The new File you wish to write the XLS to
*
* @exception IOException if anything can't be written.
* @see org.apache.poi.poifs.filesystem.POIFSFileSystem
*/
@Override
public void write(File newFile) throws IOException {
validateSpreadsheetVersionWritePossible();
POIFSFileSystem fs = POIFSFileSystem.create(newFile);
try {
write(fs);
fs.writeFilesystem();
} finally {
fs.close();
}
}
/**
* Method write - write out this workbook to an {@link OutputStream}. Constructs
* a new POI POIFSFileSystem, passes in the workbook binary representation and
* writes it out.
*
* If {@code stream} is a {@link java.io.FileOutputStream} on a networked drive
* or has a high cost/latency associated with each written byte,
* consider wrapping the OutputStream in a {@link java.io.BufferedOutputStream}
* to improve write performance.
*
* @param stream - the java OutputStream you wish to write the XLS to
*
* @exception IOException if anything can't be written.
* @see org.apache.poi.poifs.filesystem.POIFSFileSystem
*/
@Override
public void write(OutputStream stream) throws IOException {
validateSpreadsheetVersionWritePossible();
NPOIFSFileSystem fs = new NPOIFSFileSystem();
try {
write(fs);
fs.writeFilesystem(stream);
} finally {
fs.close();
}
}
/** Writes the workbook out to a brand new, empty POIFS */
private void write(NPOIFSFileSystem fs) throws IOException {
validateSpreadsheetVersionWritePossible();
// For tracking what we've written out, used if we're
// going to be preserving nodes
List<String> excepts = new ArrayList<String>(1);
// Write out the Workbook stream
fs.createDocument(new ByteArrayInputStream(getBytes()), "Workbook");
// Write out our HPFS properties, if we have them
writeProperties(fs, excepts);
if (preserveNodes) {
// Don't write out the old Workbook, we'll be doing our new one
// If the file had an "incorrect" name for the workbook stream,
// don't write the old one as we'll use the correct name shortly
excepts.addAll(Arrays.asList(WORKBOOK_DIR_ENTRY_NAMES));
// Copy over all the other nodes to our new poifs
EntryUtils.copyNodes(
new FilteringDirectoryNode(getDirectory(), excepts)
, new FilteringDirectoryNode(fs.getRoot(), excepts)
);
// YK: preserve StorageClsid, it is important for embedded workbooks,
// see Bugzilla 47920
fs.getRoot().setStorageClsid(getDirectory().getStorageClsid());
}
}
/** /**
* Totals the sizes of all sheet records and eventually serializes them * Totals the sizes of all sheet records and eventually serializes them
*/ */
@ -1529,125 +1181,6 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
} }
} }
/**
* Method getBytes - get the bytes of just the HSSF portions of the XLS file.
* Use this to construct a POI POIFSFileSystem yourself.
*
*
* @return byte[] array containing the binary representation of this workbook and all contained
* sheets, rows, cells, etc.
*/
public byte[] getBytes() {
if (log.check( POILogger.DEBUG )) {
log.log(DEBUG, "HSSFWorkbook.getBytes()");
}
HSSFSheet[] sheets = getSheets();
int nSheets = sheets.length;
// before getting the workbook size we must tell the sheets that
// serialization is about to occur.
workbook.preSerialize();
for (HSSFSheet sheet : sheets) {
sheet.getSheet().preSerialize();
sheet.preSerialize();
}
int totalsize = workbook.getSize();
// pre-calculate all the sheet sizes and set BOF indexes
SheetRecordCollector[] srCollectors = new SheetRecordCollector[nSheets];
for (int k = 0; k < nSheets; k++) {
workbook.setSheetBof(k, totalsize);
SheetRecordCollector src = new SheetRecordCollector();
sheets[k].getSheet().visitContainedRecords(src, totalsize);
totalsize += src.getTotalSize();
srCollectors[k] = src;
}
byte[] retval = new byte[totalsize];
int pos = workbook.serialize(0, retval);
for (int k = 0; k < nSheets; k++) {
SheetRecordCollector src = srCollectors[k];
int serializedSize = src.serialize(pos, retval);
if (serializedSize != src.getTotalSize()) {
// Wrong offset values have been passed in the call to setSheetBof() above.
// For books with more than one sheet, this discrepancy would cause excel
// to report errors and loose data while reading the workbook
throw new IllegalStateException("Actual serialized sheet size (" + serializedSize
+ ") differs from pre-calculated size (" + src.getTotalSize()
+ ") for sheet (" + k + ")");
// TODO - add similar sanity check to ensure that Sheet.serializeIndexRecord() does not write mis-aligned offsets either
}
pos += serializedSize;
}
encryptBytes(retval);
return retval;
}
@SuppressWarnings("resource")
protected void encryptBytes(byte buf[]) {
int initialOffset = 0;
FilePassRecord fpr = null;
for (Record r : workbook.getRecords()) {
initialOffset += r.getRecordSize();
if (r instanceof FilePassRecord) {
fpr = (FilePassRecord)r;
break;
}
}
if (fpr == null) {
return;
}
LittleEndianByteArrayInputStream plain = new LittleEndianByteArrayInputStream(buf, 0); // NOSONAR
LittleEndianByteArrayOutputStream leos = new LittleEndianByteArrayOutputStream(buf, 0); // NOSONAR
Encryptor enc = fpr.getEncryptionInfo().getEncryptor();
enc.setChunkSize(Biff8DecryptingStream.RC4_REKEYING_INTERVAL);
byte tmp[] = new byte[1024];
try {
ChunkedCipherOutputStream os = enc.getDataStream(leos, initialOffset);
int totalBytes = 0;
while (totalBytes < buf.length) {
plain.read(tmp, 0, 4);
final int sid = LittleEndian.getUShort(tmp, 0);
final int len = LittleEndian.getUShort(tmp, 2);
boolean isPlain = Biff8DecryptingStream.isNeverEncryptedRecord(sid);
os.setNextRecordSize(len, isPlain);
os.writePlain(tmp, 0, 4);
if (sid == BoundSheetRecord.sid) {
// special case for the field_1_position_of_BOF (=lbPlyPos) field of
// the BoundSheet8 record which must be unencrypted
byte bsrBuf[] = new byte[len];
plain.readFully(bsrBuf);
os.writePlain(bsrBuf, 0, 4);
os.write(bsrBuf, 4, len-4);
} else {
int todo = len;
while (todo > 0) {
int nextLen = Math.min(todo, tmp.length);
plain.readFully(tmp, 0, nextLen);
if (isPlain) {
os.writePlain(tmp, 0, nextLen);
} else {
os.write(tmp, 0, nextLen);
}
todo -= nextLen;
}
}
totalBytes += 4 + len;
}
os.close();
} catch (Exception e) {
throw new EncryptedDocumentException(e);
}
}
/*package*/ InternalWorkbook getWorkbook() { /*package*/ InternalWorkbook getWorkbook() {
return workbook; return workbook;
} }
@ -1996,65 +1529,6 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
return olemap; return olemap;
} }
/**
* Adds an OLE package manager object with the given POIFS to the sheet
*
* @param poiData an POIFS containing the embedded document, to be added
* @param label the label of the payload
* @param fileName the original filename
* @param command the command to open the payload
* @return the index of the added ole object
* @throws IOException if the object can't be embedded
*/
public int addOlePackage(POIFSFileSystem poiData, String label, String fileName, String command)
throws IOException {
DirectoryNode root = poiData.getRoot();
Map<String,ClassID> olemap = getOleMap();
for (Map.Entry<String,ClassID> entry : olemap.entrySet()) {
if (root.hasEntry(entry.getKey())) {
root.setStorageClsid(entry.getValue());
break;
}
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
poiData.writeFilesystem(bos);
return addOlePackage(bos.toByteArray(), label, fileName, command);
}
@Override
public int addOlePackage(byte[] oleData, String label, String fileName, String command)
throws IOException {
// check if we were created by POIFS otherwise create a new dummy POIFS for storing the package data
if (initDirectory()) {
preserveNodes = true;
}
// get free MBD-Node
int storageId = 0;
DirectoryEntry oleDir = null;
do {
String storageStr = "MBD"+ HexDump.toHex(++storageId);
if (!getDirectory().hasEntry(storageStr)) {
oleDir = getDirectory().createDirectory(storageStr);
oleDir.setStorageClsid(ClassID.OLE10_PACKAGE);
}
} while (oleDir == null);
// the following data was taken from an example libre office document
// beside this "\u0001Ole" record there were several other records, e.g. CompObj,
// OlePresXXX, but it seems, that they aren't neccessary
byte oleBytes[] = { 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
oleDir.createDocument("\u0001Ole", new ByteArrayInputStream(oleBytes));
Ole10Native oleNative = new Ole10Native(label, fileName, command, oleData);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
oleNative.writeOut(bos);
oleDir.createDocument(Ole10Native.OLE10_NATIVE, new ByteArrayInputStream(bos.toByteArray()));
return storageId;
}
/** /**
* Adds the LinkTable records required to allow formulas referencing * Adds the LinkTable records required to allow formulas referencing
* the specified external workbook to be added to this one. Allows * the specified external workbook to be added to this one. Allows
@ -2234,15 +1708,6 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
return workbook.changeExternalReference(oldUrl, newUrl); return workbook.changeExternalReference(oldUrl, newUrl);
} }
/**
* @deprecated POI 3.16 beta 1. use {@link POIDocument#getDirectory()} instead
*/
@Deprecated
@Removal(version="3.18")
public DirectoryNode getRootDirectory(){
return getDirectory();
}
@Internal @Internal
public InternalWorkbook getInternalWorkbook() { public InternalWorkbook getInternalWorkbook() {
return workbook; return workbook;

View File

@ -17,7 +17,6 @@
package org.apache.poi.ss.usermodel; package org.apache.poi.ss.usermodel;
import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Iterator; import java.util.Iterator;
@ -33,7 +32,7 @@ import org.apache.poi.util.Removal;
* will construct whether they are reading or writing a workbook. It is also the * will construct whether they are reading or writing a workbook. It is also the
* top level object for creating new sheets/etc. * top level object for creating new sheets/etc.
*/ */
public interface Workbook extends Closeable, Iterable<Sheet> { public interface Workbook extends Iterable<Sheet> {
/** Extended windows meta file */ /** Extended windows meta file */
int PICTURE_TYPE_EMF = 2; int PICTURE_TYPE_EMF = 2;
@ -344,25 +343,6 @@ public interface Workbook extends Closeable, Iterable<Sheet> {
*/ */
CellStyle getCellStyleAt(int idx); CellStyle getCellStyleAt(int idx);
/**
* Write out this workbook to an Outputstream.
*
* @param stream - the java OutputStream you wish to write to
* @exception IOException if anything can't be written.
*/
void write(OutputStream stream) throws IOException;
/**
* Close the underlying input resource (File or Stream),
* from which the Workbook was read.
*
* <p>Once this has been called, no further
* operations, updates or reads should be performed on the
* Workbook.
*/
@Override
void close() throws IOException;
/** /**
* @return the total number of defined names in this workbook * @return the total number of defined names in this workbook
*/ */
@ -657,20 +637,6 @@ public interface Workbook extends Closeable, Iterable<Sheet> {
*/ */
SpreadsheetVersion getSpreadsheetVersion(); SpreadsheetVersion getSpreadsheetVersion();
/**
* Adds an OLE package manager object with the given content to the sheet
*
* @param oleData the payload
* @param label the label of the payload
* @param fileName the original filename
* @param command the command to open the payload
*
* @return the index of the added ole object, i.e. the storage id
*
* @throws IOException if the object can't be embedded
*/
int addOlePackage(byte[] oleData, String label, String fileName, String command) throws IOException;
/** /**
* Whether a call to {@link Cell#setCellFormula(String)} will validate the formula or not. * Whether a call to {@link Cell#setCellFormula(String)} will validate the formula or not.
* *

View File

@ -1,57 +0,0 @@
/* ====================================================================
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.util;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.ss.usermodel.Sheet;
/**
* Dump out the aggregated escher records
*/
public class DrawingDump
{
public static void main( String[] args ) throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(System.out, Charset.defaultCharset());
PrintWriter pw = new PrintWriter(osw);
NPOIFSFileSystem fs = new NPOIFSFileSystem(new File(args[0]));
HSSFWorkbook wb = new HSSFWorkbook(fs);
try {
pw.println( "Drawing group:" );
wb.dumpDrawingGroupRecords(true);
int i = 1;
for (Sheet sheet : wb)
{
pw.println( "Sheet " + i + "(" + sheet.getSheetName() + "):" );
((HSSFSheet) sheet).dumpDrawingRecords(true, pw);
}
} finally {
wb.close();
fs.close();
}
}
}

View File

@ -1,5 +1,6 @@
//package org.apache.poi.hssf.usermodel.examples; //package org.apache.poi.hssf.usermodel.examples;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.junit.Test; import org.junit.Test;
import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.usermodel.*;
@ -39,9 +40,9 @@ public class CalculationTest {
public static void runAssert(final int maxRow, final double expected) { public static void runAssert(final int maxRow, final double expected) {
//runAssert(new org.apache.poi.hssf.usermodel.GenericSSEvaluationWorkbook(), maxRow, expected); //runAssert(new org.apache.poi.hssf.usermodel.GenericSSEvaluationWorkbook(), maxRow, expected);
runAssert(new org.apache.poi.hssf.usermodel.HSSFWorkbook(SpreadsheetVersion.EXCEL2007), maxRow, expected); runAssert(new org.apache.poi.hssf.usermodel.HSSFWorkbook(), maxRow, expected);
if(maxRow <= SpreadsheetVersion.EXCEL97.getMaxRows()) if(maxRow <= SpreadsheetVersion.EXCEL97.getMaxRows())
runAssert(new org.apache.poi.hssf.usermodel.HSSFWorkbook(), maxRow, expected); runAssert(new org.apache.poi.hssf.usermodel.HSSFWorkbook(SpreadsheetVersion.EXCEL97), maxRow, expected);
//runAssert(newXSSFWorkbookNoFormulaValidation(), maxRow, expected); //runAssert(newXSSFWorkbookNoFormulaValidation(), maxRow, expected);
} }