【问题标题】:C# Error: Microsoft Excel cannot access the file '...'. There are several possible reasonsC# 错误:Microsoft Excel 无法访问文件“...”。有几个可能的原因
【发布时间】:2019-11-19 14:29:04
【问题描述】:

我开发了一个在 IIS 服务器上运行的 ASP.Net MVC 应用程序。我编写了一个读取 CSV 并将其行插入数据库的代码。

[HttpPost]
    public ActionResult InsertPosition(int id, HttpPostedFileBase position)
    {
        var posicoesExistentes = db.tbPositions.Where(s => s.id_unique == id).AsEnumerable();

        foreach (tbPosition posicao in posicoesExistentes)
        {
            db.tbPositions.Remove(posicao);
        }

        if (!Directory.Exists(Server.MapPath("~/App_Data/")))
        {
            System.IO.Directory.CreateDirectory(Server.MapPath("~/App_Data/"));
        }

        string excelPath = Server.MapPath("~/App_Data/" + position.FileName);
        if (System.IO.File.Exists(excelPath))
        {
            System.IO.File.Delete(excelPath);
        }

        position.SaveAs(excelPath);

        string tempPath = Server.MapPath("~/App_Data/" + "tmp_" + position.FileName);
        System.IO.File.Copy(excelPath, tempPath, true);

        Excel.Application application = new Excel.Application();
        Excel.Workbook workbook = application.Workbooks.Open(tempPath, ReadOnly: true,Editable:false);
        Excel.Worksheet worksheet = workbook.ActiveSheet;
        Excel.Range range = worksheet.UsedRange;
        application.Visible = true;

        for (int row = 1; row < range.Rows.Count - 1; row++)
        {
            tbPosition p = new tbPosition();

            p.position = (((Excel.Range)range.Cells[row, 1]).Text == "") ? null : Convert.ToInt32(((Excel.Range)range.Cells[row, 1]).Text);
            p.left = ((Excel.Range)range.Cells[row, 2]).Text;
            p.right = ((Excel.Range)range.Cells[row, 3]).Text;
            p.paper = ((Excel.Range)range.Cells[row, 4]).Text;
            p.denomination = ((Excel.Range)range.Cells[row, 5]).Text;
            p.material = ((Excel.Range)range.Cells[row, 6]).Text;
            p.norme = ((Excel.Range)range.Cells[row, 7]).Text;
            p.finalized_measures = ((Excel.Range)range.Cells[row, 8]).Text;
            p.observation = ((Excel.Range)range.Cells[row, 9]).Text;
            p.id_unique = id;

            db.tbPositions.Add(p);
            db.SaveChanges();
        }
        workbook.Close(true, Type.Missing, Type.Missing);
        application.Quit();
        System.IO.File.Delete(tempPath);

        return Json("Success", JsonRequestBehavior.AllowGet);
    }

但作为回报,我收到错误“Microsoft Excel 无法访问文件'...'。当我尝试打开请求的 Excel 文件时,有几个可能的原因。

我已经尝试以只读方式打开文件,我已经尝试授予指定文件夹的权限,关闭excel文件的多种方式,并创建原始文件的副本并读取他。但是在这些解决方案中的每一个中都不成功。我在这里错过了什么?

【问题讨论】:

  • 如果是 csv,为什么不使用简单的“File.ReadAllLines()”?
  • 也许这回答了你的问题stackoverflow.com/a/7386967/2972052
  • 确保您为站点和 excel 文件夹分配了 iis_iusrs 和 iusr 权限,并且您在 iis 中启用了匿名身份验证。分配权限后,还需要在iis中刷新站点。此外,请检查您的应用程序池在哪个身份下运行。

标签: c# asp.net excel asp.net-mvc-4 iis


【解决方案1】:

不支持

简短的回答是,在 UI 上下文之外不支持尝试使用自动化 API 以编程方式操作 Excel 文档。您遇到各种各样的挫折(例如,API 被允许显示对话框 - 如果它在网络服务器上运行,您将如何单击“确定”?)​​。

微软明确state this here

Microsoft 不推荐也不支持 Office 的服务器端自动化。

那我用什么?

我建议使用OpenXML SDK - 这是免费的,完全受支持,而且比自动化 API 快得多。

Aspose也有一套产品,不过不是免费的,我也没用过。

但我必须这样做

但是,如果您绝对必须使用 COM API,那么以下内容可能会对您有所帮助:

这里有龙

Excel 中自动化的最大问题是,您需要确保在使用它们时关闭每个引用(通过调用 ReleaseComObject)。

例如,以下代码将使 Excel 保持打开状态:

var range;
range = excelApplication.Range("A1");
range = excelApplication.Range("A2");
System.Runtime.InteropServices.Marshal.ReleaseComObject(range)
range = Nothing

这是因为在获取范围“A1”的调用中仍有一个引用。

因此,我建议围绕 Excel 类编写一个包装器,以便对范围的任何访问(例如,范围)在访问新范围之前释放任何先前访问的范围。

作为参考,下面是我写的类中释放COM对象的代码:

Private Sub ReleaseComObject(ByVal o As Object)
    Try
        If Not IsNothing(o) Then
            While System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0
                'Wait for COM object to be released.'
            End While
        End If
        o = Nothing
    Catch exc As System.Runtime.InteropServices.COMException
        LogError(exc) ' Suppress errors thrown here '
    End Try
End Sub

【讨论】:

    【解决方案2】:

    试试这个

      protected void ImportCSV(object sender, EventArgs e)
            {
                importbtn();
    
            }
            public class Item
            {
                public Item(string line)
                {
                    var split = line.Split(',');
                    string FIELD1 = split[0];
                    string FIELD2 = split[1];
                    string FIELD3 = split[2];
    
    
                    string mainconn = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
    
                    using (SqlConnection con = new SqlConnection(mainconn))
                    {
                        using (SqlCommand cmd = new SqlCommand("storedProcedureName", con))
                        {
                            cmd.CommandType = CommandType.StoredProcedure;
    
    
                            cmd.Parameters.AddWithValue("@FIELD1", SqlDbType.VarChar).Value = FIELD1;
                            cmd.Parameters.AddWithValue("@FIELD2", SqlDbType.VarChar).Value = FIELD2;
                            cmd.Parameters.AddWithValue("@FIELD3", SqlDbType.VarChar).Value = FIELD3;
    
                            con.Open();
                            cmd.ExecuteNonQuery();
                        }
    
    
                    }
    
                }
            }
            private void importbtn()
            {
                try
                {
    
                    string csvPath = Server.MapPath("~/Files/") + Path.GetFileName(FileUpload1.PostedFile.FileName);
                    FileUpload1.SaveAs(csvPath);
    
    
                    var listOfObjects = File.ReadLines(csvPath).Select(line => new Item(line)).ToList();
    
    
                    DataTable dt = new DataTable();
    
                    dt.Columns.AddRange(new DataColumn[3] { new DataColumn("FIELD1", typeof(string)),
                    new DataColumn("FIELD2", typeof(string)),
                    new DataColumn("FIELD3",typeof(string)) });
    
    
                    string csvData = File.ReadAllText(csvPath);
    
    
                    foreach (string row in csvData.Split('\n'))
                    {
    
                        if (!string.IsNullOrEmpty(row))
                        {
    
    
                            dt.Rows.Add();
    
                            int i = 0;
    
                            //Execute a loop over the columns.
                            foreach (string cell in row.Split(','))
                            {
    
    
                                dt.Rows[dt.Rows.Count - 1][i] = cell;
    
                                i++;
    
                            }
    
                        }
                    }
    
                    GridView1.DataSource = dt;
                    GridView1.DataBind();
    
    
                    Label1.Text = "File Attached Successfully";
    
    
    
                }
                catch (Exception ex)
                {
                    Message.Text = "Please Attach any File" /*+ ex.Message*/;
    
                }
            }
    

    【讨论】:

      猜你喜欢
      • 2019-05-01
      • 1970-01-01
      • 2013-06-14
      • 2013-05-11
      • 1970-01-01
      • 2015-07-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多