using System; using System.Collections; using System.Data; namespace WindowsFormsApplication4 { public class MegerTable { #region 私有字段 private string LastErrInfo = String.Empty; //最后一次出错信息 #endregion public string GetLastErrInfo() { return LastErrInfo; } /// <summary> /// 将主从表进行左连接操作 /// </summary> /// <param name="mainTable">主表</param> /// <param name="subTable">从表</param> /// <param name="keyFields">关联字段</param> /// <param name="megerFields">子表要合并的字段</param> /// <returns>合并后的表</returns> public DataTable LeftJoinTabel(DataTable mainTable, DataTable subTable, string[] keyFields, string[] megerFields) { if ((keyFields.Length == 0) || (megerFields.Length == 0)) { LastErrInfo = "必须指定关联字段及要合并的字段!"; return null; } foreach (string keyField in keyFields) { if (keyField.Length == 0) { LastErrInfo = "关键字段的列名不允许为空!"; return null; } if (!mainTable.Columns.Contains(keyField)) { LastErrInfo = "主表并没有关键字段[" + keyField + "]!"; return null; } if (!subTable.Columns.Contains(keyField)) { LastErrInfo = "子表并没有关键字段[" + keyField + "]!"; return null; } } foreach (string megerField in megerFields) { if (megerField.Length == 0) { LastErrInfo = "要合并字段的列名不允许为空!"; return null; } if (!subTable.Columns.Contains(megerField)) { LastErrInfo = "子表并没有要合并的字段[" + megerField + "]!"; return null; } } if (mainTable.Rows.Count * subTable.Rows.Count < 5000) { return NestJoin(mainTable, subTable, keyFields, megerFields); } else { if ((megerFields.Length < 5) && (subTable.Rows.Count < 10000)) { return HashJoin(mainTable, subTable, keyFields, megerFields); } else { return IndexJoin(mainTable, subTable, keyFields, megerFields); } } } /// <summary> /// 嵌套循环方式。当主从表都足够小,循环总次数不超过5000时,可免去建立哈希表的开销。 /// </summary> public DataTable NestJoin(DataTable mainTable, DataTable subTable, string[] keyFields, string[] megerFields) { int mainTableSrcCols = mainTable.Columns.Count; //添加主表列 DataColumn newColumn; foreach (string colName in megerFields) { newColumn = new DataColumn(colName); if (mainTable.Columns.Contains(colName)) { newColumn.ColumnName = colName + "$"; } mainTable.Columns.Add(newColumn); } //合并表 bool same; foreach (DataRow mainRow in mainTable.Rows) { foreach (DataRow subRow in subTable.Rows) { //比较当前行的所有关键列值是否一致 same = true; foreach (string keyField in keyFields) { if (mainRow[keyField].ToString() != subRow[keyField].ToString()) { same = false; break; } } //若一致才合并 if (same) { int newColIndex = mainTableSrcCols; foreach (string megerField in megerFields) { mainRow[newColIndex++] = subRow[megerField].ToString(); } } } } return mainTable; } /// <summary> /// 哈希查询方式。当从表比较小,列数少于5且记录数少于1万时,可直接把所有行存入哈希表,就无需再查询从表。 /// </summary> public DataTable HashJoin(DataTable mainTable, DataTable subTable, string[] keyFields, string[] megerFields) { const string SEP = "#%"; //关键字段的列分隔符 int mainTableSrcCols = mainTable.Columns.Count; int subTableSrcCols = subTable.Columns.Count; //将子表放入哈希表 string key; string[] value; Hashtable hashTable = new Hashtable(); foreach (DataRow row in subTable.Rows) { key = row[keyFields[0]].ToString(); for (int i = 1; i < keyFields.Length; i++) { key += SEP + row[keyFields[i]].ToString(); } value = new string[megerFields.Length]; for (int i = 0; i < megerFields.Length; i++) { value[i] = row[megerFields[i]].ToString(); } //哈希表保存主键和实际行内容 hashTable.Add(key, value); } //添加主表列 DataColumn newColumn; foreach (string colName in megerFields) { newColumn = new DataColumn(colName); if (mainTable.Columns.Contains(colName)) { newColumn.ColumnName = colName + "$"; } mainTable.Columns.Add(newColumn); } //合并表 foreach (DataRow row in mainTable.Rows) { key = row[keyFields[0]].ToString(); for (int i = 1; i < keyFields.Length; i++) { key += SEP + row[keyFields[i]].ToString(); } if (hashTable.ContainsKey(key)) { value = hashTable[key] as string[]; for (int i = mainTableSrcCols; i < mainTable.Columns.Count; i++) { row[i] = value[i - mainTableSrcCols]; } } } return mainTable; } /// <summary> /// 哈希索引方式。当从表比较大时,只在哈希表存储索引,找根据索引到从表查询记录,可避免建立过大的哈希表。 /// </summary> public DataTable IndexJoin(DataTable mainTable, DataTable subTable, string[] keyFields, string[] megerFields) { const string SEP = "#%"; //关键字段的列分隔符 int mainTableSrcCols = mainTable.Columns.Count; int subTableSrcCols = subTable.Columns.Count; //将子表索引放入哈希表 int rowIndex = 0; string key; Hashtable hashTable = new Hashtable(); foreach (DataRow row in subTable.Rows) { key = row[keyFields[0]].ToString(); for (int i = 1; i < keyFields.Length; i++) { key += SEP + row[keyFields[i]].ToString(); } //哈希表保存主键和行索引 hashTable.Add(key, rowIndex); rowIndex++; } //添加主表列 DataColumn newColumn; foreach (string colName in megerFields) { newColumn = new DataColumn(colName); if (mainTable.Columns.Contains(colName)) { newColumn.ColumnName = colName + "$"; } mainTable.Columns.Add(newColumn); } //合并表 foreach (DataRow row in mainTable.Rows) { key = row[keyFields[0]].ToString(); for (int i = 1; i < keyFields.Length; i++) { key += SEP + row[keyFields[i]].ToString(); } if (hashTable.ContainsKey(key)) { rowIndex = (int)hashTable[key]; for (int i = mainTableSrcCols; i < mainTable.Columns.Count; i++) { row[i] = subTable.Rows[rowIndex][megerFields[i - mainTableSrcCols].ToString()]; } } } return mainTable; } } }
相关推荐
C#-DataTable操作类(添加自增列、检查是否为数据行、DataTable转换为List、List转换为DataTable,DataTable排序、DataRow转自定义实体)
在C#编程中,连接和操作数据库是常见的任务,尤其在开发桌面应用、Web应用或者服务时。本篇文章将详细讲解如何使用C#语言连接不同的数据库,并通过执行SQL语句获取DataTable对象,其中包括Access、SQL Server、...
### C# 中 DataTable 数据到 Excel 的导出及行列转换 #### 一、概述 在实际开发过程中,我们经常需要将数据库中的数据导出为 Excel 文件,以便于数据分析或分享给其他人。同时,在某些场景下还需要对数据进行行列...
在C#编程中,DataTable是System.Data命名空间中的一个类,它用于存储和操作数据集中的数据表。在处理大量数据时,有时我们需要删除DataTable中的特定...在进行这类操作时,确保正确处理行事件,避免不必要的性能损失。
在Java开发中,特别是在Android应用开发中,常常需要处理数据集合,C#中的DataTable是一种非常方便的数据结构,它允许我们动态地存储和操作表格数据。然而,Java原生API并没有提供与之对应的类。这篇博客(博文链接...
DataTable是System.Data命名空间中的一个类,它代表了一个可以在内存中存储和操作数据的表格。在处理数据库数据或者进行数据操作时,DataTable是一个非常实用的工具。本文将深入探讨如何在C#中利用DataTable进行`...
Excel文件可能包含多个工作表,通过工作表索引(默认为0)选择要读取的工作表。 ```csharp ISheet sheet = workbook.GetSheetAt(0); ``` 6. **创建DataTable对象**: 初始化一个新的DataTable对象,用于存储...
首先,解释了 DataSet 和 DataTable 的不同之处,其中 DataSet 是数据集,可以包含多个 DataTable,而 DataTable 是数据表,存储具体的数据行。接着,文中介绍了 DataSet 的多种创建方式、常用方法、属性、事件及其...
本篇将详细介绍如何使用C#结合Aspose.Cells.dll来高效地导出数据表(DataTable)到Excel。 首先,确保已将Aspose.Cells库添加到项目中。这可以通过NuGet包管理器完成,搜索"Aspose.Cells"并安装对应的版本。安装...
在C#编程环境中,NPOI提供了一种强大的方式来读取、写入和操作Excel文件,而无需依赖Microsoft Office。这个“NPOI操作实例C# ExcelToDataTable DataTableToExcel”是一个很好的学习资源,它展示了如何在C# WinForm...
在C#编程中,DataTable是一种常用的结构,用于存储和操作数据,类似于数据库表格。当我们处理多个DataTable时,可能需要比较它们之间的数据,找出交集、并集或差集。这在数据分析、数据清洗或者数据库同步等场景中...
在.NET框架中,DataTable是一个非常常用的类,它用于存储和操作数据,类似于数据库中的表格。在许多业务场景中,我们可能需要将DataTable中的数据展示在DataGridView控件中,并且提供打印功能,以便用户可以将数据...
### C# DataTable 数据表的操作详解 #### 一、概述 在C#开发中,`DataTable` 是一个非常重要的数据结构,它提供了类似数据库表格的功能,用于存储和操作数据集。本文将详细介绍如何在C#中操作`DataTable`,特别是...
- `NPOI.HSSF` 系列命名空间提供了操作Excel文件的功能。 ##### 3.2 创建Excel类 ```csharp public class Excel { private HSSFWorkbook _workBook; private ISheet _wbSheet = null; private ...
`DataTable`是.NET框架中的一个类,它代表了一个可以存储和操作数据的表格结构,类似于数据库中的表。你可以通过执行SQL查询或者使用ADO.NET的数据适配器从数据库中填充一个`DataTable`。 生成Excel文件的过程通常...
这个库允许C#代码与Excel应用程序进行交互,创建、修改和操作Excel工作簿。不过,需要注意的是,使用此库需要在开发机器上安装Office软件。 `ExportDataGrid.cs`可能是实现数据导出功能的主要代码文件。以下是一个...
在C#编程中,将数据从List和DataTable导出到Excel是一种常见的需求,尤其在数据处理和报告生成的场景下。这个功能允许开发者轻松地将程序内部的数据结构转换为用户可读的电子表格格式,如Microsoft Excel。Open XML ...
在.NET开发环境中,C#语言提供了多种方式来操作Excel文件,包括使用Microsoft Office Interop库、第三方库如EPPlus、NPOI等。本主题主要围绕C#如何使用不同的方法来处理Excel,尤其是将DataTable数据写入Excel文件,...
首先,`DataTable`类是`System.Data`命名空间的一部分,它允许开发者创建一个类似于数据库表的数据结构。`DataTable`可以包含多个`DataColumn`,用于定义列的类型和约束,以及`DataRow`,用于存储实际的数据行。`...