コード例 #1
0
        /// <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);
        }
コード例 #2
0
 /// <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;
     }
 }
コード例 #3
0
        /// <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);
        }
コード例 #4
0
        /// <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;
                }
            }
        }
コード例 #5
0
        /// <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);
                }
            }
        }
コード例 #6
0
        /// <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);
        }
コード例 #7
0
        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);
        }
コード例 #8
0
        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);
        }
コード例 #9
0
        /// <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);
        }
コード例 #10
0
        /// <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;
                }
            }
        }
コード例 #11
0
        /// <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));
        }