一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

C#批量导入Excel数据到SQLite数据库的流程步骤实用指南

时间:2026-10-21 09:26:01 编辑:袖梨 来源:一聚教程网

平时做技术实践时,很多问题不是概念不会,而是细节没串起来。拿“C#批量导入Excel数据到SQLite数据库的流程步骤”来说,它看着像小点,放到项目里常会牵出环境、配置、兼容性和维护成本。下面按实际采用顺序,把思路、关键写法和容易踩坑的地方讲清楚,便于大家直接对照操作。

一、需求

理解这一步时,在winforms里实现批量导入Excel数据到SQLite数据库中,兼容xls和xlsx。

导入到MySQL逻辑也一致。

效果图

二、安装依赖包

在这个场景下,在VS2022里,右键项目->管理NuGet程序包,搜索同时安装以下依赖包

需安装三个依赖包:

1、ExcelDataReader:读取 Excel 文件

2、ExcelDataReader.DataSet:把 Excel 读成 DataSet

3、System.Text.Encoding.CodePages:读取老式 .xls 文件

三、数据表结构

四、准备Excel文件

Excel第一行必须是标题,标题名要和代码里读取的完全一致

五、界面设计

在窗体上放以下两个控件,导入成功后刷新重新加载数据到下面的表格。

控件:Button;名称:btnImport;说明:Text=导入Excel

控件:Lable;名称:importStatus;说明:用来显示导入状态

六、完整代码

/// <summary>
/// 批量导入excel
/// </summary>
private void btnImport_Click(object sender, EventArgs e)
{
    using (OpenFileDialog ofd = new OpenFileDialog()) {
        ofd.Title = "选择要导入的Excel文件";
        ofd.Filter = "Excel文件|*.xls;*.xlsx";

        if (ofd.ShowDialog() != DialogResult.OK)
            return;
        string filePath = ofd.FileName;
        try
        {
            // 1.读取Excel
            importStatus.Text = "正在读取Excel...";
            Application.DoEvents();

            DataTable dt = ReadExcel(filePath);

            // 判断读取的excel里是否有数据
            if (dt == null || dt.Rows.Count == 0) {
                importStatus.Text = "Excel里没有数据";
                MessageBox.Show("Excel里没有数据", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            // 2.批量导入
            importStatus.Text = $"共读取{dt.Rows.Count}行,正在导入...";
            Application.DoEvents();

            int success = ImportToDatabase(dt);

            // 3.显示结果
            importStatus.Text = $"导入完成:成功{success}条,失败{dt.Rows.Count - success}条";
            MessageBox.Show($"导入成功!n成功:{success}条n失败:{dt.Rows.Count - success}条", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            
            // 重新加载数据
            LoadUserData();
        }
        catch (Exception ex)
        {
            importStatus.Text = "导入失败";
            MessageBox.Show($"导入失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
}

/// <summary>
/// 读取 Excel 文件到 DataTable
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
private DataTable ReadExcel(string filePath) {

    // .NET Framework 读取 .xls 需要注册编码提供程序
    System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);

    using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read))
    {
        using (var reader = ExcelReaderFactory.CreateReader(stream))
        {
            var result = reader.AsDataSet(new ExcelDataSetConfiguration()
            {
                ConfigureDataTable = (_) => new ExcelDataTableConfiguration()
                {
                    UseHeaderRow = true // 第一行作为标题
                }
            });

            if(result.Tables.Count > 0)
                return result.Tables[0];

            return null;
        }
    }
}

/// <summary>
/// 批量导入数据库(用事务提高性能)
/// </summary>
/// <param name="dt"></param>
private int ImportToDatabase(DataTable dt) {

    int successCount = 0;
    int totalCount = dt.Rows.Count;

    using (var conn = SqliteHelper.GetConnection()) {

        // 打开连接
        conn.Open();

        // 启动事务
        using (var transaction = conn.BeginTransaction())
        {
            using (var cmd = new SQLiteCommand(conn)) {
                cmd.Transaction = transaction;
                cmd.CommandText = "INSERT INTO user (username, password, status) VALUES (@username, @password, @status)";

                var pUsername = new SQLiteParameter("@username", DbType.String);
                var pPassword = new SQLiteParameter("@password", DbType.String);
                var pStatus = new SQLiteParameter("@status", DbType.Int32);
                cmd.Parameters.AddRange(new[] { pUsername, pPassword, pStatus });

                foreach (DataRow row in dt.Rows)
                {
                    try
                    {
                        string username = row["用户名"]?.ToString().Trim();
                        string password = row["密码"]?.ToString().Trim();
                        string statusStr = row["状态"]?.ToString().Trim();

                        int status = 0; //未知
                        if (statusStr == "开启") status = 1;
                        else if (statusStr == "关闭") status = 2;
                        else status = 0;

                        if (string.IsNullOrEmpty(username))
                            continue;

                        string passwordHash = BCrypt.Net.BCrypt.HashPassword(password ?? "123456");

                        pUsername.Value = username;
                        pPassword.Value = passwordHash;
                        pStatus.Value = status;

                        cmd.ExecuteNonQuery();
                        successCount++;
                    }
                    catch (Exception ex)
                    {

                        continue;
                    }

                    //每100条更新一次进度
                    if (successCount % 100 == 0)
                    {
                        importStatus.Text = $"正在导入:{successCount}/{totalCount}条...";
                        Application.DoEvents();
                    }
                }
            }
            transaction.Commit();
        }
    }
    return successCount;
}

加载数据到DataGridView方法

/// <summary>
/// 加载用户数据到 DataGridView
/// </summary>
private void LoadUserData() {

    try
    {
        string sql = "SELECT id, username, CASE status WHEN 1 THEN '开启' WHEN 2 THEN '关闭' ELSE '未知' END AS status FROM user ORDER BY ID ASC";
        DataTable dt = SqliteHelper.ExecuteDataTable(sql);
        dgvUsers.DataSource = dt;

        // 设置标题
        if (dgvUsers.Columns.Contains("id"))
            dgvUsers.Columns["id"].HeaderText = "编号";
        if (dgvUsers.Columns.Contains("username"))
            dgvUsers.Columns["username"].HeaderText = "用户名";
        if (dgvUsers.Columns.Contains("status"))
            dgvUsers.Columns["status"].HeaderText = "状态";

        // 添加修改/删除列
        // 先移除旧的按钮列,避免重复添加
        if (dgvUsers.Columns.Contains("colEdit"))
            dgvUsers.Columns.Remove("colEdit");
        if (dgvUsers.Columns.Contains("colDelete"))
            dgvUsers.Columns.Remove("colDelete");

        // 修改按钮列
        DataGridViewButtonColumn btnEdit = new DataGridViewButtonColumn();
        btnEdit.Name = "colEdit";
        btnEdit.HeaderText = "操作";
        btnEdit.Text = "修改";
        btnEdit.UseColumnTextForButtonValue = true;
        btnEdit.Width = 60;
        dgvUsers.Columns.Add(btnEdit);

        // 删除按钮列
        DataGridViewButtonColumn btnDelete = new DataGridViewButtonColumn();
        btnDelete.Name = "colDelete";
        btnDelete.HeaderText = "操作";
        btnDelete.Text = "删除";
        btnDelete.UseColumnTextForButtonValue = true;
        btnDelete.Width = 60;
        dgvUsers.Columns.Add(btnDelete);

    }
    catch (Exception ex)
    {
        MessageBox.Show("加载数据失败:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }

}

实际处理时,总的来说,C#导入Excel数据到SQLite适合结合实际项目边做边理解。先抓住核心思路,再逐步补上细节和边界处理,最后效果会更稳定,也更容易复用。

热门栏目