예제 #1
0
 /// <summary>
 /// Sort data on specified column.
 /// </summary>
 /// <param name="columnIndex">Zero-based number of column to sort data.</param>
 /// <param name="startRow">First number of row to allow sort data.</param>
 /// <param name="endRow">Last number of number of row to allow sort data.</param>
 /// <param name="startColumn">First number of column to allow sort data.</param>
 /// <param name="endColumn">Last number of column to allow sort data.</param>
 /// <param name="order">Order of data sort.</param>
 /// <param name="cellDataComparer">Custom cell data comparer, compares two cells and returns an integer.
 /// Set this value to null to use default built-in comparer.</param>
 /// <returns>Data changed range.</returns>
 public RangePosition SortColumn(int columnIndex, int startRow, int endRow, int startColumn, int endColumn,
                                 SortOrder order = SortOrder.Ascending,
                                 CellElementFlag moveElementFlag = CellElementFlag.Data,
                                 Func <int, int, object, object, int> cellDataComparer = null)
 {
     return(SortColumn(columnIndex, new RangePosition(startRow, startColumn, MaxContentRow - startRow + 1,
                                                      endColumn - startColumn + 1), order, moveElementFlag, cellDataComparer));
 }
예제 #2
0
        /// <summary>
        /// Clear content inside specified range.
        /// </summary>
        /// <param name="addressOrName">Address or name to locate the range.</param>
        /// <param name="flags">Elements in cell specified by this flag to be removed.</param>
        public void ClearRangeContent(string addressOrName, CellElementFlag flags)
        {
            NamedRange namedRange;

            if (RangePosition.IsValidAddress(addressOrName))
            {
                ClearRangeContent(new RangePosition(addressOrName), flags);
            }
            else if (this.TryGetNamedRange(addressOrName, out namedRange))
            {
                ClearRangeContent(namedRange.Position, flags);
            }
            else
            {
                throw new InvalidAddressException(addressOrName);
            }
        }
예제 #3
0
 /// <summary>
 /// Sort data inside specified range.
 /// </summary>
 /// <param name="columnIndex">Data will be sorted based on this column.</param>
 /// <param name="applyRange">Affect range.</param>
 /// <param name="order">Order of data sort.</param>
 /// <param name="cellDataComparer"></param>
 /// <returns></returns>
 public RangePosition SortColumn(int columnIndex, string applyRange, SortOrder order = SortOrder.Ascending,
                                 CellElementFlag moveElementFlag = CellElementFlag.Data,
                                 Func <int, int, object, object, int> cellDataComparer = null)
 {
     if (RangePosition.IsValidAddress(applyRange))
     {
         return(this.SortColumn(columnIndex, new RangePosition(applyRange), order, moveElementFlag, cellDataComparer));
     }
     else if (this.TryGetNamedRangePosition(applyRange, out var range))
     {
         return(this.SortColumn(columnIndex, range, order, moveElementFlag, cellDataComparer));
     }
     else
     {
         throw new InvalidAddressException(applyRange);
     }
 }
예제 #4
0
        /// <summary>
        /// Sort data on specified column.
        /// </summary>
        /// <param name="columnIndex">Zero-based number of column to sort data.</param>
        /// <param name="applyRange">Data only be changed in this range during sort.</param>
        /// <param name="order">Order of data sort.</param>
        /// <param name="cellDataComparer">Custom cell data comparer, compares two cells and returns an integer.
        /// Set this value to null to use default built-in comparer.</param>
        /// <returns>Data changed range.</returns>
        public RangePosition SortColumn(int columnIndex, RangePosition applyRange,
                                        SortOrder order = SortOrder.Ascending,
                                        CellElementFlag moveElementFlag = CellElementFlag.Data,
                                        Func <int, int, object, object, int> cellDataComparer = null)
        {
            var range = FixRange(applyRange);

            RangePosition affectRange = RangePosition.Empty;

            if (cellDataComparer != null)
            {
                this.cellDataComparer = cellDataComparer;
            }

#if DEBUG
            Stopwatch sw = Stopwatch.StartNew();
#endif // DEBUG

            int[] sortedOrder = null;

            // stop fire events
            this.SuspendDataChangedEvents();

            try
            {
                this.controlAdapter.ChangeCursor(CursorStyle.Busy);

                if (!this.CheckQuickSortRange(columnIndex, range.Row, range.EndRow, range.Col, range.EndCol, order, ref affectRange))
                {
                    throw new InvalidOperationException("Cannot change a part of range, all cells should be having same colspan on column.");
                }

                this.QuickSortColumn(columnIndex, range.Row, range.EndRow, range.Col, range.EndCol, order, ref affectRange,
                                     cellDataComparer == null ? (Func <int, int, object, int>)CompareCell : UserCellDataComparerAdapter, sortedOrder);

#if DEBUG
                sw.Stop();

                if (sw.ElapsedMilliseconds > 10)
                {
                    Debug.WriteLine(string.Format("sort column by {0} on [{1}-{2}]: {3} ms", columnIndex,
                                                  range.Col, range.EndCol, sw.ElapsedMilliseconds));
                }
#endif // DEBUG
            }
            finally
            {
                // resume to fire events
                this.ResumeDataChangedEvents();
            }

            this.RequestInvalidate();

            this.controlAdapter.ChangeCursor(CursorStyle.PlatformDefault);

            if (!affectRange.IsEmpty)
            {
                for (int c = affectRange.Col; c <= affectRange.EndCol; c++)
                {
                    var header = this.cols[c];

                    if (header.Body != null)
                    {
                        header.Body.OnDataChange(affectRange.Row, affectRange.EndRow);
                    }
                }

                this.RaiseRangeDataChangedEvent(affectRange);

                this.RowsSorted?.Invoke(this, new Events.RangeEventArgs(affectRange));
            }

            return(affectRange);
        }
예제 #5
0
 /// <summary>
 /// Sort data on specified column.
 /// </summary>
 /// <param name="columnIndex">Zero-based number of column to sort data</param>
 /// <param name="titleRows">Indicates that how many title rows exist at the top of worksheet,
 /// Title rows will not be included in sort apply range.</param>
 /// <param name="order">Order of data sort.</param>
 /// <param name="cellDataComparer">Custom cell data comparer, compares two cells and returns an integer.
 /// Set this value to null to use default built-in comparer.</param>
 /// <returns>Data changed range.</returns>
 public RangePosition SortColumn(int columnIndex, int titleRows, SortOrder order = SortOrder.Ascending,
                                 CellElementFlag moveElementFlag = CellElementFlag.Data,
                                 Func <int, int, object, object, int> cellDataComparer = null)
 {
     return(SortColumn(columnIndex, titleRows, MaxContentRow, 0, MaxContentCol, order, moveElementFlag, cellDataComparer));
 }
예제 #6
0
 /// <summary>
 /// Sort data on specified column.
 /// </summary>
 /// <param name="columnAddress">Base column specified by an address to sort data.</param>
 /// <param name="order">Order of data sort.</param>
 /// <param name="cellDataComparer">Custom cell data comparer, compares two cells and returns an integer.
 /// Set this value to null to use default built-in comparer.</param>
 /// <returns>Data changed range</returns>
 public RangePosition SortColumn(string columnAddress, SortOrder order = SortOrder.Ascending,
                                 CellElementFlag moveElementFlag       = CellElementFlag.Data,
                                 Func <int, int, object, object, int> cellDataComparer = null)
 {
     return(SortColumn(RGUtility.GetNumberOfChar(columnAddress), order, moveElementFlag, cellDataComparer));
 }
예제 #7
0
        /// <summary>
        /// Clear content inside specified range.
        /// </summary>
        /// <param name="range">The range to be clear.</param>
        /// <param name="flags">Elements in cell specified by this flag to be removed.</param>
        /// <param name="checkReadonly">True to ignore read-only cells; False to delete content from read-only cells.</param>
        public void ClearRangeContent(RangePosition range, CellElementFlag flags, bool checkReadonly = true)
        {
            var fixedRange = FixRange(range);

            bool deleteData       = (flags & CellElementFlag.Data) == CellElementFlag.Data;
            bool deleteFormula    = (flags & CellElementFlag.Formula) == CellElementFlag.Formula;
            bool deleteDataFormat = (flags & CellElementFlag.DataFormat) == CellElementFlag.DataFormat;
            bool deleteBody       = (flags & CellElementFlag.Body) == CellElementFlag.Body;
            bool deleteStyle      = (flags & CellElementFlag.Style) == CellElementFlag.Style;

            int maxcol = range.Col;

#if FORMULA
            List <Cell> formulaDirtyCells = new List <Cell>();
#endif // FORMULA

            for (int r = fixedRange.Row; r <= fixedRange.EndRow; r++)
            {
                for (int c = fixedRange.Col; c <= fixedRange.EndCol; c++)
                {
                    var cell = this.cells[r, c];

                    if (cell != null)
                    {
                        bool dirty = false;

                        if ((!checkReadonly || !cell.IsReadOnly))
                        {
                            if (deleteData)
                            {
                                cell.InnerData    = null;
                                cell.InnerDisplay = string.Empty;

                                if (cell.InnerStyle.HAlign == ReoGridHorAlign.General)
                                {
                                    cell.RenderHorAlign = ReoGridRenderHorAlign.Left;
                                }

                                dirty = true;
                            }

                            if (deleteFormula)
                            {
                                cell.InnerFormula = null;
#if FORMULA
                                ClearCellReferenceList(cell);
#endif // FORMULA
                            }

                            if (deleteDataFormat)
                            {
                                cell.DataFormat     = DataFormat.CellDataFormatFlag.General;
                                cell.DataFormatArgs = null;

                                dirty = true;
                            }

                            if (deleteBody)
                            {
                                cell.body = null;

                                dirty = true;
                            }

                            if (dirty)
                            {
                                if (maxcol < c)
                                {
                                    maxcol = c;
                                }

                                //cell.RenderTextBounds = RGRectF.Empty;
                                //cell.RenderColor = null;
                                //cell.RenderScaleFactor = this.scaleFactor;

                                // TODO: auto adjust row height

#if FORMULA
                                foreach (var referecedRange in this.formulaRanges)
                                {
                                    if (referecedRange.Value.Any(rr => rr.Contains(cell.InternalPos)) &&
                                        !formulaDirtyCells.Contains(referecedRange.Key))
                                    {
                                        formulaDirtyCells.Add(referecedRange.Key);
                                    }
                                }
#endif // FORMULA

                                this.RaiseCellDataChangedEvent(cell);
                            }
                        }
                    }
                }
            }

            if (deleteStyle)
            {
                this.RemoveRangeStyles(fixedRange, PlainStyleFlag.All);
            }

#if FORMULA
            foreach (var dirtyCell in formulaDirtyCells)
            {
                RecalcCell(dirtyCell);
            }
#endif // FORMULA

            // only update the changed columns (up to maxcol)
            for (int i = fixedRange.Col; i <= maxcol; i++)
            {
                var header = this.cols[i];
                if (header.Body != null)
                {
                    header.Body.OnDataChange(fixedRange.Row, fixedRange.EndRow);
                }
            }

            //var fromRange = FixRange(range);

            //if (flags == CellElementFlag.All)
            //{
            //	for (int r = fromRange.Row; r <= fromRange.EndRow; r++)
            //	{
            //		for (int c = fromRange.Col; c <= fromRange.EndCol; c++)
            //		{
            //			this.cells[r, c] = null;
            //		}
            //	}

            //	InvalidateCanvas();
            //}
            //else
            //{
            //	if ((flags & CellElementFlag.Data) == CellElementFlag.Data)
            //	{
            //		DeleteRangeData(fromRange, true);
            //	}

            //	if ((flags & CellElementFlag.Body) == CellElementFlag.Body)
            //	{
            //		this.IterateCells(fromRange, (r, c, cell) =>
            //		{
            //			cell.body = null;
            //			return true;
            //		});

            //		InvalidateCanvas();
            //	}

            //	if ((flags & CellElementFlag.DataFormat) == CellElementFlag.DataFormat)
            //	{
            //		this.DeleteRangeDataFormat(fromRange);
            //	}

            //	if ((flags & CellElementFlag.Style) == CellElementFlag.Style)
            //	{
            //		RemoveRangeStyle(fromRange, PlainStyleFlag.All);
            //	}
            //}

            if ((flags & CellElementFlag.Border) == CellElementFlag.Border)
            {
                this.RemoveRangeBorders(fixedRange, BorderPositions.All);
            }

            RequestInvalidate();
        }