Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在没有“内存不足”异常的情况下将大型DataGridView导出到Excel?_Excel_Vb.net_Winforms - Fatal编程技术网

如何在没有“内存不足”异常的情况下将大型DataGridView导出到Excel?

如何在没有“内存不足”异常的情况下将大型DataGridView导出到Excel?,excel,vb.net,winforms,Excel,Vb.net,Winforms,我的问题是,我需要从MySQL数据库填充的DataGridView中将90.000+行/143列导出到Excel。无论我做什么,我总是在45k-60k行之后出现“System.Out.Of.Memory”异常,具体取决于解决方案。我知道可能会有像“为什么你需要这么多行”这样的问题,我会回答“不幸的是,这是需要的。”我已经搜索了关于我的问题的论坛,但没有找到任何有效的解决方案。我尝试将StreamWriter转换为CSV,使用下面的解决方案将数据分块处理,也使用多个Excel或CSV文件,但没有任

我的问题是,我需要从MySQL数据库填充的DataGridView中将90.000+行/143列导出到Excel。无论我做什么,我总是在45k-60k行之后出现“System.Out.Of.Memory”异常,具体取决于解决方案。我知道可能会有像“为什么你需要这么多行”这样的问题,我会回答“不幸的是,这是需要的。”我已经搜索了关于我的问题的论坛,但没有找到任何有效的解决方案。我尝试将StreamWriter转换为CSV,使用下面的解决方案将数据分块处理,也使用多个Excel或CSV文件,但没有任何帮助。每次在执行期间,当我尝试使用较少的行数时,RAM的使用量都在增长,并且在成功导出后不会释放。我不知道成功执行后RAM何时释放,是否释放

测试机器有8 GB的RAM,并且使用Windows 10。不幸的是,我无法使用MySQL服务器的资源处理那里的Excel导出,然后输出文件与用户共享,所以我需要使用客户端机器

下面是我最新的不工作解决方案,其中数据从DGV中读取,并分块写入Excel。改变块的大小并不能减少内存消耗,如果我把它缩小到500到2000,唯一的效果就是导出速度变慢了

Imports Excel = Microsoft.Office.Interop.Excel

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click

        If DataGridView1.Rows.Count > 0 Then
            Dim filename As String = ""
            Dim SV As SaveFileDialog = New SaveFileDialog()
            SV.FileName = "Worst_cells"

            SV.Filter = "xlsx files (*.xlsx)|*.xlsx|All files (*.*)|*.*"
            SV.FilterIndex = 1
            SV.RestoreDirectory = True

            Dim result As DialogResult = SV.ShowDialog()

            If result = DialogResult.OK Then

                filename = SV.FileName

                Dim XCELAPP As Microsoft.Office.Interop.Excel.Application = Nothing
                Dim XWORKBOOK As Microsoft.Office.Interop.Excel.Workbook = Nothing
                Dim XSHEET As Microsoft.Office.Interop.Excel.Worksheet = Nothing
                Dim misValue As Object = System.Reflection.Missing.Value
                XCELAPP = New Excel.Application()
                XWORKBOOK = XCELAPP.Workbooks.Add(misValue)
                XCELAPP.DisplayAlerts = False
                XCELAPP.Visible = False
                XSHEET = XWORKBOOK.ActiveSheet

                XSHEET.Range("B1").ColumnWidth = 11

                For Each column As DataGridViewColumn In DataGridView1.Columns
                    XSHEET.Cells(1, column.Index + 1) = column.HeaderText
                Next

                Dim rowCnt As Integer = DataGridView1.Rows.Count
                Dim colCnt As Integer = DataGridView1.Columns.Count

                Dim batchSize As Integer = 10000
                Dim currentRow As Integer = 0
                Dim valueObjArray As Object(,) = New Object(batchSize - 1, colCnt - 1) {}

                While currentRow < rowCnt
                    Dim rowIndex As Integer = 0

                    While rowIndex < batchSize AndAlso currentRow + rowIndex < rowCnt

                        For colIndex As Integer = 0 To colCnt - 1
                            valueObjArray(rowIndex, colIndex) = DataGridView1(colIndex, currentRow + rowIndex).Value
                        Next

                        rowIndex += 1
                    End While
                    Dim colName As String = ColumnLetter(colCnt)

                    If (currentRow + batchSize + 1) < rowCnt Then
                        XSHEET.Range("A" + (currentRow + 2).ToString(), colName + (currentRow + batchSize + 1).ToString()).Value2 = valueObjArray
                    Else
                        XSHEET.Range("A" + (currentRow + 2).ToString(), colName + (rowCnt + 1).ToString()).Value2 = valueObjArray
                    End If
                    XWORKBOOK.SaveAs(filename)
                    currentRow += batchSize
                End While

                XCELAPP.DisplayAlerts = True

                XWORKBOOK.Close(False)
                XCELAPP.Quit()

                Try
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(XSHEET)
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(XWORKBOOK)
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(XCELAPP)
                Catch
                End Try

                GC.Collect()
                GC.WaitForPendingFinalizers()
                GC.Collect()
                GC.WaitForPendingFinalizers()
            
            End If
        End If

    End Sub
确认使用Marshal.ReleaseComObject。。。;在范围对象上修复OutOfMemory异常。下面是用于测试的代码。您必须用自己的代码替换几行代码。代码的第一部分是生成大量随机数据。第二部分以块的形式写出DataTable行。通过设置xls.Visible=true;您可以看到Excel使用Excel窗口底部的进度条处理每个块

public static void TestExcel(String filename, int maxRows) {
    int numCols = 100;
    Type[] availTypes = new Type[] { typeof(bool), typeof(int), typeof(double), typeof(String), typeof(DateTime) };
    Type[] types = new Type[numCols];
    Random r = new Random();
    DataTable table = new DataTable();
    for (int i = 0; i < numCols; i++) {
        Type ty = availTypes[r.Next(availTypes.Length)];
        types[i] = ty;
        table.Columns.Add("Col" + i, ty);
    }
    DateTime minDate = new DateTime(1901,01,01);
    for (int i = 0; i < maxRows; i++) {
        Object[] arr2 = new Object[numCols];
        for (int j = 0; j < numCols; j++) {
            Object o = null;
            Type ty = types[j];
            if (ty == typeof(bool))
                o = (r.Next(2) == 0 ? false : true);
            else if (ty == typeof(int))
                o = r.Next(int.MinValue, int.MaxValue);
            else if (ty == typeof(double))
                o = r.NextDouble();
            else if (ty == typeof(String)) {
                int len = r.Next(0, 256);
                char c = ExcelUtils.ToLetters(r.Next(26))[0];
                o = new String(c, len);
            }
            else if (ty == typeof(DateTime))
                o = minDate.AddSeconds(r.Next(int.MaxValue));

            arr2[j] = o;
        }
        table.Rows.Add(arr2);   
    }

    XlFileFormat format = XlFileFormat.xlWorkbookDefault;
    if (File.Exists(filename))
        File.Delete(filename);

    DateTime utcNow = DateTime.UtcNow;
    Workbook wb = null;
    Worksheet ws = null;

    Excel xls = new Excel(); // replace with Application.Excel
    xls.Visible = true;
    xls.DisplayAlerts = false;
    if (xls.Workbooks.Count == 0)
        wb = xls.Workbooks.Add();
    else
        wb = xls.Workbooks[1];

    if (wb.Worksheets.Count == 0)
        ws = wb.Worksheets.Add();
    else
        ws = wb.Worksheets[1];

    int maxCellsPerInsert = 1000000; // inserting too much data at once results in an out of memory exception
    int batchSize = maxCellsPerInsert / table.Columns.Count; 
    int fromIndex = 0;
    int n = table.Rows.Count;
    while (fromIndex < n) {
        int toIndex = Math.Min(fromIndex + batchSize, n);
        Range r0 = ws.get_Range("A" + (fromIndex + 1));
        Object[,] arr = DataTableUtils.ToObjectArray(table, false, true, null, fromIndex, toIndex); // replace with your own arr[,] code
        Range r00 = r0.Resize(arr.GetLength(0), arr.GetLength(1));
        r00.Value = arr;
        r00.Dispose(); // replace with Marshal.Release
        r0.Dispose(); // replace with Marshal.Release
        fromIndex = toIndex;
    }

    wb.SaveAs(filename, format, AccessMode: XlSaveAsAccessMode.xlNoChange);
    wb.Close(false, filename, null);
    xls.Quit(false, false);

    long length = FileEx.GetFileLengthFast(filename);
    double totalSeconds = (DateTime.UtcNow - utcNow).TotalSeconds;
    String message = "NumRows: " + maxRows + " duration: " + Math.Round(totalSeconds, 1) + " seconds. File length: " + length + "  rows/sec: " + Math.Round(1.0* maxRows / totalSeconds);
}
确认使用Marshal.ReleaseComObject。。。;在范围对象上修复OutOfMemory异常。下面是用于测试的代码。您必须用自己的代码替换几行代码。代码的第一部分是生成大量随机数据。第二部分以块的形式写出DataTable行。通过设置xls.Visible=true;您可以看到Excel使用Excel窗口底部的进度条处理每个块

public static void TestExcel(String filename, int maxRows) {
    int numCols = 100;
    Type[] availTypes = new Type[] { typeof(bool), typeof(int), typeof(double), typeof(String), typeof(DateTime) };
    Type[] types = new Type[numCols];
    Random r = new Random();
    DataTable table = new DataTable();
    for (int i = 0; i < numCols; i++) {
        Type ty = availTypes[r.Next(availTypes.Length)];
        types[i] = ty;
        table.Columns.Add("Col" + i, ty);
    }
    DateTime minDate = new DateTime(1901,01,01);
    for (int i = 0; i < maxRows; i++) {
        Object[] arr2 = new Object[numCols];
        for (int j = 0; j < numCols; j++) {
            Object o = null;
            Type ty = types[j];
            if (ty == typeof(bool))
                o = (r.Next(2) == 0 ? false : true);
            else if (ty == typeof(int))
                o = r.Next(int.MinValue, int.MaxValue);
            else if (ty == typeof(double))
                o = r.NextDouble();
            else if (ty == typeof(String)) {
                int len = r.Next(0, 256);
                char c = ExcelUtils.ToLetters(r.Next(26))[0];
                o = new String(c, len);
            }
            else if (ty == typeof(DateTime))
                o = minDate.AddSeconds(r.Next(int.MaxValue));

            arr2[j] = o;
        }
        table.Rows.Add(arr2);   
    }

    XlFileFormat format = XlFileFormat.xlWorkbookDefault;
    if (File.Exists(filename))
        File.Delete(filename);

    DateTime utcNow = DateTime.UtcNow;
    Workbook wb = null;
    Worksheet ws = null;

    Excel xls = new Excel(); // replace with Application.Excel
    xls.Visible = true;
    xls.DisplayAlerts = false;
    if (xls.Workbooks.Count == 0)
        wb = xls.Workbooks.Add();
    else
        wb = xls.Workbooks[1];

    if (wb.Worksheets.Count == 0)
        ws = wb.Worksheets.Add();
    else
        ws = wb.Worksheets[1];

    int maxCellsPerInsert = 1000000; // inserting too much data at once results in an out of memory exception
    int batchSize = maxCellsPerInsert / table.Columns.Count; 
    int fromIndex = 0;
    int n = table.Rows.Count;
    while (fromIndex < n) {
        int toIndex = Math.Min(fromIndex + batchSize, n);
        Range r0 = ws.get_Range("A" + (fromIndex + 1));
        Object[,] arr = DataTableUtils.ToObjectArray(table, false, true, null, fromIndex, toIndex); // replace with your own arr[,] code
        Range r00 = r0.Resize(arr.GetLength(0), arr.GetLength(1));
        r00.Value = arr;
        r00.Dispose(); // replace with Marshal.Release
        r0.Dispose(); // replace with Marshal.Release
        fromIndex = toIndex;
    }

    wb.SaveAs(filename, format, AccessMode: XlSaveAsAccessMode.xlNoChange);
    wb.Close(false, filename, null);
    xls.Quit(false, false);

    long length = FileEx.GetFileLengthFast(filename);
    double totalSeconds = (DateTime.UtcNow - utcNow).TotalSeconds;
    String message = "NumRows: " + maxRows + " duration: " + Math.Round(totalSeconds, 1) + " seconds. File length: " + length + "  rows/sec: " + Math.Round(1.0* maxRows / totalSeconds);
}

经过其他用户的大量测试和帮助,尤其是厌恶,我发现用标准方法无法将大型DataGridView导出到Excel而不将异常抛出内存,我还没有测试Oledb或Xml。对我来说,一个可行的解决方案是导出数据表,这是DGV的数据源。请注意,这种解决方案适用于在DGV填充数据之后在同一过程中进行导出。否则,如果要在以后导出数据,例如在单击按钮之后,则需要将datatable声明为Public,我不会这样做。似乎直接从DGV导出时发生的内存中断是,在从DGV读取数据块并将其复制到Excel range后,这些数据块仍保留在内存中,我不知道这是为什么。此解决方案中的一个关键问题是,从datatable读取数据,然后批量写入Excel。我的情况是,我需要将90.000多行导出到Excel。对于90.000行,我使用了25.000行的批处理大小,这对于90k单元格来说效果很好。但对于我测试的270k或360k等较大的行数,我使用了较小的批处理值10.000行。这是因为我的WinForm已经因为显示一个大DGV而加重了内存方面的负担。所以,如果在DGV中有270k行,那么以25000行为一批进行导出会出现异常。但有了10.000,这还可以,尽管出口时间更长。关于导出时间:90k行,批次为25k,在我的环境中1分钟05秒;270k行10k批次耗时9分钟,360k行10k批次耗时15分钟

        Dim filename As String = ""
        Dim SV As SaveFileDialog = New SaveFileDialog()
        SV.FileName = "Excel export"

        SV.Filter = "xlsx files (*.xlsx)|*.xlsx|All files (*.*)|*.*"
        SV.FilterIndex = 1
        SV.RestoreDirectory = True

        Dim result As DialogResult = SV.ShowDialog()

        If result = DialogResult.OK Then

            filename = SV.FileName

            Dim xcelApp As Microsoft.Office.Interop.Excel.Application = Nothing
            Dim xWorkbook As Microsoft.Office.Interop.Excel.Workbook = Nothing
            Dim xSheet As Microsoft.Office.Interop.Excel.Worksheet = Nothing
            Dim misValue As Object = System.Reflection.Missing.Value
            xcelApp = New Excel.Application()
            xWorkbook = xcelApp.Workbooks.Add(misValue)
            xcelApp.DisplayAlerts = False
            xcelApp.Visible = False
            xSheet = xWorkbook.ActiveSheet

            xSheet.Range("B1").ColumnWidth = 11

            'export column headers to Excel is shown below
            Dim i As Integer = 1
            For Each column As DataColumn In dataTab.Columns
                xSheet.Cells(1, i) = column.ColumnName
                i = i + 1
            Next

            Dim rowCnt As Integer = dataTab.Rows.Count
            Dim colCnt As Integer = dataTab.Columns.Count

            Dim batchSize As Integer = 10000 'export will de done in batches
            Dim startRow As Integer = 0 'starting row for each batch
            Dim valueObjArray As Object(,) = New Object(batchSize - 1, colCnt - 1) {}
            'object array with a size of the batch x number of columns

            While startRow < rowCnt 'iterate until max row number is exceeded
                Dim rowIndex As Integer = 0

                'iterate each until row index reaches batch size
                While rowIndex < batchSize AndAlso startRow + rowIndex < rowCnt

                    'iterate each cell in the row until last column is reached
                    'and assign the value of the cell in datatable to the object array
                    For colIndex As Integer = 0 To colCnt - 1
                        valueObjArray(rowIndex, colIndex) =
                            dataTab.Rows(startRow + rowIndex).Item(colIndex)
                    Next

                    rowIndex += 1 'go to new row
                End While

                Dim colName As String = ColumnLetter(colCnt) 'transform column index to Excel column name

                '("if" below) assign object array to Excel range if batch range + starting row is less than total rows
                If (startRow + batchSize + 1) < rowCnt Then
                    Dim r As Excel.Range = xSheet.Range("A" + (startRow + 2).ToString(),
                                                        colName + (startRow + batchSize + 1).ToString())
                    r.Value2 = valueObjArray
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(r) 'this might be not needed
                Else 'if batch range + starting row is more than total rows assign to Excel range only the remaining rows
                    Dim r As Excel.Range = xSheet.Range("A" + (startRow + 2).ToString(),
                                                        colName + (rowCnt + 1).ToString())
                    r.Value2 = valueObjArray
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(r) 'this might be not needed
                End If
                xWorkbook.SaveAs(filename)
                startRow += batchSize
            End While

            xcelApp.DisplayAlerts = True

            xWorkbook.Close(False)
            xcelApp.Quit()

            Try
                System.Runtime.InteropServices.Marshal.ReleaseComObject(xSheet)
                System.Runtime.InteropServices.Marshal.ReleaseComObject(xWorkbook)
                System.Runtime.InteropServices.Marshal.ReleaseComObject(xcelApp)
            Catch
            End Try

            GC.Collect()
            GC.WaitForPendingFinalizers()
            GC.Collect()
            GC.WaitForPendingFinalizers()

        End If

经过其他用户的大量测试和帮助,尤其是厌恶,我发现用标准方法无法将大型DataGridView导出到Excel而不将异常抛出内存,我还没有测试Oledb或Xml。对我来说,一个可行的解决方案是导出数据表,这是DGV的数据源。请注意,这种解决方案适用于在DGV填充数据之后在同一过程中进行导出。否则,如果要在以后导出数据,例如在单击按钮之后,则需要将datatable声明为Public,我不会这样做。似乎直接从DGV导出时发生的内存中断是,在从DGV读取数据块并将其复制到Excel range后,这些数据块仍保留在内存中,我不知道这是为什么。此解决方案中的一个关键问题是,从datatable读取数据,然后批量写入Excel。我的情况是,我需要将90.000多行导出到Excel。对于90000行,我使用了25000行的批量大小,这很有效 对90k细胞来说很好。但对于我测试的270k或360k等较大的行数,我使用了较小的批处理值10.000行。这是因为我的WinForm已经因为显示一个大DGV而加重了内存方面的负担。所以,如果在DGV中有270k行,那么以25000行为一批进行导出会出现异常。但有了10.000,这还可以,尽管出口时间更长。关于导出时间:90k行,批次为25k,在我的环境中1分钟05秒;270k行10k批次耗时9分钟,360k行10k批次耗时15分钟

        Dim filename As String = ""
        Dim SV As SaveFileDialog = New SaveFileDialog()
        SV.FileName = "Excel export"

        SV.Filter = "xlsx files (*.xlsx)|*.xlsx|All files (*.*)|*.*"
        SV.FilterIndex = 1
        SV.RestoreDirectory = True

        Dim result As DialogResult = SV.ShowDialog()

        If result = DialogResult.OK Then

            filename = SV.FileName

            Dim xcelApp As Microsoft.Office.Interop.Excel.Application = Nothing
            Dim xWorkbook As Microsoft.Office.Interop.Excel.Workbook = Nothing
            Dim xSheet As Microsoft.Office.Interop.Excel.Worksheet = Nothing
            Dim misValue As Object = System.Reflection.Missing.Value
            xcelApp = New Excel.Application()
            xWorkbook = xcelApp.Workbooks.Add(misValue)
            xcelApp.DisplayAlerts = False
            xcelApp.Visible = False
            xSheet = xWorkbook.ActiveSheet

            xSheet.Range("B1").ColumnWidth = 11

            'export column headers to Excel is shown below
            Dim i As Integer = 1
            For Each column As DataColumn In dataTab.Columns
                xSheet.Cells(1, i) = column.ColumnName
                i = i + 1
            Next

            Dim rowCnt As Integer = dataTab.Rows.Count
            Dim colCnt As Integer = dataTab.Columns.Count

            Dim batchSize As Integer = 10000 'export will de done in batches
            Dim startRow As Integer = 0 'starting row for each batch
            Dim valueObjArray As Object(,) = New Object(batchSize - 1, colCnt - 1) {}
            'object array with a size of the batch x number of columns

            While startRow < rowCnt 'iterate until max row number is exceeded
                Dim rowIndex As Integer = 0

                'iterate each until row index reaches batch size
                While rowIndex < batchSize AndAlso startRow + rowIndex < rowCnt

                    'iterate each cell in the row until last column is reached
                    'and assign the value of the cell in datatable to the object array
                    For colIndex As Integer = 0 To colCnt - 1
                        valueObjArray(rowIndex, colIndex) =
                            dataTab.Rows(startRow + rowIndex).Item(colIndex)
                    Next

                    rowIndex += 1 'go to new row
                End While

                Dim colName As String = ColumnLetter(colCnt) 'transform column index to Excel column name

                '("if" below) assign object array to Excel range if batch range + starting row is less than total rows
                If (startRow + batchSize + 1) < rowCnt Then
                    Dim r As Excel.Range = xSheet.Range("A" + (startRow + 2).ToString(),
                                                        colName + (startRow + batchSize + 1).ToString())
                    r.Value2 = valueObjArray
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(r) 'this might be not needed
                Else 'if batch range + starting row is more than total rows assign to Excel range only the remaining rows
                    Dim r As Excel.Range = xSheet.Range("A" + (startRow + 2).ToString(),
                                                        colName + (rowCnt + 1).ToString())
                    r.Value2 = valueObjArray
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(r) 'this might be not needed
                End If
                xWorkbook.SaveAs(filename)
                startRow += batchSize
            End While

            xcelApp.DisplayAlerts = True

            xWorkbook.Close(False)
            xcelApp.Quit()

            Try
                System.Runtime.InteropServices.Marshal.ReleaseComObject(xSheet)
                System.Runtime.InteropServices.Marshal.ReleaseComObject(xWorkbook)
                System.Runtime.InteropServices.Marshal.ReleaseComObject(xcelApp)
            Catch
            End Try

            GC.Collect()
            GC.WaitForPendingFinalizers()
            GC.Collect()
            GC.WaitForPendingFinalizers()

        End If


您是否尝试过用于Excel的Oledb提供程序?一个网格中可能需要90000行。用户无法查看90000行。我没有检查Oledb。你认为值得检查一下吗?关于你的问题,一个人怎么可能需要90k行:假设你有一个拥有90k+电池的移动网络,而网络中存在一个主要问题,有成千上万的客户投诉。在这种情况下,工程师需要能够识别顶级单元格贡献者,还需要能够对单元格列表进行后期处理,以便找到交通量变化、KPI降级等。不确定这是否会产生影响,但您不会释放任何范围对象。通常情况下,它类似于范围r=。。。;r、 值2=。。。;Marshal.ReleaseComObject;应该避免代码中的双点。DGV是否绑定到数据表?如果是这样,考虑从DATAROW.ITEMLAMP中取值,而不是通过DGV Cyto.Valk来避免复制数据。对于额外信息的请求,您不会作出响应。你还在寻求解决这个问题的办法吗?我怀疑问题是由于迭代DGV行,从而导致它们变得不共享,并消耗大量内存。可以通过在rows集合上运行empty For Each循环来验证这一点。您是否尝试过用于Excel的Oledb提供程序?一个网格中可能需要90000行。用户无法查看90000行。我没有检查Oledb。你认为值得检查一下吗?关于你的问题,一个人怎么可能需要90k行:假设你有一个拥有90k+电池的移动网络,而网络中存在一个主要问题,有成千上万的客户投诉。在这种情况下,工程师需要能够识别顶级单元格贡献者,还需要能够对单元格列表进行后期处理,以便找到交通量变化、KPI降级等。不确定这是否会产生影响,但您不会释放任何范围对象。通常情况下,它类似于范围r=。。。;r、 值2=。。。;Marshal.ReleaseComObject;应该避免代码中的双点。DGV是否绑定到数据表?如果是这样,考虑从DATAROW.ITEMLAMP中取值,而不是通过DGV Cyto.Valk来避免复制数据。对于额外信息的请求,您不会作出响应。你还在寻求解决这个问题的办法吗?我怀疑问题是由于迭代DGV行,从而导致它们变得不共享,并消耗大量内存。这可以通过在rows集合上运行一个empty For Each循环来验证。我昨天尝试了您在我的原始帖子中关于释放Range对象的建议,见下文。不幸的是,这并没有改变内存消耗,并以抛出异常再次结束。我会根据我的需要修改你的新代码。谢谢你!我更改的代码,没有帮助行之间用;:尺寸r为Excel.Range=XSHEET.RangeA+currentRow+2.ToString,colName+currentRow+batchSize+1.ToString;r、 Value2=valueObjArray;System.Runtime.InteropServices.Marshal。ReleaseComObjectr@Ivaylo编辑您的原始问题,并放置整个更新的代码。您的原始代码在每个块之后调用SaveAs,这是不需要的。此外,基于100万个单元格/143列,最大行批处理大小应为6993。如果您的测试仍然使用10000,那么这就可以解释异常情况。代码中还有其他地方没有释放对象,例如:XSHEET.RangeB1.ColumnWidth=11和XSHEET.Cells1,column.Index+1I会将更新后的代码作为附加答案发布。问题似乎出在DGV本身,尤其是读取它的值,这些值显然保留在内存中。导出DGV后面的数据表解决了这个问题。我还没有测试过just Save和avoiding SaveAs。在处理Excel range时,我的测试没有显示任何更改,但我将它们保存在代码中以防万一。我昨天尝试了您在我的原始帖子中关于发布range对象的建议,请参见下文。不幸的是,这并没有改变内存消耗,并以抛出异常再次结束。我会根据我的需要修改你的新代码。谢谢你!我更改的代码,没有帮助行之间用;:尺寸r为Excel.Range=XSHEET.RangeA+currentRow+2.ToString,colName+currentRow+batchSize+1.ToString;r、 Value2=valueObjArray;System.Runtime.InteropServices.Marshal。ReleaseComObjectr@Ivaylo编辑你的
原始问题,并把整个更新的代码。您的原始代码在每个块之后调用SaveAs,这是不需要的。此外,基于100万个单元格/143列,最大行批处理大小应为6993。如果您的测试仍然使用10000,那么这就可以解释异常情况。代码中还有其他地方没有释放对象,例如:XSHEET.RangeB1.ColumnWidth=11和XSHEET.Cells1,column.Index+1I会将更新后的代码作为附加答案发布。问题似乎出在DGV本身,尤其是读取它的值,这些值显然保留在内存中。导出DGV后面的数据表解决了这个问题。我还没有测试过just Save和avoiding SaveAs。在处理Excel范围时,我的测试没有显示任何更改,但我将它们保存在代码中以防万一。