【C#】MySQL数据库数据导入(批量Excel插入)

系列文章

【C#】代码模板生成工具

本文链接:https://blog.csdn.net/youcheng_ge/article/details/126890673

【C#】MySQL数据库导入工具(批量Excel插入)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/126427323

【C#】简单二维码制作和打印工具

本文链接:https://blog.csdn.net/youcheng_ge/article/details/126884228

【C#】最全单据打印源码(打印模板、条形码&二维码、字体样式、logo)

本文链接:https://blog.csdn.net/youcheng_ge/article/details/129415723

【C#】编号生成器(定义单号规则、固定字符、流水号、业务单号)

本文链接:https://blog.csdn.net/youcheng_ge/article/details/129129787


目录

前言

一、问题描述

二、解决方案

三、软件开发(源码)

3.1 界面设计

3.2 底层库--Excel数据读取类

3.3 底层库--XML配置参数读写辅助类

3.4 底层库--脚本生成器

3.5 转换按钮单击事件

3.6 保存按钮单击事件

3.7 脚本生成方法(核心)

四、成果展示

五、资源链接 


前言

我能抽象出整个世界,但是我不能抽象你。 想让你成为私有常量,这样外部函数就无法访问你。 又想让你成为全局常量,这样在我的整个生命周期都可以调用你。 可惜世上没有这样的常量,我也无法定义你,因为你在我心中是那么的具体。

哈喽大家好,本专栏为【项目实战】专栏,有别于【底层库】专栏,我们可以发现增加 了『问题描述』、『项目展示』章节,十分符合项目开发流程,让读者更加清楚项目解决的问题、以及产品能够达到的效果。本专栏收纳项目开发过程的解决方案,是我项目开发相对成熟、可靠方法的提炼,我将这些问题的解决思路梳理,撰写本文分享给大家,大家遇到类似问题,可按本文方案处理。

本专栏会持续更新,不断完善,专栏文章关联性较弱(文章之间依赖性较弱,没有阅读顺序)。如果您对本专栏感兴趣,持续关注吧,我将带你用最简洁的代码,实现复杂的功能。大家有任何问题,可以评论区反馈,私信我。

·提示:本专栏为项目实战篇,未接触项目开发的同学可能理解困难,不推荐阅读。


一、问题描述

今天,我完成了【Excel导入工具】第一版,测试成功。本文主要和大家分享一下,我为什么要开发这个工具?

我司推进【条码管理】,一来提高信息化水平,二来方便录入单据,此时就需要有个强大的后台库,能联想到用户想要录入的数据,或者说能够让用户“以选代输”,更加快捷、准确制单。

我们是没有基础库的,但是公司有使用用友U8产品,所有U8中的基础数据可行。经协商,他们只肯开放API数据接口给我们。所以,我决定新建数据库,将数据导入我们的库中,为啥不直连呢?一是,我们为了明确职责,不希望扯皮,不影响原U8服务器性能;二是,用友物理库还是不肯开放给我们的,涉及保密可以理解。

好了,上面是我遇见的情况,其实基础数据建档工作,你们肯定也有做过,我觉得会有如下几种情况:

  • 基础数据初始化工作,做企业ERP管理常会遇到,需协助业务部门创建基础档案,员工档案、部门档案、存货档案、供应商档案、仓库档案、财务科目等,往往业务人员提供一个Excel表,需要我们将数据导入系统。
  • 与外部系统对接,第三方软件公司对接,对方开放了API数据接口,你需要将获得的数据存储到自己的数据库中,这是我遇到的情况。
  • 同步表数据工作,当我们研发要修复一个隐蔽的bug,但是测试环境,缺乏真实业务数据,无法重现问题,需要还原某张表的数据,却不想还原整个库。
  • 跨平台数据转换工作,发生在新老系统更替,原先公司用的oracle数据库,现在要换Sql Server数据库,业务数据希望转换过去。


二、解决方案

我的想法是开发一个工具,可以将Excel表格转化成SQL插入语句,这样我们拿SQL语句放数据库里一执行就成功了。

我暗自定了几点要求:

  • 工具通用型,支持任何表,不能说一个业务,开发一个工具,不得累死。
  • 支持Excel 97-2003 工作簿(*.xls)、Excel 工作簿(.xlsx)
  • 界面友好化,功能完善,能运用到多场景。


三、软件开发(源码)

3.1 界面设计

C#窗体,第一步总是先设计界面。你们参考我,设计的界面吧。

主页面:

 配置界面

3.2 底层库--Excel数据读取类

创建类ExcelHelper.cs,实现将Excel中sheet数据读取,并转换转换成DataTable格式。

请阅读下文:

C#底层库--Excel数据读取类(可读加密表格)

本文链接:https://blog.csdn.net/youcheng_ge/article/details/126887445

3.3 底层库--XML配置参数读写辅助类

创建类AppConfig.cs,实现【配置】界面,参数的读取和写入。

请阅读下文:

C#底层库--XML配置参数读写辅助类(推荐阅读)

本文链接:https://blog.csdn.net/youcheng_ge/article/details/129175304

3.4 底层库--脚本生成器

创建类CodeFactory.cs,实现SQL Insert 语句的生成,请复制以下代码:

using System;
using System.Data;
using System.Text;

namespace ExcelImportTool
{
    public static class CodeFactory
    {
        /// <summary>
        /// 创建Insert语句(采用分批处理)
        /// </summary>
        /// <param name="a_dtSource">DataTable</param>
        /// <param name="a_strTableName">数据库表名</param>
        /// <param name="a_intBatchNum">每批数量</param>
        /// <returns></returns>
        public static string CreateInsertSQLBatch(DataTable a_dtSource, string a_strTableName,int a_intBatchNum)
        {
            //insert语句
            string str_Insert = $"INSERT INTO {a_strTableName} ({GetColumnsByDataTable(a_dtSource)})";

            bool l_bflag = false;
            StringBuilder str_builder = new StringBuilder();

            //表格总行数
            int int_RowCount = a_dtSource.Rows.Count;
            //select语句,采用for循环便于计算行数
            for (int i = 0; i < int_RowCount; i++)
            {
                if (i % a_intBatchNum == 0)
                {
                    if (l_bflag)
                    {
                        //以分号结尾,分批执行
                        str_builder.Append(";");
                    }
                    str_builder.AppendLine();
                    str_builder.AppendLine(str_Insert);
                    l_bflag = false;
                }

                if (l_bflag)
                {
                    str_builder.AppendLine();
                    str_builder.AppendLine("UNION ALL");
                }

                DataRow dr = a_dtSource.Rows[i];

                str_builder.Append("SELECT ");
                string text = string.Empty;
                for (int j = 0; j < a_dtSource.Columns.Count; j++)
                {
                    text = text + "'" + dr[j].ToString() + "'" + ",";
                }
                //去掉末尾分号
                text = DelLastComma(text);
                str_builder.Append(text);
                l_bflag = true;
            }

            return str_builder.ToString();
        }


        /// <summary>
        /// 创建Insert语句
        /// </summary>
        /// <param name="a_dtSource">DataTable</param>
        /// <param name="a_strTableName">数据库表名</param>
        /// <returns></returns>
        public static string CreateInsertSQL(DataTable a_dtSource, string a_strTableName)
        {
            //insert语句
            string str_Insert = $"INSERT INTO {a_strTableName} ({GetColumnsByDataTable(a_dtSource)})";

            bool l_bflag = false;
            StringBuilder str_builder = new StringBuilder();
            str_builder.AppendLine(str_Insert);

            //表格总行数
            int int_RowCount = a_dtSource.Rows.Count;
            //select语句,采用for循环便于计算行数
            for (int i = 0; i < int_RowCount; i++)
            {
                if (l_bflag)
                {
                    str_builder.AppendLine("UNION ALL");
                }

                DataRow dr = a_dtSource.Rows[i];

                str_builder.Append("SELECT ");
                string text = string.Empty;
                for (int j = 0; j < a_dtSource.Columns.Count; j++)
                {
                    text = text + "'" + dr[j].ToString() + "'" + ",";
                }
                //去掉末尾分号
                text = DelLastComma(text);
                str_builder.Append(text);
                str_builder.AppendLine();
                l_bflag = true;
            }

            return str_builder.ToString();
        }


        /// <summary>
        /// 内部获取字段列表
        /// </summary>
        /// <param name = "a_tbSchema" > DataTable </ param >
        /// < returns > SQL </ returns >
        private static string GetColumnsByDataTable(DataTable a_tbSchema)
        {
            string text = string.Empty;
            for (int i = 0; i < a_tbSchema.Columns.Count; i++)
            {
                string text2 = a_tbSchema.Columns[i].ColumnName;
                text = text + text2 + ",";
            }
            return DelLastComma(text);
        }


        /// <summary>
        /// 删除最后结尾的逗号
        /// </summary>
        /// <param name="a_strSource">源字符串</param>
        /// <returns>string</returns>
        public static string DelLastComma(string a_strSource)
        {
            return a_strSource.Substring(0, a_strSource.LastIndexOf(","));
        }

    }
}

扩展阅读,本库已经二次优化,方法已经汇总进《MySQLBuilder脚本构建类》中。

C#底层库--MySQLBuilder脚本构建类(select、insert、update、in、带条件的SQL自动生成)

本文链接:https://blog.csdn.net/youcheng_ge/article/details/129179216

3.5 转换按钮单击事件

没啥好讲解的,都可以看得懂吧

        //转换
        private void BTN_Change_Click(object sender, EventArgs e)
        {
            if (!File.Exists(this.text_ExcelDir.Text))
            {
                FrmTips.ShowTipsInfo(this, "文件不存在,请检查!");
                return;
            }

            ConvertSQL();
        }

3.6 保存按钮单击事件

        //保存
        private void BTN_Save_Click(object sender, EventArgs e)
        {
            string l_strFileName = DateTime.Now.ToString("yyyyMMddHHmmssff") + ".txt";

            FolderBrowserDialog fbd = new FolderBrowserDialog();
            fbd.Description = "选择脚本保存位置";
            fbd.SelectedPath = AppDomain.CurrentDomain.BaseDirectory;
            DialogResult dialogResult = fbd.ShowDialog();
            if (dialogResult == DialogResult.OK)
            {
                string l_strDir = Path.Combine(fbd.SelectedPath, l_strFileName);
                Utils.FileWrite(richTextBox1.Text, l_strDir);
                FrmTips.ShowTipsSuccess(this, "保存成功!");

                System.Diagnostics.Process.Start(l_strDir);
            }
        }

3.7 脚本生成方法(核心)

因为二次调用,所以单独出一个方法。转换、保存 按钮单击事件,均有调用此方法。

       //转换SQL
        private void ConvertSQL()
        {
            this.richTextBox1.Clear();
            string l_strFileName = Path.GetFileNameWithoutExtension(this.text_ExcelDir.Text);

            ExcelHelper excelHelper = new ExcelHelper();
            DataTable dt_Temp = excelHelper.ExcelToDataTableWhithEncryp(this.text_ExcelDir.Text);
            if (dt_Temp == null || dt_Temp.Rows.Count==0)
            {
                FrmTips.ShowTipsError(this, "表格读取为空!");
                return;
            }

            //每批数量
            decimal dec_num = 100;
            decimal.TryParse(AppConfig.GetValue("batch_num"), out dec_num);

            //是否开启
            bool b_Open = false;
            bool.TryParse(AppConfig.GetValue("open_tag"), out b_Open);

            if (b_Open)
            {
                int int_num = Convert.ToInt32(Math.Truncate(dec_num));
                richTextBox1.AppendText(CodeFactory.CreateInsertSQLBatch(dt_Temp, l_strFileName, int_num));
            }
            else
            {
                richTextBox1.AppendText(CodeFactory.CreateInsertSQL(dt_Temp, l_strFileName));
            }

            FrmTips.ShowTipsSuccess(this, "转换成功!");
        }

四、成果展示

这里主要展示我开发完的程序,你们也可以在我的基础上进行个性化的修改。

主界面

 

 点击复制按钮,拷贝脚本到数据库管理工具。

好了,是不是很完美。

提示:为了高性能执行,建议数据分批,在【配置】界面设置分批数量。 

五、资源链接 

工具名称:ExcelImportTool

链接:https://pan.baidu.com/s/1NgZEGVzXDXecUxiqMmYAeg?pwd=858o 
提取码:858o

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花北城

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值