2012-05-09 13 views
12

У меня есть DataGridView в приложении .Net (V4 C# VS2010) & хочу скопировать все данные в буфер обмена одним нажатием кнопки. Нет проблем -DataGridView: Копировать в буфер обмена

private void copyToClipboard() 
{ 
    dataGridView1.SelectAll(); 
    DataObject dataObj = dataGridView1.GetClipboardContent(); 
    if (dataObj != null) 
     Clipboard.SetDataObject(dataObj); 
} 

Проблема не в том, что пользователь, возможно, уже есть несколько ячеек, строк и т.д., выбранные на DataGrid & Я не хочу, чтобы изменить этот выбор. Вышеизложенное явно выбирает все. Я мог бы dataGridView1.ClearSelection(); в конце, который немного лучше, но все еще не достигает того, что требуется.

можно сохранить выбранные ячейки:

var mySelectedCells = dataGridView1.SelectedCells; 

, но как я могу получить эти выбранные ячейки перевыбранных на DataGrid после копирования? Есть ли простой способ вернуть выбранную коллекцию ячеек в DataGrid? Возможно, есть лучший способ получить всю сетку, скопированную в буфер обмена, в первую очередь, не затрагивая выбранные ячейки?

ответ

10

Я полагаю, что если вы просто хотели, чтобы представить содержимое ячеек в виде текста и скопировать их в буфер обмена, с разделителями табуляции, вы могли бы сделать что-то вроде:

var newline = System.Environment.NewLine; 
    var tab = "\t"; 
    var clipboard_string = ""; 

    foreach (DataGridViewRow row in dataGridView1.Rows) 
    { 
     for (int i=0; i < row.Cells.Count; i++) 
     { 
       if(i == (row.Cells.Count - 1)) 
        clipboard_string += row.Cells[i].Value + newline; 
       else 
        clipboard_string += row.Cells[i].Value + tab; 
     } 
    } 

    Clipboard.SetText(clipboard_string); 

Выходной кажется довольно похож на GetClipboardContent(), но будьте внимательны к любым элементам DataGridViewImageColumns или любому типу, который не является неявно строкой.

Редактировать: Anthony правильно, используйте StringBuilder, чтобы не выделять новую строку для каждой конкатенации. Новый код:

var newline = System.Environment.NewLine; 
    var tab = "\t"; 
    var clipboard_string = new StringBuilder(); 

    foreach (DataGridViewRow row in dataGridView1.Rows) 
    { 
     for (int i = 0; i < row.Cells.Count; i++) 
     { 
      if (i == (row.Cells.Count - 1)) 
       clipboard_string.Append(row.Cells[i].Value + newline); 
      else 
       clipboard_string.Append(row.Cells[i].Value + tab); 
     } 
    } 

    Clipboard.SetText(clipboard_string.ToString()); 
+0

Спасибо. Это то, что я сделал в конце. Мне пришлось добавить еще один оператор if: if (row.Cells [i] .Visible) ', потому что пара столбцов была невидима, и это решение копирует все ячейки, видимые или нет - (' dataGridView1.GetClipboardContent(); 'только копии видимые вещи). Не знаете, как будет обрабатываться DataGridViewImageCell, но это не касается моего конкретного приложения. – Nigel

+0

Без проблем Найджел, рад помочь. Когда я упоминал DataGridViewImageCell, я просто имел в виду, что не знаю, как будет вести себя код, если вы используете что-либо, кроме DataGridViewTextBoxCell, но я считаю, что этот тип является значением по умолчанию, если вы не указали иначе. Но если вы используете все ячейки TextBox, это не должно быть проблемой. Приветствия. –

+0

Просто хочу отметить, что если 'DataGridView' большой, вы, вероятно, захотите использовать' StringBuilder', а не просто использовать конкатенацию строк. – Anthony

0

Я думаю, что ниже метод точно сделает то, что вы хотите. Просто вызовите этот метод с именем DataGridView при событии нажатия кнопки.

Private Sub CopyDataGridViewToClipboard(ByRef dgv As DataGridView) 
    Try 
     Dim s As String = "" 
     Dim oCurrentCol As DataGridViewColumn 'Get header 
     oCurrentCol = dgv.Columns.GetFirstColumn(DataGridViewElementStates.Visible) 
     Do 
      s &= oCurrentCol.HeaderText & Chr(Keys.Tab) 
      oCurrentCol = dgv.Columns.GetNextColumn(oCurrentCol, _ 
       DataGridViewElementStates.Visible, DataGridViewElementStates.None) 
     Loop Until oCurrentCol Is Nothing 
     s = s.Substring(0, s.Length - 1) 
     s &= Environment.NewLine 'Get rows 
     For Each row As DataGridViewRow In dgv.Rows 
      oCurrentCol = dgv.Columns.GetFirstColumn(DataGridViewElementStates.Visible) 
      Do 
       If row.Cells(oCurrentCol.Index).Value IsNot Nothing Then 
        s &= row.Cells(oCurrentCol.Index).Value.ToString 
       End If 
       s &= Chr(Keys.Tab) 
       oCurrentCol = dgv.Columns.GetNextColumn(oCurrentCol, _ 
         DataGridViewElementStates.Visible, DataGridViewElementStates.None) 
      Loop Until oCurrentCol Is Nothing 
      s = s.Substring(0, s.Length - 1) 
      s &= Environment.NewLine 
     Next 'Put to clipboard 
     Dim o As New DataObject 
     o.SetText(s) 
     Clipboard.SetDataObject(o, True) 

    Catch ex As Exception 
     ShowError(ex, Me) 
    End Try 
End Sub 
1

Вот версия кода VB на C# с возможностью копирования заголовков и копирования только выбранных строк.

private void CopyDataGridViewToClipboard(DataGridView dgv, bool includeHeaders = true, bool allRows = false) 
    { 
     // copies the contents of selected/all rows in a data grid view control to clipboard with optional headers 
     try 
     { 
      string s = ""; 
      DataGridViewColumn oCurrentCol = dgv.Columns.GetFirstColumn(DataGridViewElementStates.Visible); 
      if (includeHeaders) 
      {     
       do 
       { 
        s = s + oCurrentCol.HeaderText + "\t"; 
        oCurrentCol = dgv.Columns.GetNextColumn(oCurrentCol, DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
       } 
       while (oCurrentCol != null); 
       s = s.Substring(0, s.Length - 1); 
       s = s + Environment.NewLine; //Get rows 
      } 
      foreach (DataGridViewRow row in dgv.Rows) 
      { 
       oCurrentCol = dgv.Columns.GetFirstColumn(DataGridViewElementStates.Visible); 

       if (row.Selected || allRows) 
       { 
        do 
        { 
         if (row.Cells[oCurrentCol.Index].Value != null) s = s + row.Cells[oCurrentCol.Index].Value.ToString(); 
         s = s + "\t"; 
         oCurrentCol = dgv.Columns.GetNextColumn(oCurrentCol, DataGridViewElementStates.Visible, DataGridViewElementStates.None); 
        } 
        while (oCurrentCol != null); 
        s = s.Substring(0, s.Length - 1); 
        s = s + Environment.NewLine; 
       }          
      } 
      Clipboard.SetText(s); 
     } 
     catch (Exception ex) 
     { 
      toolStripStatusLabel2.Text = @"Error: " + ex.Message; 
     } 
    } 
Смежные вопросы