前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Excel催化剂开源第15波-VSTO开发之DataTable数据导出至单元格区域

Excel催化剂开源第15波-VSTO开发之DataTable数据导出至单元格区域

作者头像
Excel催化剂
发布2021-08-19 15:00:35
2.4K0
发布2021-08-19 15:00:35
举报
文章被收录于专栏:Excel催化剂

上篇提到如何从Excel界面上拿到用户的数据,另外反方向的怎样输出给用户数据,也是关键之处。

VSTO最大的优势是,这双向的过程中,全程有用户的交互操作。

而一般IT型的程序,都是脱离用户的操作,只能让用户准备好数据,离开Excel,或生成数据,要重新打开某文件才能获取到数据结果。

在VSTO中,用户随时在Excel最强UI前端中生产数据,同时也在获得数据结果后,无缝地利用Excel强大的数据处理能力进行数据的再次加工如Vlookup一些其他信息进来,做个图表展示等等。

VSTO程序在用户全程数据链条中,都无缝地参与了,只在用户无法解决的复杂数据转换时,才使用二次开发进行处理,处理完,立即可进行下游的其他操作,用户体验绝对是一流。

言归正传,如何DataTable数据导出至单元格区域

在传统的VBA方法中,有ADO的某个方法CopyToRange,直接将DataRecordset的数据输出至单元格区域。

许多VSTO用户还在抱怨着ADO.Net没有相应的方法而郁闷万方,看完此篇内容,会彻底改观,并且可以彻底放弃ADO这样的落后的技术,拥抱ADO.Net这样与时俱进的专业程序猿使用的技术。

DataTable当然可以很轻松地转换为二维数组,再用Range.Resize的方式将二维数组返回给单元格区域,这不失为一个方法,但此处再次强调,这不是最优的方法。

在VSTO中,提供了ListObject的数据对象,区别于传统VBA中能够使用的ListObject。它是在Microsoft.Office.Tools.Excel命名空间内,是VSTO的宿主项,较传统的ListObject,其命名空间为Microsoft.Office.Interop.Excel,新的ListObject得到很大的增强,其中最明显的是可以绑定数据,类似DataGridView一样。

具体代码实现 先创建一个Microsoft.Office.Tools.Excel命名空间内下的ListObject

代码语言:javascript
复制
public static ListObject CreateNewVSTOListObject(string outputSheetName, bool isRetainExistingTable)
        {
            Excel.Worksheet sht;
            if (isRetainExistingTable)
            {
                sht = Common.ExcelApp.ActiveWorkbook.Worksheets.Add();
                try
                {
                    sht.Name = outputSheetName;
                }
                catch (Exception)
                {
                    outputSheetName = outputSheetName + DateTime.Now.ToString("yyyyMMddhhmmss");
                    sht.Name = outputSheetName;
                }
            }
            else
            {
                try
                {
                    sht = Common.ExcelApp.ActiveWorkbook.Worksheets[outputSheetName];
                    var displayAlertsStatus = Common.ExcelApp.DisplayAlerts;

                    if (displayAlertsStatus == true)
                    {
                        Common.ExcelApp.DisplayAlerts = false;
                        sht.Delete();
                        Common.ExcelApp.DisplayAlerts = true;
                    }
                }
                catch (Exception)
                {
                }
                sht = Common.ExcelApp.ActiveWorkbook.Worksheets.Add();
                sht.Name = outputSheetName;
            }

            Worksheet vstoSht = Globals.Factory.GetVstoObject(sht);
            ListObject listObject = vstoSht.Controls.AddListObject(sht.Range["A1"], outputSheetName);
            return listObject;
        }

再将DataTable绑定到ListObject的Datasource上,整个过程结束。

public static void OutputDataToListObject(ListObject listObject, DataTable outputTable, bool isTransDataType=false,string[] mapCols=null) { ////先提取listDstTable原有公式 DictionarydicListObjectCalColumns = GetCalColumnsOfListObject(listObject); //激活工作表 Excel.Worksheet actSht = (Excel.Worksheet)listObject.Parent; actSht.Activate();

代码语言:javascript
复制
        listObject.AutoSetDataBoundColumnHeaders = true;
        listObject.ShowHeaders = true;

        if (mapCols!=null)
        {
            listObject.MappedColumns = mapCols;
        }

        //转换列数据格式
        if (isTransDataType)
        {
            ////先绑定没有数据的dtEmpty,用于调整列的数字格式
            DataTable dtEmpty = outputTable.Clone();
            listObject.SetDataBinding(dtEmpty);
            TransDataTypeOfListObject(listObject, dtEmpty);
        }

        ////重新绑定数据,用有数据的DataTable
        listObject.SetDataBinding(outputTable);
        listObject.AutoSetDataBoundColumnHeaders = false;
        TransHeaderNameOfListObject(listObject);
        listObject.Disconnect();
        //追加之前用户加入的公式,有可能会报错的,用Try-Catch来处理
        AddCustomCalColumns(listObject, dicListObjectCalColumns);
        ////自动调整列宽
        AutoFitColumnWidth(listObject);

    }
大数据下的数据导出

对于数据量较大的数据导出需求时,用ListObject的数据绑定方式导出,有性能瓶颈,可考虑用EPPLUS的方式读写Excel文件。

代码语言:javascript
复制
 public static void OutputDataByEpplus(ListObject listObject, DataTable outputTable, bool isTransDataType)
        {

            var actSht = (Excel.Worksheet)listObject.Parent;
            Excel.Workbook actWkb = actSht.Parent;

            string shtName = actSht.Name;
            string tableName = listObject.Name;

            ////先提取listDstTable原有公式
            Dictionary<string, string> dicListObjectCalColumns = GetCalColumnsOfListObject(listObject);

            listObject.Delete();

            string filePath = actWkb.FullName;

            var listCustomStyleIncludeInfos = StyleSetting.GetCustomStyleIncludeInfos(actWkb);
            actWkb.Close(SaveChanges: true);

            var fi = new FileInfo(filePath);
            using (var p = new ExcelPackage(fi))
            {
                ExcelWorksheet sht = p.Workbook.Worksheets[shtName];
                sht.Cells[1, 1].LoadFromDataTable(outputTable, true, OfficeOpenXml.Table.TableStyles.Light19);
                sht.Tables[0].Name = tableName;
                p.Save();
            };
            Excel.Workbook workbook = Common.ExcelApp.Workbooks.Open(filePath);
            StyleSetting.SetCustomeStyleIncludInfos(actWkb, listCustomStyleIncludeInfos);

            Excel.Worksheet dstSht = workbook.Worksheets[shtName];
            dstSht.Activate();
            var vstoListObject = Globals.Factory.GetVstoObject(dstSht.ListObjects[tableName]);
            //转换格式
            if (isTransDataType)
            {
                TransDataTypeOfListObject(vstoListObject, outputTable);
            }
            //修改列名
            TransHeaderNameOfListObject(vstoListObject);
            //追加之前用户加入的公式,有可能会报错的,用Try-Catch来处理
            AddCustomCalColumns(vstoListObject, dicListObjectCalColumns);
            ////自动调整列宽
            AutoFitColumnWidth(vstoListObject);

        }

结语

通过此篇介绍,给广大开发者特别是VBA转移过来的VSTO开发者带来一些新的方式,不止于只是语法上的更新层面,在.Net环境下开发OFFICE程序时,可以用到许多新的技术和功能,并且较VBA时代的更好用、更易用。

同样最后一句话总结,可以让大家更聚焦在业务逻辑的实现上,通用性的功能,只需找相应的现成轮子帮助即可。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-01-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Excel催化剂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 言归正传,如何DataTable数据导出至单元格区域
    • 大数据下的数据导出
    • 结语
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档