public object Clone()
        {
            ColumnAttributesCollection obj = new ColumnAttributesCollection();

            if (_list != null)
            {
                obj._list = new List <ColumnAttributes>();
                for (int i = 0; i < _list.Count; i++)
                {
                    obj._list.Add((ColumnAttributes)_list[i].Clone());
                }
            }
            return(obj);
        }
        /// <summary>
        /// do summary for each sorting field
        /// </summary>
        /// <param name="r"></param>
        /// <param name="cac"></param>
        /// <returns>Each item represent one summary result for a sorting field. If an item is null then the summary not finish</returns>
        public SummaryResult[] ProcessRow(DataTable tbl, int rowNumber, ColumnAttributesCollection cac)
        {
            bool    hasSum = false;
            DataRow r      = tbl.Rows[rowNumber];

            SummaryResult[] ret;
            ret = new SummaryResult[StartColumnSummaries.Length];
            for (int k = 0; k < EndColumnSummaries.Length; k++)
            {
                ret[k] = null;
                //sort value
                object v = r[EndColumnSummaries[k].SortFieldIndex];
                //sort field ordinal
                int kI = EndColumnSummaries[k].SortFieldIndex;
                if (EndSummaryKeys[kI].IsEqual(v))
                {
                    //key not changed, do summary
                    for (int i = 0; i < cac.Count; i++)
                    {
                        if (cac[i].ShowSummaries)
                        {
                            EndColumnSummaries[k].ColumnSummaries[i]  += Convert.ToDouble(r[i], CultureInfo.InvariantCulture);
                            EndColumnSummaries[k].ColumnRecordCount[i] = EndColumnSummaries[k].ColumnRecordCount[i] + 1;
                        }
                    }
                }
                else
                {
                    //key changed, return EndColumnSummaries[k].ColumnSummaries
                    for (int h = k; h < EndColumnSummaries.Length; h++)
                    {
                        ret[h] = new SummaryResult(EndColumnSummaries[h].ColumnSummaries, EndColumnSummaries[h].ColumnRecordCount);
                        int ki = EndColumnSummaries[h].SortFieldIndex;
                        EndSummaryKeys[ki].SetValue(r[ki]);
                    }
                    //reset initial value for the summaries of all sub-elevels
                    for (int h = k; h < EndColumnSummaries.Length; h++)
                    {
                        for (int i = 0; i < cac.Count; i++)
                        {
                            if (cac[i].ShowSummaries)
                            {
                                if (r[i] == null || r[i] == DBNull.Value)
                                {
                                    EndColumnSummaries[h].ColumnSummaries[i] = 0;
                                }
                                else
                                {
                                    EndColumnSummaries[h].ColumnSummaries[i] = Convert.ToDouble(r[i], CultureInfo.InvariantCulture);
                                }
                                EndColumnSummaries[h].ColumnRecordCount[i] = 1;
                            }
                        }
                    }
                    hasSum = true;
                    //rowNumber is actually the next row of the summing rows
                    _owner.AddResults(rowNumber - 1, ret);
                    break;                     //no need to process sub-levels
                }
            }
            if (hasSum)
            {
                return(ret);
            }
            return(null);
        }