【问题标题】:Is there any simple way to convert .xls file to .csv file? (Excel)有没有简单的方法将 .xls 文件转换为 .csv 文件? (Excel)
【发布时间】:2010-03-29 06:44:09
【问题描述】:

有什么简单的方法可以将 .xls 文件转换为 .csv 文件吗? (Excel)

在 C# 代码中?

我的意思是获取一个现有的 .xls 文件并将它们转换为 .csv 文件

提前致谢

【问题讨论】:

    标签: c# excel 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,并且我没有从这篇帖子中以任何方式获利。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2010-10-30
            • 1970-01-01
            • 1970-01-01
            • 2014-12-26
            • 2012-11-30
            • 2014-03-13
            • 1970-01-01
            相关资源
            最近更新 更多