我试图在没有"周"的情况下删除所有工作表。或"月"包含在他们的名字中。我尝试了下面的代码:
var workbookFileInfo = new FileInfo(path);
using (var excelPackage = new ExcelPackage(workbookFileInfo))
{
List<string> listNames = excelPackage.Workbook.Worksheets.Where(t => !t.Name.Contains("Week") && !t.Name.Contains("Month")).Select(t =>t.Name).ToList();
foreach (string name in listNames)
{
excelPackage.Workbook.Worksheets.Delete(name);
}
excelPackage.Save();
}
但它会在for循环中导致以下错误:
类型&#39; System.InvalidOperationException&#39;的第一次机会异常。 发生在EPPlus.dll
附加信息:部分不存在。
如何正确删除?
答案 0 :(得分:0)
通常,不允许使用for-each循环从集合中删除。从集合中删除某些内容后,就没有“下一步”。
因此,你应该以不同的方式循环:
for (int i = Worksheets.Count; i > 0; i--)
{
//delete by index here
}
参见VBA中的逻辑,在C#中它完全相同 - Deleting worksheets with looping
但是,就这两个集合而言,情况并非如此(我们正在循环使用的集合和我们正在删除的集合不同)。
我没有安装XML SDK,但这对我有用:
using System;
using Excel = Microsoft.Office.Interop.Excel;
class LooperMain
{
static void Main()
{
Excel.Application excel = new Excel.Application();
excel.Visible = true;
Excel.Workbook wkb = Open(excel, @"C:\testa.xlsx");
for (int i = wkb.Worksheets.Count; i > 0; i--)
{
Excel.Worksheet sheet = wkb.Worksheets[i];
Console.WriteLine(i);
Console.WriteLine(sheet.Name);
if (sheet.Name == "something")
{
sheet.Delete();
}
}
}
public static Excel.Workbook Open(Excel.Application excelInstance,
string fileName,
bool readOnly = false,
bool editable = true,
bool updateLinks = true)
{
Excel.Workbook book = excelInstance.Workbooks.Open(
fileName, updateLinks, readOnly,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, editable, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing);
return book;
}
}
Dependancies:为了能够这样声明:
using Excel = Microsoft.Office.Interop.Excel;
您需要添加MS对象库(参考&gt;添加参考&gt; COM搜索&gt;选择&gt;确定):
答案 1 :(得分:0)
这个问题:Unable to delete a worksheet using EPPlus
答案似乎表明您可能最好将要删除的Worksheet对象传递给.Delete()而不是字符串
var sheets = excelPackage.Workbook.Worksheets.Where(t => !(t.Name.Contains("Week") || t.Name.Contains("Month"))).ToList();
foreach (var sheet in sheets)
{
excelPackage.Workbook.Worksheets.Delete(sheet);
}
excelPackage.Save();
请注意,我调整了字符串包含的逻辑,因为我不相信!t.Name.Contains("Week") || !t.Name.Contains("Month")
表示&#34;名称中没有周数或月数的表格&#34; - 如果一个工作表被调用Week 1
,那么name.contains(周)检查将返回true,否定为false,或者name.contains(月)检查将返回false,否定为true,并且工作表将是列出要删除
我相信逻辑应该是以下之一:
!name.contains(week) AND !name.contains(month)
!(name.contains(week) OR name.contains(month))
如果没有解决问题,请尝试按索引删除:
for(int i = excelPackage.Workbook.Worksheets.Length; i>=1; i--){
var name = excelPackage.Workbook.Worksheets[i].Name.ToLower();
if(name.Contains("week") || name.Contains("month")
continue;
else
excelPackage.Workbook.Worksheets.Delete(i);
}
请注意;链接表明此集合的索引是基于1而不是基于0。如果您发现它基于0,则相应地调整循环
我们以相反的顺序删除的原因是一个技巧;从集合中删除最后一项,不会破坏我们必须删除的下一项的索引,而在转发顺序中删除意味着所有剩余项的索引都会向上移一,所以如果我们只是i ++,那么我们每次删除一个
时都可以跳过一个