您的位置:首页 > 编程语言 > C#

【C#】Excel导出合并行和列并动态加载行与列

2017-11-08 14:24 351 查看
原文链接:http://blog.csdn.net/ww130929/article/details/51816751

简单的Excel导出比较好做,只要设置表头,循环在表格中赋值添加数据即可,但是如果表头是不固定的,并且个数是不确定的,这就需要根据查询出数据的特点来添加导出了。



如上图所示,商品的个数是不确定的,时间的月份个数也是不确定的,所以简单的通过模板是不可以的。并且数据库中查询出的信息是每个商品不同时间的信息,所以查询出的数据相同时间的可能有多条,一个商品在不同的时间分布,所以也可以是多条。



public int DataTableToExcelByMProduct(DataTable dt_model, string sheetName)
{
workbook = new HSSFWorkbook();
ISheet sheet = workbook.CreateSheet(sheetName);
IRow row = null;
ICell cell = null;
//样式
ICellStyle style = workbook.CreateCellStyle();
style.Alignment = HorizontalAlignment.CENTER;//设置单元格的样式:水平对齐居中
style.VerticalAlignment = VerticalAlignment.CENTER;//设置单元格样式:垂直对齐居中
IFont font = workbook.CreateFont();//新建一个字体样式对象
font.Boldweight = short.MaxValue;
style.SetFont(font);
DateTime nowTime = DateTime.Now;

//商品编码数量
var dtgroup=(from p in dt_model.AsEnumerable()
group p by new {
RealName=p.Field<string>("RealName"),
Name=p.Field<string>("Name")
}into g
select new {
RealName=g.Key.RealName,
Name=g.Key.Name,
counts=g.Count()
}).ToList();
//数据表头,时间

row = sheet.CreateRow(0);
cell = row.CreateCell(0);
cell.SetCellValue("时间");
cell.CellStyle = style;
//CellRangeAddress四个参数:起始行、结束行、起始列、结束列
sheet.AddMergedRegion(new CellRangeAddress(0, 2, 0, 0));

//进出口岸  1,1,2,口岸数*2
cell = row.CreateCell(1);
cell.SetCellValue(“进出口商品编码”);
cell.CellStyle = style;
//CellRangeAddress四个参数:起始行、结束行、起始列、结束列
sheet.AddMergedRegion(new CellRangeAddress(0, 0, 1, 2*dtgroup.Count));

//商品拼接
row = sheet.CreateRow(1);
row = sheet.CreateRow(2);
for( int c=0;c<dtgroup.Count;c++)
{
//创建进出口岸单元格,开始
cell = row.CreateCell(2*c+1);
cell.SetCellValue(dtgroup[c].RealName);
cell.CellStyle = style;
//CellRangeAddress四个参数:起始行、结束行、起始列、结束列
sheet.AddMergedRegion(new CellRangeAddress(1, 1, 2*c+1, 2*c+2));

//创建进口单元格
//创建一列
cell=row.CreateCell(2*c+1);
cell.SetCellValue("进口");
cell=row.CreateCell(2*c+2);
cell.SetCellValue("出口");
}

var AllYearCount=(from p in dt_model.AsEnumerable()
group p by new {Year_Month=p.Field<string>("Year_Month")} into m
select new
{
YearMonth =m.Key.Year_Month,
AllYearCount=m.Count()
}).ToList();
//年份
for (int i=0;i < AllYearCount.Count;i++)
{
row=sheet.CreateRow(i+3);
cell=row.CreateCell(0);
string YearMonth=AllYearCount[i].YearMonth;

int month =SafeConvert.ToInt16(YearMonth.Substring(4,2));
cell.SetCellValue("1-"+month+"月");

//贸易额对碰情况
for (int j=0;j<dtgroup.Count;j++)
{
var items=dt_model.AsEnumerable().Where(a=>a.Field<string>("Year_Month")==AllYearCount[i].YearMonth && a.Field<string>("Name")==dtgroup[j].Name).ToList();
if(items.Count>0)
{
cell=row.CreateCell(2*j+1);
cell.SetCellValue(items[0].Field<string>("Export_Desn"));
cell=row.CreateCell(2*j+2);
cell.SetCellValue(items[0].Field<string>("Import_Desn"));
}
else
{
cell=row.CreateCell(2*j+1);
cell.SetCellValue("");
cell=row.CreateCell(2*j+2);
cell.SetCellValue("");
}

}
}
using(FileStream fsm=File.Open(fileName,FileMode.OpenOrCreate,FileAccess.ReadWrite))
{
workbook.Write(fsm);
fsm.Close();
}
return 1;

}


其实代码的核心部分就是创建行与列并且为表格赋值,如果已经创建了行就不用创建了,就像这个例子中的时间单元格已经创建了一次行,这样“进出口商品编码”就不用再次创建行了。但是创建了行必须要创建列,列是在行的基础上创建的,所以即使上一行已经创建了列,下一行还是需要重新创建的。

小结:

这个方法传入的是datatable和表格名称,如果我们返回的数据不是直接输出的需要做一些处理,我们可以采用给datatable增加字段的方法,将我们想要的结果存储到新加的字段中。

导出的思想是一样的,都是要循环行和列,在表格中赋值,不同的是从哪里开始赋,把不同的地方解决,导出也一样easy!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: