private IEnumerable <OpenXmlAttribute> EnumCellProxyAttributes(uint row, uint col, CellProxy cellProxy)
        {
            yield return(new OpenXmlAttribute(null, "r", null, RowColumn.ToAddress(row, col)));

            if (cellProxy.DataType != null)
            {
                yield return(new OpenXmlAttribute(null, "t", null, STCellType((CellValues)cellProxy.DataType)));
            }
            if (cellProxy.StyleIndex != null)
            {
                yield return(new OpenXmlAttribute(null, "s", null, cellProxy.StyleIndex.Value.ToString()));
            }
        }
        public void WriteWorksheetPart(OpenXmlWriter writer)
        {
            // TODO: final cleanup
            // - merge redundant columns
            // - remove unused shared strings

            // Remove rows without cells
            foreach (var rowItem in _cachedCells.ToList())
            {
                if (rowItem.Value.Count == 0)
                {
                    _cachedCells.Remove(rowItem.Key);
                }
            }

            // Simulate rows for cached rows
            foreach (var rowIdx in _cachedRows.Keys)
            {
                if (!_cachedCells.ContainsKey(rowIdx))
                {
                    _cachedCells[rowIdx] = new SortedList <uint, CellProxy>();
                }
            }

            // Get first and last addresses
            uint minRow = uint.MaxValue;
            uint minCol = uint.MaxValue;
            uint maxRow = 0;
            uint maxCol = 0;

            foreach (var rowItem in _cachedCells)
            {
                uint rowIdx = rowItem.Key;
                var  cells  = rowItem.Value;
                if (minRow == uint.MaxValue)
                {
                    minRow = rowIdx;
                }
                maxRow = rowIdx;
                if (cells.Count > 0)
                {
                    minCol = Math.Min(minCol, cells.Keys.First());
                    maxCol = Math.Max(maxCol, cells.Keys.Last());
                }
            }

            string firstAddress = null, lastAddress = null;

            if (minRow < uint.MaxValue && minCol < uint.MaxValue)
            {
                firstAddress = RowColumn.ToAddress(minRow, minCol);
                if (minRow != maxRow || minCol != maxCol)
                {
                    lastAddress = RowColumn.ToAddress(maxRow, maxCol);
                }
            }
            else
            {
                firstAddress = "A1";
            }

            writer.WriteStartDocument();
            writer.WriteStartElement(new Worksheet());
            foreach (string childTagName in SchemaInfo.WorksheetChildSequence)
            {
                if (childTagName == "sheetData")
                {
                    WriteSheetData(writer);
                }
                else if (childTagName == "dimension")
                {
                    string dimensionRef = firstAddress + (lastAddress != null ? ":" + lastAddress : "");
                    writer.WriteElement(new SheetDimension()
                    {
                        Reference = dimensionRef
                    });
                }
                else if (childTagName == "sheetViews")
                {
                    SheetViews svs = GetFirstElement <SheetViews>();
                    if (svs != null)
                    {
                        foreach (SheetView sv in svs.Elements <SheetView>())
                        {
                            foreach (Selection sel in sv.Elements <Selection>())
                            {
                                if (minRow < uint.MaxValue)
                                {
                                    sel.ActiveCell           = firstAddress;
                                    sel.SequenceOfReferences = new ListValue <StringValue>(new StringValue[] { new StringValue(firstAddress) });
                                }
                                else
                                {
                                    sel.Remove();
                                }
                            }
                        }
                        writer.WriteElement(svs);
                    }
                }
                else
                {
                    foreach (var e in GetElementsByTagName(childTagName))
                    {
                        writer.WriteElement(e);
                    }
                }
            }
            writer.WriteEndElement(); // worksheet
        }