• Excel导出报表学习


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

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

      基本思路:任何一个报表都可以划分成若干区域,如图的课程表用红色框划分成了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         }

    文章未经说明均属原创,学习笔记可能有大段的引用,一般会注明参考文献。 欢迎大家留言交流,转载请注明出处。
  • 相关阅读:
    Android实战——第三方服务之Bmob后端云的集成、用户登陆、用户注册、获取用户、用户注销(一)
    Android实战——第三方服务之Bmob后端云的答题系统小项目(四)
    10.Python运行Scrapy时出现错误: ModuleNotFoundError: No module named 'win32api'
    基础小知识(1)
    9.Python安装scrapy教程
    1.使用Fiddler进行接口测试
    8.Python编写登录接口
    18.Selenium+Python案例 -- 豆瓣
    17.Selenium+Python日期控件小案例
    16.Selenium+Python关于句柄的小Demo
  • 原文地址:https://www.cnblogs.com/yhlx125/p/2770141.html
Copyright © 2020-2023  润新知