using System;
using System.Data;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections.Generic;
namespace ZcPeng.PublicLibrary
{
///
/// DataTableEx
/// 功能:操作DataTable的一些静态方法。
/// 作者:彭昭成
/// 时间:2018年12月10日
///
public static class DataTableEx
{
///
/// 将DataTable序列化成字节数组
///
/// 数据表
/// 如果序列化成功,返回字节数组;否则返回null。
public static byte[] Serialize(DataTable dt)
{
byte[] bytes = null;
if (dt != null)
{
MemoryStream ms = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
try
{
bf.Serialize(ms, dt);
bytes = ms.ToArray();
}
catch { }
ms.Close();
}
return bytes;
}
///
/// 将字节数组反序列化为DataTable对象
///
/// 字节数组
/// 返回数据表;如果失败,返回null。
public static DataTable Deserialize(byte[] bytes)
{
DataTable dt = null;
if (bytes != null && bytes.Length > 0)
{
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream(bytes);
try
{
dt = (DataTable)bf.Deserialize(ms);
}
catch { }
ms.Close();
}
return dt;
}
///
/// 从数据表中移除列名列表中的列
///
/// 数据表
/// 需要被移除的列名列表
/// 返回成功移除列的数目
public static int RemoveDataColumn(DataTable dt, List columnList)
{
int count = 0;
if (dt != null && dt.Columns != null && dt.Columns.Count > 0 && columnList != null && columnList.Count > 0)
{
foreach (string columnName in columnList)
{
if (dt.Columns.Contains(columnName))
{
DataColumn dc = dt.Columns[columnName];
if (dt.Columns.CanRemove(dc))
{
dt.Columns.Remove(dc);
count++;
}
}
}
}
return count;
}
///
/// 从数据表中移除列名列表中的列
///
/// 数据表
/// 需要被移除的列名列表
/// 返回成功移除列的数目
public static int RemoveDataColumn(DataTable dt, string[] columnList)
{
if (columnList.Length > 0)
return RemoveDataColumn(dt, new List(columnList));
else
return 0;
}
///
/// 比较两个数据表的表结构是否相同;
/// 比较过程如下:
/// (1)比较列数目是否相同;
/// (2)比较每列的列名及数据类型是否相同。
///
/// 数据表1
/// 数据表2
/// 是否需要列的次序保持一致
/// 返回比较的结果。
public static bool CompareTableStructure(DataTable dt1, DataTable dt2, bool needSameColumnOrder)
{
if (dt1 == null && dt2 == null)
return true;
if ((dt1 == null && dt2 != null) || (dt1 != null && dt2 == null))
return false;
if (dt1 != null && dt2 != null)
{
if (dt1.Columns.Count != dt2.Columns.Count) //列数目不同
return false;
for (int i = 0; i < dt1.Columns.Count; i++)
{
if (needSameColumnOrder)
{
if (dt1.Columns[i].ColumnName != dt2.Columns[i].ColumnName || dt1.Columns[i].DataType != dt2.Columns[i].DataType) //列名或者列数据类型不一致
return false;
}
else
{
DataColumn dc = dt1.Columns[i];
if (!dt2.Columns.Contains(dc.ColumnName)) //数据表2中不包含数据表1中的某列
return false;
if (dc.DataType != dt2.Columns[dc.ColumnName].DataType) //列的数据类型不同
return false;
}
}
}
return true;
}
///
/// 合并数据表:将dtSource表中的数据行添加到dtDest表的行之后
///
/// 目标数据表
/// 源数据表
/// 返回是否合并成功。
public static bool Merge(ref DataTable dtDest, DataTable dtSource)
{
if (dtSource == null || dtSource.Rows == null || dtSource.Rows.Count == 0)
return false;
if (dtDest == null)
dtDest = dtSource.Copy();
else
{
if (!CompareTableStructure(dtDest, dtSource, false)) //如果表结构不一致,返回
return false;
foreach (DataRow drSource in dtSource.Rows)
{
DataRow drNew = dtDest.NewRow();
for (int i = 0; i < dtDest.Columns.Count; i++)
drNew[i] = drSource[dtDest.Columns[i].ColumnName]; //drNew[i] = drSource[i];
dtDest.Rows.Add(drNew);
}
}
dtDest.AcceptChanges();
return true;
}
///
/// 从指定数据表中查找特定值所在的数据行
///
/// 数据表
/// 被查找的列名
/// 被查找的值
/// 如果成功找到了值所在的数据行,返回数据行;否则返回null。
public static DataRow FindDataRow(DataTable dt, string columnName, object value)
{
if (dt != null)
{
int columnIndex = dt.Columns.IndexOf(columnName);
return FindDataRow(dt, columnIndex, value);
}
else
return null;
}
///
/// 从指定数据表中查找特定值所在的数据行
///
/// 数据表
/// 被查找的列名
/// 被查找的值
/// 如果成功找到了值所在的数据行,返回数据行的索引;否则返回-1。
public static int FindDataRowIndex(DataTable dt, string columnName, object value)
{
if (dt != null)
{
int columnIndex = dt.Columns.IndexOf(columnName);
return FindDataRowIndex(dt, columnIndex, value);
}
else
return -1;
}
///
/// 从指定数据表中查找特定值所在的数据行
///
/// 数据表
/// 被查找的列索引
/// 被查找的值
/// 如果成功找到了值所在的数据行,返回数据行;否则返回null。
public static DataRow FindDataRow(DataTable dt, int columnIndex, object value)
{
int rowIndex = FindDataRowIndex(dt, columnIndex, value);
if (rowIndex != -1)
return dt.Rows[rowIndex];
else
return null;
}
///
/// 从指定数据表中查找特定值所在的数据行
///
/// 数据表
/// 被查找的列索引
/// 被查找的值
/// 如果成功找到了值所在的数据行,返回数据行的索引;否则返回-1。
public static int FindDataRowIndex(DataTable dt, int columnIndex, object value)
{
int rowIndex = -1;
if (dt != null && dt.Rows != null && dt.Rows.Count > 0 && columnIndex >= 0 && columnIndex < dt.Columns.Count)
{
Type type = value.GetType();
if (dt.Columns[columnIndex].DataType == type)
{
if (type.IsValueType || type == typeof(string))
{
for (int i = 0; i < dt.Rows.Count; i++)
{
if (dt.Rows[i][columnIndex].ToString() == value.ToString())
{
rowIndex = i;
break;
}
}
}
else
{
for (int i = 0; i < dt.Rows.Count; i++)
{
if (dt.Rows[i][columnIndex] == value)
{
rowIndex = i;
break;
}
}
}
}
}
return rowIndex;
}
///
/// 从指定数据表中查找特定值所在的数据行
///
/// 数据表
/// 关键列及值
/// 如果成功找到了值所在的数据行,返回数据行;否则返回null。
public static DataRow FindDataRow(DataTable dt, Dictionary columnIndexAndValues)
{
int rowIndex = FindDataRowIndex(dt, columnIndexAndValues);
if (rowIndex != -1)
return dt.Rows[rowIndex];
else
return null;
}
///
/// 从指定数据表中查找特定值所在的数据行
///
/// 数据表
/// 关键列及值
/// 如果成功找到了值所在的数据行,返回数据行的索引;否则返回-1。
public static int FindDataRowIndex(DataTable dt, Dictionary columnIndexAndValues)
{
int rowIndex = -1;
if (dt != null && dt.Rows != null && dt.Rows.Count > 0)
{
//检查关键列是否都有效
int columnCount = dt.Columns.Count;
foreach (KeyValuePair pair in columnIndexAndValues)
{
if (pair.Key < 0 || pair.Key >= columnCount) //索引是否在范围内
return -1;
if (dt.Columns[pair.Key].DataType != pair.Value.GetType()) //类型是否相同
return -1;
}
//依次在每行中查找
for (int i = 0; i < dt.Rows.Count; i++)
{
bool match = true;
DataRow dr = dt.Rows[i];
foreach (KeyValuePair pair in columnIndexAndValues)
{
Type type = pair.Value.GetType();
if (type.IsValueType || type == typeof(string))
{
if (dr[pair.Key].ToString() != pair.Value.ToString())
{
match = false;
break;
}
}
else
{
if (dr[pair.Key] != pair.Value)
{
match = false;
break;
}
}
}
if (match)
{
rowIndex = i;
break;
}
}
}
return rowIndex;
}
///
/// 从指定数据表中查找特定值所在的数据行
///
/// 数据表
/// 关键列及值
/// 如果成功找到了值所在的数据行,返回数据行;否则返回null。
public static DataRow FindDataRow(DataTable dt, Dictionary columnNameAndValues)
{
int rowIndex = FindDataRowIndex(dt, columnNameAndValues);
if (rowIndex != -1)
return dt.Rows[rowIndex];
else
return null;
}
///
/// 从指定数据表中查找特定值所在的数据行
///
/// 数据表
/// 关键列及值
/// 如果成功找到了值所在的数据行,返回数据行的索引;否则返回-1。
public static int FindDataRowIndex(DataTable dt, Dictionary columnNameAndValues)
{
if (dt == null || dt.Rows == null || dt.Rows.Count == 0)
return -1;
//先将关键列名转换成列号,然后再查找
Dictionary columnIndexAndValues = new Dictionary(columnNameAndValues.Count);
foreach (KeyValuePair pair in columnNameAndValues)
{
int columnIndex = dt.Columns.IndexOf(pair.Key);
if (columnIndex >= 0)
columnIndexAndValues.Add(columnIndex, pair.Value);
else
return -1;
}
return FindDataRowIndex(dt, columnIndexAndValues);
}
///
/// 汇总数据表:对于dtSource与dtDest共有的数据行,将dtSource表中的数据累加到dtDest表;对于dtSource中多出的数据行,添加到dtDest表之中;对于dtDest中多出的数据行,保持原样。
/// 注:要求dtDest和dtSource有相同的表结构,并且除了关键列之外的其他列数据类型均为整型。
///
/// 目标数据表
/// 源数据表
/// 关键列名
/// 返回是否汇总成功。
public static bool Summarize(ref DataTable dtDest, DataTable dtSource, string keyColumnName)
{
if (dtSource == null || dtSource.Rows == null || dtSource.Rows.Count == 0)
return false;
if (dtDest == null)
dtDest = dtSource.Copy();
else
{
if (!CompareTableStructure(dtDest, dtSource, false)) //如果表结构不一致,返回
return false;
if (!dtDest.Columns.Contains(keyColumnName)) //如果表中不包含关键列,返回
return false;
foreach (DataRow drSource in dtSource.Rows)
{
DataRow drDest = FindDataRow(dtDest, keyColumnName, drSource[keyColumnName]);
if (drDest != null)
{
//如果在dtDest中找到了数据行,累加数据
for (int i = 0; i < dtDest.Columns.Count; i++)
{
string columnName = dtDest.Columns[i].ColumnName;
if (columnName != keyColumnName)
drDest[i] = (Convert.IsDBNull(drDest[i]) ? 0 : (int)drDest[i]) + (Convert.IsDBNull(drSource[columnName]) ? 0 : (int)drSource[columnName]);
}
}
else
{
//如果没有找到区域对应的行,创建新行
DataRow drNew = dtDest.NewRow();
for (int i = 0; i < dtDest.Columns.Count; i++)
{
string columnName = dtDest.Columns[i].ColumnName;
drNew[i] = drSource[columnName];
}
dtDest.Rows.Add(drNew);
}
}
}
dtDest.AcceptChanges();
return true;
}
///
/// 汇总数据表:对于dtSource与dtDest共有的数据行,将dtSource表中的数据累加到dtDest表;对于dtSource中多出的数据行,添加到dtDest表之中;对于dtDest中多出的数据行,保持原样。
///
/// 目标数据表
/// 源数据表
/// 关键列索引
/// 返回是否汇总成功。
public static bool Summarize(ref DataTable dtDest, DataTable dtSource, int keyColumnIndex)
{
if (dtSource != null && keyColumnIndex >= 0 && keyColumnIndex < dtSource.Columns.Count)
{
string keyColumnName = dtSource.Columns[keyColumnIndex].ColumnName;
return Summarize(ref dtDest, dtSource, keyColumnName);
}
else
return false;
}
///
/// 汇总数据表:对于dtSource与dtDest共有的数据行,将dtSource表中的数据累加到dtDest表;对于dtSource中多出的数据行,添加到dtDest表之中;对于dtDest中多出的数据行,保持原样。
/// 注:要求dtDest和dtSource有相同的表结构,并且除了关键列之外的其他列数据类型均为整型。
///
/// 目标数据表
/// 源数据表
/// 关键列名
/// 返回是否汇总成功。
public static bool Summarize(ref DataTable dtDest, DataTable dtSource, List keyColumnNames)
{
if (dtSource == null || dtSource.Rows == null || dtSource.Rows.Count == 0)
return false;
if (dtDest == null)
dtDest = dtSource.Copy();
else
{
if (!CompareTableStructure(dtDest, dtSource, false)) //如果表结构不一致,返回
return false;
foreach (string keyColumnName in keyColumnNames)
{
if (!dtDest.Columns.Contains(keyColumnName)) //如果表中不包含关键列,返回
return false;
}
foreach (DataRow drSource in dtSource.Rows)
{
//查找关键列在源表中的值
Dictionary columnNameAndValues = new Dictionary();
foreach (string keyColumnName in keyColumnNames)
columnNameAndValues.Add(keyColumnName, drSource[keyColumnName]);
//在目标表中查找匹配的数据行
DataRow drDest = FindDataRow(dtDest, columnNameAndValues);
if (drDest != null)
{
//如果在dtDest中找到了数据行,累加数据
for (int i = 0; i < dtDest.Columns.Count; i++)
{
string columnName = dtDest.Columns[i].ColumnName;
if (!keyColumnNames.Contains(columnName))
drDest[i] = (Convert.IsDBNull(drDest[i]) ? 0 : (int)drDest[i]) + (Convert.IsDBNull(drSource[columnName]) ? 0 : (int)drSource[columnName]);
}
}
else
{
//如果没有找到区域对应的行,创建新行
DataRow drNew = dtDest.NewRow();
for (int i = 0; i < dtDest.Columns.Count; i++)
{
string columnName = dtDest.Columns[i].ColumnName;
drNew[i] = drSource[columnName];
}
dtDest.Rows.Add(drNew);
}
}
}
dtDest.AcceptChanges();
return true;
}
///
/// 汇总数据表:对于dtSource与dtDest共有的数据行,将dtSource表中的数据累加到dtDest表;对于dtSource中多出的数据行,添加到dtDest表之中;对于dtDest中多出的数据行,保持原样。
///
/// 目标数据表
/// 源数据表
/// 关键列索引
/// 返回是否汇总成功。
public static bool Summarize(ref DataTable dtDest, DataTable dtSource, List keyColumnIndexes)
{
if (dtSource != null)
{
List keyColumnNames = new List(keyColumnIndexes.Count);
int columnCount = dtSource.Columns.Count;
foreach (int keyColumnIndex in keyColumnIndexes)
{
if (keyColumnIndex >= 0 && keyColumnIndex < columnCount)
keyColumnNames.Add(dtSource.Columns[keyColumnIndex].ColumnName);
else
return false;
}
return Summarize(ref dtDest, dtSource, keyColumnNames);
}
else
return true;
}
}
}