VSTO 系列(02)- 实现数据导入功能

之所以基于 Excel 开发插件,一个重要的原因就是 Excel 在数据展示、分析和处理的灵活性。本篇实现从数据库中基于 SQL 将数据导入到 Excel 工作表。

按照上一篇介绍的操作方法创建一个 Excel VSTO Add-In 项目,添加一个 Ribbon,从工具箱中拖入一个 Button 控件,Label 属性设置为 Import Data。完成后 Ribbon 的界面如下:

实现从数据库中获取数据

考虑到 MS Access 是微软数据库,Visual Studio 天然支持,本例的数据库使用 MS Access 数据库。从数据库导入的数据,可以用 IList<> 来存储,也可以用 ADO.Net 的 DataTable 数据类型来存储,用 DataTable 比较灵活,所以我们用 DataTable 来实现。下面的代码基于 ADO.Net,因为 ADO.Net 的使用不是本篇的重点,代码不做说明。

using System.Data;
using System.Data.OleDb;

namespace VSTODemo {
    
    
    public class EmployeeService {
    
    
        private static OleDbConnection conn = null;

        public static OleDbConnection GetConnection() {
    
    
            string connStr = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\my-documents\Sample Database\Employees.accdb";
            var conn = new OleDbConnection(connStr);
           
            return conn;
        }

        public static DataTable ListAll() {
    
    
            var conn = EmployeeService.GetConnection();
            string selectCmd = "select * from employees";
            OleDbDataAdapter adapter = new OleDbDataAdapter(selectCmd, conn);

            DataTable employees = new DataTable();
            adapter.Fill(employees);
            return employees;
        }
    }
}

数据导入工作表

基于 Excel 对象模型将输入导入也是很模式化的代码,我编写了一段通用代码来实现:

using Microsoft.Office.Interop.Excel;
using System;

namespace VSTODemo {
    
    
    public class ExcelUtils {
    
    
        public static void CopyFromDataTable(System.Data.DataTable dt, Worksheet sht) {
    
    
            if (dt == null) return;

            int colCount = dt.Columns.Count; // 列数量
            int rowCount = dt.Rows.Count;    // 行数量
            if (colCount == 0 || rowCount == 0) {
    
    
                throw new Exception("Empty table!");
            }

            // Header array
            object[] headerArray = new object[colCount];
            for (int col = 0; col < colCount; col++) {
    
    
                headerArray[col] = dt.Columns[col].ColumnName;
            }

            Range startCell = (Range)sht.Cells[1, 1]; // 从第一行第一列开始
            // Write header from header array
            Range headerRange = sht.get_Range(startCell, (Range)sht.Cells[startCell.Row, colCount]);
            headerRange.Value = headerArray;

            // Value for line item Cells
            object[,] valueArray = new object[rowCount, colCount];

            for (int row = 0; row < rowCount; row++) {
    
    
                for (int col = 0; col < colCount; col++) {
    
    
                    valueArray[row, col] = dt.Rows[row][col];
                }
            }

            // 数据整体从array拷贝到工作表(从表头的下一行开始)
            sht.get_Range(startCell.Offset[1, 0], (Range)(sht.Cells[rowCount + 1, colCount])).Value = valueArray;
        }
    }
}

在 Button_click 事件中编写导入的代码:

using Microsoft.Office.Interop.Excel;
using Microsoft.Office.Tools.Ribbon;

namespace VSTODemo {
    
    
    public partial class Ribbon1 {
    
    
        private Application excelApp;

        private void Ribbon1_Load(object sender, RibbonUIEventArgs e) {
    
    
            excelApp = Globals.ThisAddIn.Application;
        }

        private void btnImport_Click(object sender, RibbonControlEventArgs e) {
    
    
            System.Data.DataTable employees = EmployeeService.ListAll();

            Worksheet activeSheet = excelApp.ActiveSheet;
            ExcelUtils.CopyFromDataTable(employees, activeSheet);
        }
    }
}

源码

Gitee - Excel VSTO Import Data

猜你喜欢

转载自blog.csdn.net/stone0823/article/details/114642041