winforms 数据网格视图:复制完成到剪贴板

goucqfw6  于 2022-12-30  发布在  其他
关注(0)|答案(6)|浏览(256)

我在一个.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;

但是,如何在复制后在数据网格上重新选择这些选定的单元格?是否有一种简单的方法可以将选定的单元格集合放回数据网格中?也许有一种更好的方法可以首先将整个网格复制到剪贴板中,而不影响当前选定的单元格?

qjp7pelc

qjp7pelc1#

我想,如果您只想将单元格的内容表示为文本,并将其复制到剪贴板中,以制表符分隔,您可以执行以下操作:

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

svujldwt2#

下面是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;
        }
    }
a8jjtwal

a8jjtwal3#

您应该更改DataGridView的多选属性。以下是代码:

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

yizd12fk4#

您可能需要包含列标题:

private void copyAllToClipboard()
    {
        var newline = System.Environment.NewLine;
        var tab = "\t";
        var clipboard_string = new StringBuilder();
        int i;

        for (i = 0; i < this.Columns.Count - 1; i++)
        {
            clipboard_string.Append(this.Columns[i].Name);
            clipboard_string.Append(tab);
        }
        clipboard_string.Append(this.Columns[i].Name);
        clipboard_string.Append(newline);

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

        Clipboard.SetText(clipboard_string.ToString());
    }
jei2mxaa

jei2mxaa5#

我认为下面的方法将完全做你想要的。只要调用这个方法与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
pexxcrt2

pexxcrt26#

DataGridView列可以是可见的/不可见的,也可以按照与创建时不同的顺序显示。此代码负责以下两个方面:

public static void CopyGridViewToClipboard(DataGridView gvCopy)
    {
        if (gvCopy == null) return;
        StringBuilder s = new StringBuilder();

        int offset = gvCopy.ColumnHeadersVisible ? 1 : 0;
        int visibleColumnsCount = 0;

        //count visible columns and build mapping between each column and it's display position
        Dictionary<int, int> indexMapping = new Dictionary<int, int>();
        int currIndex = 0;
        int lastFoundMinDisplayIndex = -1;
        for (int j = 0; j < gvCopy.ColumnCount; j++)
        {
            //find min DisplayIndex >= currIndex where column is visible
            int minDisplayIndex = 100000;
            int minDisplayIndexColumn = 100000;
            for (int k = 0; k < gvCopy.ColumnCount; k++)
            {
                if ((gvCopy.Columns[k].Visible) && (gvCopy.Columns[k].DisplayIndex >= currIndex) && (gvCopy.Columns[k].DisplayIndex > lastFoundMinDisplayIndex))
                {
                    if (gvCopy.Columns[k].DisplayIndex < minDisplayIndex)
                    {
                        minDisplayIndex = gvCopy.Columns[k].DisplayIndex;
                        minDisplayIndexColumn = k;
                    }
                }
            }

            if (minDisplayIndex == 100000) break;

            indexMapping.Add(minDisplayIndexColumn, currIndex);

            lastFoundMinDisplayIndex = minDisplayIndex;
            currIndex++;
        }
        visibleColumnsCount = currIndex;

        //put data in temp array -- required to position columns in display order
        string[,] data = new string[gvCopy.RowCount + offset, visibleColumnsCount];

        if (gvCopy.ColumnHeadersVisible)
        {
            for (int j = 0; j < gvCopy.ColumnCount; j++)
            {
                if (gvCopy.Columns[j].Visible)
                {
                    data[0, indexMapping[j]] = gvCopy.Columns[j].HeaderText;
                }
            }
        }

        for (int i = 0; i < gvCopy.RowCount; i++)
        {
            for (int j = 0; j < gvCopy.ColumnCount; j++)
            {
                if (gvCopy.Columns[j].Visible)
                {
                    data[i + offset, indexMapping[j]] = gvCopy[j, i].FormattedValue.ToString();
                }
            }
        }

        //copy data
        for (int i = 0; i < gvCopy.RowCount + offset; i++)
        {
            for (int j = 0; j < visibleColumnsCount; j++)
            {
                s.Append(data[i, j]);

                s.Append("\t");
            }
            s.Append("\r\n");
        }
        Clipboard.SetDataObject(s.ToString());
    }

相关问题