【发布时间】:2022-01-22 19:25:41
【问题描述】:
原始查询: 目前我想从 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]";
为 OLE 安装 64 位驱动程序是不可能的。所以也许有人偶然发现了它,或者有任何想法。
我想将数据构建到数据表中,其标题类似于HDR=YES,并且可以像上面的示例一样将其关闭。
另外,由于 excel 格式,dapper 是不可能的:(
我试图找到一些问题,但我能找到的只是安装 64 位的 OLEDB 驱动程序。
编辑:
我不明白为什么有人会放弃 Panagiotis 的答案,因为它已得到纠正,这就是我接受它的原因。他建议使用ExcelDataReader 被证明是最有效的,因为我在应用程序中使用更多格式的excel,如.xlsx、.xlsm 和.xlsb,另外还有一些.csv 文件。
这让我可以构建一个模块,这就足够了。
他指出.xls 是古老的,但不幸的是它并没有过时,因为我公司的许多流程仍然依赖它,这也是正确的。但它应该是过时的,不幸的是,由于流程计划不周,我们被卡住了,而不是因为.xls 很有用。尤其是那些公司应该注意不支持某些格式的事实,或者可能会失去这种支持,因为.xls 正在慢慢得到这种处理。
另一个编辑: 不幸的是,我刚刚注意到,我是菜鸟,我不知道可以支付 nugets。 Aspose,不幸的是,它是那些付费扩展之一。所以我不得不更改代码并添加另一个转换器类。 为此,我根据需要使用并修改了另一个 [thread ][1] 中使用的代码。
最后编辑:
好的,在更新到 ExcelDataReader 后,我对性能不满意,并且转换文件对我来说似乎不合适,因为我注意到 @MarkPflug 已更新 [Sylvan.Data.Excel][2]库,并且对基准印象深刻,我基于它编写了代码。有一些探险,但在联系并给马克提供了样本后,他很快就解决了这些问题。目前这是我能想到的最快最好的解决方案。
我将更新它以用于从选定的文件数量中异步提取。但基于此,任何人都可以使用它。
**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]: https://stackoverflow.com/questions/28398071/reading-excel-xlsb-files-in-c-sharp
[2]: https://github.com/MarkPflug/Sylvan.Data.Excel
【问题讨论】:
-
不要以 XLS 开头。该格式在 2007 年被
xlsx取代 - 那是 15 年前。 所有 Excel 版本使用xlsx,所有应用程序也是如此。不存在兼容性问题 - 事实上,导致兼容性问题的是古老的xls。例如,除非您付费,否则 Google 表格不支持xls文件 -
“为 OLE 安装 64 位驱动程序是不可能的”为什么?在提出替代解决方案之前了解约束条件会有所帮助。
-
嘿,我都不能停止使用 xls 并安装 64 位驱动程序,这是因为我正在使用现有的基础架构,这超出了我的控制范围,如果由我决定,我们会首先不要使用 xls。