public UpdateEntry(CellInfo cell)
 {
     if (cell != null)
     {
         Tuple = cell.Tuple;
     }
 }
 public MemberItem(MemberInfo data, double val, CellInfo cell)
 {
     if (data == null)
         throw new ArgumentNullException("data");
     Cell = cell;
     Member = data;
     Caption = data.Caption;
     m_OriginalValue = val;
     m_DeliveredValue = 0;
     m_NewValue = val;
 }
 public CellControl this[CellInfo cellInfo]
 {
     get
     {
         CellControl res = null;
         if (this.m_CellsViewCache.ContainsKey(cellInfo))
         {
             res = this.m_CellsViewCache[cellInfo];
         }
         return res;
     }
 }
 public void Initialize(CellInfo cell, DataTableWrapper data)
 {
     if (cell != null &&
         cell.CellDescr != null &&
         cell.CellDescr.Value != null)
     {
         txtValue.Text = cell.CellDescr.Value.DisplayValue;
     }
     else
     {
         txtValue.Text = String.Empty;
     }
     tupleCtrl.Initialize(cell);
     dataGrid.Initialize(data);
 }
        public CellInfo GetCellInfo(int column_index, int row_index)
        {
            CellInfo cell_Info = null;
            CellData cell_data = null;

            if (m_CellSet_Descr != null && 
                Rows != null && // чтобы проинициализировать
                Columns != null && // чтобы проинициализировать
                //column_index >= 0 &&
                column_index < m_Columns_LowestMembers.Count &&
                row_index < m_Rows_LowestMembers.Count) 
            {
                if(row_index >= 0)
                    cell_data = m_CellSet_Descr.GetCellDescription(column_index, row_index);
                else
                    cell_data = m_CellSet_Descr.GetCellDescription(column_index);
                
                if (cell_data != null)
                {
                    if (m_CellInfos.ContainsKey(cell_data))
                    {
                        cell_Info = m_CellInfos[cell_data];
                    }
                    else
                    {
                        if (row_index >= 0)
                        {
                            cell_Info = new CellInfo(cell_data,
                               m_Columns_LowestMembers[column_index],
                               m_Rows_LowestMembers[row_index], 
                               GetInvisibleCoords(column_index, row_index));
                        }
                        else
                        {
                            cell_Info = new CellInfo(cell_data,
                               column_index >= 0 ? m_Columns_LowestMembers[column_index] : MemberInfo.Empty,
                               MemberInfo.Empty, 
                               GetInvisibleCoords(column_index, row_index));
                        }
                        m_CellInfos.Add(cell_data, cell_Info);
                    }
                }
            }
            return cell_Info;
        }
		void ShowDrillthroughResult(CellInfo cell, DataTableWrapper tableWrapper)
		{
			if (tableWrapper != null)
			{
				if (m_DrillthroughDialog == null)
				{
					m_DrillthroughDialog = new ModalDialog() { Width = 600, Height = 500, DialogStyle = ModalDialogStyles.OK };
					m_DrillthroughDialog.Caption = Localization.DrillthroughDialog_Caption;
				}
				//RanetDataGrid grid = new RanetDataGrid();
				//grid.Initialize(tableWrapper);

				DrillThroughControl grid = new DrillThroughControl();
				grid.Initialize(cell, tableWrapper);
				m_DrillthroughDialog.Content = grid;
				Panel panel = GetRootPanel(this);
				if (panel != null && !panel.Children.Contains(m_DrillthroughDialog.Dialog.PopUpControl))
				{
					panel.Children.Add(m_DrillthroughDialog.Dialog.PopUpControl);
				}
				ShowDialog(m_DrillthroughDialog);
			}
		}
 /// <summary>
 /// Ищет в кэше изменений ячейку
 /// </summary>
 /// <param name="args"></param>
 /// <returns></returns>
 public UpdateEntry FindChange(CellInfo cell)
 {
     if (cell != null)
     {
         UpdateEntry entry = new UpdateEntry(cell);
         return FindChange(entry);
     }
     return null;
 }
 public void RemoveChange(CellInfo cell)
 {
     if (cell != null)
     {
         UpdateEntry entry = new UpdateEntry(cell);
         RemoveChange(entry);
     }
 }
		protected virtual void ShowValueCopyDialog(CellInfo cell)
		{
			if (m_CSDescr != null && cell != null && cell.IsUpdateable)
			{
				// Если в кэше есть изменения, то нужно спросить об их сохранении
				if (UseChangesCashe && PivotGrid.LocalChanges.Count > 0)
				{
					MessageBox.Show(Localization.PivotGrid_SaveCachedChanges, Localization.MessageBox_Warning, MessageBoxButton.OK);
					return;
				}

				IDictionary<String, MemberWrap> slice = new Dictionary<String, MemberWrap>();
				IDictionary<String, MemberInfo> tuple = cell.GetTuple();
				foreach (String hierarchyUniqueName in tuple.Keys)
				{
					slice.Add(hierarchyUniqueName, new MemberWrap(tuple[hierarchyUniqueName]));
				}

				ModalDialog dlg = new ModalDialog();
				dlg.MinHeight = 300;
				dlg.MinWidth = 400;
				dlg.Height = 500;
				dlg.Width = 600;
				dlg.Caption = Localization.ValueCopyDialog_Caption;
				dlg.DialogOk += new EventHandler<DialogResultArgs>(ValueCopyDialog_OkButtonClick);

				ValueCopyControl CopyControl = new ValueCopyControl();
				CopyControl.CubeName = m_CSDescr.CubeName;
				CopyControl.ConnectionID = m_CSDescr.Connection.ConnectionID;
				CopyControl.LoadMetaData += new EventHandler(ValueCopyControl_LoadMetaData);
				CopyControl.GetOlapDataLoader += new EventHandler<GetIDataLoaderArgs>(CopyControl_GetMetadataLoader);
				CopyControl.LogManager = this.LogManager;
				CopyControl.Initialize(slice, cell.Value);
				dlg.Content = CopyControl;

				ShowDialog(dlg);
			}
		}
		protected virtual void ShowValueDeliveryDialog(CellInfo cell)
		{
			if (m_CSDescr != null && cell != null && cell.IsUpdateable)
			{
				// Если в кэше есть изменения, то нужно спросить об их сохранении
				if (UseChangesCashe && PivotGrid.LocalChanges.Count > 0)
				{
					MessageBox.Show(Localization.PivotGrid_SaveCachedChanges, Localization.MessageBox_Warning, MessageBoxButton.OK);
					return;
				}

				ModalDialog dlg = new ModalDialog();
				dlg.MinHeight = 300;
				dlg.MinWidth = 400;
				dlg.Height = 500;
				dlg.Width = 600;
				dlg.Caption = Localization.ValueDeliveryDialog_Caption;
				dlg.DialogOk += new EventHandler<DialogResultArgs>(ValueDeliveryDialog_OkButtonClick);

				ValueDeliveryControl DeliveryControl = new ValueDeliveryControl();
				DeliveryControl.CubeName = m_CSDescr.CubeName;
				DeliveryControl.ConnectionID = m_CSDescr.Connection.ConnectionID;
				DeliveryControl.LoadMembers += new EventHandler<QueryEventArgs>(DeliveryControl_LoadMembers);
				DeliveryControl.Initialize(cell);
				dlg.Content = DeliveryControl;

				ShowDialog(dlg);
			}
		}
        /// <summary>
        /// Формирует список ячеек, попдающих в область, на углах которой указанные ячейки
        /// </summary>
        /// <param name="cell1"></param>
        /// <param name="cell2"></param>
        /// <returns></returns>
        private IList<CellInfo> ProcessCellsArea(CellInfo cell1, CellInfo cell2)
        {
            IList<CellInfo> selectionArea = new List<CellInfo>();

            if (cell1 != null && cell2 != null)
            {
                int beginColumnIndex = Math.Min(cell1.ColumnMember.Sorted_MemberIndexInAxis, cell2.ColumnMember.Sorted_MemberIndexInAxis);
                int endColumnIndex = Math.Max(cell1.ColumnMember.Sorted_MemberIndexInAxis, cell2.ColumnMember.Sorted_MemberIndexInAxis);
                int beginRowIndex = Math.Min(cell1.RowMember.Sorted_MemberIndexInAxis, cell2.RowMember.Sorted_MemberIndexInAxis);
                int endRowIndex = Math.Max(cell1.RowMember.Sorted_MemberIndexInAxis, cell2.RowMember.Sorted_MemberIndexInAxis);

                //beginRowIndex и endRowIndex могут быть равны -1 (когда только одна ось в запросе)
                if (beginColumnIndex >= 0 &&
                    endColumnIndex >= 0 &&
                    ((beginRowIndex >= 0 && endRowIndex >= 0) || (beginRowIndex == -1 && endRowIndex >= -1)))
                {
                    for (int columnIndex = beginColumnIndex; columnIndex <= endColumnIndex; columnIndex++)
                    {
                        for (int rowIndex = beginRowIndex; rowIndex <= endRowIndex; rowIndex++)
                        {

                            CellInfo cell_Info = m_LayoutProvider.PivotProvider.Provider.GetCellInfo(m_LayoutProvider.PivotProvider.Provider.GetAxisCoord(0, columnIndex), 
                                m_LayoutProvider.PivotProvider.Provider.GetAxisCoord(1, rowIndex));
                            if (cell_Info != null)
                            {
                                if (m_CellControls_Dict.ContainsKey(cell_Info))
                                {
                                    CellControl cell_Control = m_CellControls_Dict[cell_Info];
                                    if (cell_Control != null)
                                    {
                                        cell_Control.IsSelected = true;
                                    }
                                }
                                selectionArea.Add(cell_Info);
                            }
                        }
                    }
                }
            }

            if (selectionArea.Count == 0)
            {
                if (cell1 != null)
                    selectionArea.Add(cell1);
                if (cell2 != null)
                    selectionArea.Add(cell2);
            }

            return selectionArea;
        }
        void ShowDrillthroughResult(CellInfo cell, DataTableWrapper tableWrapper)
        {
            if (tableWrapper != null)
            {
                if (m_DrillthroughDialog == null)
                {
                    m_DrillthroughDialog = new ModalDialog() { Width = 600, Height = 500, DialogStyle = ModalDialogStyles.OK };
                    m_DrillthroughDialog.Caption = Localization.DrillthroughDialog_Caption;
                    m_DrillthroughDialog.DialogClosed += new EventHandler<DialogResultArgs>(Dlg_DialogClosed);
                }
                //RanetDataGrid grid = new RanetDataGrid();
                //grid.Initialize(tableWrapper);

                DrillThroughControl grid = new DrillThroughControl();
                grid.Initialize(cell, tableWrapper);
                m_DrillthroughDialog.Content = grid;
                Panel panel = GetRootPanel(this);
                if (panel != null && !panel.Children.Contains(m_DrillthroughDialog.Dialog.PopUpControl))
                {
                    panel.Children.Add(m_DrillthroughDialog.Dialog.PopUpControl);
                }
                // На время убираем контекстное меню сводной таблицы
                PivotGrid.UseContextMenu = false;
                m_DrillthroughDialog.Show();
            }
        }
 CellControl GetCellControl(CellInfo view)
 {
     if (view != null)
     {
         if (m_CellControls_Dict.ContainsKey(view))
             return m_CellControls_Dict[view];
     }
     return null;
 }
        /// <summary>
        /// Проверяет возможность выполнения для указанной ячейки дрилл-операций по указанной оси
        /// </summary>
        /// <param name="cell"></param>
        /// <param name="axis"></param>
        /// <returns></returns>
        bool TestCellToInteractive(CellInfo cell, int axis, MemberActionType action)
        {
            MemberInfo member = null;
            if(cell != null && (axis ==0 || axis == 1))
            {
                if(axis == 0)
                {
                    if (Columns_IsInteractive)
                    {
                        member = cell.ColumnMember;
                    }
                }

                if (axis == 1)
                {
                    if (Rows_IsInteractive)
                    {
                        member = cell.RowMember;
                    }
                }

                if (member != null)
                {
                    if ((action == MemberActionType.Expand && member.DrilledDown == false) ||
                        (action == MemberActionType.Collapse && member.DrilledDown == true))
                    {
                        // "+/-"-операции имеют смысл только для элемента, у которого есть дочерние
                        if (member.ChildCount > 0)
                            return true;
                    }
                    if (action == MemberActionType.DrillDown)
                        return true;
                }
            }
            return false;
        }
        public String BuildDrillThrough(CellInfo cell)
        {
            String result = String.Empty;
            if (cell != null)
            {
                //var tuple = new Dictionary<String, MemberInfo>();
                //if (cell.ColumnMember != null && cell.ColumnMember != MemberInfo.Empty)
                //{
                //    cell.ColumnMember.CollectAncestors(tuple);
                //}
                //if (cell.RowMember != null && cell.RowMember != MemberInfo.Empty)
                //{
                //    cell.RowMember.CollectAncestors(tuple);
                //}
                
                //var statement = GetMoveAxesStatement(RefreshQuery());
                var statement = this.CreateWrappedStatement();
                var tuple = cell.GetTuple();
                if (statement != null && tuple != null && tuple.Count > 0)
                {
                    statement.Axes.Clear();
                    List<MdxExpression> members = new List<MdxExpression>();
                    foreach(var member in tuple.Values)
                    {
                        var expr = new MdxObjectReferenceExpression(member.UniqueName, member.Caption);
                        members.Add(expr);
                    }

                    statement.Axes.Add(new MdxAxis("0", new MdxTupleExpression(members)));

                    using (MdxDomProvider provider = MdxDomProvider.CreateProvider())
                    {
                        StringBuilder sb = new StringBuilder();
                        provider.GenerateMdxFromDom(statement, sb, new MdxGeneratorOptions());
                        result = sb.ToString();
                    }

                    if (!String.IsNullOrEmpty(result))
                        result = String.Format("DRILLTHROUGH {0}", result);
                }
            }
            return result;
        }
        public void Initialize(CellInfo cell)
        {
            m_Cell = cell;

            List<TupleItem> list = new List<TupleItem>();
            if (m_Cell != null)
            {
                IDictionary<String, MemberInfo> tuple = m_Cell.GetTuple();
                foreach (MemberInfo member in tuple.Values)
                {
                    list.Add(new TupleItem(member));
                }
            }
            m_Grid.ItemsSource = list;
            if (list.Count > 0)
                m_Grid.SelectedIndex = 0;
            else
                m_Grid.SelectedIndex = -1;
        }
 public UpdateEntry(CellInfo cell, String newValue)
     : this(cell)
 {
     this.NewValue = newValue;
 }
        public void Initialize(CellInfo cell)
        {
            m_Cell = cell;

            InitDeliveredValues();
            m_Tupple.Initialize(m_Cell);
        }
        public void Initialize(CellInfo cell)
        {
            m_Cell = cell;

            List<PropertyItem> properties_list = new List<PropertyItem>();
            List<PropertyItem> tuple_list = new List<PropertyItem>();

            if (cell != null)
            {
                if (cell.CellDescr != null && cell.CellDescr.Value != null)
                {
                    foreach (PropertyData pair in cell.CellDescr.Value.Properties)
                    {
                        PropertyItem item = new PropertyItem();
                        item.Property = pair.Name;
                        if (pair.Value != null)
                        {
                            item.Value = pair.Value.ToString();
                        }
                        else
                        {
                            item.Value = String.Empty;
                        }
                        properties_list.Add(item);
                    }
                }
            }

            PropertiesCtrl.Initialize(properties_list);
            TupleCtrl.Initialize(cell);
        }
 void OnCellControlMouseDown(CellControl cell)
 {
     // Если нажат Shift и ячейка ч фокусом уже есть, то нужно изменить выбранную область,
     // Ячейка с фокусом при этои не меняется
     if (((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift) && FocusedCellView != null)
     {
         SelectionManager.ChangeSelectionArea(ProcessCellsArea(FocusedCellView, cell.Cell));
         m_PrevAreaBorderCell = cell.Cell;
     }
     else
     {
         FocusedCellView = cell.Cell;
     }
 }
		void DrillThroughCell(CellInfo cell)
		{
			if (DataManager != null)
			{
				String query = DataManager.BuildDrillThrough(cell);
				if (!String.IsNullOrEmpty(query))
				{
					MdxQueryArgs query_args = CommandHelper.CreateMdxQueryArgs(Connection, query);
					query_args.Type = QueryTypes.DrillThrough;
					LogManager.LogInformation(this, this.Name + " - DrillThrough cell");
					IsWaiting = true;
					OlapDataLoader.LoadData(query_args, new UserSchemaWrapper<String, CellInfo>("DRILLTHROUGH_CELL", cell));
				}
			}
		}
 public void ChangeCell(CellInfo cell, UpdateEntry entry)
 {
     if (cell != null)
     {
         if (m_CellControls_Dict.ContainsKey(cell))
         {
             CellControl cell_control = m_CellControls_Dict[cell];
             if (cell_control != null)
             {
                 cell_control.NotRecalculatedChange = entry;
             }
         }
     }
 }
		void PasteCellsFromClipboard(CellInfo cell)
		{
			// На всякий случай проверим
			if (!PivotGrid.CanEdit || !PivotGrid.EditMode)
				return;

			String text = Clipboard.GetClipboardText();
			if (!String.IsNullOrEmpty(text))
			{
				// В буфере ячейки хранятся разделенные табуляцией и переходом на новую строку. 
				//  Например ячейки (* - пустая):
				//  3   *   *   *
				//  *   *   *   *
				//  5   *   6   *
				//  *   *   *   *
				// В буфере при копировании из Excel это выглядит так: "3\t\t\t\r\n\r\n5\t\t6"

				// Буфер, в который накапливаются значения из Clipboard
				List<List<String>> buff = new List<List<string>>();

				// Разделим содержимое буфера на строки
				text = text.Trim();
				String[] rows_list = text.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
				if (rows_list != null)
				{
					// Разделим содержимое каждой строки
					foreach (String str in rows_list)
					{
						List<String> row_Buff = new List<string>();
						String[] columns_list = str.Split(new string[] { "\t" }, StringSplitOptions.None);
						if (columns_list != null)
						{
							foreach (String val in columns_list)
							{
								row_Buff.Add(val);
							}
						}

						buff.Add(row_Buff);
					}
				}
				// Буфер с целью оптимизации не содержит пустые ячейки, если они вляются последними в строке.
				// Поэтому чтобы найти реальный размер копируемой области по ширине нужно взять максимальную длину из имеющихся
				int width = 0;
				foreach (List<String> row in buff)
				{
					width = Math.Max(width, row.Count);
				}

				// Обходим буфер и меняем значения ячеек
				int row_index = 0;
				List<UpdateEntry> changes = new List<UpdateEntry>();
				int start_ColumnIndex = 0;
				int start_RowIndex = 0;
				if (cell != null)
				{
					start_ColumnIndex = cell.CellDescr.Axis0_Coord;
					start_RowIndex = cell.CellDescr.Axis1_Coord;
				}
				foreach (List<String> row in buff)
				{
					for (int col_index = 0; col_index < width; col_index++)
					{
						String val = String.Empty;
						if (col_index < row.Count)
							val = row[col_index];

						// Пытаемся по координате получить ячейку
						CellInfo destination_cell = m_CellSetProvider.GetCellInfo(start_ColumnIndex + col_index, start_RowIndex + row_index);
						//FAST CellControl destination_cell = PivotPanelControl.CellsControl.GetCell(start_ColumnIndex + col_index, start_RowIndex + row_index);
						if (destination_cell != null && destination_cell.IsUpdateable)
						{
							if (String.IsNullOrEmpty(val))
							{
								// КC:
								// записывать НОЛЬ только в том случае если у нас было какое-то число, если числа не было (в ячейке было null) то оставлять null
								if (destination_cell.Value != null || PivotGrid.LocalChanges.FindChange(destination_cell) != null)
								{
									UpdateEntry entry = new UpdateEntry(destination_cell, "0");
									PivotGrid.ChangeCell(destination_cell, entry);
									changes.Add(entry);
									continue;
								}
							}
							else
							{
								try
								{
									// Пытаемся преобразовать строку в число
									double new_val = 0;
									new_val = Convert.ToDouble(val);

									if (destination_cell.Value != null)
									{
										double x = 0;
										x = Convert.ToDouble(destination_cell.Value.ToString());
										if (x == new_val)
											continue;
									}

									UpdateEntry entry = new UpdateEntry(destination_cell, new_val.ToString());
									PivotGrid.ChangeCell(destination_cell, entry);
									changes.Add(entry);
								}
								catch { }
							}
						}
					}
					row_index++;
				}

				if (changes.Count > 0)
					PerformCellChanges(changes);
			}
		}
 void Raise_PerformControlAction(ControlActionType action, CellInfo cell)
 {
     EventHandler<ControlActionEventArgs<CellInfo>> handler = Cells_PerformControlAction;
     if (handler != null)
     {
         handler(this, new ControlActionEventArgs<CellInfo>(action, cell));
     }
 }
		void CopyCellsToClipboard(CellInfo current)
		{
			IList<CellInfo> cells = PivotGrid.Selection;
			if (cells != null && cells.Count > 0)
			{
				// Ячейки для опреации копирования должны быть в прямоугольной области. Причем область должна быть без пустот
				// Для начала определим максимальные и минимальные индексы используемых строк и столбцов
				int min_row = -1;
				int max_row = -1;
				int min_col = -1;
				int max_col = -1;

				foreach (CellInfo cell in cells)
				{
					// Индексы для строки
					if (min_row == -1)
					{
						min_row = cell.CellDescr.Axis1_Coord;
					}
					else
					{
						min_row = Math.Min(min_row, cell.CellDescr.Axis1_Coord);
					}

					if (max_row == -1)
					{
						max_row = cell.CellDescr.Axis1_Coord;
					}
					else
					{
						max_row = Math.Max(max_row, cell.CellDescr.Axis1_Coord);
					}

					// Индексы для колонки
					if (min_col == -1)
					{
						min_col = cell.CellDescr.Axis0_Coord;
					}
					else
					{
						min_col = Math.Min(min_col, cell.CellDescr.Axis0_Coord);
					}
					if (max_col == -1)
					{
						max_col = cell.CellDescr.Axis0_Coord;
					}
					else
					{
						max_col = Math.Max(max_col, cell.CellDescr.Axis0_Coord);
					}
				}

				if (min_col > -1 && max_col > -1 && max_col >= min_col &&
						max_row >= min_row &&
						min_row >= -1 && max_row >= -1) // min_row и max_row могут быть равны -1 для случая когда в запросе только одна ось
				{
					// Теперь определяем массив (двумерный) с размерностью, которую мы определили
					// И пытаемся заполнить массив тем что есть. Если потом останутся в нем дырки (null) то область получается незамкнутая
					// Учитываем запросы с одной осью. Кол-во строк и столбцов не может быть меньше 1.
					int col_count = Math.Max(max_col - min_col + 1, 1);
					int row_count = Math.Max(max_row - min_row + 1, 1);

					List<List<String>> list = new List<List<string>>();
					for (int row_index = 0; row_index < row_count; row_index++)
					{
						List<String> row = new List<string>();
						for (int col_index = 0; col_index < col_count; col_index++)
						{
							// Зануляем все значения
							row.Add("_NULL_");
						}
						list.Add(row);
					}

					// Разбрасываем значения ячеек на свои места
					foreach (CellInfo cell in cells)
					{
						// Учитываем запросы с одной осью. Индекс не может быть отрицательным
						int row_indx = Math.Max(cell.CellDescr.Axis1_Coord - min_row, 0);
						int col_indx = Math.Max(cell.CellDescr.Axis0_Coord - min_col, 0);
						if (row_indx >= 0 && row_indx < row_count &&
								col_indx >= 0 && col_indx < col_count)
						{
							UpdateEntry change = PivotGrid.LocalChanges.FindChange(cell);
							if (change != null)
							{
								list[row_indx][col_indx] = change.NewValue;
							}
							else
							{
								if (cell.Value != null)
									list[row_indx][col_indx] = cell.Value.ToString();
								else
									list[row_indx][col_indx] = null;
							}
						}
					}

					bool has_dyrki = false;
					// Определяем есть ли дырки
					foreach (List<String> rows_list in list)
					{
						foreach (String str in rows_list)
						{
							if (str == "_NULL_")
							{
								has_dyrki = true;
								break;
							}
						}
					}

					// Если есть дырки - значит копировать не судьба
					if (has_dyrki)
					{
						MessageBox.Show(Localization.PivotGrid_CellsCopyAreaError, Localization.MessageBox_Warning, MessageBoxButton.OK);
						return;
					}

					StringBuilder sb = new StringBuilder();
					// Формируем результат. Значения размеляются \t 
					// Строки разделяются \r\n
					// Определяем есть ли дырки
					foreach (List<String> rows_list in list)
					{
						int i = 0;
						foreach (String str in rows_list)
						{
							if (i != 0)
								sb.Append("\t");
							sb.Append(str);
							i++;
						}
						sb.Append(Environment.NewLine);
					}

					Clipboard.SetClipboardText(sb.ToString());
				}
			}
		}