Excel导出报表学习

  报表特别多的业务逻辑,还是做成一个电子政务、文件管理系统比较合适。比如煤矿的储量管理,就针对报表!和OA系统很类似啊!有些侧重信息管理如地质信息,水文信息,当然也有报表,但是相对来说就少的多了!还是做成信息管理系统,用数据库比较好!对于煤矿机电设备设施管理不好说,感觉各有利弊!

今天重新拾起用Excel输出报表的工作。别人封装的来实在是看不懂!

Excel导出报表学习_第1张图片

  基本思路:任何一个报表都可以划分成若干区域,如图的课程表用红色框划分成了7个区域。

  (似乎用树来组织会不错,如果能有个配置文件,能否不用编码就能实现任何报表的生成?)

  水晶报表的思想是报表包含子报表。如果类比这种思想报表->子报表->区域,那么区域就是输出报表的最小单位。区域包含一系列相同的特性:边框、对齐方式、颜色、字体。区域的确定通过左上角点Cell和行列数目。运用Excel自带的互操作集,划分的区域可以再次划分,如7区域可以再进一步划分,Range可以支持反复的写入。这里只是初步实现了基本功能,区域包含的属性包括:起始xlsCell、行数、列数、object[,]数据、对齐方式、边框(是一个16进制的整数值)、字体、颜色、单元宽度、单元格行高等属性。

目前的类关系是区域(父类)<--标题类,如果使用多工厂方法模式或者简单工厂模式,似乎可以,把区域作为抽象,不过似乎有没有那个必要。再考虑吧。

区域定义如下:

报表区域类
 1 using System;  2 using System.Collections.Generic;  3 using System.Linq;  4 using System.Text;  5 using Excel=Microsoft.Office.Interop.Excel;  6 using System.Reflection;  7 namespace NtExcel  8 {  9     
 10     public class xlsRegion  11  {  12         public const uint Grid_InsideHorizontal = 0x0001;  13         public const uint Grid_InsideVertical = 0x0002;  14         public const uint Grid_EdgeTop = 0x0004;  15         public const uint Grid_EdgeBottom = 0x0008;  16         public const uint Grid_EdgeLeft = 0x0010;  17         public const uint Grid_EdgeRight = 0x0020;  18 
 19 
 20         public static Excel._Application xlApp;  21         public static Excel.Worksheet sheet;  22 
 23         protected Excel.Range range;  24         //起点单元格
 25         protected xlsCell startCell;  26         //行数
 27         int nRowsCount = 0;  28         public int RowsCount  29  {  30             get{return nRowsCount;}  31             set{ nRowsCount=value;}  32  }  33         //列数
 34         int nColumnsCount = 0;  35         public int ColumnsCount  36  {  37             get
 38  {  39                 return nColumnsCount;  40  }  41             set { nColumnsCount = value; }  42  }  43         //合并单元格
 44         protected bool IsMergeCells;  45         public bool MergeCells  46  {  47             get { return IsMergeCells; }  48             set { IsMergeCells = value;}  49  }  50         //对齐方式
 51  Excel.Constants align;  52 
 53         public Excel.Constants Alignment  54  {  55             get { return align; }  56             set { align = value; }  57  }  58         //边框
 59         uint gridLine;  60 
 61         public uint GridLine  62  {  63             get { return gridLine; }  64             set { gridLine = value; }  65  }  66         //数据
 67         object[,] objdata;  68 
 69         public object[,] Objdata  70  {  71             get { return objdata; }  72             set { objdata = value; }  73  }  74         //构造函数
 75         public xlsRegion(xlsCell _startCell, int _RowCount, int _ColumnCount)  76  {  77             startCell = _startCell;  78             int _endRowIndex = _startCell.RowIndex + _RowCount - 1;  79             int _endColumnIndex = _startCell.ColumnIndex + _ColumnCount - 1;  80             xlsCell endCell = new xlsCell(_endRowIndex, _endColumnIndex);//依赖值
 81             range = sheet.get_Range(xlApp.Cells[_startCell.RowIndex, startCell.ColumnIndex], xlApp.Cells[endCell.RowIndex, endCell.ColumnIndex]);  82  }  83         public xlsRegion(string strRange)  84  {  85             //正则表达式验证
 86             range = sheet.get_Range(strRange, Missing.Value);  87  }  88         public virtual void SetStyle()  89  {  90             //range.HorizontalAlignment = align;
 91             range.MergeCells = IsMergeCells;  92  DrawGridLine();  93  }  94         protected void DrawGridLine()  95  {  96             if ((gridLine&Grid_InsideHorizontal)==Grid_InsideHorizontal)  97             { range.Borders.get_Item(Excel.XlBordersIndex.xlInsideHorizontal).Weight = Excel.XlBorderWeight.xlThin;  98  }  99            if ((gridLine&Grid_InsideVertical)==Grid_InsideVertical) 100            {range.Borders.get_Item(Excel.XlBordersIndex.xlInsideVertical).Weight = Excel.XlBorderWeight.xlThin; 101  } 102             if ((gridLine&Grid_EdgeTop)==Grid_EdgeTop) 103             {range.Borders.get_Item(Excel.XlBordersIndex.xlEdgeTop).Weight = Excel.XlBorderWeight.xlThin; 104  } 105             if ((gridLine&Grid_EdgeBottom)==Grid_EdgeBottom) 106             {range.Borders.get_Item(Excel.XlBordersIndex.xlEdgeBottom).Weight = Excel.XlBorderWeight.xlThin; 107  } 108             if ((Grid_EdgeLeft&gridLine)==Grid_EdgeLeft) 109             {range.Borders.get_Item(Excel.XlBordersIndex.xlEdgeLeft).Weight = Excel.XlBorderWeight.xlThin; 110  } 111             if ((Grid_EdgeRight&gridLine)==Grid_EdgeRight) 112             {range.Borders.get_Item(Excel.XlBordersIndex.xlEdgeRight).Weight = Excel.XlBorderWeight.xlThin; 113  } 114             
115  } 116         public virtual void FillData() 117  { 118             range.Value2 = objdata; 119  } 120         
121  } 122 
123 }
xlsCell
 1 public class xlsCell
 2     {
 3         int nRowIndex;
 4 
 5         public int RowIndex
 6         {
 7             get { return nRowIndex; }
 8             set { nRowIndex = value; }
 9         }
10         int nColumnIndex;
11 
12         public int ColumnIndex
13         {
14             get { return nColumnIndex; }
15             set { nColumnIndex = value; }
16         }
17         public xlsCell(int _RowIndex, int _ColumnIndex)
18         {
19             nRowIndex = _RowIndex;
20             nColumnIndex = _ColumnIndex;
21         }
22        public  void MoveTo(int _RowIndex, int _ColumnIndex)
23        {
24             nRowIndex = _RowIndex;
25             nColumnIndex = _ColumnIndex;
26        }
27     }

为方便起见:从xlsRegion继承了标题类和列头类,图上1和3区域。

标题类
 1  public class xlsTitle: xlsRegion  2  {  3         public xlsTitle(xlsCell _startCell, int _cols)  4            : base(_startCell, 1, _cols)  5  {  6             base.IsMergeCells = true;  7             base.Alignment = Excel.Constants.xlCenter;  8             base.GridLine = Grid_EdgeBottom | Grid_EdgeTop|Grid_EdgeLeft|Grid_EdgeRight;  9  } 10         string title; 11 
12         public string Title 13  { 14             get { return title; } 15             set { title = value; } 16  } 17         public override void FillData() 18  { 19             range.Value2=title; 20  } 21         public override void SetStyle() 22  { 23             range.MergeCells = base.IsMergeCells; 24             range.HorizontalAlignment = base.Alignment; 25             base.DrawGridLine(); 26  } 27     }
列头类
 1 public class xlsColumnHeader:xlsRegion  2  {  3         public xlsColumnHeader(xlsCell _startCell,int _ColumnsCount )  4            : base(_startCell, 1, _ColumnsCount)  5  {  6             base.Alignment=Excel.Constants.xlCenter;  7             base.GridLine=Grid_EdgeBottom|Grid_EdgeTop|Grid_EdgeLeft|Grid_EdgeRight;  8  }  9         List<string> headers; 10 
11         public List<string> Headers 12  { 13             get { return headers; } 14             set { headers = value; } 15  } 16         public override void FillData() 17  { 18             int i=0; 19  Excel.Range rg; 20             foreach (string str in headers) 21  { 22                 rg = xlApp.get_Range(xlApp.Cells[startCell.RowIndex, startCell.ColumnIndex+i], xlApp.Cells[startCell.RowIndex, startCell.ColumnIndex + i]); 23                 i++; 24                 rg.Value2 = str; 25  } 26            
27  } 28         public override void SetStyle() 29  { 30             range.MergeCells = base.IsMergeCells; 31             range.HorizontalAlignment = base.Alignment; 32             base.DrawGridLine(); 33         }

Excel导出报表的流程一般为:启动Excel应用程序,初始化工作簿,初始化sheet,写入报表,保存文件,关闭工作簿,退出Excel。

因此封装工作流程类:

xlsApp
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using Excel = Microsoft.Office.Interop.Excel;
 6 using System.Diagnostics;
 7 namespace NtExcel
 8 {
 9    public class xlsApp
10     {
11         public  Excel._Application xlApp;
12         public  Excel.Worksheet sheet;
13         Excel.Workbook book;
14         public void InitReport(string _Sheetname,int _SheetIndex=1)
15         {
16             xlApp = new Excel.ApplicationClass();
17             if (xlApp == null)
18             {
19                 throw new ArgumentException("Excel无法启动,可能是您未安装Excel软件.");
20             }
21             object missing = System.Reflection.Missing.Value;
22             xlApp.Workbooks.Add(missing);
23 
24             book = xlApp.Workbooks[1];
25             sheet = (Excel.Worksheet)book.Sheets[_SheetIndex];
26             sheet.Name = _Sheetname;
27         }
28         public void KillExcelProcess()
29         {
30             Process[] myProcesses;
31             myProcesses = Process.GetProcessesByName("Excel");
32 
33             foreach (Process myProcess in myProcesses)
34             {
35                 myProcess.Kill();
36             }
37         }
38         private void ReleaseObject(object obj)
39         {
40             try
41             {
42                 System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
43             }
44             catch { }
45             finally { obj = null; }
46         }
47        public void SaveReport(string filename)
48         {
49             xlApp.DisplayAlerts = false;
50             book.SaveCopyAs(filename);
51             xlApp.Workbooks.Close();
52             xlApp.Quit();
53             sheet = null;
54             this.ReleaseObject(book);
55             this.ReleaseObject(xlApp);
56         }
57     }
58 }

位运算的应用:
借鉴Window窗体样式设置的思想用‘|’按位并操作实现样式的叠加。因为区域的边框有六种样式,用户可以设置不同的样式组合。每一种特性用二进制的0和1表示,每位表示一种特性。如A=0001、B=0010、C=0100、D=1000表示四种特性,通用'|'运算获得style,style1=A|B|C=0111,style2=B|C=0110。用'&'获的是否包含此特性,style&A=0001,style2&A=0000。

        public const uint Grid_InsideHorizontal = 0x0001; public const uint Grid_InsideVertical = 0x0002; public const uint Grid_EdgeTop = 0x0004; public const uint Grid_EdgeBottom = 0x0008; public const uint Grid_EdgeLeft = 0x0010; public const uint Grid_EdgeRight = 0x0020;

类的调用实例如下:

调用的示例
 1   private void button2_Click(object sender, EventArgs e)
 2         {
 3             OracleHelper.connectionString = "Data Source =demo; User Id =peouser; Password =123; Integrated Security = no";
 4             csRegions reg = new csRegions();
 5             reg.Fetch();
 6             object[,] objs = new object[csRegions.list.Count, 1];
 7             int i=0;
 8             foreach (string str in csRegions.list)
 9             {
10                 objs[i, 0] = str;
11                 i++;
12             }
13             string VirFileName = "D:\\" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".xls";
14 
15             xlsApp excel = new xlsApp();
16             excel.InitReport("很好啊");
17 
18             xlsRegion.xlApp = excel.xlApp;
19             xlsRegion.sheet = excel.sheet;
20 
21             xlsCell cel1 = new xlsCell(1, 1);
22             xlsTitle xls_Title = new xlsTitle(cel1, 10);
23             xls_Title.Title = "我是中国人!";
24             xls_Title.SetStyle();
25             xls_Title.FillData();
26             
27             cel1.MoveTo(2, 1);
28             int rowsData = objs.GetLength(0);
29             xlsRegion xls_Region = new xlsRegion(cel1, rowsData, 1);
30             xls_Region.Objdata = objs;
31             xls_Region.FillData();
32             xls_Region.SetStyle();
33 
34             cel1.MoveTo(2, 2);
35             xlsColumnHeader xls_Column = new xlsColumnHeader(cel1,9);
36             List<string> listheader = new List<string>();
37             listheader.Add("姓名");
38             listheader.Add("工种");
39             xls_Column.Headers = listheader;
40             xls_Column.FillData();
41             xls_Column.SetStyle();
42 
43             excel.SaveReport(VirFileName);
44             GC.Collect();
45 
46             excel.KillExcelProcess();
47         }

Excel导出报表学习_第2张图片

你可能感兴趣的:(Excel)