//private static POILogger log = POILogFactory.GetLogger(typeof(HSSFSheet)); /// <summary> /// Creates new HSSFSheet - called by HSSFWorkbook to Create a _sheet from /// scratch. You should not be calling this from application code (its protected anyhow). /// </summary> /// <param name="_workbook">The HSSF Workbook object associated with the _sheet..</param> /// <see cref="NPOI.HSSF.UserModel.HSSFWorkbook.CreateSheet"/> public HSSFSheet(HSSFWorkbook _workbook) { _sheet = Sheet.CreateSheet(); rows = new Dictionary<int, NPOI.SS.UserModel.Row>(); this._workbook = _workbook; this.book = _workbook.Workbook; }
public void TestActiveCell() { //read in sample HSSFWorkbook book = OpenSample("Simple.xls"); //Check initial position HSSFSheet umSheet = (HSSFSheet)book.GetSheetAt(0); NPOI.HSSF.Model.Sheet s = umSheet.Sheet; Assert.AreEqual(0, s.ActiveCellCol, "Initial active cell should be in col 0"); Assert.AreEqual(1, s.ActiveCellRow, "Initial active cell should be on row 1"); //modify position through Cell Cell cell = umSheet.CreateRow(3).CreateCell(2); cell.SetAsActiveCell(); Assert.AreEqual(2, s.ActiveCellCol, "After modify, active cell should be in col 2"); Assert.AreEqual(3, s.ActiveCellRow, "After modify, active cell should be on row 3"); //Write book to temp file; read and Verify that position is serialized book = WriteOutAndReadBack(book); umSheet = (HSSFSheet)book.GetSheetAt(0); s = umSheet.Sheet; Assert.AreEqual(2, s.ActiveCellCol, "After serialize, active cell should be in col 2"); Assert.AreEqual(3, s.ActiveCellRow, "After serialize, active cell should be on row 3"); }
public void TestBackupRecord() { HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet s = (HSSFSheet)wb.CreateSheet(); NPOI.HSSF.Model.Sheet sheet = s.Sheet; Assert.AreEqual(true, sheet.GridsetRecord.Gridset); s.IsGridsPrinted = true; Assert.AreEqual(false, sheet.GridsetRecord.Gridset); }
public void TestHorizontallyCenter() { HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet s = (HSSFSheet)wb.CreateSheet(); NPOI.HSSF.Model.Sheet sheet = s.Sheet; HCenterRecord record = sheet.PageSettings.HCenter; Assert.AreEqual(false, record.HCenter); s.HorizontallyCenter = (true); Assert.AreEqual(true, record.HCenter); }
public void TestVerticallyCenter() { HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet s = (HSSFSheet)wb.CreateSheet(); NPOI.HSSF.Model.Sheet sheet = s.Sheet; VCenterRecord record = sheet.PageSettings.VCenter; Assert.AreEqual(false, record.VCenter); s.VerticallyCenter = (true); Assert.AreEqual(true, record.VCenter); // wb.Write(new FileOutputStream("c:\\Test.xls")); }
public void TestProtectSheet() { short expected = unchecked ((short)0xfef1); HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet s = (HSSFSheet)wb.CreateSheet(); s.ProtectSheet("abcdefghij"); NPOI.HSSF.Model.Sheet sheet = s.Sheet; ProtectRecord Protect = sheet.Protect; PasswordRecord pass = sheet.Password; Assert.IsTrue(Protect.Protect, "Protection should be on"); Assert.IsTrue(sheet.IsProtected[1], "object Protection should be on"); Assert.IsTrue(sheet.IsProtected[2], "scenario Protection should be on"); Assert.AreEqual(expected, pass.Password, "well known value for top secret hash should be " + NPOI.Util.StringUtil.ToHexString(expected).Substring(4)); }
public void TestWSBool() { HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet s = (HSSFSheet)wb.CreateSheet(); NPOI.HSSF.Model.Sheet sheet = s.Sheet; WSBoolRecord record = (WSBoolRecord)sheet.FindFirstRecordBySid(WSBoolRecord.sid); // Check defaults Assert.AreEqual(true, record.AlternateExpression); Assert.AreEqual(true, record.AlternateFormula); Assert.AreEqual(false, record.Autobreaks); Assert.AreEqual(false, record.Dialog); Assert.AreEqual(false, record.DisplayGuts); Assert.AreEqual(true, record.FitToPage); Assert.AreEqual(false, record.RowSumsBelow); Assert.AreEqual(false, record.RowSumsRight); // Alter s.AlternativeExpression = (false); s.AlternativeFormula = (false); s.Autobreaks = true; s.Dialog = true; s.DisplayGuts = true; s.FitToPage = false; s.RowSumsBelow = true; s.RowSumsRight = true; // Check Assert.AreEqual(false, record.AlternateExpression); Assert.AreEqual(false, record.AlternateFormula); Assert.AreEqual(true, record.Autobreaks); Assert.AreEqual(true, record.Dialog); Assert.AreEqual(true, record.DisplayGuts); Assert.AreEqual(false, record.FitToPage); Assert.AreEqual(true, record.RowSumsBelow); Assert.AreEqual(true, record.RowSumsRight); Assert.AreEqual(false, s.AlternativeExpression); Assert.AreEqual(false, s.AlternativeFormula); Assert.AreEqual(true, s.Autobreaks); Assert.AreEqual(true, s.Dialog); Assert.AreEqual(true, s.DisplayGuts); Assert.AreEqual(false, s.FitToPage); Assert.AreEqual(true, s.RowSumsBelow); Assert.AreEqual(true, s.RowSumsRight); }
/// <summary> /// 创建Excel标题行 /// </summary> /// <param name="workbook">工作簿对象</param> /// <param name="sheet">Excel单页</param> /// <param name="strHeaderText">标题行文本</param> /// <param name="dtSource">DataTable数据源</param> public void CreateRowHeader(HSSFWorkbook workbook, Sheet sheet, int startRowIndex, string strHeaderText, DataTable dtSource) { #region 表头及样式 { Row headerRow = sheet.CreateRow(startRowIndex); headerRow.HeightInPoints = 25; headerRow.CreateCell(0).SetCellValue(strHeaderText); CellStyle headStyle = workbook.CreateCellStyle(); headStyle.Alignment = HorizontalAlignment.CENTER; Font font = workbook.CreateFont(); font.FontHeightInPoints = 20; font.Boldweight = 700; headStyle.SetFont(font); headStyle.WrapText = true; headerRow.GetCell(0).CellStyle = headStyle; sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, dtSource.Columns.Count - 1)); } #endregion #region 列头及样式 { int[] arrColWidth = GetColumnWidth(dtSource); Row headerRow = sheet.CreateRow(startRowIndex+1); CellStyle headStyle = workbook.CreateCellStyle(); headStyle.Alignment = HorizontalAlignment.CENTER; Font font = workbook.CreateFont(); font.FontHeightInPoints = 10; font.Boldweight = 700; headStyle.SetFont(font); foreach (DataColumn column in dtSource.Columns) { headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName); headerRow.GetCell(column.Ordinal).CellStyle = headStyle; //设置列宽 sheet.SetColumnWidth(column.Ordinal, (arrColWidth[column.Ordinal] + 1) * 256); } } #endregion }
public void TestProtect() { HSSFWorkbook workbook = new HSSFWorkbook(); HSSFSheet hssfSheet = (HSSFSheet)workbook.CreateSheet(); NPOI.HSSF.Model.Sheet sheet = hssfSheet.Sheet; ProtectRecord Protect = sheet.Protect; Assert.IsFalse(Protect.Protect); // This will tell us that CloneSheet, and by extension, // the list forms of CreateSheet leave us with an accessible // ProtectRecord. hssfSheet.ProtectSheet("secret"); NPOI.HSSF.Model.Sheet Cloned = sheet.CloneSheet(); Assert.IsNotNull(Cloned.Protect); Assert.IsTrue(hssfSheet.Protect); }
public void TestSheetSerializeSizeMisMatch_bug45066() { HSSFWorkbook wb = new HSSFWorkbook(); NPOI.HSSF.Model.Sheet sheet = ((HSSFSheet)wb.CreateSheet("Sheet1")).Sheet; IList sheetRecords = sheet.Records; // one way (of many) to cause the discrepancy is with a badly behaved record: sheetRecords.Add(new BadlyBehavedRecord()); // There is also much logic inside Sheet that (if buggy) might also cause the discrepancy try { wb.GetBytes(); throw new AssertFailedException("Identified bug 45066 a"); } catch (InvalidOperationException e) { // Expected badly behaved sheet record to cause exception Assert.IsTrue(e.Message.StartsWith("Actual serialized sheet size")); } }
/// <summary> /// Returns the index of the given sheet /// </summary> /// <param name="sheet">the sheet to look up</param> /// <returns>index of the sheet (0 based).-1 /// if not found </returns> public int GetSheetIndex(Sheet sheet) { for (int i = 0; i < _sheets.Count; i++) { if (_sheets[i] == sheet) { return i; } } return -1; }
/// <summary> /// 创建Excel标题行 /// </summary> /// <param name="workbook">工作簿对象</param> /// <param name="sheet">Excel单页</param> /// <param name="strHeaderText">标题行文本</param> /// <param name="dtSource">DataTable数据源</param> public void CreateRowHeader(HSSFWorkbook workbook, Sheet sheet, string strHeaderText, DataTable dtSource) { CreateRowHeader(workbook, sheet, 0, strHeaderText, dtSource); }
/// <summary> /// 填充Excel数据行 /// </summary> /// <param name="workbook">工作簿对象</param> /// <param name="sheet">Excel单页</param> /// <param name="startRowIndex">数据行开始索引,默认为2</param> /// <param name="dtSource">DataTable数据源</param> /// <param name="formatOptions">格式化选项</param> /// <param name="footerAvgColumns">平均汇总的列</param> /// <param name="footerSumColumns">总和汇总的列</param> /// <param name="mergeColumnIndexs">合并的列</param> public void FillRowData(HSSFWorkbook workbook, Sheet sheet, int startRowIndex, DataTable dtSource, Dictionary<int, FormatStyle> formatOptions, List<int> footerAvgColumns, List<int> footerSumColumns, List<int> mergeColumnIndexs) { #region 格式化选项 CellStyle dateTimeStyle = workbook.CreateCellStyle(); DataFormat dateTimeFormat = workbook.CreateDataFormat(); dateTimeStyle.DataFormat = dateTimeFormat.GetFormat("yyyy-mm-dd hh:mm:ss"); CellStyle dateStyle = workbook.CreateCellStyle(); DataFormat format = workbook.CreateDataFormat(); dateStyle.DataFormat = format.GetFormat("yyyy-mm-dd"); CellStyle percentStyle = workbook.CreateCellStyle(); percentStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("0.00%"); CellStyle toFix2CellStyle = workbook.CreateCellStyle(); toFix2CellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("0.00"); #endregion for (int i = 0; i < dtSource.Rows.Count; i++) { Row dataRow = sheet.CreateRow(startRowIndex); #region 填充内容 for (int j = 0; j < dtSource.Columns.Count; j++) { Cell newCell = dataRow.CreateCell(j); string drValue = dtSource.Rows[i][j].ToString(); switch (dtSource.Columns[j].DataType.ToString()) { case "System.String"://字符串类型 newCell.SetCellValue(drValue); break; case "System.DateTime"://日期类型 DateTime dateV; DateTime.TryParse(drValue, out dateV); if (formatOptions != null && formatOptions.Count > 0) { // 格式化设置 if (formatOptions.ContainsKey(j)) { switch (formatOptions[j]) { case FormatStyle.Date: newCell.CellStyle = dateStyle; break; default: newCell.CellStyle = dateTimeStyle; break; } } } else { newCell.CellStyle = dateTimeStyle; } newCell.SetCellValue(dateV); break; case "System.Boolean"://布尔型 bool boolV = false; bool.TryParse(drValue, out boolV); newCell.SetCellValue(boolV); break; case "System.Int16"://整型 case "System.Int32": case "System.Int64": case "System.Byte": int intV = 0; int.TryParse(drValue, out intV); newCell.SetCellValue(intV); break; case "System.Decimal"://浮点型 case "System.Double": double doubV = 0; double.TryParse(drValue, out doubV); if (formatOptions != null && formatOptions.Count > 0) { // 格式化设置 if (formatOptions.ContainsKey(j)) { switch (formatOptions[j]) { case FormatStyle.Percent: newCell.CellStyle = percentStyle; break; case FormatStyle.ToFix2: newCell.CellStyle = toFix2CellStyle; break; } } } newCell.SetCellValue(doubV); break; case "System.DBNull"://空值处理 newCell.SetCellValue(""); break; default: newCell.SetCellValue(""); break; } } #endregion startRowIndex++; } #region 合并单元格 if (mergeColumnIndexs != null) { foreach (int startIndex in mergeColumnIndexs) { int t1, t2, initSpan; string temp; for (t1 = 2; t1 <= sheet.LastRowNum; t1++) { initSpan = 1; if (sheet.GetRow(t1).GetCell(startIndex) != null) { Cell cell = sheet.GetRow(t1).GetCell(startIndex); switch (cell.CellType) { case CellType.NUMERIC: temp = sheet.GetRow(t1).GetCell(startIndex).DateCellValue.ToString(); break; case CellType.STRING: temp = sheet.GetRow(t1).GetCell(startIndex).StringCellValue; break; default: temp = sheet.GetRow(t1).GetCell(startIndex).StringCellValue; break; } for (t2 = t1 + 1; t2 <= sheet.LastRowNum; t2++) { if (sheet.GetRow(t2).GetCell(startIndex) != null) { Cell cellCol = sheet.GetRow(t2).GetCell(startIndex); string current = string.Empty; switch (cellCol.CellType) { case CellType.NUMERIC: current = sheet.GetRow(t2).GetCell(startIndex).DateCellValue.ToString(); break; case CellType.STRING: current = sheet.GetRow(t2).GetCell(startIndex).StringCellValue; break; default: current = sheet.GetRow(t2).GetCell(startIndex).StringCellValue; break; } if (String.Compare(temp, current) == 0) { initSpan++; CellRangeAddress region = new CellRangeAddress(t1, t2, startIndex, startIndex); sheet.AddMergedRegion(region); CellStyle style = workbook.CreateCellStyle(); style.VerticalAlignment = VerticalAlignment.BOTTOM; sheet.GetRow(t1).GetCell(startIndex).CellStyle = style; } else { break; } } } t1 = t2 - 1; } } } } #endregion #region 汇总运算 string[] alphabet = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" }; CellStyle footerRowStyle = workbook.CreateCellStyle(); #region 平均值汇总运算 if (footerAvgColumns != null && footerAvgColumns.Count > 0) { startRowIndex++; Row footerAvgTitleRow = sheet.CreateRow(startRowIndex++); footerAvgTitleRow.RowStyle = footerRowStyle; Cell footerAvgTitleCell = footerAvgTitleRow.CreateCell(0); footerAvgTitleCell.SetCellValue("平均:"); Row footerAvgRow = sheet.CreateRow(startRowIndex++); for (int i = 0; i < footerAvgColumns.Count; i++) { Cell footerAvg5Cell = footerAvgRow.CreateCell(footerAvgColumns[i]); switch (formatOptions[footerAvgColumns[i]]) { case FormatStyle.Percent: footerAvg5Cell.CellStyle = percentStyle; break; case FormatStyle.ToFix2: footerAvg5Cell.CellStyle = toFix2CellStyle; break; } string num = alphabet[footerAvgColumns[i]]; string formulaExpr = string.Format("AVERAGE(${0}3:${0}{1})", num, dtSource.Rows.Count + 3); footerAvg5Cell.CellFormula = formulaExpr; } } #endregion #region 总和汇总运算 if (footerSumColumns != null && footerSumColumns.Count > 0) { startRowIndex++; Row footerSumTitleRow = sheet.CreateRow(startRowIndex++); footerSumTitleRow.RowStyle = footerRowStyle; Cell footerSumTitleCell = footerSumTitleRow.CreateCell(0); footerSumTitleCell.SetCellValue("总计:"); Row footerSumRow = sheet.CreateRow(startRowIndex++); for (int i = 0; i < footerSumColumns.Count; i++) { Cell footerSumCell = footerSumRow.CreateCell(footerSumColumns[i]); switch (formatOptions[footerSumColumns[i]]) { case FormatStyle.Percent: footerSumCell.CellStyle = percentStyle; break; case FormatStyle.ToFix2: footerSumCell.CellStyle = toFix2CellStyle; break; } string num = alphabet[footerSumColumns[i]]; string formulaExpr = string.Format("SUM(${0}3:${0}{1})", num, dtSource.Rows.Count + 3 + 1); footerSumCell.CellFormula = formulaExpr; } } #endregion #endregion }
/// <summary> /// Creates an HSSFSheet representing the given Sheet object. Should only be /// called by HSSFWorkbook when Reading in an exisiting file. /// </summary> /// <param name="workbook">The HSSF Workbook object associated with the sheet.</param> /// <param name="sheet">lowlevel Sheet object this sheet will represent</param> /// <see cref="NPOI.HSSF.UserModel.HSSFWorkbook.CreateSheet"/> public HSSFSheet(HSSFWorkbook workbook, Sheet sheet) { this.sheet = sheet; rows = new Dictionary<int,HSSFRow>(); this.workbook = workbook; this.book = workbook.Workbook; SetPropertiesFromSheet(sheet); }
/// <summary> /// used internally to Set the properties given a Sheet object /// </summary> /// <param name="sheet">The sheet.</param> private void SetPropertiesFromSheet(Sheet sheet) { RowRecord row = sheet.NextRow; bool rowRecordsAlreadyPresent = row != null; while (row != null) { CreateRowFromRecord(row); row = sheet.NextRow; } CellValueRecordInterface[] cvals = sheet.GetValueRecords(); long timestart = DateTime.Now.Millisecond; if (log.Check(POILogger.DEBUG)) log.Log(DEBUG, "Time at start of cell creating in HSSF sheet = ", timestart); HSSFRow lastrow = null; // Add every cell to its row for (int i = 0; i < cvals.Length; i++) { CellValueRecordInterface cval = cvals[i]; long cellstart = DateTime.Now.Millisecond; HSSFRow hrow = lastrow; if ((lastrow == null) || (lastrow.RowNum != cval.Row)) { hrow = GetRow(cval.Row); if (hrow == null) { // Some tools (like Perl module SpReadsheet::WriteExcel - bug 41187) skip the RowRecords // Excel, OpenOffice.org and GoogleDocs are all OK with this, so POI should be too. if (rowRecordsAlreadyPresent) { // if at least one row record is present, all should be present. throw new Exception("Unexpected missing row when some rows alReady present"); } // Create the row record on the fly now. RowRecord rowRec = new RowRecord(cval.Row); sheet.AddRow(rowRec); hrow = CreateRowFromRecord(rowRec); } } if (hrow != null) { lastrow = hrow; if (cval is Record) { if (log.Check(POILogger.DEBUG)) log.Log(DEBUG, "record id = " + StringUtil.ToHexString(((Record)cval).Sid)); } hrow.CreateCellFromRecord(cval); if (log.Check(POILogger.DEBUG)) log.Log(DEBUG, "record took ",DateTime.Now.Millisecond - cellstart); } else { cval = null; } } if (log.Check(POILogger.DEBUG)) log.Log(DEBUG, "total sheet cell creation took ", DateTime.Now.Millisecond - timestart); }
/// <summary> /// Creates new HSSFSheet - called by HSSFWorkbook to Create a sheet from /// scratch. You should not be calling this from application code (its protected anyhow). /// </summary> /// <param name="workbook">The HSSF Workbook object associated with the sheet..</param> /// <see cref="NPOI.HSSF.UserModel.HSSFWorkbook.CreateSheet"/> public HSSFSheet(HSSFWorkbook workbook) { sheet = Sheet.CreateSheet(); rows = new Dictionary<int,HSSFRow>(); this.workbook = workbook; this.book = workbook.Workbook; }
/* package */ public HSSFSheetConditionalFormatting(HSSFWorkbook workbook, Sheet sheet) { _workbook = workbook; _conditionalFormattingTable = sheet.ConditionalFormattingTable; }
/// <summary> /// Creates an HSSFSheet representing the given Sheet object. Should only be /// called by HSSFWorkbook when Reading in an exisiting file. /// </summary> /// <param name="_workbook">The HSSF Workbook object associated with the _sheet.</param> /// <param name="_sheet">lowlevel Sheet object this _sheet will represent</param> /// <see cref="NPOI.HSSF.UserModel.HSSFWorkbook.CreateSheet"/> public HSSFSheet(HSSFWorkbook workbook, Sheet sheet) { this._sheet = sheet; rows = new Dictionary<int, NPOI.SS.UserModel.Row>(); this._workbook = workbook; this.book = _workbook.Workbook; SetPropertiesFromSheet(_sheet); }
/// <summary> /// Cell comment Finder. /// Returns cell comment for the specified sheet, row and column. /// </summary> /// <param name="sheet">The sheet.</param> /// <param name="row">The row.</param> /// <param name="column">The column.</param> /// <returns>cell comment or /// <c>null</c> /// if not found</returns> public static HSSFComment FindCellComment(Sheet sheet, int row, int column) { HSSFComment comment = null; Dictionary<short, TextObjectRecord> noteTxo = new Dictionary<short, TextObjectRecord>(); //map shapeId and TextObjectRecord int i=0; for (IEnumerator it = sheet.Records.GetEnumerator(); it.MoveNext(); ) { RecordBase rec = (RecordBase)it.Current; if (rec is NoteRecord) { NoteRecord note = (NoteRecord)rec; if (note.Row == row && note.Column == column) { if (i < noteTxo.Count) { TextObjectRecord txo = (TextObjectRecord)noteTxo[note.ShapeId]; comment = new HSSFComment(note, txo); comment.Row = note.Row; comment.Column = note.Column; comment.Author = (note.Author); comment.Visible = (note.Flags == NoteRecord.NOTE_VISIBLE); comment.String = txo.Str; break; } } } else if (rec is ObjRecord) { ObjRecord obj = (ObjRecord)rec; SubRecord sub = (SubRecord)obj.GetSubRecords()[0]; if (sub is CommonObjectDataSubRecord) { CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord)sub; if (cmo.ObjectType == CommonObjectType.COMMENT) { //Find the nearest TextObjectRecord which holds comment's text and map it to its shapeId while (it.MoveNext()) { rec = (Record)it.Current; if (rec is TextObjectRecord) { noteTxo.Add(cmo.ObjectId, (TextObjectRecord)rec); break; } } } } } } return comment; }
/** * Check if the cloned sheet has drawings. If yes, then allocate a new drawing group ID and * re-generate shape IDs * * @param sheet the cloned sheet */ public void CloneDrawings(Sheet sheet) { FindDrawingGroup(); if (drawingManager == null) { //this workbook does not have drawings return; } //check if the cloned sheet has drawings int aggLoc = sheet.AggregateDrawingRecords(drawingManager, false); if (aggLoc != -1) { EscherAggregate agg = (EscherAggregate)sheet.FindFirstRecordBySid(EscherAggregate.sid); EscherContainerRecord escherContainer = agg.GetEscherContainer(); if (escherContainer == null) { return; } EscherDggRecord dgg = drawingManager.GetDgg(); //register a new drawing group for the cloned sheet int dgId = drawingManager.FindNewDrawingGroupId(); dgg.AddCluster(dgId, 0); dgg.DrawingsSaved = dgg.DrawingsSaved + 1; EscherDgRecord dg = null; for (IEnumerator it = escherContainer.ChildRecords.GetEnumerator(); it.MoveNext(); ) { Object er = it.Current; if (er is EscherDgRecord) { dg = (EscherDgRecord)er; //update id of the drawing in the cloned sheet dg.Options = ((short)(dgId << 4)); } else if (er is EscherContainerRecord) { //recursively find shape records and re-generate shapeId ArrayList spRecords = new ArrayList(); EscherContainerRecord cp = (EscherContainerRecord)er; cp.GetRecordsById(EscherSpRecord.RECORD_ID, ref spRecords); for (IEnumerator spIt = spRecords.GetEnumerator(); spIt.MoveNext(); ) { EscherSpRecord sp = (EscherSpRecord)spIt.Current; int shapeId = drawingManager.AllocateShapeId((short)dgId, dg); //allocateShapeId increments the number of shapes. roll back to the previous value dg.NumShapes = (dg.NumShapes - 1); sp.ShapeId = (shapeId); } } } } }