如何优化DataGridView单元格值粘贴到Excel电子表格的运行速度
DataGridView导出到Excel提速优化方案
核心问题原因
原代码逐单元格写入Excel属于跨COM接口调用,每次赋值都会触发一次进程间通信,行数越多性能损耗越明显。
优化方案1:二维数组批量写入(性能提升最显著)
先把所有符合条件的行读取到内存数组中,最后一次性写入Excel对应区域,避免频繁跨进程调用。
' 第一步:先筛选所有符合条件的行,统计数量 Dim targetRows As New List(Of Object()) For i = 0 To PartsDataGridView.RowCount - 1 If PartsDataGridView.Rows(i).Cells(0).Value?.ToString() = "Positive" Then ' 提取当前行第1到12列的值存入数组 Dim rowData(11) As Object ' 索引0对应A列,11对应L列 For col = 1 To 12 rowData(col - 1) = PartsDataGridView.Rows(i).Cells(col).Value Next targetRows.Add(rowData) End If Next ' 第二步:如果有符合条件的数据,一次性写入Excel If targetRows.Count > 0 Then ' 获取Excel起始行 Dim startRow As Integer = WS.Range("A" & WS.Rows.Count).End(Excel.XlDirection.xlUp).Row + 1 ' 对应写入区域:行数是targetRows.Count,列数是12列(A到L) Dim writeRange = WS.Range("A" & startRow, "L" & (startRow + targetRows.Count - 1)) ' 把List转二维数组赋值给区域 Dim dataArray(targetRows.Count - 1, 11) As Object For rowIdx = 0 To targetRows.Count - 1 For colIdx = 0 To 11 dataArray(rowIdx, colIdx) = targetRows(rowIdx)(colIdx) Next Next writeRange.Value = dataArray End If
优化方案2:临时关闭Excel冗余特性(可搭配方案1使用,进一步提速)
写入前关闭Excel的屏幕更新、自动计算、事件触发,写入完成后恢复,避免写入过程中Excel的额外计算开销:
' 写入前关闭 Dim originalCalcMode = Excel.Application.Calculation Excel.Application.Calculation = Excel.XlCalculation.xlCalculationManual Excel.Application.ScreenUpdating = False Excel.Application.EnableEvents = False ' 这里放写入逻辑(方案1的代码) ' 写入完成后恢复 Excel.Application.Calculation = originalCalcMode Excel.Application.ScreenUpdating = True Excel.Application.EnableEvents = True
优化方案3:剪贴板快速粘贴(适合简单场景,代码最简)
如果不需要额外处理数据格式,直接把符合条件的行选中后复制到剪贴板,直接在Excel粘贴即可:
' 先选中所有符合条件的行 PartsDataGridView.ClearSelection() For i = 0 To PartsDataGridView.RowCount - 1 If PartsDataGridView.Rows(i).Cells(0).Value?.ToString() = "Positive" Then PartsDataGridView.Rows(i).Selected = True End If Next ' 复制选中行到剪贴板(包含表头可自行调整CopyColumnHeaders属性) PartsDataGridView.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithoutHeaderText Clipboard.SetDataObject(PartsDataGridView.GetClipboardContent()) ' Excel直接粘贴 Dim pasteRow As Integer = WS.Range("A" & WS.Rows.Count).End(Excel.XlDirection.xlUp).Row + 1 WS.Range("A" & pasteRow).PasteSpecial() Clipboard.Clear()
内容的提问来源于stack exchange,提问作者Patrick
相关产品推荐
相关产品推荐

