使用EPPlus库从SQL Server导出到Excel时出现“Out Of Memory”异常

时间:2012-12-16 13:53:17

标签: vb.net excel sqlconnection datareader epplus

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

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

问题是当我对大表使用此函数时,我遇到“内存不足”错误。我需要一种方法在Read 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()

1 个答案:

答案 0 :(得分:3)

由于在达到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";
    }
}