使用EPPlus库从SQL Server导出到Excel时出现“内存不足”exception

我正在使用EPPlus .NET库来将数据从SQL Server导出到Excel文件。

我正在使用SqlConnection类来读取数据。 对于SqlDataReader游标的每一行,我遍历所有相应行的excel单元格,并从读取器input数据。

这个问题是,当我使用这个函数的大表时,我得到了“内存不足”的错误。 我需要一个方法来创buildRead CURSOR内的某种缓冲区。

一个简洁的代码示例:

 Dim sqlConnection As SqlConnection = New SqlConnection() sqlConnection.ConnectionString = sqlConnectionString.ConnectionString 'connectionstring built before Dim query As SqlCommand = New SqlCommand(query...) Dim newFileStream As New FileStream("c:\junk\test.xlsx", System.IO.FileMode.Create,System.IO.FileAccess.ReadWrite) Using excelApp As New ExcelPackage(newFileStream) sqlConnection.Open() Dim sqlReader As SqlDataReader = query.ExecuteReader() Dim numOfColumns As Byte = sqlReader.FieldCount() Dim rowNumber As Integer = 1 While sqlReader.Read() Dim currentColumn As Byte For currentColumn = 1 To numOfColumns ws.Cells(rowNumber,currentColumn).Value = sqlReader.Item(currentColumn - 1) Next rowNumber += 1 End While excelApp.Save() End Using newFileStream.Close() 

由于在打开Excel的限制时,您将不得不分割文件,下面是一些从数据库中读入多个Excel文件的代码:

 static class Program { private static string _dataSource; private static string _database; private static string _table; private static string _outputPath; private static int _batchSize; public static void Main() { try { _dataSource = ConfigurationManager.AppSettings["DataSource"]; _database = ConfigurationManager.AppSettings["Database"]; _table = ConfigurationManager.AppSettings["Table"]; _outputPath = ConfigurationManager.AppSettings["OutputPath"]; _batchSize = int.Parse(ConfigurationManager.AppSettings["BatchSize"]); CreateExcel(_dataSource, _database, _table, _outputPath, "SELECT * FROM " + _table); } catch (Exception e) { Console.WriteLine(e); } Console.WriteLine("All done!"); } public static void CreateExcel(string dataSource, string databaseName, string tableName, string outputFilePath, string queryNoParameters) { var sqlConnectionString = new SqlConnectionStringBuilder { DataSource = dataSource, InitialCatalog = databaseName, IntegratedSecurity = true }; using (var connection = new SqlConnection(sqlConnectionString.ConnectionString)) { connection.Open(); using (var command = new SqlCommand { Connection = connection, CommandType = CommandType.Text, CommandText = queryNoParameters }) using (var sqlReader = command.ExecuteReader()) { int i = 0; while (WriteExcelFile(tableName, GetFileInfo(databaseName, tableName, outputFilePath, i++), sqlReader, sqlReader.FieldCount, _batchSize)) { Console.WriteLine("Reading next batch..."); } } } } private static bool WriteExcelFile(string tableName, FileInfo fileInfo, IDataReader sqlReader, int numOfColumns, int count) { using (var excelPackage = new ExcelPackage(fileInfo)) { ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets.Add(tableName); Console.WriteLine("Populating header row..."); for (var currentColumn = 1; currentColumn <= numOfColumns; currentColumn++) { worksheet.Cells[1, currentColumn].Value = sqlReader.GetName(currentColumn - 1); worksheet.Column(currentColumn).Style.Numberformat.Format = TranslateSystemtypeToExceltype(sqlReader.GetFieldType(currentColumn - 1)); } Console.WriteLine("Reading data rows..."); int rowNumber = 2; while (rowNumber <= count + 1 && sqlReader.Read()) { for (var currentColumn = 1; currentColumn <= numOfColumns; currentColumn++) worksheet.Cells[rowNumber, currentColumn].Value = sqlReader[currentColumn - 1]; rowNumber++; } if (rowNumber == 2) //nothing read { Console.WriteLine("Nothing to read, reached end of table!"); return false; } Console.WriteLine("Saving Excel file..."); excelPackage.Save(); return rowNumber == count + 2; //in which case we want to read more } } private static FileInfo GetFileInfo(string databaseName, string tableName, string outputFilePath, int i) { return new FileInfo(Path.Combine(outputFilePath, Path.ChangeExtension( string.Format("{0}_{1}_{2}", databaseName, tableName.Replace('.', '-'), i), "xlsx"))); } public static string TranslateSystemtypeToExceltype(Type sysType) { if (sysType == typeof(string)) return "@"; if (sysType == typeof(DateTime)) return "dd/MM/YYYY"; if (sysType == typeof(Decimal)) return "0.000"; if (sysType == typeof(bool)) return "@"; if (sysType == typeof(int)) return "0"; if (sysType == typeof(short)) return "0"; if (sysType == typeof(double)) return "0.000"; return "General"; } }