2012-05-09 61 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; 
     } 
    }