有没有简单的方法将 .xls 文件转换为 .csv 文件? (Excel)
Posted
技术标签:
【中文标题】有没有简单的方法将 .xls 文件转换为 .csv 文件? (Excel)【英文标题】:Is there any simple way to convert .xls file to .csv file? (Excel) 【发布时间】:2010-03-29 06:44:09 【问题描述】:有什么简单的方法可以将 .xls 文件转换为 .csv 文件吗? (Excel)
在 C# 代码中?
我的意思是获取一个现有的 .xls 文件并将它们转换为 .csv 文件
提前致谢
【问题讨论】:
【参考方案1】:这是执行此操作的 C# 方法。请记住添加您自己的错误处理 - 这主要是为了简洁起见假设事情有效。它只是 4.0+ 框架,但这主要是因为可选的 worksheetNumber
参数。如果需要支持早期版本,可以重载该方法。
static void ConvertExcelToCsv(string excelFilePath, string csvOutputFile, int worksheetNumber = 1)
if (!File.Exists(excelFilePath)) throw new FileNotFoundException(excelFilePath);
if (File.Exists(csvOutputFile)) throw new ArgumentException("File exists: " + csvOutputFile);
// connection string
var cnnStr = String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=0;Extended Properties=\"Excel 8.0;IMEX=1;HDR=NO\"", excelFilePath);
var cnn = new OleDbConnection(cnnStr);
// get schema, then data
var dt = new DataTable();
try
cnn.Open();
var schemaTable = cnn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (schemaTable.Rows.Count < worksheetNumber) throw new ArgumentException("The worksheet number provided cannot be found in the spreadsheet");
string worksheet = schemaTable.Rows[worksheetNumber - 1]["table_name"].ToString().Replace("'", "");
string sql = String.Format("select * from [0]", worksheet);
var da = new OleDbDataAdapter(sql, cnn);
da.Fill(dt);
catch (Exception e)
// ???
throw e;
finally
// free resources
cnn.Close();
// write out CSV data
using (var wtr = new StreamWriter(csvOutputFile))
foreach (DataRow row in dt.Rows)
bool firstLine = true;
foreach (DataColumn col in dt.Columns)
if (!firstLine) wtr.Write(","); else firstLine = false;
var data = row[col.ColumnName].ToString().Replace("\"", "\"\"");
wtr.Write(String.Format("\"0\"", data));
wtr.WriteLine();
【讨论】:
【参考方案2】:检查 Excel 对象中的 .SaveAs()
方法。
wbWorkbook.SaveAs("c:\yourdesiredFilename.csv", Microsoft.Office.Interop.Excel.XlFileFormat.xlCSV)
或以下:
public static void SaveAs()
Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.ApplicationClass();
Microsoft.Office.Interop.Excel.Workbook wbWorkbook = app.Workbooks.Add(Type.Missing);
Microsoft.Office.Interop.Excel.Sheets wsSheet = wbWorkbook.Worksheets;
Microsoft.Office.Interop.Excel.Worksheet CurSheet = (Microsoft.Office.Interop.Excel.Worksheet)wsSheet[1];
Microsoft.Office.Interop.Excel.Range thisCell = (Microsoft.Office.Interop.Excel.Range)CurSheet.Cells[1, 1];
thisCell.Value2 = "This is a test.";
wbWorkbook.SaveAs(@"c:\one.xls", Microsoft.Office.Interop.Excel.XlFileFormat.xlWorkbookNormal, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlShared, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
wbWorkbook.SaveAs(@"c:\two.csv", Microsoft.Office.Interop.Excel.XlFileFormat.xlCSVWindows, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlShared, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
wbWorkbook.Close(false, "", true);
【讨论】:
感谢您的帮助,但如何转换现有文件? 如果您仍然想知道,您需要先使用 Excel.Application.Workbooks.Open() 方法将现有文件作为工作簿打开,并将其用作 wbWorkbook 参数 使用 xlSaveAsAccessMode.xlNoChange 更可靠(如果我使用 xlShared,对 SaveAs 的调用会崩溃)。 我发现这个答案确实有缺陷。如果有外语字符(中文等),则必须将第二个参数设置为 XlUnicodeText。这允许您保留字符,但您会丢失 CSV 格式。它将它保存为制表符分隔。末尾有一个参数可以设置代码页,但是上网一搜,似乎没有人知道如何使它工作。 无法嵌入互操作类型“ApplicationClass”?只需将“ApplicationClass”替换为“Application”即可。【参考方案3】:安装这两个包
<packages>
<package id="ExcelDataReader" version="3.3.0" targetFramework="net451" />
<package id="ExcelDataReader.DataSet" version="3.3.0" targetFramework="net451" />
</packages>
辅助函数
using ExcelDataReader;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ExcelToCsv
public class ExcelFileHelper
public static bool SaveAsCsv(string excelFilePath, string destinationCsvFilePath)
using (var stream = new FileStream(excelFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
IExcelDataReader reader = null;
if (excelFilePath.EndsWith(".xls"))
reader = ExcelReaderFactory.CreateBinaryReader(stream);
else if (excelFilePath.EndsWith(".xlsx"))
reader = ExcelReaderFactory.CreateOpenXmlReader(stream);
if (reader == null)
return false;
var ds = reader.AsDataSet(new ExcelDataSetConfiguration()
ConfigureDataTable = (tableReader) => new ExcelDataTableConfiguration()
UseHeaderRow = false
);
var csvContent = string.Empty;
int row_no = 0;
while (row_no < ds.Tables[0].Rows.Count)
var arr = new List<string>();
for (int i = 0; i < ds.Tables[0].Columns.Count; i++)
arr.Add(ds.Tables[0].Rows[row_no][i].ToString());
row_no++;
csvContent += string.Join(",", arr) + "\n";
StreamWriter csv = new StreamWriter(destinationCsvFilePath, false);
csv.Write(csvContent);
csv.Close();
return true;
用法:
var excelFilePath = Console.ReadLine();
string output = Path.ChangeExtension(excelFilePath, ".csv");
ExcelFileHelper.SaveAsCsv(excelFilePath, output);
【讨论】:
我尝试使用这个库但遇到了一个阻止程序,在这里提出:github.com/ExcelDataReader/ExcelDataReader/issues/350 ExcelDataReader 对我来说非常有用,但是,如果您要将大型 Excel 文件转换为 CSV,我建议您避免使用 AsDataSet 将整个数据集读入内存,而是逐行读取数据,然后无需在内存中存储大量数据即可管理输出。如何做到这一点的一个很好的例子位于他们的维基上github.com/ExcelDataReader/ExcelDataReader#how-to-use 非常感谢这个伟大的功能。我有一个 XLSX 格式的日期10/08/2018
出于某种原因,当我将其转换为 CSV 格式时,它也插入了一个时间 10/08/2018 12:00:00AM
我尝试通过设置 UseColumnDataType = false
来攻击它,但是产生了相同的结果跨度>
愚蠢的问题 - 如果您有不止一张纸会怎样?
我想使用 .Xls 扩展名文件,它就像一个魅力,对于多张纸我会检查和更新。这个答案会更理想,因为它不依赖于microsoft office。【参考方案4】:
我需要做同样的事情。我最终得到了类似于 Kman 的东西
static void ExcelToCSVCoversion(string sourceFile, string targetFile)
Application rawData = new Application();
try
Workbook workbook = rawData.Workbooks.Open(sourceFile);
Worksheet ws = (Worksheet) workbook.Sheets[1];
ws.SaveAs(targetFile, XlFileFormat.xlCSV);
Marshal.ReleaseComObject(ws);
finally
rawData.DisplayAlerts = false;
rawData.Quit();
Marshal.ReleaseComObject(rawData);
Console.WriteLine();
Console.WriteLine($"The excel file sourceFile has been converted into targetFile (CSV format).");
Console.WriteLine();
如果有多个工作表,这会在转换中丢失,但您可以遍历工作表的数量并将每个工作表保存为 csv。
【讨论】:
了解程序集参考会有所帮助【参考方案5】:这是对 nate_weldon 答案的修改,有一些改进:
更强大的 Excel 对象发布 在尝试保存之前设置application.DisplayAlerts = false;
以隐藏提示
还要注意application.Workbooks.Open
和ws.SaveAs
方法期望sourceFilePath
和targetFilePath
是完整路径(即目录路径+文件名)
private static void SaveAs(string sourceFilePath, string targetFilePath)
Application application = null;
Workbook wb = null;
Worksheet ws = null;
try
application = new Application();
application.DisplayAlerts = false;
wb = application.Workbooks.Open(sourceFilePath);
ws = (Worksheet)wb.Sheets[1];
ws.SaveAs(targetFilePath, XlFileFormat.xlCSV);
catch (Exception e)
// Handle exception
finally
if (application != null) application.Quit();
if (ws != null) Marshal.ReleaseComObject(ws);
if (wb != null) Marshal.ReleaseComObject(wb);
if (application != null) Marshal.ReleaseComObject(application);
【讨论】:
【参考方案6】:在更新到 Visual Studio 2022 并测试最相关的答案后,我不得不提出一个混合解决方案。
首先,我们需要安装以下Nuget包:ExcelDataReader、ExcelDataReader.DataSet和System.Text.Encoding.CodePages
然后,为了简洁的架构,继续在相应的命名空间中创建一个单独的类:
using ExcelDataReader;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace YourProjectNameSpace
public class ExcelFileHelper
/// <summary>
/// Converts a given XLS into CSV file format.
/// </summary>
public static bool SaveAsCsv(string excelFilePath, string destinationCsvFilePath)
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
using (var stream = new FileStream(excelFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
IExcelDataReader reader = null;
if (excelFilePath.EndsWith(".xls"))
reader = ExcelReaderFactory.CreateBinaryReader(stream);
else if (excelFilePath.EndsWith(".xlsx"))
reader = ExcelReaderFactory.CreateOpenXmlReader(stream);
if (reader == null)
return false;
var ds = reader.AsDataSet(new ExcelDataSetConfiguration()
ConfigureDataTable = (tableReader) => new ExcelDataTableConfiguration()
UseHeaderRow = false
);
var csvContent = string.Empty;
int row_no = 0;
while (row_no < ds.Tables[0].Rows.Count)
var arr = new List<string>();
for (int i = 0; i < ds.Tables[0].Columns.Count; i++)
arr.Add(ds.Tables[0].Rows[row_no][i].ToString());
row_no++;
csvContent += string.Join(",", arr) + "\n";
StreamWriter csv = new StreamWriter(destinationCsvFilePath, false);
csv.Write(csvContent);
csv.Close();
return true;
请注意,我必须在函数的开头包含这一行:
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
如果省略上面的行,您最终可能会收到以下错误:
NotSupportedException:没有数据可用于编码 1252
因此,请确保使用它以获得更好的兼容性。
最后,使用例子:
var execPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)?.Replace("file:\\", "");
string FileNameXLS = "\\file.xls";
string FileNameCSV = "\\file.csv";
Console.WriteLine("Exporting file to CSV...." + "\n");
ExcelFileHelper.SaveAsCsv(execPath + FileNameXLS, execPath + FileNameCSV);
Console.WriteLine("File exported to CSV!" + "\n");
【讨论】:
这非常有效!在 string.Join() 中用分号替换逗号时,这将产生与在 Excel 中使用 Save As CSV UTF-8 (Comma-delimited) 完全相同的结果。 这对我的项目非常有效,谢谢 谢谢。我能够轻松修改以使用管道作为分隔符并跳过前导行。SaveAsCsv(string excelFilePath, string destinationCsvFilePath, int startRow = 0, string delimiter = ",")
【参考方案7】:
我整合了@mattmc3 aswer。如果你想转换 xlsx 文件,你应该使用这个连接字符串(matt 提供的字符串适用于 xls 格式,而不是 xlsx):
var cnnStr = String.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=0;Extended Properties=\"Excel 12.0;IMEX=1;HDR=NO\"", excelFilePath);
【讨论】:
【参考方案8】:我遇到了类似的任务问题。将 xlsx 等入站事务转换为制表符分隔,以供现有系统自动处理。需要在无人看管的情况下运行。在查看了几个不同站点上的许多解决方案并尝试了其中两个之后,使用 MS Office Excel for C#,就像上面一样,遇到了不同版本的 MS Office 和可能在 PC 上的旧版本的问题,并且无法控制.我最终通过 NuGet 选择了...Aspose.Cells
。解决方案是四行代码。
string soureFilePath = "my/source/path/file.xlsx";
string targetFilePath = "my/output/path/file.txt";
var book = new Workbook(soureFilePath);
book.Save(targetFilePath, SaveFormat.Tsv);
它只转换工作表 1,忽略工作表 2 和 3,但这对我来说没问题。我猜它确实具有在需要时转换所有这些的功能,我只是不需要,所以没有研究它。
他们的网站,以防人们想查看他们的信息或许可协议(免费使用)。
轻松操作电子表格 | Aspose.Cells 通用库 https://products.aspose.com/cells
注意:我不为 Aspose 工作,我不隶属于 Aspose,并且我没有从这篇帖子中以任何方式获利。
【讨论】:
以上是关于有没有简单的方法将 .xls 文件转换为 .csv 文件? (Excel)的主要内容,如果未能解决你的问题,请参考以下文章
有没有一种简单的方法可以将 CSV 文件中记录的行号映射到 POCO?