在c#控制台应用程序中更新Excel文件后无法保存该文件
资料: 已安装MS Excel版本:Excel 2013(如果需要,可以尝试更改) 使用的参考库:Microsoft Excel 15.0对象库(1.8版) .Net Framework:4.7.2(无法更改) 应用程序类型:控制台应用程序(无法更改) 我需要的是: 所以我有一个excel工作簿,在前两页中已经有大约8000行,在其他4页中有一些图表。 我需要将此数据添加到前两张表中现有数据的底部,进行刷新、保存并关闭 这就是我所做的:在c#控制台应用程序中更新Excel文件后无法保存该文件,c#,excel,excel-2013,C#,Excel,Excel 2013,资料: 已安装MS Excel版本:Excel 2013(如果需要,可以尝试更改) 使用的参考库:Microsoft Excel 15.0对象库(1.8版) .Net Framework:4.7.2(无法更改) 应用程序类型:控制台应用程序(无法更改) 我需要的是: 所以我有一个excel工作簿,在前两页中已经有大约8000行,在其他4页中有一些图表。 我需要将此数据添加到前两张表中现有数据的底部,进行刷新、保存并关闭 这就是我所做的: using MSExcel = Microsoft
using MSExcel = Microsoft.Office.Interop.Excel;
在类构造函数中--
初始化工作簿函数---
在该类中的单独函数中,该函数在该类初始化后从Program.cs调用--
public void UpdateLoginRawDataToWorkbook(列表LSTLoginanda)
{
var dtloginda=ConvertDataListToDatatable(lstloginanda);--我将在这里获得超过1500行。
如果(dtloginda.Rows.Count>0)
{
MSExcel.Worksheet sheet=_workbook.Sheets[“SheetAlreadyHasData”]作为MSExcel.Worksheet;
MSExcel.Range lastCell=sheet.Cells.Find(
"*",
缺少。值,
缺少。值,
缺少。值,
MSExcel.XlSearchOrder.xlByRows,
MSExcel.XlSearchDirection.xlPrevious,
假,,
缺少。值,
缺失值);
int lastRow=lastCell.Row;
对于(int i=0;i _workbook.Save();好的,所以我将此作为一个答案而不是评论发布,因为我相信我们中的许多人可能会在没有意识到的情况下做同样的事情
特别感谢@PanagiotisKanavos和@MikeJ:你刚刚救了我一天。你的评论让我想到我真的再次打开了文件吗
我说“再”一次是因为发生了这样的事
所以我打开这个文件,检查它是否是只读的,然后运行我的控制台应用程序。
(请参见此处我忘记关闭桌面应用程序上的工作簿)
>P>在调试过程中,我得到了异常,因为它是打开的,所以在我看到异常的时候停止调试。
(这里的第一件事是,因为我刚刚在测试,我忘了将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
现在可以正常工作了。请详细描述您收到的异常。什么类型的异常,确切的异常消息是什么,是否存在任何内部异常?无法保存只读文件
消息非常清楚。如果您自己打开Excel并尝试编辑和保存该文件,您会收到相同的错误-事实上,这就是您所做的。您是否使用下载的文件作为模板?使用像EPPlus或NPOI这样的库来生成xlsx
文件会容易得多,而无需安装Excel。使用EPPlus填充包含数据的工作表与sheet.Cells.LoadFromCollection(事件)一样简单
。如果工作表包含命名表,您可以访问它们并附加行。源文档来自何处?是从远程网络位置下载的吗?当然,您已经手动打开了它,并确保它实际上不是只读文档?好的,所以我刚刚删除了您建议的所有内容。
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
);
}
}
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();
}
public void Close()
{
if(excel != null && _workbook != null)
{
_workbook.Close(true);
excel.Quit();
}
}