.NET Framework 4.0可用EXCEL导入至DataTable

需要用到的控件为:button1 ;

openFileDialog;

dataGridView

cs 复制代码
    private void button1_Click(object sender, EventArgs e)
    {
        if (openFileDialog1.ShowDialog() == DialogResult.OK)
        {
            try
            {
                DataTable excelData = ReadExcelToDataTable(openFileDialog1.FileName);

                if (excelData.Rows.Count > 0)
                {
                    // 输出数据
                    dataGridView1.DataSource = excelData;
                }
                else
                {

                }
                
            }
            catch (Exception ex)
            {
                MessageBox.Show("Excel数据导入失败!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
    }
    public DataTable ReadExcelToDataTable(string filePath)
    {
        DataTable dt = new DataTable();

        // 1. 打开Excel文件作为ZIP存档
        using (Package excelPackage = Package.Open(filePath, FileMode.Open, FileAccess.Read))
        {
            // 2. 读取共享字符串表
            List<string> sharedStrings = ReadSharedStrings(excelPackage);

            // 3. 获取活动工作表URI
            Uri sheetUri = GetActiveWorksheetUri(excelPackage);
            if (sheetUri == null)
            {
                // 备用方案:尝试获取第一个工作表
                sheetUri = GetFirstWorksheetUri(excelPackage);
                if (sheetUri == null)
                    throw new Exception("Excel文件中未找到任何工作表");
            }

            // 4. 读取工作表数据
            PackagePart worksheetPart = excelPackage.GetPart(sheetUri);
            using (Stream worksheetStream = worksheetPart.GetStream())
            using (XmlReader reader = XmlReader.Create(worksheetStream))
            {
                bool isFirstRow = true;
                int maxColumns = 0;

                // 先确定最大列数
                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element && reader.Name == "row")
                    {
                        using (XmlReader rowReader = reader.ReadSubtree())
                        {
                            int colCount = 0;
                            while (rowReader.Read())
                            {
                                if (rowReader.NodeType == XmlNodeType.Element && rowReader.Name == "c")
                                {
                                    colCount++;
                                }
                            }
                            maxColumns = Math.Max(maxColumns, colCount);
                        }
                    }
                }

                // 重置流位置
                worksheetStream.Seek(0, SeekOrigin.Begin);
                XmlReader reader1 = XmlReader.Create(worksheetStream);

                // 创建足够多的列
                for (int i = 0; i < maxColumns; i++)
                {
                    dt.Columns.Add($"Column{i + 1}");
                }

                // 读取实际数据
                while (reader1.Read())
                {
                    if (reader1.NodeType == XmlNodeType.Element && reader1.Name == "row")
                    {
                        DataRow row = dt.NewRow();
                        int currentColIndex = 0;

                        using (XmlReader rowReader = reader1.ReadSubtree())
                        {
                            while (rowReader.Read())
                            {
                                if (rowReader.NodeType == XmlNodeType.Element && rowReader.Name == "c")
                                {
                                    string cellReference = rowReader.GetAttribute("r"); // 如"A1"
                                    string cellType = rowReader.GetAttribute("t");
                                    string cellValue = string.Empty;

                                    // 确定当前列索引
                                    currentColIndex = GetColumnIndexFromReference(cellReference);

                                    // 读取单元格值(如果有)
                                    if (rowReader.ReadToDescendant("v"))
                                    {
                                        cellValue = rowReader.ReadElementContentAsString();

                                        // 处理共享字符串
                                        if (cellType == "s")
                                        {
                                            int index = int.Parse(cellValue);
                                            if (index < sharedStrings.Count)
                                                cellValue = sharedStrings[index];
                                        }
                                    }

                                    // 确保列索引在范围内
                                    if (currentColIndex >= 0 && currentColIndex < dt.Columns.Count)
                                    {
                                        row[currentColIndex] = cellValue;
                                    }
                                }
                            }
                        }

                        // 填充空单元格
                        for (int i = 0; i < dt.Columns.Count; i++)
                        {
                            if (row[i] == null || row[i] == DBNull.Value)
                            {
                                row[i] = string.Empty;
                            }
                        }

                        dt.Rows.Add(row);
                    }
                }
            }
        }
        return dt;
    }

    // 辅助方法:读取共享字符串表
    private List<string> ReadSharedStrings(Package excelPackage)
    {
        List<string> sharedStrings = new List<string>();

        Uri sharedStringsUri = new Uri("/xl/sharedStrings.xml", UriKind.Relative);
        if (excelPackage.PartExists(sharedStringsUri))
        {
            PackagePart sharedStringsPart = excelPackage.GetPart(sharedStringsUri);
            using (Stream sharedStringsStream = sharedStringsPart.GetStream())
            using (XmlReader reader = XmlReader.Create(sharedStringsStream))
            {
                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element && reader.Name == "t")
                    {
                        string text = reader.ReadElementContentAsString();
                        sharedStrings.Add(text);
                    }
                }
            }
        }

        return sharedStrings;
    }

    // 辅助方法:获取活动工作表URI
    private Uri GetActiveWorksheetUri(Package excelPackage)
    {
        // 1. 读取workbook.xml获取所有工作表信息
        Uri workbookUri = new Uri("/xl/workbook.xml", UriKind.Relative);
        PackagePart workbookPart = excelPackage.GetPart(workbookUri);

        Dictionary<string, Tuple<string, bool>> sheets = new Dictionary<string, Tuple<string, bool>>();

        using (Stream workbookStream = workbookPart.GetStream())
        using (XmlReader reader = XmlReader.Create(workbookStream))
        {
            while (reader.Read())
            {
                if (reader.NodeType == XmlNodeType.Element && reader.Name == "sheet")
                {
                    string name = reader.GetAttribute("name");
                    string sheetId = reader.GetAttribute("sheetId");
                    string state = reader.GetAttribute("state"); // 活动状态
                    bool isActive = (state == "visible" || string.IsNullOrEmpty(state));

                    sheets.Add(sheetId, Tuple.Create(name, isActive));
                }
            }
        }

        // 2. 读取workbook.xml.rels获取实际路径
        Uri workbookRelsUri = new Uri("/xl/_rels/workbook.xml.rels", UriKind.Relative);
        PackagePart workbookRelsPart = excelPackage.GetPart(workbookRelsUri);

        Dictionary<string, string> sheetPaths = new Dictionary<string, string>();

        using (Stream relsStream = workbookRelsPart.GetStream())
        using (XmlReader reader = XmlReader.Create(relsStream))
        {
            while (reader.Read())
            {
                if (reader.NodeType == XmlNodeType.Element && reader.Name == "Relationship")
                {
                    string id = reader.GetAttribute("Id");
                    string target = reader.GetAttribute("Target");
                    if (target.StartsWith("worksheets/"))
                    {
                        sheetPaths.Add(id, target);
                    }
                }
            }
        }

        // 3. 查找活动工作表
        foreach (var sheet in sheets)
        {
            if (sheet.Value.Item2) // 如果是活动工作表
            {
                string sheetId = sheet.Key;
                if (sheetPaths.ContainsKey($"rId{sheetId}"))
                {
                    return new Uri("/xl/" + sheetPaths[$"rId{sheetId}"], UriKind.Relative);
                }
            }
        }

        // 如果没有明确标记的活动工作表,返回第一个可见工作表
        foreach (var sheet in sheets)
        {
            string sheetId = sheet.Key;
            if (sheetPaths.ContainsKey($"rId{sheetId}"))
            {
                return new Uri("/xl/" + sheetPaths[$"rId{sheetId}"], UriKind.Relative);
            }
        }

        return null;
    }

    // 辅助方法:从单元格引用获取列索引(如"A1" -> 0)
    private int GetColumnIndexFromReference(string cellReference)
    {
        if (string.IsNullOrEmpty(cellReference))
            return -1;

        string columnPart = string.Empty;
        foreach (char c in cellReference)
        {
            if (char.IsLetter(c))
                columnPart += c;
            else
                break;
        }

        if (string.IsNullOrEmpty(columnPart))
            return -1;

        int index = 0;
        foreach (char c in columnPart)
        {
            index = index * 26 + (char.ToUpper(c) - 'A' + 1);
        }

        return index - 1; // 转为0-based索引
    }


    // 获取第一个工作表URI(备用方案)
    private Uri GetFirstWorksheetUri(Package excelPackage)
    {
        Uri workbookUri = new Uri("/xl/workbook.xml", UriKind.Relative);
        PackagePart workbookPart = excelPackage.GetPart(workbookUri);

        using (Stream workbookStream = workbookPart.GetStream())
        using (XmlReader reader = XmlReader.Create(workbookStream))
        {
            while (reader.Read())
            {
                if (reader.NodeType == XmlNodeType.Element && reader.Name == "sheet")
                {
                    string sheetId = reader.GetAttribute("sheetId");
                    return new Uri($"/xl/worksheets/sheet{sheetId}.xml", UriKind.Relative);
                }
            }
        }

        return null;
    }

}

导入格式XLSX

上述代码可进一步改进报错信息

cs 复制代码
            try
            {
using (FileStream stream = File.Open(openFileDialog1.FileName, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            {
            catch (IOException)
            {
            MessageBox.Show($"文件已被占用", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }

界面展示:

相关推荐
电商api接口开发3 小时前
ASP.NET MVC 入门指南
c#·asp.net·mvc
我不是程序猿儿4 小时前
[C#]反射的实战应用,实际数据模拟
开发语言·c#
爱编程的鱼4 小时前
C# 结构(Struct)
开发语言·人工智能·算法·c#
是阿根5 小时前
unity使用iTextSharp生成PDF文件
unity·c#·游戏引擎
WineMonk9 小时前
C#多线程访问资源
c#
Bardb9 小时前
04-stm32的标准外设库
stm32·c#
风,停下9 小时前
C#基于Sunnyui框架和MVC模式实现用户登录管理
设计模式·c#·mvc
钢铁男儿9 小时前
C# 实战_RichTextBox选中某一行条目高亮,离开恢复
开发语言·c#
千叶真尹12 小时前
【无标题】
c#·linq