Exemplo n.º 1
0
        internal static void Reuse(Worksheet sheet, CellPosition fromPosition, RangePosition toRange)
        {
            fromPosition = sheet.FixPos(fromPosition);
            toRange      = sheet.FixRange(toRange);

            var cell = sheet.cells[fromPosition.Row, fromPosition.Col];

            #region Arguments Check
            if (cell == null ||
                string.IsNullOrEmpty(cell.InnerFormula) ||
                cell.FormulaTree == null)
            {
                throw new InvalidOperationException("cannot found formula from specified position, try reset formula for the cell again");
            }

            if (cell.formulaStatus != Formula.FormulaStatus.Normal)
            {
                throw new InvalidOperationException("formula in specified cell contains errors, correct the formula firstly");
            }

            if (toRange.Contains(fromPosition))
            {
                throw new ArgumentException("toRange should not contain the position of the formula to be reused");
            }
            #endregion             // Arguments Check

            var    rs   = new ReplacableString(cell.InnerFormula);
            STNode node = cell.FormulaTree;

            Stack <List <Cell> > dirtyCells = new Stack <List <Cell> >();

            for (int r = toRange.Row; r <= toRange.EndRow; r++)
            {
                for (int c = toRange.Col; c <= toRange.EndCol;)
                {
                    var toCell = sheet.CreateAndGetCell(r, c);

                    if (toCell.Colspan <= 0)
                    {
                        c++;
                        continue;
                    }

                    FormulaRefactor.CopyFormula(fromPosition, node, toCell, rs, dirtyCells);

                    c += cell.Colspan;
                }
            }
        }
Exemplo n.º 2
0
        internal static void CopyFormula(CellPosition fromPosition, STNode fromNode, Cell toCell,
                                         ReplacableString rs, Stack <List <Cell> > dirtyCells)
        {
            var sheet = toCell.Worksheet;

            STNode node2 = (STNode)fromNode.Clone();

            int r = toCell.Row;
            int c = toCell.Column;

            rs.Restore();

            #region Rebuilt Formula
            STNode.RecursivelyIterate(node2, n =>
            {
                switch (n.Type)
                {
                case STNodeType.CELL:
                    #region Cell Offset
                    {
                        var refCellNode = (STCellNode)n;
                        var newPos      = refCellNode.Position;

                        #region Calc Offset
                        // B2: =A1
                        // B3: =A2
                        if (newPos.RowProperty == PositionProperty.Relative)
                        {
                            newPos.Row += r - fromPosition.Row;
                        }

                        if (newPos.ColumnProperty == PositionProperty.Relative)
                        {
                            newPos.Col += c - fromPosition.Col;
                        }
                        #endregion                                 // Calc Offset

                        if (newPos.Row < 0 || newPos.Col < 0 ||
                            newPos.Row >= sheet.rows.Count || newPos.Col >= sheet.cols.Count)
                        {
                            toCell.formulaStatus = FormulaStatus.InvalidReference;
                        }

                        refCellNode.Position = newPos;

                        n.Start  += rs.Offset;
                        int diff  = rs.Replace(n.Start, n.Length, newPos.ToAddress());
                        n.Length += diff;
                    }
                    break;
                    #endregion                     // Cell Offset

                case STNodeType.RANGE:
                    #region Range Offset
                    {
                        var refRangeNode = (STRangeNode)n;
                        var newRange     = refRangeNode.Range;

                        #region Calc Offset
                        int diffRow = r - fromPosition.Row;
                        int diffCol = c - fromPosition.Col;

                        if (newRange.StartRowProperty == PositionProperty.Relative)
                        {
                            newRange.Row += diffRow;
                        }

                        if (newRange.StartColumnProperty == PositionProperty.Relative)
                        {
                            newRange.Col += diffCol;
                        }

                        //if (newRange.EndRowProperty == PositionProperty.Relative)
                        //{
                        //	newRange.EndRow += diffRow;
                        //}

                        //if (newRange.EndColumnProperty == PositionProperty.Relative)
                        //{
                        //	newRange.EndCol += diffCol;
                        //}
                        #endregion                                 // Calc Offset

                        if (newRange.Row < 0 || newRange.Col < 0 ||
                            newRange.Row >= sheet.rows.Count || newRange.Col >= sheet.cols.Count ||
                            newRange.EndRow < 0 || newRange.EndCol < 0 ||
                            newRange.EndRow >= sheet.rows.Count || newRange.EndCol >= sheet.cols.Count)
                        {
                            toCell.formulaStatus = FormulaStatus.InvalidReference;
                        }

                        refRangeNode.Range = newRange;

                        n.Start  += rs.Offset;
                        int diff  = rs.Replace(n.Start, n.Length, newRange.ToAddress());
                        n.Length += diff;
                    }
                    break;
                    #endregion                             // Range Offset
                }
            });
            #endregion             // Rebuilt Formula

            #region Update To New Cell

            toCell.InnerFormula = rs.ToString();

#if FORMULA_FORMAT
            toCell.InnerFormula = Generate(cell.InnerFormula, node2);
#endif // FORMULA_FORMAT

            sheet.SetCellFormula(toCell, node2);

            if (toCell.formulaStatus == FormulaStatus.Normal)
            {
                sheet.RecalcCell(toCell, dirtyCells);
            }
            #endregion             // Update To New Cell
        }