剑花 烟雨

   江南  好 风景旧曾谙 日出江花红胜火 春来江水绿如蓝 能不忆东北

理想中的建筑师应该是一个诗人、数学家、精通历史、精通心理学、熟悉音乐、了解医学、还要具备天文学和计算的基本知识。
                                                                                                                         ------------------公元前25年,罗马建筑学家Vitruvius
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

C# Exce编程

Posted on 2008-01-21 14:31  落花人独立  阅读(1677)  评论(2编辑  收藏  举报

以下是整理的网上的关于Excel编程的几个帖子的内容:

1.Excel 编程模型的说明


framework.JPG

在这里 ,就大概描述了在Excel 编程中常用的对象的层次关系。

Excel Application   代表整个 Microsoft Excel 应用程序,

WorkBook            代表 Microsoft Excel 工作簿

Range                    代表某一单元格、某一行、某一列、某一选定区域(该区域可包含一个或若干连续单元格区域),或者某一三维区域。

Areas                       选定区域内的子区域或连续单元格块的集合。

Borders                 代表对象的边框。

Characters             代表包含文本的对象中的字符。可用 Characters对象修改包含在完整文本字符串中的任意字符序列。

Font                        包含对象的字体属性(字体名称、字体大小、字体颜色等)。

ListRow                 代表列表对象中的一行。

Errors                    表示区域的电子表格错误。


2.Excel编程中常用一些功能

2.1 给单元格赋值

Excel._Worksheet oSheet;

oSheet =(Excel._Worksheet)oWB.Sheets.get_Item(1);

    Excel.Range oRg=null ;

    oRg=oSheet.get_Range("C2",Type.Missing);

oRg.Value2 =UserName;

    oRg.Borders[Excel.XlBordersIndex.xlEdgeTop].LineStyle=Excel.XlLineStyle.xlContinuous;

oRg.Borders[Excel.XlBordersIndex.xlEdgeTop].Weight =Excel.XlBorderWeight.xlThin;

oRg.Borders[Excel.XlBordersIndex.xlEdgeTop].ColorIndex=Excel.XlColorIndex.xlColorIndexAutomatic;

本代码的含义是选择单元格C2 ,并给单元格中赋值 UserName ,并控制单元格的上边框的样式

2.2Excel报表添加图片

从原有文件中创建图片。返回一个 Shape 对象,该对象代表新图片。

方法的语法

expression.AddPicture(FileName, LinkToFile, SaveWithDocument, Left, Top, Width, Height)

expression      必需。该表达式返回“应用于”列表中的对象之一。

FileName      String 类型,必需。要创建的 OLE 对象的源文件。

LinkToFile      MsoTriState 类型,必需。要链接至的文件。

SaveWithDocument      MsoTriState 类型,必需。将图片与文档一起保存。

Left      Single 类型,必需。相对于文档的左上角,以磅为单位给出图片左上角的位置。

Top      Single 类型,必需。相对于文档的顶部,以磅为单位给出图片左上角的位置。

Width      Single 类型,必需。以磅为单位给出图片的宽度。

Height      Single 类型,必需。以磅为单位给出图片的高度。

举例

oSheet.Shapes.AddPicture(filename,Microsoft.Office.Core.MsoTriState.msoCTrue ,Microsoft.Office.Core.MsoTriState.msoCTrue,photoLeft,photoTop,photowidth,photoheight);

 

2.3 报表的打印

打印指定对象。

方法的语法

expression.PrintOut(From, To, Copies, Preview, ActivePrinter, PrintToFile, Collate, PrToFileName)

expression      必需。该表达式返回“应用于”列表中的一个对象。

From      Variant 类型,可选。打印的开始页号。如果省略该参数,将从起始位置开始打印。

To      Variant 类型,可选。打印的终止页号。如果省略该参数,将打印至最后一页。

Copies      Variant 类型,可选。要打印的份数。如果省略该参数,将只打印一份。

Preview      Variant 类型,可选。如果该值为 True,则 Microsoft Excel 打印指定对象之前进行打印预览。如果该值为 False(或者省略此参数),则立即打印该对象。

ActivePrinter      Variant 类型,可选。设置活动打印机的名称。

PrintToFile      Variant 类型,可选。如果该值为 True,则打印输出到文件。如果没有指定 PrToFileName,则 Microsoft Excel 将提示用户输入要输出文件的文件名。

Collate      Variant 类型,可选。如果该值为 True,则逐份打印每份副本。

PrToFileName      可选,Variant 类型。如果 PrintToFile True,则本参数指定要打印到的文件名。

举例:

oSheet.PrintOut(1,10,"1","False","HPLaserJ","False","True","");

2.4 通过服务在系统间传输报表

    

flow.JPG
             生成用户报表的数据流程图

      Web服务程序

       [WebMethod]

         public byte[] GetFamilyMember(string PersonIdentifier)

         {

              return FamilyMember.GetReport(PersonIdentifier); //The Bussiness of Create the

                                                //report File and Return as The type

                                                //of byte[]

         }

Web服务器段的主要的功能就是提供一个接口供其他系统引用来获取他需要的数据。

Web 程序将取得的报表二进制流发送给请求的客户

      string ReportName ; //the created Report Name

      byte[] result ;      //the date which Tanslate from Web Server

      HttpContext.Current.Response.ContentType = "application/vnd.ms-excel";

      HttpContext.Current.Response.AppendHeader("Content-disposition","inline;filename="+Server.UrlEncode(ReportName+".xls"));

                     //define the header of Web pages

                    result= Server.GetFamilyMember (TemplateName,PersonID);   //get the date                                                                                                     //from Web server 

                    HttpContext.Current.Response.BinaryWrite(result);

                    HttpContext.Current.Response.End();

2.5以下代码示意打开一个已有的Excel文档的第一个sheet页,获取单元格“B1的内容,并判断其值是否为“my”:

 private void Operate(string pFileName)
        
{
            Excel.Application app 
= new Excel.Application();//打开一个Excel应用
            if (app == null)
            
{
                
return;
            }


            Workbooks wbs 
= app.Workbooks;
            _Workbook wb 
= wbs.Add(pFileName);//打开一个现有的工作薄
            Sheets shs = wb.Sheets;
            _Worksheet sh 
= (_Worksheet)shs.get_Item(1);//选择第一个Sheet页
            if (sh == null)
            
{
                
return;
            }


            Range r 
= sh.get_Range("B1", Missing.Value);
            
if (System.Convert.ToString(r.Value2).Trim().Equals("my"))
            
{
                
//Do Something.
            }

        }

2.6不少人在打开Excel应用后,对如何在使用完成后释放它大感头痛,在网上我找到一种方法,经过实验证明是OK的:

 private void ReleaseCOM(object pObj)
        
{
            
try
            
{
                System.Runtime.InteropServices.Marshal.ReleaseComObject(pObj);
            }

            
catch
            
{
                
throw new Exception("释放资源时发生错误!");
            }

            
finally
            
{
                pObj 
= null;
            }

        }

2.7
有了该方法,则只要在步骤2)代码之后添加以下代码,就可以完成对资源的释放:

 private void Operate(string pFileName)
        

……
//释放资源
            ReleaseCOM(sh);
            ReleaseCOM(shs);
            ReleaseCOM(wb);
            ReleaseCOM(wbs);
            app.Quit();
            ReleaseCOM(app);
        }

2.8基于Excel中的函数可以编辑出相当复杂的公式,有时候在处理Excel文档时,希望使用Excel中的公式,以下结合FREQUENCYMATCH函数对B列计算distinct count,将其写入B100单元格(假定有数据的行不超过100行):

string  count = sh.UsedRange.Rows.Count.ToString();
        Range r 
= sh.get_Range("B100",Missing.Value);
        r.Formula 
= "=SUM(IF(FREQUENCY(MATCH(B1:B" + count + ",B1:B" + count + ",0),MATCH(B1:B" + count + ",B1:B" + count + ",0))>0,1))";
        Console.WriteLine(System.Convert.ToString(r.Value2));


2.9Excel导入数据,可以先使用ODBC,以select查询时使用“[sheet页名称$]”作为“表名”,将数据以datatable形式载入到内存中,之后的事就比较简单了,可以根据datatable逐行构造insert语句,然后插入到目标数据库中:
private DataTable LoadExcel(string pPath)
        {
            
string connString = "Driver={Driver do Microsoft Excel(*.xls)};DriverId=790;SafeTransactions=0;ReadOnly=1;MaxScanRows=16;Threads=3;MaxBufferSize=2048;UserCommitSync=Yes;FIL=excel 8.0;PageTimeout=5;";
            connString 
+= "DBQ=" + pPath;
            OdbcConnection conn 
= new OdbcConnection(connString);
            OdbcCommand cmd 
= new OdbcCommand();
            cmd.Connection 
= conn;
            
//获取Excel中第一个Sheet名称,作为查询时的表名
            string sheetName = this.GetExcelSheetName(pPath);
            
string sql = "select * from [" + sheetName.Replace('.''#'+ "$]";
            cmd.CommandText 
= sql;
            OdbcDataAdapter da 
= new OdbcDataAdapter(cmd);
            DataSet ds 
= new DataSet();
            
try
            {                
                da.Fill(ds);
                
return ds.Tables[0];
            }
            
catch (Exception x)
            {
                ds 
= null;
                
throw new Exception("从Excel文件中获取数据时发生错误!");
            }
            
finally
            {
                cmd.Dispose();
                cmd 
= null;
                da.Dispose();
                da 
= null;
                
if (conn.State == ConnectionState.Open)
                {
                    conn.Close();
                }
                conn 
= null;
            }
        }

        
private string GetExcelSheetName(string pPath)
        {
            
//打开一个Excel应用
            Excel.Application app = new Excel.Application();
            
if (app == null)
            {
                
throw new Exception("打开Excel应用时发生错误!");
            }
            Excel.Workbooks wbs 
= app.Workbooks;
            
//打开一个现有的工作薄
            Excel._Workbook wb = wbs.Add(pPath);
            Excel.Sheets shs 
= wb.Sheets;
            
//选择第一个Sheet页
            Excel._Worksheet sh = (Excel._Worksheet)shs.get_Item(1);
            
string sheetName = sh.Name;

            ReleaseCOM(sh);
            ReleaseCOM(shs);
            ReleaseCOM(wb);
            ReleaseCOM(wbs);
            app.Quit();
            ReleaseCOM(app);
            
return sheetName;
        }

(“string sql = "select * from [" + sheetName.Replace('.', '#') + "$]";”如果sheet页名称中含有“.”,则要将其替换为“#”,具体原因,没研究出来-_-。另外贴一张界面截图:)

2.10

关于从Excel导入数据,网上应该有很多例子,这里补充一个关于数据导入时的效率问题。最初在从Excel导入数据到MySql中时,当文件达到50000行时,逐行导入花了10余分钟的时间。大量执行插入操作,逐条执行很慢原因可能在于:

(1)每执行一条插入语句,客户端需要与服务器交互一次,这要有代价

(2)一些数据库对每一条插入操作都执行事务,这也要有代价

所以在大量执行插入操作时,应该尽量先多个insert语句拼接好,例如每次拼接好200个insert语句,然后再一次执行它,这样可以大幅提高效率。


以上为两个帖子的合集,还有其它的编程方法也会一并发在这个帖子里。

count hit
欢迎您到紫阁阳光坐客