2012-05-09 86 views
12

Tengo un DataGridView en una aplicación .Net (V4 C# VS2010) & quiero copiar todos los datos en el portapapeles con el clic de un botón. No hay problema -DataGridView: copia completa en el portapapeles

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

problema es que el usuario ya puede tener algunas células, etc filas seleccionadas en la cuadrícula de datos & realmente no quieren cambiar esa selección. Lo anterior obviamente selecciona todo. Podría dataGridView1.ClearSelection(); al final, que es marginalmente mejor, pero aún no logra lo que se requiere.

puedo guardar las celdas seleccionadas:

var mySelectedCells = dataGridView1.SelectedCells; 

pero ¿cómo puedo obtener esas células seleccionadas vuelve a seleccionar en la cuadrícula de datos después de la copia? ¿Hay alguna manera fácil de recuperar la colección de celdas seleccionadas en DataGrid? ¿Quizás haya una mejor manera de copiar toda la cuadrícula al portapapeles sin afectar las celdas actualmente seleccionadas?

Respuesta

10

supongo que si sólo quería para representar el contenido de las celdas como texto y copiarlos al portapapeles, delimitado por tabuladores, que podría hacer algo como:

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); 

La salida parece bastante similar a la del GetClipboardContent(), pero tenga cuidado con cualquier DataGridViewImage Columns o cualquier tipo que no sea implícitamente una cadena.

Editar: Anthony es correcto, use StringBuilder para evitar asignar una nueva cadena para cada concatenación. El nuevo código:

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

Gracias. Esto es lo que hice al final. Tuve que agregar otra instrucción if 'if (row.Cells [i] .Visible)' porque un par de columnas eran invisibles y esta solución copia todas las celdas, visibles o no - ('dataGridView1.GetClipboardContent();' copies only cosas visibles). No estoy seguro de cómo se manejaría DataGridViewImageCell, pero eso no es una preocupación para mi aplicación en particular. – Nigel

+0

No hay problema Nigel, me alegro de ayudar. Cuando mencioné DataGridViewImageCell, solo quería decir que no estoy seguro de cómo se comportaría el código si estuviera usando algo más que DataGridViewTextBoxCell, pero creo que ese tipo es el predeterminado si no especifica lo contrario. Pero si está usando todas las celdas TextBox, no debería ser un problema. Aclamaciones. –

+0

Solo quiero mencionar que si 'DataGridView' es grande, probablemente quiera usar' StringBuilder' y no solo usar la concatenación de cadenas. – Anthony

0

Creo que a continuación el método hará exactamente lo que quiera. Simplemente llame a este método con el nombre de DataGridView en el evento de clic de botón.

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

Aquí hay una versión del código VB en C# con opciones para copiar encabezados y copiar únicamente las filas seleccionadas.

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; 
     } 
    } 
Cuestiones relacionadas