Excel AddIn 开发(二)
来源:互联网 发布:燃情岁月知乎 编辑:程序博客网 时间:2024/05/23 11:49
客户有个简单的需求,每次在excel中操作的东西要保存下来,以便于下一次打开时,好多东西就可以复用。比如一张简单报表,表中保存特定测点的实时值。每次打开用户就可以看到自己关心的测点,刷新下就可以获取实时数据。(用过PI-DataLink的肯定一下子就明白了。)
刚开始一看,这个需求不难呀,存东西是office的专长。具体做的时候,问题来了。每个格子中存的东西不是固定的文本内容,而是从数据库中获取的动态数据,客户不要看 之前的数据,他要看到之前操作的内容,包括数据库连接信息,数据库测点信息等等。
问题:如何存相关的操作信息,存在哪里?在展开问题之前,先学点基础知识。
Excle中的基本操作都需要强大的Range对象。离开对Range的深入学习,具体的技巧都是无源之水
下面的信息来自于网络:
Range 对象是 Excel 应用程序中最经常使用的对象;在操作 Excel 内的任何区域之前,都需要将其表示为一个 Range 对象,然后使用该 Range 对象的方法和属性。一个 Range 对象代表一个单元格、一行、一列、包含一个或者更多单元块(可以是连续的单元格,也可以式不连续的单元格)的选定单元格,甚至是多个工作表上的一组单元格。在代码中引用范围。
Address 属性:这个属性返回范围坐标的字符串,坐标以下面几种格式之一表示,包括:“$A$1”(单元格在位置 A1)、“$1”(在工作表的第一行)和“$A$1:$C$5”(范围包括介于 A1 和 C5 之间矩形内的所有单元格)。“$”表示绝对坐标(而非相对坐标)。
Excel.Worksheet ws = (Excel.Worksheet)ThisWorkbook.Worksheets[1];
Excel.Range rng;
rng = ThisApplication.ActiveCell;
rng = ws.get_Range("A1", Type.Missing);//使用对象的 Range 属性指定一个区域
rng = ws.get_Range("A1:B12", Type.Missing);//使用对象的 Range 属性指定一个区域
rng = (Excel.Range)ws.Cells[1, 1];//使用工作表的 Cells 属性,指定单个行和列值
rng = ThisApplication.Range("SomeRangeName", Type.Missing);//引用一个命名范围
rng = ws.Range("A1", "C5")//直接引用范围的 Cells、Rows 或 Columns 属性,作用相同
rng = ws.Range("A1", "C5").Cellsrng = ws.Range("A1", "C5").Rowsrng = ws.Range("A1", "C5").Columnsrng = (Excel.Range)ws.Rows[1, Type.Missing];//引用特定行或特定列或行和列的范围
rng = (Excel.Range)ws.Rows["1:3", Type.Missing];rng = (Excel.Range)ws.Columns[3, Type.Missing];//Application 对象的 Selection 属性返回与选定单元格对应的范围
rng = (Excel.Range)ThisApplication.Selection;//创建一个包含其他两个合并范围的范围(在引号内指定两个范围,并用逗号隔开)
rng = ThisApplication.get_Range("A1:D4, F2:G5", Type.Missing);//与后三行效果相同
rng1 = ThisApplication.get_Range("A1", "D4");
rng2 = ThisApplication.get_Range("F2", "G5");
rng = ThisApplication.Union(rng1, rng2, Type.Missing, Type.Missing, ……);//创建一个引用其他两个范围重叠部分的范围(在引号内指定两个范围,并不使用分隔符)
rng = ThisApplication.get_Range("A1:D16 B2:F14", Type.Missing);//与后三行效果相同
rng1 = ThisApplication.get_Range("A1", "D16");
rng2 = ThisApplication.get_Range("B2", "F14");
rng = ThisApplication.Intersect(rng1, rng2,Type.Missing, Type.Missing, Type.Missing, Type.Missing,……);//使用范围的 Offset 属性取得相对于初始范围的一个偏移
rng = (Excel.Range) ws.Cells[1, 1];
for (int i = 1; i <= 5; i++)
{
rng.get_Offset(i, 0).Value2 = i.ToString();
}//使用范围的 CurrentRegion 属性取得一个代表当前区域的范围,这个当前区域由最近的空行和列限定,即连接在一起的单元格
ThisApplication.get_Range("C3", Type.Missing).CurrentRegion.Font.Bold = true;//使用范围的 Areas 属性取得范围集合,其中每个范围对应于范围内容的一个区域
rng = ThisApplication.get_Range("Test", Type.Missing);
for (int i = 1; i <= rng.Areas.Count; i++)
{
MessageBox.Show( rng.Areas[i].get_Address(Type.Missing, Type.Missing, Excel.XlReferenceStyle.xlA1, Type.Missing, Type.Missing));
}
/使用 End 属性,以及一个 XlDirection 枚举值(xlUp、xlToRight、xlToLeft、xlDown)来取得一个代表区域末端单元格的范围(即四个方向上离该选中范围最远的单元格)
Excel.Range rngLeft, rngRight, rngUp, rngDown;
rng = (Excel.Range) ThisApplication.Selection;
rngRight = rng.get_End(Excel.XlDirection.xlToRight);
rngLeft = rng.get_End(Excel.XlDirection.xlToLeft);
rngUp = rng.get_End(Excel.XlDirection.xlUp);
rngDown = rng.get_End(Excel.XlDirection.xlDown);//使用 EntireRow 或 EntireColumn 属性引用包含特定范围的行或列
rng = ThisApplication.get_Range("Test", Type.Missing);
rng.Areas[2].EntireRow.Font.Bold = true;在代码中操作范围。
自动填充:AutoFill查找:Find排序:SortCells 获取一个 Range 对象,该对象表示工作表上的所有单元格(不仅仅是当前正在使用的单元格)。Cells[行,列]Columns 获取一个表示工作表上的所有列的 Range 对象Rows 获取一个表示工作表上的所有行的 Range 对象.
贴了上述代码,是为了把Range的基本操作做个交代。详细的肯定以MSDN或以微软官方文档为准。
学完Range,再回到开头的问题。
要存下上次的操作及参数,关键点在Range.Formula。
我们在Excel中某个格子中输入 =SUM(A1:A2),然后回车。
可以看到C3格子中显示的计算结果,上面的fx显示的是 =SUM(A1:A2)。这个时候保存该sheet,就保存了使用的公式,C3显示的最终结果不重要了,
重要的是保存了公式。
以此类推,我们要保存的东西就是要放在Formula中,后续的事情水到渠成。
调用的函数哪里来?SUM是Excel内置的,我们需要的Excel当然没有,这就要用UDF(User Define Function)。UDF的开发,在上一篇中有所 描述。
不涉及效率问题,使用VSTO C#开发当然没有问题。
看一下基类说明:
public abstract class UDFBase { /// <summary> /// 解决在某些机器的Excel提示找不到mscoree.dll的问题 /// 这里在注册表中将该dll的路径注册进去,当使用regasm注册该类库为com组件 /// 时会调用该方法 /// </summary> /// <param name="type"></param> [ComRegisterFunctionAttribute] public static void RegisterFunction(Type type) { Registry.ClassesRoot.CreateSubKey( GetSubKeyName(type, "Programmable")); RegistryKey key = Registry.ClassesRoot.OpenSubKey( GetSubKeyName(type, "InprocServer32"), true); key.SetValue("", System.Environment.SystemDirectory + @"\mscoree.dll", RegistryValueKind.String); } [ComUnregisterFunctionAttribute] public static void UnregisterFunction(Type type) { Registry.ClassesRoot.DeleteSubKey( GetSubKeyName(type, "Programmable"), false); } private static string GetSubKeyName(Type type, string subKeyName) { return string.Format("CLSID\\{{{0}}}\\{1}", type.GUID.ToString().ToUpper(), subKeyName); } /// <summary> /// 将Object类的四个公共方法隐藏 /// 否则将会出现在Excel的UDF函数中 /// </summary> /// <returns></returns> [ComVisible(false)] public override string ToString() { return base.ToString(); } [ComVisible(false)] public override bool Equals(object obj) { return base.Equals(obj); } [ComVisible(false)] public override int GetHashCode() { return base.GetHashCode(); } }
在基类的基础上,开发自己的UDF
[Guid("E458BA70-3F9A-409E-9832-F7BDAF71D554")] [ClassInterface(ClassInterfaceType.AutoDual)] [ComVisible(true)] public class RDataLinkFunc : UDFBase { // UDF Functions ... }
- Excel AddIn 开发(二)
- Excel AddIn 开发(一)
- Excel AddIn 开发(三)
- vb.net 开发 excel Addin学习(1)---- 准备
- EXCEL ADDIN 学习(一)
- 【C#】23. Excel Addin 开发(1)
- Excel addin
- Excel addin
- vb.net 开发 excel Addin学习(2)---- 工具栏 和 菜单
- vb.net 开发 excel Addin学习(3)---- 菜单 的 操作
- vb.net 开发 excel Addin 学习(4)---- 菜单 的 及联及图标
- vb.net 开发 excel Addin 学习(5)---- 几个小问题
- VB.Net开发Excel COM AddIn一个示例
- 使用VS2008进行VSTO-Addin实战开发-创建自己的工具栏(二)
- ArcGIS AddIn开发系列问题(一)
- VS-Addin的开发
- arcgis addin开发初探
- Arcgis AddIn开发笔记
- Apache和Nginx下php $_SERVER['SERVER_NAME'] 变量的区别
- vi命令
- ELF格式的重定位原理分析
- strtol()详解
- POJ 3925 Minimal Ratio Tree
- Excel AddIn 开发(二)
- 华为S5700配置
- easyui 分页控件 显示页码 宽度问题
- android 手机定位并获取城市信息
- MFC中CvvImage类的应用
- 兼容主流浏览器 的html 视频播放器
- PAT A 1014. Waiting in Line (30)
- linux环境下maven安装与配置
- 用DPM(Deformable Part Model,voc-release3.1)算法在INRIA数据集上训练自己的人体检测模型