C# ExcelAddIn 开发笔记

好久都没有写博客了,最近真的是太忙了,接手公司要做的一个小的新的项目,从接触认识到一个新东西,再到自己琢磨研究,最终结合公司业务把整个excel插件项目完成,还是有一点点成就感。以下是项目中基本上大致所有总结的Points:

1.ADO.NET数据库操作,当然效率还是不是很高,初级水平数据量不是很大,先使用这个。

2.ThisAddin包含的对象,当前活动sheet: Excel.Worksheet worksheet = (Excel.Worksheet)Globals.ThisAddIn.Application.ActiveSheet;

3.excel range对象的各种属性及方法,如赋值,隐藏,筛选,清除,添加公式等等。

------------------------------------------------------------------------------------------

这里面有个很费劲的东西研究了一上午:”excel工作表的保护“,首先要解除锁定,然后对于要保护的range锁定以后再保护。

即用户在编辑excel的时候不允许编辑公式列。大家可以参考excelhome论坛多学习一下,虽然里面很多都是VBA的内容,翻译到C#相信不难。

-----------------------------------------------------------------------------------------------------------------------------------------

4.WINFORM窗体回传值,使用委托,不限于窗体子父窗体传值,很好用。

5.backgroundWorker1组件使用,达到后台下载或回传到数据库操作中,不允许界面操作。

Ribbon的设计器以及业务逻辑:

点击登陆按钮,判断当前sheet是否可用此插件,选择相应登陆条件(数据源从数据里选出的datatable),并获取当前AD域用户值,判断权限OK之后,回传到当前Ribbon界面。以备接下来的业务应用。每次登陆之后自动清空当前SHEET的特定内容。

点击下载按钮(未登陆不可用)公式列自动初始化excel,从DB->excel,做好excel列字段与DB表字段Mapping之后,使用二维数组对RANGE赋值,效率很高。

<下载和上传包括两个表的更新插入,Master表用于保存对于模板内的一些备注和表头等信息>

用户在相应登陆条件下编辑excel。

点击上传按钮(未登陆不可用)excel->DB,判断excel相应字段是否符合要求,NO->提示当前NOcell的行列数,修改之后上传。

      

以下是excel模板:

以上是大致业务逻辑。

接下来针对基本大致逻辑的部分代码,删去了部分业务,与大家分享。

DB->excel

protected void Fill(System.Data.DataTable dt, int rowStart, int colStart, bool isFormat, int digit)
        {
            int p = 50000;
            for (int beginIndex = 0; beginIndex < dt.Rows.Count; beginIndex += p)
            {
                int endIndex = dt.Rows.Count - 1;
                if (beginIndex + p < dt.Rows.Count)
                {
                    endIndex = beginIndex + p - 1;
                }
                object[,] arr = new object[endIndex - beginIndex + 1, dt.Columns.Count];
                for (int i = beginIndex; i <= endIndex; i++)
                {
                    for (int j = 0; j < dt.Columns.Count; j++)
                    {
                        arr[i - beginIndex, j] = dt.Rows[i][j].ToString().Replace("=", "");
                    }
                }
                Range range = sheet.get_Range(sheet.Cells[rowStart + beginIndex + 1, colStart + 1], sheet.Cells[rowStart + endIndex + 1, colStart + dt.Columns.Count]);
                range.Value2 = arr;
                range.Borders.LineStyle = XlLineStyle.xlContinuous;
                if (isFormat)
                {
                    string strDigit = string.Empty;
                    for (int k = 0; k < digit; k++)
                    {
                        strDigit += "0";
                    }
                    if (string.IsNullOrEmpty(strDigit))
                    {
                        range.NumberFormat = "#,##0.00";
                    }
                    else
                    {
                        range.NumberFormat = "#,##0." + strDigit;
                    }
                }
                else
                {
                    range.NumberFormat = "#,##0";
                }
            }
        }

range的各种基本属性:

 range.EntireColumn.Hidden = true;//隐藏列
        /// <summary>
        /// 设置标题行样式,红底
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="sheet"></param>
        /// <param name="rowCount">设置的行数</param>
        public void SetTitleStyle(System.Data.DataTable dt, Excel.Worksheet sheet, int rowCount)
        {
            if (dt.Rows.Count <= 0 || dt.Columns.Count <= 0)
            {
                return;
            }
            rngTemp = sheet.get_Range(sheet.Cells[startRowIndex + 1, startColIndex + 1], sheet.Cells[startRowIndex + 1, startColIndex + dt.Columns.Count]);
            rngTemp.Interior.ColorIndex = 30;
            rngTemp.Font.ColorIndex = 2;
            rngTemp.Font.Bold = 1;
        }
//=====================================

            if (worksheet.ProtectContents)//如果被保护则解除保护
            {
                worksheet.Unprotect("MyPassword");//之前下载过,删除之前要设置不保护
            }
            Excel.Range range = (Excel.Range)worksheet.get_Range((Excel.Range)worksheet.Cells[startRow, startColumn], (Excel.Range)worksheet.Cells[endRow, endColumn]);
            range.Select();//选择要清除的range
            if (IsDeleteEntireRow)
            {//是否整行删除
                range.EntireRow.Delete(Excel.XlDeleteShiftDirection.xlShiftUp);
            }
            else
            {
                //range.Delete(Excel.XlDeleteShiftDirection.xlShiftUp);
                range2.Cells.ClearContents();
                range.Cells.ClearContents();//只清除值
                //定位到第一个单元格
                Excel.Range range3 = worksheet.get_Range(worksheet.Cells[11, 1], worksheet.Cells[11, 1]);
                range3.Activate();
            }

获取当前域及用户名:

        private string domainName = System.Environment.UserDomainName;//获取当前AD域
        private string domainUserName = System.Environment.UserName;//获取当前域用户名

设置公式及保护:

                    Excel.Range range2 = worksheet.get_Range(worksheet.Cells[i, 5], worksheet.Cells[i, 5]);
                    if (worksheet.ProtectContents)//如果被保护则解除保护
                    {
                        worksheet.Unprotect("MyPassword");//之前下载过,删除之前要设置不保护
                    }
                    range2.Formula = "=B" + i + "+C" + i + "+D" + i;
                    range2.Locked = false;
                    if (IfProtected)
                    {
                        range2.Locked = true;
                    }
...

 worksheet.Protect("MyPassword", Type.Missing, Type.Missing, Type.Missing,
                                                    Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                                                    Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                                                    Type.Missing, Type.Missing, Type.Missing, Type.Missing);

大致就先这样吧,工作又来了,,,加油!

Fighting~~~~~~~~~~~~

时间: 2024-10-22 03:19:24

C# ExcelAddIn 开发笔记的相关文章

张高兴的 Windows 10 IoT 开发笔记:RTC 时钟模块 DS3231

原文:张高兴的 Windows 10 IoT 开发笔记:RTC 时钟模块 DS3231 GitHub:https://github.com/ZhangGaoxing/windows-iot-demo/tree/master/DS3231 注意:不包含闹钟设置

Android开发笔记(一百零三)地图与定位SDK

集成地图SDK 国内常用的地图SDK就是百度和高德了,二者的用法大同小异,可按照官网上的开发指南一步步来.下面是我在集成地图SDK时遇到的问题说明: 1.点击基本地图功能选项,不能打开地图,弹出"key验证出错!请在AndroidManifest.xml文件中检查key设置的"的红色字提示.查看日志提示"galaxy lib host missing meta-data,make sure you know the right way to integrate galaxy&

微信订阅号开发笔记(二)

微信开发的流程其实很简单 o(∩_∩)o 哈哈!在微信网站的编辑操作 额,就不说了.虽然有人问过.下面是我的微信开发过程,简单记录下. 成为开发者 材料:1.自己的服务器资源,百度的BAE,新浪的SAE都不错. 2.懂那么点编程语言. 3.注册微信公众号. 上面的都有了之后,就可以自己动手开发了.哇咔咔,好兴奋.有木有. 在登录进去之后,怎么成为开发者?不知道,自己看去. 开始coding吧. 1.验证 if (! empty ( $_GET ['echostr'] ) && ! empt

微信订阅号开发笔记(三)

1.接收语音识别结果 if($msgType=="voice"){ //收到语音消息 //MediaId 语音消息媒体id,可以调用多媒体文件下载接口拉取数据. //Format 语音格式,如amr,speex等 $format = $postObj->Format; $mediaId = $postObj->MediaId; //开通语音识别功能,用户每次发送语音给公众号时,微信会在推送的语音消息XML数据包中,增加一个Recongnition字段. //注:由于客户端缓

微信订阅号开发笔记(四)

1.创建菜单 //创建菜单 public function createMenu(){ $url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token="; $url.=$this->getacctoken(); //目前自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单.一级菜单最多4个汉字, //二级菜单最多7个汉字,多出来的部分将会以"..."代替.请注意,创建自定义菜单

Swift开发笔记

Swift开发笔记(一) 刚开始接触XCode时,整个操作逻辑与Android Studio.Visual Studio等是完全不同的,因此本文围绕IOS中控件的设置.事件的注册来简单的了解IOS开发 1.新建一个Xcode项目,项目目录大致如图: 2.在Main.storyboard添加控件 首先要显示右侧的工具栏(Utilities),之后选择显示Object Library,就可以找到常用的一些控件了,然后添加几个控件到界面中 3.将控件和ViewController进行关联 此时要将Ed

张高兴的 Xamarin.Forms 开发笔记:为 Android 与 iOS 引入 UWP 风格的汉堡菜单 ( MasterDetailPage )

所谓 UWP 样式的汉堡菜单,我曾在"张高兴的 UWP 开发笔记:汉堡菜单进阶"里说过,也就是使用 Segoe MDL2 Assets 字体作为左侧 Icon,并且左侧使用填充颜色的矩形用来表示 ListView 的选中.如下图 但怎样通过 Xamarin.Forms ,将这一样式的汉堡菜单带入到 Android 与 iOS 中呢? 一.大纲-细节模式简介 讲代码前首先来说说这种导航模式,官方称"大纲-细节模式"(MasterDetail).左侧的汉堡菜单称为&qu

web前端开发笔记(2)

web前端开发笔记(1) 一.HTML标签书写有哪些规范? 页面编码. 文档声明. 关键字与描述. 行内元素不能包含块级元素. a标签不能嵌套a标签. 标签名和属性必须用小写字母书写,属性必须加引号,标签必须闭合,单标签页必须闭合. 页面中不要用 进行缩进,如需缩进,用css控制. html标签使用必须语义化. 要为img标签填写alt和title属性. 二.HTML静态页面出现中文乱码如何解决? 引入<meta charset="UTF-8"> 三.通常情况下块属性标签和

[APP] Android 开发笔记 003

接上节 [APP] Android 开发笔记 002 5. 使用ant release 打包 1)制作 密钥文件 release.keystore (*.keystore) keytool -genkey -v -keystore "release.keystore" -alias "release" -keyalg "RSA" -validity "10000" 这里需要注意的是: -keystore "relea