【发布时间】:2010-03-29 06:44:09
【问题描述】:
有什么简单的方法可以将 .xls 文件转换为 .csv 文件吗? (Excel)
在 C# 代码中?
我的意思是获取一个现有的 .xls 文件并将它们转换为 .csv 文件
提前致谢
【问题讨论】:
有什么简单的方法可以将 .xls 文件转换为 .csv 文件吗? (Excel)
在 C# 代码中?
我的意思是获取一个现有的 .xls 文件并将它们转换为 .csv 文件
提前致谢
【问题讨论】:
这是执行此操作的 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();
}
}
}
【讨论】:
检查 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);
}
【讨论】:
安装这两个包
<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);
【讨论】:
10/08/2018 出于某种原因,当我将其转换为 CSV 格式时,它也插入了一个时间 10/08/2018 12:00:00AM 我尝试通过设置 UseColumnDataType = false 来攻击它,但是产生了相同的结果跨度>
我需要做同样的事情。我最终得到了类似于 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。
【讨论】:
这是对 nate_weldon 答案的修改,有一些改进:
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);
}
}
【讨论】:
在更新到 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");
【讨论】:
SaveAsCsv(string excelFilePath, string destinationCsvFilePath, int startRow = 0, string delimiter = ",")
我整合了@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);
【讨论】:
我遇到了类似的任务问题。将 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,并且我没有从这篇帖子中以任何方式获利。
【讨论】: