C# Excel 强制只读,没有编辑权限

C# Excel forces ReadOnly with no Edit Priveledges

我有一个 Excel 工作簿 ("test.xlsx"),其中有一个名为 "gv_epxsize" 的单元格。我的目标是打开 excel 工作簿并在名称为 "gv_epxsize".

的单元格中写下字符串“101”

问题是我的代码一直将文件设置为只读,因此它不会将字符串“101”写入指定的单元格。我不断收到 windows 提示,提示我已经使用 Windows 权限打开文件,并询问我是否要打开只读副本。问题是我没有打开文件,在启动代码之前没有 EXCEL.EXE 进程 运行ning。

我已经做过的事情:

有人可以告诉我我做错了什么吗?

这是 C# 的片段

  string filePath = "C:\Users\ussatdafa\Desktop\Work\Projects\test.xlsx";

  Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();

        if (xlApp == null)
        {
            MessageBox.Show("Excel has not been properly installed");
        }
        else
        {
            //string fileName = Path.Combine(Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath), filePath);
            Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
            Workbooks wbs = excelApp.Workbooks;
            Workbook wb = wbs.Open(filePath, 0, false, 5, "", "", false, XlPlatform.xlWindows, "", true, false, 0, true, false, false);


            Worksheet ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.Worksheets.get_Item(1);
            wb.Names.Item("gv_epxsize").RefersToRange.Value = "101";
        }

我很确定您的问题出在保存文件的代码中。从您发布的代码中,有一件事实际上不起作用,可以解释您的问题。看看下面的片段:

else {
  //string fileName = Path.Combine(Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath), filePath);
  Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
  Workbooks wbs = excelApp.Workbooks;
  Workbook wb = wbs.Open(filePath, 0, false, 5, "", "", false, XlPlatform.xlWindows, "", true, false, 0, true, false, false);

  Worksheet ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.Worksheets.get_Item(1);
  wb.Names.Item("gv_epxsize").RefersToRange.Value = "101";
}

这是 if (xlApp == null) 语句的 else 部分。首先,在此 else 部分中,您将创建一个名为 excelApp 的新 Excel 应用程序,其中:

Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();

您为什么要这样做是未知的,因为您之前已经创建了一个名为 xlApp 的文件。但这仍然可以;您可以打开多个 Excel 应用程序。

然后打开文件并进行更改:

Workbooks wbs = excelApp.Workbooks;
Workbook wb = wbs.Open(filePath, 0, false, 5, "", "", false, XlPlatform.xlWindows, "", true, false, 0, true, false, false);
Worksheet ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.Worksheets.get_Item(1);
wb.Names.Item("gv_epxsize").RefersToRange.Value = "101";

您使用 filePath 打开工作簿并调用工作簿 wb。然后抓取 wb 中的第一个 sheet 并将其分配给工作 sheet 变量 ws。请记住,您在此 else 子句中打开了工作簿。对工作簿进行更改,然后退出 else 子句。一切似乎都正常,除了……因为我们已经退出了 else 子句……excelAppwbswbws 变量不再存在。即使您尝试在 else 子句之外保存或关闭文件,您也无法引用它,因为您在 else 子句内创建了这些变量。

因为你不能创建一个名为 wb 的新变量,如果它已经存在...那么很明显工作簿 wb 永远不会被保存或关闭。

我在您的 else 子句中添加了以下几行,并且即使使用您的程序 运行 也能够正确打开文件。很明显,您可能稍后会在代码中的某处保存和关闭该文件,但它不是您在此 else 子句中打开的文件。

else {
  Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
  Workbooks wbs = excelApp.Workbooks;
  Workbook wb = wbs.Open(filePath, 0, false, 5, "", "", false, XlPlatform.xlWindows, "", true, false, 0, true, false, false);

  Worksheet ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.Worksheets.get_Item(1);
  wb.Names.Item("gv_epxsize").RefersToRange.Value = "101";
  wb.Save();
  wb.Close();
  excelApp.Quit();
  System.Runtime.InteropServices.Marshal.ReleaseComObject(wb);
  System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp);
}

希望这是有道理的。

老实说,我不确定发生了什么,但我有两个观察结果:

  1. 您打开 Excel 两次 -- 这似乎是肯定的。一个实例是 xlApp,另一个实例是 excelApp。如果您在 excelApp 实例化时打开任务管理器,我很确定您会发现 Excel 运行 的两个实例。我不知道这是否与您的问题有关
  2. 我总是发现在调试时让 Excel 可见很有帮助。您始终可以在部署之前注释该行,但在调试期间它很好,因为在调试期间公开 COM 对象不如本机 .NET 对象有用——这样您就可以看到它的本机形式

我 运行 您的代码版本进行了这些更改,更改命名 运行ge "gv_epxsize."

的单元格值没有问题
string filePath = "C:\Users\ussatdafa\Desktop\Work\Projects\test.xlsx";
Microsoft.Office.Interop.Excel.Application excelApp =
    new Microsoft.Office.Interop.Excel.Application();

if (excelApp == null)
{
    MessageBox.Show("Excel has not been properly installed");
}
else
{
    excelApp.Visible = true;
    Workbook wb = excelApp.Workbooks.Open(filePath, 0, false, 5, "", "", false,
        XlPlatform.xlWindows, "", true, false, 0, true, false, false);
    Worksheet ws = wb.Sheets[1];

    wb.Names.Item("gv_epxsize").RefersToRange.Value = "101";
}

这对我来说完美无缺。这是证明:

所以这让我想到了几种可能性:

(Microsoft.Office.Interop.Excel.Worksheet)wb.Worksheets.get_Item(1);

不是你想的那样。或者,它可能与我使用的不一样,它是:

Worksheet ws = wb.Sheets[1];

这将 return 第一个工作表("Sheet1" 在新工作簿上)。

当然,打开两个 Excel 可能会导致问题。