该软件作用 Excel 的辅助,可以执行excel不方便的操作,从excel复制数据到软件进行操作又复制回Excel。
下载软件地址 ,大小:65kb
点击下载
完整UI
列操作 右键单击列名弹出菜单
单元格操作 右键单击单元格弹出菜单
导航模式 每个操作都可以返回后退
代码
采用c# winform 写的
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Collections;
using System.Globalization;
using System.Collections.Concurrent;
using System.Diagnostics;
namespace Form_Dev
{
public partial class Form1 : Form
{
string exePath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
string fileName { get { return exePath + "myDataTable.csv"; } }
DataTable _dataTable = new DataTable { };
int curr_history_index = 0;
List<DataTable> dataTable_history = new List<DataTable>();
/// <summary>
/// 撤销和恢复 模式,不记录表格数据了
/// </summary>
bool Undo_Redo_Mode = false;
DataTable dataTable_0000
{
get { return _dataTable; }
set
{
// 追加数据到历史记录
if (Undo_Redo_Mode == false)
{
//克隆的 DataTable 中的数据
DataTable clonedDataTable = value.Clone();
foreach (DataRow row in value.Rows)
{
clonedDataTable.ImportRow(row); // 导入原始 DataTable 中的每一行数据到克隆的 DataTable
}
// Clone一个新的DataTable加入列表,而非只是对DataTable对象的引用
dataTable_history.Add(clonedDataTable);
curr_history_index = dataTable_history.Count - 1;
}
//克隆的 DataTable 中的数据
DataTable clonedDataTable2 = value.Clone();
foreach (DataRow row in value.Rows)
{
clonedDataTable2.ImportRow(row); // 导入原始 DataTable 中的每一行数据到克隆的 DataTable
}
DataTable clonedDataTable3 = value.Clone();
foreach (DataRow row in value.Rows)
{
clonedDataTable3.ImportRow(row); // 导入原始 DataTable 中的每一行数据到克隆的 DataTable
}
//清空表格数据
_dataTable.Reset();
_dataTable = clonedDataTable3;
//显示表格
_dataTable.Locale = new CultureInfo("zh-CN");
//关闭自动计算列宽度,改为手动计算,当列数自动计算就报错了,默认列宽100,最大值65535,当超过600列就报错了。所以手动计算
dataGridView1.AutoGenerateColumns = false;
//清除上次显示结构
dataGridView1.Columns.Clear();
// 手动为DataGridView添加列并设置FillWeight
int totalFillWeight = 65535;
int reservedWidth = 100; // 预留宽度,用于标题和边框
int columnCount = _dataTable.Columns.Count;
if (columnCount > 0)
{
// 计算每列的平均填充宽度
int averageFillWeight = (totalFillWeight - reservedWidth) / columnCount;
if (averageFillWeight > 200)//防止列少时 ,超过200
{
averageFillWeight = 200;
}
foreach (DataColumn column in _dataTable.Columns)
{
DataGridViewTextBoxColumn gridColumn = new DataGridViewTextBoxColumn();
gridColumn.DataPropertyName = column.ColumnName;
gridColumn.HeaderText = column.ColumnName;
gridColumn.Name = column.ColumnName;
gridColumn.FillWeight = averageFillWeight; // 使用计算出的平均宽度
dataGridView1.Columns.Add(gridColumn);
}
}
dataGridView1.DataSource = _dataTable;
// 设置所有列的单元格内容居中显示
foreach (DataGridViewColumn column in dataGridView1.Columns)
{
column.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
}
// 设置列名居中显示
dataGridView1.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
// 刷新 DataGridView 显示
dataGridView1.Refresh();
// 更新显示
textBox1.AppendText(GetTableSchema(value) + Environment.NewLine);
this.textBox2.Text = "行row : " + _dataTable.Rows.Count + " ,列col : " + _dataTable.Columns.Count;
textBox3.Text = dataTable_history.Count + "";
textBox5.Text = curr_history_index + 1 + "";
//保存到文件
SaveDataTableToFile(_dataTable);
if (Undo_Redo_Mode)//恢复 清空表格数据 操作的数据
{
dataTable_history[curr_history_index] = clonedDataTable2;
}
}
}
public DataTable dataTable
{
get { return _dataTable; }
set
{
// 追加数据到历史记录
if (Undo_Redo_Mode == false)
{
//克隆的 DataTable 中的数据
DataTable clonedDataTable = value.Clone();
foreach (DataRow row in value.Rows)
{
clonedDataTable.ImportRow(row); // 导入原始 DataTable 中的每一行数据到克隆的 DataTable
}
// Clone一个新的DataTable加入列表,而非只是对DataTable对象的引用
dataTable_history.Add(clonedDataTable);
curr_history_index = dataTable_history.Count - 1;
}
//克隆的 DataTable 中的数据
DataTable clonedDataTable2 = value.Clone();
foreach (DataRow row in value.Rows)
{
clonedDataTable2.ImportRow(row); // 导入原始 DataTable 中的每一行数据到克隆的 DataTable
}
DataTable clonedDataTable3 = value.Clone();
foreach (DataRow row in value.Rows)
{
clonedDataTable3.ImportRow(row); // 导入原始 DataTable 中的每一行数据到克隆的 DataTable
}
//清空表格数据
_dataTable.Reset();
_dataTable = clonedDataTable3;
//显示表格
_dataTable.Locale = new CultureInfo("zh-CN");
//关闭自动计算列宽度,改为手动计算,当列数自动计算就报错了,默认列宽100,最大值65535,当超过600列就报错了。所以手动计算
dataGridView1.AutoGenerateColumns = false;
//清除上次显示结构
dataGridView1.Columns.Clear();
// 手动为DataGridView添加列并设置FillWeight
int totalFillWeight = 65535;
int reservedWidth = 100; // 预留宽度,用于标题和边框
int columnCount = value.Columns.Count;
if (columnCount > 0)
{
// 计算每列的平均填充宽度
int averageFillWeight = (totalFillWeight - reservedWidth) / columnCount;
if (averageFillWeight > 200)//防止列少时 ,超过200
{
averageFillWeight = 200;
}
foreach (DataColumn column in value.Columns)
{
DataGridViewTextBoxColumn gridColumn = new DataGridViewTextBoxColumn();
gridColumn.DataPropertyName = column.ColumnName;
gridColumn.HeaderText = column.ColumnName;
gridColumn.Name = column.ColumnName;
gridColumn.FillWeight = averageFillWeight; // 使用计算出的平均宽度
dataGridView1.Columns.Add(gridColumn);
}
}
dataGridView1.DataSource = _dataTable;
// 设置所有列的单元格内容居中显示
foreach (DataGridViewColumn column in dataGridView1.Columns)
{
column.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
}
// 设置列名居中显示
dataGridView1.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
// 刷新 DataGridView 显示
dataGridView1.Refresh();
// 更新显示
textBox1.AppendText(GetTableSchema(value) + Environment.NewLine);
this.textBox2.Text = "行row : " + _dataTable.Rows.Count + " ,列col : " + _dataTable.Columns.Count;
textBox3.Text = dataTable_history.Count + "";
textBox5.Text = curr_history_index + 1 + "";
//保存到文件
SaveDataTableToFile(_dataTable);
if (Undo_Redo_Mode)//恢复 清空表格数据 操作的数据
{
dataTable_history[curr_history_index] = clonedDataTable2;
}
}
}
public DataTable dataTable_2
{
get { return _dataTable; }
set
{
if (_dataTable == value) return;
if (value == null || value.Rows.Count == 0 || value.Columns.Count == 0)
return;
// 克隆 DataTable
DataTable clonedDataTable = value.Copy();
// 追加数据到历史记录
if (!Undo_Redo_Mode)
{
dataTable_history.Add(clonedDataTable);
curr_history_index = dataTable_history.Count - 1;
}
// 清空表格数据
_dataTable.Clear();
// 将克隆的数据表复制到实例的数据表中
foreach (DataRow row in clonedDataTable.Rows)
{
_dataTable.ImportRow(row);
}
// 设置显示语言
_dataTable.Locale = new CultureInfo("zh-CN");
// 重新绑定数据源
dataGridView1.DataSource = _dataTable;
// 设置列的样式和显示
dataGridView1.AutoGenerateColumns = false;
dataGridView1.Columns.Clear();
int totalFillWeight = 65535;
int reservedWidth = 100; // 预留宽度,用于标题和边框
int columnCount = _dataTable.Columns.Count;
if (columnCount > 0)
{
int averageFillWeight = (totalFillWeight - reservedWidth) / columnCount;
if (averageFillWeight > 200)
{
averageFillWeight = 200;
}
foreach (DataColumn column in _dataTable.Columns)
{
DataGridViewTextBoxColumn gridColumn = new DataGridViewTextBoxColumn();
gridColumn.DataPropertyName = column.ColumnName;
gridColumn.HeaderText = column.ColumnName;
gridColumn.Name = column.ColumnName;
gridColumn.FillWeight = averageFillWeight;
dataGridView1.Columns.Add(gridColumn);
}
}
foreach (DataGridViewColumn column in dataGridView1.Columns)
{
column.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
}
dataGridView1.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
// 刷新 DataGridView
dataGridView1.Refresh();
// 更新文本框显示
textBox1.AppendText(GetTableSchema(value) + Environment.NewLine);
textBox2.Text = "行row : " + value.Rows.Count + " ,列col : " + value.Columns.Count;
textBox3.Text = dataTable_history.Count.ToString();
textBox5.Text = (curr_history_index + 1).ToString();
SaveDataTableToFile(value);
if (Undo_Redo_Mode)
{
dataTable_history[curr_history_index] = value.Copy();
}
}
}
/// <summary>
/// 更新文本框显示
/// </summary>
/// <param name="value">数据表</param>
private void UpdateTextBoxes(DataTable value)
{
textBox1.AppendText(GetTableSchema(value) + Environment.NewLine);
textBox2.Text = "行row : " + value.Rows.Count + " ,列col : " + value.Columns.Count;
textBox3.Text = dataTable_history.Count.ToString();
textBox5.Text = (curr_history_index + 1).ToString();
SaveDataTableToFile(value);
if (Undo_Redo_Mode)
{
dataTable_history[curr_history_index] = value.Copy();
}
}
public DataTable CountStrings(DataTable dataTable)
{
// 创建一个用于统计的DataTable
DataTable stringCountTable = new DataTable();
stringCountTable.Columns.Add("String", typeof(string));
stringCountTable.Columns.Add("Count", typeof(int));
// 使用Dictionary来存储字符串及其出现次数
Dictionary<string, int> stringCounts = new Dictionary<string, int>();
// 遍历dataTable中的每一行和每一列
foreach (DataRow row in dataTable.Rows)
{
foreach (DataColumn col in dataTable.Columns)
{
// 获取单元格的字符串值
string cellValue = row[col].ToString();
// 如果字符串已经在字典中,增加计数
if (stringCounts.ContainsKey(cellValue))
{
stringCounts[cellValue]++;
}
else
{
// 如果字符串不在字典中,添加到字典
stringCounts[cellValue] = 1;
}
}
}
// 将字典中的数据添加到DataTable中
foreach (var kvp in stringCounts)
{
DataRow newRow = stringCountTable.NewRow();
newRow["String"] = kvp.Key;
newRow["Count"] = kvp.Value;
stringCountTable.Rows.Add(newRow);
}
// 对结果进行排序
DataView dv = stringCountTable.DefaultView;
dv.Sort = "Count DESC";
DataTable sortedTable = dv.ToTable();
return sortedTable;
}
public Form1()
{
InitializeComponent();
}
/// <summary>
/// 从剪贴板读取数据并转换成DataTable
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
// 检查剪贴板是否包含文本数据
if (Clipboard.ContainsText())
{
// 获取剪贴板文本数据,并移除末尾的换行符
string clipboardData = Clipboard.GetText().TrimEnd('\r', '\n');
// 获取换行符,用于可视化显示
string lineSeparator = GetLineSeparator(clipboardData);
// 可视化显示换行符
textBox1.AppendText("换行符为:" + lineSeparator.Replace("\r", "\\r").Replace("\n", "\\n") + Environment.NewLine);
// 将剪贴板数据按换行符分割成行数组
string[] lines = clipboardData.Split(new[] { lineSeparator }, StringSplitOptions.None);
string executionTime = stopwatch.Elapsed.ToString();
textBox1.AppendText("将剪贴板数据按换行符分割成行数组,函数执行时间: " + executionTime + Environment.NewLine);
// 计算最大制表符数量,确定列数
int maxTabCount = lines.Select(line => line.Count(c => c == '\t')).Max();
// 确保列数至少有1列
int colCount = maxTabCount + 1;
// 创建一个 DataTable 对象用于存储数据
DataTable new_dt = new DataTable();
// 获取第一行的列名,用于判断是否存在空值或重复值
string[] columnNames = lines[0].Split('\t');
bool firstLineHasEmpty = columnNames.Any(string.IsNullOrEmpty);
bool firstLineHasDuplicates = columnNames.Length != columnNames.Distinct().Count();
// 根据第一行的情况,确定是否添加默认列名
if (firstLineHasEmpty || firstLineHasDuplicates)
{
for (int i = 0; i < colCount; i++)
{
new_dt.Columns.Add($"列{i + 1}", typeof(string));
}
//在加载数据之前调用 BeginLoadData() 方法,在加载完成后调用 EndLoadData() 方法。这会暂时禁用表的约束和索引,从而提高性能。
new_dt.BeginLoadData();
textBox1.AppendText("开始添加行数据: " + lines + Environment.NewLine);
// 遍历剪贴板数据的每一行,并添加到 DataTable 中
foreach (var line in lines)
{
string[] cells = line.Split('\t');
//if (cells.Length < colCount)
//{
// // 如果单元格数量小于列数,使用 Array.Resize 调整大小
// Array.Resize(ref cells, colCount);
//}
textBox1.AppendText("添加行数据: " + lines + Environment.NewLine);
new_dt.Rows.Add(cells);
}
new_dt.EndLoadData();
}
else
{
// 如果第一行没有空值或重复值,则使用第一行作为列名
foreach (var columnName in columnNames)
{
new_dt.Columns.Add(columnName, typeof(string));
}
//在加载数据之前调用 BeginLoadData() 方法,在加载完成后调用 EndLoadData() 方法。这会暂时禁用表的约束和索引,从而提高性能。
new_dt.BeginLoadData();
// 遍历剩余行的数据,并添加到 DataTable 中
for (int i = 1; i < lines.Length; i++)
{
string[] cells = lines[i].Split('\t');
//if (cells.Length < colCount)
//{
// // 如果单元格数量小于列数,使用 Array.Resize 调整大小
// Array.Resize(ref cells, colCount);
//}
textBox1.AppendText("添加行数据: " + lines + Environment.NewLine);
new_dt.Rows.Add(cells);
}
new_dt.EndLoadData();
}
textBox1.AppendText("结束添加行数据: " + lines + Environment.NewLine);
executionTime = stopwatch.Elapsed.ToString();
textBox1.AppendText("从剪贴板读取数据并转换成DataTable,函数执行时间: " + executionTime + Environment.NewLine);
// 处理或显示dataTable
// 例如:dataGridView.DataSource = dataTable;
this.dataTable = new_dt;
}
else
{
MessageBox.Show("剪贴板中没有文本数据。");
}
}
private void button1_Click_0(object sender, EventArgs e)
{
// 检查剪贴板是否含有文本数据
if (Clipboard.ContainsText())
{
string clipboardData = Clipboard.GetText();
// 判断并删除字符串末尾的换行符,最后一个字符是换行符,要删除,不然多了一个空行
if (clipboardData.EndsWith("\r\n"))
{
clipboardData = clipboardData.Remove(clipboardData.Length - 2); // 删除末尾的 "\r\n"
}
else if (clipboardData.EndsWith("\n"))
{
clipboardData = clipboardData.Remove(clipboardData.Length - 1); // 删除末尾的 "\n"
}
var line_split = GetLineSeparator(clipboardData);
//可视化的字符串
string visibleNewLine = line_split
.Replace("\r", "\\r")
.Replace("\n", "\\n");
textBox1.AppendText("换行符为:"+ visibleNewLine + Environment.NewLine);
string[] lines = clipboardData.Split(new[] { line_split }, StringSplitOptions.None);
// 计算制表符数量,找出最多的制表符数量
int maxTabCount = lines.Select(line => line.Count(c => c == '\t')).Max();
// 确定列数,至少有1列
int colCount = maxTabCount + 1;
// 创建DataTable
DataTable dataTable = new DataTable();
var firstLineCells = lines[0].Split('\t');
bool firstLineHasEmpty = firstLineCells.Any(cell => string.IsNullOrEmpty(cell));
bool firstLineHasDuplicates = firstLineCells.Length != firstLineCells.Distinct().Count();
// 检查第一行是否存在空值或重复的值,如果存在,则添加默认列名
if (firstLineHasEmpty || firstLineHasDuplicates)
{
for (int i = 0; i < colCount; i++)
{
dataTable.Columns.Add($"列{i + 1}", typeof(string));
}
// 添加所有数据行到DataTable,包括第一行
foreach (var line in lines)
{
var cells = line.Split('\t');
if (cells.Length < colCount)
{
cells = cells.Concat(new string[colCount - cells.Length]).ToArray();
}
dataTable.Rows.Add(cells);
}
}
else
{
// 使用第一行作为列名
foreach (var columnName in firstLineCells)
{
dataTable.Columns.Add(columnName, typeof(string));
}
// 添加剩余的数据行到DataTable
for (int i = 1; i < lines.Length; i++)
{
var cells = lines[i].Split('\t');
if (cells.Length < colCount)
{
cells = cells.Concat(new string[colCount - cells.Length]).ToArray();
}
dataTable.Rows.Add(cells);
}
}
// 此处应有代码来处理或显示dataTable
// 例如:dataGridView.DataSource = dataTable;
// // 显示数据
this.dataTable = dataTable;
}
else
{
MessageBox.Show("剪贴板中没有文本数据。");
}
}
/// <summary>
/// 数组中是否有重复值
/// </summary>
/// <param name="columnNames"></param>
/// <returns></returns>
bool HasDuplicate(string[] columnNames)
{
bool hasDuplicate = false;
for (int i = 0; i < columnNames.Length; i++)
{
for (int j = i + 1; j < columnNames.Length; j++)
{
if (columnNames[i] == columnNames[j])
{
hasDuplicate = true;
break;
}
}
}
return hasDuplicate;
}
/// <summary>
/// 删除该列中值为 null 的行
/// </summary>
/// <param name="table">待处理的源DataTable</param>
/// <param name="colName">要检查的列名</param>
/// <returns>处理后的DataTable</returns>
public DataTable RemoveRowsWithNull(DataTable table, string colName)
{
// 使用DataTable.Select方法筛选符合条件的行
DataRow[] rowsToDelete = table.Select($"{colName} IS NULL");
// 删除符合条件的行
foreach (DataRow row in rowsToDelete)
{
table.Rows.Remove(row);
}
// 返回处理后的DataTable
return table;
}
//删除该列中不是对子的行
public DataTable RemoveNonTripletPairRows(DataTable dataTable, string columnName)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
if (dataTable == null || dataTable.Rows.Count == 0)
{
throw new ArgumentException("输入的DataTable不能为空或无数据行");
}
if (!dataTable.Columns.Contains(columnName))
{
throw new ArgumentException($"DataTable中不存在名为'{columnName}'的列");
}
// 获取列数据
List<string> columnData = dataTable.AsEnumerable()
.Select(row => row.Field<string>(columnName))
.ToList();
// 并行处理列数据
Parallel.For(0, columnData.Count, i =>
{
string value = columnData[i];
if (!string.IsNullOrEmpty(value) && value.Length == 3 && value.Distinct().Count() != 2)
{
columnData[i] = null; // 标记要删除的数据
}
});
// 重新构建DataTable
DataTable newDataTable = new DataTable();
newDataTable.Columns.Add(columnName);
foreach (string value in columnData)
{
if (value != null)
{
newDataTable.Rows.Add(value);
}
}
stopwatch.Stop();
string executionTime = stopwatch.Elapsed.ToString();
textBox1.AppendText("函数执行时间: " + executionTime + Environment.NewLine);
return newDataTable;
}
/// <summary>
/// 从剪贴板 数据 分别统计 \r\n、\r、\n 这个三个换行符的数量,哪个高用哪个
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
private string GetLineSeparator(string text)
{
int crlfCount = 0;
int crCount = 0;
int lfCount = 0;
for (int i = 0; i < text.Length; i++)
{
if (text[i] == '\r' && i < text.Length - 1 && text[i + 1] == '\n')
{
crlfCount++;
i++;
}
else if (text[i] == '\r')
{
crCount++;
}
else if (text[i] == '\n')
{
lfCount++;
}
// 如果某种换行符的数量已经大于其它两种的总和,就可以立即返回结果
if (crlfCount > crCount + lfCount)
{
return "\r\n";
}
else if (crCount > lfCount + crlfCount)
{
return "\r";
}
else if (lfCount > crCount + crlfCount)
{
return "\n";
}
}
// 如果没有找到换行符,则默认使用 \r\n
return "\r\n";
}
/// <summary>
/// 把连续的一个空格 或者连续的空格替换为制表符
/// </summary>
/// <param name="lines"></param>
/// <returns></returns>
private string[] ReplaceSpacesWithTabs(string[] lines)
{
//每一行中的连续空白字符(两个或以上)替换为制表符,
for (int i = 0; i < lines.Length; i++)
{
lines[i] = Regex.Replace(lines[i], @" {2,}", "\t");
}
//每个单独的空格也替换为制表符
for (int i = 0; i < lines.Length; i++)
{
lines[i] = lines[i].Replace(" ", "\t");
}
return lines;
}
/// <summary>
/// 返回两个结果 一个是所有行中制表符是否一致,第二个返回数组每行的数组制表符数量
/// </summary>
/// <param name="lines"></param>
/// <returns></returns>
public static (bool, int[]) CheckTabCounts(string[] lines)
{
int[] tabCounts = new int[lines.Length];
bool consistent = true;
int prevTabCount = -1;
for (int i = 0; i < lines.Length; i++)
{
// 统计每行中制表符的数量
tabCounts[i] = Regex.Matches(lines[i], "\t").Count;
// 判断每行中制表符的数量是否一致
if (prevTabCount != -1 && prevTabCount != tabCounts[i])
{
consistent = false;
}
prevTabCount = tabCounts[i];
}
return (consistent, tabCounts);
}
/// <summary>
/// 去除 纯空行 和 只包含空格的空行
/// </summary>
/// <param name="lines"></param>
/// <returns></returns>
public string[] TrimLines(string[] lines)
{
List<string> newLine = new List<string>();
// 循环遍历每行数据,去除首尾空白字符,并将结果存储到新的字符串数组中
for (int i = 0; i < lines.Length; i++)
{
var line = lines[i];
if(IsBlankLine(line))
{//空行
}
else
{ //非空行
newLine.Add(line);
}
}
return newLine.ToArray();
}
/// <summary>
///检测 纯空行 和 只包含空格的空行
/// </summary>
/// <param name="line"></param>
/// <returns></returns>
bool IsBlankLine(string line)
{
for (int i = 0; i < line.Length; i++)
{
if (line[i] != ' ' || line != "\r" || line != "\n")
return false;
}
return true;
}
/// <summary>
/// 删除最后面连续空行
/// </summary>
/// <param name="lines"></param>
/// <returns></returns>
public string[] RemoveTrailingEmptyLines(string[] lines)
{
int lastNonEmptyLineIndex = -1;
for (int i = lines.Length - 1; i >= 0; i--)
{
if (!string.IsNullOrWhiteSpace(lines[i]))
{
lastNonEmptyLineIndex = i;
break;
}
}
if (lastNonEmptyLineIndex == -1)
{
return new string[0];
}
string[] result = new string[lastNonEmptyLineIndex + 1];
Array.Copy(lines, result, lastNonEmptyLineIndex + 1);
return result;
}
/// <summary>
/// 右键单击表 列名行 事件 弹出菜单
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == MouseButtons.Right) // 只处理右键单击事件
{
// 获取点击的列的信息
DataGridViewColumn clickedColumn = dataGridView1.Columns[e.ColumnIndex];
string columnName = clickedColumn.Name;
int columnIndex = clickedColumn.Index;
textBox1.AppendText("右键单击 列名标题栏 事件, 列名称: " + columnName + Environment.NewLine);
// 弹出菜单
ContextMenuStrip menu = new ContextMenuStrip();
menu.Items.Add("删除重复行").Click += (s, args) =>
{
// 删除重复行的逻辑
textBox1.AppendText("执行 删除重复行 列名称:" + columnName + Environment.NewLine);
var newDataTable = RemoveDuplicateRows(columnName);
dataTable = newDataTable;
};
menu.Items.Add("统计次数").Click += (s, args) =>
{
// 统计次数的逻辑
// ...
textBox1.AppendText("统计次数:" + columnName + Environment.NewLine);
var newDataTable = CountColumnValues(columnName);
dataTable = newDataTable;
};
menu.Items.Add("修改该列数据类型").Click += (s, args) =>
{
// 统计次数的逻辑
// ...
// 创建一个新的SelectColumnTypeForm实例,并将其显示为模式对话框
SelectColumnTypeForm form = new SelectColumnTypeForm();
form.ShowDialog();
Type type=null;
// 检查用户是否选择了数据类型
if (!string.IsNullOrEmpty(form.SelectedColumnType))
{
// 用户选择了数据类型,将其显示在Label控件中
type = form.type;
var newDataTable = ChangeColumnType(dataTable, columnName, type);
dataTable = newDataTable;
textBox1.AppendText("修改该列数据类型:" + columnName + ":"+ type.ToString() + Environment.NewLine);
}
else
{
}
};
menu.Items.Add("删除该列").Click += (s, args) =>
{
textBox1.AppendText("删除该列:"+ columnName + Environment.NewLine);
var newDataTable = RemoveColumn(dataTable, columnName);
dataTable = newDataTable;
};
menu.Items.Add("只保留该列").Click += (s, args) =>
{
var newDataTable = KeepColumn(dataTable, columnName);
dataTable = newDataTable;
textBox1.AppendText("只保留该列:" + columnName + Environment.NewLine);
};
menu.Items.Add("排序从大到小").Click += (s, args) =>
{
var newDataTable = SortDataTable(dataTable, columnName);
dataTable = newDataTable;
textBox1.AppendText("排序从大到小:"+ columnName + Environment.NewLine);
};
menu.Items.Add("排序从小到大").Click += (s, args) =>
{
var newDataTable = SortColumnAscending(dataTable, columnName);
dataTable = newDataTable;
textBox1.AppendText("排序从小到大:" + columnName + Environment.NewLine);
};
menu.Items.Add("删除该列中不等于字符串的行").Click += (s, args) =>
{
// 弹出输入框,让用户输入要删除的字符串
// 弹出一个对话框,让用户输入
string userInput = "";
using (var form = new Form())
{
form.Text = "请输入字符串";
var textBox = new TextBox { Left = 50, Top = 50, Width = 200 };
var buttonOk = new Button { Text = "确定", Left = 100, Top = 100, Width = 75, DialogResult = DialogResult.OK };
var buttonCancel = new Button { Text = "取消", Left = 200, Top = 100, Width = 75, DialogResult = DialogResult.Cancel };
form.AcceptButton = buttonOk;
form.CancelButton = buttonCancel;
form.ClientSize = new System.Drawing.Size(300, 150);
form.Controls.Add(textBox);
form.Controls.Add(buttonOk);
form.Controls.Add(buttonCancel);
if (form.ShowDialog() == DialogResult.OK)
{
userInput = textBox.Text;
textBox1.AppendText("删除该列中不等于字符串的行:" + columnName + ",字符:" + userInput + Environment.NewLine);
}
else
{
// 用户取消输入,做一些处理
textBox1.AppendText("取消输入:" + columnName + Environment.NewLine);
}
}
var newDataTable = RemoveRowsNotEqual(dataTable, columnName, userInput);
dataTable = newDataTable;
};
menu.Items.Add("删除该列中等于字符串的行").Click += (s, args) =>
{
// 弹出输入框,让用户输入要删除的字符串
// 弹出一个对话框,让用户输入
string userInput = "";
using (var form = new Form())
{
form.Text = "请输入字符串";
var textBox = new TextBox { Left = 50, Top = 50, Width = 200 };
var buttonOk = new Button { Text = "确定", Left = 100, Top = 100, Width = 75, DialogResult = DialogResult.OK };
var buttonCancel = new Button { Text = "取消", Left = 200, Top = 100, Width = 75, DialogResult = DialogResult.Cancel };
form.AcceptButton = buttonOk;
form.CancelButton = buttonCancel;
form.ClientSize = new System.Drawing.Size(300, 150);
form.Controls.Add(textBox);
form.Controls.Add(buttonOk);
form.Controls.Add(buttonCancel);
// 设置窗口启动位置为手动
form.StartPosition = FormStartPosition.Manual;
// 设置form的位置为父窗口的左中上位置
form.Location = new Point(this.Left, this.Top + (this.Height - form.Height) / 2);
if (form.ShowDialog() == DialogResult.OK)
{
userInput = textBox.Text;
textBox1.AppendText("删除该列中等于字符串的行:" + columnName + ",字符:" + userInput + Environment.NewLine);
var newDataTable = RemoveRowsEqual(dataTable, columnName, userInput);
dataTable = newDataTable;
}
else
{
// 用户取消输入,做一些处理
textBox1.AppendText("取消输入:" + columnName + Environment.NewLine);
}
}
};
menu.Items.Add("删除该列中不包含该字符串中任意字符的行").Click += (s, args) =>
{
// 弹出输入框,让用户输入要删除的字符串
// 弹出一个对话框,让用户输入
string userInput = "";
using (var form = new Form())
{
form.Text = "请输入字符串";
var textBox = new TextBox { Left = 50, Top = 50, Width = 200 };
var buttonOk = new Button { Text = "确定", Left = 100, Top = 100, Width = 75, DialogResult = DialogResult.OK };
var buttonCancel = new Button { Text = "取消", Left = 200, Top = 100, Width = 75, DialogResult = DialogResult.Cancel };
form.AcceptButton = buttonOk;
form.CancelButton = buttonCancel;
form.ClientSize = new System.Drawing.Size(300, 150);
form.Controls.Add(textBox);
form.Controls.Add(buttonOk);
form.Controls.Add(buttonCancel);
// 设置窗口启动位置为手动
form.StartPosition = FormStartPosition.Manual;
// 设置form的位置为父窗口的左中上位置
form.Location = new Point(this.Left, this.Top + (this.Height - form.Height) / 2);
if (form.ShowDialog() == DialogResult.OK)
{
userInput = textBox.Text;
textBox1.AppendText("删除该列中不包含该字符串中任意字符的行:" + columnName + ",字符:" + userInput + Environment.NewLine);
var newDataTable = RemoveRowsNotContain(dataTable, columnName, userInput);
dataTable = newDataTable;
}
else
{
// 用户取消输入,做一些处理
textBox1.AppendText("取消输入:" + columnName + Environment.NewLine);
}
}
};
menu.Items.Add("删除该列中包含该字符串中任意字符的行").Click += (s, args) =>
{
// 弹出输入框,让用户输入要删除的字符串
// 弹出一个对话框,让用户输入
string userInput = "";
using (var form = new Form())
{
form.Text = "请输入字符串";
var textBox = new TextBox { Left = 50, Top = 50, Width = 200 };
var buttonOk = new Button { Text = "确定", Left = 100, Top = 100, Width = 75, DialogResult = DialogResult.OK };
var buttonCancel = new Button { Text = "取消", Left = 200, Top = 100, Width = 75, DialogResult = DialogResult.Cancel };
form.AcceptButton = buttonOk;
form.CancelButton = buttonCancel;
form.ClientSize = new System.Drawing.Size(300, 150);
form.Controls.Add(textBox);
form.Controls.Add(buttonOk);
form.Controls.Add(buttonCancel);
// 设置窗口启动位置为手动
form.StartPosition = FormStartPosition.Manual;
// 设置form的位置为父窗口的左中上位置
form.Location = new Point(this.Left, this.Top + (this.Height - form.Height) / 2);
if (form.ShowDialog() == DialogResult.OK)
{
userInput = textBox.Text;
textBox1.AppendText("删除该列中包含该字符串中任意字符的行:" + columnName + ",字符:" + userInput + Environment.NewLine);
var newDataTable = RemoveRowsContainAnyCharacter(dataTable, columnName, userInput);
dataTable = newDataTable;
}
else
{
// 用户取消输入,做一些处理
textBox1.AppendText("取消输入:" + columnName + Environment.NewLine);
}
}
};
menu.Items.Add("删除该列中等于空字符串的行").Click += (s, args) =>
{
// 列名行变成第一行数据,并增加默认的列名行
dataTable = RemoveRowsWithEmptyString(dataTable,columnName);
textBox1.AppendText("删除该列中等于空字符串的行:" + columnName + Environment.NewLine);
};
menu.Items.Add("删除该列中等于NULL的行").Click += (s, args) =>
{
// 列名行变成第一行数据,并增加默认的列名行
dataTable = RemoveRowsWithNull(dataTable, columnName);
textBox1.AppendText("删除该列中等于NULL的行:" + columnName + Environment.NewLine);
};
menu.Items.Add("只保留整型数字的行").Click += (s, args) =>
{
// 列名行变成第一行数据,并增加默认的列名行
dataTable = FilterNumericColumn(e.ColumnIndex,dataTable);
textBox1.AppendText("列名称:" + columnName + ",执行操作\"只保留整型数字的行\""+ Environment.NewLine);
};
menu.Items.Add("只保留包含浮点数的行").Click += (s, args) =>
{
// 列名行变成第一行数据,并增加默认的列名行
dataTable = FilterDecimalColumnRegex(e.ColumnIndex, dataTable);
textBox1.AppendText("只保留包含浮点数的行:" + columnName + Environment.NewLine);
};
menu.Items.Add("计算综合得分").Click += (s, args) =>
{
// 列名行变成第一行数据,并增加默认的列名行
dataTable = GetScores(dataTable);
textBox1.AppendText("计算综合得分:" + columnName + Environment.NewLine);
};
menu.Items.Add("保留该列中 两相同的行").Click += (s, args) =>
{
dataTable = RemoveNonTripletPairRows(dataTable, columnName);
textBox1.AppendText("保留该列中 两相同的行:" + columnName + Environment.NewLine);
};
menu.Items.Add("保留该列中 三不同的行").Click += (s, args) =>
{
dataTable = RemoveStringPairRows(dataTable, columnName);
textBox1.AppendText("保留该列中 三不同的行:" + columnName + Environment.NewLine);
};
menu.Items.Add("输出该列中 该列每5个为一行的字符串").Click += (s, args) =>
{
var restr = CombineEveryFiveCells(dataTable, columnName);
textBox1.AppendText("输出该列中 该列每5个为一行的字符串" + columnName + Environment.NewLine);
textBox1.AppendText(restr + Environment.NewLine);
};
menu.Items.Add("删除该列中长度小于3的所有行").Click += (s, args) =>
{
dataTable = RemoveLengthThreeRows(dataTable, columnName);
textBox1.AppendText("删除该列中长度小于3的所有行" + columnName + Environment.NewLine);
};
menu.Items.Add("删除该列中含非数字字符的行").Click += (s, args) =>
{
RemoveRowsWithNonNumericContent(dataTable, columnName);
textBox1.AppendText("删除该列中含非数字字符的行" + columnName + Environment.NewLine);
};
menu.Items.Add("单元格-去除空白字符").Click += (s, args) =>
{
RemoveAllWhitespaceFromColumnContents(dataTable, columnName);
textBox1.AppendText("单元格-去除空白字符" + columnName + Environment.NewLine);
};
menu.Items.Add("单元格-排序").Click += (s, args) =>
{
AllCellContents(dataTable, columnName);
textBox1.AppendText("单元格-排序" + columnName + Environment.NewLine);
};
menu.Items.Add("单元格-去重复").Click += (s, args) =>
{
DeduplicateEachCellContentInColumn(dataTable, columnName);
textBox1.AppendText("单元格-去重复" + columnName + Environment.NewLine);
};
menu.Show(dataGridView1, dataGridView1.PointToClient(Cursor.Position));
}
}
/// <summary>
/// 对指定列的每个单元格内容进行内部去重,而不是比较不同单元格之间的内容,
/// </summary>
/// <param name="table"></param>
/// <param name="columnName"></param>
public static void DeduplicateEachCellContentInColumn(DataTable table, string columnName)
{
// 检查是否存在该列
if (!table.Columns.Contains(columnName))
{
throw new ArgumentException($"Column '{columnName}' does not exist in the DataTable.");
}
// 遍历 DataTable 的每一行
foreach (DataRow row in table.Rows)
{
string originalContent = row[columnName].ToString();
StringBuilder deduplicatedContent = new StringBuilder();
HashSet<char> seenChars = new HashSet<char>();
// 遍历单元格内容的每个字符
foreach (char ch in originalContent)
{
// 如果字符尚未出现过,添加到结果字符串中
if (seenChars.Add(ch))
{
deduplicatedContent.Append(ch);
}
}
// 更新单元格内容为去重后的字符串
row[columnName] = deduplicatedContent.ToString();
}
}
/// <summary>
/// 删除该列中含非数字字符的行。
/// </summary>
/// <param name="table"></param>
/// <param name="columnName"></param>
public static void RemoveRowsWithNonNumericContent(DataTable table, string columnName)
{
// 检查是否存在该列
if (!table.Columns.Contains(columnName))
{
throw new ArgumentException($"Column '{columnName}' does not exist in the DataTable.");
}
// 从最后一行向前遍历,避免因删除行而改变索引
for (int i = table.Rows.Count - 1; i >= 0; i--)
{
var row = table.Rows[i];
var cellValue = row[columnName].ToString();
// 检查字符串是否包含任何非数字字符
if (cellValue.Any(ch => !char.IsDigit(ch)))
{
// 如果包含非数字字符,则删除该行
table.Rows.Remove(row);
}
}
}
/// <summary>
/// 去除该列单元格内容空白字符
/// </summary>
/// <param name="table"></param>
/// <param name="columnName"></param>
public static void RemoveAllWhitespaceFromColumnContents(DataTable table, string columnName)
{
// 检查是否存在该列
if (!table.Columns.Contains(columnName))
{
throw new ArgumentException($"Column '{columnName}' does not exist in the DataTable.");
}
foreach (DataRow row in table.Rows)
{
var cellValue = row[columnName].ToString();
// 使用正则表达式移除所有类型的空白字符
var cleanedValue = Regex.Replace(cellValue, @"\s+", "");
// 更新单元格内容
row[columnName] = cleanedValue;
}
}
/// <summary>
/// 该列单元格内容排序
/// </summary>
/// <param name="dataTable"></param>
/// <param name="columnName"></param>
/// <returns></returns>
public void AllCellContents(DataTable table, string columnName)
{
// 检查是否存在该列
if (!table.Columns.Contains(columnName))
{
throw new ArgumentException($"Column '{columnName}' does not exist in the DataTable.");
}
foreach (DataRow row in table.Rows)
{
var cellValue = row[columnName].ToString();
// 将字符串转换为字符数组,并进行排序
var charArray = cellValue.ToCharArray();
Array.Sort(charArray);
// 将排序后的字符数组转换回字符串,并更新单元格内容
row[columnName] = new string(charArray);
}
}
/// <summary>
/// 删除该列中 长度为2的所有行
/// </summary>
/// <param name="dataTable"></param>
/// <param name="columnName"></param>
/// <returns></returns>
public DataTable RemoveLengthThreeRows(DataTable dataTable, string columnName)
{
if (dataTable == null || dataTable.Rows.Count == 0)
{
throw new ArgumentException("输入的DataTable不能为空或无数据行");
}
if (!dataTable.Columns.Contains(columnName))
{
throw new ArgumentException($"DataTable中不存在名为'{columnName}'的列");
}
// 获取列数据
List<string> columnData = dataTable.AsEnumerable()
.Select(row => row.Field<string>(columnName))
.ToList();
// 并行处理列数据
Parallel.For(0, columnData.Count, i =>
{
string value = columnData[i];
if (!string.IsNullOrEmpty(value) && value.Length == 3 && value.Distinct().Count() != 3)
{
columnData[i] = null; // 标记要删除的数据
}
});
// 重新构建DataTable
DataTable newDataTable = new DataTable();
newDataTable.Columns.Add(columnName);
foreach (string value in columnData)
{
if (value != null)
{
newDataTable.Rows.Add(value);
}
}
return newDataTable;
}
/// <summary>
/// 该列每5个为一行的字符串
/// </summary>
/// <param name="dataTable"></param>
/// <param name="columnName"></param>
/// <returns></returns>
public string CombineEveryFiveCells(DataTable dataTable, string columnName)
{
// 检查DataTable是否为空或无数据行
if (dataTable == null || dataTable.Rows.Count == 0)
{
throw new ArgumentException("输入的DataTable不能为空或无数据行");
}
// 检查指定列是否存在
if (!dataTable.Columns.Contains(columnName))
{
throw new ArgumentException($"DataTable中不存在名为'{columnName}'的列");
}
StringBuilder combinedString = new StringBuilder();
combinedString.Append("共有" + dataTable.Rows.Count + "注," + dataTable.Rows.Count * 2 + "元");
combinedString.AppendLine(); // 每5个单元格内容合并完成后换行
int rowIndex = 0;
while (rowIndex < dataTable.Rows.Count)
{
for (int i = 0; i < 5 && rowIndex < dataTable.Rows.Count; i++, rowIndex++)
{
string cellValue = dataTable.Rows[rowIndex][columnName] as string;
if (i > 0)
{
combinedString.Append("\t"); // 添加制表符间隔
}
combinedString.Append(cellValue);
}
combinedString.AppendLine(); // 每5个单元格内容合并完成后换行
}
return combinedString.ToString();
}
/// <summary>
/// 保留三不同的行
/// </summary>
/// <param name="dataTable"></param>
/// <param name="columnName"></param>
/// <returns></returns>
public DataTable RemoveStringPairRows(DataTable dataTable, string columnName)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
if (dataTable == null || dataTable.Rows.Count == 0)
{
throw new ArgumentException("输入的DataTable不能为空或无数据行");
}
if (!dataTable.Columns.Contains(columnName))
{
throw new ArgumentException($"DataTable中不存在名为'{columnName}'的列");
}
// 获取列数据
List<string> columnData = dataTable.AsEnumerable()
.Select(row => row.Field<string>(columnName))
.ToList();
// 并行处理列数据
Parallel.For(0, columnData.Count, i =>
{
string value = columnData[i];
if (!string.IsNullOrEmpty(value) && value.Length == 3 && value.Distinct().Count() != 3)
{
columnData[i] = null; // 标记要删除的数据
}
});
// 重新构建DataTable
DataTable newDataTable = new DataTable();
newDataTable.Columns.Add(columnName);
foreach (string value in columnData)
{
if (value != null)
{
newDataTable.Rows.Add(value);
}
}
stopwatch.Stop();
string executionTime = stopwatch.Elapsed.ToString();
textBox1.AppendText("函数执行时间: " + executionTime + Environment.NewLine);
return newDataTable;
}
public DataTable GetScores(DataTable inputData)
{
DataTable scores = new DataTable();
scores.Columns.Add("Rank");
scores.Columns.Add("Number");
scores.Columns.Add("PositionScore");
scores.Columns.Add("TimesScore");
scores.Columns.Add("TotalScore");
Dictionary<int, Score> dict = new Dictionary<int, Score>();
foreach (DataRow row in inputData.Rows)
{
int number = int.Parse(row[1].ToString());
int times = int.Parse(row[2].ToString());
if (!dict.ContainsKey(number))
{
dict.Add(number, new Score() { Number = number });
}
dict[number].PositionScore += GetPositionScore(row.ItemArray.Length);
dict[number].TimesScore += GetTimesScore(times);
}
int rank = 1;
foreach (Score score in dict.Values)
{
score.Rank = rank++;
score.TotalScore = score.PositionScore + score.TimesScore;
scores.Rows.Add(score.Rank, score.Number, score.PositionScore, score.TimesScore, score.TotalScore);
}
return scores;
}
/// <summary>
/// 过滤DataTable指定列,只保留包含浮点数的行
/// </summary>
/// <param name="columnIndex">需要过滤的列索引</param>
/// <param name="table">原始DataTable</param>
/// <returns>过滤后的DataTable</returns>
public DataTable FilterDecimalColumnRegex(int columnIndex, DataTable table)
{
DataTable result = table.Clone();
for (int rowIndex = 0; rowIndex < table.Rows.Count; rowIndex++)
{
DataRow row = table.Rows[rowIndex];
string cellValue = row[columnIndex].ToString();
// 使用正则判断是否包含小数
Regex regex = new Regex(@"^[-+]?[0-9]*\.?[0-9]+$");
if (regex.IsMatch(cellValue))
{
result.ImportRow(row);
}
}
return result;
}
/// <summary>
/// 过滤DataTable指定列,只保留整型数字的行
/// </summary>
/// <param name="columnIndex">需要过滤的列索引</param>
/// <param name="table">原始DataTable</param>
/// <returns>过滤后的DataTable</returns>
public DataTable FilterNumericColumn(int columnIndex, DataTable table)
{
/// 克隆一个空的DataTable作为结果
DataTable result = table.Clone();
// 遍历原始table的所有行
for (int rowIndex = 0; rowIndex < table.Rows.Count; rowIndex++)
{
// 获取当前行
DataRow row = table.Rows[rowIndex];
/// 直接将指定列的值转换为字符串
string cellValue = row[columnIndex].ToString();
/// 使用正则判断字符串是否全部由数字组成
Regex regex = new Regex(@"^[0-9]+$");
//如果字符串与正则匹配,说明是数字
if (regex.IsMatch(cellValue))
{
//将当前行加入结果DataTable
result.ImportRow(row);
}
}
// 返回结果DataTable
return result;
}
/// <summary>
/// 将当前 DataTable 的列名行变成第一行数据,并增加默认的列名行,,列1 列2 ...
/// </summary>
/// <param name="inputTable"></param>
/// <returns></returns>
public DataTable TransformDataTable(DataTable inputTable)
{
DataTable outputTable = new DataTable();
// 添加默认的列名行
for (int i = 0; i < inputTable.Columns.Count; i++)
{
outputTable.Columns.Add("列" + (i + 1));
}
// 将当前 DataTable 的列名行转换为数据行
DataRow columnNameRow = outputTable.NewRow();
foreach (DataColumn column in inputTable.Columns)
{
columnNameRow[column.Ordinal] = column.ColumnName;
}
outputTable.Rows.Add(columnNameRow);
// 将当前 DataTable 的数据复制到新的 DataTable
foreach (DataRow row in inputTable.Rows)
{
DataRow newRow = outputTable.NewRow();
foreach (DataColumn column in inputTable.Columns)
{
newRow[column.Ordinal] = row[column.Ordinal];
}
outputTable.Rows.Add(newRow);
}
return outputTable;
}
/// <summary>
/// 删除该列中不等于字符串的行
/// </summary>
/// <param name="colName"></param>
/// <param name="value"></param>
/// <returns></returns>
public DataTable RemoveRowsNotEqual(DataTable table, string colName, string value)
{
// 使用DataTable.Select方法筛选符合条件的行
DataRow[] rowsToDelete = table.Select($"{colName} <> '{value}'");
// 删除符合条件的行
foreach (DataRow row in rowsToDelete)
{
table.Rows.Remove(row);
}
// 返回处理后的DataTable
return dataTable;
}
/// <summary>
/// 删除该列中等于字符串的行
/// </summary>
/// <param name="table">待处理的源DataTable</param>
/// <param name="colName">要检查的列名</param>
/// <param name="value">要匹配的字符串值</param>
/// <returns>处理后的DataTable</returns>
public DataTable RemoveRowsEqual(DataTable table, string colName, string value)
{
// 使用DataTable.Select方法筛选符合条件的行
DataRow[] rowsToDelete = table.Select($"{colName} = '{value}'");
// 删除符合条件的行
foreach (DataRow row in rowsToDelete)
{
table.Rows.Remove(row);
}
// 返回处理后的DataTable
return table;
}
/// <summary>
/// 删除该列中不包含特定字符串中任意字符的行的功能
/// </summary>
/// <param name="table"></param>
/// <param name="colName"></param>
/// <param name="value"></param>
/// <returns></returns>
public DataTable RemoveRowsNotContain(DataTable table, string colName, string value)
{
// 创建一个新的DataTable以存储满足条件的行
DataTable filteredTable = table.Clone();
foreach (DataRow row in table.Rows)
{
string cellValue = row[colName].ToString();
bool containsAnyChar = value.Any(c => cellValue.Contains(c));
if (containsAnyChar)
{
// 如果行包含value中的任意字符,将其添加到新的DataTable中
filteredTable.ImportRow(row);
}
}
// 返回处理后的DataTable,只包含符合条件的行
return filteredTable;
}
/// <summary>
/// 删除该列中包含特定字符串中任意字符的行的功能
/// </summary>
/// <param name="table"></param>
/// <param name="colName"></param>
/// <param name="value"></param>
/// <returns></returns>
public DataTable RemoveRowsContainAnyCharacter(DataTable table, string colName, string value)
{
// 创建一个新的DataTable用于存储不需要删除的行
DataTable filteredTable = table.Clone();
foreach (DataRow row in table.Rows)
{
string cellValue = row[colName].ToString();
// 检查cellValue是否包含value中的任意一个字符
bool containsAnyChar = value.Any(c => cellValue.Contains(c));
if (!containsAnyChar)
{
// 如果cellValue不包含value中的任何字符,将行添加到新的DataTable
filteredTable.ImportRow(row);
}
}
// 返回处理后的DataTable,已经删除了包含指定字符的行
return filteredTable;
}
/// <summary>
/// 删除该列中值为空字符串的行
/// </summary>
/// <param name="table">待处理的源DataTable</param>
/// <param name="colName">要检查的列名</param>
/// <returns>处理后的DataTable</returns>
public DataTable RemoveRowsWithEmptyString(DataTable table, string colName)
{
// 使用DataTable.Select方法筛选符合条件的行
DataRow[] rowsToDelete = table.Select($"{colName} = ''");
// 删除符合条件的行
foreach (DataRow row in rowsToDelete)
{
table.Rows.Remove(row);
}
// 返回处理后的DataTable
return table;
}
/// <summary>
/// 删除colName列中不等于该值的行
/// </summary>
/// <param name="colName"></param>
/// <param name="value"></param>
/// <returns></returns>
public DataTable RemoveRowsNotEqual(DataTable table, string colName, object value)
{
DataColumn column = table.Columns[colName];
// 根据列的数据类型进行值的转换
value = Convert.ChangeType(value, column.DataType);
// 使用DataTable.Select方法筛选符合条件的行
DataRow[] rowsToDelete = table.Select($"{colName} <> '{value}'");
// 删除符合条件的行
foreach (DataRow row in rowsToDelete)
{
table.Rows.Remove(row);
}
// 返回处理后的DataTable
return table;
}
/// <summary>
/// 删除colName列中等于该值的行
/// </summary>
/// <param name="colName"></param>
/// <param name="value"></param>
/// <returns></returns>
public DataTable RemoveRowsEqual(DataTable table, string colName, object value)
{
DataColumn column = table.Columns[colName];
// 根据列的数据类型进行值的转换
value = Convert.ChangeType(value, column.DataType);
// 使用DataTable.Select方法筛选符合条件的行
DataRow[] rowsToDelete = table.Select($"{colName} = '{value}'");
// 删除符合条件的行
foreach (DataRow row in rowsToDelete)
{
table.Rows.Remove(row);
}
//返回处理后的DataTable
return table;
}
/// <summary>
/// 排序从大到小
/// </summary>
/// <param name="table"></param>
/// <param name="columnName"></param>
/// <returns></returns>
public DataTable SortDataTable(DataTable table, string columnName)
{
// 使用Select方法按照指定列的值从大到小排序
DataRow[] sortedRows = table.Select("", $"{columnName} DESC");
// 创建新的DataTable用于存储排序后的数据
DataTable sortedTable = table.Clone();
// 复制排序后的数据到新的DataTable中
foreach (DataRow row in sortedRows)
{
sortedTable.ImportRow(row);
}
return sortedTable;
}
/// <summary>
/// 排序从小到大
/// </summary>
/// <param name="table"></param>
/// <param name="columnName"></param>
/// <returns></returns>
public DataTable SortColumnAscending(DataTable table, string columnName)
{
if (!table.Columns.Contains(columnName))
{
throw new ArgumentException($"Column '{columnName}' does not exist in the table.");
}
table.DefaultView.Sort = $"{columnName} ASC";
return table.DefaultView.ToTable();
}
/// <summary>
/// 删除指定列
/// </summary>
/// <param name="table"></param>
/// <param name="columnName"></param>
/// <returns></returns>
public DataTable RemoveColumn(DataTable table, string columnName)
{
// 检查表格中是否存在该列
if (!table.Columns.Contains(columnName))
{
throw new ArgumentException($"Column '{columnName}' does not exist in the table.");
}
// 删除指定列
table.Columns.Remove(columnName);
return table;
}
/// <summary>
/// 只保留该列
/// </summary>
/// <param name="table"></param>
/// <param name="columnName"></param>
/// <returns></returns>
public static DataTable KeepColumn__0(DataTable table, string columnName)
{
// 获取指定列
DataColumn col = table.Columns[columnName];
// 备份主键约束
DataColumn[] keyCols = table.PrimaryKey;
// 使用for循环移除其他所有列
for (int i = table.Columns.Count - 1; i >= 0; i--)
{
DataColumn c = table.Columns[i];
if (c != col)
{
table.Columns.Remove(c);
}
}
// 重新设置主键约束
if (keyCols != null)
{
table.PrimaryKey = keyCols;
}
return table;
}
/// <summary>
/// 只保留指定列
/// </summary>
/// <param name="table">原始 DataTable</param>
/// <param name="columnName">要保留的列名</param>
/// <returns>只包含指定列的新 DataTable</returns>
public static DataTable KeepColumn(DataTable table, string columnName)
{
// 新建一个 DataTable 用于存储指定列
DataTable newTable = new DataTable();
// 获取指定列
DataColumn col = table.Columns[columnName];
// 将指定列添加到新 DataTable 中
newTable.Columns.Add(col.ColumnName, col.DataType);
// 复制原 DataTable 中的数据到新 DataTable
foreach (DataRow row in table.Rows)
{
DataRow newRow = newTable.NewRow();
newRow[col.ColumnName] = row[col.ColumnName];
newTable.Rows.Add(newRow);
}
return newTable;
}
/// <summary>
/// 统计该列的出现次数
/// </summary>
/// <param name="colName"></param>
/// <returns></returns>
public DataTable CountColumnValues( string colName)
{
// 创建一个新的DataTable来存储统计结果
DataTable resultTable = new DataTable();
resultTable.Columns.Add(colName, typeof(string));
resultTable.Columns.Add("Count", typeof(int));
// 创建一个哈希表来存储每个值出现的次数
Hashtable valueCounts = new Hashtable();
// 遍历每一行,将每个值出现的次数添加到哈希表中
foreach (DataRow row in dataTable.Rows)
{
string value = row[colName].ToString();
if (valueCounts.ContainsKey(value))
{
valueCounts[value] = (int)valueCounts[value] + 1;
}
else
{
valueCounts[value] = 1;
}
}
// 将哈希表转换为列表,并根据次数进行降序排序
var sortedValueCounts = from entry in valueCounts.Cast<DictionaryEntry>()
orderby (int)entry.Value descending
select entry;
// 将每个值和它出现的次数添加到结果表中
foreach (DictionaryEntry entry in sortedValueCounts)
{
DataRow resultRow = resultTable.NewRow();
resultRow[colName] = entry.Key;
resultRow["Count"] = entry.Value;
resultTable.Rows.Add(resultRow);
}
// 返回包含统计结果的DataTable
return resultTable;
}
/// <summary>
///
/// </summary>
/// <param name="table"></param>
/// <param name="columnName"></param>
/// <param name="newType"></param>
/// <returns></returns>
public DataTable ChangeColumnType(DataTable table, string columnName, Type newType)
{
// 检查表格中是否存在该列
if (!table.Columns.Contains(columnName))
{
throw new ArgumentException($"Column '{columnName}' does not exist in the table.");
}
// 创建新列
DataColumn newColumn = new DataColumn(columnName + "_new", newType);
// 将新列添加到旧列后面
int columnIndex = table.Columns.IndexOf(columnName);
table.Columns.Add(newColumn);
newColumn.SetOrdinal(columnIndex + 1);
// 复制数据到新列
foreach (DataRow row in table.Rows)
{
object value = row[columnName];
if (value != DBNull.Value)
{
row[newColumn] = Convert.ChangeType(value, newType);
}
}
// 删除旧列并将新列重命名为旧列名
table.Columns.Remove(columnName);
newColumn.ColumnName = columnName;
return table;
}
/// <summary>
/// 删除重复行
/// </summary>
/// <param name="colName"></param>
/// <returns></returns>
public DataTable RemoveDuplicateRows(string colName)
{
// 记录原始行数
int originalRowCount = dataTable.Rows.Count;
// 创建一个临时的DataTable来存储不重复的行
DataTable tempTable = new DataTable();
tempTable = dataTable.Clone();
// 创建一个哈希集合来存储已经出现过的值
HashSet<string> uniqueValues = new HashSet<string>();
int rowCount = 0; // 定义计数器
// 遍历每一行
foreach (DataRow row in dataTable.Rows)
{
// 获取当前行的列值
string value = row[colName].ToString();
// 如果这个值没有出现过,将它添加到哈希集合和临时表中
if (!uniqueValues.Contains(value))
{
uniqueValues.Add(value);
tempTable.ImportRow(row);
}
}
// 返回删除的行数
rowCount = originalRowCount - tempTable.Rows.Count;
textBox1.AppendText("删除重复行: "+rowCount+"行" + Environment.NewLine);
// 返回新的不含重复行的DataTable
return tempTable;
}
/// <summary>
/// 从剪贴板中获取字符串,分析每个字符出现次数 除了换行符
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public DataTable AnalyzeCharacterFrequency()
{
string input = Clipboard.GetText();
// 创建一个临时的DataTable来存储结果
DataTable resultTable = new DataTable();
resultTable.Columns.Add("Character", typeof(string));
resultTable.Columns.Add("Frequency", typeof(int));
// 创建一个哈希字典来记录每个字符串的出现次数
Dictionary<string, int> frequencyDict = new Dictionary<string, int>();
// 遍历每个字符并计数
foreach (char c in input)
{
string key = ConvertSpecialCharacters(c.ToString());
if (frequencyDict.ContainsKey(key))
{
frequencyDict[key]++;
}
else
{
frequencyDict[key] = 1;
}
}
// 将哈希字典中的结果添加到DataTable中
foreach (KeyValuePair<string, int> pair in frequencyDict)
{
if (pair.Key.Length == 1 && char.IsDigit(pair.Key[0]) && int.Parse(pair.Key) >= 0 && int.Parse(pair.Key) <= 9)
{//仅当KeyValuePair<string, int>中的键("Character")是0-9之间的数字时才将行添加到DataTable中
DataRow row = resultTable.NewRow();
row["Character"] = pair.Key;
row["Frequency"] = pair.Value;
resultTable.Rows.Add(row);
}
}
// 按照出现次数从大到小对结果进行排序
DataView view = resultTable.DefaultView;
view.Sort = "Frequency DESC";
resultTable = view.ToTable();
// 返回结果DataTable
return resultTable;
}
/// <summary>
/// 显示统计表格的窗口
/// </summary>
/// <param name="dataTable"></param>
void new_Form_Show(DataTable dataTable)
{
var form = new Form();
var dataGrid = new DataGridView { Dock = DockStyle.Fill, DataSource = dataTable };
form.Controls.Add(dataGrid);
form.Text = "row : " + dataTable.Rows.Count + " ,col : " + dataTable.Columns.Count;
form.ShowDialog();
}
/// <summary>
/// 将正确地将制表符 (\t)、空格 ( )、换行符 (\n) 和回车符 (\r) 转换为相应的可见字符。
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public string ConvertSpecialCharacters(string input)
{
StringBuilder result = new StringBuilder();
foreach (char c in input)
{
switch (c)
{
case '\t':
result.Append("\\t"); // 转换制表符为"\t"
break;
case ' ':
result.Append(" "); // 转换空格为"\s"
break;
case '\n':
result.Append("\\n"); // 转换换行符为"\n"
break;
case '\r':
result.Append("\\r"); // 转换回车符为"\r"
break;
default:
result.Append(c); // 其他字符保持不变
break;
}
}
return result.ToString();
}
public void SaveDataTableToFile(DataTable dataTable)
{
// 将 DataTable 写入到 CSV 文件中
using (StreamWriter writer = new StreamWriter(fileName))
{
// 写入列名
writer.WriteLine(string.Join(",", dataTable.Columns.Cast<DataColumn>().Select(column => column.ColumnName)));
// 写入数据行
foreach (DataRow row in dataTable.Rows)
{
writer.WriteLine(string.Join(",", row.ItemArray));
}
}
}
public string GetTableSchema(DataTable table)
{
StringBuilder sb = new StringBuilder();
sb.Append("------------------------------------------"+"\r\n");
sb.Append("当前表格列数据信息:\r\n");
sb.Append("总共有多少列:" + table.Columns.Count+ "\r\n");
foreach (DataColumn column in table.Columns)
{
sb.Append("列名称:");
sb.Append(column.ColumnName);
sb.Append("\t,数据类型:");
sb.Append(column.DataType.Name);
sb.Append("\r\n");
}
if (sb.Length > 2)
{
sb.Remove(sb.Length - 2, 2);
}
sb.Append( "\r\n"+ "------------------------------------------" + "\r\n");
return sb.ToString();
}
private void button2_Click(object sender, EventArgs e)
{
// 显示数据
dataTable = LoadDataTableFromFile();
}
public DataTable LoadDataTableFromFile()
{
DataTable dataTable = new DataTable();
// 从 CSV 文件中读取 DataTable
using (StreamReader reader = new StreamReader(fileName))
{
string line = reader.ReadLine();
if (!string.IsNullOrEmpty(line))
{
string[] headers = line.Split(',');
foreach (string header in headers)
{
dataTable.Columns.Add(header);
}
}
while ((line = reader.ReadLine()) != null)
{
string[] fields = line.Split(',');
DataRow row = dataTable.NewRow();
for (int i = 0; i < fields.Length; i++)
{
row[i] = fields[i];
}
dataTable.Rows.Add(row);
}
}
return dataTable;
}
private void button3_Click(object sender, EventArgs e)
{
Clipboard.SetText("0");
Clipboard.SetText("1");
Clipboard.SetText("2");
Clipboard.SetText("3");
StringBuilder sb = new StringBuilder();
// 添加列名称
foreach (DataColumn column in dataTable.Columns)
{
sb.Append(column.ColumnName);
sb.Append('\t');
}
sb.Length--; // 删除最后一个制表符
sb.AppendLine();
// 添加行数据
foreach (DataRow row in dataTable.Rows)
{
for (int i = 0; i < dataTable.Columns.Count; i++)
{
sb.Append(row[i]);
sb.Append('\t');
}
sb.Length--; // 删除最后一个制表符
// 如果不是最后一行,添加回车符
if (row != dataTable.Rows[dataTable.Rows.Count - 1])
{
sb.AppendLine();
}
}
Clipboard.SetText(sb.ToString());
}
private void button4_Click(object sender, EventArgs e)
{
dataTable = AnalyzeCharacterFrequency();
}
private void textBox6_TextChanged(object sender, EventArgs e)
{
}
/// <summary>
/// DataTable 中根据行索引删除行
/// </summary>
/// <param name="table"></param>
/// <param name="rowIndex"></param>
public DataTable DeleteRowByIndex(DataTable table, int rowIndex)
{
if (rowIndex >= 0 && rowIndex < table.Rows.Count)
{
table.Rows.RemoveAt(rowIndex);
}
return table;
}
/// <summary>
/// 删除DataTable中指定行索引及其以上的所有行
/// </summary>
/// <param name="table">要操作的DataTable</param>
/// <param name="rowIndex">起始行索引</param>
public DataTable DeleteRowsAboveIndex(DataTable table, int rowIndex)
{
// 确保索引在有效范围内
if (rowIndex >= 0 && rowIndex < table.Rows.Count)
{
// 从指定的行索引开始删除,直到表的第一行
for (int i = rowIndex; i >= 0; i--)
{
table.Rows.RemoveAt(i);
}
}
return table;
}
/// <summary>
/// 从DataTable中删除指定行索引及其以下的所有行
/// </summary>
/// <param name="table">要操作的DataTable</param>
/// <param name="rowIndex">起始行索引</param>
/// <returns>返回修改后的DataTable</returns>
public DataTable DeleteRowsFromIndex(DataTable table, int rowIndex)
{
// 检查DataTable是否为null以及索引是否在有效范围内
// (索引不能小于0,也不能大于或等于表的行数)
if (table != null && rowIndex >= 0 && rowIndex < table.Rows.Count)
{
// 从指定的行索引开始,删除该行及其以下的所有行
// 由于每次删除一行后,下一行会自动成为当前索引的行,所以不需要手动增加索引
while (rowIndex < table.Rows.Count)
{
// 删除当前索引处的行
table.Rows.RemoveAt(rowIndex);
// 由于已删除一行,无需对rowIndex进行递增操作
}
}
// 返回修改后的DataTable(注意:DataTable是引用类型,所以直接返回table即可)
return table;
}
/// <summary>
/// 删除colName列中小于该值的行
/// </summary>
/// <param name="colName">列名</param>
/// <param name="value">比较的值</param>
/// <returns>过滤后的DataTable</returns>
public DataTable RemoveRowsLessThan(DataTable table, string colName, object value)
{
/// 获取指定列
DataColumn column = table.Columns[colName];
/// 将比较的值转换为列的数据类型
value = Convert.ChangeType(value, column.DataType);
/// 使用DataTable.Select选择colName列中小于value的行
DataRow[] rowsToDelete = table.Select($"{colName} < '{value}'");
/// 删除选择的行
foreach (DataRow row in rowsToDelete)
{
table.Rows.Remove(row);
}
/// 返回处理后的DataTable
return table;
}
/// <summary>
/// 删除colName列中大于该值的行
/// </summary>
/// <param name="colName">列名</param>
/// <param name="value">比较的值</param>
/// <returns>过滤后的DataTable</returns>
public DataTable RemoveRowsGreaterThan(DataTable table, string colName, object value)
{
/// 获取指定列
DataColumn column = table.Columns[colName];
/// 将比较的值转换为列的数据类型
value = Convert.ChangeType(value, column.DataType);
/// 使用DataTable.Select选择colName列中大于value的行
DataRow[] rowsToDelete = table.Select($"{colName} > '{value}'");
/// 删除选择的行
foreach (DataRow row in rowsToDelete)
{
table.Rows.Remove(row);
}
/// 返回处理后的DataTable
return table;
}
/// <summary>
/// 单元格上右键点击时 创建上下文菜单
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void dataGridView1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
if (e.RowIndex >= 0 && e.ColumnIndex >= 0)
{
dataGridView1.CurrentCell = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex];
DataGridViewColumn currentColumn = dataGridView1.Columns[e.ColumnIndex];
string columnName = currentColumn.Name;//获取列名称
textBox1.AppendText("右键单击 单元格 事件 :[" + e.RowIndex +","+ e.ColumnIndex+"] , 列名称:"+ columnName + Environment.NewLine);
// 获取当前单元格的值
object cellValue = dataGridView1.CurrentCell.Value;
// 创建上下文菜单
ContextMenuStrip contextMenuStrip = new ContextMenuStrip();
contextMenuStrip.Items.Add("删除->小于该值的行").Click += (s, args) =>
{
//检查 cellValue 是否为 null,以确保单元格中有值。
if (cellValue != null)
{
dataTable = RemoveRowsLessThan(dataTable, columnName, cellValue);
textBox1.AppendText("删除->小于该值的行,RowIndex:" + e.RowIndex + Environment.NewLine);
}
};
contextMenuStrip.Items.Add("删除->大于该值的行 ").Click += (s, args) =>
{
//检查 cellValue 是否为 null,以确保单元格中有值。
if (cellValue != null)
{
dataTable = RemoveRowsGreaterThan(dataTable, columnName, cellValue);
textBox1.AppendText("删除->大于该值的行,RowIndex:" + e.RowIndex + Environment.NewLine);
}
};
contextMenuStrip.Items.Add("删除该行").Click += (s, args) =>
{
//检查 cellValue 是否为 null,以确保单元格中有值。
if (cellValue != null)
{
dataTable = DeleteRowByIndex(dataTable, e.RowIndex);
textBox1.AppendText("删除该行,RowIndex:" + e.RowIndex + Environment.NewLine);
}
};
contextMenuStrip.Items.Add("删除->等于该值的行").Click += (s, args) =>
{
//检查 cellValue 是否为 null,以确保单元格中有值。
if (cellValue != null)
{
dataTable = RemoveRowsEqual(dataTable, columnName, cellValue);
textBox1.AppendText("删除->等于该值的行,RowIndex:" + e.RowIndex + Environment.NewLine);
}
};
contextMenuStrip.Items.Add("删除->不等于该值的行").Click += (s, args) =>
{
//检查 cellValue 是否为 null,以确保单元格中有值。
if (cellValue != null)
{
dataTable = RemoveRowsNotEqual(dataTable, columnName, cellValue);
textBox1.AppendText("删除->不等于该值的行,RowIndex:" + e.RowIndex + Environment.NewLine);
}
};
contextMenuStrip.Items.Add("删除该行及上面的所有行").Click += (s, args) =>
{
//检查 cellValue 是否为 null,以确保单元格中有值。
if (cellValue != null)
{
dataTable = DeleteRowsAboveIndex(dataTable, e.RowIndex);
textBox1.AppendText("删除该行,RowIndex:" + e.RowIndex + Environment.NewLine);
}
};
contextMenuStrip.Items.Add("删除该行及下面的所有行").Click += (s, args) =>
{
//检查 cellValue 是否为 null,以确保单元格中有值。
if (cellValue != null)
{
dataTable = DeleteRowsFromIndex(dataTable, e.RowIndex);
textBox1.AppendText("删除该行,RowIndex:" + e.RowIndex + Environment.NewLine);
}
};
// 显示上下文菜单
contextMenuStrip.Show(MousePosition);
}
}
}
/// <summary>
/// 统计次数出现的数
/// </summary>
/// <param name="nums"></param>
/// <returns></returns>
int GetMajorityItem(int[] nums)
{
int count = 0;
int majorityItem = 0;
for (int i = 0; i < nums.Length; i++)
{
int item = nums[i];
int sameCount = 1;
for (int j = i + 1; j < nums.Length; j++)
{
if (nums[j] == item)
{
sameCount++;
}
}
if (sameCount > count)
{
count = sameCount;
majorityItem = item;
}
}
return majorityItem;
}
public static string[] RemoveNonMatchingLengthElements(int length, string[] strArray, int[] lengthArray)
{
List<string> strList = new List<string>(strArray.Length); //指定容量为strArray.Length
for (int i = 0; i < strArray.Length; i++)
{
if (lengthArray[i] == length)
{
strList.Add(strArray[i]); //使用Add方法而不是Append
}
}
return strList.ToArray();
}
private void button5_Click(object sender, EventArgs e)
{
// 从剪贴板读取数据
if (Clipboard.ContainsText())
{
string clipboardData = Clipboard.GetText();
string lineSeparator = GetLineSeparator(clipboardData);
textBox1.AppendText("分析换行符为: " + lineSeparator + Environment.NewLine);
var lines = clipboardData.Split(new string[] { lineSeparator }, StringSplitOptions.None);
textBox1.AppendText("读取数据行数:" + lines.Length + Environment.NewLine);
if (lines.Length <= 1)
{
textBox1.AppendText("数据格式错误,必须包含列名并且至少有2行数据。" + Environment.NewLine);
return;
}
//去除每行 首尾空白字符
lines = TrimLines(lines);
//删除最后面连续空行
lines = RemoveTrailingEmptyLines(lines);
//把连续的空格替换为制表符
lines = ReplaceSpacesWithTabs(lines);
//检测制表符数量
(bool consistent, int[] tabCounts) = CheckTabCounts(lines);
if (tabCounts[0] < 1)
{
textBox1.AppendText("每行的制表符数量为0" + Environment.NewLine);
textBox1.AppendText("尝试转换空格为制表符 " + Environment.NewLine);
}
//分析每行制表符的数量
(consistent, tabCounts) = CheckTabCounts(lines);
textBox1.AppendText("每行的制表符数量为:" + tabCounts[0] + Environment.NewLine);
if (tabCounts[0] < 1)
{
return;
}
// 所有行中 制表符数量 出现最多的 制表符数量,大多数行中一致的制表符数量
var maxMajorityItem = GetMajorityItem(tabCounts);
//删除制表符不等于 大多数行中一致的制表符数量
lines = RemoveNonMatchingLengthElements(maxMajorityItem, lines, tabCounts);
(consistent, tabCounts) = CheckTabCounts(lines);
if (consistent == false)
{
//每行制表符的数量不一致
textBox1.AppendText("每行制表符的数量不一致 失败" + Environment.NewLine);
//展示出每行 每行制表符的数量
textBox1.AppendText("行\t制表符数量" + Environment.NewLine);
for (int i = 0; i < tabCounts.Length; i++)
{
textBox1.AppendText((i + 1) + "\t" + tabCounts[i] + Environment.NewLine);
}
return;
}
DataTable dataTable1 = new DataTable { };
if (tabCounts[0] >= 1 && consistent)
{
textBox1.AppendText("每行的制表符数量一致 表格数据正确" + Environment.NewLine);
// 处理数据
int rowCount = lines.Length;
int colCount = lines[0].Split('\t').Length;
string[] columnNames = lines[0].Split('\t');
//取第一行为表头时 表头不能重复
//判定第一行是否有重复值
if (HasDuplicate(columnNames))
{
//有重复值则 自动生成默认表头标题
textBox1.AppendText("取第一行为表头标题时 发现表头有重复值 自动生成默认表头标题" + Environment.NewLine);
for (int i = 0; i < colCount; i++)
{
dataTable1.Columns.Add("列" + (i + 1), typeof(string));
}
}
else
{
//没有重复值 取第一行为表头标题
textBox1.AppendText("取第一行为表头标题" + Environment.NewLine);
for (int i = 0; i < colCount; i++)
{
dataTable1.Columns.Add(columnNames[i], typeof(string));
}
}
for (int i = 1; i < rowCount; i++)
{
string[] cells = lines[i].Split('\t');
if (cells.Length == colCount)
{
dataTable1.Rows.Add(cells);
}
}
// 显示数据
dataTable = dataTable1;
}
}
else
{
MessageBox.Show("剪贴板中没有文本数据。");
}
}
public static List<Score> GetScores(List<List<string>> inputData)
{
Dictionary<int, Score> scores = new Dictionary<int, Score>();
for (int i = 0; i < inputData.Count; i++)
{
int number = int.Parse(inputData[i][1]);
int times = int.Parse(inputData[i][2]);
if (!scores.ContainsKey(number))
{
scores.Add(number, new Score() { Number = number });
}
scores[number].PositionScore += GetPositionScore(i + 1);
scores[number].TimesScore += GetTimesScore(times);
}
int rank = 1;
foreach (Score score in scores.Values)
{
score.Rank = rank++;
score.TotalScore = score.PositionScore + score.TimesScore;
}
return scores.Values.ToList();
}
public static double GetPositionScore(int position)
{
switch (position)
{
case 1: return 1.0;
case 2: return 0.9;
case 3: return 0.8;
case 4: return 0.7;
case 5: return 0.6;
case 6: return 0.5;
case 7: return 0.4;
case 8: return 0.3;
case 9: return 0.2;
default: return 0.1;
}
}
public static double GetTimesScore(int times)
{
switch (times)
{
case 1: return 0.1;
case 2: return 0.2;
case 3: return 0.3;
case 4: return 0.4;
case 5: return 0.5;
case 6: return 0.6;
case 7: return 0.7;
case 8: return 0.8;
case 9: return 0.9;
default: return 1.0;
}
}
private void button6_Click(object sender, EventArgs e)
{
// 显示数据
DataTable resultTable = new DataTable();
dataTable = resultTable;
}
/// <summary>
/// 撤销 返回上一个表格
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button7_Click(object sender, EventArgs e)
{
// 撤销和恢复 模式,不记录表格数据了
Undo_Redo_Mode = true;
var lastIndex = curr_history_index - 1;
//如果有上一个表格
if (lastIndex >= 0 )
{
curr_history_index = lastIndex;
dataTable = dataTable_history[curr_history_index];
textBox1.AppendText("撤销 返回上一个表格" + Environment.NewLine);
}
else
{
textBox1.AppendText("无法撤销:已经是第一个表格了" + Environment.NewLine);
}
Undo_Redo_Mode = false;
}
/// <summary>
/// 恢复 返回下一个表格
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button8_Click(object sender, EventArgs e)
{
Undo_Redo_Mode = true;
var nextIndex = curr_history_index +1;
//如果有下一个表格
if (nextIndex <= dataTable_history.Count-1)
{
curr_history_index = nextIndex;
dataTable = dataTable_history[curr_history_index];
textBox1.AppendText("恢复 返回下一个表格" + Environment.NewLine);
}
else
{
textBox1.AppendText("无法恢复:已经是最后一个表格了" + Environment.NewLine);
}
// 撤销和恢复 模式,不记录表格数据了
Undo_Redo_Mode = false;
}
/// <summary>
/// 从剪贴板追加数据
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button9_Click(object sender, EventArgs e)
{
//克隆的 DataTable 中的数据
DataTable clonedDataTable = _dataTable.Clone();
clonedDataTable.Clear(); // 清空克隆的 DataTable 中的数据
foreach (DataRow row in _dataTable.Rows)
{
clonedDataTable.ImportRow(row); // 导入原始 DataTable 中的每一行数据到克隆的 DataTable
}
// 从剪贴板读取数据
if (Clipboard.ContainsText())
{
string clipboardData = Clipboard.GetText();
string lineSeparator = GetLineSeparator(clipboardData);
var lines = clipboardData.Split(new string[] { lineSeparator }, StringSplitOptions.None);
if (lines.Length <= 1)
{
textBox1.AppendText("数据格式错误,必须包含列名并且至少有2行数据。" + Environment.NewLine);
return;
}
lines = TrimLines(lines);
lines = RemoveTrailingEmptyLines(lines);
(bool consistent, int[] tabCounts) = CheckTabCounts(lines);
if (tabCounts[0] < 1)
{
textBox1.AppendText("每行的制表符数量为0" + Environment.NewLine);
lines = ReplaceSpacesWithTabs(lines);
textBox1.AppendText("尝试转换空格为制表符 " + Environment.NewLine);
}
(consistent, tabCounts) = CheckTabCounts(lines);
if (tabCounts[0] < 1)
{
return;
}
if (!consistent)
{
textBox1.AppendText("每行制表符的数量不一致 失败" + Environment.NewLine);
textBox1.AppendText("行\t制表符数量" + Environment.NewLine);
for (int i = 0; i < tabCounts.Length; i++)
{
textBox1.AppendText((i + 1) + "\t" + tabCounts[i] + Environment.NewLine);
}
return;
}
if (tabCounts[0] >= 1 && consistent)
{
textBox1.AppendText("每行的制表符数量一致 表格数据正确" + Environment.NewLine);
int rowCount = lines.Length;
int colCount = lines[0].Split('\t').Length;
string[] columnNames = lines[0].Split('\t');
// 追加新列到 DataTable
// 检查重复列名
foreach (string columnName in columnNames)
{
DataColumn existingColumn = clonedDataTable.Columns[columnName];
if (existingColumn == null)
{// 添加新列
clonedDataTable.Columns.Add(columnName, typeof(string));
int columnIndex = clonedDataTable.Columns.IndexOf(columnName);
int rowCount1 = clonedDataTable.Rows.Count;
// 添加对应列的数据
for (int i = 1; i < rowCount1; i++)
{
string[] cells = lines[i].Split('\t');
if (cells.Length > columnIndex)
{
clonedDataTable.Rows[i - 1][columnIndex] = cells[columnIndex];
}
}
}
else
{// 列名重复,将数据添加到已存在列的最后一行
int rowIndex = clonedDataTable.Rows.Count - 1;
DataRow lastRow = clonedDataTable.Rows[rowIndex];
}
}
for (int i = 1; i < rowCount; i++)
{
string[] cells = lines[i].Split('\t');
if (cells.Length == colCount)
{
clonedDataTable.Rows.Add(cells);
}
}
}
dataTable = clonedDataTable;
}
else
{
MessageBox.Show("剪贴板中没有文本数据。");
}
}
private void button10_Click(object sender, EventArgs e)
{
dataTable = CountStrings(dataTable);
}
/// <summary>
/// 为给定的DataTable的第一列添加一个序号列,并返回处理后的DataTable副本
/// </summary>
/// <param name="table">待处理的源DataTable</param>
/// <returns>添加了序号列的DataTable副本</returns>
public DataTable AddSequentialNumberColumnToFirstColumn(DataTable table)
{
// 检查DataTable是否为空或无数据行
if (table == null || table.Rows.Count == 0)
{
throw new ArgumentException("输入的DataTable不能为空或无数据行");
}
// 创建新的DataTable,包含序号列和其他原列
DataTable processedTable = new DataTable();
// 确定新序号列的唯一名称
int suffixCounter = 1;
string columnName = "序号";
while (table.Columns.Contains(columnName)) // 检查是否存在同名列并适当命名
{
columnName = $"序号_{suffixCounter++}";
}
// 在第一位置添加新的序号列
DataColumn numberColumn = new DataColumn(columnName, typeof(int));
table.Columns.Add(numberColumn);
numberColumn.SetOrdinal(0); // 将这个新列设置为第一列
// 填充新列的序号
int rowIndex = 1;
foreach (DataRow row in table.Rows)
{
row[columnName] = rowIndex++;
}
return table;
}
/// <summary>
/// 为给定的DataTable的第一行添加一个序号行,并返回处理后的DataTable副本
/// </summary>
/// <param name="table">待处理的源DataTable</param>
/// <returns>添加了序号行的DataTable副本</returns>
public DataTable AddSequentialNumberRowToFirstRow(DataTable table)
{
// 检查DataTable是否为空或无列
if (table == null || table.Columns.Count == 0)
{
throw new ArgumentException("输入的DataTable不能为空或无列");
}
// 创建序号行
DataRow numberRow = table.NewRow();
for (int i = 0; i < table.Columns.Count; i++)
{
// 尝试将列名作为序号,如果不是数字类型则填充为DBNull或特定标识符
if (table.Columns[i].DataType == typeof(int) ||
table.Columns[i].DataType == typeof(long) ||
table.Columns[i].DataType == typeof(string) ||
table.Columns[i].DataType == typeof(short))
{
numberRow[i] = i + 1; // 序号从1开始
}
else
{
numberRow[i] = DBNull.Value; // 或使用任何适合列数据类型的默认值
}
}
// 将序号行插入到DataTable的第一行
table.Rows.InsertAt(numberRow, 0);
return table;
}
/// <summary>
/// 将输入的DataTable中所有列(从第二列开始)的数据依次纵向连接到第一列的末尾,并返回处理后的新的DataTable。
/// 新表中保持原第一列的名称。
/// </summary>
/// <param name="inputTable">待处理的源DataTable</param>
/// <returns>处理后的新的DataTable</returns>
public DataTable StackColumnsVertically(DataTable inputTable)
{
// 检查输入的DataTable是否为空或列数不足2列
if (inputTable == null || inputTable.Rows.Count == 0 || inputTable.Columns.Count < 2)
{
throw new ArgumentException("输入的DataTable不能为空、无数据行或列数不足2列");
}
// 创建一个新的DataTable用于存放处理后的数据
DataTable processedTable = new DataTable();
// 添加新列,列名与原第一列相同,但数据类型设置为object,以便能容纳任何类型的数据
processedTable.Columns.Add(inputTable.Columns[0].ColumnName, typeof(object));
// 先处理第一列,将所有值添加到新DataTable中
foreach (DataRow row in inputTable.Rows)
{
processedTable.Rows.Add(row[0]);
}
// 遍历除第一列之外的所有列
for (int columnIndex = 1; columnIndex < inputTable.Columns.Count; columnIndex++)
{
// 对当前列中的每一行进行遍历
foreach (DataRow sourceRow in inputTable.Rows)
{
// 获取当前列的值
object columnValue = sourceRow[columnIndex];
// 将当前列的值添加到新的DataTable中
processedTable.Rows.Add(columnValue);
}
}
return processedTable;
}
//所有列的数据合并到一个新的单列
private void button11_Click(object sender, EventArgs e)
{
dataTable = StackColumnsVertically(dataTable);
}
/// <summary>
/// 增加序号列
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button12_Click(object sender, EventArgs e)
{
dataTable = AddSequentialNumberColumnToFirstColumn(dataTable);
}
/// <summary>
/// //增加序号行
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button13_Click(object sender, EventArgs e)
{
dataTable = AddSequentialNumberRowToFirstRow(dataTable);
}
private void button14_Click(object sender, EventArgs e)
{
// 提取所有数字并转换为 int 数组
int[] numbers = dataTable.AsEnumerable() // 将 DataTable 转换为 EnumerableRowCollection
.SelectMany(row => row.ItemArray)
.SelectMany(element => element.ToString())
.Where(char.IsDigit)
.Select(char.ToString)
.Select(int.Parse)
.ToArray();
// 初始化变量
int totalNumbers = numbers.Length;
int sumOfNumbers = numbers.Sum();
int minNumber = numbers.Min();
int maxNumber = numbers.Max();
// 计算平均值、中位数、方差和标准差
double average = totalNumbers > 0 ? (double)sumOfNumbers / totalNumbers : 0;
double median = totalNumbers > 0 ? numbers.OrderBy(n => n).Skip(totalNumbers / 2).Take(1).DefaultIfEmpty(0).Average() : 0;
double variance = totalNumbers > 1 ? numbers.Average(n => Math.Pow(n - average, 2)) : 0;
double standardDeviation = Math.Sqrt(variance);
// 输出结果到 textBox1
textBox1.AppendText("多少列: " + dataTable.Columns.Count + Environment.NewLine);
textBox1.AppendText("多少行: " + dataTable.Rows.Count + Environment.NewLine);
textBox1.AppendText("多少个元素: " + (dataTable.Columns.Count * dataTable.Rows.Count) + Environment.NewLine);
textBox1.AppendText("共有多少个数字: " + totalNumbers + Environment.NewLine);
textBox1.AppendText("数字的总和: " + sumOfNumbers + Environment.NewLine);
textBox1.AppendText("平均值: " + average + Environment.NewLine);
textBox1.AppendText("最小值: " + minNumber + Environment.NewLine);
textBox1.AppendText("最大值: " + maxNumber + Environment.NewLine);
textBox1.AppendText("中位数: " + median + Environment.NewLine);
textBox1.AppendText("方差: " + variance + Environment.NewLine);
textBox1.AppendText("标准差: " + standardDeviation + Environment.NewLine);
}
/// <summary>
/// 增加默认列名行
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button15_Click(object sender, EventArgs e)
{
// 列名行变成第一行数据,并增加默认的列名行
dataTable = TransformDataTable(dataTable);
textBox1.AppendText("增加表格默认列名行" + Environment.NewLine);
}
}
public class Score
{
public int Rank { get; set; }
public int Number { get; set; }
public double PositionScore { get; set; }
public double TimesScore { get; set; }
public double TotalScore { get; set; }
}
}