From 463e00558d60a41015e581a8e4f53661952b3f05 Mon Sep 17 00:00:00 2001 From: moparisthebest Date: Tue, 26 Mar 2019 14:55:35 -0400 Subject: [PATCH] Remove any reading/writing to files code from HSSFWorkbook --- .../apache/poi/hssf/dev/BiffDrawingToXml.java | 164 ---- .../org/apache/poi/hssf/dev/BiffViewer.java | 876 ------------------ .../org/apache/poi/hssf/dev/EFBiffViewer.java | 94 -- .../apache/poi/hssf/dev/FormulaViewer.java | 236 ----- .../java/org/apache/poi/hssf/dev/ReSave.java | 83 -- .../org/apache/poi/hssf/dev/RecordLister.java | 202 ---- .../java/org/apache/poi/hssf/dev/package.html | 36 - .../extractor/EventBasedExcelExtractor.java | 266 ------ .../poi/hssf/extractor/ExcelExtractor.java | 421 --------- .../poi/hssf/extractor/OldExcelExtractor.java | 324 ------- .../poi/hssf/model/InternalWorkbook.java | 1 - .../poi/hssf/record/RecordInputStream.java | 1 - .../poi/hssf/usermodel/HSSFPatriarch.java | 100 +- .../poi/hssf/usermodel/HSSFWorkbook.java | 541 +---------- .../org/apache/poi/ss/usermodel/Workbook.java | 36 +- .../java/org/apache/poi/util/DrawingDump.java | 57 -- src/test/java/CalculationTest.java | 5 +- 17 files changed, 9 insertions(+), 3434 deletions(-) delete mode 100644 src/main/java/org/apache/poi/hssf/dev/BiffDrawingToXml.java delete mode 100644 src/main/java/org/apache/poi/hssf/dev/BiffViewer.java delete mode 100644 src/main/java/org/apache/poi/hssf/dev/EFBiffViewer.java delete mode 100644 src/main/java/org/apache/poi/hssf/dev/FormulaViewer.java delete mode 100644 src/main/java/org/apache/poi/hssf/dev/ReSave.java delete mode 100644 src/main/java/org/apache/poi/hssf/dev/RecordLister.java delete mode 100644 src/main/java/org/apache/poi/hssf/dev/package.html delete mode 100644 src/main/java/org/apache/poi/hssf/extractor/EventBasedExcelExtractor.java delete mode 100644 src/main/java/org/apache/poi/hssf/extractor/ExcelExtractor.java delete mode 100644 src/main/java/org/apache/poi/hssf/extractor/OldExcelExtractor.java delete mode 100644 src/main/java/org/apache/poi/util/DrawingDump.java diff --git a/src/main/java/org/apache/poi/hssf/dev/BiffDrawingToXml.java b/src/main/java/org/apache/poi/hssf/dev/BiffDrawingToXml.java deleted file mode 100644 index 9af510443..000000000 --- a/src/main/java/org/apache/poi/hssf/dev/BiffDrawingToXml.java +++ /dev/null @@ -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 getIndexesByName(String[] params, HSSFWorkbook workbook) { - List list = new ArrayList(); - 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 getIndexesByIdArray(String[] params) { - List list = new ArrayList(); - 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 getSheetsIndexes(String[] params, HSSFWorkbook workbook) { - List list = new ArrayList(); - 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 output sheets with specified indexes"); - System.out.println(" -sheet-namek 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("\n"); - String tab = "\t"; - if (!excludeWorkbookRecords && r != null) { - r.decode(); - List escherRecords = r.getEscherRecords(); - for (EscherRecord record : escherRecords) { - builder.append(record.toXml(tab)); - } - } - List sheets = getSheetsIndexes(params, workbook); - for (Integer i : sheets) { - HSSFPatriarch p = workbook.getSheetAt(i).getDrawingPatriarch(); - if(p != null ) { - builder.append(tab).append("\n"); - builder.append(p.getBoundAggregate().toXml(tab + "\t")); - builder.append(tab).append("\n"); - } - } - builder.append("\n"); - fos.write(builder.toString().getBytes(StringUtil.UTF8)); - fos.close(); - workbook.close(); - } - -} diff --git a/src/main/java/org/apache/poi/hssf/dev/BiffViewer.java b/src/main/java/org/apache/poi/hssf/dev/BiffViewer.java deleted file mode 100644 index d6b8777a3..000000000 --- a/src/main/java/org/apache/poi/hssf/dev/BiffViewer.java +++ /dev/null @@ -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 temp = new ArrayList(); - - 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 - * - * Usage:

- * - * BiffViewer [--biffhex] [--noint] [--noescher] [--out] <fileName>

- * BiffViewer --rawhex [--out] <fileName> - * - * - * - * - * - * - * - * - *
--biffhexshow hex dump of each BIFF record
--nointdo not output interpretation of BIFF records
--outsend output to <fileName>.out
--rawhexoutput raw hex dump of whole workbook stream
--escherturn on deserialization of escher records (default is off)
--noheaderdo not print record header (default is on)
- * - * @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 _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(); - } - - @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 getRecentHeaders() { - List result = _headers; - _headers = new ArrayList(); - 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; - } - } -} diff --git a/src/main/java/org/apache/poi/hssf/dev/EFBiffViewer.java b/src/main/java/org/apache/poi/hssf/dev/EFBiffViewer.java deleted file mode 100644 index b136e4ca8..000000000 --- a/src/main/java/org/apache/poi/hssf/dev/EFBiffViewer.java +++ /dev/null @@ -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"); - } - } -} diff --git a/src/main/java/org/apache/poi/hssf/dev/FormulaViewer.java b/src/main/java/org/apache/poi/hssf/dev/FormulaViewer.java deleted file mode 100644 index 3426d4a09..000000000 --- a/src/main/java/org/apache/poi/hssf/dev/FormulaViewer.java +++ /dev/null @@ -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 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(); - } - } -} diff --git a/src/main/java/org/apache/poi/hssf/dev/ReSave.java b/src/main/java/org/apache/poi/hssf/dev/ReSave.java deleted file mode 100644 index 7f1988897..000000000 --- a/src/main/java/org/apache/poi/hssf/dev/ReSave.java +++ /dev/null @@ -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(); - } - } - } - } -} diff --git a/src/main/java/org/apache/poi/hssf/dev/RecordLister.java b/src/main/java/org/apache/poi/hssf/dev/RecordLister.java deleted file mode 100644 index 8cb71e5da..000000000 --- a/src/main/java/org/apache/poi/hssf/dev/RecordLister.java +++ /dev/null @@ -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 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 - - - - - - -DEV package serves two purposes. 1. Examples for how to use HSSF and 2. tools for developing -and validating HSSF. - -

Related Documentation

- -For overviews, tutorials, examples, guides, and tool documentation, please see: - - - - diff --git a/src/main/java/org/apache/poi/hssf/extractor/EventBasedExcelExtractor.java b/src/main/java/org/apache/poi/hssf/extractor/EventBasedExcelExtractor.java deleted file mode 100644 index 107602d1c..000000000 --- a/src/main/java/org/apache/poi/hssf/extractor/EventBasedExcelExtractor.java +++ /dev/null @@ -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. - *

- * To turn an excel file into a CSV or similar, then see - * the XLS2CSVmra example - *

- * - * @see XLS2CSVmra - */ -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 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(); - } - 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); - } - } - } -} diff --git a/src/main/java/org/apache/poi/hssf/extractor/ExcelExtractor.java b/src/main/java/org/apache/poi/hssf/extractor/ExcelExtractor.java deleted file mode 100644 index c4eb04731..000000000 --- a/src/main/java/org/apache/poi/hssf/extractor/ExcelExtractor.java +++ /dev/null @@ -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. - *

- * Returns the textual content of the file, suitable for - * indexing by something like Lucene, but not really - * intended for display to the user. - *

- *

- * To turn an excel file into a CSV or similar, then see - * the XLS2CSVmra example - *

- * - * @see XLS2CSVmra - */ -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) { - 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() + " [ [ [...]]] [-i ]"); - ps.println(" -i 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 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(); - } -} diff --git a/src/main/java/org/apache/poi/hssf/extractor/OldExcelExtractor.java b/src/main/java/org/apache/poi/hssf/extractor/OldExcelExtractor.java deleted file mode 100644 index 922db321c..000000000 --- a/src/main/java/org/apache/poi/hssf/extractor/OldExcelExtractor.java +++ /dev/null @@ -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. - *

- * 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. - *

- */ -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 "); - 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'); - } -} diff --git a/src/main/java/org/apache/poi/hssf/model/InternalWorkbook.java b/src/main/java/org/apache/poi/hssf/model/InternalWorkbook.java index 7bddcdd67..454bdc7b5 100644 --- a/src/main/java/org/apache/poi/hssf/model/InternalWorkbook.java +++ b/src/main/java/org/apache/poi/hssf/model/InternalWorkbook.java @@ -42,7 +42,6 @@ import org.apache.poi.ddf.EscherRecord; import org.apache.poi.ddf.EscherSimpleProperty; import org.apache.poi.ddf.EscherSpRecord; 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.BackupRecord; import org.apache.poi.hssf.record.BookBoolRecord; diff --git a/src/main/java/org/apache/poi/hssf/record/RecordInputStream.java b/src/main/java/org/apache/poi/hssf/record/RecordInputStream.java index 8fd042393..bc4884d24 100644 --- a/src/main/java/org/apache/poi/hssf/record/RecordInputStream.java +++ b/src/main/java/org/apache/poi/hssf/record/RecordInputStream.java @@ -22,7 +22,6 @@ import java.io.IOException; import java.io.InputStream; import java.util.Locale; -import org.apache.poi.hssf.dev.BiffViewer; import org.apache.poi.hssf.record.crypto.Biff8DecryptingStream; import org.apache.poi.poifs.crypt.EncryptionInfo; import org.apache.poi.util.Internal; diff --git a/src/main/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java b/src/main/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java index d7baeb58e..c0da6f191 100644 --- a/src/main/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java +++ b/src/main/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java @@ -80,13 +80,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing 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){ EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID); if (shape.getAnchor().isHorizontallyFlipped()) { diff --git a/src/main/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/src/main/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java index 51360f014..39a8b6cf0 100644 --- a/src/main/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java +++ b/src/main/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java @@ -17,16 +17,8 @@ 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 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.PrintWriter; 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.aggregates.RecordAggregate.RecordVisitor; 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.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.formula.FormulaShifter; 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.HexDump; 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.POILogger; 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.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(","); /** @@ -201,14 +177,14 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss private UDFFinder _udfFinder = new IndexedUDFFinder(AggregatingUDFFinder.DEFAULT); public static HSSFWorkbook create(InternalWorkbook book) { - return new HSSFWorkbook(book); + return new HSSFWorkbook(book, SpreadsheetVersion.EXCEL2007); } /** * Creates new HSSFWorkbook from scratch (start here!) * */ public HSSFWorkbook() { - this(InternalWorkbook.createWorkbook()); + this(InternalWorkbook.createWorkbook(), SpreadsheetVersion.EXCEL2007); } 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"); } - private HSSFWorkbook(InternalWorkbook book) { - this(book, SpreadsheetVersion.EXCEL97); - } - private HSSFWorkbook(InternalWorkbook book, final SpreadsheetVersion spreadsheetVersion) { - super((DirectoryNode)null); this.spreadsheetVersion = spreadsheetVersion; workbook = book; _sheets = new ArrayList(INITIAL_CAPACITY); names = new ArrayList(INITIAL_CAPACITY); } - /** - * Given a POI POIFSFileSystem object, read in its Workbook along - * with all related nodes, and populate the high and low level models. - *

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. - *

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(INITIAL_CAPACITY); - names = new ArrayList(INITIAL_CAPACITY); - - // Grab the data from the workbook stream, however - // it happens to be spelled. - InputStream stream = directory.createDocumentInputStream(workbookName); - - List 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. - *

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. */ @@ -1366,139 +1145,12 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss return new HSSFCellStyle((short)idx, xfr, this); } - /** - * Closes the underlying {@link NPOIFSFileSystem} from which - * the Workbook was read, if any. - * - *

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 { if (this.spreadsheetVersion != SpreadsheetVersion.EXCEL97) { 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. - * - *

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 must 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 excepts = new ArrayList(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 */ @@ -1528,125 +1180,6 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss return result; } } - - - /** - * 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() { return workbook; @@ -1996,65 +1529,6 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss 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 olemap = getOleMap(); - for (Map.Entry 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 * the specified external workbook to be added to this one. Allows @@ -2233,15 +1707,6 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss public boolean changeExternalReference(String oldUrl, String 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 public InternalWorkbook getInternalWorkbook() { diff --git a/src/main/java/org/apache/poi/ss/usermodel/Workbook.java b/src/main/java/org/apache/poi/ss/usermodel/Workbook.java index ad40b331b..f31803229 100644 --- a/src/main/java/org/apache/poi/ss/usermodel/Workbook.java +++ b/src/main/java/org/apache/poi/ss/usermodel/Workbook.java @@ -17,7 +17,6 @@ package org.apache.poi.ss.usermodel; -import java.io.Closeable; import java.io.IOException; import java.io.OutputStream; 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 * top level object for creating new sheets/etc. */ -public interface Workbook extends Closeable, Iterable { +public interface Workbook extends Iterable { /** Extended windows meta file */ int PICTURE_TYPE_EMF = 2; @@ -344,25 +343,6 @@ public interface Workbook extends Closeable, Iterable { */ 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. - * - *

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 */ @@ -657,20 +637,6 @@ public interface Workbook extends Closeable, Iterable { */ 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. * diff --git a/src/main/java/org/apache/poi/util/DrawingDump.java b/src/main/java/org/apache/poi/util/DrawingDump.java deleted file mode 100644 index bc06bcfc1..000000000 --- a/src/main/java/org/apache/poi/util/DrawingDump.java +++ /dev/null @@ -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(); - } - } -} diff --git a/src/test/java/CalculationTest.java b/src/test/java/CalculationTest.java index 66f12d187..1f43035d4 100644 --- a/src/test/java/CalculationTest.java +++ b/src/test/java/CalculationTest.java @@ -1,5 +1,6 @@ //package org.apache.poi.hssf.usermodel.examples; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.junit.Test; import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.usermodel.*; @@ -39,9 +40,9 @@ public class CalculationTest { 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.HSSFWorkbook(SpreadsheetVersion.EXCEL2007), maxRow, expected); + runAssert(new org.apache.poi.hssf.usermodel.HSSFWorkbook(), maxRow, expected); 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); }