C#如何定制Excel界面并实现与数据库交互

时间:2021-10-09 08:14:11

  Excel是微软办公套装软件的一个重要的组成部分,它可以进行各种数据的处理、统计分析和辅助决策操作,广泛地应用于管理、统计财经、金融等众多领域。(另外,Excel还是伦敦一所会展中心的名称)。.NET可以创建Excel Add-In对Excel进行功能扩展,这些扩展的功能包括自定义用户函数,自定义UI,与数据库进行数据交互等。

一 主要的Excel开发方式

  1 VBA 

VBA是一种Visual Basic的宏语言,它是最早的Office提供定制化的一种解决方案,VBA是VB的一个子集,和Visual Basic不同,VBA是一种宿主型语言,无论是专业的开发人员,还是刚入门的非开发人员,都可以利用VBA完成简单或复杂的需求。

  2 Excel Addin

Excel Addin,就像Visual Studio外接插件一样,也可以使用一些技术为Office开发一些插件。对VBA的一些问题,一些专业的开发人员,可以使用 VisualBasic或者VisualC++等工具来引用Office的一些dll,来针对Office进行开发。开发的时候将dll注册为com组 件,并在注册表里面进行注册,这样就可以在Excel里直接调用这些插件。

  3 VSTO (Visual Studio Tools for Office)

VSTO主要是对Office的一些dll进行了.NET封装,使得我们可以使用.NET上的语言来方便的对Office的一些方法进行调用。所 以,Office开发跨入了一个新的时代,开发人员可以使用更加高级的语言和熟悉的技术来更容易的进行Office开发。 对于企业及的应用和开发,VSTO或许是首要选择,他极大地扩展了Office应用程序的能力,使用.NET平台支持的编程语言,能够直接访问.NET上面众多的类库。具有较好的安全机制。简化了Office插件的开发和部署。

  4 XLL

XLL是Excel的一种外接应用程序,他使用C和C++开发,程序通过调用Excel暴漏的C接口来实现扩展功能。这种方式开发的应用程序效率高,但是难度大,对开发者自身的要求较高。开源项目Excel-DNA就是使用XLL技术开发的,能够帮助.NET 开发人员来极大地简化RTD函数,同步、异步UDF函数的编写和开发。

  5 OpenXML

如果用户没有安装Excel应用程序,或者在服务器端需要动态生成Excel文件的时候。我们可能需要直接读取或者生成Excel文件,这种情况下,如果要对Excel文件进行各种定制化开发的话,建议使用OpenXML。NPOI开源项目可以直接读写Excel文件,而且兼容多个版本。

二 使用Excel Add-In构建扩展

  开发环境: 操作系统为Windows Server 2008R2 x64;Excel为Excel 2010 x64;开发工具为Visual Studio 2012旗舰版x64;数据库为SQL Server 2008R2 x64.

  1 程序结构

  用Visual Studio 2012新建一个ExcelAddInDemo的Excel Add-In项目,并添加若干文件,程序结构如下图:

C#如何定制Excel界面并实现与数据库交互

  其中,RibbonAddIn可以定制2010的UI面板,SqlHelper.cs是一个简单的数据库访问帮助类,UClog.cs,UCPaneLeft.cs,UCTaskGrid.cs,UCTaskPane.cs都为添加的自定义控件,并通过程序添加到EXCEL界面中.运行起来的界面如下:

C#如何定制Excel界面并实现与数据库交互

  程序可以通过在Excel界面中输入ID,First,Last,Email的值(对应标签的后一个单元格),单击用户列表面板上的保存按钮,将数据保存到数据库中.

  2 RibbonAddIn设计

  我们通过RibbonAddIn.cs给Excel的Ribbon添加了一个名为CUMT的插件.RibbonAddIn面板可以通过工具条控件方便的拖放到设计界面上.RibbonAddIn.cs的属性设置如下图所示:

C#如何定制Excel界面并实现与数据库交互

  后台代码如下:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Tools.Ribbon; namespace ExcelAddInDemo
{
public partial class RibbonAddIn
{ private void RibbonAddIn_Load(object sender, RibbonUIEventArgs e)
{ } private void btnAbout_Click(object sender, RibbonControlEventArgs e)
{
System.Windows.Forms.MessageBox.Show("JackWangCUMT!");
} private void btnShow_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn._MyCustomTaskPane != null)
{
Globals.ThisAddIn._MyCustomTaskPane.Visible = true;
}
} private void btnHide_Click(object sender, RibbonControlEventArgs e)
{
if (Globals.ThisAddIn._MyCustomTaskPane != null)
{
Globals.ThisAddIn._MyCustomTaskPane.Visible = false;
}
}
}
}

  3 ThisAddIn逻辑编写

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Excel = Microsoft.Office.Interop.Excel;
namespace ExcelAddInDemo
{
using Microsoft.Office.Tools;
public partial class ThisAddIn
{
public CustomTaskPane _MyCustomTaskPane = null; private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
UCTaskPane taskPane = new UCTaskPane();
_MyCustomTaskPane = this.CustomTaskPanes.Add(taskPane, "我的任务面板");
_MyCustomTaskPane.Width = ;//height有问题,此处width ==height
_MyCustomTaskPane.Visible = true;
_MyCustomTaskPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionTop; UCPaneLeft panLeft = new UCPaneLeft();
_MyCustomTaskPane = this.CustomTaskPanes.Add(panLeft, "组织");
_MyCustomTaskPane.Width = ;
_MyCustomTaskPane.Visible = true;
_MyCustomTaskPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionLeft; UCTaskGrid panRight = new UCTaskGrid();
_MyCustomTaskPane = this.CustomTaskPanes.Add(panRight, "用户列表");
_MyCustomTaskPane.Width = ;
_MyCustomTaskPane.Visible = true;
_MyCustomTaskPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionRight; UCLog panLog = new UCLog();
_MyCustomTaskPane = this.CustomTaskPanes.Add(panLog, "日志列表");
_MyCustomTaskPane.Width = ;
_MyCustomTaskPane.Visible = true;
_MyCustomTaskPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionBottom; //Hook into the workbook open event
//This is because Office doesn't always have a document ready when this method is run
this.Application.WorkbookActivate += Application_WorkbookActivate;
//test
//this.Application.SheetSelectionChange += Application_SheetSelectionChange;
} void Application_SheetSelectionChange(object Sh, Excel.Range Target)
{
if (this.Application != null)
{
this.Application.Caption = this.Application.ActiveCell.Address.ToString();//$A$1
//+ this.Application.ActiveCell.AddressLocal.ToString();//$A$1
//this.Application.ActiveCell.Formula = "=sum(1+2)"; }
} void Application_WorkbookActivate(Excel.Workbook Wb)
{
//using Microsoft.Office.Tools.Excel 和 using Microsoft.Office.Interop.Excel 都有worksheet等,容易混淆
//string path = this.Application.ActiveWorkbook.FullName;
Excel._Worksheet ws = (Excel._Worksheet)this.Application.ActiveWorkbook.ActiveSheet;
ws.Cells[, ] = "ID2";
//如何设置只读等有待研究
int r=,c=;
//((Excel.Range)ws.Cells[r, c]).NumberFormat = format;
((Excel.Range)ws.Cells[r, c]).Value2 = "ID";
((Excel.Range)ws.Cells[r, c]).Interior.Color =System.Drawing. ColorTranslator.ToOle(System.Drawing.Color.Red);
//((Excel.Range)ws.Cells[r, c]).Style.Name = "Normal";
((Excel.Range)ws.Cells[r, c]).Style.Font.Bold = true; #region format
((Microsoft.Office.Interop.Excel.Range)ws.get_Range("A2", "E10")).Font.Bold = true;
((Microsoft.Office.Interop.Excel.Range)ws.get_Range("A2", "E10")).Font.Italic = true;
((Microsoft.Office.Interop.Excel.Range)ws.get_Range("A2", "E10")).Font.Color = System.Drawing.Color.FromArgb(, , ).ToArgb();
((Microsoft.Office.Interop.Excel.Range)ws.get_Range("A2", "E10")).Font.Name = "Calibri";
((Microsoft.Office.Interop.Excel.Range)ws.get_Range("A2", "E10")).Font.Size = ; //border
Excel.Range range = ((Microsoft.Office.Interop.Excel.Range)ws.get_Range("B2", "E3"));
Excel. Borders border = range.Borders;
border[Excel.XlBordersIndex.xlEdgeBottom].LineStyle =Excel. XlLineStyle.xlContinuous;
border.Weight = 2d;
border[Excel.XlBordersIndex.xlEdgeTop].LineStyle = Excel.XlLineStyle.xlContinuous;
border[Excel.XlBordersIndex.xlEdgeLeft].LineStyle = Excel.XlLineStyle.xlContinuous;
border[Excel.XlBordersIndex.xlEdgeRight].LineStyle = Excel.XlLineStyle.xlContinuous;
#endregion
ws.Cells[, ] = "First";
ws.Cells[, ] = "Last";
ws.Cells[, ] = "Email";
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
} #region VSTO 生成的代码 /// <summary>
/// 设计器支持所需的方法 - 不要
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
} #endregion
}
}

  ThisAddIn_Startup事件中,初始化四个面板,并对其基本属性进行设置,停靠在上的面板我设置其Height无效,改成Width后其效果和Height预期的一样(不知道这个底层开发人员是怎么想的,哈哈!)另外 Excel._Worksheet ws = (Excel._Worksheet)this.Application.ActiveWorkbook.ActiveSheet;是非常关键的一句,我这里足足折腾了很久,原因是using Microsoft.Office.Tools.Excel 和 using Microsoft.Office.Interop.Excel 都有worksheet元素,结构混淆了,运行时老是获取不到Excel的ActiveWorkbook.

  4 UCTaskGrid设计

  UCTaskGrid是一个用户控件,包含一个工具条和一个dataGridView1控件,其设计界面如下:

C#如何定制Excel界面并实现与数据库交互

  后台代码如下:

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms; namespace ExcelAddInDemo
{
using Excel = Microsoft.Office.Interop.Excel;
public partial class UCTaskGrid : UserControl
{
public UCTaskGrid()
{
InitializeComponent();
} private void UCTaskGrid_Load(object sender, EventArgs e)
{
//load data
System.Data.DataTable dt = SqlHelper.getDateTable("select * from ACT_ID_USER", null);
this.dataGridView1.DataSource = dt;
} private void 保存SToolStripButton_Click(object sender, EventArgs e)
{
//核心代码,获取当前的worksheet
Excel._Worksheet ws = (Excel._Worksheet)Globals.ThisAddIn.Application.ActiveWorkbook.ActiveSheet;
string name = ws.Name;
string ID = ((string)(ws.Cells[, ] as Excel.Range).Value).ToString();
string First = ((string)(ws.Cells[, ] as Excel.Range).Value).ToString();
string Last = ((string)(ws.Cells[, ] as Excel.Range).Value).ToString();
string Email = ((string)(ws.Cells[, ] as Excel.Range).Value).ToString();
string sql = string.Format("insert into ACT_ID_USER ([ID_],[FIRST_],[LAST_],[EMAIL_]) values('{0}','{1}','{2}','{3}')", ID, First, Last, Email);
int rows= SqlHelper.ExecuteNonQuery(SqlHelper.ConnectionStringLocalTransaction, System.Data.CommandType.Text,sql,null);
if (rows == )
{
System.Windows.Forms.MessageBox.Show("saved");
}
else
{
System.Windows.Forms.MessageBox.Show("error");
} } private void 打开OToolStripButton_Click(object sender, EventArgs e)
{
//refresh
System.Data.DataTable dt = SqlHelper.getDateTable("select * from ACT_ID_USER", null);
this.dataGridView1.DataSource = dt;
}
}
}

  5 Add-In强签名

  通过设置程序的属性中的签名页,让VS自动生成一个签名即可(需设置密码)

C#如何定制Excel界面并实现与数据库交互

三 最终效果演示

  为了直观的展示,看下面的动画:

C#如何定制Excel界面并实现与数据库交互

四 猜想 Excel Service

  现在功能很强大的Excel服务器,其中一个亮点就是在Excel中进行界面设计和数据操作,然后就数据持久化到数据库中,那么我的猜想是,能不能通过AddIn的方式实现一个excel service功能呢,将界面设计序列化保存到数据库中,并给一个路径(唯一),但用户单击菜单(确定了路径)后将界面设计呈现到excel中,然后用户操作完成后,通过后台程序将数据保存到数据库中.

C#如何定制Excel界面并实现与数据库交互的更多相关文章

  1. 案例分享:Qt西门子机床人机界面以及数据看板定制(西门子通讯,mysql数据库,生产信息,参数信息,信息化看板,权限控制,播放器,二维图表,参数调试界面)

    若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/118685521 长期持续带来更多项目与技术分享 ...

  2. Inno setup定制安装界面

    Innosetup功能很强大,可以通过它提供的Wizard接口来定制界面,但我对PASCAL语言不熟悉,也不清楚通过那种接口可改动的范围有多大,最后做出来的效果是否好,所以选择了通过一个DLL来实现我 ...

  3. Android—— ListView 的简单用法及定制ListView界面

    一.ListView的简单用法 2. 训练目标 1) 掌握 ListView 控件的使用 2) 掌握 Adapter 桥梁的作用 实现步骤: 1)首先新建一个项目, 并让ADT 自动帮我们创建好活动. ...

  4. 利用MFC实现浏览器的定制与扩展(JavaScript与C&plus;&plus;交互)

    原文地址:http://www.vckbase.com/document/viewdoc/?id=1486 浏览器的定制与扩展       作者:李汉鹏 下载源代 码  本文分如下章节: 前 言 在 ...

  5. ASP&period;NET Excel导入到SQL Server数据库

    本文转自:http://www.cnblogs.com/lhking/archive/2009/06/08/1499002.html 提供把Excel里的数据导入到SQL Server 数据库,前提是 ...

  6. OleContainer操作Excel以二进制方式读写数据库

    需求源头:OleContainer操作Excel,想把Excel以二进制方式存入数据库,并且以二进制方式读取存入流:Procedure SaveToStream(ADOTable1: TAdoTabl ...

  7. C&num;将Excel数据表导入SQL数据库的两种方法(转)

    最近用写个winform程序想用excel 文件导入数据库中,网上寻求办法,找到了这个经过尝试可以使用. 方法一: 实现在c#中可高效的将excel数据导入到sqlserver数据库中,很多人通过循环 ...

  8. NodeJs之EXCEL文件导入导出MongoDB数据库数据

    NodeJs之EXCEL文件导入导出MongoDB数据库数据 一,介绍与需求 1.1,介绍 (1),node-xlsx : 基于Node.js解析excel文件数据及生成excel文件. (2),ex ...

  9. AndroidStudio制作个人资料界面模块以及SQLite数据库的使用

    前言 大家好,给大家带来AndroidStudio制作个人资料界面模块以及SQLite数据库的使用的概述,希望你们喜欢 学习目标 掌握SQLite数据库的使用,能够实现用数据库来保存用户的信息: 学会 ...

随机推荐

  1. save&lpar;&rpar;&comma;saveorupdate&lpar;&rpar;还有marqe&lpar;&rpar;

    所有这三个方法,也就是save().saveOrUpdate()和persist()都是用于将对象保存到数据库中的方法,但其中有些细微的差别.例如,save()只能INSERT记录,但是saveOrU ...

  2. 项目新的需求,网页的自适应交付&sol;响应式交付 Responsive&sol;Adaptive Delivery

    网页为什么要做自适应交付,皆因现在移动设备大行其道,现在是移动互联网时代,以IOS及Android为首的各种移动终端已经遍地开花. 当人家用380px的iphone打开你的网页时,你总不能显示个102 ...

  3. Java高级之虚拟机加载机制

    本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 1.0版本:2016-05-21 SubClass!! 执行结果说明一个问题:子类调用父类变量的时候 ...

  4. HDU 5164Matching on Array&lpar;AC自动机&rpar;

    这是BC上的一道题,当时比赛没有做,回头看看题解,说是AC自动机,想着没有写过AC自动机,于是便试着抄抄白书的模板,硬是搞了我数个小时2000ms时限1800过了= = ! 这里就直接贴上BC的结题报 ...

  5. css div 垂直居中

    参考:http://css-tricks.com/centering-in-the-unknown/ <style> .valign { font-size: 0px;/* clear s ...

  6. boa安装

    Boa 下载地址:http://www.boa.org/boa-0.94.13.tar.gz 1.解压生成Makefile tar xzf boa-0.94.13.tar.gz #解压 cd boa- ...

  7. cdn是什么和作用有些

    内容分发网络其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快.更稳定.通过在网络各处放置节点服务器所构 成的在现有的互联网基础之上的一层智能虚拟网络,CDN系 ...

  8. HeadFirst设计模式读书笔记&lpar;3&rpar;-装饰者模式&lpar;Decorator Pattern&rpar;

    装饰者模式:动态地将责任附件到对象上.若要扩展功能,装饰者提东了比继承更有弹性的替代方案. 装饰者和被装饰对象有相同的超类型 你可以用一个或者多个装饰者包装一个对象. 既然装饰者和被装饰对象有相同的超 ...

  9. jQuery实现拼图小游戏

    小熊维尼拼图                                                                                    2017-07-23 ...

  10. Dos命令的巧用

    豪华绚丽的Windows让人们把DOS抛到遥远的记忆角落,然而,真正有价值的东西不会轻易退出历史的舞台.很多人都已经习惯于 Windows的图形化用户界面,熟不知古老的DOS命令却可以轻易的办到很多事 ...