当前位置: 首页 > news >正文

.NET Framework 4.0可用EXCEL导入至DataTable

需要用到的控件为:button1    ;

                                openFileDialog;

                                dataGridView

    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. 获取活动工作表URIUri 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;}// 辅助方法:获取活动工作表URIprivate 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;elsebreak;}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

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

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

界面展示:

相关文章:

  • 如何保证高防服务器中的系统安全?
  • Linux系统的延迟任务及定时任务
  • 阶段性人生答疑解惑篇:穿越市场迷雾,重构生命坐标系
  • 从数据到智慧:解密机器学习的自主学习密码
  • 下篇:深入剖析 BLE GATT / GAP / SMP 与应用层(约5000字)
  • .NET代码保护混淆和软件许可系统——Eziriz .NET Reactor 7
  • React-JSX语法
  • 第七届能源系统与电气电力国际学术会议(ICESEP 2025)
  • 深入探索RAG(检索增强生成)模型的优化技巧
  • 考研系列-计算机组成原理第二章:数据的表示和运算
  • 【UML建模】starUML工具
  • synchronized关键字的实现
  • 第二篇:Django配置及ORM操作
  • 金融软件测试有哪些注意事项?专业第三方软件测试服务机构分享
  • 【leetcode100】组合总和Ⅳ
  • AIP代码生成器——标准化接口开发智能工具
  • 算法之分支定界
  • 多语言虚拟币海外游戏娱乐平台源码详解(整合篇)
  • 架构-系统可靠性分析与设计
  • 复杂性决策-思维训练
  • 铁线礁、牛轭礁珊瑚礁“体检”报告首次发布,专家:菲非法活动产生胁迫性影响
  • 两部门:推动“青年驿站”为毕业生跨地区求职提供住宿优惠便利
  • “五一”前多地市监部门告诫经营者:对预订客房不得毁约提价
  • 儒说︱问世间孝为何物
  • 华夏银行青岛分行另类处置不良债权,德州近百亩土地被神奇操作抵押贷款
  • 马上评丨电子屏不如黑板?解决问题不能靠怀旧