DB數據導出工具分享

一個根據數據庫連接字符串,sql語句 便可將結果集導出到Excel的工具 分享,支持sqlserver,mysql。html

前因

一個月前朋友找到我,讓我幫忙作一個根據sql導出查詢結果到Excel的工具(以前幫他一個導入Excel而後按其規則統計數據的工具)。
而後扔了我一個SQL語句,瞬間懵比。臥槽。這麼多列,我特麼得定義這麼屬性,改了還得從新改程序(一直用EF)。
因而思考如何忽略列名,進而如何作到通用,作到於我有益,而不是簡單的幫個忙。mysql

如何完成這個需求

Q:程序中根據SQL查詢出數據而不須要關注有哪些列?
A:將查詢結果保存到DataTable中而後遍歷
Q:如何將DataTable轉換Excel?
A:一搜,一試,可用之
Q:如何保存到本地?
A:待我改改寫日誌的方法git

使用SqlSugar 4.x 進行數據操做github

SqlSugar 4.x是一款高性能(達到ADO.NET最高性能水平)、輕量級、支持多庫和人性化語法的ORM,語法方便,入門簡單,功能強大。
對數據庫結構沒太多要求,支持多主鍵,多自增列
SqlSugar支持sqlserver,mysql故此工具適用於此二者數據庫sql

0. 建立項目-預覽

1. 到github倉庫clone了源碼至本地生成須要的dll,而後在項目中添加了引用


2. 使用SqlSugar獲取結果到DataTable中(不知道是否是最近幫朋友寫ado.net的代碼寫多了,感受挺好)

3. DataTable轉Excel

public class DataTableToExcel
{
    private DataTableToExcel()
    { }
    private static DataTableToExcel _instance = null;

    public static DataTableToExcel Instance
    {
        get
        {
            if (_instance == null) _instance = new DataTableToExcel();
            return _instance;
        }
    }
    /// <summary>
    /// DataTable經過流導出Excel
    /// </summary>
    /// <param name="ds">數據源DataSet</param>
    /// <param name="columns">DataTable中列對應的列名(能夠是中文),若爲null則取DataTable中的字段名</param>
    /// <param name="fileName">保存文件名(例如:a.xls)</param>
    /// <returns></returns>
    public string StreamExport(DataTable dt, string[] columns = null,string savePath="")
    {
        //if (dt.Rows.Count > 65535) //總行數大於Excel的行數 
        //{
        //    throw new Exception("預導出的數據總行數大於excel的行數");
        //}

        StringBuilder content = new StringBuilder();
        content.Append("<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:x='urn:schemas-microsoft-com:office:excel' xmlns='http://www.w3.org/TR/REC-html40'>");
        content.Append("<head><title></title><meta http-equiv='Content-Type' content=\"text/html; charset=gb2312\">");
        //注意:[if gte mso 9]到[endif]之間的代碼,用於顯示Excel的網格線,若不想顯示Excel的網格線,能夠去掉此代碼
        content.Append("<!--[if gte mso 9]>");
        content.Append("<xml>");
        content.Append(" <x:ExcelWorkbook>");
        content.Append("  <x:ExcelWorksheets>");
        content.Append("   <x:ExcelWorksheet>");
        content.Append("    <x:Name>Sheet1</x:Name>");
        content.Append("    <x:WorksheetOptions>");
        content.Append("      <x:Print>");
        content.Append("       <x:ValidPrinterInfo />");
        content.Append("      </x:Print>");
        content.Append("    </x:WorksheetOptions>");
        content.Append("   </x:ExcelWorksheet>");
        content.Append("  </x:ExcelWorksheets>");
        content.Append("</x:ExcelWorkbook>");
        content.Append("</xml>");
        content.Append("<![endif]-->");
        content.Append("</head><body><table style='border-collapse:collapse;table-layout:fixed;'><tr>");

        if (columns != null)
        {
            for (int i = 0; i < columns.Length; i++)
            {
                if (columns[i] != null && columns[i] != "")
                {
                    content.Append("<td><b>" + columns[i] + "</b></td>");
                }
                else
                {
                    content.Append("<td><b>" + dt.Columns[i].ColumnName + "</b></td>");
                }
            }
        }
        else
        {
            for (int j = 0; j < dt.Columns.Count; j++)
            {
                content.Append("<td><b>" + dt.Columns[j].ColumnName + "</b></td>");
            }
        }
        content.Append("</tr>\n");

        for (int j = 0; j < dt.Rows.Count; j++)
        {
            content.Append("<tr>");
            for (int k = 0; k < dt.Columns.Count; k++)
            {
                object obj = dt.Rows[j][k];
                Type type = obj.GetType();
                if (type.Name == "Int32" || type.Name == "Single" || type.Name == "Double" || type.Name == "Decimal")
                {
                    double d = obj == DBNull.Value ? 0.0d : Convert.ToDouble(obj);
                    if (type.Name == "Int32" || (d - Math.Truncate(d) == 0))
                        content.AppendFormat("<td style='vnd.ms-excel.numberformat:#,##0'>{0}</td>", obj);
                    else
                        content.AppendFormat("<td style='vnd.ms-excel.numberformat:#,##0.00'>{0}</td>", obj);
                }
                else
                    content.AppendFormat("<td style='vnd.ms-excel.numberformat:@'>{0}</td>", obj);
            }
            content.Append("</tr>\n");
        }
        content.Append("</table></body></html>");
        content.Replace("&nbsp;", "");
        using (var w = new StreamWriter(savePath, false, Encoding.UTF8))
        {
            w.WriteLine(content);
        }
        return savePath;
    }
}

4. 使用Ini文件保存輸入

public class IniHelper
{
    // 聲明INI文件的寫操做函數 WritePrivateProfileString()
    [System.Runtime.InteropServices.DllImport("kernel32")]
    private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);

    // 聲明INI文件的讀操做函數 GetPrivateProfileString()
    [System.Runtime.InteropServices.DllImport("kernel32")]
    private static extern int GetPrivateProfileString(string section, string key, string def, System.Text.StringBuilder retVal, int size, string filePath);

    private int retLength = 500;
    private string sPath = null;
    public IniHelper(string path, int rl = 500)
    {
        this.sPath = path;
        if (rl > 0)
        {
            this.retLength = rl;
        }
    }

    public void WriteValue(string key, string value, string section = "Setting")
    {
        // section=配置節,key=鍵名,value=鍵值,path=路徑
        WritePrivateProfileString(section, key, value, sPath);
    }

    public string ReadValue(string key, string section = "Setting")
    {
        // 每次從ini中讀取多少字節
        System.Text.StringBuilder temp = new System.Text.StringBuilder(retLength);
        // section=配置節,key=鍵名,temp=上面,path=路徑
        GetPrivateProfileString(section, key, "", temp, retLength, sPath);
        return temp.ToString();
    }
}

5. 文本框全選功能

public frmMain()
    {
      
        this.ControlAdded += new System.Windows.Forms.ControlEventHandler(this.Control_ControlAdded); //註冊全選功能
        InitializeComponent();
    }
    #region 文本框可以使用Ctrl+A 全選功能
    private void Control_ControlAdded(object sender, ControlEventArgs e)
    {
        //使「將來」生效
        e.Control.ControlAdded += new System.Windows.Forms.ControlEventHandler(this.Control_ControlAdded);
        //使「子孫」生效
        foreach (Control c in e.Control.Controls)
        {
            Control_ControlAdded(sender, new ControlEventArgs(c));
        }
        //使「過去」生效
        TextBox textBox = e.Control as TextBox;
        if (textBox != null)
        {
            textBox.KeyPress += TextBox_KeyPress;
        }
    }
    private void TextBox_KeyPress(object sender, KeyPressEventArgs e)
    {
        TextBox textBox = sender as TextBox;
        if (textBox == null)
            return;
        if (e.KeyChar == (char)1)
        {
            textBox.SelectAll();
            e.Handled = true;
        }
    }
    #endregion

6. 打開保存的excel

private void btnOpenDir_Click(object sender, EventArgs e)
    {
        var txtFileName = this.txtFileName.Text;
        var txtExportDir = this.txtExportDir.Text;
        var openPath = Path.Combine(txtExportDir, txtFileName);
        if (File.Exists(openPath))
        {
            System.Diagnostics.Process.Start(openPath, "c:\\windows");
        }
        else
        {
            AppendTipMsg("文件" + openPath + "不存在");
        }
    }

7. 頁面主要功能代碼

winform中使用多線程時給ui控件賦值

var txtThread = new Thread(() => txtMsg.BeginInvoke(new Action(() => txtMsg.AppendText("向文本框中追加內容"))));   
txtThread.Start();

8. 一些記錄

winform中使用多線程時給ui控件賦值

var txtThread = new Thread(() => txtMsg.BeginInvoke(new Action(() => txtMsg.AppendText("向文本框中追加內容"))));   
txtThread.Start();

源碼中的NopI組件可移除,此工具實際未用到數據庫

開啓線程執行導出的時候使用的是Task.Run(() =>{});若將框架版本改成4.0則須要將此處修改成new Thread(() =>{}).Start();windows

整個過程解決了一下問題

  1. 數據庫查詢(SqlSugar支持sqlserver,mysql)
  2. datatable轉excel文本
  3. ini存取文件
  4. winform文本框全選功能
  5. winform中使用多線程時給ui控件賦值

源碼

下載使用:http://files.cnblogs.com/files/morang/DB數據導出工具.rar
源碼下載:http://files.cnblogs.com/files/morang/DB數據導出工具_源碼.rar
Coding地址:https://coding.net/u/yimocoding/p/WeDemo/git/tree/NopiExcelDemo
git克隆:git clone https://git.coding.net/yimocoding/WeDemo.git -b NopiExcelDemo多線程

使用說明


相關文章
相關標籤/搜索