我知道有不同的方法来阅读Excel文件:
Iterop
Oledb
Open Xml SDK
兼容性不是问题,因为程序将在受控环境中执行。
我的要求:
将文件读取到DataTable
/ CUstom Entitie
(我不知道如何为对象创建动态属性/字段[列名将在Excel文件中变化])
使用DataTable/Custom Entities
使用其数据执行某些操作。
使用操作结果更新DataTable
将其写回excel file
。
哪个会更简单。
另外,如果可能的话,请告诉我自定义实体(动态地向对象添加属性/字段)
答案 0 :(得分:63)
看看Linq-to-Excel。它非常整洁。
var book = new LinqToExcel.ExcelQueryFactory(@"File.xlsx");
var query =
from row in book.Worksheet("Stock Entry")
let item = new
{
Code = row["Code"].Cast<string>(),
Supplier = row["Supplier"].Cast<string>(),
Ref = row["Ref"].Cast<string>(),
}
where item.Supplier == "Walmart"
select item;
它也允许强类型的行访问。
答案 1 :(得分:20)
使用OLE Query,它非常简单(例如sheetName是Sheet1 $):
DataTable LoadWorksheetInDataTable(string fileName, string sheetName)
{
DataTable sheetData = new DataTable();
using (OleDbConnection conn = this.returnConnection(fileName))
{
conn.Open();
// retrieve the data using data adapter
OleDbDataAdapter sheetAdapter = new OleDbDataAdapter("select * from [" + sheetName + "]", conn);
sheetAdapter.Fill(sheetData);
}
return sheetData;
}
private OleDbConnection returnConnection(string fileName)
{
return new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + fileName + "; Jet OLEDB:Engine Type=5;Extended Properties=\"Excel 8.0;\"");
}
对于较新的Excel版本:
return new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filename + ";Extended Properties=Excel 12.0;");
您还可以在CodePlex上使用Excel Data Reader开源项目。它的工作非常适合从Excel工作表导出数据。
指定链接上给出的示例代码:
FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read);
//1. Reading from a binary Excel file ('97-2003 format; *.xls)
IExcelDataReader excelReader = ExcelReaderFactory.CreateBinaryReader(stream);
//...
//2. Reading from a OpenXml Excel file (2007 format; *.xlsx)
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
//...
//3. DataSet - The result of each spreadsheet will be created in the result.Tables
DataSet result = excelReader.AsDataSet();
//...
//4. DataSet - Create column names from first row
excelReader.IsFirstRowAsColumnNames = true;
DataSet result = excelReader.AsDataSet();
//5. Data Reader methods
while (excelReader.Read())
{
//excelReader.GetInt32(0);
}
//6. Free resources (IExcelDataReader is IDisposable)
excelReader.Close();
参考:How do I import from Excel to a DataSet using Microsoft.Office.Interop.Excel?
答案 2 :(得分:6)
尝试使用这种免费方式,https://freenetexcel.codeplex.com
Workbook workbook = new Workbook();
workbook.LoadFromFile(@"..\..\parts.xls",ExcelVersion.Version97to2003);
//Initialize worksheet
Worksheet sheet = workbook.Worksheets[0];
DataTable dataTable = sheet.ExportDataTable();
答案 3 :(得分:5)
我个人认为,开源免费ExcelMapper 最容易使用。
与通常的Microsoft.Interop和OLE查询相比,它提供了一种更简洁(即可读)的读取Excel文件的方式。
1。给定一个Excel文件:
2。创建一个Person C#对象:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
}
3。使用ExcelMapper进行阅读
var fileName = @"C:\Temp\Names.xlsx"; // your excel file
List<Person> people = new ExcelMapper(fileName).Fetch<Person>();
您还可以通过简单地传入一个额外的工作表参数来读取其他工作表:
var fileName = @"C:\Temp\Names.xlsx"; // your excel file
List<Person> people = new ExcelMapper(fileName).Fetch<Person>("Sheet2");
您可以使用NuGet进行安装
Install-Package ExcelMapper
免责声明:我没有与ExcelMapper关联,但是在尝试了各种不同的库之后,我发现该库最容易使用。
这是简短的video,展示了上述内容。来源:excel-automation-guide.com
答案 4 :(得分:4)
我意识到这个问题是在将近7年前提出的,但是对于某些有关使用C#导入excel数据的关键字,它仍然是Google搜索结果中的佼佼者,因此我想根据最近的一些技术发展提供一个替代方案。
导入Excel数据已经成为我日常工作中的一项常见任务,因此我简化了流程并在博客best way to read excel file in c#上记录了该方法。
我使用NPOI是因为它可以在未安装Microsoft Office的情况下读取/写入Excel文件,并且它不使用COM +或任何互操作性。这意味着它可以在云中工作!
但真正的魔力来自与NPOI映射器from Donny Tian配对,因为它使我无需编写任何代码即可将Excel列映射到C#类中的属性。很漂亮。
这是基本概念:
我创建一个.net类来匹配/映射我感兴趣的Excel列:
class CustomExcelFormat
{
[Column("District")]
public int District { get; set; }
[Column("DM")]
public string FullName { get; set; }
[Column("Email Address")]
public string EmailAddress { get; set; }
[Column("Username")]
public string Username { get; set; }
public string FirstName
{
get
{
return Username.Split('.')[0];
}
}
public string LastName
{
get
{
return Username.Split('.')[1];
}
}
}
注意,如果需要,它允许我根据列名进行映射!
然后,当我处理excel文件时,我需要做的就是这样:
public void Execute(string localPath, int sheetIndex)
{
IWorkbook workbook;
using (FileStream file = new FileStream(localPath, FileMode.Open, FileAccess.Read))
{
workbook = WorkbookFactory.Create(file);
}
var importer = new Mapper(workbook);
var items = importer.Take<CustomExcelFormat>(sheetIndex);
foreach(var item in items)
{
var row = item.Value;
if (string.IsNullOrEmpty(row.EmailAddress))
continue;
UpdateUser(row);
}
DataContext.SaveChanges();
}
现在,当然,我的代码没有修改Excel文件本身。我改为使用Entity Framework将数据保存到数据库中(这就是为什么在我的示例中看到“ UpdateUser”和“ SaveChanges”的原因)。但是关于SO save/modify a file using NPOI的讨论已经很好。
答案 5 :(得分:3)
答案 6 :(得分:0)
尝试使用Aspose.cells库,这非常好。
Install-package Aspose.cells
有示例代码:
using Aspose.Cells;
using System;
namespace ExcelReader
{
class Program
{
static void Main(string[] args)
{
// Replace path for your file
readXLS(@"C:\MyExcelFile.xls"); // or "*.xlsx"
Console.ReadKey();
}
public static void readXLS(string PathToMyExcel)
{
//Open your template file.
Workbook wb = new Workbook(PathToMyExcel);
//Get the first worksheet.
Worksheet worksheet = wb.Worksheets[0];
//Get cells
Cells cells = worksheet.Cells;
// Get row and column count
int rowCount = cells.MaxDataRow;
int columnCount = cells.MaxDataColumn;
// Current cell value
string strCell = "";
Console.WriteLine(String.Format("rowCount={0}, columnCount={1}", rowCount, columnCount));
for (int row = 0; row <= rowCount; row++) // Numeration starts from 0 to MaxDataRow
{
for (int column = 0; column <= columnCount; column++) // Numeration starts from 0 to MaxDataColumn
{
strCell = "";
strCell = Convert.ToString(cells[row, column].Value);
if (String.IsNullOrEmpty(strCell))
{
continue;
}
else
{
// Do your staff here
Console.WriteLine(strCell);
}
}
}
}
}
}
答案 7 :(得分:-1)
从excel中读取,修改并写回
/// <summary>
/// /Reads an excel file and converts it into dataset with each sheet as each table of the dataset
/// </summary>
/// <param name="filename"></param>
/// <param name="headers">If set to true the first row will be considered as headers</param>
/// <returns></returns>
public DataSet Import(string filename, bool headers = true)
{
var _xl = new Excel.Application();
var wb = _xl.Workbooks.Open(filename);
var sheets = wb.Sheets;
DataSet dataSet = null;
if (sheets != null && sheets.Count != 0)
{
dataSet = new DataSet();
foreach (var item in sheets)
{
var sheet = (Excel.Worksheet)item;
DataTable dt = null;
if (sheet != null)
{
dt = new DataTable();
var ColumnCount = ((Excel.Range)sheet.UsedRange.Rows[1, Type.Missing]).Columns.Count;
var rowCount = ((Excel.Range)sheet.UsedRange.Columns[1, Type.Missing]).Rows.Count;
for (int j = 0; j < ColumnCount; j++)
{
var cell = (Excel.Range)sheet.Cells[1, j + 1];
var column = new DataColumn(headers ? cell.Value : string.Empty);
dt.Columns.Add(column);
}
for (int i = 0; i < rowCount; i++)
{
var r = dt.NewRow();
for (int j = 0; j < ColumnCount; j++)
{
var cell = (Excel.Range)sheet.Cells[i + 1 + (headers ? 1 : 0), j + 1];
r[j] = cell.Value;
}
dt.Rows.Add(r);
}
}
dataSet.Tables.Add(dt);
}
}
_xl.Quit();
return dataSet;
}
public string Export(DataTable dt, bool headers = false)
{
var wb = _xl.Workbooks.Add();
var sheet = (Excel.Worksheet)wb.ActiveSheet;
//process columns
for (int i = 0; i < dt.Columns.Count; i++)
{
var col = dt.Columns[i];
//added columns to the top of sheet
var currentCell = (Excel.Range)sheet.Cells[1, i + 1];
currentCell.Value = col.ToString();
currentCell.Font.Bold = true;
//process rows
for (int j = 0; j < dt.Rows.Count; j++)
{
var row = dt.Rows[j];
//added rows to sheet
var cell = (Excel.Range)sheet.Cells[j + 1 + 1, i + 1];
cell.Value = row[i];
}
currentCell.EntireColumn.AutoFit();
}
var fileName="{somepath/somefile.xlsx}";
wb.SaveCopyAs(fileName);
_xl.Quit();
return fileName;
}