注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

奕克

爱家人爱工作爱生活

 
 
 

日志

 
 

How To Get Properties and Methods in Late Binding COM-Apps Like Excel(forward)  

2010-06-26 11:56:32|  分类: 技术 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
IntroductionIf you want to automate Microsoft Excel (or any other COM-Object) from a C#-app, you have two possibilities: 
  • Early Binding: If you know, which Excel-version is on the target-machine of your customer (and you are so lucky, that you have this version too, you can do an early binding, i.e. the binding between your app and Excel will be done at compilation-time. You can read more about this here
  • Late Binding: If you do not know, which version will run on your target-machine, you have to use late binding. The binding to Excel will be done at runtime. 
  • In late binding, there is unfortunately (almost) no support of the methods and properties of the Excel-Object at compile time in Visual Studio .NET. I had to automate Excel with a chart and it was a hard trial and error time to get the appropriate methods and properties. But there is a way to go through (of course, I found it at the very end...) .
    Step 1: Write a VBA-script in ExcelJust to be sure, write a VisualBasic Application (VBA) macro in Excel. Then you are sure, that the steps you want to go are really possible. Here you have the support even for one version. 
    Step 2: Open Excel from your C# AppThe technique to do a late binding is described here. First, you have to start the Application out of the registry. 
    First some definitions: 
    using System;using System.Reflection;...public class ExcelCommander{    const int xlAutomatic=-4105;    const int xlManual   =-4135;    const int xlUpward    =-4171;    const int xlWait    =2;    object oApp;    object oBook;    object oBooks;    object oSheets;    object oSheet;    object objRange_Late;    object oCharts;    object oChart;    object oPoints;    object oPoint;    object oAxisX;    object oAxisY;    object oCursor;    object[] Parameters;
    (If you look for the values of the xlFoo constants: Open the direct-window in VBA and enter the name of the constant. If you are looking for the constant-names itself: seek in the object-browser in VBA.) 
    Now we do the job: start Excel: 
    // Get the class type and instantiate Excel.Type objClassType;objClassType = Type.GetTypeFromProgID("Excel.Application");oApp = Activator.CreateInstance(objClassType);
    Now we have a reference to the Excel-application. 
    Step 3: Invoke the Members, Methods and PropertiesBefore I describe, how to get the members and properties here's the calling technique: it is done in one call: 
    obj.GetType().InvokeMember(sProperty,BindingFlags, null, obj, oParam );
    With: 
  • sProperty: Name of the property or method (string
  • BindingFlags.GetProperty to get a property 
  • BindingFlags.SetProperty to set a property 
  • BindingFlags.InvokeMethod to call a method 
  • obj: Reference to the COM-Object 
  • oParam: List of parameters for this call 
  • For convenience, I wrote some wrappers for these calls: 
    #region private Wrappersprivate void SetProperty(object obj,string sProperty,object oValue){    object[] oParam=new object[1];    oParam[0]=oValue;    obj.GetType().InvokeMember(sProperty,BindingFlags.SetProperty, null, obj, oParam );}private object GetProperty(object obj,string sProperty,object oValue){    object[] oParam=new object[1];    oParam[0]=oValue;    return obj.GetType().InvokeMember(sProperty,BindingFlags.GetProperty, null, obj, oParam );}private object GetProperty(object obj,string sProperty,object oValue1,object oValue2){    object[] oParam=new object[2];    oParam[0]=oValue1;    oParam[1]=oValue2;    return obj.GetType().InvokeMember(sProperty,BindingFlags.GetProperty, null, obj, oParam );}private object GetProperty(object obj,string sProperty){    return obj.GetType().InvokeMember(sProperty,BindingFlags.GetProperty, null, obj, null );}private object InvokeMethod(object obj,string sProperty,object[] oParam){    return obj.GetType().InvokeMember(sProperty,BindingFlags.InvokeMethod, null, obj, oParam);}private object InvokeMethod(object obj,string sProperty,object oValue){    object[] oParam=new object[1];    oParam[0]=oValue;    return obj.GetType().InvokeMember(sProperty,BindingFlags.InvokeMethod, null, obj, oParam );}#endregion
    Now we can do the job with little effort. 
    We open a Workbook
    //Get the workbooks collection.oBooks=GetProperty(oApp,"Workbooks");//Add a new workbook.Parameters[0]=System.Windows.Forms.Application.StartupPath+@"\EndoTherm.xlt";oBook=InvokeMethod(oBooks,"Add",Parameters);
    As you can see, I opened it with a template. In this way, it is possible to do most of the job (creating a Chart, etc.) already in the template. So we need only import the data values and do some adjustment. 
    Next, we look for a single Worksheet and do some "Cosmetics": 
    //Get the worksheets collection.oSheets = GetProperty(oBook,"Worksheets");//Get the first worksheet.oSheet = GetProperty(oSheets,"Item","Temp");SetProperty(oApp,"Calculation",xlManual);SetProperty(oApp,"Visible",true);oCursor=GetProperty(oApp,"Cursor");SetProperty(oApp,"Cursor",xlWait);SetProperty(oApp,"UserControl"false);
    Due to the fact that the template already has a chart, we can go further and load the references too. 
    Note: Such properties are only addressable if they are defined in the Excel-sheet. Of course! (I spent a lot of time to learn this...) 
    //Get the first Diagram.oCharts=GetProperty(oSheet,"ChartObjects");oChart=GetProperty(oCharts,"Item",1);oChart=GetProperty(oChart,"Chart");//Get AxisoAxisY=GetProperty(oChart,"Axes");oAxisX=GetProperty(oAxisY,"Item",1);oAxisY=GetProperty(oAxisY,"Item",2);
    Now we can fill in the data. e.g.: Cell(1,1,"Hello World")
    public void Cell(int Row,int Col,object Value){oRange = GetProperty(oSheet,"Range",(char)col+Row.ToString(),Missing.Value);SetProperty(oRange,"Value",Value);}
    Or set the Minimum and Maximum of the chart:
    public ChartMiniMax(double Xmin,double Xmax,double Ymin,double Ymax){SetProperty(oAxisX,"MinimumScale",Xmin);SetProperty(oAxisX,"MaximumScale",Xmax);SetProperty(oAxisY,"MinimumScale",Ymin);SetProperty(oAxisY,"MaximumScale",Ymax);}
    At least we close the whole business. And here is a problem: the number of parameters depends on the version of Excel. V9.0 uses 9 parameters but V10.0 uses 10 for a "SaveAs" so we have to do some preparing: 
    SetProperty(oApp,"StatusBar","Ready");//get Excel-version as integerswitch((int)Single.Parse((string)GetProperty(oApp,"Version")))        {  case 9: {  Parameters = new Object[9];  break; } case 10: {  Parameters = new Object[10];  break; } default: {  Parameters = new Object[9];  break; }}SetProperty(oApp,"Calculation",xlAutomatic);SetProperty(oApp,"UserControl"true);SetProperty(oApp,"Cursor",oCursor);Parameters[0] = sFileName;for (int i=1;i<Parameters.Length;i++)Parameters = Missing.Value;InvokeMethod(oSheet,"SaveAs",Parameters );//Return control of Excel to the user.SetProperty(oApp,"Visible",true);
    In my application, I imported some DataLabels too. But for brevity, I omit this part. Up to here, the code is only meant as an example. The main question is still unanswered. 
    How to Get the Members, Properties and Methods?Your VBA-macro gives you an idea, which members, methods and properties you need. Now include a reference to your Excel-application: 
  • In Visual Studio .NET, goto View 
  • Select Add reference 
  • Select COM Tab 
  • Select Microsoft Excel Open the Object browser and goto "Excel". There you will find all methods and properties. 
  • For methods (marked with a margenta icon), use the InvokeMethod(...) wrapper. 
    For properties (white and grey icon), use the GetProperty(...) or SetProperty(...)wrapper. 
    If you have to get an instance of a collection use the "ItemGetProperty(...,"Item",...). (it seems that you can also use the InvokeMethod(...,"Item",...). In this case, click on the "Item"-item in the object-browser. In the bottom of the window, you see the type of the returned object. Select this object in the object-browser to see its members, properties and methods. In the next step, you have to use the reference to this member. 
    We saw it already: 
    oCharts=GetProperty(oSheet,"ChartObjects");oAxisY=GetProperty(oChart,"Axes");oAxisX=GetProperty(oAxisY,"Item",1);SetProperty(oAxisX,"MinimumScale",Xmin);
    A member of ChartObjects is the collection Axes. The first Member of this Axes-collection is the X-axis. You can now use this reference to set or get the properties. 
    I hope this helps you a little to shorten the way to an Excel solution. 
    original article: http://www.codeproject.com/KB/cs/How2LateBinding.aspx
      评论这张
     
    阅读(158)| 评论(0)
    推荐 转载

    历史上的今天

    在LOFTER的更多文章

    评论

    <#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
     
     
     
     
     
     
     
     
     
     
     
     
     
     

    页脚

    网易公司版权所有 ©1997-2017