private void CreateColumnCopies(uint colFromIdx, int numOfColumns, Func <CellProxy, CellProxy> fnCreate)
        {
            Action <uint, uint> actionCopyColumn = (rowIdx, colIdx) =>
            {
                RowColumn rcOld = new RowColumn()
                {
                    Row = rowIdx, Column = colIdx
                };
                if (rcOld.Column == colFromIdx)
                {
                    foreach (var newColIdx in Enumerable.Range((int)colFromIdx + 1, numOfColumns))
                    {
                        RowColumn rcNew = new RowColumn()
                        {
                            Row = rcOld.Row, Column = (uint)newColIdx
                        };
                        CellProxy cOld = GetCell(rcOld.Row, rcOld.Column);
                        if (cOld != null)
                        {
                            CellProxy cNew = fnCreate(cOld);
                            if (cNew != null)
                            {
                                AddCellToCache(cNew, rcNew.Row, rcNew.Column);
                            }
                        }
                    }
                }
            };

            LoopCells(actionCopyColumn);
        }
Esempio n. 2
0
        private object GetValue()
        {
            CellProxy c = this.Worksheet.GetCell(this.Row, this.Column);

            if (c != null)
            {
                if (c.DataType != null)
                {
                    CellValues cellDataType = (CellValues)c.DataType;
                    if (cellDataType == CellValues.Number)
                    {
                        return(c.Value);
                    }
                    if (cellDataType == CellValues.InlineString)
                    {
                        return(c.Value);
                    }
                    else if (cellDataType == CellValues.SharedString)
                    {
                        if (c.Value != null)
                        {
                            return(this.Worksheet.Document.SharedStrings.Get(Convert.ToUInt32(c.Value)));
                        }
                    }
                }
                if (c.StyleIndex != null)
                {
                    CellFormat cf = this.Worksheet.Document.Styles.GetCellFormat(c.StyleIndex.Value);
                    if (this.Worksheet.Document.Styles.IsDateFormat(cf))
                    {
                        if (c.Value != null)
                        {
                            return(DateTime.FromOADate((double)c.Value));
                        }
                    }
                    else
                    {
                        if (c.Value != null)
                        {
                            return(c.Value);
                        }
                    }
                }
                else
                {
                    if (c.Value != null)
                    {
                        return(c.Value);
                    }
                }
            }
            return(null);
        }
        private void AddCellToCache(CellProxy c, uint rowIdx, uint colIdx)
        {
            this.Modified = true;

            SortedList <uint, CellProxy> rowCache;

            if (!_cachedCells.TryGetValue(rowIdx, out rowCache))
            {
                rowCache             = new SortedList <uint, CellProxy>();
                _cachedCells[rowIdx] = rowCache;
            }
            rowCache[colIdx] = c;
        }
        private CellProxy RemoveCellFromCache(uint rowIdx, uint colIdx)
        {
            this.Modified = true;

            CellProxy c = null;
            SortedList <uint, CellProxy> rowCache;

            if (_cachedCells.TryGetValue(rowIdx, out rowCache))
            {
                if (rowCache.TryGetValue(colIdx, out c))
                {
                    rowCache.Remove(colIdx);
                    return(c);
                }
            }
            return(null);
        }
        private void CreateRowCopies(uint rowFromIdx, int numOfRows, Func <CellProxy, CellProxy> fnCreate)
        {
            SortedList <uint, CellProxy> rowCache;

            if (_cachedCells.TryGetValue(rowFromIdx, out rowCache))
            {
                Row cachedRow;
                _cachedRows.TryGetValue(rowFromIdx, out cachedRow);

                foreach (var newRowIdx in Enumerable.Range((int)rowFromIdx + 1, numOfRows))
                {
                    if (cachedRow != null)
                    {
                        Row cachedRowCopy = (Row)cachedRow.CloneNode(false);
                        cachedRowCopy.RowIndex = (uint)newRowIdx;
                        _cachedRows.Add(cachedRowCopy.RowIndex, cachedRowCopy);
                    }

                    foreach (var colIdx in rowCache.Keys)
                    {
                        RowColumn rcOld = new RowColumn()
                        {
                            Row = rowFromIdx, Column = colIdx
                        };
                        RowColumn rcNew = new RowColumn()
                        {
                            Row = (uint)newRowIdx, Column = colIdx
                        };
                        CellProxy cOld = GetCell(rcOld.Row, rcOld.Column);
                        CellProxy cNew = fnCreate(cOld);
                        if (cNew != null)
                        {
                            AddCellToCache(cNew, rcNew.Row, rcNew.Column);
                        }
                    }
                }
            }
        }
        public CellProxy EnsureCell(uint row, uint col)
        {
            CellProxy c = null;
            SortedList <uint, CellProxy> rowCache;

            if (!_cachedCells.TryGetValue(row, out rowCache))
            {
                c = new CellProxy(this);
                AddCellToCache(c, row, col);
            }
            else
            {
                if (!rowCache.TryGetValue(col, out c))
                {
                    c = new CellProxy(this);
                    if (rowCache != null)
                    {
                        AddCellToCache(c, rowCache, col);
                    }
                }
            }
            return(c);
        }
        public void InsertOrDeleteColumns(uint colStart, int colDelta, bool copyPreviousStyle)
        {
            if (colDelta == 0)
            {
                return;
            }

            this.Modified = true;

            Action <uint, uint> shiftCells = (rowIdx, colIdx) =>
            {
                if (colIdx >= colStart)
                {
                    CellProxy c = RemoveCellFromCache(rowIdx, colIdx);

                    int newColIdx = (int)colIdx + colDelta;
                    // If delta is negative, cells will be not put back, i.e. deleted
                    if (newColIdx >= colStart && newColIdx >= 1)
                    {
                        if (colIdx >= ExcelConstraints.MaxColumns)
                        {
                            throw new InvalidOperationException("Max number of columns exceeded");
                        }

                        AddCellToCache(c, rowIdx, (uint)newColIdx);
                    }
                }
            };

            if (colDelta > 0)
            {
                LoopCellsReverse(shiftCells);
            }
            else
            {
                LoopCells(shiftCells);
            }

            // Adjust cached <col> elements
            Columns cols = this.GetFirstElement <Columns>();

            if (cols != null)
            {
                List <Column> colsToRemove = new List <Column>();
                foreach (Column col in cols)
                {
                    if (col.Min >= colStart)
                    {
                        col.Min = (uint)Math.Max(0, col.Min + colDelta);
                    }
                    if (col.Max >= colStart)
                    {
                        col.Max = (uint)Math.Max(0, col.Max + colDelta);
                    }
                    if (col.Min <= 0 || col.Max < col.Min)
                    {
                        colsToRemove.Add(col);
                    }
                }
                foreach (Column col in colsToRemove)
                {
                    col.Remove();
                }

                Column colPrev = (from col in cols.Elements <Column>()
                                  where col.Max == colStart - 1
                                  select col).FirstOrDefault();
                if (colPrev != null)
                {
                    colPrev.Max = (uint)(colPrev.Max + colDelta);
                }
                if (cols.ChildElements.Count == 0)
                {
                    _cachedElements.Remove(cols);
                }
            }

            if (colDelta > 0)
            {
                if (copyPreviousStyle)
                {
                    CreateColumnCopies(colStart - 1, colDelta,
                                       cOld =>
                    {
                        if (cOld.StyleIndex != null)
                        {
                            var cNew        = new CellProxy(this);
                            cNew.StyleIndex = cOld.StyleIndex;
                            return(cNew);
                        }
                        return(null);
                    }
                                       );
                }
                else
                {
                    // Ensure this column does not have a column defintion
                    // so we don't copy previous column style

                    // TODO: make this more efficient
                    for (uint ctr = colStart; ctr < colStart + colDelta; ctr++)
                    {
                        EnsureSingleSpanColumn(ctr);
                        DeleteSingleSpanColumn(ctr);
                    }
                }
            }
        }
        public void InsertOrDeleteRows(uint rowStart, int rowDelta, bool copyPreviousStyle)
        {
            if (rowDelta == 0)
            {
                return;
            }

            this.Modified = true;

            IList <uint> rowIndexes;

            if (rowDelta > 0)
            {
                rowIndexes = _cachedCells.Keys.Reverse().ToList();
            }
            else
            {
                rowIndexes = _cachedCells.Keys.ToList();
            }

            var newCellProxies = new SortedList <uint, SortedList <uint, CellProxy> >();

            foreach (uint rowIdx in rowIndexes)
            {
                uint newRowIdx;
                if (rowIdx >= rowStart)
                {
                    newRowIdx = (uint)(rowIdx + rowDelta);
                }
                else
                {
                    newRowIdx = rowIdx;
                }

                newCellProxies[newRowIdx] = _cachedCells[rowIdx];
            }
            _cachedCells = newCellProxies;

            // Adjust cached <row> elements
            IEnumerable <uint> affectedCachedRowIndexes;

            if (rowDelta > 0)
            {
                affectedCachedRowIndexes = _cachedRows.Keys.Where(k => k >= rowStart).Reverse().ToList();
            }
            else
            {
                affectedCachedRowIndexes = _cachedRows.Keys.Where(k => k >= rowStart).ToList();
            }
            foreach (var rowIdx in affectedCachedRowIndexes)
            {
                Row r         = _cachedRows[rowIdx];
                int newRowIdx = (int)r.RowIndex.Value + rowDelta;
                _cachedRows.Remove(rowIdx);

                // If delta is negative, rows will be not put back, i.e. deleted
                if (newRowIdx >= rowStart && newRowIdx >= 1)
                {
                    r.RowIndex = (uint)(newRowIdx);
                    _cachedRows[r.RowIndex] = r;
                }
            }

            if (rowDelta > 0 && copyPreviousStyle)
            {
                CreateRowCopies(rowStart - 1, rowDelta,
                                cOld =>
                {
                    if (cOld.StyleIndex != null)
                    {
                        var cNew        = new CellProxy(this);
                        cNew.StyleIndex = cOld.StyleIndex;
                        return(cNew);
                    }
                    return(null);
                }
                                );
            }
        }
        /// <summary>
        /// For optimization -- enables use of rowCache if we already have it
        /// </summary>
        /// <param name="c"></param>
        /// <param name="rowIdx"></param>
        /// <param name="colIdx"></param>
        private void AddCellToCache(CellProxy c, SortedList <uint, CellProxy> rowCache, uint colIdx)
        {
            this.Modified = true;

            rowCache[colIdx] = c;
        }
        public void Load()
        {
            WorksheetPart wp = _wsheet.GetOWorksheetPart();

            if (wp == null)
            {
                return;
            }

            Action <Cell> readCell = (cell) =>
            {
                RowColumn rc        = ExcelAddress.ToRowColumn(cell.CellReference);
                CellProxy cellProxy = this.EnsureCell(rc.Row, rc.Column);
                if (cell.DataType != null)
                {
                    cellProxy.DataType = cell.DataType.Value;
                    if (cell.DataType.Value == CellValues.InlineString)
                    {
                        cellProxy.Value = cell.InlineString.Text.Text;
                    }
                    else
                    {
                        if (cell.CellValue != null)
                        {
                            cellProxy.Value = cell.CellValue.Text;
                        }
                        else
                        {
                            cellProxy.Value = string.Empty;
                        }
                    }
                }
                else
                {
                    if (cell.CellValue != null)
                    {
                        cellProxy.Value = cell.CellValue.Text;
                    }
                }
                if (cell.StyleIndex != null)
                {
                    cellProxy.StyleIndex = cell.StyleIndex;
                }
                if (cell.ShowPhonetic != null)
                {
                    cellProxy.ShowPhonetic = cell.ShowPhonetic;
                }
                if (cell.ValueMetaIndex != null)
                {
                    cellProxy.ValueMetaIndex = cell.ValueMetaIndex;
                }
                if (cell.CellFormula != null)
                {
                    cellProxy.CreateFormula();
                    cellProxy.Formula.Text      = cell.CellFormula.Text;
                    cellProxy.Formula.R1        = cell.CellFormula.R1;
                    cellProxy.Formula.R2        = cell.CellFormula.R2;
                    cellProxy.Formula.Reference = cell.CellFormula.Reference;
                    if (cell.CellFormula.AlwaysCalculateArray != null)
                    {
                        cellProxy.Formula.AlwaysCalculateArray = cell.CellFormula.AlwaysCalculateArray;
                    }
                    if (cell.CellFormula.Bx != null)
                    {
                        cellProxy.Formula.Bx = cell.CellFormula.Bx;
                    }
                    if (cell.CellFormula.CalculateCell != null)
                    {
                        cellProxy.Formula.CalculateCell = cell.CellFormula.CalculateCell;
                    }
                    if (cell.CellFormula.DataTable2D != null)
                    {
                        cellProxy.Formula.DataTable2D = cell.CellFormula.DataTable2D;
                    }
                    if (cell.CellFormula.DataTableRow != null)
                    {
                        cellProxy.Formula.DataTableRow = cell.CellFormula.DataTableRow;
                    }
                    if (cell.CellFormula.FormulaType != null)
                    {
                        cellProxy.Formula.FormulaType = cell.CellFormula.FormulaType;
                    }
                    if (cell.CellFormula.Input1Deleted != null)
                    {
                        cellProxy.Formula.Input1Deleted = cell.CellFormula.Input1Deleted;
                    }
                    if (cell.CellFormula.Input2Deleted != null)
                    {
                        cellProxy.Formula.Input2Deleted = cell.CellFormula.Input2Deleted;
                    }
                    if (cell.CellFormula.SharedIndex != null)
                    {
                        cellProxy.Formula.SharedIndex = cell.CellFormula.SharedIndex;
                    }

                    cellProxy.Value = null; // Don't cache/store values for formulas
                }
            };

            OpenXmlReader reader      = OpenXmlReader.Create(_wsheet.GetOWorksheetPart());
            bool          inWorksheet = false;
            bool          inSheetData = false;

            while (reader.Read())
            {
                if (inWorksheet && reader.IsStartElement)
                {
                    if (reader.ElementType == typeof(Row) && reader.IsStartElement)
                    {
                        // ----------------------------------------
                        // Scan row if anything other than RowIndex and Spans has been set,
                        // if so then cache
                        Row r = (Row)reader.LoadCurrentElement();
                        var needToCacheRow = (from a in r.GetAttributes()
                                              let ln = a.LocalName
                                                       where ln != "r" && ln != "spans"
                                                       select a).Any();

                        if (needToCacheRow)
                        {
                            _cachedRows.Add(r.RowIndex, (Row)r.CloneNode(false));
                        }
                        foreach (Cell cell in r.Elements <Cell>())
                        {
                            readCell(cell);
                        }
                        // ----------------------------------------
                    }
                    else if (reader.ElementType == typeof(SheetData))
                    {
                        inSheetData = reader.IsStartElement;
                    }
                    else if (reader.IsStartElement)
                    {
                        var e = reader.LoadCurrentElement();
                        _cachedElements.Add(e);
                    }
                }
                else if (reader.ElementType == typeof(Worksheet))
                {
                    inWorksheet = reader.IsStartElement;
                }
            }

            // Reset modified to false (loading sets it to true due to CellProxy loading)
            this.Modified = false;
        }
        private void WriteSheetData(OpenXmlWriter writer)
        {
            writer.WriteStartElement(new SheetData());
            foreach (var rowItem in _cachedCells)
            {
                uint rowIdx   = rowItem.Key;
                var  cells    = rowItem.Value;
                var  rowAttrs = EnumRowAttributes(rowIdx, cells).ToList();
                if (rowAttrs.Count > 0 || cells.Count > 0)
                {
                    writer.WriteStartElement(new Row(), rowAttrs);

                    foreach (var cellItem in cells)
                    {
                        uint      colIdx    = cellItem.Key;
                        CellProxy cellProxy = cellItem.Value;
                        writer.WriteStartElement(new Cell(), EnumCellProxyAttributes(rowIdx, colIdx, cellProxy));
                        if (cellProxy.Formula != null)
                        {
                            CellFormula cf = new CellFormula(cellProxy.Formula.Text);
                            if (cellProxy.Formula.R1 != null)
                            {
                                cf.R1 = cellProxy.Formula.R1;
                            }
                            if (cellProxy.Formula.R2 != null)
                            {
                                cf.R2 = cellProxy.Formula.R2;
                            }
                            if (cellProxy.Formula.Reference != null)
                            {
                                cf.Reference = cellProxy.Formula.Reference;
                            }

                            if (cellProxy.Formula.AlwaysCalculateArray != null)
                            {
                                cf.AlwaysCalculateArray = cellProxy.Formula.AlwaysCalculateArray;
                            }
                            if (cellProxy.Formula.Bx != null)
                            {
                                cf.Bx = cellProxy.Formula.Bx;
                            }
                            if (cellProxy.Formula.CalculateCell != null)
                            {
                                cf.CalculateCell = cellProxy.Formula.CalculateCell;
                            }
                            if (cellProxy.Formula.DataTable2D != null)
                            {
                                cf.DataTable2D = cellProxy.Formula.DataTable2D;
                            }
                            if (cellProxy.Formula.DataTableRow != null)
                            {
                                cf.DataTableRow = cellProxy.Formula.DataTableRow;
                            }
                            if (cellProxy.Formula.FormulaType != null)
                            {
                                cf.FormulaType = cellProxy.Formula.FormulaType;
                            }
                            if (cellProxy.Formula.Input1Deleted != null)
                            {
                                cf.Input1Deleted = cellProxy.Formula.Input1Deleted;
                            }
                            if (cellProxy.Formula.Input2Deleted != null)
                            {
                                cf.Input2Deleted = cellProxy.Formula.Input2Deleted;
                            }
                            if (cellProxy.Formula.SharedIndex != null)
                            {
                                cf.SharedIndex = cellProxy.Formula.SharedIndex;
                            }

                            writer.WriteElement(cf);
                        }
                        if (cellProxy.Value != null)
                        {
                            writer.WriteElement(new CellValue(cellProxy.SerializedValue));
                        }
                        writer.WriteEndElement(); // c
                    }

                    writer.WriteEndElement(); // row
                }
            }
            writer.WriteEndElement(); // sheetData
        }
        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()));
            }
        }
Esempio n. 13
0
        private void SetValue(object value)
        {
            CellProxy c             = this.Worksheet.EnsureCell(this.Row, this.Column);
            bool      hasDateFormat = false;

            if (c.StyleIndex != null)
            {
                CellFormat cfCurrent = this.Worksheet.Document.Styles.GetCellFormat(c.StyleIndex.Value);
                if (this.Worksheet.Document.Styles.IsDateFormat(cfCurrent))
                {
                    hasDateFormat = true;
                }
            }

            if (value == null)
            {
                c.DataType = null;
                c.Value    = null;
            }
            else
            {
                Type valueType = value.GetType();
                if (valueType == typeof(DateTime))
                {
                    c.DataType = null;
                    if (!hasDateFormat)
                    {
                        // 14 = generic date format
                        CellFormat cfDate = new CellFormat()
                        {
                            ApplyNumberFormat = true, NumberFormatId = 14
                        };
                        uint cfIdxDate = this.Worksheet.Document.Styles.MergeAndRegisterCellFormat(cfDate, c.StyleIndex, false);
                        c.StyleIndex = cfIdxDate;
                    }
                    DateTime dtValue = (DateTime)value;
                    c.Value = dtValue.ToOADate();
                }
                else if (ValueChecker.IsNumeric(valueType))
                {
                    if (hasDateFormat)
                    {
                        CellFormat cfGeneric = new CellFormat()
                        {
                            NumberFormatId = 0
                        };
                        uint cfIfxGeneric = this.Worksheet.Document.Styles.MergeAndRegisterCellFormat(cfGeneric, c.StyleIndex, false);
                        c.StyleIndex = cfIfxGeneric;
                    }
                    c.DataType = CellValues.Number;
                    c.Value    = value;
                }
                else
                {
                    if (hasDateFormat)
                    {
                        CellFormat cfGeneric = new CellFormat()
                        {
                            NumberFormatId = 0
                        };
                        uint cfIfxGeneric = this.Worksheet.Document.Styles.MergeAndRegisterCellFormat(cfGeneric, c.StyleIndex, false);
                        c.StyleIndex = cfIfxGeneric;
                    }
                    string valueStr     = value.ToString();
                    int    sharedStrIdx = this.Worksheet.Document.SharedStrings.Put(valueStr);
                    c.DataType = CellValues.SharedString;
                    c.Value    = (uint)sharedStrIdx;
                }
            }
        }