/// <summary> /// Counts and returns the number of <see cref="RowOrColumnInfo"/>s in the <see cref="RowOrColumnsModel"/> /// </summary> public int Count() { int count = 0; RowOrColumnInfo info = this.first; while (info != null) { count++; info.ExcelIndex = count; info = info.Next; } return(count); }
/// <summary> /// Appends a <see cref="RowOrColumnInfo"/> to the end of this <see cref="RowOrColumnsModel"/>. /// </summary> /// <param name="map">A <see cref="ExcelMapCoOrdinate"/> which relates to the <see cref="RowOrColumnInfo"/> being added.</param> internal void Add(ExcelMapCoOrdinate map) { if (this.first == null) { this.first = RowOrColumnInfo.Create(map, this.isRowModel); this.last = this.first; } else { RowOrColumnInfo newInfo = RowOrColumnInfo.Create(map, this.isRowModel); this.last.Next = newInfo; this.last = newInfo; } }
/// <summary> /// Creates and returns a new instance of the <see cref="RowOrColumnInfo" /> class. /// </summary> /// <param name="map">The <see cref="ExcelMapCoOrdinate"/> which is the source for this column</param> /// <param name="isRow">If true, the <see cref="RowOrColumnInfo" /> created relates a row, otherwise a column.</param> /// <returns>A new instance of a <see cref="RowOrColumnInfo"/> class</returns> public static RowOrColumnInfo Create(ExcelMapCoOrdinate map, bool isRow) { var info = new RowOrColumnInfo(isRow); if (isRow) { info.HeightOrWidth = map.AssignedHeight; info.Hidden = map.RowIsHidden; } else { info.HeightOrWidth = map.AssignedWidth; info.Hidden = map.ColumnIsHidden; } info.AddMap(map); return(info); }
/// <summary> /// Appends the <see cref="RowOrColumnInfo"/>s within a <see cref="RowOrColumnsModel"/> to the end of this <see cref="RowOrColumnsModel"/>. /// </summary> /// <param name="model"><see cref="RowOrColumnsModel"/> to be appended</param> internal void AppendModel(RowOrColumnsModel model) { if (this.first == null) { // Model currently not populated, so set this.first = model.First; this.last = model.Last; } else { // Chain to the end RowOrColumnInfo nextFirstInfo = model.First; this.last.Next = nextFirstInfo; if (nextFirstInfo != null) { this.last = model.Last; } } }
/// <summary> /// Adds all of the <see cref="ExcelMapCoOrdinate">maps</see> associated with a <see cref="RowOrColumnInfo"/> /// </summary> /// <param name="info">A <see cref="RowOrColumnInfo"/></param> public void AddMaps(RowOrColumnInfo info) { // Add RowOrColumnInfo maps to the column (if not already there) this.maps.AddDistinct(info.Maps); if (this.IsRow) { // Add the column to the maps foreach (ExcelMapCoOrdinate map in info.Maps) { map.Rows.AddDistinct(this); } } else { // Add the column to the maps foreach (ExcelMapCoOrdinate map in info.Maps) { map.Columns.AddDistinct(this); } } }
/// <summary> /// Builds a model of the rows within this entity. /// </summary> internal override RowOrColumnsModel BuildRowsModel() { var rowsModel = new RowOrColumnsModel(true); // Consider all elements in the container on a column-by-column basis. for (uint colIdx = 1; colIdx <= this.mapColumnCount; colIdx++) { // Create a RowsModel for the column var columnRowsModel = new RowOrColumnsModel(true); for (uint rowIdx = 1; rowIdx <= this.mapRowCount; rowIdx++) { // Use System.Drawing.Point as key as it has a very efficient hashing algorithm var cellListKey = new System.Drawing.Point((int)colIdx, (int)rowIdx); if (this.cells.ContainsKey(cellListKey)) { ExcelMapCoOrdinate element = this.cells[cellListKey]; RowOrColumnsModel elementRowsModel = element.BuildRowsModel(); columnRowsModel.AppendModel(elementRowsModel); } } // Merge the columns model generated for the row with the model for the container. rowsModel.MergeModel(columnRowsModel); // Add this container into the column (if not already there) RowOrColumnInfo rowInfo = rowsModel.First; while (rowInfo != null) { rowInfo.AddMap(this); rowInfo = rowInfo.Next; } } return(rowsModel); }
private RowOrColumnInfo AllocateHiddenSourceToTargets(RowOrColumnInfo source, RowOrColumnInfo target, double?remainingSourceHeightOrWidth) { // First, assign source info to target. target.AddMaps(source); // Next allocate source to next targets, until all has been allocated while (remainingSourceHeightOrWidth == null || remainingSourceHeightOrWidth.Value > 0) { // While the target is smaller than the source, allocate new columns // for the target to accept the source column information. RowOrColumnInfo nextTarget = target.Next; if (nextTarget == null) { // No 'Next' target. // Create and link target row/column for the remaining height/width, assign source to new target. nextTarget = RowOrColumnInfo.Create(this.isRowModel); nextTarget.HeightOrWidth = remainingSourceHeightOrWidth; nextTarget.Hidden = source.Hidden; nextTarget.MoveMaps(source); target.Next = nextTarget; // Update the last row/column if the inserted row/column is now the last. if (target == this.last) { this.last = nextTarget; } // Set remains to 0 so no more allocating. target = nextTarget; remainingSourceHeightOrWidth = 0; } else { if (!nextTarget.Hidden) { // Create and link in a new target for the remaining source. RowOrColumnInfo insertedTarget = RowOrColumnInfo.Create(this.isRowModel); insertedTarget.HeightOrWidth = remainingSourceHeightOrWidth; insertedTarget.Hidden = true; insertedTarget.MoveMaps(source); // Link in the newly inserted column before the next insertedTarget.Next = nextTarget; target.Next = insertedTarget; // Set remains to 0 so no more allocating. target = insertedTarget; remainingSourceHeightOrWidth = 0; } else { // We have a 'Next' target column which is hidden if (nextTarget.HeightOrWidth.HasValue) { // It has a fixed height/width double nextTargetHeightOrWidth = nextTarget.HeightOrWidth.Value; if (nextTargetHeightOrWidth == remainingSourceHeightOrWidth) { // Next target row/column can be fully allocated to the source nextTarget.MoveMaps(source); target = nextTarget; // Set remains to 0 so no more allocating. remainingSourceHeightOrWidth = 0; } else if (nextTargetHeightOrWidth > remainingSourceHeightOrWidth) { // Next target row/column is higher/wider than required remaining. // Create a new target for the remaining height/width + insert before the target RowOrColumnInfo insertedTarget = RowOrColumnInfo.Create(this.isRowModel); insertedTarget.HeightOrWidth = remainingSourceHeightOrWidth; insertedTarget.Hidden = nextTarget.Hidden; // Assign target + source info to inserted. insertedTarget.MoveMaps(source); insertedTarget.AddMaps(nextTarget); // Truncate the original target and update with source info. nextTarget.HeightOrWidth = nextTargetHeightOrWidth - remainingSourceHeightOrWidth; // Link in the newly inserted row/column before the next insertedTarget.Next = nextTarget; target.Next = insertedTarget; // Set remains to 0 so no more allocating. target = insertedTarget; remainingSourceHeightOrWidth = 0; } else { // Next target is smaller than required remaining, assign source info to target, nextTarget.AddMaps(source); target = nextTarget; // Move on to next, reducing remaining. remainingSourceHeightOrWidth = remainingSourceHeightOrWidth - nextTargetHeightOrWidth; } } else { // Next target has no specified height/width, assign source info to target, and set height/width of source. nextTarget.HeightOrWidth = remainingSourceHeightOrWidth; nextTarget.MoveMaps(source); // Set remains to 0 so no more allocating. remainingSourceHeightOrWidth = 0; } } } } return(target); }
private RowOrColumnInfo AllocateVisibleSourceToVisibleTargets(RowOrColumnInfo source, RowOrColumnInfo target) { RowOrColumnInfo currentTarget = target; RowOrColumnInfo lastTarget = currentTarget; if (currentTarget.HeightOrWidth.HasValue) { if (source.HeightOrWidth.HasValue) { // The amount the source width is over the target width double remainingSourceHeightOrWidth = source.HeightOrWidth.Value - lastTarget.HeightOrWidth.Value; if (remainingSourceHeightOrWidth < 0) { // Target column is wider than the source // Create a new row/column for the remaining source width/height, assign target info to this column. RowOrColumnInfo insertedTarget = RowOrColumnInfo.Create(this.isRowModel); insertedTarget.HeightOrWidth = -remainingSourceHeightOrWidth; insertedTarget.AddMaps(lastTarget); // Truncate the target to the height/width of the source lastTarget.HeightOrWidth = source.HeightOrWidth; // Assign source info to truncated target. lastTarget.MoveMaps(source); // Link new row/column into chain after original target insertedTarget.Next = lastTarget.Next; lastTarget.Next = insertedTarget; // Update the last row/column if the inserted row/column is now the last. if (lastTarget == this.last) { this.last = insertedTarget; } } else { // Source is the same size, or wider, that the target. if (source.Hidden) { lastTarget = AllocateHiddenSourceToTargets(source, lastTarget, remainingSourceHeightOrWidth); } else { lastTarget = AllocateVisibleSourceToTargets(source, lastTarget, remainingSourceHeightOrWidth); } } } else { // Target row/column has height/width, but source does not, assign source info to target. currentTarget.MoveMaps(source); } } else { // Target row/column has no specified height/width, assign source info to target and set height/width of target to source. currentTarget.HeightOrWidth = source.HeightOrWidth; currentTarget.MoveMaps(source); } return(lastTarget); }
/// <summary> /// Allocates target <see cref="RowOrColumnInfo"/> to the source <see cref="RowOrColumnInfo"/> until the source row or column is covered. /// </summary> /// <param name="lastAllocatedTarget">The target row or column where the source row or column is to be allocated</param> /// <param name="source">The source row or column to be allocated</param> /// <returns>The last target that was allocated (target may have been split to accomodate the source)</returns> private RowOrColumnInfo AllocateTargetToSource(RowOrColumnInfo lastAllocatedTarget, RowOrColumnInfo source) { // Determine the next target column to be allocated to the supplied source RowOrColumnInfo lastTarget = lastAllocatedTarget == null ? this.first : lastAllocatedTarget.Next;; bool allocateToTargetWidth = lastTarget.HeightOrWidth.HasValue && !source.HeightOrWidth.HasValue; bool allocateToSourceWidth = source.HeightOrWidth.HasValue && !lastTarget.HeightOrWidth.HasValue; double?remainingSourceWidth = source.HeightOrWidth - lastTarget.HeightOrWidth; // Next allocate source to next targets, until all has been allocated if (allocateToTargetWidth) { // Target column has width, but source does not, assign source column info to target. lastTarget.MoveMaps(source); } else if (allocateToSourceWidth) { // Target column has no specified width, but the source does, assign source column info to target and set width of target to source. lastTarget.HeightOrWidth = source.HeightOrWidth; lastTarget.MoveMaps(source); } else if (remainingSourceWidth.HasValue) { if (remainingSourceWidth.Value == 0) { // Source and target column widths are the same, assign source to target lastTarget.MoveMaps(source); } else if (remainingSourceWidth.Value < 0) { // Target column is wider than the source (both have values) // Create a new column for the remaining source width, assign target column info to this column. RowOrColumnInfo insertedTargetColumnInfo = RowOrColumnInfo.Create(this.isRowModel); insertedTargetColumnInfo.HeightOrWidth = -remainingSourceWidth; insertedTargetColumnInfo.Hidden = source.Hidden; insertedTargetColumnInfo.AddMaps(lastTarget); // Truncate the target to the width of the source lastTarget.HeightOrWidth = source.HeightOrWidth; // Assign source column info to target. lastTarget.MoveMaps(source); // Link new column into chain after original target insertedTargetColumnInfo.Next = lastTarget.Next; lastTarget.Next = insertedTargetColumnInfo; // Update the last column if the inserted column is now the last column. if (lastTarget == this.last) { this.last = insertedTargetColumnInfo; } } else { // Source column is wider than the target (both have values) lastTarget = AllocateVisibleSourceToVisibleTargets(source, lastTarget); } } else { lastTarget.MoveMaps(source); } // Return the last target column that was allocated return(lastTarget); }
/// <summary> /// Merge the supplied <see cref="RowOrColumnsModel"/> into this <see cref="RowOrColumnsModel"/>. /// </summary> /// <param name="modelToBeMerged">The <see cref="RowOrColumnsModel" /> to be merged into this <see cref="RowOrColumnsModel"/></param> internal void MergeModel(RowOrColumnsModel modelToBeMerged) { if (this.first == null) { // Model currently not populated, so set this.first = modelToBeMerged.First; this.last = modelToBeMerged.Last; } else { // Traverse this linked list. RowOrColumnInfo sourceRowOrColInfo = modelToBeMerged.First; RowOrColumnInfo previousTargetRowOrColInfo = null; RowOrColumnInfo currentTargetRowOrColInfo = this.first; while (sourceRowOrColInfo != null) { if (!sourceRowOrColInfo.Hidden && !currentTargetRowOrColInfo.Hidden) { // Allocate the visible source column to the visible target columns currentTargetRowOrColInfo = AllocateVisibleSourceToVisibleTargets(sourceRowOrColInfo, currentTargetRowOrColInfo); } else if (sourceRowOrColInfo.Hidden && !currentTargetRowOrColInfo.Hidden) { // Allocate the hidden source column before the current visible target column RowOrColumnInfo insertedColumn = RowOrColumnInfo.Create(this.isRowModel); insertedColumn.Hidden = sourceRowOrColInfo.Hidden; insertedColumn.HeightOrWidth = sourceRowOrColInfo.HeightOrWidth; insertedColumn.AddMaps(sourceRowOrColInfo); insertedColumn.AddMaps(currentTargetRowOrColInfo); insertedColumn.Next = currentTargetRowOrColInfo; if (previousTargetRowOrColInfo == null) { // The new hidden target column is first column in this model this.first = insertedColumn; } else { previousTargetRowOrColInfo.Next = insertedColumn; } // Move back to newly inserted column, so next current remains unchanged currentTargetRowOrColInfo = insertedColumn; } else if (sourceRowOrColInfo.Hidden && currentTargetRowOrColInfo.Hidden) { // Allocate the source to the current target (creating new target row/columns for splits etc). currentTargetRowOrColInfo = AllocateTargetToSource(previousTargetRowOrColInfo, sourceRowOrColInfo); } else if (!sourceRowOrColInfo.Hidden && currentTargetRowOrColInfo.Hidden) { currentTargetRowOrColInfo = AllocateVisibleSourceToTargets(sourceRowOrColInfo, currentTargetRowOrColInfo, sourceRowOrColInfo.HeightOrWidth); } // Source column allocation complete, move on to next source column. sourceRowOrColInfo = sourceRowOrColInfo.Next; // If there is a next source column, and no next target column, then create // a null width target column with the same visibility as the source to accept the next source. if (sourceRowOrColInfo != null && currentTargetRowOrColInfo.Next == null) { currentTargetRowOrColInfo.Next = RowOrColumnInfo.Create(this.isRowModel); currentTargetRowOrColInfo.Next.Hidden = sourceRowOrColInfo.Hidden; // Update the last column if the inserted column is now the last column. if (currentTargetRowOrColInfo == this.last) { this.last = currentTargetRowOrColInfo.Next; } } // Move on to next target column previousTargetRowOrColInfo = currentTargetRowOrColInfo; currentTargetRowOrColInfo = currentTargetRowOrColInfo.Next; } } }
/// <summary> /// Write the content of the <see cref="ExcelMapCoOrdinateContainer"> to the worksheet</see>. /// </summary> /// <param name="sheetName">Name of the sheet.</param> /// <param name="worksheetPart">The worksheet part.</param> /// <param name="mapCoOrdinateContainer">The map co ordinate container.</param> /// <param name="stylesManager">The styles manager.</param> /// <param name="spreadsheetDocument">The spreadsheet document.</param> public static void WriteMapToExcel(string sheetName, WorksheetPart worksheetPart, ExcelMapCoOrdinateContainer mapCoOrdinateContainer, ExcelStylesManager stylesManager, SpreadsheetDocument spreadsheetDocument) { TempDiagnostics.Output(string.Format("Writing map for ExcelMap[{0}] to worksheet '{1}'", mapCoOrdinateContainer.ContainerType, sheetName)); var dimensionConverter = new ExcelDimensionConverter("Calibri", 11.0f); // Manages the writing to Excel. var excelWriteManager = new OpenXmlExcelWriteManager(worksheetPart.Worksheet); //** First we need to clear the destination worksheet down (rows, columns and merged areas) excelWriteManager.EmptyWorksheet(); // Build up Columns models on all nested containers. RowOrColumnsModel columnsModel = mapCoOrdinateContainer.BuildColumnsModel(); int colCount = columnsModel.Count(); // ========================================================== // Traverse each column assigning start and end // column indexes to the maps associated with that column. // ========================================================== RowOrColumnInfo columnInfo = columnsModel.First; while (columnInfo != null) { double?width = columnInfo.HeightOrWidth.HasValue ? (double?)dimensionConverter.WidthToOpenXmlWidth(columnInfo.HeightOrWidth.Value) : null; excelWriteManager.AddColumn(width, columnInfo.Hidden); // Assign Excel start and end columns to maps for merge operations. foreach (ExcelMapCoOrdinate map in columnInfo.Maps) { // Extend any cells that are merged across maps. if (map is ExcelMapCoOrdinatePlaceholder) { var cell = map as ExcelMapCoOrdinatePlaceholder; if (cell.MergeWith != null) { cell.ExcelColumnStart = cell.MergeWith.ExcelColumnStart; cell.MergeWith.ExcelColumnEnd = columnInfo.ExcelIndex; //excelCol } } if (map.ExcelColumnStart == 0) { map.ExcelColumnStart = columnInfo.ExcelIndex; //excelCol; map.ExcelColumnEnd = columnInfo.ExcelIndex; //excelCol; } else { map.ExcelColumnEnd = columnInfo.ExcelIndex; //excelCol; } } // Move on to next column in list columnInfo = columnInfo.Next; } TempDiagnostics.Output(string.Format("Created ColumnsModel which contains '{0}' columns", colCount)); // Build up Rows models on all nested containers. RowOrColumnsModel rowsModel = mapCoOrdinateContainer.BuildRowsModel(); int rowCount = rowsModel.Count(); // ========================================================== // Traverse each row assigning start and end // row indexes to the maps associated with that row. // ========================================================== RowOrColumnInfo rowInfo = rowsModel.First; while (rowInfo != null) { double?height = rowInfo.HeightOrWidth.HasValue ? (double?)dimensionConverter.HeightToOpenXmlHeight(rowInfo.HeightOrWidth.Value) : null; excelWriteManager.AddRow(height, rowInfo.Hidden); // Assign Excel start and end rows to maps for merge operations. foreach (ExcelMapCoOrdinate map in rowInfo.Maps) { if (map.ExcelRowStart == 0) { map.ExcelRowStart = rowInfo.ExcelIndex; //excelRow; map.ExcelRowEnd = rowInfo.ExcelIndex; //excelRow; } else { map.ExcelRowEnd = rowInfo.ExcelIndex; //excelRow; } } // Move on to next Row in list rowInfo = rowInfo.Next; } TempDiagnostics.Output(string.Format("Created RowsModel which contains '{0}' rows", rowCount)); // Build a layered cells dictionary for all cells, keyed by Excel row and column index var layeredCellsDictionary = new LayeredCellsDictionary(); mapCoOrdinateContainer.UpdateLayeredCells(ref layeredCellsDictionary); TempDiagnostics.Output(string.Format("Updated Layered Cell Information for worksheet '{0}' = {1}", sheetName, layeredCellsDictionary.Count)); // Probe the Row, Column and Cell Layered maps, embellishing them with row, column and cell formatting information. for (uint worksheetRow = 1; worksheetRow <= rowCount; worksheetRow++) { for (uint worksheetCol = 1; worksheetCol <= colCount; worksheetCol++) { // We can now use the layeredCellsDictionary to build the // excel workbook based on layered cell information var currentCoOrdinate = new System.Drawing.Point((int)worksheetCol, (int)worksheetRow); LayeredCellInfo layeredCellInfo = layeredCellsDictionary[currentCoOrdinate]; // Work through the layered maps to determine what needs to be written to the Excel worksheet at that Row/Column ProcessLayeredCellMaps(currentCoOrdinate, layeredCellInfo); } } TempDiagnostics.Output(string.Format("Built Worksheet CellInfos[Cols={0},Rows={1}]", colCount, rowCount)); //** Write the 2D array of cell information to the Excel Worksheet //** building a list of areas that are to be merged. for (uint worksheetRow = 1; worksheetRow <= rowCount; worksheetRow++) { OpenXmlSpreadsheet.Row row = excelWriteManager.GetRow(worksheetRow); for (uint worksheetCol = 1; worksheetCol <= colCount; worksheetCol++) { // Pluck out information relating to the current cell var currentCoOrdinate = new System.Drawing.Point((int)worksheetCol, (int)worksheetRow); ExcelCellInfo cellInfo = layeredCellsDictionary[currentCoOrdinate].CellInfo; // Not sure if we need this as column letters are easily (quickly) translated using existing OpenXml helpers string columnLetter = excelWriteManager.GetColumnLetter(worksheetCol); // All merge cells should have the same style as the source merge cell. if (cellInfo.MergeFrom != null) { // If MergeFrom is non-null, then this cell has been already been marked as a merge cell, // whose style is to be the same as the source 'MergeFrom cell. // Update the source (MergeFrom) cell so it ends up containing a reference to the last (MergeTo) cell to be merged. cellInfo.MergeFrom.MergeTo = cellInfo; // Create/lookup styles in the target workbook and return index of created style uint cellStyleIndex = stylesManager.GetOrCreateStyle(cellInfo.MergeFrom.StyleInfo); // Write in to Excel (style information only) var cell = new OpenXmlSpreadsheet.Cell(); cell.SetCellReference(columnLetter, worksheetRow); cell.StyleIndex = cellStyleIndex; row.Append(cell); cellInfo.Cell = cell; } else { // Create/lookup styles in the target workbook and return index of created style uint cellStyleIndex = stylesManager.GetOrCreateStyle(cellInfo.StyleInfo); // NB! If we write a Null value then we lose cell formatting information for some reason object value = cellInfo.Value == null ? string.Empty : cellInfo.Value; // Write in to Excel var cell = new OpenXmlSpreadsheet.Cell(); cell.SetCellReference(columnLetter, worksheetRow); excelWriteManager.SetCellValue(cell, value); cell.StyleIndex = cellStyleIndex; row.Append(cell); cellInfo.Cell = cell; } // Span the cell accross it's parent columns if specified if (cellInfo.LastSpanRow == 0) { cellInfo.LastSpanRow = worksheetRow; } if (cellInfo.LastSpanColumn == 0) { cellInfo.LastSpanColumn = worksheetCol; } // Merge cells if required (spanning) for (uint rowIdx = worksheetRow; rowIdx <= cellInfo.LastSpanRow; rowIdx++) { for (uint colIdx = worksheetCol; colIdx <= cellInfo.LastSpanColumn; colIdx++) { // Mark processed (so we don't over-write) var coOrdinate = new System.Drawing.Point((int)colIdx, (int)rowIdx); if (coOrdinate != currentCoOrdinate) { var mergeCoOrdinate = new System.Drawing.Point((int)colIdx, (int)rowIdx); ExcelCellInfo mergeCellInfo = layeredCellsDictionary[mergeCoOrdinate].CellInfo; if (mergeCellInfo.MergeFrom == null) { mergeCellInfo.MergeFrom = cellInfo; } } } } } } //#if DEBUG // if (!skipMerge) // { //#endif // Merge cells that have been marked to merge in the cellInfos dictionary. MergeCells(worksheetPart.Worksheet, (uint)rowCount, (uint)colCount, layeredCellsDictionary); //#if DEBUG // } //#endif TempDiagnostics.Output(string.Format("Written CellInfos[Cols={0},Rows={1}] to Excel", colCount, rowCount)); // Create a list of all of the the defined names in the container. var definedNameList = new List <ExcelDefinedNameInfo>(); mapCoOrdinateContainer.UpdateDefinedNameList(ref definedNameList, sheetName); // And write into Excel workbook foreach (var definedNameInfo in definedNameList) { uint rangeColumnCount = definedNameInfo.EndColumnIndex - definedNameInfo.StartColumnIndex + 1; uint rangeRowCount = definedNameInfo.EndRowIndex - definedNameInfo.StartRowIndex + 1; if (rangeRowCount > 0 && rangeColumnCount > 0) { spreadsheetDocument.WorkbookPart.Workbook.AddDefinedName(sheetName, definedNameInfo.DefinedName, (uint)definedNameInfo.StartColumnIndex, (uint)definedNameInfo.StartRowIndex, (int)rangeColumnCount, (int)rangeRowCount); } } TempDiagnostics.Output(string.Format("Defined Names added - write map for {0} complete...", mapCoOrdinateContainer.ContainerType)); }