有没有简单的方法将 .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.Openws.SaveAs 方法期望sourceFilePathtargetFilePath 是完整路径(即目录路径+文件名)

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包:ExcelDataReaderExcelDataReader.DataSetSystem.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?

不使用Stata软件将dta文件转换为csv

使用 Python 将 .csv 文件转换为 .dbf?

在 csv 文件的第三列中将秒数转换为年龄

有没有办法使用 KnockoutJS 将 XML 文件转换为 CSV?

将 d3.csv 方法转换为 d3.csv.parse 方法