C#:从 32 位切换到 64 位后需要 XLS 库
C#: XLS library needed after switching from 32BIT to 64BIT
原始查询:
目前我想从 32 位版本切换到 64 位版本,但我无法找到任何库以从 xls 中提取数据。
我可以在 ClosedXML 上与其他人一起工作,例如 (xlsx, xlsm),不幸的是不支持 xls。
所以现在这个连接不会成立。
string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties='Excel 12.0;HDR=NO,IMEX=1'";
string excelQuery = "SELECT * FROM [monthly$A:G]";
安装64位OLE驱动不在话下。所以也许有人偶然发现了它,或者有任何想法。
我想使用类似于 HDR=YES
的 headers 将数据构建到数据表中,并且可以像上面的示例那样将其关闭。
此外,由于 excel 格式,短小精悍是不可能的:(
我试图找到一些问题,但我能找到的只是为 64 位安装 OLEDB Driver。
编辑:
我不明白为什么有人对 Panagiotis 的回答进行投票,因为它已更正,这就是我接受它的原因。他建议使用 ExcelDataReader
被证明是最有效的,因为我在应用程序中使用了更多格式的 excel,如 .xlsx
、.xlsm
和 .xlsb
,此外还有一些.csv
个文件。
这让我可以构建一个模块,这就足够了。
他还指出 .xls
很古老,但不幸的是它并没有过时,因为我公司的许多流程仍然依赖它。但它应该是 osbsolete,不幸的是,我们由于计划不周的流程而陷入困境,而不是因为 .xls
有用。尤其是那些公司应该看看某些格式不受支持的事实,或者可能会失去这种支持,因为 .xls
正在慢慢获得这种待遇。
另一项编辑:
不幸的是,我刚刚注意到,我是一个菜鸟,我不知道可以支付 nugets。不幸的是,Aspose 是那些付费扩展之一。所以我不得不更改代码并添加另一个转换器 class。
为此,我根据需要使用并修改了另一个 [thread][1] 中使用的代码。
最后编辑:
好的,在更新到 ExcelDataReader
之后,我对性能不满意,并且转换文件对我来说似乎不合适,因为我注意到@MarkPflug 已经更新 [Sylvan.Data.Excel ][2] 库,我基于它编写代码的基准给我留下了深刻的印象。有一些问题,但在联系并向 Mark 提供示例后,他很快就解决了这些问题。目前这是我能想到的最快最好的解决方案。
我将更新它以用于从选定的文件中异步提取。但基于此,任何人都可以使用它。
**FINAL CODE:**
using SylExcel = Sylvan.Data.Excel;
using SylCSV = Sylvan.Data.Csv;
using SylData = Sylvan.Data;
/// <summary>
/// get data from .csv, .xls, .xlsx, .xlsm, .xlsb. Call is then redirected accordingly
/// </summary>
/// <param name="_filePath">path to file needed</param>
/// <param name="_sheetName">sheet name to extract</param>
/// <param name="_structure">structure of needed file</param>
public void GetData(string _filePath, string? _sheetName, FilesStructures.Structure _structure)
{
//if (CheckIfOpened(_filePath))
//{
// throw new OperationCanceledException(_filePath + " is opened, please close it.");
//}
try
{
string extension = Path.GetExtension(_filePath);
switch (extension)
{
case ".csv":
SylvanReaderCSV(_filePath, _structure);
break;
default:
SylvanReader(_filePath, _sheetName, _structure);
break;
}
//collect file information
GetMetadata(_filePath);
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
/// <summary>
/// sylvan reader for .xls, .xlsx, .xlsm, .xlsb
/// </summary>
/// <param name="_filePath">path to file needed</param>
/// <param name="_sheetName">sheet name to extract</param>
/// <param name="_structure">structure of needed file</param>
/// <exception cref="Exception"></exception>
private void SylvanReader(string _filePath, string? _sheetName, FilesStructures.Structure _structure)
{
try
{
string headerSchema = "";
//get unique column list to test for duplicates
List<string> columnList = new List<string>();
//build headers
//_structure.HeaderList = List<strings> passed by object _structure
foreach (var header in _structure.HeaderList)
{
if (!columnList.Exists(column => column == header))
{
headerSchema += header + ", ";
columnList.Add(header);
}
}
//remove last 2 chars
headerSchema = headerSchema.Substring(0, headerSchema.Length - 2);
var options = new SylExcel.ExcelDataReaderOptions { Schema = SylExcel.ExcelSchema.NoHeaders, GetErrorAsNull = true };
//collect data
using (SylExcel.ExcelDataReader excelDataReader = SylExcel.ExcelDataReader.Create(_filePath, options))
{
//loop to locate sheet
while (excelDataReader.WorksheetName != _sheetName)
{
excelDataReader.NextResult();
if (excelDataReader.WorksheetName == null)
{
throw new Exception("didnt find the sheet");
}
}
//loop to find headers
for(int i = 0; i < _structure.StartRow; i++)
{
excelDataReader.Read();
}
// parse the schema, and use it to reinitialize the schema for the sheet.
var schema = SylData.Schema.Parse(headerSchema);
excelDataReader.InitializeSchema(schema.GetColumnSchema(), useHeaders: true);
DataTable = new DataTable();
DataTable.Load(excelDataReader);
}
}
catch(Exception ex)
{
throw new Exception(ex.Message);
}
}
/// <summary>
/// sylvan reader for .csv
/// </summary>
/// <param name="_filePath">path to file needed</param>
/// <param name="_sheetName">sheet name to extract</param>
/// <param name="_structure">structure of needed file</param>
/// <exception cref="Exception"></exception>
private void SylvanReaderCSV(string _filePath, FilesStructures.Structure _structure)
{
try
{
string headerSchema = "";
//get unique column list to test for duplicates
List<string> columnList = new List<string>();
//build headers
//_structure.HeaderList = List<strings> passed by object _structure
foreach (var header in _structure.HeaderList)
{
if (!columnList.Exists(column => column == header))
{
headerSchema += header + ", ";
columnList.Add(header);
}
}
//remove last 2 chars
headerSchema = headerSchema.Substring(0, headerSchema.Length - 2);
var schema = new SylCSV.CsvSchema(SylData.Schema.Parse(headerSchema));
var options = new SylCSV.CsvDataReaderOptions //check if get error as null possible
{
Schema = schema,
};
using (SylCSV.CsvDataReader csvDataReader = SylCSV.CsvDataReader.Create(_filePath, options))
{
DataTable = new DataTable();
DataTable.Load(csvDataReader);
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
[1]:
[2]: https://github.com/MarkPflug/Sylvan.Data.Excel
您可以查看我的图书馆 Sylvan.Data.Excel. It has no external dependencies, is cross plat, open-source, MIT licensed, and also the fastest Excel data reader for .NET。它通过相同的 API 同时支持 .xls、.xlsx 和 .xlsb。它不像其他一些库那样功能齐全,它只支持读取(不支持写入),但它应该是 ACE 的一个相当直接的替代品,因为它实现了 DbDataReader
。如果您 运行 进入任何 issues/questions,请随时在 GitHub 存储库中打开它们。
使用起来非常简单:
var edr = ExcelDataReader.Create("data.xls");
while(edr.Read()) {
for(int i = 0; i < edr.FieldCount; i++) {
var value = edr.GetString(i);
}
}
默认情况下,它会期望每个 sheet 的第一行包含 headers。然而,这可以被禁用。禁用时,只能按顺序访问列。
var opts = new ExcelDataReaderOptions { Schema = ExcelSchema.NoHeaders };
var edr = ExcelDataReader.Create("data.xls", opts);
由于它实现了DbDataReader
,将其加载到数据table中是一个one-liner:
var dt = new DataTable();
dt.Load(edr);
首先,不要一开始就使用 XLS。该格式在 2007 年被 xlsx
取代 - 那是 15 年前。 所有 Excel 版本使用 xlsx
,所有应用程序也是如此。不存在兼容性问题 - 事实上,导致兼容性问题的是古老的 xls
。 Google 表格不支持 xls
文件,除非您付费。 xls
坚持的唯一原因是惰性。
如果您坚持使用 xls
(为什么?)您可以使用 ExcelDataReaader. That library can read both xls
and xlsx
files and return either an DbDataReader
or a DataSet
. The NuGet package 有 17M 的下载量,使其成为继 EPPlus 之后第二受欢迎的 Excel 库。
存储库页面中的示例显示了如何在最简单的情况下使用它 - ExcelReaderFactory.CreateReader(stream)
returns a DbDataReader
:
using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read))
{
// Auto-detect format, supports:
// - Binary Excel files (2.0-2003 format; *.xls)
// - OpenXml Excel files (2007 format; *.xlsx, *.xlsb)
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
// Choose one of either 1 or 2:
// 1. Use the reader methods
do
{
while (reader.Read())
{
// reader.GetDouble(0);
}
} while (reader.NextResult());
// 2. Use the AsDataSet extension method
var result = reader.AsDataSet();
// The result of each spreadsheet is in result.Tables
}
}
原始查询: 目前我想从 32 位版本切换到 64 位版本,但我无法找到任何库以从 xls 中提取数据。 我可以在 ClosedXML 上与其他人一起工作,例如 (xlsx, xlsm),不幸的是不支持 xls。
所以现在这个连接不会成立。
string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties='Excel 12.0;HDR=NO,IMEX=1'";
string excelQuery = "SELECT * FROM [monthly$A:G]";
安装64位OLE驱动不在话下。所以也许有人偶然发现了它,或者有任何想法。
我想使用类似于 HDR=YES
的 headers 将数据构建到数据表中,并且可以像上面的示例那样将其关闭。
此外,由于 excel 格式,短小精悍是不可能的:(
我试图找到一些问题,但我能找到的只是为 64 位安装 OLEDB Driver。
编辑:
我不明白为什么有人对 Panagiotis 的回答进行投票,因为它已更正,这就是我接受它的原因。他建议使用 ExcelDataReader
被证明是最有效的,因为我在应用程序中使用了更多格式的 excel,如 .xlsx
、.xlsm
和 .xlsb
,此外还有一些.csv
个文件。
这让我可以构建一个模块,这就足够了。
他还指出 .xls
很古老,但不幸的是它并没有过时,因为我公司的许多流程仍然依赖它。但它应该是 osbsolete,不幸的是,我们由于计划不周的流程而陷入困境,而不是因为 .xls
有用。尤其是那些公司应该看看某些格式不受支持的事实,或者可能会失去这种支持,因为 .xls
正在慢慢获得这种待遇。
另一项编辑: 不幸的是,我刚刚注意到,我是一个菜鸟,我不知道可以支付 nugets。不幸的是,Aspose 是那些付费扩展之一。所以我不得不更改代码并添加另一个转换器 class。 为此,我根据需要使用并修改了另一个 [thread][1] 中使用的代码。
最后编辑:
好的,在更新到 ExcelDataReader
之后,我对性能不满意,并且转换文件对我来说似乎不合适,因为我注意到@MarkPflug 已经更新 [Sylvan.Data.Excel ][2] 库,我基于它编写代码的基准给我留下了深刻的印象。有一些问题,但在联系并向 Mark 提供示例后,他很快就解决了这些问题。目前这是我能想到的最快最好的解决方案。
我将更新它以用于从选定的文件中异步提取。但基于此,任何人都可以使用它。
**FINAL CODE:**
using SylExcel = Sylvan.Data.Excel;
using SylCSV = Sylvan.Data.Csv;
using SylData = Sylvan.Data;
/// <summary>
/// get data from .csv, .xls, .xlsx, .xlsm, .xlsb. Call is then redirected accordingly
/// </summary>
/// <param name="_filePath">path to file needed</param>
/// <param name="_sheetName">sheet name to extract</param>
/// <param name="_structure">structure of needed file</param>
public void GetData(string _filePath, string? _sheetName, FilesStructures.Structure _structure)
{
//if (CheckIfOpened(_filePath))
//{
// throw new OperationCanceledException(_filePath + " is opened, please close it.");
//}
try
{
string extension = Path.GetExtension(_filePath);
switch (extension)
{
case ".csv":
SylvanReaderCSV(_filePath, _structure);
break;
default:
SylvanReader(_filePath, _sheetName, _structure);
break;
}
//collect file information
GetMetadata(_filePath);
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
/// <summary>
/// sylvan reader for .xls, .xlsx, .xlsm, .xlsb
/// </summary>
/// <param name="_filePath">path to file needed</param>
/// <param name="_sheetName">sheet name to extract</param>
/// <param name="_structure">structure of needed file</param>
/// <exception cref="Exception"></exception>
private void SylvanReader(string _filePath, string? _sheetName, FilesStructures.Structure _structure)
{
try
{
string headerSchema = "";
//get unique column list to test for duplicates
List<string> columnList = new List<string>();
//build headers
//_structure.HeaderList = List<strings> passed by object _structure
foreach (var header in _structure.HeaderList)
{
if (!columnList.Exists(column => column == header))
{
headerSchema += header + ", ";
columnList.Add(header);
}
}
//remove last 2 chars
headerSchema = headerSchema.Substring(0, headerSchema.Length - 2);
var options = new SylExcel.ExcelDataReaderOptions { Schema = SylExcel.ExcelSchema.NoHeaders, GetErrorAsNull = true };
//collect data
using (SylExcel.ExcelDataReader excelDataReader = SylExcel.ExcelDataReader.Create(_filePath, options))
{
//loop to locate sheet
while (excelDataReader.WorksheetName != _sheetName)
{
excelDataReader.NextResult();
if (excelDataReader.WorksheetName == null)
{
throw new Exception("didnt find the sheet");
}
}
//loop to find headers
for(int i = 0; i < _structure.StartRow; i++)
{
excelDataReader.Read();
}
// parse the schema, and use it to reinitialize the schema for the sheet.
var schema = SylData.Schema.Parse(headerSchema);
excelDataReader.InitializeSchema(schema.GetColumnSchema(), useHeaders: true);
DataTable = new DataTable();
DataTable.Load(excelDataReader);
}
}
catch(Exception ex)
{
throw new Exception(ex.Message);
}
}
/// <summary>
/// sylvan reader for .csv
/// </summary>
/// <param name="_filePath">path to file needed</param>
/// <param name="_sheetName">sheet name to extract</param>
/// <param name="_structure">structure of needed file</param>
/// <exception cref="Exception"></exception>
private void SylvanReaderCSV(string _filePath, FilesStructures.Structure _structure)
{
try
{
string headerSchema = "";
//get unique column list to test for duplicates
List<string> columnList = new List<string>();
//build headers
//_structure.HeaderList = List<strings> passed by object _structure
foreach (var header in _structure.HeaderList)
{
if (!columnList.Exists(column => column == header))
{
headerSchema += header + ", ";
columnList.Add(header);
}
}
//remove last 2 chars
headerSchema = headerSchema.Substring(0, headerSchema.Length - 2);
var schema = new SylCSV.CsvSchema(SylData.Schema.Parse(headerSchema));
var options = new SylCSV.CsvDataReaderOptions //check if get error as null possible
{
Schema = schema,
};
using (SylCSV.CsvDataReader csvDataReader = SylCSV.CsvDataReader.Create(_filePath, options))
{
DataTable = new DataTable();
DataTable.Load(csvDataReader);
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
[1]:
[2]: https://github.com/MarkPflug/Sylvan.Data.Excel
您可以查看我的图书馆 Sylvan.Data.Excel. It has no external dependencies, is cross plat, open-source, MIT licensed, and also the fastest Excel data reader for .NET。它通过相同的 API 同时支持 .xls、.xlsx 和 .xlsb。它不像其他一些库那样功能齐全,它只支持读取(不支持写入),但它应该是 ACE 的一个相当直接的替代品,因为它实现了 DbDataReader
。如果您 运行 进入任何 issues/questions,请随时在 GitHub 存储库中打开它们。
使用起来非常简单:
var edr = ExcelDataReader.Create("data.xls");
while(edr.Read()) {
for(int i = 0; i < edr.FieldCount; i++) {
var value = edr.GetString(i);
}
}
默认情况下,它会期望每个 sheet 的第一行包含 headers。然而,这可以被禁用。禁用时,只能按顺序访问列。
var opts = new ExcelDataReaderOptions { Schema = ExcelSchema.NoHeaders };
var edr = ExcelDataReader.Create("data.xls", opts);
由于它实现了DbDataReader
,将其加载到数据table中是一个one-liner:
var dt = new DataTable();
dt.Load(edr);
首先,不要一开始就使用 XLS。该格式在 2007 年被 xlsx
取代 - 那是 15 年前。 所有 Excel 版本使用 xlsx
,所有应用程序也是如此。不存在兼容性问题 - 事实上,导致兼容性问题的是古老的 xls
。 Google 表格不支持 xls
文件,除非您付费。 xls
坚持的唯一原因是惰性。
如果您坚持使用 xls
(为什么?)您可以使用 ExcelDataReaader. That library can read both xls
and xlsx
files and return either an DbDataReader
or a DataSet
. The NuGet package 有 17M 的下载量,使其成为继 EPPlus 之后第二受欢迎的 Excel 库。
存储库页面中的示例显示了如何在最简单的情况下使用它 - ExcelReaderFactory.CreateReader(stream)
returns a DbDataReader
:
using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read))
{
// Auto-detect format, supports:
// - Binary Excel files (2.0-2003 format; *.xls)
// - OpenXml Excel files (2007 format; *.xlsx, *.xlsb)
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
// Choose one of either 1 or 2:
// 1. Use the reader methods
do
{
while (reader.Read())
{
// reader.GetDouble(0);
}
} while (reader.NextResult());
// 2. Use the AsDataSet extension method
var result = reader.AsDataSet();
// The result of each spreadsheet is in result.Tables
}
}