/** * Writes out the MsoDrawing records and Obj records for each image * and chart on the sheet * * @param outputFile the output file * @exception IOException */ public void write(File outputFile) { // If there are no drawings or charts on this sheet then exit if (drawings.Count == 0 && charts.Length == 0) return; // See if any drawing has been modified bool modified = drawingsModified; int numImages = drawings.Count; foreach (DrawingGroupObject d in drawings) { if (d.getOrigin() != Origin.READ) modified = true; } // If the drawing order has been muddled at all, then we'll need // to regenerate the Escher drawing data if (numImages > 0 && !modified) { DrawingGroupObject d2 = (DrawingGroupObject)drawings[0]; if (!d2.isFirst()) modified = true; } // Check to see if this sheet consists of just a single chart. If so // there is no MsoDrawingRecord, so write out the data and exit if (numImages == 0 && charts.Length == 1 && charts[0].getMsoDrawingRecord() == null) modified = false; // this sheet has not been modified // If no drawing has been modified, then simply write them straight out // again and exit if (!modified) { writeUnmodified(outputFile); return; } object[] spContainerData = new object[numImages + charts.Length]; int length = 0; EscherContainer firstSpContainer = null; // Get all the spContainer byte data from the drawings // and store in an array for (int i = 0; i < numImages; i++) { DrawingGroupObject drawing = (DrawingGroupObject)drawings[i]; EscherContainer spc = drawing.getSpContainer(); if (spc != null) { byte[] data = spc.getData(); spContainerData[i] = data; if (i == 0) { firstSpContainer = spc; } else { length += data.Length; } } } // Get all the spContainer bytes from the charts and add to the array for (int i = 0; i < charts.Length; i++) { EscherContainer spContainer = charts[i].getSpContainer(); byte[] data = spContainer.getBytes(); //use getBytes instead of getData data = spContainer.setHeaderData(data); spContainerData[i + numImages] = data; if (i == 0 && numImages == 0) firstSpContainer = spContainer; else length += data.Length; } // Put the generalised stuff around the first item DgContainer dgContainer = new DgContainer(); Dg dg = new Dg(numImages + charts.Length); dgContainer.add(dg); SpgrContainer spgrContainer = new SpgrContainer(); SpContainer _spContainer = new SpContainer(); Spgr spgr = new Spgr(); _spContainer.add(spgr); Sp sp = new Sp(ShapeType.MIN,1024,5); _spContainer.add(sp); spgrContainer.add(_spContainer); spgrContainer.add(firstSpContainer); dgContainer.add(spgrContainer); byte[] firstMsoData = dgContainer.getData(); // Adjust the length of the DgContainer int len = IntegerHelper.getInt(firstMsoData[4], firstMsoData[5], firstMsoData[6], firstMsoData[7]); IntegerHelper.getFourBytes(len + length,firstMsoData,4); // Adjust the length of the SpgrContainer len = IntegerHelper.getInt(firstMsoData[28], firstMsoData[29], firstMsoData[30], firstMsoData[31]); IntegerHelper.getFourBytes(len + length,firstMsoData,28); // Now write out each MsoDrawing record // First MsoRecord // test hack for form objects, to remove the ClientTextBox record // from the end of the SpContainer if (numImages > 0 && ((DrawingGroupObject)drawings[0]).isFormObject()) { byte[] msodata2 = new byte[firstMsoData.Length - 8]; System.Array.Copy(firstMsoData,0,msodata2,0,msodata2.Length); firstMsoData = msodata2; } MsoDrawingRecord msoDrawingRecord = new MsoDrawingRecord(firstMsoData); outputFile.write(msoDrawingRecord); if (numImages > 0) { DrawingGroupObject firstDrawing = (DrawingGroupObject)drawings[0]; firstDrawing.writeAdditionalRecords(outputFile); } else { // first image is a chart Chart chart = charts[0]; ObjRecord objRecord = chart.getObjRecord(); outputFile.write(objRecord); outputFile.write(chart); } // Now do all the others for (int i = 1; i < spContainerData.Length; i++) { byte[] bytes = (byte[])spContainerData[i]; // test hack for form objects, to remove the ClientTextBox record // from the end of the SpContainer if (i < numImages && ((DrawingGroupObject)drawings[i]).isFormObject()) { byte[] bytes2 = new byte[bytes.Length - 8]; System.Array.Copy(bytes,0,bytes2,0,bytes2.Length); bytes = bytes2; } msoDrawingRecord = new MsoDrawingRecord(bytes); outputFile.write(msoDrawingRecord); if (i < numImages) { // Write anything else the object needs DrawingGroupObject d = (DrawingGroupObject)drawings[i]; d.writeAdditionalRecords(outputFile); } else { Chart chart = charts[i - numImages]; ObjRecord objRecord = chart.getObjRecord(); outputFile.write(objRecord); outputFile.write(chart); } } // Write any tail records that need to be written foreach (DrawingGroupObject dgo2 in drawings) dgo2.writeTailRecords(outputFile); }
/** * Writes out the drawings and the charts if nothing has been modified * * @param outputFile the output file * @exception IOException */ private void writeUnmodified(File outputFile) { if (charts.Length == 0 && drawings.Count == 0) { // No drawings or charts return; } else if (charts.Length == 0 && drawings.Count != 0) { // If there are no charts, then write out the drawings and return foreach (DrawingGroupObject d in drawings) { outputFile.write(d.getMsoDrawingRecord()); d.writeAdditionalRecords(outputFile); } foreach (DrawingGroupObject d in drawings) d.writeTailRecords(outputFile); return; } else if (drawings.Count == 0 && charts.Length != 0) { // If there are no drawings, then write out the charts and return Chart curChart = null; for (int i = 0; i < charts.Length; i++) { curChart = charts[i]; if (curChart.getMsoDrawingRecord() != null) outputFile.write(curChart.getMsoDrawingRecord()); if (curChart.getObjRecord() != null) outputFile.write(curChart.getObjRecord()); outputFile.write(curChart); } return; } // There are both charts and drawings - the output // drawing group records will need // to be re-jigged in order to write the drawings out first, then the // charts int numDrawings = drawings.Count; int length = 0; EscherContainer[] spContainers = new EscherContainer[numDrawings + charts.Length]; bool[] isFormobject = new bool[numDrawings + charts.Length]; for (int i = 0; i < numDrawings; i++) { DrawingGroupObject d = (DrawingGroupObject)drawings[i]; spContainers[i] = d.getSpContainer(); if (i > 0) length += spContainers[i].getLength(); if (d.isFormObject()) isFormobject[i] = true; } for (int i = 0; i < charts.Length; i++) { spContainers[i + numDrawings] = charts[i].getSpContainer(); length += spContainers[i + numDrawings].getLength(); } // Put the generalised stuff around the first item DgContainer dgContainer = new DgContainer(); Dg dg = new Dg(numDrawings + charts.Length); dgContainer.add(dg); SpgrContainer spgrContainer = new SpgrContainer(); SpContainer spContainer = new SpContainer(); Spgr spgr = new Spgr(); spContainer.add(spgr); Sp sp = new Sp(ShapeType.MIN,1024,5); spContainer.add(sp); spgrContainer.add(spContainer); spgrContainer.add(spContainers[0]); dgContainer.add(spgrContainer); byte[] firstMsoData = dgContainer.getData(); // Adjust the length of the DgContainer int len = IntegerHelper.getInt(firstMsoData[4], firstMsoData[5], firstMsoData[6], firstMsoData[7]); IntegerHelper.getFourBytes(len + length,firstMsoData,4); // Adjust the length of the SpgrContainer len = IntegerHelper.getInt(firstMsoData[28], firstMsoData[29], firstMsoData[30], firstMsoData[31]); IntegerHelper.getFourBytes(len + length,firstMsoData,28); // Now write out each MsoDrawing record and object record // Hack to remove the last eight bytes (text box escher record) // from the container if (isFormobject[0] == true) { byte[] cbytes = new byte[firstMsoData.Length - 8]; System.Array.Copy(firstMsoData,0,cbytes,0,cbytes.Length); firstMsoData = cbytes; } // First MsoRecord MsoDrawingRecord msoDrawingRecord = new MsoDrawingRecord(firstMsoData); outputFile.write(msoDrawingRecord); DrawingGroupObject dgo = (DrawingGroupObject)drawings[0]; dgo.writeAdditionalRecords(outputFile); // Now do all the others for (int i = 1; i < spContainers.Length; i++) { byte[] bytes = spContainers[i].getBytes(); byte[] bytes2 = spContainers[i].setHeaderData(bytes); // Hack to remove the last eight bytes (text box escher record) // from the container if (isFormobject[i] == true) { byte[] cbytes = new byte[bytes2.Length - 8]; System.Array.Copy(bytes2,0,cbytes,0,cbytes.Length); bytes2 = cbytes; } msoDrawingRecord = new MsoDrawingRecord(bytes2); outputFile.write(msoDrawingRecord); if (i < numDrawings) { dgo = (DrawingGroupObject)drawings[i]; dgo.writeAdditionalRecords(outputFile); } else { Chart chart = charts[i - numDrawings]; ObjRecord objRecord = chart.getObjRecord(); outputFile.write(objRecord); outputFile.write(chart); } } // Write any tail records that need to be written foreach (DrawingGroupObject dgo2 in drawings) dgo2.writeTailRecords(outputFile); }
/** * Constructor used when reading images * * @param mso the drawing record * @param obj the object record * @param dd the drawing data for all drawings on this sheet * @param dg the drawing group * @param ws the workbook settings */ public ComboBox(MsoDrawingRecord mso,ObjRecord obj,DrawingData dd, DrawingGroup dg,WorkbookSettings ws) { drawingGroup = dg; msoDrawingRecord = mso; drawingData = dd; objRecord = obj; initialized = false; workbookSettings = ws; origin = Origin.READ; drawingData.addData(msoDrawingRecord.getData()); drawingNumber = drawingData.getNumDrawings() - 1; drawingGroup.addDrawing(this); Assert.verify(mso != null && obj != null); initialize(); }
/** * Copy constructor used to copy drawings from read to write * * @param dgo the drawing group object * @param dg the drawing group * @param ws the workbook settings */ public ComboBox(DrawingGroupObject dgo, DrawingGroup dg, WorkbookSettings ws) { ComboBox d = (ComboBox)dgo; Assert.verify(d.origin == Origin.READ); msoDrawingRecord = d.msoDrawingRecord; objRecord = d.objRecord; initialized = false; origin = Origin.READ; drawingData = d.drawingData; drawingGroup = dg; drawingNumber = d.drawingNumber; drawingGroup.addDrawing(this); workbookSettings = ws; }
/** * Adds an mso record to this object * * @param d the mso record */ public void addMso(MsoDrawingRecord d) { mso = d; drawingData.addRawData(mso.getData()); }
/** * Writes out the additional comment records * * @param outputFile the output file * @exception IOException */ public virtual void writeAdditionalRecords(File outputFile) { if (origin == Origin.READ) { outputFile.write(objRecord); if (mso != null) outputFile.write(mso); outputFile.write(txo); outputFile.write(text); if (formatting != null) outputFile.write(formatting); return; } // Create the obj record ObjRecord objrec = new ObjRecord(objectId,ObjRecord.EXCELNOTE); outputFile.write(objrec); // Create the mso data record. Write the text box record again, // although it is already included in the SpContainer ClientTextBox textBox = new ClientTextBox(); MsoDrawingRecord msod = new MsoDrawingRecord(textBox.getData()); outputFile.write(msod); TextobjectRecord txorec = new TextobjectRecord(getText()); outputFile.write(txorec); // Data for the first continue record byte[] textData = new byte[commentText.Length * 2 + 1]; textData[0] = 0x1; // unicode indicator StringHelper.getUnicodeBytes(commentText,textData,1); //StringHelper.getBytes(commentText, textData, 1); ContinueRecord textContinue = new ContinueRecord(textData); outputFile.write(textContinue); // Data for the formatting runs byte[] frData = new byte[16]; // First txo run (the user) IntegerHelper.getTwoBytes(0,frData,0); // index to the first character IntegerHelper.getTwoBytes(0,frData,2); // index to the font(default) // Mandatory last txo run IntegerHelper.getTwoBytes(commentText.Length,frData,8); IntegerHelper.getTwoBytes(0,frData,10); // index to the font(default) ContinueRecord frContinue = new ContinueRecord(frData); outputFile.write(frContinue); }
/** * Copy constructor used to copy drawings from read to write * * @param dgo the drawing group object * @param dg the drawing group */ protected Drawing2(DrawingGroupObject dgo,DrawingGroup dg) { Drawing2 d = (Drawing2)dgo; Assert.verify(d.origin == Origin.READ); msoDrawingRecord = d.msoDrawingRecord; initialized = false; origin = Origin.READ; drawingData = d.drawingData; drawingGroup = dg; drawingNumber = d.drawingNumber; drawingGroup.addDrawing(this); }
/** * Copy constructor used to copy drawings from read to write * * @param dgo the drawing group object * @param dg the drawing group * @param ws the workbook settings */ /*protected*/ public Comment(DrawingGroupObject dgo, DrawingGroup dg, WorkbookSettings ws) { Comment d = (Comment)dgo; Assert.verify(d.origin == Origin.READ); msoDrawingRecord = d.msoDrawingRecord; objRecord = d.objRecord; initialized = false; origin = Origin.READ; drawingData = d.drawingData; drawingGroup = dg; drawingNumber = d.drawingNumber; drawingGroup.addDrawing(this); mso = d.mso; txo = d.txo; text = d.text; formatting = d.formatting; note = d.note; width = d.width; height = d.height; workbookSettings = ws; }
/** * Copy constructor used to copy drawings from read to write * * @param dgo the drawing group object * @param dg the drawing group * @param ws the workbook settings */ public Button(DrawingGroupObject dgo, DrawingGroup dg, WorkbookSettings ws) { Button d = (Button)dgo; Assert.verify(d.origin == Origin.READ); msoDrawingRecord = d.msoDrawingRecord; objRecord = d.objRecord; initialized = false; origin = Origin.READ; drawingData = d.drawingData; drawingGroup = dg; drawingNumber = d.drawingNumber; drawingGroup.addDrawing(this); mso = d.mso; txo = d.txo; text = d.text; formatting = d.formatting; workbookSettings = ws; }
/** * Constructor used when reading images * * @param mso the drawing record * @param dd the drawing data for all drawings on this sheet * @param dg the drawing group */ public Drawing2(MsoDrawingRecord mso, DrawingData dd, DrawingGroup dg) { drawingGroup = dg; msoDrawingRecord = mso; drawingData = dd; initialized = false; origin = Origin.READ; // there is no drawing number associated with this drawing drawingData.addRawData(msoDrawingRecord.getData()); drawingGroup.addDrawing(this); Assert.verify(mso != null); initialize(); }
/// <summary> Reads in the contents of this sheet</summary> internal void read() { Record r = null; BaseSharedFormulaRecord sharedFormula = null; bool sharedFormulaAdded = false; bool cont = true; // Set the position within the file excelFile.Pos = startPosition; // Handles to the last drawing and obj records MsoDrawingRecord msoRecord = null; ObjRecord objRecord = null; // A handle to window2 record Window2Record window2Record = null; // A handle to printgridlines record PrintGridLinesRecord printGridLinesRecord = null; // A handle to printheaders record PrintHeadersRecord printHeadersRecord = null; while (cont) { r = excelFile.next(); if (r.Type == NExcel.Biff.Type.UNKNOWN && r.Code == 0) { //System.Console.Error.Write("Warning: biff code zero found"); // Try a dimension record if (r.Length == 0xa) { logger.warn("Biff code zero found - trying a dimension record."); r.Type = (NExcel.Biff.Type.DIMENSION); } else { logger.warn("Biff code zero found - Ignoring."); } } if (r.Type == NExcel.Biff.Type.DIMENSION) { DimensionRecord dr = null; if (workbookBof.isBiff8()) { dr = new DimensionRecord(r); } else { dr = new DimensionRecord(r, DimensionRecord.biff7); } numRows = dr.NumberOfRows; numCols = dr.NumberOfColumns; cells = new Cell[numRows][]; for (int i = 0; i < numRows; i++) { cells[i] = new Cell[numCols]; } } else if (r.Type == NExcel.Biff.Type.LABELSST) { LabelSSTRecord label = new LabelSSTRecord(r, sharedStrings, formattingRecords, sheet); addCell(label); } else if (r.Type == NExcel.Biff.Type.RK || r.Type == NExcel.Biff.Type.RK2) { RKRecord rkr = new RKRecord(r, formattingRecords, sheet); if (formattingRecords.isDate(rkr.XFIndex)) { DateCell dc = new DateRecord(rkr, rkr.XFIndex, formattingRecords, nineteenFour, sheet); addCell(dc); } else { addCell(rkr); } } else if (r.Type == NExcel.Biff.Type.HLINK) { HyperlinkRecord hr = new HyperlinkRecord(r, sheet, workbookSettings); hyperlinks.Add(hr); } else if (r.Type == NExcel.Biff.Type.MERGEDCELLS) { MergedCellsRecord mc = new MergedCellsRecord(r, sheet); if (mergedCells == null) { mergedCells = mc.Ranges; } else { Range[] newMergedCells = new Range[mergedCells.Length + mc.Ranges.Length]; Array.Copy(mergedCells, 0, newMergedCells, 0, mergedCells.Length); Array.Copy(mc.Ranges, 0, newMergedCells, mergedCells.Length, mc.Ranges.Length); mergedCells = newMergedCells; } } else if (r.Type == NExcel.Biff.Type.MULRK) { MulRKRecord mulrk = new MulRKRecord(r); // Get the individual cell records from the multiple record int num = mulrk.NumberOfColumns; int ixf = 0; for (int i = 0; i < num; i++) { ixf = mulrk.getXFIndex(i); NumberValue nv = new NumberValue(mulrk.Row, mulrk.FirstColumn + i, RKHelper.getDouble(mulrk.getRKNumber(i)), ixf, formattingRecords, sheet); if (formattingRecords.isDate(ixf)) { DateCell dc = new DateRecord(nv, ixf, formattingRecords, nineteenFour, sheet); addCell(dc); } else { nv.setNumberFormat(formattingRecords.getNumberFormat(ixf)); addCell(nv); } } } else if (r.Type == NExcel.Biff.Type.NUMBER) { NumberRecord nr = new NumberRecord(r, formattingRecords, sheet); if (formattingRecords.isDate(nr.XFIndex)) { DateCell dc = new DateRecord(nr, nr.XFIndex, formattingRecords, nineteenFour, sheet); addCell(dc); } else { addCell(nr); } } else if (r.Type == NExcel.Biff.Type.BOOLERR) { BooleanRecord br = new BooleanRecord(r, formattingRecords, sheet); if (br.Error) { ErrorRecord er = new ErrorRecord(br.getRecord(), formattingRecords, sheet); addCell(er); } else { addCell(br); } } else if (r.Type == NExcel.Biff.Type.PRINTGRIDLINES) { printGridLinesRecord = new PrintGridLinesRecord(r); settings.PrintGridLines = (printGridLinesRecord.PrintGridLines); } else if (r.Type == NExcel.Biff.Type.PRINTHEADERS) { printHeadersRecord = new PrintHeadersRecord(r); settings.PrintHeaders = (printHeadersRecord.PrintHeaders); } else if (r.Type == NExcel.Biff.Type.WINDOW2) { window2Record = new Window2Record(r); settings.ShowGridLines = (window2Record.ShowGridLines); settings.DisplayZeroValues = (window2Record.DisplayZeroValues); settings.setSelected(); } else if (r.Type == NExcel.Biff.Type.PANE) { PaneRecord pr = new PaneRecord(r); if (window2Record != null && window2Record.Frozen && window2Record.FrozenNotSplit) { settings.VerticalFreeze = (pr.RowsVisible); settings.HorizontalFreeze = (pr.ColumnsVisible); } } else if (r.Type == NExcel.Biff.Type.CONTINUE) { ; } else if (r.Type == NExcel.Biff.Type.NOTE) { ; } else if (r.Type == NExcel.Biff.Type.ARRAY) { ; } else if (r.Type == NExcel.Biff.Type.PROTECT) { ProtectRecord pr = new ProtectRecord(r); settings.Protected = (pr.IsProtected()); } else if (r.Type == NExcel.Biff.Type.SHAREDFORMULA) { if (sharedFormula == null) { logger.warn("Shared template formula is null - " + "trying most recent formula template"); SharedFormulaRecord lastSharedFormula = (SharedFormulaRecord)sharedFormulas[sharedFormulas.Count - 1]; if (lastSharedFormula != null) { sharedFormula = lastSharedFormula.TemplateFormula; } } SharedFormulaRecord sfr = new SharedFormulaRecord(r, sharedFormula, workbook, workbook, sheet); sharedFormulas.Add(sfr); sharedFormula = null; } else if (r.Type == NExcel.Biff.Type.FORMULA || r.Type == NExcel.Biff.Type.FORMULA2) { FormulaRecord fr = new FormulaRecord(r, excelFile, formattingRecords, workbook, workbook, sheet, workbookSettings); if (fr.Shared) { BaseSharedFormulaRecord prevSharedFormula = sharedFormula; sharedFormula = (BaseSharedFormulaRecord)fr.Formula; // See if it fits in any of the shared formulas sharedFormulaAdded = addToSharedFormulas(sharedFormula); if (sharedFormulaAdded) { sharedFormula = prevSharedFormula; } // If we still haven't added the previous base shared formula, // revert it to an ordinary formula and add it to the cell if (!sharedFormulaAdded && prevSharedFormula != null) { // Do nothing. It's possible for the biff file to contain the // record sequence // FORMULA-SHRFMLA-FORMULA-SHRFMLA-FORMULA-FORMULA-FORMULA // ie. it first lists all the formula templates, then it // lists all the individual formulas addCell(revertSharedFormula(prevSharedFormula)); } } else { Cell cell = fr.Formula; // See if the formula evaluates to date if (fr.Formula.Type == CellType.NUMBER_FORMULA) { NumberFormulaRecord nfr = (NumberFormulaRecord)fr.Formula; if (formattingRecords.isDate(nfr.XFIndex)) { cell = new DateFormulaRecord(nfr, formattingRecords, workbook, workbook, nineteenFour, sheet); } } addCell(cell); } } else if (r.Type == NExcel.Biff.Type.LABEL) { LabelRecord lr = null; if (workbookBof.isBiff8()) { lr = new LabelRecord(r, formattingRecords, sheet, workbookSettings); } else { lr = new LabelRecord(r, formattingRecords, sheet, workbookSettings, LabelRecord.biff7); } addCell(lr); } else if (r.Type == NExcel.Biff.Type.RSTRING) { RStringRecord lr = null; // RString records are obsolete in biff 8 Assert.verify(!workbookBof.isBiff8()); lr = new RStringRecord(r, formattingRecords, sheet, workbookSettings, RStringRecord.biff7); addCell(lr); } else if (r.Type == NExcel.Biff.Type.NAME) { ; } else if (r.Type == NExcel.Biff.Type.PASSWORD) { PasswordRecord pr = new PasswordRecord(r); settings.PasswordHash = (pr.PasswordHash); } else if (r.Type == NExcel.Biff.Type.ROW) { RowRecord rr = new RowRecord(r); // See if the row has anything funny about it if (!rr.isDefaultHeight() || rr.isCollapsed() || rr.isZeroHeight()) { rowProperties.Add(rr); } } else if (r.Type == NExcel.Biff.Type.BLANK) { BlankCell bc = new BlankCell(r, formattingRecords, sheet); addCell(bc); } else if (r.Type == NExcel.Biff.Type.MULBLANK) { MulBlankRecord mulblank = new MulBlankRecord(r); // Get the individual cell records from the multiple record int num = mulblank.NumberOfColumns; for (int i = 0; i < num; i++) { int ixf = mulblank.getXFIndex(i); MulBlankCell mbc = new MulBlankCell(mulblank.Row, mulblank.FirstColumn + i, ixf, formattingRecords, sheet); addCell(mbc); } } else if (r.Type == NExcel.Biff.Type.SCL) { SCLRecord scl = new SCLRecord(r); settings.ZoomFactor = (scl.ZoomFactor); } else if (r.Type == NExcel.Biff.Type.COLINFO) { ColumnInfoRecord cir = new ColumnInfoRecord(r); columnInfosArray.Add(cir); } else if (r.Type == NExcel.Biff.Type.HEADER) { HeaderRecord hr = null; if (workbookBof.isBiff8()) { hr = new HeaderRecord(r, workbookSettings); } else { hr = new HeaderRecord(r, workbookSettings, HeaderRecord.biff7); } NExcel.HeaderFooter header = new NExcel.HeaderFooter(hr.Header); settings.Header = (header); } else if (r.Type == NExcel.Biff.Type.FOOTER) { FooterRecord fr = null; if (workbookBof.isBiff8()) { fr = new FooterRecord(r, workbookSettings); } else { fr = new FooterRecord(r, workbookSettings, FooterRecord.biff7); } NExcel.HeaderFooter footer = new NExcel.HeaderFooter(fr.Footer); settings.Footer = (footer); } else if (r.Type == NExcel.Biff.Type.SETUP) { SetupRecord sr = new SetupRecord(r); if (sr.isPortrait()) { settings.Orientation = (PageOrientation.PORTRAIT); } else { settings.Orientation = (PageOrientation.LANDSCAPE); } settings.PaperSize = (PaperSize.getPaperSize(sr.PaperSize)); settings.HeaderMargin = (sr.HeaderMargin); settings.FooterMargin = (sr.FooterMargin); settings.ScaleFactor = (sr.ScaleFactor); settings.PageStart = (sr.PageStart); settings.FitWidth = (sr.FitWidth); settings.FitHeight = (sr.FitHeight); settings.HorizontalPrintResolution = (sr.HorizontalPrintResolution); settings.VerticalPrintResolution = (sr.VerticalPrintResolution); settings.Copies = (sr.Copies); if (workspaceOptions != null) { settings.FitToPages = (workspaceOptions.FitToPages); } } else if (r.Type == NExcel.Biff.Type.WSBOOL) { workspaceOptions = new WorkspaceInformationRecord(r); } else if (r.Type == NExcel.Biff.Type.DEFCOLWIDTH) { DefaultColumnWidthRecord dcwr = new DefaultColumnWidthRecord(r); settings.DefaultColumnWidth = (dcwr.Width); } else if (r.Type == NExcel.Biff.Type.DEFAULTROWHEIGHT) { DefaultRowHeightRecord drhr = new DefaultRowHeightRecord(r); if (drhr.Height != 0) { settings.DefaultRowHeight = (drhr.Height); } } else if (r.Type == NExcel.Biff.Type.LEFTMARGIN) { MarginRecord m = new LeftMarginRecord(r); settings.LeftMargin = (m.Margin); } else if (r.Type == NExcel.Biff.Type.RIGHTMARGIN) { MarginRecord m = new RightMarginRecord(r); settings.RightMargin = (m.Margin); } else if (r.Type == NExcel.Biff.Type.TOPMARGIN) { MarginRecord m = new TopMarginRecord(r); settings.TopMargin = (m.Margin); } else if (r.Type == NExcel.Biff.Type.BOTTOMMARGIN) { MarginRecord m = new BottomMarginRecord(r); settings.BottomMargin = (m.Margin); } else if (r.Type == NExcel.Biff.Type.HORIZONTALPAGEBREAKS) { HorizontalPageBreaksRecord dr = null; if (workbookBof.isBiff8()) { dr = new HorizontalPageBreaksRecord(r); } else { dr = new HorizontalPageBreaksRecord(r, HorizontalPageBreaksRecord.biff7); } rowBreaks = dr.RowBreaks; } else if (r.Type == NExcel.Biff.Type.PLS) { plsRecord = new PLSRecord(r); } else if (r.Type == NExcel.Biff.Type.OBJ) { objRecord = new ObjRecord(r); if (objRecord.Type == ObjRecord.PICTURE && !workbookSettings.DrawingsDisabled) { if (msoRecord == null) { logger.warn("object record is not associated with a drawing " + " record - ignoring"); } else { Drawing drawing = new Drawing(msoRecord, objRecord, workbook.DrawingGroup); drawings.Add(drawing); } msoRecord = null; objRecord = null; } } else if (r.Type == NExcel.Biff.Type.MSODRAWING) { msoRecord = new MsoDrawingRecord(r); } else if (r.Type == NExcel.Biff.Type.BOF) { BOFRecord br = new BOFRecord(r); Assert.verify(!br.isWorksheet()); int startpos = excelFile.Pos - r.Length - 4; // Skip to the end of the nested bof // Thanks to Rohit for spotting this Record r2 = excelFile.next(); while (r2.Code != NExcel.Biff.Type.EOF.Value) { r2 = excelFile.next(); } if (br.isChart()) { Chart chart = new Chart(msoRecord, objRecord, startpos, excelFile.Pos, excelFile, workbookSettings); charts.Add(chart); if (workbook.DrawingGroup != null) { workbook.DrawingGroup.add(chart); } // Reset the drawing records msoRecord = null; objRecord = null; } // If this worksheet is just a chart, then the EOF reached // represents the end of the sheet as well as the end of the chart if (sheetBof.isChart()) { cont = false; } } else if (r.Type == NExcel.Biff.Type.EOF) { cont = false; } } // Restore the file to its accurate position excelFile.restorePos(); // Add all the shared formulas to the sheet as individual formulas foreach (SharedFormulaRecord sfr in sharedFormulas) { Cell[] sfnr = sfr.getFormulas(formattingRecords, nineteenFour); for (int sf = 0; sf < sfnr.Length; sf++) { addCell(sfnr[sf]); } } // If the last base shared formula wasn't added to the sheet, then // revert it to an ordinary formula and add it if (!sharedFormulaAdded && sharedFormula != null) { addCell(revertSharedFormula(sharedFormula)); } }
/** * Constructor * * @param mso a <code>MsoDrawingRecord</code> value * @param obj an <code>ObjRecord</code> value * @param dd the drawing data * @param sp an <code>int</code> value * @param ep an <code>int</code> value * @param f a <code>File</code> value * @param ws the workbook settings */ public Chart(MsoDrawingRecord mso, ObjRecord obj, DrawingData dd, int sp,int ep,File f,WorkbookSettings ws) { msoDrawingRecord = mso; objRecord = obj; startpos = sp; endpos = ep; file = f; workbookSettings = ws; // msoDrawingRecord is null if the entire sheet consists of just the // chart. In this case, as there is only one drawing on the page, // it isn't necessary to add to the drawing data record anyway if (msoDrawingRecord != null) { drawingData = dd; drawingData.addData(msoDrawingRecord.getRecord().getData()); drawingNumber = drawingData.getNumDrawings() - 1; } initialized = false; // Note: mso and obj values can be null if we are creating a chart // which takes up an entire worksheet. Check that both are null or both // not null though Assert.verify((mso != null && obj != null) || (mso == null && obj == null)); }
/** * Reads in the contents of this sheet */ public void read() { Record r = null; BaseSharedFormulaRecord sharedFormula = null; bool sharedFormulaAdded = false; bool cont = true; // Set the position within the file excelFile.setPos(startPosition); // Handles to the last drawing and obj records MsoDrawingRecord msoRecord = null; ObjRecord objRecord = null; bool firstMsoRecord = true; // Handle to the last conditional format record ConditionalFormat condFormat = null; // Handle to the autofilter records FilterModeRecord filterMode = null; AutoFilterInfoRecord autoFilterInfo = null; // A handle to window2 record Window2Record window2Record = null; // A handle to printgridlines record PrintGridLinesRecord printGridLinesRecord = null; // A handle to printheaders record PrintHeadersRecord printHeadersRecord = null; // Hash map of comments, indexed on objectId. As each corresponding // note record is encountered, these are removed from the array Dictionary<uint,Comment> comments = new Dictionary<uint,Comment>(); // A list of object ids - used for cross referencing ArrayList objectIds = new ArrayList(); // A handle to a continue record read in ContinueRecord continueRecord = null; while (cont) { r = excelFile.next(); Type type = r.getType(); if (type == Type.UNKNOWN && r.getCode() == 0) { //logger.warn("Biff code zero found"); // Try a dimension record if (r.getLength() == 0xa) { //logger.warn("Biff code zero found - trying a dimension record."); r.setType(Type.DIMENSION); } else { //logger.warn("Biff code zero found - Ignoring."); } } if (type == Type.DIMENSION) { DimensionRecord dr = null; if (workbookBof.isBiff8()) { dr = new DimensionRecord(r); } else { dr = new DimensionRecord(r, DimensionRecord.biff7); } numRows = dr.getNumberOfRows(); numCols = dr.getNumberOfColumns(); cells = new Cell[numRows, numCols]; } else if (type == Type.LABELSST) { LabelSSTRecord label = new LabelSSTRecord(r, sharedStrings, formattingRecords, sheet); addCell(label); } else if (type == Type.RK || type == Type.RK2) { RKRecord rkr = new RKRecord(r, formattingRecords, sheet); if (formattingRecords.isDate(rkr.getXFIndex())) { DateCell dc = new DateRecord (rkr, rkr.getXFIndex(), formattingRecords, nineteenFour, sheet); addCell(dc); } else { addCell(rkr); } } else if (type == Type.HLINK) { HyperlinkRecord hr = new HyperlinkRecord(r, sheet, workbookSettings); hyperlinks.Add(hr); } else if (type == Type.MERGEDCELLS) { MergedCellsRecord mc = new MergedCellsRecord(r, sheet); if (mergedCells == null) { mergedCells = mc.getRanges(); } else { Range[] newMergedCells = new Range[mergedCells.Length + mc.getRanges().Length]; System.Array.Copy(mergedCells, 0, newMergedCells, 0, mergedCells.Length); System.Array.Copy(mc.getRanges(), 0, newMergedCells, mergedCells.Length, mc.getRanges().Length); mergedCells = newMergedCells; } } else if (type == Type.MULRK) { MulRKRecord mulrk = new MulRKRecord(r); // Get the individual cell records from the multiple record int num = mulrk.getNumberOfColumns(); int ixf = 0; for (int i = 0; i < num; i++) { ixf = mulrk.getXFIndex(i); NumberValue nv = new NumberValue (mulrk.getRow(), mulrk.getFirstColumn() + i, RKHelper.getDouble(mulrk.getRKNumber(i)), ixf, formattingRecords, sheet); if (formattingRecords.isDate(ixf)) { DateCell dc = new DateRecord(nv, ixf, formattingRecords, nineteenFour, sheet); addCell(dc); } else { nv.setNumberFormat(formattingRecords.getNumberFormat(ixf)); addCell(nv); } } } else if (type == Type.NUMBER) { NumberRecord nr = new NumberRecord(r, formattingRecords, sheet); if (formattingRecords.isDate(nr.getXFIndex())) { DateCell dc = new DateRecord(nr,nr.getXFIndex(),formattingRecords,nineteenFour, sheet); addCell(dc); } else addCell(nr); } else if (type == Type.BOOLERR) { BooleanRecord br = new BooleanRecord(r, formattingRecords, sheet); if (br.isError()) { ErrorRecord er = new ErrorRecord(br.getRecord(), formattingRecords, sheet); addCell(er); } else { addCell(br); } } else if (type == Type.PRINTGRIDLINES) { printGridLinesRecord = new PrintGridLinesRecord(r); settings.setPrintGridLines(printGridLinesRecord.getPrintGridLines()); } else if (type == Type.PRINTHEADERS) { printHeadersRecord = new PrintHeadersRecord(r); settings.setPrintHeaders(printHeadersRecord.getPrintHeaders()); } else if (type == Type.WINDOW2) { window2Record = null; if (workbookBof.isBiff8()) { window2Record = new Window2Record(r); } else { window2Record = new Window2Record(r, Window2Record.biff7); } settings.setShowGridLines(window2Record.getShowGridLines()); settings.setDisplayZeroValues(window2Record.getDisplayZeroValues()); settings.setSelected(true); settings.setPageBreakPreviewMode(window2Record.isPageBreakPreview()); } else if (type == Type.PANE) { PaneRecord pr = new PaneRecord(r); if (window2Record != null && window2Record.getFrozen()) { settings.setVerticalFreeze(pr.getRowsVisible()); settings.setHorizontalFreeze(pr.getColumnsVisible()); } } else if (type == Type.CONTINUE) { // don't know what this is for, but keep hold of it anyway continueRecord = new ContinueRecord(r); } else if (type == Type.NOTE) { if (!workbookSettings.getDrawingsDisabled()) { NoteRecord nr = new NoteRecord(r); // Get the comment for the object id if (!comments.ContainsKey(nr.getObjectId())) { //logger.warn(" cannot find comment for note id " + nr.getObjectId() + "...ignoring"); } else { Comment comment = comments[nr.getObjectId()]; comments.Remove(nr.getObjectId()); comment.setNote(nr); drawings.Add(comment); addCellComment(comment.getColumn(), comment.getRow(), comment.getText(), comment.getWidth(), comment.getHeight()); } } } else if (type == Type.ARRAY) { ; } else if (type == Type.PROTECT) { ProtectRecord pr = new ProtectRecord(r); settings.setProtected(pr.isProtected()); } else if (type == Type.SHAREDFORMULA) { if (sharedFormula == null) { //logger.warn("Shared template formula is null - " + // "trying most recent formula template"); SharedFormulaRecord lastSharedFormula = (SharedFormulaRecord)sharedFormulas[sharedFormulas.Count - 1]; if (lastSharedFormula != null) sharedFormula = lastSharedFormula.getTemplateFormula(); } SharedFormulaRecord sfr = new SharedFormulaRecord(r, sharedFormula, workbook, workbook, sheet); sharedFormulas.Add(sfr); sharedFormula = null; } else if (type == Type.FORMULA || type == Type.FORMULA2) { FormulaRecord fr = new FormulaRecord(r, excelFile, formattingRecords, workbook, workbook, sheet, workbookSettings); if (fr.isShared()) { BaseSharedFormulaRecord prevSharedFormula = sharedFormula; sharedFormula = (BaseSharedFormulaRecord)fr.getFormula(); // See if it fits in any of the shared formulas sharedFormulaAdded = addToSharedFormulas(sharedFormula); if (sharedFormulaAdded) { sharedFormula = prevSharedFormula; } // If we still haven't added the previous base shared formula, // revert it to an ordinary formula and add it to the cell if (!sharedFormulaAdded && prevSharedFormula != null) { // Do nothing. It's possible for the biff file to contain the // record sequence // FORMULA-SHRFMLA-FORMULA-SHRFMLA-FORMULA-FORMULA-FORMULA // ie. it first lists all the formula templates, then it // lists all the individual formulas addCell(revertSharedFormula(prevSharedFormula)); } } else { Cell cell = fr.getFormula(); try { // See if the formula evaluates to date if (fr.getFormula().getType() == CellType.NUMBER_FORMULA) { NumberFormulaRecord nfr = (NumberFormulaRecord)fr.getFormula(); if (formattingRecords.isDate(nfr.getXFIndex())) { cell = new DateFormulaRecord(nfr, formattingRecords, workbook, workbook, nineteenFour, sheet); } } addCell(cell); } catch (FormulaException e) { // Something has gone wrong trying to read the formula data eg. it // might be unsupported biff7 data //logger.warn(CellReferenceHelper.getCellReference(cell.getColumn(), cell.getRow()) + " " + e.Message); } } } else if (type == Type.LABEL) { LabelRecord lr = null; if (workbookBof.isBiff8()) { lr = new LabelRecord(r, formattingRecords, sheet, workbookSettings); } else { lr = new LabelRecord(r, formattingRecords, sheet, workbookSettings, LabelRecord.biff7); } addCell(lr); } else if (type == Type.RSTRING) { RStringRecord lr = null; // RString records are obsolete in biff 8 Assert.verify(!workbookBof.isBiff8()); lr = new RStringRecord(r, formattingRecords, sheet, workbookSettings, RStringRecord.biff7); addCell(lr); } else if (type == Type.NAME) { ; } else if (type == Type.PASSWORD) { PasswordRecord pr = new PasswordRecord(r); settings.setPasswordHash(pr.getPasswordHash()); } else if (type == Type.ROW) { RowRecord rr = new RowRecord(r); // See if the row has anything funny about it if (!rr.isDefaultHeight() || !rr.matchesDefaultFontHeight() || rr.isCollapsed() || rr.hasDefaultFormat() || rr.getOutlineLevel() != 0) { rowProperties.Add(rr); } } else if (type == Type.BLANK) { if (!workbookSettings.getIgnoreBlanks()) { BlankCell bc = new BlankCell(r, formattingRecords, sheet); addCell(bc); } } else if (type == Type.MULBLANK) { if (!workbookSettings.getIgnoreBlanks()) { MulBlankRecord mulblank = new MulBlankRecord(r); // Get the individual cell records from the multiple record int num = mulblank.getNumberOfColumns(); for (int i = 0; i < num; i++) { int ixf = mulblank.getXFIndex(i); MulBlankCell mbc = new MulBlankCell (mulblank.getRow(), mulblank.getFirstColumn() + i, ixf, formattingRecords, sheet); addCell(mbc); } } } else if (type == Type.SCL) { SCLRecord scl = new SCLRecord(r); settings.setZoomFactor(scl.getZoomFactor()); } else if (type == Type.COLINFO) { ColumnInfoRecord cir = new ColumnInfoRecord(r); columnInfosArray.Add(cir); } else if (type == Type.HEADER) { HeaderRecord hr = null; if (workbookBof.isBiff8()) hr = new HeaderRecord(r, workbookSettings); else hr = new HeaderRecord(r, workbookSettings, HeaderRecord.biff7); HeaderFooter header = new HeaderFooter(hr.getHeader()); settings.setHeader(header); } else if (type == Type.FOOTER) { FooterRecord fr = null; if (workbookBof.isBiff8()) { fr = new FooterRecord(r, workbookSettings); } else { fr = new FooterRecord(r, workbookSettings, FooterRecord.biff7); } HeaderFooter footer = new HeaderFooter(fr.getFooter()); settings.setFooter(footer); } else if (type == Type.SETUP) { SetupRecord sr = new SetupRecord(r); // If the setup record has its not initialized bit set, then // use the sheet settings default values if (sr.getInitialized()) { if (sr.isPortrait()) { settings.setOrientation(PageOrientation.PORTRAIT); } else { settings.setOrientation(PageOrientation.LANDSCAPE); } if (sr.isRightDown()) { settings.setPageOrder(PageOrder.RIGHT_THEN_DOWN); } else { settings.setPageOrder(PageOrder.DOWN_THEN_RIGHT); } settings.setPaperSize(PaperSize.getPaperSize(sr.getPaperSize())); settings.setHeaderMargin(sr.getHeaderMargin()); settings.setFooterMargin(sr.getFooterMargin()); settings.setScaleFactor(sr.getScaleFactor()); settings.setPageStart(sr.getPageStart()); settings.setFitWidth(sr.getFitWidth()); settings.setFitHeight(sr.getFitHeight()); settings.setHorizontalPrintResolution (sr.getHorizontalPrintResolution()); settings.setVerticalPrintResolution(sr.getVerticalPrintResolution()); settings.setCopies(sr.getCopies()); if (workspaceOptions != null) { settings.setFitToPages(workspaceOptions.getFitToPages()); } } } else if (type == Type.WSBOOL) { workspaceOptions = new WorkspaceInformationRecord(r); } else if (type == Type.DEFCOLWIDTH) { DefaultColumnWidthRecord dcwr = new DefaultColumnWidthRecord(r); settings.setDefaultColumnWidth(dcwr.getWidth()); } else if (type == Type.DEFAULTROWHEIGHT) { DefaultRowHeightRecord drhr = new DefaultRowHeightRecord(r); if (drhr.getHeight() != 0) { settings.setDefaultRowHeight(drhr.getHeight()); } } else if (type == Type.CONDFMT) { ConditionalFormatRangeRecord cfrr = new ConditionalFormatRangeRecord(r); condFormat = new ConditionalFormat(cfrr); conditionalFormats.Add(condFormat); } else if (type == Type.CF) { ConditionalFormatRecord cfr = new ConditionalFormatRecord(r); condFormat.addCondition(cfr); } else if (type == Type.FILTERMODE) { filterMode = new FilterModeRecord(r); } else if (type == Type.AUTOFILTERINFO) { autoFilterInfo = new AutoFilterInfoRecord(r); } else if (type == Type.AUTOFILTER) { if (!workbookSettings.getAutoFilterDisabled()) { AutoFilterRecord af = new AutoFilterRecord(r); if (autoFilter == null) { autoFilter = new AutoFilter(filterMode, autoFilterInfo); filterMode = null; autoFilterInfo = null; } autoFilter.add(af); } } else if (type == Type.LEFTMARGIN) { MarginRecord m = new LeftMarginRecord(r); settings.setLeftMargin(m.getMargin()); } else if (type == Type.RIGHTMARGIN) { MarginRecord m = new RightMarginRecord(r); settings.setRightMargin(m.getMargin()); } else if (type == Type.TOPMARGIN) { MarginRecord m = new TopMarginRecord(r); settings.setTopMargin(m.getMargin()); } else if (type == Type.BOTTOMMARGIN) { MarginRecord m = new BottomMarginRecord(r); settings.setBottomMargin(m.getMargin()); } else if (type == Type.HORIZONTALPAGEBREAKS) { HorizontalPageBreaksRecord dr = null; if (workbookBof.isBiff8()) { dr = new HorizontalPageBreaksRecord(r); } else { dr = new HorizontalPageBreaksRecord (r, HorizontalPageBreaksRecord.biff7); } rowBreaks = dr.getRowBreaks(); } else if (type == Type.VERTICALPAGEBREAKS) { VerticalPageBreaksRecord dr = null; if (workbookBof.isBiff8()) { dr = new VerticalPageBreaksRecord(r); } else { dr = new VerticalPageBreaksRecord (r, VerticalPageBreaksRecord.biff7); } columnBreaks = dr.getColumnBreaks(); } else if (type == Type.PLS) { plsRecord = new PLSRecord(r); // Check for Continue records while (excelFile.peek().getType() == Type.CONTINUE) { r.addContinueRecord(excelFile.next()); } } else if (type == Type.DVAL) { if (!workbookSettings.getCellValidationDisabled()) { DataValidityListRecord dvlr = new DataValidityListRecord(r); if (dvlr.getObjectId() == DataValidation.DEFAULT_OBJECT_ID) { if (msoRecord != null && objRecord == null) { // there is a drop down associated with this data validation if (drawingData == null) drawingData = new DrawingData(); Drawing2 d2 = new Drawing2(msoRecord, drawingData, workbook.getDrawingGroup()); drawings.Add(d2); msoRecord = null; dataValidation = new DataValidation(dvlr); } else { // no drop down dataValidation = new DataValidation(dvlr); } } else if (objectIds.Contains(dvlr.getObjectId())) dataValidation = new DataValidation(dvlr); else { //logger.warn("object id " + dvlr.getObjectId() + " referenced " + // " by data validity list record not found - ignoring"); } } } else if (type == Type.HCENTER) { CentreRecord hr = new CentreRecord(r); settings.setHorizontalCentre(hr.isCentre()); } else if (type == Type.VCENTER) { CentreRecord vc = new CentreRecord(r); settings.setVerticalCentre(vc.isCentre()); } else if (type == Type.DV) { if (!workbookSettings.getCellValidationDisabled()) { DataValiditySettingsRecord dvsr = new DataValiditySettingsRecord(r, workbook, workbook, workbook.getSettings()); if (dataValidation != null) { dataValidation.add(dvsr); addCellValidation(dvsr.getFirstColumn(), dvsr.getFirstRow(), dvsr.getLastColumn(), dvsr.getLastRow(), dvsr); } else { //logger.warn("cannot add data validity settings"); } } } else if (type == Type.OBJ) { objRecord = new ObjRecord(r); if (!workbookSettings.getDrawingsDisabled()) { // sometimes excel writes out continue records instead of drawing // records, so forcibly hack the stashed continue record into // a drawing record if (msoRecord == null && continueRecord != null) { //logger.warn("Cannot find drawing record - using continue record"); msoRecord = new MsoDrawingRecord(continueRecord.getRecord()); continueRecord = null; } handleobjectRecord(objRecord, msoRecord, comments); objectIds.Add((objRecord.getObjectId())); } // Save chart handling until the chart BOF record appears if (objRecord.getType() != ObjRecord.CHART) { objRecord = null; msoRecord = null; } } else if (type == Type.MSODRAWING) { if (!workbookSettings.getDrawingsDisabled()) { if (msoRecord != null) { // For form controls, a rogue MSODRAWING record can crop up // after the main one. Add these into the drawing data drawingData.addRawData(msoRecord.getData()); } msoRecord = new MsoDrawingRecord(r); if (firstMsoRecord) { msoRecord.setFirst(); firstMsoRecord = false; } } } else if (type == Type.BUTTONPROPERTYSET) { buttonPropertySet = new ButtonPropertySetRecord(r); } else if (type == Type.CALCMODE) { CalcModeRecord cmr = new CalcModeRecord(r); settings.setAutomaticFormulaCalculation(cmr.isAutomatic()); } else if (type == Type.SAVERECALC) { SaveRecalcRecord cmr = new SaveRecalcRecord(r); settings.setRecalculateFormulasBeforeSave(cmr.getRecalculateOnSave()); } else if (type == Type.GUTS) { GuttersRecord gr = new GuttersRecord(r); maxRowOutlineLevel = gr.getRowOutlineLevel() > 0 ? gr.getRowOutlineLevel() - 1 : 0; maxColumnOutlineLevel = gr.getColumnOutlineLevel() > 0 ? gr.getRowOutlineLevel() - 1 : 0; } else if (type == Type.BOF) { BOFRecord br = new BOFRecord(r); Assert.verify(!br.isWorksheet()); int startpos = excelFile.getPos() - r.getLength() - 4; // Skip to the end of the nested bof // Thanks to Rohit for spotting this Record r2 = excelFile.next(); while (r2.getCode() != Type.EOF.value) r2 = excelFile.next(); if (br.isChart()) { if (!workbook.getWorkbookBof().isBiff8()) { //logger.warn("only biff8 charts are supported"); } else { if (drawingData == null) drawingData = new DrawingData(); if (!workbookSettings.getDrawingsDisabled()) { Chart chart = new Chart(msoRecord, objRecord, drawingData, startpos, excelFile.getPos(), excelFile, workbookSettings); charts.Add(chart); if (workbook.getDrawingGroup() != null) workbook.getDrawingGroup().add(chart); } } // Reset the drawing records msoRecord = null; objRecord = null; } // If this worksheet is just a chart, then the EOF reached // represents the end of the sheet as well as the end of the chart if (sheetBof.isChart()) cont = false; } else if (type == Type.EOF) cont = false; } // Restore the file to its accurate position excelFile.restorePos(); // Add any out of bounds cells if (outOfBoundsCells.Count > 0) handleOutOfBoundsCells(); // Add all the shared formulas to the sheet as individual formulas foreach (SharedFormulaRecord sfr in sharedFormulas) { Cell[] sfnr = sfr.getFormulas(formattingRecords, nineteenFour); for (int sf = 0; sf < sfnr.Length; sf++) addCell(sfnr[sf]); } // If the last base shared formula wasn't added to the sheet, then // revert it to an ordinary formula and add it if (!sharedFormulaAdded && sharedFormula != null) addCell(revertSharedFormula(sharedFormula)); // If there is a stray msoDrawing record, then flag to the drawing group // that one has been omitted if (msoRecord != null && workbook.getDrawingGroup() != null) workbook.getDrawingGroup().setDrawingsOmitted(msoRecord, objRecord); // Check that the comments hash is empty if (comments.Count != 0) { //logger.warn("Not all comments have a corresponding Note record"); } }
/** * Reads in the object record * * @param objRecord the obj record * @param msoRecord the mso drawing record read in earlier * @param comments the hash map of comments */ private void handleobjectRecord(ObjRecord objRecord,MsoDrawingRecord msoRecord,Dictionary<uint,Comment> comments) { if (msoRecord == null) { //logger.warn("object record is not associated with a drawing record - ignoring"); return; } try { // Handle images if (objRecord.getType() == ObjRecord.PICTURE) { if (drawingData == null) { drawingData = new DrawingData(); } Drawing drawing = new Drawing(msoRecord, objRecord, drawingData, workbook.getDrawingGroup(), sheet); drawings.Add(drawing); return; } // Handle comments if (objRecord.getType() == ObjRecord.EXCELNOTE) { if (drawingData == null) drawingData = new DrawingData(); Comment comment = new Comment(msoRecord, objRecord, drawingData, workbook.getDrawingGroup(), workbookSettings); // Sometimes Excel writes out Continue records instead of drawing // records, so forcibly hack all of these into a drawing record Record r2 = excelFile.next(); if (r2.getType() == Type.MSODRAWING || r2.getType() == Type.CONTINUE) { MsoDrawingRecord mso = new MsoDrawingRecord(r2); comment.addMso(mso); r2 = excelFile.next(); } Assert.verify(r2.getType() == Type.TXO); TextobjectRecord txo = new TextobjectRecord(r2); comment.setTextobject(txo); r2 = excelFile.next(); Assert.verify(r2.getType() == Type.CONTINUE); ContinueRecord text = new ContinueRecord(r2); comment.setText(text); r2 = excelFile.next(); if (r2.getType() == Type.CONTINUE) { ContinueRecord formatting = new ContinueRecord(r2); comment.setFormatting(formatting); } comments.Add(comment.getObjectId(), comment); return; } // Handle combo boxes if (objRecord.getType() == ObjRecord.COMBOBOX) { if (drawingData == null) { drawingData = new DrawingData(); } ComboBox comboBox = new ComboBox(msoRecord, objRecord, drawingData, workbook.getDrawingGroup(), workbookSettings); drawings.Add(comboBox); return; } // Handle check boxes if (objRecord.getType() == ObjRecord.CHECKBOX) { if (drawingData == null) { drawingData = new DrawingData(); } CheckBox checkBox = new CheckBox(msoRecord, objRecord, drawingData, workbook.getDrawingGroup(), workbookSettings); Record r2 = excelFile.next(); Assert.verify(r2.getType() == Type.MSODRAWING || r2.getType() == Type.CONTINUE); if (r2.getType() == Type.MSODRAWING || r2.getType() == Type.CONTINUE) { MsoDrawingRecord mso = new MsoDrawingRecord(r2); checkBox.addMso(mso); r2 = excelFile.next(); } Assert.verify(r2.getType() == Type.TXO); TextobjectRecord txo = new TextobjectRecord(r2); checkBox.setTextobject(txo); if (txo.getTextLength() == 0) { return; } r2 = excelFile.next(); Assert.verify(r2.getType() == Type.CONTINUE); ContinueRecord text = new ContinueRecord(r2); checkBox.setText(text); r2 = excelFile.next(); if (r2.getType() == Type.CONTINUE) { ContinueRecord formatting = new ContinueRecord(r2); checkBox.setFormatting(formatting); } drawings.Add(checkBox); return; } // Handle form buttons if (objRecord.getType() == ObjRecord.BUTTON) { if (drawingData == null) { drawingData = new DrawingData(); } Button button = new Button(msoRecord, objRecord, drawingData, workbook.getDrawingGroup(), workbookSettings); Record r2 = excelFile.next(); Assert.verify(r2.getType() == Type.MSODRAWING || r2.getType() == Type.CONTINUE); if (r2.getType() == Type.MSODRAWING || r2.getType() == Type.CONTINUE) { MsoDrawingRecord mso = new MsoDrawingRecord(r2); button.addMso(mso); r2 = excelFile.next(); } Assert.verify(r2.getType() == Type.TXO); TextobjectRecord txo = new TextobjectRecord(r2); button.setTextobject(txo); r2 = excelFile.next(); Assert.verify(r2.getType() == Type.CONTINUE); ContinueRecord text = new ContinueRecord(r2); button.setText(text); r2 = excelFile.next(); if (r2.getType() == Type.CONTINUE) { ContinueRecord formatting = new ContinueRecord(r2); button.setFormatting(formatting); } drawings.Add(button); return; } // Non-supported types which have multiple record types if (objRecord.getType() == ObjRecord.TEXT) { //logger.warn(objRecord.getType() + " object on sheet \"" + // sheet.getName() + // "\" not supported - omitting"); // Still need to add the drawing data to preserve the hierarchy if (drawingData == null) { drawingData = new DrawingData(); } drawingData.addData(msoRecord.getData()); Record r2 = excelFile.next(); Assert.verify(r2.getType() == Type.MSODRAWING || r2.getType() == Type.CONTINUE); if (r2.getType() == Type.MSODRAWING || r2.getType() == Type.CONTINUE) { MsoDrawingRecord mso = new MsoDrawingRecord(r2); drawingData.addRawData(mso.getData()); r2 = excelFile.next(); } Assert.verify(r2.getType() == Type.TXO); if (workbook.getDrawingGroup() != null) // can be null for Excel 95 { workbook.getDrawingGroup().setDrawingsOmitted(msoRecord, objRecord); } return; } // Handle other types if (objRecord.getType() != ObjRecord.CHART) { //logger.warn(objRecord.getType() + " object on sheet \"" + // sheet.getName() + // "\" not supported - omitting"); // Still need to add the drawing data to preserve the hierarchy if (drawingData == null) { drawingData = new DrawingData(); } drawingData.addData(msoRecord.getData()); if (workbook.getDrawingGroup() != null) // can be null for Excel 95 { workbook.getDrawingGroup().setDrawingsOmitted(msoRecord, objRecord); } return; } } catch (DrawingDataException e) { //logger.warn(e.Message + "...disabling drawings for the remainder of the workbook"); workbookSettings.setDrawingsDisabled(true); } }
/** * Constructor used when reading images * * @param mso the drawing record * @param obj the object record * @param dd the drawing data for all drawings on this sheet * @param dg the drawing group */ public Drawing(MsoDrawingRecord mso, ObjRecord obj, DrawingData dd, DrawingGroup dg, Sheet s) { drawingGroup = dg; msoDrawingRecord = mso; drawingData = dd; objRecord = obj; sheet = s; initialized = false; origin = Origin.READ; drawingData.addData(msoDrawingRecord.getData()); drawingNumber = drawingData.getNumDrawings() - 1; drawingGroup.addDrawing(this); Assert.verify(mso != null && obj != null); initialize(); }