Excel精英培训网

 找回密码
 注册
数据透视表40+个常用小技巧,让你一次学会!
查看: 15404|回复: 23

[分享] 新春献礼:VSTO C#入门

[复制链接]
发表于 2014-2-7 11:16 | 显示全部楼层 |阅读模式
各位网友新春快乐!{:101:}
      坛子做为久负盛名的最大华语VBA论坛之一,但一直以来好象都没有VSTO方面的东东(其实不管是网上还是书籍,关于vsto的资料也非常少),此贴希望能填补一点点空白(口气太大了
      为什么要用VSTO?难道VBA不好?VSTO有什么优势?为什么用C#不用VB?……太多的为什么,可惜只关心是什么,不涉及为什么。这些问题都不答(不是不答,其实是根本就不晓得)。
      这里用的环境是win8.1+Vs2013+office2013(没用过vs2013以前的版本,据说以前版本的发布有点困难),全在此环境下运行通过。

      下面步入正轨:
      下载好Vs2013、office2013后进行安装,其过程非常简单、特别耗时,要有耐心。并做好相关工作。
      打开安装好的vs2013(如图所示):
1.gif
      新建项目,由于要用VSTO C#,我们点模板----visual c#------office/sharepoint-----office外接程序------excel 2013工作薄,下方的名称那里系统默认的excelworkbook1改成vsto_c1(当然也可以是其它,或者什么都不改,就看你啦),随着修改解决方案名称也跟着变,还有个位置(都懂得,就不说了),好了后点确定,就出现让你改工作薄名,也可以点复制现有文档,这里我们让它是默认的,确认后就进入了工作界面,其中的excel界面占很大部份(excel2013中默认新建工作薄的工作表数是1,所以这里只显1张表),这里注意右侧的“解决方案资源管理器”窗口,三处要留意,下面我们要用到:vsto_c1(这是我们新建工程时填的名称)、sheet1.cs(由于只有一张表,所以只有一个,如果有sheet2则这里还有sheet2.cs)、thisworkbook.cs。图示中显示了进入thisworkbook.cs 代码界面的方法,进入sheet1.cs代码界面也雷同。
下面继续

点评

我在春节前也安装了VS2013,准备研究一下这个。看来还得学学C#才行呀。以后多交流啊。  发表于 2014-2-9 19:15

评分

参与人数 5 +134 金币 +80 收起 理由
无聊的疯子 + 24 感觉山哥分享
JLxiangwei + 30 + 30
windimi007 + 21 神马都是浮云
hoogle + 9 赞一个!
兰色幻想 + 50 很给力!加二级精华贴

查看全部评分

 楼主| 发表于 2014-2-7 11:28 | 显示全部楼层
本帖最后由 青城山苦丁茶 于 2014-2-7 11:34 编辑

一、初次使用vsto中的Worksheet_SelectionChange事件:
      现在来做第一个实例:点任一个格子,都显示出一个提示框,显示选中的格子是哪个。下面我们用单元格事件SelectionChange来解决:
      打开前面新建的工程vsto_c1,右击ThisWorkbook.cs-----查看代码进入代码编辑界面,会看到里面已经有一大堆东东了:
2.png
      在这一堆代码中找private void ThisWorkbook_Startup(object sender, System.EventArgs e),他的下面有一对{ }占了两行,在这两行间新增一行,输入this.SheetSelectionChange += 会提示你按tab键(实际上整个过程中每按一个键都有提示),这时按一下tab键后自动完成代码this.SheetSelectionChange += ThisWorkbook_SheetSelectionChange; 别动,再一下tab键,会再出现一段代码光标也到里面去了(下图显示了刚才键入的内容和自动生成的):
3.png
throw new NotImplementedException();改成MessageBox.Show (Target.Address);后点工具栏中的启动或按F5键,会自动启动excel,点单元格就会看到效果了。至此,第一个任务完成了!最终代码如下(只有红色的为添加的,其它都是系统自己原有的):
private void ThisWorkbook_Startup(object sender, System.EventArgs e)
        {
            this.SheetSelectionChange += ThisWorkbook_SheetSelectionChange;
        }
       void ThisWorkbook_SheetSelectionChange(object Sh, Excel.Range Target)
        {
            MessageBox.Show (Target.Address);//VBA为msgbox target.address
        }
        private void ThisWorkbook_Shutdown(object sender, System.EventArgs e)
        {
        }
      将其中的Target.Address改成Target.Address[0,1]、Target.Address[1,1] 、Target.Address[1,0]等情况,可看到不一样的显示形式,这与VBA中一样,不同的是VBA中为(),而此处为[]。同时这段代码与VBA还有点不同的是:多加几个sheet,随便在哪个sheet中点单元格都起作用。
      把这个实例再改一下,改得稍有点实用价值,为此将MessageBox.Show (Target.Address);改为以下代码(具体功能运行一下看):
Application.Cells.Interior.ColorIndex =0;
Target.EntireRow.Interior.ColorIndex = 8;
Target.EntireColumn.Interior.ColorIndex = 8;
第二三行也可换成下面几行:
int r = Target.Row;
int c = Target.Column;
Application.Rows[r].Interior.ColorIndex = 8;
Application.Columns[c].Interior.ColorIndex = 8;
      怎么样?与VBA差不多吧?去试下其它事件吧,如SheetChange等。提示:C#中同样有用于关闭和打开事件响应Application.EnableEvents = false与Application.EnableEvents = true,只是与VBA不同的是,不能用0代替false非0代替true。当然C#语言还有些规则:变量必须声明后才能用;一个语句是以;为结束符;代码(或代码段,如forif等)是放在一对{ }当中;区分大小写,如Rr是不同的;//为行注释,即//后面的内容为注释内容,要注释连续的多行时可用/* 需要注释的内容 */;等等。
      上面我们把事件代码写在thisworkbook.cs中,要是改到sheet1.cs中呢?试下看会怎样。只是如果写到sheet1.cs中事件代码稍有不同,是this.SelectionChange,作用范围也有变化哟
      留意:thisworkbook.cs中的
private void ThisWorkbook_Startup(object sender, System.EventArgs e)
        {
        }
是工作薄打开时就要执行的,代码就写在一对{}中,而
private void ThisWorkbook_Shutdown(object sender, System.EventArgs e)
        {
        }
是工作薄关闭时要执行的。Sheet1.cs中同样有雷同的Sheet1_Startup和Sheet1_Shutdown也一样。

下面继续
回复

使用道具 举报

 楼主| 发表于 2014-2-7 11:40 | 显示全部楼层
调好了,试运行通过了,就该发布了:
点菜单栏上的生成------发布,按步骤提示做就成了。
做好后,如果安装路径是CD,我们把生成的东西全拷到其它机子上,运行里面的安装,他会自动连到网上下相关文件安到机子中(有点耗时,看网速),完成后,运行就可以看到我们的成果了

下面继续以其它实例来展示,待续……

评分

参与人数 1 +9 收起 理由
hoogle + 9 很给力,期待后面的!

查看全部评分

回复

使用道具 举报

 楼主| 发表于 2014-2-7 12:42 | 显示全部楼层
本帖最后由 青城山苦丁茶 于 2014-2-9 13:42 编辑

      现在我们来做个自定义功能菜单。
      新建一工程VSTO_C2,右击VSTO_c2------添加-----新建项,选功能区(可视化设计器)  
2.gif
      默认为group1,可随意改,改的地方在右下边的属性label中,改一下,如my
      添加按钮:点最左边的工具箱-----button点两下就增加了一个按钮button1(同样可改,改为如first。而且可以给它加个图片,都在属性中),右击first----查看代码,则进入编制代码界面。编制代码界面同样已经有一大堆东东了。我们在其中的
private void Ribbon1_Load(object sender, RibbonUIEventArgs e)
        {

        }
中加代码,输入this.button1.Click +=按两次tab(和前面的事件一样操作)自动完成一些工作,再输入些东东,完成的结果如下:
private void Ribbon1_Load(object sender, RibbonUIEventArgs e)
        {
            this.button1.Click += button1_Click;
        }

void button1_Click(object sender, RibbonControlEventArgs e)
        {
            System.Windows.Forms.MessageBox.Show("Test");
        }
      运行一下,EXCEL中多了个“加载项”,点他,点一下first,就有提示框了。
      下面我们将这个按钮的功能实用化一点:将当前工作薄的所有表名写到当前工作表A1起的一列单元格中。右击sheet1.cs-----查看代码进入sheet1.cs的代码界面,添加一段代码(红色部份)
private void Sheet1_Startup(object sender, System.EventArgs e)
        {
        }
public void listsheetname()//VBA:public sub listsheetname()
        {
            int i = 0;
            Excel.Range rng = Application.get_Range("a1");  //VBA:set rng=range(“a1”)
            foreach (Excel.Worksheet sht in this.Application.Worksheets) //VBA:for each sht in worksheets
            {
                rng.get_Offset(i++, 0).Value = sht.Name; //VBA:rng.offset(i,0).value=sht.name:i=i+1
            }
        }

private void Sheet1_Shutdown(object sender, System.EventArgs e)
        {
        }
      然后再将前面写在ribbon1.cs中的代码改成:
void button1_Click(object sender, RibbonControlEventArgs e)
        {
            Globals.Sheet1.listsheetname(); //就改成这句
        }
      运行一下,多加几张sheet,看结果对不对。成了吧?


      列出所有表名的代码还可改成以下几种方式(只是为了多体现几种表示方法):
方法A:
int i = 1;
Excel.Range rng;
foreach(Excel.Worksheet sht in this.Application.Worksheets )
{
     rng = Application.get_Range("a" + i);
     rng.Value   = sht.Name;               
     i++;
}
方法B:
int i = 0; //此处的初值为0,所以下面为++i,与i++不同
foreach(Excel.Worksheet sht in this.Application.Worksheets )            
      Application.ActiveSheet.cells[++i,1]= sht.Name;  //由于循环体只有一句,{}可省
方法C:
for (int i = 1; i <= Application.Worksheets.Count; i++)
     Application.ActiveSheet.cells[i, 1] = Application.Worksheets.name;
方法D:显示数组的定义、应用。将名称先写进数组,再将数组写进单元格,用了resize、数组最大下标、数组转置
string[] ar = new string[Application.Worksheets.Count];
for (int i = 0; i < Application.Worksheets.Count; i++)
     ar = Application.Worksheets[i+1].name;            
Application.get_Range("a1").get_Resize(ar.GetUpperBound(0) + 1).Value =
Application.WorksheetFunction.Transpose(ar);

发布问题就不再说了,同上面。

待续……
回复

使用道具 举报

发表于 2014-2-7 14:54 | 显示全部楼层
这个有难度啊
回复

使用道具 举报

 楼主| 发表于 2014-2-7 16:21 | 显示全部楼层
本帖最后由 青城山苦丁茶 于 2014-2-7 16:23 编辑

有了初步的印象后,中断一下例子,先来看看C#操作EXCEL的一些方法,完了后再继续实例。

操作workbook(打开、新建、存储等等)
Excel.Workbook newWorkbook = this.Application.Workbooks.Add();//新增工作薄,vba:Set wb = Workbooks.Add


this.Application.Workbooks.Open(@"C:\Test\YourWorkbook.xlsx");
或this.Application.Workbooks.Open("C:\\Test\\YourWorkbook.xlsx"); //
打开指定路径下的工作薄,注意两者的区别,下同。

this
.Application.ActiveWorkbook.Close(false);//关闭活动工作薄,不提示是否保存



Excel.Workbook owb= this.Application.ActiveWorkbook ;//vba:set owb=activeworkbook
owb.Activate();或this.Application.Workbooks[owb.Name].Activate();//owb为活动工作薄
owb.Close(false);//关闭owb,不提示是否保存

this.Application.Workbooks[1].Activate();//激活所有打开的工作薄中的第一个


Excel.Workbook nwb = this.Application.Workbooks.Add();  
string fn = "aaa.xlsx";  //VBA:fn$=""aaa.xlsx""

nwb.SaveAs(fn);  //注意:如果带路径,同前面一样,\得为\\,否则在fn前加@;不带路径,则存到默认位置




待续……

回复

使用道具 举报

发表于 2014-2-8 17:21 | 显示全部楼层
感谢分享!
回复

使用道具 举报

发表于 2014-2-8 17:35 | 显示全部楼层
感觉在看天书,囧{:181:}

点评

照着步骤做不出来,还是什么呢?  发表于 2014-2-8 22:23
回复

使用道具 举报

发表于 2014-2-8 17:39 | 显示全部楼层
顶一个。
回复

使用道具 举报

 楼主| 发表于 2014-2-8 22:18 | 显示全部楼层
操作sheet:
this.Application.Worksheets.Add();添加一张sheet。与VBA中相同,支持带参数,如:
this.Application.Worksheets.Add(this.Application.Sheets[1],missing ,2,missing );与
this.Application.Worksheets.Add(Before:this.Application.Sheets[1],Count:2);相同,都是在最前面添加两张表

Application.ActiveWorkbook.Sheets[1].Copy();当前工作薄表1复制到一新建工作薄中            Application.ActiveWorkbook.Sheets[1].Copy(Application.ActiveWorkbook.Sheets[1]); 当前工作薄表1复制到表1的前面。
Application.ActiveWorkbook.Sheets[1].Copy(missing,Application.ActiveWorkbook.Sheets[1]); 当前工作薄表1复制到表1的后面。

this.Application.ActiveWorkbook.Sheets[1].Delete();删除工作表1,有提示框提示,如果不需要提示,加上Application.DisplayAlerts = false;只是别忘了删后要改回来,且在这种情况下被删的表不得为Activesheet.

this.Application.ActiveWorkbook.Sheets[1].Select();选择第一张表

this.Application.ActiveWorkbook.Sheets[1].Move(this.Application.ActiveWorkbook.Sheets[3]);移动工作表
this.Application.ActiveWorkbook.Sheets[1].Visible = 0;隐藏工作表,=-1显示,=2深度隐藏。这几个值同VBA


这么细了,怎么还觉得不清楚呢
费心写的,怎么反应却不怎么样呢?
如果这样,写下去还有什么意义呢?

评分

参与人数 1 +9 收起 理由
hoogle + 9 神马都是浮云

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|Excel精英培训 ( 豫ICP备11015029号 )

GMT+8, 2024-5-1 04:22 , Processed in 0.335361 second(s), 11 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表