c# - C# + Excel 的难点
问题描述
我有个问题。
我有一个 Excel 文件,有时同一客户在 2 行中。但不总是。
它就像: 点击
现在,我想在 C# 中创建一个 DataGrid,它可以将其列在一行中,例如: 单击
我知道更改 Excel 文件会更容易,但假设它不会那样工作(我们得到这样的文件,我们不能更改它)
我知道我也可以制作另一个 Excel 文件并用 Excel 制作(已经这样做了,但我们更需要它作为 C#)
现在我在这一点上:
private void button2_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog() { Filter = "Excel Arbeitsmappe |*.xlsx", ValidateNames = true };
if (ofd.ShowDialog() == DialogResult.OK)
textBox1.Text = ofd.SafeFileName;
Excel.Application excelApp = new Excel.Application();
excelApp.Visible = false;
string filename = ofd.FileName;
Excel.Workbook workbook = excelApp.Workbooks.Open(filename);
Excel.Worksheet worksheet = workbook.Worksheets[1];
dataGridView1.ColumnCount = 2;
dataGridView1.Columns[0].Name = "Number";
dataGridView1.Columns[1].Name = "Street";
int rows = worksheet.UsedRange.Rows.Count;
for (int i = 2; i <= rows; i++)
{
string combinehr = worksheet.Cells[i, 150].Text + worksheet.Cells[i, 151].Text;
dataGridView1.Rows.Add(worksheet.Cells[i,29].Text, combinehr);
}
}
我如何扩展它以使其像我想要的那样工作?
我会很感激
(对不起英语)
解决方案
参考ExcelDataReader、ExcelDataReader.DataSet和DataSetExtensions (.Net),您可以很容易地将 Excel 文件读入 a DataSet
,然后您只需使用以下逻辑:
输入文件:
using System;
using System.Data;
using System.IO;
using System.Linq;
using ExcelDataReader;
public DataTable GetTableFromExcel(string filePath)
{
DataSet ds = new DataSet();
using (var stream = System.IO.File.Open(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
ds = reader.AsDataSet();
}
}
DataTable table = new DataTable();
table.Columns.Add(new DataColumn("CustomerNr"));
table.Columns.Add(new DataColumn("Address"));
// Set column names
for (int i = 0; i < ds.Tables[0].Columns.Count; i++)
{
// DataColumn.ColumnName can't be empty when DataColumn is part
// of a DataTable (throws ArgumentException)
string columnName = ds.Tables[0].Rows[0][i].ToString();
if (string.IsNullOrWhiteSpace(columnName))
{
columnName = $"Column{i}";
}
ds.Tables[0].Columns[i].ColumnName = columnName;
}
// Remove the first row containing the headers
ds.Tables[0].Rows.Remove(ds.Tables[0].Rows[0]);
// I don't have the benchmarks with me right now, but I've tested
// DataTable.Select vs DataTable.AsEnumerable.Select many times
// and the AsEnumerable method its faster, that's why you need the
// reference to System.Data.DataSetExtensions
var enumerableTable = ds.Tables[0].AsEnumerable();
// list of unique products
var products = enumerableTable.Select(row => row.Field<string>("Product")).Distinct();
// Add a column for each product
foreach (string product in products)
{
table.Columns.Add(new DataColumn(product));
}
// list of unique customers
var customerNumbers = enumerableTable.Select(row => row.Field<double>("CustomerNr")).Distinct();
foreach (var customerNumber in customerNumbers)
{
DataRow record = table.NewRow();
record["CustomerNr"] = customerNumber;
record["Address"] = enumerableTable.First(row => row.Field<double>("CustomerNr").Equals(customerNumber))[1];
for (int i = 2; i < table.Columns.Count; i++)
{
DataRow product = enumerableTable.FirstOrDefault(row => row.Field<double>("CustomerNr").Equals(customerNumber)
&& row.Field<string>("Product").Equals(table.Columns[i].ColumnName));
// Quantity = 0 if product is null
record[i] = product?["Quantity"] ?? 0;
}
table.Rows.Add(record);
}
return table;
}
结果DataTable
:
推荐阅读
- csv - 将订单日期和订单总额列添加到 woocommerce 报告 csv
- swift - 表查看两个不同单元格的相同 cellForRowAt 用法
- asp.net-mvc - Controller.OnException 被调用但返回错误 500,仅在生产中
- c++ - Visual Studio 选择启动项
- android - 三星上的安卓振动器
- arrays - 将 nsmanganedobject 转换为数组以查找数组的平均值
- database - 在性能方面,数据库是读优化还是写优化更好?
- django - 是否可以在 Django 中组合多个 values_list() ?
- r - “mean.default(X [[i]],...)中的错误:'trim'必须是长度为1的数字”R中的消息
- c - 释放指针范围之外的内存