2012-05-09 57 views
12

我在.Net应用程序(V4 C#VS2010)中有一个DataGridView &想要复制所有数据到剪贴板上点击一个按钮。没问题 -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或任何非隐式字符串的类型。

编辑:安东尼是正确的,使用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

以下是C#中VB代码的一个版本,其中包含复制标题和仅复制选定行的选项。

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