1.思路:用Excel模版+Data = .net关于企业Excel报表的生成
2.模板样式,表头字段用{|field|},表字段用{[field]}
3.代码


/// <summary>
/// 根据模板生成Excel报表
/// </summary>
/// <param name="dt">DataTable</param>
/// <param name="templetFilePath">模板存放路径Sheet</param>
/// <param name="outputFilePath">报表输出路径</param>
public static void ExportReportForXLS(DataTable dt, string templetFilePath, string outputFilePath)
{
#region 验证
if (templetFilePath == null)
throw new System.Exception("Excel模板文件路径不能为空!");
if (outputFilePath == null)
throw new System.Exception("输出Excel文件路径不能为空!");
int colCount = dt.Columns.Count;//源dt的行数
int rowCount = dt.Rows.Count; //源dt的列数
if(rowCount == 0)
throw new System.Exception("没有数据");
#endregion
#region 变量定义
int i = 0; int j = 0;int k = 0;
CellInfo mycell;
ArrayList headlist = new ArrayList();
ArrayList detaillist = new ArrayList();
DateTime beforeTime;
DateTime afterTime;
object missing = System.Reflection.Missing.Value;
//创建一个Application对象并使其可见
beforeTime = DateTime.Now;
Excel.Application app = new Excel.ApplicationClass();
app.Visible = true;
afterTime = DateTime.Now;
//打开模板文件,得到WorkBook对象
Excel.Workbook workBook = app.Workbooks.Open(templetFilePath, missing, missing, missing, missing, missing,
missing, missing, missing, missing, missing, missing, missing);
//得到WorkSheet对象
Excel.Worksheet workSheet = (Excel.Worksheet)workBook.Sheets.get_Item(1);
Excel.Range oRange;
#endregion
try
{
#region 收集模板中的相关信息
int rowCountM = 20;//模板最多20行
int colCountM = 25; //模板最多25列
mycell = new CellInfo();
for (i = 1; i <= rowCountM; i++)
{
for (j = 1; j <= colCountM; j++)
{
#region 表头和表内容信息收集
//sheet.Cells[top + j, left + k] = dt.Rows[startRow + j][k].ToString();
string celText = ((Excel.Range)workSheet.UsedRange.Cells[i, j]).Text.ToString();
if (celText.IndexOf("{|") > -1)
{
mycell = new CellInfo();
mycell.cellRow = i;
mycell.cellCol = j;
mycell.cellText = celText.Replace("{|", "").Replace("|}", "");
headlist.Add(mycell);
}
if (celText.IndexOf("{[") > -1)
{
mycell = new CellInfo();
mycell.cellRow = i;
mycell.cellCol = j;
mycell.cellText = celText.Replace("{[", "").Replace("]}", "");
detaillist.Add(mycell);
}
#endregion
#region 分组和图形
//if (((Excel.Range)worksheet.UsedRange.Cells[i, j]).Text.ToString().IndexOf("{(") > -1)
//{
// mycell = new CellInfo();
// mycell.cellRow = i;
// mycell.cellCol = j;
// mycell.cellText = ((Excel.Range)worksheet.UsedRange.Cells[i, j]).Text.ToString().Replace("{[", "").Replace("]}", "");
// grouplist.Add(mycell);
//}
//if (((Excel.Range)worksheet.UsedRange.Cells[i, j]).Text.ToString().IndexOf("{@") > -1)
//{
// graphstring = ((Excel.Range)worksheet.UsedRange.Cells[i, j]).Text.ToString().Replace("{@", "").Replace("@}", "");
//}
#endregion
}
}
#endregion
if (detaillist.Count == 0) return;//没有表内容字段返回
mycell = (CellInfo)detaillist[0];
k = mycell.cellRow; //表内容的起始行号
for (int row = 0; row < rowCount; row++)
{
for (int col = 0; col < colCount; col++)
{
#region 处理header

if (row == 0)
{
for (int header = 0; header < headlist.Count; header++)
{
mycell = new CellInfo();
mycell = (CellInfo)headlist[header];
if (mycell.cellText == dt.Columns[col].Caption)
{
workSheet.UsedRange.Cells[mycell.cellRow, mycell.cellCol] = dt.Rows[row][col].ToString();
}
}
}
#endregion
}
#region 处理Deatil

oRange = (Excel.Range)workSheet.Rows[k + row, missing];
oRange.Copy(missing);
oRange.Insert(Excel.XlInsertShiftDirection.xlShiftDown);
for (int detail = 0; detail < detaillist.Count; detail++)
{
mycell = new CellInfo();
mycell = (CellInfo)detaillist[detail];
//if (mycell.cellText == dt.Columns[col].Caption)
//{
string tt = dt.Rows[row][mycell.cellText].ToString();
workSheet.UsedRange.Cells[k + row + 1, mycell.cellCol] = dt.Rows[row][mycell.cellText].ToString();
//}
}
#endregion
}
//移除k行
oRange = (Excel.Range)workSheet.Rows[k, missing];
oRange.Delete(Excel.XlDeleteShiftDirection.xlShiftUp);
oRange = (Excel.Range)workSheet.Rows[k + rowCount, missing];
oRange.Delete(Excel.XlDeleteShiftDirection.xlShiftUp);
#region grouplist
/*
string groupheader = "";
int grouprow = -1;
int sumindex = 0;
int groupcount = 0;
int[] fields;
Excel.Range cell1;
Excel.Range cell2;
Excel.Range sortcell;
string subtotalloacaltion = "";
if (grouplist.Count > 0)
{
//get grouprow;
for (i = 0; i < grouplist.Count; i++)
{
mycell = new CellInfo();
mycell = (CellInfo)grouplist[i];
if (mycell.cellText.IndexOf("*") > -1)
{
grouprow = mycell.cellCol;
subtotalloacaltion = mycell.cellText.Replace("{(", "").Replace(")}", "").Replace("*", "").Trim().ToLower();
break;
}
}
if (grouprow > 0)
{
fields = new int[] { grouprow + 1, grouprow + 2 };
cell1 = (Excel.Range)worksheet.Cells[k, 1];
cell2 = (Excel.Range)worksheet.Cells[j, worksheet.UsedRange.Columns.Count];
sortcell = (Excel.Range)worksheet.Cells[k, grouprow];
oRange = (Excel.Range)worksheet.UsedRange.get_Range((Excel.Range)cell1, (Excel.Range)cell2);
oRange.Sort(sortcell, Excel.XlSortOrder.xlAscending, refmissing, refmissing, Excel.XlSortOrder.xlAscending, refmissing,
Excel.XlSortOrder.xlAscending, Excel.XlYesNoGuess.xlNo, refmissing, refmissing, Excel.XlSortOrientation.xlSortColumns, Excel.XlSortMethod.xlStroke);
cell1 = (Excel.Range)worksheet.Cells[k - 1, 1];
cell2 = (Excel.Range)worksheet.Cells[j, worksheet.UsedRange.Columns.Count];
oRange = (Excel.Range)worksheet.UsedRange.get_Range((Excel.Range)cell1, (Excel.Range)cell2);
if (subtotalloacaltion != "1")
oRange.Subtotal(grouprow, Excel.XlConsolidationFunction.xlCount, refmissing, refmissing, refmissing, Excel.XlSummaryRow.xlSummaryAbove);
else
oRange.Subtotal(grouprow, Excel.XlConsolidationFunction.xlCount, refmissing, refmissing, refmissing, Excel.XlSummaryRow.xlSummaryBelow);
//getsubtotal array
for (sumindex = k; sumindex <= worksheet.UsedRange.Rows.Count; sumindex++)
{
if (((Excel.Range)worksheet.Cells[sumindex, grouprow]).Text.ToString().IndexOf(" 計數") > -1)
{
mycell = new CellInfo();
mycell.cellCol = grouprow;
mycell.cellRow = sumindex;
subtotallist.Add(mycell);
}
}
CellInfo groupcellcurrent;
CellInfo groupcelllast;
CellInfo grouplistindex;
string fomu;
for (sumindex = 0; sumindex < grouplist.Count; sumindex++)
{
grouplistindex = new CellInfo();
grouplistindex = (CellInfo)grouplist[sumindex];
if (grouplistindex.cellText.IndexOf("*") < 0)
{
for (i = 0; i < subtotallist.Count; i++)
{
if (i == 0)
{
mycell = new CellInfo();
mycell = (CellInfo)subtotallist[i];
groupcelllast = new CellInfo();
groupcelllast.cellRow = k;
groupcelllast.cellCol = grouplistindex.cellCol;
groupcellcurrent = new CellInfo();
groupcellcurrent.cellRow = mycell.cellRow - 1;
groupcellcurrent.cellCol = grouplistindex.cellCol;
}
else
{
mycell = new CellInfo();
mycell = (CellInfo)subtotallist[i - 1];
groupcelllast = new CellInfo();
groupcelllast.cellRow = mycell.cellRow;
groupcelllast.cellCol = grouplistindex.cellCol;
mycell = new CellInfo();
mycell = (CellInfo)subtotallist[i];
groupcellcurrent = new CellInfo();
groupcellcurrent.cellRow = mycell.cellRow - 1;
groupcellcurrent.cellCol = grouplistindex.cellCol;
}
oRange = (Excel.Range)worksheet.Cells[groupcellcurrent.cellRow + 1, groupcellcurrent.cellCol];
fomu = "=" + grouplistindex.cellText.Replace("{(", "").Replace(")}", "") + "(R" + groupcelllast.cellRow.ToString() + "C" + groupcelllast.cellCol.ToString() +
":" + "R" + groupcellcurrent.cellRow.ToString() + "C" + groupcellcurrent.cellCol.ToString() + ")";
try
{
oRange.FormulaR1C1 = fomu;
}
catch (System.Exception exfomu)
{
oRange.Value2 = "Error" + exfomu.ToString();
}
}
}
else // get the first groupcout list {(*)}
{
for (i = 0; i < subtotallist.Count; i++)
{
mycell = new CellInfo();
mycell = (CellInfo)subtotallist[i];
oRange = (Excel.Range)worksheet.Cells[mycell.cellRow, mycell.cellCol + 1];
mycell.cellText = ((Excel.Range)worksheet.UsedRange.Cells[mycell.cellRow, mycell.cellCol]).Text.ToString().Replace(" 計數", "");
oRange.Value = mycell.cellText;
// oRange = worksheet.UsedRange.get_End(Excel.XlDirection.xlToLeft);
// oRange.Value = mycell.cellCol.ToString();
//fomu = "=" + "R" + mycell.cellRow.ToString() + "C" + mycell.cellCol.ToString() ;
// oRange.FormulaR1C1 = fomu;
}
}
}
}
}
string[] graphpara = graphstring.Split("|".ToCharArray());
*/
//draw graphic
//1 . copy all the subtotal informat to worksheet2
//for (i = 0; i < subtotallist.Count; i++)
//{
// mycell = new CellInfo();
// mycell = (CellInfo)subtotallist[i];
// cell1 = (Excel.Range)worksheet.Cells[mycell.cellRow, 1];
// cell2 = (Excel.Range)worksheet.Cells[mycell.cellRow, worksheet.UsedRange.Columns.Count];
// oRange = (Excel.Range)worksheet.UsedRange.get_Range((Excel.Range)cell1, (Excel.Range)cell2);
// oRange.Copy(refmissing);
// cell1 = (Excel.Range)worksheet2.Cells[i, 1];
// cell1.PasteSpecial(Excel.XlPasteType.xlPasteAll, Excel.XlPasteSpecialOperation.xlPasteSpecialOperationNone, refmissing, refmissing);
//}
// //end copy
//Excel.Range oRange2;
//oRange2 = worksheet.UsedRange;
//if (graphpara.Length > 0)
//{
// cell1 = (Excel.Range)worksheet.Cells[k, 1];
// cell2 = (Excel.Range)worksheet.Cells[j, worksheet.UsedRange.Columns.Count];
// oRange = (Excel.Range)worksheet.UsedRange.get_Range((Excel.Range)cell1, (Excel.Range)cell2);
// if (graphpara[0].ToLower().Trim() != "b")
// oRange2 = oRange;
//}
////xlChart.ChartWizard(cellRange.CurrentRegion,Excel.XlChartType.xl3DColumn, Type.Missing,
////Excel.XlRowCol.xlColumns,1, 0, true ,"访问量比较(dahuzizyd.cnblogs.com)", "月份", "访问量",
////"");
//if (graphpara.Length == 8)
//{
// Excel.XlChartType charttype = getchartype(graphpara[1]);
// Excel.Chart xlChart = (Excel.Chart)Myexcel.Charts.Add(refmissing, refmissing, refmissing, refmissing);
// //xlChartl.ChartWizard(oRange2, Excel.XlChartType.xl3DColumn, refmissing, refmissing, refmissing, refmissing,refmissing, refmissing, refmissing, refmissing, refmissing);
// xlChart.ChartWizard(oRange2, charttype, Type.Missing, Excel.XlRowCol.xlColumns, Convert.ToInt32(graphpara[2]),
// Convert.ToInt32(graphpara[3]), true, graphpara[4], graphpara[5], graphpara[6], graphpara[7]);
//}
////设置统计图Sheet的名称:
////xlChart.Name = "统计";
////现在的统计图只有一个组,他们会显示成一样的颜色,我们来让12个Bar都显示不同的颜色:
////Excel.ChartGroup grp = (Excel.ChartGroup)xlChart.ChartGroups(1);
////grp.GapWidth = 20;
////grp.VaryByCategories = true;
////现在Chart的条目的显示形状是Box,我们让它们变成圆柱形,并给它们显示加上数据标签:
////Excel.Series s = (Excel.Series)grp.SeriesCollection(1);
////s.BarShape = XlBarShape.xlCylinder;
////s.HasDataLabels = true;
////下面再来设置统计图的标题和图例的显示:
////xlChart.Legend.Position = XlLegendPosition.xlLegendPositionTop;
////xlChart.ChartTitle.Font.Size = 24;
////xlChart.ChartTitle.Shadow = true;
////xlChart.ChartTitle.Border.LineStyle = Excel.XlLineStyle.xlContinuous;
//最后设置两个轴的属性,Excel.XlAxisType.xlValue对应的是Y轴,Excel.XlAxisType.xlCategory对应的是X轴:
//Excel.Axis valueAxis = (Excel.Axis)xlChart.Axes(Excel.XlAxisType.xlValue, XlAxisGroup.xlPrimary);
//valueAxis.AxisTitle.Orientation = -90;
//Excel.Axis categoryAxis = (Excel.Axis)xlChart.Axes(Excel.XlAxisType.xlCategory, XlAxisGroup.xlPrimary);
//categoryAxis.AxisTitle.Font.Name = "MS UI Gothic";
// Excel.Chart thischart;
// Excel.Range chartrange = (Excel.Range)worksheet.Cells[2,3];
#endregion
#region file save
workBook.SaveAs(outputFilePath, missing, missing, missing, missing, missing, Excel.XlSaveAsAccessMode.xlExclusive, missing, missing, missing, missing);
workBook.Close(null, null, null);
app.Workbooks.Close();
app.Application.Quit();
app.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(workSheet);
System.Runtime.InteropServices.Marshal.ReleaseComObject(workBook);
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
workSheet = null;
workBook = null;
app = null;
GC.Collect();
#endregion
}
catch (System.Exception ex)
{
throw ex;
}
finally
{
#region 关闭在导出报表期间创建的Excel进程
Process[] myProcesses;
DateTime startTime;
myProcesses = Process.GetProcessesByName("Excel");
//得不到Excel进程ID,暂时只能判断进程启动时间
foreach (Process myProcess in myProcesses)
{
startTime = myProcess.StartTime;
if (startTime > beforeTime && startTime < afterTime)
{
myProcess.Kill();
}
}
#endregion
}
}
4.导出结果