Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/codeigniter/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我的Excel数据提取是否没有有效运行?_C#_Excel_Performance_Office Interop - Fatal编程技术网

C# 我的Excel数据提取是否没有有效运行?

C# 我的Excel数据提取是否没有有效运行?,c#,excel,performance,office-interop,C#,Excel,Performance,Office Interop,我正在编写一个控制台应用程序,它将从许多xls文件中提取数据,并将它们合并到一个大型csv中。 我已经在每个文件之间完成了所有Excel应用程序加载/GC,我担心这会导致应用程序花费的时间超过需要的时间 这是我的密码: namespace SubconDataExtractToCSV { class Program { static void Main(string[] args) { StreamWriter output

我正在编写一个控制台应用程序,它将从许多xls文件中提取数据,并将它们合并到一个大型csv中。 我已经在每个文件之间完成了所有Excel应用程序加载/GC,我担心这会导致应用程序花费的时间超过需要的时间

这是我的密码:

namespace SubconDataExtractToCSV
{
    class Program
    {
        static void Main(string[] args)
        {
            StreamWriter outputCSV = new StreamWriter(@"C:\Users\mbelmer\Desktop\Helpful Files\Subcon Files\SubconEmailExtract\ExtractData\ExtractedData.csv", true);
            DirectoryInfo folder = new DirectoryInfo(@"C:\Users\mbelmer\Desktop\Helpful Files\Subcon Files\SubconEmailExtract\");
            FileInfo[] files = folder.GetFiles("*.xls");
            foreach (var file in files)
            {
                ExtractData(file, outputCSV);
            }
            outputCSV.Close();
        }

        static void ExtractData(FileInfo filename, StreamWriter output)
        {
            Excel.Application xlApp = new Excel.Application();
            Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(filename.FullName);
            Excel._Worksheet xlWorksheet = xlWorkbook.Sheets[1];
            Excel.Range xlRange = xlWorksheet.UsedRange;
            int rowCount = xlRange.Rows.Count;
            int colCount = xlRange.Columns.Count;
            string fileDate = filename.Name.Substring(0, 7);
            if (filename.Name.Contains("WIP"))
            {
                //EXTRACT MMT
                for(int i = 2; i <= rowCount; i++)
                {
                    string dataLine = fileDate + ",";
                    for(int j = 1; j <= 10; j++)
                    {
                        if (xlRange.Cells[i, j].Value2 != null)
                        {
                            dataLine += xlRange.Cells[i, j].Value2 + ",";
                        }
                        else
                        {
                            dataLine += ",";
                        }
                    }
                    output.WriteLine(dataLine);
                }

            }
            else
            {
                //EXTRACT AMKOR
                for(int i = 2; i <= rowCount; i++)
                {
                    string dataLine = fileDate + ",,,,,,,,,,,";
                    for(int j = 1; j <= colCount; j++)
                    {
                        if(xlRange.Cells[i,j].Value2 != null)
                        {
                            dataLine += xlRange.Cells[i, j].Value2 + ",";
                        }
                        else
                        {
                            dataLine += ",";
                        }
                    }
                    output.WriteLine(dataLine);
                }
            }
            GC.Collect();
            GC.WaitForPendingFinalizers();
            Marshal.ReleaseComObject(xlRange);
            Marshal.ReleaseComObject(xlWorksheet);
            xlWorkbook.Close();
            Marshal.ReleaseComObject(xlWorkbook);
            xlApp.Quit();
            Marshal.ReleaseComObject(xlApp);
        }
    }
}
dataextractocsv
{
班级计划
{
静态void Main(字符串[]参数)
{
StreamWriter outputCSV=新的StreamWriter(@“C:\Users\mbelmer\Desktop\Help Files\Subco Files\SubcommailExtract\ExtractData\ExtractedData.csv”,真);
DirectoryInfo文件夹=新的DirectoryInfo(@“C:\Users\mbelmer\Desktop\Help Files\Subco Files\SubcomailExtract\”;
FileInfo[]files=folder.GetFiles(“*.xls”);
foreach(文件中的var文件)
{
提取数据(文件、输出CSV);
}
outputCSV.Close();
}
静态void ExtractData(FileInfo文件名、StreamWriter输出)
{
Excel.Application xlApp=新的Excel.Application();
Excel.Workbook xlWorkbook=xlApp.Workbooks.Open(filename.FullName);
Excel._工作表xlWorksheet=xlWorkbook.Sheets[1];
Excel.Range xlRange=xlWorksheet.UsedRange;
int rowCount=xlRange.Rows.Count;
int colCount=xlRange.Columns.Count;
字符串fileDate=filename.Name.Substring(0,7);
if(filename.Name.Contains(“WIP”))
{
//提取蒙脱土

对于(inti=2;i,正如其他人所提到的,interop很奇怪,通常非常慢,尤其是对于大文件。但是,我知道有时您没有其他选择

我以前见过的一个可能的问题是使用“UsedRange”属性时。在循环中使用范围时速度非常慢。我在尝试删除大文件上“UsedRange”返回的“显然”空行和列时发现了这一点

当用户在Excel中设置单元格格式时…比如选择整行或整列,并为所选范围设置某种格式…然后“UsedRange”将选择此格式。您可能在“UsedRange”中看到此格式返回底部的一组空行或右侧的空列。这是因为即使单元格可能是空的…任何具有某种类型格式的单元格都将在
UsedRange
属性中拾取

正是这些“明显的”空行和空列揭示了Excel互操作的缓慢之处。您可以查看我的答案以及其他用户提供的其他帮助

在我的测试中,我试着使用与上面答案相同的策略。基本上,它是这样的

如果在循环中使用
范围
,就像代码对行所做的那样

dataLine += xlRange.Cells[i, j].Value2
和其他一些地方。这导致了一个很大的减速。由于某种原因,当你参考范围(
xlRange
)时,它的速度是出了名的慢

幸运的是,有一个不那么困难的解决方案。在我以前的删除空行和空列的解决方案中,它是通过在任何循环中不使用“范围”来解决的

不要直接使用
UsedRange
属性中的
Range
,而是将使用的Range转换为两(2)维对象数组。然后循环对象数组,而不是Excel范围。这至少应该可以大大加快速度

例如,更改获取已使用范围的行

Excel.Range xlRange = xlWorksheet.UsedRange;

然后通过
dataArray
而不是Excel范围进行循环。注意,由于
dataArray
来自Excel.Range…它不会基于零(0),这意味着第一个索引将是一(1)。您将在我的示例中看到这一点

下面是一个使用您的代码的小测试,并将其与使用如上所述的对象数组的我的代码进行速度比较。在我的测试中,使用两个Excel文件,每个文件有5列和1000行,从秒表中可以看出存在显著差异。使用您的代码大约需要51000毫秒。使用我的代码,它可以耗时约2100毫秒

代码与您的类似,但是您可以看到,在循环中,我使用了对象数组而不是Excel范围

最后,我可能弄错了,但是,我会做更多的研究来调用垃圾收集器

GC.Collect();
GC.WaitForPendingFinalizers();
我认为你打电话给GC不会有任何收获

我希望这是有意义和有帮助的

我使用了winforms应用程序,button click方法将是代码中的主要方法

private void button1_Click(object sender, EventArgs e) {
  StreamWriter outputCSV = new StreamWriter(@"D:\Test\Excel_Test\export.csv", true);
  DirectoryInfo folder = new DirectoryInfo(@"D:\Test\Excel_Test\");
  FileInfo[] files = folder.GetFiles("*.xlsx");
  int count = 1;
  Stopwatch sw = new Stopwatch();
  sw.Start();
  foreach (var file in files) {
    //ExtractData(file, outputCSV);
    ExtractData3(file, outputCSV);
    count++;
  }
  MessageBox.Show("Done! It took: " + sw.ElapsedMilliseconds + " milliseconds");
  outputCSV.Close();
}

private void ExtractData3(FileInfo filename, StreamWriter output) {
  Excel.Application xlApp = new Excel.Application();
  Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(filename.FullName);
  Excel._Worksheet xlWorksheet = xlWorkbook.Sheets[1];
  Object[,] dataArray = (Object[,])xlWorksheet.UsedRange.Cells.Value2;
  string fileDate = filename.Name.Substring(0, 7);
  if (filename.Name.Contains("WIP")) {
    //EXTRACT MMT
    fileDate = fileDate + ",";
  }
  else {
    //EXTRACT AMKOR
    fileDate = fileDate + ",,,,,,,,,,,";
  }
  WriteData(dataArray, fileDate, output);
  Marshal.ReleaseComObject(xlWorksheet);
  xlWorkbook.Close();
  Marshal.ReleaseComObject(xlWorkbook);
  xlApp.Quit();
  Marshal.ReleaseComObject(xlApp);
}

private void WriteData(Object[,] dataArray, string prefix, StreamWriter output) {
  int rowCount = dataArray.GetLength(0);
  int colCount = dataArray.GetLength(1);
  StringBuilder sb = new StringBuilder();
  sb.Append(prefix + ",");
  for (int i = 1; i <= rowCount; i++) {
    for (int j = 1; j <= colCount; j++) {
      if (dataArray[i, j] != null) {
        sb.Append(dataArray[i, j]);
        if (j < colCount) {
          sb.Append(",");
        }
      }
      else {
        sb.Append(",");
      }
    }
    output.WriteLine(sb.ToString());
    sb.Clear();
    sb.Append(prefix + ",");
  }
}
private void按钮1\u单击(对象发送者,事件参数e){
StreamWriter outputCSV=新的StreamWriter(@“D:\Test\Excel\u Test\export.csv”,true);
DirectoryInfo文件夹=新的DirectoryInfo(@“D:\Test\Excel\u Test\”);
FileInfo[]files=folder.GetFiles(“*.xlsx”);
整数计数=1;
秒表sw=新秒表();
sw.Start();
foreach(文件中的var文件){
//提取数据(文件、输出CSV);
提取数据3(文件,输出CSV);
计数++;
}
Show(“完成!耗时:”+sw.elapsedmillisons+“毫秒”);
outputCSV.Close();
}
私有void ExtractData3(FileInfo文件名,StreamWriter输出){
Excel.Application xlApp=新的Excel.Application();
Excel.Workbook xlWorkbook=xlApp.Workbooks.Open(filename.FullName);
Excel._工作表xlWorksheet=xlWorkbook.Sheets[1];
对象[,]数据数组=(对象[,])xlsheet.UsedRange.Cells.Value2;
字符串fileDate=filename.Name.Substring(0,7);
if(filename.Name.Contains(“WIP”)){
//提取蒙脱土
fileDate=fileDate+“,”;
}
否则{
//阿姆科提取物
fileDate=fileDate+“,,,,,,,,,,,,”;
}
WriteData(数据数组、文件日期、输出);
Marshal.ReleaseComObject(xlWorksheet);
xlWorkbook.Close();
Marshal.ReleaseComObject(xlWorkbook);
xlApp.Quit();
Marshal.ReleaseComObject(xlApp);
}
私有void WriteData(对象[,]数据数组,字符串前缀,StreamWriter输出)
private void button1_Click(object sender, EventArgs e) {
  StreamWriter outputCSV = new StreamWriter(@"D:\Test\Excel_Test\export.csv", true);
  DirectoryInfo folder = new DirectoryInfo(@"D:\Test\Excel_Test\");
  FileInfo[] files = folder.GetFiles("*.xlsx");
  int count = 1;
  Stopwatch sw = new Stopwatch();
  sw.Start();
  foreach (var file in files) {
    //ExtractData(file, outputCSV);
    ExtractData3(file, outputCSV);
    count++;
  }
  MessageBox.Show("Done! It took: " + sw.ElapsedMilliseconds + " milliseconds");
  outputCSV.Close();
}

private void ExtractData3(FileInfo filename, StreamWriter output) {
  Excel.Application xlApp = new Excel.Application();
  Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(filename.FullName);
  Excel._Worksheet xlWorksheet = xlWorkbook.Sheets[1];
  Object[,] dataArray = (Object[,])xlWorksheet.UsedRange.Cells.Value2;
  string fileDate = filename.Name.Substring(0, 7);
  if (filename.Name.Contains("WIP")) {
    //EXTRACT MMT
    fileDate = fileDate + ",";
  }
  else {
    //EXTRACT AMKOR
    fileDate = fileDate + ",,,,,,,,,,,";
  }
  WriteData(dataArray, fileDate, output);
  Marshal.ReleaseComObject(xlWorksheet);
  xlWorkbook.Close();
  Marshal.ReleaseComObject(xlWorkbook);
  xlApp.Quit();
  Marshal.ReleaseComObject(xlApp);
}

private void WriteData(Object[,] dataArray, string prefix, StreamWriter output) {
  int rowCount = dataArray.GetLength(0);
  int colCount = dataArray.GetLength(1);
  StringBuilder sb = new StringBuilder();
  sb.Append(prefix + ",");
  for (int i = 1; i <= rowCount; i++) {
    for (int j = 1; j <= colCount; j++) {
      if (dataArray[i, j] != null) {
        sb.Append(dataArray[i, j]);
        if (j < colCount) {
          sb.Append(",");
        }
      }
      else {
        sb.Append(",");
      }
    }
    output.WriteLine(sb.ToString());
    sb.Clear();
    sb.Append(prefix + ",");
  }
}