winforms 数据网格视图到剪贴板优化

voase2hg  于 2023-01-17  发布在  其他
关注(0)|答案(5)|浏览(119)

我不是在问如何将数据网格复制到剪贴板,而是在问如何优化代码。
这是我必须复制我的datagridview到我的剪贴板,这样我就可以粘贴到excel的内容。

Dim dgv As DataGridView = dgvData
    Dim s As String = ""
    Dim oCurrentCol As DataGridViewColumn    'Get header
    oCurrentCol = dgv.Columns.GetFirstColumn(DataGridViewElementStates.Visible)
    oCurrentCol = dgv.Columns.GetNextColumn(oCurrentCol, DataGridViewElementStates.Visible, DataGridViewElementStates.None)

    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)
        oCurrentCol = dgv.Columns.GetNextColumn(oCurrentCol, DataGridViewElementStates.Visible, DataGridViewElementStates.None)
        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)

这工作得很好!做的正是我想让它做的,包括省去第一列,粘贴到Excel中时看起来很完美。
现在我遇到的问题是它非常慢。在我的开发计算机上,复制大约10,000行10列需要将近两分钟。在我们的一些旧服务器上,我让它运行了10分钟以上,最后因为时间太长而终止了进程。
我不知道我能做些什么来加快这个过程。任何帮助都是感激的!
谢谢!

yqkkidmi

yqkkidmi1#

下面是我用来通过剪贴板将数据移动到Excel的代码。

Private Sub tsbtnCopy_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tsbtnCopy.Click
    Try
        If dgv01.Rows.Count = 0 Then Exit Sub
        dgv01.SuspendLayout()
        dgv01.RowHeadersVisible = False
        If dgv01.SelectedRows.Count = 0 Then dgv01.SelectAll()
        Clipboard.SetDataObject(dgv01.GetClipboardContent())
        dgv01.ClearSelection()
    Catch ex As Exception
        MsgBox(ex.Message)
    Finally
        dgv01.RowHeadersVisible = True
        dgv01.ResumeLayout()
    End Try
End Sub
pb3skfrl

pb3skfrl2#

所以,考虑到我的情况,我结束了用StringBuilder交换字符串string。为了复制~10000,我从2分钟到几乎瞬间完成!在阅读了string builder是如何工作的之后,它看起来对我正在做的事情非常有效。我非常惊讶地看到它实际上产生了多大的不同!下面是我做的一些小修改。
即使在我们的旧服务器上,它几乎是即时的,这是巨大的相比,15+分钟,它将采取。

Dim dgv As DataGridView = dgvData
    Dim s As New StringBuilder
    Dim oCurrentCol As DataGridViewColumn = dgv.Columns.GetFirstColumn(DataGridViewElementStates.Visible)   'Get header

    oCurrentCol = dgv.Columns.GetNextColumn(oCurrentCol, DataGridViewElementStates.Visible, DataGridViewElementStates.None)

    Do
        s.Append(oCurrentCol.HeaderText & Chr(Keys.Tab))
        oCurrentCol = dgv.Columns.GetNextColumn(oCurrentCol, DataGridViewElementStates.Visible, DataGridViewElementStates.None)
    Loop Until oCurrentCol Is Nothing

    s.Append(Environment.NewLine)    'Get rows
    For Each row As DataGridViewRow In dgv.Rows
        oCurrentCol = dgv.Columns.GetFirstColumn(DataGridViewElementStates.Visible)
        oCurrentCol = dgv.Columns.GetNextColumn(oCurrentCol, DataGridViewElementStates.Visible, DataGridViewElementStates.None)
        Do
            If row.Cells(oCurrentCol.Index).Value IsNot Nothing Then
                s.Append(row.Cells(oCurrentCol.Index).Value.ToString)
            End If
            s.Append(Chr(Keys.Tab))
            oCurrentCol = dgv.Columns.GetNextColumn(oCurrentCol, DataGridViewElementStates.Visible, DataGridViewElementStates.None)
        Loop Until oCurrentCol Is Nothing
        s.Append(Environment.NewLine)
    Next    'Put to clipboard

    Dim o As New DataObject
    o.SetText(s.ToString())
    Clipboard.SetDataObject(o, True)
e4yzc0pl

e4yzc0pl3#

如果您将在GridView和Excel之间使用那么多行,我将永远不会使用剪贴板(您可能会在某个时候遇到障碍,内存方面的问题)。
相反,我将创建一个CSV并直接在Excel中打开它。您甚至可以使用ShellExecute自动打开它。
还有其他几个类似的问题,如:
[C#]字符串

[VB.NET]虚拟仪器技术

ltqd579y

ltqd579y4#

这里不需要循环,如果您将对象数据转到剪贴板,它将足够快...对于您的目的,您可以选择所有DGV控制数据,然后将所选对象数据一次性传输到剪贴板,或者,您可以只传输所选项目。但首先在DGV属性中将DGV的ClipboardCopyMode设置为EnableAlwaysIncludeHeaderText,以便接收器识别不同的列。然后,在控件按钮单击事件中实现以下代码,其中dgv_Curves是数据网格视图控件:

Dim sel as Boolean = False
        
My.Computer.Clipboard.Clear()
        
If dgv_Curves.GetCellCount(DataGridViewElementStates.Selected) = 0 Then
    dgv_Curves.SelectAll()
    sel = True
End If

Clipboard.SetDataObject(dgv_Curves.GetClipboardContent())

If sel Then
    dgv.Curves.ClearSelection()
End If

如果在传输按钮点击事件中没有选择任何项目,则会执行所有网格元素的自动选择,并将相应的数据传输到带有列标题的剪贴板中。现在,您可以根据需要使用excel电子表格或panda数据框阅读它...
块传输更快,在您的情况下,如果DGV控件可见,循环传输将在执行循环以收集数据时不断更新一个又一个选择,这些数据已由对象收集并可通过其方法检索。

nfzehxib

nfzehxib5#

1.优化的第一步是只显示需要的数据,也就是说只使用需要的列来执行SELECT查询。
1.不需要复制第一列。
1.使用方法DO和FOR循环本质上是慢的。
1.简单地说:

dgv01.RowHeadersVisible = False
    dgv01.SelectAll()
    Clipboard.SetDataObject(dgv01.GetClipboardContent())
    dgv001.ClearSelection()

相关问题