最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#讀取CSV/Excel文件數(shù)據(jù)并顯示在DataGridView

 更新時間:2026年04月16日 08:55:59   作者:hoiii187  
本文介紹了C#讀取CSV和Excel文件數(shù)據(jù)并展示在DataGridView控件中的解決方案,該方案包括文件讀取、數(shù)據(jù)處理、用戶界面、性能優(yōu)化等功能特點,并提供了詳細的使用方法和常見問題解決方案,旨在實現(xiàn)多格式支持、智能識別、強大數(shù)據(jù)處理和用戶友好界面

C# 用于讀取 CSV 和 Excel 文件數(shù)據(jù)并顯示在 DataGridView 控件中,支持文件選擇、數(shù)據(jù)預(yù)覽、格式處理和錯誤處理等功能。

解決方案結(jié)構(gòu)

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

完整代碼實現(xiàn)

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()
        {
            // 窗體設(shè)置
            this.Text = "CSV/Excel 數(shù)據(jù)讀取器";
            this.Size = new Size(900, 600);
            this.StartPosition = FormStartPosition.CenterScreen;
            this.BackColor = Color.FromArgb(240, 240, 240);
            
            // 創(chuàng)建控件
            lblTitle = new Label
            {
                Text = "CSV/Excel 數(shù)據(jù)讀取器",
                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 = "清除數(shù)據(jù)",
                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;
            
            // 狀態(tài)標簽
            lblStatus = new Label
            {
                Text = "就緒",
                AutoSize = true,
                Location = new Point(30, 120),
                Font = new Font("微軟雅黑", 9),
                ForeColor = Color.DimGray
            };
            
            // 數(shù)據(jù)網(wǎng)格視圖
            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 = $"數(shù)據(jù)已成功導(dǎo)出到: {saveFileDialog.FileName}";
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show($"導(dǎo)出失敗: {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 = $"數(shù)據(jù)已成功導(dǎo)出到: {saveFileDialog.FileName}";
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show($"導(dǎo)出失敗: {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 = "數(shù)據(jù)已清除";
        }
        #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 = "文件為空或未找到數(shù)據(jù)";
                    return;
                }
                
                // 數(shù)據(jù)預(yù)處理
                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)
                    {
                        // 創(chuàng)建列
                        foreach (string field in fields)
                        {
                            dataTable.Columns.Add(field);
                        }
                        isFirstRow = false;
                    }
                    else
                    {
                        // 添加行數(shù)據(jù)
                        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 == '"')
                {
                    // 處理轉(zhuǎn)義引號
                    if (inQuotes && i + 1 < line.Length && line[i + 1] == '"')
                    {
                        currentField.Append('"');
                        i++;
                    }
                    else
                    {
                        inQuotes = !inQuotes;
                    }
                }
                else if (c == ',' && !inQuotes)
                {
                    // 字段結(jié)束
                    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))
            {
                // 根據(jù)擴展名創(chuàng)建不同的工作簿
                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;
                
                // 創(chuàng)建列
                for (int i = 0; i < headerRow.LastCellNum; i++)
                {
                    ICell cell = headerRow.GetCell(i);
                    string columnName = cell?.ToString() ?? $"Column{i + 1}";
                    dataTable.Columns.Add(columnName);
                }
                
                // 添加數(shù)據(jù)行
                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. 數(shù)據(jù)處理類 (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數(shù)據(jù)(類型轉(zhuǎn)換、空值處理等)
        /// </summary>
        public DataTable ProcessDataTable(DataTable inputTable)
        {
            if (inputTable == null) return null;
            
            DataTable processedTable = inputTable.Clone();
            
            // 處理列數(shù)據(jù)類型
            foreach (DataColumn column in processedTable.Columns)
            {
                // 嘗試推斷列的數(shù)據(jù)類型
                Type inferredType = InferColumnType(inputTable, column.ColumnName);
                if (inferredType != null)
                {
                    column.DataType = inferredType;
                }
            }
            
            // 處理行數(shù)據(jù)
            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;
                    }
                    
                    // 處理數(shù)值類型
                    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>
        /// 推斷列的數(shù)據(jù)類型
        /// </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%以上的值都是整數(shù),則認為是整數(shù)類型
            if ((double)intCount / totalRows > 0.8) return typeof(int);
            
            // 如果80%以上的值都是浮點數(shù),則認為是浮點數(shù)類型
            if ((double)(intCount + doubleCount) / totalRows > 0.8) return typeof(double);
            
            // 如果80%以上的值都是日期,則認為是日期類型
            if ((double)dateCount / totalRows > 0.8) return typeof(DateTime);
            
            return typeof(string);
        }

        /// <summary>
        /// 導(dǎo)出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();
                
                // 寫入數(shù)據(jù)行
                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>
        /// 轉(zhuǎn)義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>
        /// 導(dǎo)出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");
            
            // 創(chuàng)建標題行
            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);
                
                // 設(shè)置標題樣式
                ICellStyle style = workbook.CreateCellStyle();
                IFont font = workbook.CreateFont();
                font.Boldweight = (short)FontBoldWeight.Bold;
                style.SetFont(font);
                cell.CellStyle = style;
            }
            
            // 填充數(shù)據(jù)
            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());
                    }
                }
            }
            
            // 自動調(diào)整列寬
            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>
        /// 應(yīng)用程序的主入口點。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
    }
}

5. 應(yīng)用程序配置文件 (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格式
  • 自動處理引號包圍的字段
  • 支持包含逗號的字段內(nèi)容
  • 自動檢測列頭和創(chuàng)建數(shù)據(jù)結(jié)構(gòu)

Excel文件

  • 支持.xls和.xlsx格式
  • 自動識別第一個工作表
  • 智能數(shù)據(jù)類型識別(文本、數(shù)值、日期)
  • 處理合并單元格和公式

2. 數(shù)據(jù)處理功能

數(shù)據(jù)類型推斷

  • 自動識別整數(shù)、浮點數(shù)、日期和文本
  • 基于數(shù)據(jù)分布智能判斷最佳類型

數(shù)據(jù)清洗

  • 自動去除多余空格
  • 處理空值和DBNull
  • 格式化日期和數(shù)字

錯誤處理

  • 捕獲并顯示文件讀取錯誤
  • 處理格式不正確的數(shù)據(jù)行
  • 提供詳細的錯誤信息

3. 用戶界面功能

直觀的操作界面

  • 清晰的按鈕布局
  • 狀態(tài)提示和進度指示
  • 響應(yīng)式設(shè)計

數(shù)據(jù)預(yù)覽

  • 自動調(diào)整列寬
  • 交替行顏色提高可讀性
  • 支持滾動查看大數(shù)據(jù)集

數(shù)據(jù)導(dǎo)出

  • 一鍵導(dǎo)出為CSV或Excel
  • 保留數(shù)據(jù)類型和格式
  • 自動命名導(dǎo)出文件

4. 性能優(yōu)化

流式讀取

  • 大文件分塊處理
  • 內(nèi)存高效的數(shù)據(jù)加載

后臺處理

  • 進度條顯示加載狀態(tài)
  • 異步操作防止界面凍結(jié)

資源管理

  • 及時釋放文件句柄
  • 使用using語句確保資源釋放

使用說明

1. 環(huán)境要求

.NET Framework 4.7.2 或更高版本

安裝NuGet包:

Install-Package NPOI
Install-Package NPOI.OOXML
Install-Package NPOI.HPSF

2. 操作步驟

打開文件

  • 點擊"打開CSV文件"按鈕選擇CSV文件
  • 點擊"打開Excel文件"按鈕選擇Excel文件

查看數(shù)據(jù)

  • 文件加載后顯示在DataGridView中
  • 自動識別數(shù)據(jù)類型并顯示
  • 可通過滾動條查看所有數(shù)據(jù)

導(dǎo)出數(shù)據(jù)

  • 加載數(shù)據(jù)后導(dǎo)出按鈕啟用
  • 點擊"保存為CSV"導(dǎo)出為CSV格式
  • 點擊"保存為Excel"導(dǎo)出為Excel格式

清除數(shù)據(jù)

  • 點擊"清除數(shù)據(jù)"按鈕清空當(dāng)前顯示

3. 使用示例

// 示例:在代碼中直接使用讀取器
var reader = new FileReader();
// 讀取CSV文件
DataTable csvData = reader.ReadCsv(@"C:\data\sales.csv");
// 讀取Excel文件
DataTable excelData = reader.ReadExcel(@"C:\data\inventory.xlsx");
// 處理數(shù)據(jù)
var processor = new DataProcessor();
DataTable processedData = processor.ProcessDataTable(csvData);
// 導(dǎo)出數(shù)據(jù)
processor.ExportToCsv(processedData, @"C:\output\processed.csv");
processor.ExportToExcel(processedData, @"C:\output\processed.xlsx");

技術(shù)亮點

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 == '"')
        {
            // 處理轉(zhuǎn)義引號
            if (inQuotes && i + 1 < line.Length && line[i + 1] == '"')
            {
                currentField.Append('"');
                i++;
            }
            else
            {
                inQuotes = !inQuotes;
            }
        }
        else if (c == ',' && !inQuotes)
        {
            // 字段結(jié)束
            fields.Add(currentField.ToString());
            currentField.Clear();
        }
        else
        {
            currentField.Append(c);
        }
    }
    
    // 添加最后一個字段
    fields.Add(currentField.ToString());
    
    return fields.ToArray();
}

2. Excel數(shù)據(jù)類型處理

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. 數(shù)據(jù)類型推斷

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)
    {
        // 分析每個值的類型...
    }
    
    // 根據(jù)分布確定最佳類型
    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. 添加數(shù)據(jù)庫支持

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. 添加數(shù)據(jù)過濾功能

public DataTable FilterData(DataTable data, string columnName, string filterValue)
{
    DataView dv = new DataView(data);
    dv.RowFilter = $"[{columnName}] LIKE '%{filterValue}%'";
    return dv.ToTable();
}

3. 添加數(shù)據(jù)統(tǒng)計功能

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. 大文件處理

問題:加載大文件時內(nèi)存不足

解決:使用分頁加載

// 分批讀取大文件
public DataTable ReadLargeCsv(string filePath, int batchSize = 1000)
{
    // 實現(xiàn)分頁讀取邏輯
}

3. 特殊格式處理

問題:Excel中的公式值

解決:使用NPOI的公式求值器

IFormulaEvaluator evaluator = workbook.GetCreationHelper().CreateFormulaEvaluator();
CellValue cellValue = evaluator.Evaluate(cell);

項目總結(jié)

這個C#解決方案提供了完整的CSV/Excel文件讀取和顯示功能,具有以下特點:

多格式支持

  • 支持CSV和Excel文件(.xls/.xlsx)
  • 智能識別文件格式
  • 處理各種數(shù)據(jù)格式和編碼

強大的數(shù)據(jù)處理

  • 自動數(shù)據(jù)類型推斷
  • 數(shù)據(jù)清洗和轉(zhuǎn)換
  • 空值處理和錯誤恢復(fù)

用戶友好界面

  • 直觀的操作流程
  • 實時狀態(tài)反饋
  • 響應(yīng)式數(shù)據(jù)展示

靈活的導(dǎo)出功能

  • 支持CSV和Excel導(dǎo)出
  • 保留數(shù)據(jù)類型和格式
  • 自定義導(dǎo)出選項

健壯的錯誤處理

  • 全面的異常捕獲
  • 詳細的錯誤信息
  • 優(yōu)雅的降級處理

以上就是C#讀取CSV/Excel文件數(shù)據(jù)并顯示在DataGridView的詳細內(nèi)容,更多關(guān)于C#讀取CSV/Excel數(shù)據(jù)并顯示的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 在.NET項目中嵌入Python代碼的實踐指南

    在.NET項目中嵌入Python代碼的實踐指南

    在現(xiàn)代開發(fā)中,.NET 與 Python 的協(xié)作需求日益增長,從機器學(xué)習(xí)模型集成到科學(xué)計算,從腳本自動化到數(shù)據(jù)分析,然而,傳統(tǒng)的解決方案(如 HTTP API 或進程間通信)往往帶來性能損耗和復(fù)雜架構(gòu),所以本文給大家介紹了在.NET項目中嵌入Python代碼的方法,需要的朋友可以參考下
    2025-08-08
  • C#中的modbus Tcp協(xié)議的數(shù)據(jù)抓取和使用解析

    C#中的modbus Tcp協(xié)議的數(shù)據(jù)抓取和使用解析

    這篇文章主要介紹了C#中的modbus Tcp協(xié)議的數(shù)據(jù)抓取和使用解析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • C# 清除cookies的代碼

    C# 清除cookies的代碼

    不同的瀏覽器會把cookie文件保存在不同的地方.這篇文章主要介紹了C# 清除cookies的代碼,需要的朋友可以參考下
    2016-10-10
  • C#操作進程的方法介紹

    C#操作進程的方法介紹

    這篇文章介紹了C#操作進程的方法,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-02-02
  • 關(guān)于C#執(zhí)行順序帶來的一些潛在問題

    關(guān)于C#執(zhí)行順序帶來的一些潛在問題

    這篇文章主要給大家介紹了關(guān)于C#執(zhí)行順序帶來的一些潛在問題,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用C#具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • c# datetime方法應(yīng)用介紹

    c# datetime方法應(yīng)用介紹

    本文將詳細介紹c# datetime方法應(yīng)用,需要了解更多的朋友可以參考下
    2012-11-11
  • C#中使用反射獲取結(jié)構(gòu)體實例及思路

    C#中使用反射獲取結(jié)構(gòu)體實例及思路

    一般用反射獲取類對象的實例比較簡單,只要類有一個無參構(gòu)造函數(shù)或沒有顯示聲明帶參的構(gòu)造函數(shù)即可使用
    2013-10-10
  • C#?wpf實現(xiàn)控件刷新的示例代碼

    C#?wpf實現(xiàn)控件刷新的示例代碼

    這篇文章主要為大家詳細介紹了C#?wpf實現(xiàn)控件刷新的相關(guān)知識,文中的示例代碼講解詳細,具有一定的借鑒價值,需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-01-01
  • Unity3D UGUI實現(xiàn)翻書特效

    Unity3D UGUI實現(xiàn)翻書特效

    這篇文章主要為大家詳細介紹了Unity3D UGUI實現(xiàn)翻書特效,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • C# 文件拖拽和pixturBox縮放與拖拽功能

    C# 文件拖拽和pixturBox縮放與拖拽功能

    這篇文章主要介紹了C# 文件拖拽和pixturBox縮放與拖拽功能,代碼簡單易懂,非常不錯具有參考借鑒價值,需要的朋友可以參考下
    2017-10-10

最新評論

名山县| 崇礼县| 罗甸县| 会理县| 黄大仙区| 阿合奇县| 阳江市| 新干县| 绥芬河市| 南郑县| 西昌市| 上高县| 无锡市| 开封市| 蓬莱市| 外汇| 两当县| 中方县| 七台河市| 南宫市| 益阳市| 山东| 四会市| 甘南县| 西贡区| 常熟市| 都匀市| 安泽县| 怀化市| 嘉善县| 宁强县| 山西省| 中方县| 黄大仙区| 宁阳县| 夏河县| 扶沟县| 海原县| 蒙城县| 博兴县| 蓬安县|