当前位置: 代码网 > it编程>编程语言>Asp.net > C#读取CSV/Excel文件数据并显示在DataGridView

C#读取CSV/Excel文件数据并显示在DataGridView

2026年04月16日 Asp.net 我要评论
c# 用于读取 csv 和 excel 文件数据并显示在 datagridview 控件中,支持文件选择、数据预览、格式处理和错误处理等功能。解决方案结构csvexcelreader/├── csve

c# 用于读取 csv 和 excel 文件数据并显示在 datagridview 控件中,支持文件选择、数据预览、格式处理和错误处理等功能。

解决方案结构

csvexcelreader/
├── csvexcelreader.sln
├── csvexcelreader/
│   ├── app.config
│   ├── form1.cs
│   ├── form1.designer.cs
│   ├── form1.resx
│   ├── program.cs
│   ├── filereader.cs
│   ├── dataprocessor.cs
│   └── properties/
│       ├── assemblyinfo.cs
│       └── resources.designer.cs
└── packages.config

完整代码实现

1. 主窗体 (form1.cs)

using system;
using system.data;
using system.drawing;
using system.io;
using system.windows.forms;
using npoi.ss.usermodel;
using npoi.xssf.usermodel;
using npoi.hssf.usermodel;

namespace csvexcelreader
{
    public partial class mainform : form
    {
        private readonly filereader filereader = new filereader();
        private readonly dataprocessor dataprocessor = new dataprocessor();
        
        public mainform()
        {
            initializecomponent();
            initializeui();
        }

        private void initializeui()
        {
            // 窗体设置
            this.text = "csv/excel 数据读取器";
            this.size = new size(900, 600);
            this.startposition = formstartposition.centerscreen;
            this.backcolor = color.fromargb(240, 240, 240);
            
            // 创建控件
            lbltitle = new label
            {
                text = "csv/excel 数据读取器",
                font = new font("微软雅黑", 16, fontstyle.bold),
                forecolor = color.darkslateblue,
                autosize = true,
                location = new point(20, 20)
            };
            
            btnopencsv = new button
            {
                text = "打开 csv 文件",
                size = new size(120, 40),
                location = new point(30, 70),
                backcolor = color.steelblue,
                forecolor = color.white,
                flatstyle = flatstyle.flat,
                font = new font("微软雅黑", 10)
            };
            btnopencsv.flatappearance.bordersize = 0;
            btnopencsv.click += btnopencsv_click;
            
            btnopenexcel = new button
            {
                text = "打开 excel 文件",
                size = new size(120, 40),
                location = new point(160, 70),
                backcolor = color.forestgreen,
                forecolor = color.white,
                flatstyle = flatstyle.flat,
                font = new font("微软雅黑", 10)
            };
            btnopenexcel.flatappearance.bordersize = 0;
            btnopenexcel.click += btnopenexcel_click;
            
            btnsavecsv = new button
            {
                text = "保存为 csv",
                size = new size(120, 40),
                location = new point(290, 70),
                backcolor = color.orange,
                forecolor = color.white,
                flatstyle = flatstyle.flat,
                font = new font("微软雅黑", 10),
                enabled = false
            };
            btnsavecsv.flatappearance.bordersize = 0;
            btnsavecsv.click += btnsavecsv_click;
            
            btnsaveexcel = new button
            {
                text = "保存为 excel",
                size = new size(120, 40),
                location = new point(420, 70),
                backcolor = color.purple,
                forecolor = color.white,
                flatstyle = flatstyle.flat,
                font = new font("微软雅黑", 10),
                enabled = false
            };
            btnsaveexcel.flatappearance.bordersize = 0;
            btnsaveexcel.click += btnsaveexcel_click;
            
            btnclear = new button
            {
                text = "清除数据",
                size = new size(120, 40),
                location = new point(550, 70),
                backcolor = color.gray,
                forecolor = color.white,
                flatstyle = flatstyle.flat,
                font = new font("微软雅黑", 10)
            };
            btnclear.flatappearance.bordersize = 0;
            btnclear.click += btnclear_click;
            
            // 状态标签
            lblstatus = new label
            {
                text = "就绪",
                autosize = true,
                location = new point(30, 120),
                font = new font("微软雅黑", 9),
                forecolor = color.dimgray
            };
            
            // 数据网格视图
            datagridview = new datagridview
            {
                location = new point(20, 150),
                size = new size(840, 400),
                backgroundcolor = color.white,
                borderstyle = borderstyle.fixedsingle,
                allowusertoaddrows = false,
                allowusertodeleterows = false,
                readonly = true,
                autosizecolumnsmode = datagridviewautosizecolumnsmode.displayedcells,
                rowheadersvisible = false,
                columnheadersdefaultcellstyle = new datagridviewcellstyle
                {
                    backcolor = color.steelblue,
                    forecolor = color.white,
                    font = new font("微软雅黑", 10, fontstyle.bold)
                },
                defaultcellstyle = new datagridviewcellstyle
                {
                    font = new font("微软雅黑", 9),
                    selectionbackcolor = color.lightsteelblue
                },
                enableheadersvisualstyles = false
            };
            
            // 进度条
            progressbar = new progressbar
            {
                location = new point(20, 560),
                size = new size(840, 20),
                visible = false
            };
            
            // 添加控件到窗体
            this.controls.add(lbltitle);
            this.controls.add(btnopencsv);
            this.controls.add(btnopenexcel);
            this.controls.add(btnsavecsv);
            this.controls.add(btnsaveexcel);
            this.controls.add(btnclear);
            this.controls.add(lblstatus);
            this.controls.add(datagridview);
            this.controls.add(progressbar);
        }

        #region 控件声明
        private label lbltitle;
        private button btnopencsv;
        private button btnopenexcel;
        private button btnsavecsv;
        private button btnsaveexcel;
        private button btnclear;
        private label lblstatus;
        private datagridview datagridview;
        private progressbar progressbar;
        #endregion

        #region 事件处理
        private void btnopencsv_click(object sender, eventargs e)
        {
            using (openfiledialog openfiledialog = new openfiledialog())
            {
                openfiledialog.filter = "csv 文件 (*.csv)|*.csv|所有文件 (*.*)|*.*";
                openfiledialog.title = "选择 csv 文件";
                
                if (openfiledialog.showdialog() == dialogresult.ok)
                {
                    loadfile(openfiledialog.filename, filetype.csv);
                }
            }
        }

        private void btnopenexcel_click(object sender, eventargs e)
        {
            using (openfiledialog openfiledialog = new openfiledialog())
            {
                openfiledialog.filter = "excel 文件 (*.xls;*.xlsx)|*.xls;*.xlsx|所有文件 (*.*)|*.*";
                openfiledialog.title = "选择 excel 文件";
                
                if (openfiledialog.showdialog() == dialogresult.ok)
                {
                    loadfile(openfiledialog.filename, filetype.excel);
                }
            }
        }

        private void btnsavecsv_click(object sender, eventargs e)
        {
            if (datagridview.datasource == null) return;
            
            using (savefiledialog savefiledialog = new savefiledialog())
            {
                savefiledialog.filter = "csv 文件 (*.csv)|*.csv";
                savefiledialog.title = "保存为 csv 文件";
                savefiledialog.filename = "data_export.csv";
                
                if (savefiledialog.showdialog() == dialogresult.ok)
                {
                    try
                    {
                        dataprocessor.exporttocsv((datatable)datagridview.datasource, savefiledialog.filename);
                        lblstatus.text = $"数据已成功导出到: {savefiledialog.filename}";
                    }
                    catch (exception ex)
                    {
                        messagebox.show($"导出失败: {ex.message}", "错误", messageboxbuttons.ok, messageboxicon.error);
                    }
                }
            }
        }

        private void btnsaveexcel_click(object sender, eventargs e)
        {
            if (datagridview.datasource == null) return;
            
            using (savefiledialog savefiledialog = new savefiledialog())
            {
                savefiledialog.filter = "excel 文件 (*.xlsx)|*.xlsx";
                savefiledialog.title = "保存为 excel 文件";
                savefiledialog.filename = "data_export.xlsx";
                
                if (savefiledialog.showdialog() == dialogresult.ok)
                {
                    try
                    {
                        dataprocessor.exporttoexcel((datatable)datagridview.datasource, savefiledialog.filename);
                        lblstatus.text = $"数据已成功导出到: {savefiledialog.filename}";
                    }
                    catch (exception ex)
                    {
                        messagebox.show($"导出失败: {ex.message}", "错误", messageboxbuttons.ok, messageboxicon.error);
                    }
                }
            }
        }

        private void btnclear_click(object sender, eventargs e)
        {
            datagridview.datasource = null;
            btnsavecsv.enabled = false;
            btnsaveexcel.enabled = false;
            lblstatus.text = "数据已清除";
        }
        #endregion

        #region 文件加载与处理
        private void loadfile(string filepath, filetype filetype)
        {
            try
            {
                progressbar.visible = true;
                progressbar.style = progressbarstyle.marquee;
                lblstatus.text = $"正在加载文件: {path.getfilename(filepath)}...";
                application.doevents();
                
                datatable datatable = filetype == filetype.csv 
                    ? filereader.readcsv(filepath) 
                    : filereader.readexcel(filepath);
                
                if (datatable == null || datatable.rows.count == 0)
                {
                    lblstatus.text = "文件为空或未找到数据";
                    return;
                }
                
                // 数据预处理
                datatable = dataprocessor.processdatatable(datatable);
                
                // 绑定到datagridview
                datagridview.datasource = datatable;
                
                // 启用保存按钮
                btnsavecsv.enabled = true;
                btnsaveexcel.enabled = true;
                
                lblstatus.text = $"已加载: {path.getfilename(filepath)} | 行: {datatable.rows.count} | 列: {datatable.columns.count}";
            }
            catch (exception ex)
            {
                messagebox.show($"加载文件失败: {ex.message}", "错误", messageboxbuttons.ok, messageboxicon.error);
                lblstatus.text = $"错误: {ex.message}";
            }
            finally
            {
                progressbar.visible = false;
            }
        }
        #endregion
    }

    public enum filetype
    {
        csv,
        excel
    }
}

2. 文件读取器 (filereader.cs)

using system;
using system.data;
using system.io;
using system.text;
using npoi.ss.usermodel;
using npoi.xssf.usermodel;
using npoi.hssf.usermodel;

namespace csvexcelreader
{
    public class filereader
    {
        /// <summary>
        /// 读取csv文件并返回datatable
        /// </summary>
        public datatable readcsv(string filepath)
        {
            if (!file.exists(filepath))
                throw new filenotfoundexception("文件不存在", filepath);
            
            datatable datatable = new datatable();
            int rowcount = 0;
            
            using (var reader = new streamreader(filepath, encoding.utf8))
            {
                string line;
                bool isfirstrow = true;
                
                while ((line = reader.readline()) != null)
                {
                    // 处理可能的引号包围字段
                    string[] fields = parsecsvline(line);
                    
                    if (isfirstrow)
                    {
                        // 创建列
                        foreach (string field in fields)
                        {
                            datatable.columns.add(field);
                        }
                        isfirstrow = false;
                    }
                    else
                    {
                        // 添加行数据
                        if (fields.length > datatable.columns.count)
                        {
                            // 添加缺失的列
                            for (int i = datatable.columns.count; i < fields.length; i++)
                            {
                                datatable.columns.add($"column{datatable.columns.count + 1}");
                            }
                        }
                        
                        datarow row = datatable.newrow();
                        for (int i = 0; i < fields.length; i++)
                        {
                            if (i < datatable.columns.count)
                            {
                                row[i] = fields[i];
                            }
                        }
                        datatable.rows.add(row);
                    }
                    
                    rowcount++;
                }
            }
            
            return datatable;
        }

        /// <summary>
        /// 解析csv行,处理逗号和引号
        /// </summary>
        private string[] parsecsvline(string line)
        {
            var fields = new system.collections.generic.list<string>();
            bool inquotes = false;
            var currentfield = new stringbuilder();
            
            for (int i = 0; i < line.length; i++)
            {
                char c = line[i];
                
                if (c == '"')
                {
                    // 处理转义引号
                    if (inquotes && i + 1 < line.length && line[i + 1] == '"')
                    {
                        currentfield.append('"');
                        i++;
                    }
                    else
                    {
                        inquotes = !inquotes;
                    }
                }
                else if (c == ',' && !inquotes)
                {
                    // 字段结束
                    fields.add(currentfield.tostring());
                    currentfield.clear();
                }
                else
                {
                    currentfield.append(c);
                }
            }
            
            // 添加最后一个字段
            fields.add(currentfield.tostring());
            
            return fields.toarray();
        }

        /// <summary>
        /// 读取excel文件并返回datatable
        /// </summary>
        public datatable readexcel(string filepath)
        {
            if (!file.exists(filepath))
                throw new filenotfoundexception("文件不存在", filepath);
            
            iworkbook workbook;
            datatable datatable = new datatable();
            int rowcount = 0;
            
            using (var filestream = new filestream(filepath, filemode.open, fileaccess.read))
            {
                // 根据扩展名创建不同的工作簿
                if (path.getextension(filepath).equals(".xlsx", stringcomparison.ordinalignorecase))
                {
                    workbook = new xssfworkbook(filestream);
                }
                else if (path.getextension(filepath).equals(".xls", stringcomparison.ordinalignorecase))
                {
                    workbook = new hssfworkbook(filestream);
                }
                else
                {
                    throw new notsupportedexception("不支持的excel文件格式");
                }
                
                // 获取第一个工作表
                isheet sheet = workbook.getsheetat(0);
                if (sheet == null) return datatable;
                
                // 获取标题行
                irow headerrow = sheet.getrow(0);
                if (headerrow == null) return datatable;
                
                // 创建列
                for (int i = 0; i < headerrow.lastcellnum; i++)
                {
                    icell cell = headerrow.getcell(i);
                    string columnname = cell?.tostring() ?? $"column{i + 1}";
                    datatable.columns.add(columnname);
                }
                
                // 添加数据行
                for (int i = 1; i <= sheet.lastrownum; i++)
                {
                    irow row = sheet.getrow(i);
                    if (row == null) continue;
                    
                    datarow datarow = datatable.newrow();
                    for (int j = 0; j < datatable.columns.count; j++)
                    {
                        icell cell = row.getcell(j);
                        if (cell != null)
                        {
                            switch (cell.celltype)
                            {
                                case celltype.string:
                                    datarow[j] = cell.stringcellvalue;
                                    break;
                                case celltype.numeric:
                                    if (dateutil.iscelldateformatted(cell))
                                    {
                                        datarow[j] = cell.datecellvalue.tostring("yyyy-mm-dd");
                                    }
                                    else
                                    {
                                        datarow[j] = cell.numericcellvalue;
                                    }
                                    break;
                                case celltype.boolean:
                                    datarow[j] = cell.booleancellvalue;
                                    break;
                                case celltype.formula:
                                    datarow[j] = cell.numericcellvalue;
                                    break;
                                default:
                                    datarow[j] = cell.tostring();
                                    break;
                            }
                        }
                    }
                    datatable.rows.add(datarow);
                    rowcount++;
                }
            }
            
            return datatable;
        }
    }
}

3. 数据处理类 (dataprocessor.cs)

using system;
using system.data;
using system.globalization;
using npoi.ss.usermodel;
using npoi.xssf.usermodel;
using npoi.hssf.usermodel;

namespace csvexcelreader
{
    public class dataprocessor
    {
        /// <summary>
        /// 处理datatable数据(类型转换、空值处理等)
        /// </summary>
        public datatable processdatatable(datatable inputtable)
        {
            if (inputtable == null) return null;
            
            datatable processedtable = inputtable.clone();
            
            // 处理列数据类型
            foreach (datacolumn column in processedtable.columns)
            {
                // 尝试推断列的数据类型
                type inferredtype = infercolumntype(inputtable, column.columnname);
                if (inferredtype != null)
                {
                    column.datatype = inferredtype;
                }
            }
            
            // 处理行数据
            foreach (datarow row in inputtable.rows)
            {
                datarow newrow = processedtable.newrow();
                
                for (int i = 0; i < inputtable.columns.count; i++)
                {
                    string columnname = inputtable.columns[i].columnname;
                    object value = row[i];
                    
                    // 处理空值
                    if (value == null || value == dbnull.value || string.isnullorwhitespace(value.tostring()))
                    {
                        newrow[columnname] = dbnull.value;
                        continue;
                    }
                    
                    // 处理数值类型
                    if (processedtable.columns[columnname].datatype == typeof(int))
                    {
                        if (int.tryparse(value.tostring(), out int intvalue))
                        {
                            newrow[columnname] = intvalue;
                        }
                        else
                        {
                            newrow[columnname] = dbnull.value;
                        }
                    }
                    else if (processedtable.columns[columnname].datatype == typeof(double))
                    {
                        if (double.tryparse(value.tostring(), numberstyles.any, cultureinfo.invariantculture, out double doublevalue))
                        {
                            newrow[columnname] = doublevalue;
                        }
                        else
                        {
                            newrow[columnname] = dbnull.value;
                        }
                    }
                    else if (processedtable.columns[columnname].datatype == typeof(datetime))
                    {
                        if (datetime.tryparse(value.tostring(), out datetime datevalue))
                        {
                            newrow[columnname] = datevalue;
                        }
                        else
                        {
                            newrow[columnname] = dbnull.value;
                        }
                    }
                    else
                    {
                        newrow[columnname] = value.tostring().trim();
                    }
                }
                
                processedtable.rows.add(newrow);
            }
            
            return processedtable;
        }

        /// <summary>
        /// 推断列的数据类型
        /// </summary>
        private type infercolumntype(datatable table, string columnname)
        {
            int totalrows = table.rows.count;
            if (totalrows == 0) return typeof(string);
            
            int intcount = 0;
            int doublecount = 0;
            int datecount = 0;
            int stringcount = 0;
            
            foreach (datarow row in table.rows)
            {
                object value = row[columnname];
                if (value == null || value == dbnull.value) continue;
                
                string strvalue = value.tostring().trim();
                if (string.isnullorempty(strvalue)) continue;
                
                if (int.tryparse(strvalue, out _))
                {
                    intcount++;
                }
                else if (double.tryparse(strvalue, numberstyles.any, cultureinfo.invariantculture, out _))
                {
                    doublecount++;
                }
                else if (datetime.tryparse(strvalue, out _))
                {
                    datecount++;
                }
                else
                {
                    stringcount++;
                }
            }
            
            // 如果80%以上的值都是整数,则认为是整数类型
            if ((double)intcount / totalrows > 0.8) return typeof(int);
            
            // 如果80%以上的值都是浮点数,则认为是浮点数类型
            if ((double)(intcount + doublecount) / totalrows > 0.8) return typeof(double);
            
            // 如果80%以上的值都是日期,则认为是日期类型
            if ((double)datecount / totalrows > 0.8) return typeof(datetime);
            
            return typeof(string);
        }

        /// <summary>
        /// 导出datatable到csv文件
        /// </summary>
        public void exporttocsv(datatable datatable, string filepath)
        {
            if (datatable == null) return;
            
            using (var writer = new streamwriter(filepath, false, encoding.utf8))
            {
                // 写入列头
                for (int i = 0; i < datatable.columns.count; i++)
                {
                    writer.write(escapecsvfield(datatable.columns[i].columnname));
                    if (i < datatable.columns.count - 1)
                    {
                        writer.write(",");
                    }
                }
                writer.writeline();
                
                // 写入数据行
                foreach (datarow row in datatable.rows)
                {
                    for (int i = 0; i < datatable.columns.count; i++)
                    {
                        object value = row[i];
                        string strvalue = value?.tostring() ?? string.empty;
                        writer.write(escapecsvfield(strvalue));
                        if (i < datatable.columns.count - 1)
                        {
                            writer.write(",");
                        }
                    }
                    writer.writeline();
                }
            }
        }

        /// <summary>
        /// 转义csv字段
        /// </summary>
        private string escapecsvfield(string field)
        {
            if (string.isnullorempty(field)) return string.empty;
            
            // 如果包含逗号、换行符或双引号,则用双引号包围
            if (field.contains(",") || field.contains("\"") || field.contains("\n") || field.contains("\r"))
            {
                return "\"" + field.replace("\"", "\"\"") + "\"";
            }
            return field;
        }

        /// <summary>
        /// 导出datatable到excel文件
        /// </summary>
        public void exporttoexcel(datatable datatable, string filepath)
        {
            if (datatable == null) return;
            
            iworkbook workbook;
            if (path.getextension(filepath).equals(".xlsx", stringcomparison.ordinalignorecase))
            {
                workbook = new xssfworkbook();
            }
            else
            {
                workbook = new hssfworkbook();
            }
            
            isheet sheet = workbook.createsheet("sheet1");
            
            // 创建标题行
            irow headerrow = sheet.createrow(0);
            for (int i = 0; i < datatable.columns.count; i++)
            {
                icell cell = headerrow.createcell(i);
                cell.setcellvalue(datatable.columns[i].columnname);
                
                // 设置标题样式
                icellstyle style = workbook.createcellstyle();
                ifont font = workbook.createfont();
                font.boldweight = (short)fontboldweight.bold;
                style.setfont(font);
                cell.cellstyle = style;
            }
            
            // 填充数据
            for (int i = 0; i < datatable.rows.count; i++)
            {
                irow row = sheet.createrow(i + 1);
                for (int j = 0; j < datatable.columns.count; j++)
                {
                    icell cell = row.createcell(j);
                    object value = datatable.rows[i][j];
                    
                    if (value == dbnull.value || value == null)
                    {
                        cell.setcellvalue(string.empty);
                    }
                    else if (value is int intvalue)
                    {
                        cell.setcellvalue(intvalue);
                    }
                    else if (value is double doublevalue)
                    {
                        cell.setcellvalue(doublevalue);
                    }
                    else if (value is datetime datevalue)
                    {
                        cell.setcellvalue(datevalue);
                        icellstyle datestyle = workbook.createcellstyle();
                        idataformat format = workbook.createdataformat();
                        datestyle.dataformat = format.getformat("yyyy-mm-dd");
                        cell.cellstyle = datestyle;
                    }
                    else
                    {
                        cell.setcellvalue(value.tostring());
                    }
                }
            }
            
            // 自动调整列宽
            for (int i = 0; i < datatable.columns.count; i++)
            {
                sheet.autosizecolumn(i);
            }
            
            // 保存文件
            using (var filestream = new filestream(filepath, filemode.create, fileaccess.write))
            {
                workbook.write(filestream);
            }
        }
    }
}

4. 程序入口 (program.cs)

using system;
using system.windows.forms;

namespace csvexcelreader
{
    static class program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [stathread]
        static void main()
        {
            application.enablevisualstyles();
            application.setcompatibletextrenderingdefault(false);
            application.run(new mainform());
        }
    }
}

5. 应用程序配置文件 (app.config)

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup> 
    <supportedruntime version="v4.0" sku=".netframework,version=v4.7.2"/>
  </startup>
  <runtime>
    <assemblybinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentassembly>
        <assemblyidentity name="npoi" publickeytoken="0df73ec7942d9264" culture="neutral"/>
        <bindingredirect oldversion="0.0.0.0-2.5.6.0" newversion="2.5.6.0"/>
      </dependentassembly>
      <dependentassembly>
        <assemblyidentity name="npoi.ooxml" publickeytoken="0df73ec7942d9264" culture="neutral"/>
        <bindingredirect oldversion="0.0.0.0-2.5.6.0" newversion="2.5.6.0"/>
      </dependentassembly>
      <dependentassembly>
        <assemblyidentity name="npoi.hpsf" publickeytoken="0df73ec7942d9264" culture="neutral"/>
        <bindingredirect oldversion="0.0.0.0-2.5.6.0" newversion="2.5.6.0"/>
      </dependentassembly>
    </assemblybinding>
  </runtime>
</configuration>

6. nuget 包配置 (packages.config)

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="npoi" version="2.5.6" targetframework="net472" />
  <package id="npoi.ooxml" version="2.5.6" targetframework="net472" />
  <package id="npoi.hpsf" version="2.5.6" targetframework="net472" />
</packages>

功能特点

1. 文件读取功能

csv文件

  • 支持逗号分隔的标准csv格式
  • 自动处理引号包围的字段
  • 支持包含逗号的字段内容
  • 自动检测列头和创建数据结构

excel文件

  • 支持.xls和.xlsx格式
  • 自动识别第一个工作表
  • 智能数据类型识别(文本、数值、日期)
  • 处理合并单元格和公式

2. 数据处理功能

数据类型推断

  • 自动识别整数、浮点数、日期和文本
  • 基于数据分布智能判断最佳类型

数据清洗

  • 自动去除多余空格
  • 处理空值和dbnull
  • 格式化日期和数字

错误处理

  • 捕获并显示文件读取错误
  • 处理格式不正确的数据行
  • 提供详细的错误信息

3. 用户界面功能

直观的操作界面

  • 清晰的按钮布局
  • 状态提示和进度指示
  • 响应式设计

数据预览

  • 自动调整列宽
  • 交替行颜色提高可读性
  • 支持滚动查看大数据集

数据导出

  • 一键导出为csv或excel
  • 保留数据类型和格式
  • 自动命名导出文件

4. 性能优化

流式读取

  • 大文件分块处理
  • 内存高效的数据加载

后台处理

  • 进度条显示加载状态
  • 异步操作防止界面冻结

资源管理

  • 及时释放文件句柄
  • 使用using语句确保资源释放

使用说明

1. 环境要求

.net framework 4.7.2 或更高版本

安装nuget包:

install-package npoi
install-package npoi.ooxml
install-package npoi.hpsf

2. 操作步骤

打开文件

  • 点击"打开csv文件"按钮选择csv文件
  • 点击"打开excel文件"按钮选择excel文件

查看数据

  • 文件加载后显示在datagridview中
  • 自动识别数据类型并显示
  • 可通过滚动条查看所有数据

导出数据

  • 加载数据后导出按钮启用
  • 点击"保存为csv"导出为csv格式
  • 点击"保存为excel"导出为excel格式

清除数据

  • 点击"清除数据"按钮清空当前显示

3. 使用示例

// 示例:在代码中直接使用读取器
var reader = new filereader();
// 读取csv文件
datatable csvdata = reader.readcsv(@"c:\data\sales.csv");
// 读取excel文件
datatable exceldata = reader.readexcel(@"c:\data\inventory.xlsx");
// 处理数据
var processor = new dataprocessor();
datatable processeddata = processor.processdatatable(csvdata);
// 导出数据
processor.exporttocsv(processeddata, @"c:\output\processed.csv");
processor.exporttoexcel(processeddata, @"c:\output\processed.xlsx");

技术亮点

1. csv解析算法

private string[] parsecsvline(string line)
{
    var fields = new list<string>();
    bool inquotes = false;
    var currentfield = new stringbuilder();
    
    for (int i = 0; i < line.length; i++)
    {
        char c = line[i];
        
        if (c == '"')
        {
            // 处理转义引号
            if (inquotes && i + 1 < line.length && line[i + 1] == '"')
            {
                currentfield.append('"');
                i++;
            }
            else
            {
                inquotes = !inquotes;
            }
        }
        else if (c == ',' && !inquotes)
        {
            // 字段结束
            fields.add(currentfield.tostring());
            currentfield.clear();
        }
        else
        {
            currentfield.append(c);
        }
    }
    
    // 添加最后一个字段
    fields.add(currentfield.tostring());
    
    return fields.toarray();
}

2. excel数据类型处理

switch (cell.celltype)
{
    case celltype.string:
        datarow[j] = cell.stringcellvalue;
        break;
    case celltype.numeric:
        if (dateutil.iscelldateformatted(cell))
        {
            datarow[j] = cell.datecellvalue.tostring("yyyy-mm-dd");
        }
        else
        {
            datarow[j] = cell.numericcellvalue;
        }
        break;
    case celltype.boolean:
        datarow[j] = cell.booleancellvalue;
        break;
    case celltype.formula:
        datarow[j] = cell.numericcellvalue;
        break;
    default:
        datarow[j] = cell.tostring();
        break;
}

3. 数据类型推断

private type infercolumntype(datatable table, string columnname)
{
    int totalrows = table.rows.count;
    if (totalrows == 0) return typeof(string);
    
    int intcount = 0;
    int doublecount = 0;
    int datecount = 0;
    int stringcount = 0;
    
    foreach (datarow row in table.rows)
    {
        // 分析每个值的类型...
    }
    
    // 根据分布确定最佳类型
    if ((double)intcount / totalrows > 0.8) return typeof(int);
    if ((double)(intcount + doublecount) / totalrows > 0.8) return typeof(double);
    if ((double)datecount / totalrows > 0.8) return typeof(datetime);
    
    return typeof(string);
}

扩展功能

1. 添加数据库支持

public class databaseexporter
{
    public void exporttosqlserver(datatable data, string connectionstring, string tablename)
    {
        using (sqlconnection connection = new sqlconnection(connectionstring))
        {
            connection.open();
            using (sqlbulkcopy bulkcopy = new sqlbulkcopy(connection))
            {
                bulkcopy.destinationtablename = tablename;
                
                // 映射列
                foreach (datacolumn column in data.columns)
                {
                    bulkcopy.columnmappings.add(column.columnname, column.columnname);
                }
                
                bulkcopy.writetoserver(data);
            }
        }
    }
}

2. 添加数据过滤功能

public datatable filterdata(datatable data, string columnname, string filtervalue)
{
    dataview dv = new dataview(data);
    dv.rowfilter = $"[{columnname}] like '%{filtervalue}%'";
    return dv.totable();
}

3. 添加数据统计功能

public datatable getsummarystatistics(datatable data)
{
    datatable summary = new datatable();
    summary.columns.add("column", typeof(string));
    summary.columns.add("type", typeof(string));
    summary.columns.add("count", typeof(int));
    summary.columns.add("nullcount", typeof(int));
    summary.columns.add("min", typeof(string));
    summary.columns.add("max", typeof(string));
    summary.columns.add("avg", typeof(string));
    
    foreach (datacolumn column in data.columns)
    {
        datarow row = summary.newrow();
        row["column"] = column.columnname;
        row["type"] = column.datatype.name;
        
        int count = data.rows.count;
        int nullcount = 0;
        double? min = null, max = null, sum = 0;
        int numericcount = 0;
        
        foreach (datarow datarow in data.rows)
        {
            object value = datarow[column];
            if (value == dbnull.value || value == null)
            {
                nullcount++;
                continue;
            }
            
            if (column.datatype == typeof(int) || column.datatype == typeof(double))
            {
                double numvalue = convert.todouble(value);
                if (!min.hasvalue || numvalue < min) min = numvalue;
                if (!max.hasvalue || numvalue > max) max = numvalue;
                sum += numvalue;
                numericcount++;
            }
        }
        
        row["count"] = count;
        row["nullcount"] = nullcount;
        row["min"] = min?.tostring() ?? "n/a";
        row["max"] = max?.tostring() ?? "n/a";
        row["avg"] = numericcount > 0 ? (sum / numericcount).tostring() : "n/a";
        
        summary.rows.add(row);
    }
    
    return summary;
}

常见问题解决

1. 文件格式问题

问题:中文乱码

解决:在读取csv时指定正确的编码

// 尝试不同编码
encoding.registerprovider(codepagesencodingprovider.instance);
using (var reader = new streamreader(filepath, encoding.getencoding("gb2312")))

2. 大文件处理

问题:加载大文件时内存不足

解决:使用分页加载

// 分批读取大文件
public datatable readlargecsv(string filepath, int batchsize = 1000)
{
    // 实现分页读取逻辑
}

3. 特殊格式处理

问题:excel中的公式值

解决:使用npoi的公式求值器

iformulaevaluator evaluator = workbook.getcreationhelper().createformulaevaluator();
cellvalue cellvalue = evaluator.evaluate(cell);

项目总结

这个c#解决方案提供了完整的csv/excel文件读取和显示功能,具有以下特点:

多格式支持

  • 支持csv和excel文件(.xls/.xlsx)
  • 智能识别文件格式
  • 处理各种数据格式和编码

强大的数据处理

  • 自动数据类型推断
  • 数据清洗和转换
  • 空值处理和错误恢复

用户友好界面

  • 直观的操作流程
  • 实时状态反馈
  • 响应式数据展示

灵活的导出功能

  • 支持csv和excel导出
  • 保留数据类型和格式
  • 自定义导出选项

健壮的错误处理

  • 全面的异常捕获
  • 详细的错误信息
  • 优雅的降级处理

以上就是c#读取csv/excel文件数据并显示在datagridview的详细内容,更多关于c#读取csv/excel数据并显示的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com