とにかく、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";
}
}