繁体   English   中英

C# 错误:Microsoft Excel 无法访问文件“...”。 有几个可能的原因

[英]C# Error: Microsoft Excel cannot access the file '…'. There are several possible reasons

我开发了一个 ASP.Net MVC 应用程序,它在 IIS 服务器上运行。 我编写了一个代码,它读取 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 文件的多种方式,并创建原始文件的副本并读取他。 但是在这些解决方案中的每一个中都不成功。 我在这里错过了什么?

不支持

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

微软在这里明确 state 这个

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 class 周围编写一个包装器,以便对范围的任何访问都可以在访问新范围之前释放任何先前访问的范围。

作为参考,这是我用来在 class 中释放 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

尝试这个

  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*/;

            }
        }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM