将 DataTable/DataSet 写入 Excel 工作簿
Writing DataTable/DataSet to Excel Workbook
我正在遍历数据库并按月查询,然后将此数据插入到 DataTable
中,用于用户指定年份的每个月。我想将此 DataTable
插入到 Excel 工作簿的新 sheet 中。因此,在我的单个 Excel 工作簿中,我最终得到 12 sheet。
所以我有几个问题由此而来。
Would it be better to have a DataSet containing my 12 DataTables (one for each month)? And then is there a quick and easy way of creating an Excel spreadsheet from my DataSet and being that there are 12 DataTables in that set it would create a separate sheet for each DataTable?
然后另一个问题是
Is it more simple or easier to just create 12 different DataTables and create a workbook and a separate sheet for each DataTable in the workbook and fill that sheet from the DataTable one by one?
您可以将所有数据放入一个数据表中,查询不同的月份,然后遍历数据行,创建 sheet 并插入数据。下面的示例使用放置在 DataTable 中的模拟数据来执行此操作。有两个 sql 语句,一个用于创建 sheet,一个用于插入数据。完成后,对于此示例,将有三个月的 sheet,而不是 12,除非每个月至少有一个记录或更多。如果您必须返回并插入更多行,那么将需要额外的逻辑,这不是要求的,但我们需要首先查看 sheet 是否存在,这可以通过简单地尝试创建现有的 sheet 会抛出异常。我让这个例子非常简单。
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Demo1_CS
{
public class MonthDemo
{
/// <summary>
/// Let's look at this as data coming back from a database table
/// </summary>
/// <returns></returns>
public DataTable Table()
{
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn()
{
ColumnName = "ID",
DataType = typeof(int),
AutoIncrement = true
});
dt.Columns.Add(new DataColumn()
{
ColumnName = "Month",
DataType = typeof(string)
});
dt.Columns.Add(new DataColumn()
{
ColumnName = "Name",
DataType = typeof(string)
});
dt.Rows.Add(new object[] { null, "January", "Karen Payne" });
dt.Rows.Add(new object[] { null, "January", "Bill Smith" });
dt.Rows.Add(new object[] { null, "March", "George Jones" });
dt.Rows.Add(new object[] { null, "April", "Frank White" });
return dt;
}
/// <summary>
/// Get a list of distinct month names
/// </summary>
/// <returns></returns>
public List<string> MonthNames()
{
return Table()
.AsEnumerable()
.Select(row => row.Field<string>("Month"))
.Distinct()
.ToList();
}
public void Work()
{
// SQL responsible for creating sheets
string createCommandText =
@"
CREATE TABLE {0}
(
ID INT,
Name CHAR(255)
)";
// SQL responsible for inserting rows of data
string insertCommandText = @"
INSERT INTO {0}
(
ID,
Name
)
VALUES
(
@ID,
@Name
)
";
// assumes this file exists
string FileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DemoMonths.xlsx");
List<DataRow> result;
using (OleDbConnection cn = new OleDbConnection { ConnectionString = "TODO"})
{
using (OleDbCommand cmd = new OleDbCommand { Connection = cn })
{
cmd.Parameters.Add(new OleDbParameter() { ParameterName = "@ID", DbType = DbType.Int32 });
cmd.Parameters.Add(new OleDbParameter() { ParameterName = "@MonthName", DbType = DbType.String });
cmd.Parameters.Add(new OleDbParameter() { ParameterName = "@Name", DbType = DbType.String });
// assume the file will open else use a try-catch
cn.Open();
// Iterate months, get rows and insert rows into proper sheet
foreach (string monthName in MonthNames())
{
result = Table().AsEnumerable().Where(row => row.Field<string>("Month") == monthName).ToList();
if (result.Count > 0)
{
foreach (DataRow row in result)
{
// assumes sheet does not exists, create it
cmd.CommandText = string.Format(createCommandText, monthName);
try
{
// test if create sheet worked
if (cmd.ExecuteNonQuery() == 1)
{
// load values into command object parameters
cmd.CommandText = string.Format(insertCommandText, monthName);
cmd.Parameters["@ID"].Value = row.Field<int>("ID");
cmd.Parameters["@Name"].Value = row.Field<string>("Name");
// insert row data
cmd.ExecuteNonQuery();
}
}
catch (Exception ex)
{
// simply an example, best to say write to a log file
Console.WriteLine("Failed to create or insert: {0}", ex.Message);
}
}
}
}
}
}
}
}
}
This 正是我所需要的。
我正在遍历数据库并按月查询,然后将此数据插入到 DataTable
中,用于用户指定年份的每个月。我想将此 DataTable
插入到 Excel 工作簿的新 sheet 中。因此,在我的单个 Excel 工作簿中,我最终得到 12 sheet。
所以我有几个问题由此而来。
Would it be better to have a DataSet containing my 12 DataTables (one for each month)? And then is there a quick and easy way of creating an Excel spreadsheet from my DataSet and being that there are 12 DataTables in that set it would create a separate sheet for each DataTable?
然后另一个问题是
Is it more simple or easier to just create 12 different DataTables and create a workbook and a separate sheet for each DataTable in the workbook and fill that sheet from the DataTable one by one?
您可以将所有数据放入一个数据表中,查询不同的月份,然后遍历数据行,创建 sheet 并插入数据。下面的示例使用放置在 DataTable 中的模拟数据来执行此操作。有两个 sql 语句,一个用于创建 sheet,一个用于插入数据。完成后,对于此示例,将有三个月的 sheet,而不是 12,除非每个月至少有一个记录或更多。如果您必须返回并插入更多行,那么将需要额外的逻辑,这不是要求的,但我们需要首先查看 sheet 是否存在,这可以通过简单地尝试创建现有的 sheet 会抛出异常。我让这个例子非常简单。
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Demo1_CS
{
public class MonthDemo
{
/// <summary>
/// Let's look at this as data coming back from a database table
/// </summary>
/// <returns></returns>
public DataTable Table()
{
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn()
{
ColumnName = "ID",
DataType = typeof(int),
AutoIncrement = true
});
dt.Columns.Add(new DataColumn()
{
ColumnName = "Month",
DataType = typeof(string)
});
dt.Columns.Add(new DataColumn()
{
ColumnName = "Name",
DataType = typeof(string)
});
dt.Rows.Add(new object[] { null, "January", "Karen Payne" });
dt.Rows.Add(new object[] { null, "January", "Bill Smith" });
dt.Rows.Add(new object[] { null, "March", "George Jones" });
dt.Rows.Add(new object[] { null, "April", "Frank White" });
return dt;
}
/// <summary>
/// Get a list of distinct month names
/// </summary>
/// <returns></returns>
public List<string> MonthNames()
{
return Table()
.AsEnumerable()
.Select(row => row.Field<string>("Month"))
.Distinct()
.ToList();
}
public void Work()
{
// SQL responsible for creating sheets
string createCommandText =
@"
CREATE TABLE {0}
(
ID INT,
Name CHAR(255)
)";
// SQL responsible for inserting rows of data
string insertCommandText = @"
INSERT INTO {0}
(
ID,
Name
)
VALUES
(
@ID,
@Name
)
";
// assumes this file exists
string FileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DemoMonths.xlsx");
List<DataRow> result;
using (OleDbConnection cn = new OleDbConnection { ConnectionString = "TODO"})
{
using (OleDbCommand cmd = new OleDbCommand { Connection = cn })
{
cmd.Parameters.Add(new OleDbParameter() { ParameterName = "@ID", DbType = DbType.Int32 });
cmd.Parameters.Add(new OleDbParameter() { ParameterName = "@MonthName", DbType = DbType.String });
cmd.Parameters.Add(new OleDbParameter() { ParameterName = "@Name", DbType = DbType.String });
// assume the file will open else use a try-catch
cn.Open();
// Iterate months, get rows and insert rows into proper sheet
foreach (string monthName in MonthNames())
{
result = Table().AsEnumerable().Where(row => row.Field<string>("Month") == monthName).ToList();
if (result.Count > 0)
{
foreach (DataRow row in result)
{
// assumes sheet does not exists, create it
cmd.CommandText = string.Format(createCommandText, monthName);
try
{
// test if create sheet worked
if (cmd.ExecuteNonQuery() == 1)
{
// load values into command object parameters
cmd.CommandText = string.Format(insertCommandText, monthName);
cmd.Parameters["@ID"].Value = row.Field<int>("ID");
cmd.Parameters["@Name"].Value = row.Field<string>("Name");
// insert row data
cmd.ExecuteNonQuery();
}
}
catch (Exception ex)
{
// simply an example, best to say write to a log file
Console.WriteLine("Failed to create or insert: {0}", ex.Message);
}
}
}
}
}
}
}
}
}
This 正是我所需要的。