c# - 在 c# 控制台应用程序中更新 Excel 文件后无法保存它
问题描述
信息:
安装的 MS Excel 版本:Excel 2013(如果需要可以尝试更改)
使用的参考库:Microsoft Excel 15.0 对象库(1.8 版)
.Net 框架:4.7.2(无法更改)
应用程序类型:控制台应用程序(无法更改)
我需要的:
所以我有一个 excel 工作簿,在前 2 张工作表中已经有大约 8000 行,在另外 4 张工作表中有一些图表。我需要将此数据添加到前两张表之一中现有数据的底部,进行刷新,保存并关闭它。
这就是我正在做的事情:
using MSExcel = Microsoft.Office.Interop.Excel;
在类构造函数中——
public UsageReportFileManager(string reportFolderPath)
{
excel = new MSExcel.Application();
if (excel == null)
{
log.Error("-E-Unable to create report!!");
throw new Exception("Microsoft excel is not installed on the client machine");
}
InitializeWorkbook();
}
初始化工作簿功能---
private void InitializeWorkbook()
{
if (excel != null)
{
var filePath = GetResultPath(); //This returns a path which ends with .xlsx and it is a path to the existing file.
if (!File.Exists(filePath)) //This is just handling a situation in case the actual file is missing.
{
//Create copy from template
var templatePath = GetTemplateFilePath(); // this is not a excel template btw, its a empty workbook with formulas.
File.Copy(templatePath, filePath);
// Till here its working and new file is created if original file is missing
}
var missing = Missing.Value;
_workbook = excel.Workbooks.Open(Filename: filePath,
UpdateLinks: missing,
ReadOnly: false,
Format: missing,
Password: missing,
WriteResPassword: missing,
IgnoreReadOnlyRecommended: true,
Origin: missing,
Delimiter: missing,
Editable: true,
Notify: missing,
Converter: missing,
AddToMru: true,
Local: true
);
}
}
在此类初始化后从 Program.cs 调用的此类中的单独函数中-
public void UpdateLoginRawDataToWorkbook(List<HubAuditEvent> lstLoginData)
{
var dtLoginData = ConvertDataListToDatatable(lstLoginData); -- I will be getting more than 1500 rows here.
if (dtLoginData.Rows.Count > 0)
{
MSExcel.Worksheet sheet = _workbook.Sheets["SheetAlreadyHasData"] as MSExcel.Worksheet;
MSExcel.Range lastCell = sheet.Cells.Find(
"*",
Missing.Value,
Missing.Value,
Missing.Value,
MSExcel.XlSearchOrder.xlByRows,
MSExcel.XlSearchDirection.xlPrevious,
false,
Missing.Value,
Missing.Value);
int lastRow = lastCell.Row;
for (int i = 0; i < dtLoginData.Rows.Count; i++)
{
int row = lastRow + i + 1;
for (int j = 0; j < dtLoginData.Columns.Count; j++)
{
var col = j + 1;
sheet.Cells[row, col] = dtLoginData.Rows[i][j].ToString();
}
}
_workbook.RefreshAll();
excel.Calculate();
_workbook.Save(); <-- I get an exception here saying Cannot Save Read-Only file ..
_workbook.Close(true);
excel.Quit();
}
_workbook.Save();
我在说Cannot Save Read-Only file ..的行出现异常。
解决方案
好的,所以我将其发布为答案而不是评论,因为我相信我们中的许多人可能在没有意识到的情况下做同样的事情。
特别感谢@PanagiotisKanavos 和@MikeJ:你们拯救了我的一天。你的评论让我觉得我真的打开了“AGAIN”文件吗?
我说“再次”,因为这就是发生的事情......
所以我打开文件,检查它是否是只读的并运行我的控制台应用程序。(见这里我忘记在我的桌面应用程序上关闭工作簿)
然后在调试过程中我得到了它打开的异常,所以我在看到异常的那一刻就停止了调试。(这里是第一件事,因为我只是在测试我忘了把 excel.Quit() 放在 finally 块中——我现在意识到这非常非常非常重要。即使我在 finally 块中有它,第二个错误我正在做的是在我得到异常的那一刻停止应用程序)。
现在我有几个未关闭的打开 excel 对象实例,因为到目前为止我已经调试了几次。从那时起,无论我将 excel.Quit() 放在哪里,该实例都出于某种原因在某处打开。
然后我检查了您的评论并尝试再次手动打开并收到与只读相同的错误消息。那时一切都一清二楚。
现在我在这个 FileManager 类中创建了一个名为 Close() 的公共方法,如下所示:
public void Close() { if(excel != null && _workbook != null) { _workbook.Close(true); excel.Quit(); } }
现在我从 Program.cs 类的 finally 块中调用了这个 Close() 方法。
- 然后我不得不重新启动我的机器来释放那个锁:D。
现在它工作正常。:)
推荐阅读
- kubernetes - 根据 Drone CI 中的外部变量不同的构建步骤
- python - 由于明显的版本与 tensorflow 冲突,tensorflowjs 的 Pip 安装无法正常工作
- twilio - 在 twilio 动作 json 中指定语音
- c# - 没有连接字符串时`dbcontext.savechanges()`在哪里保存数据
- javascript - 单击背景或按 esc 时,模态不会关闭
- python - 我有每周卫星数据,但我想将其转换为每月数据。我该怎么做?
- amazon-web-services - 从 SFTP 获取文件到 S3 AWS
- python-3.x - 如何使用 mplcursors 在条形图上添加悬停注释
- visual-studio-2015 - 如何使用 SSIS Merge Join - 无法按预期工作
- sql - 展平表中可能为 NULL 或空的数组