删除工作表不起作用

时间:2017-11-22 16:45:06

标签: c# excel epplus

我试图在没有"周"的情况下删除所有工作表。或"月"包含在他们的名字中。我尝试了下面的代码:

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

     

附加信息:部分不存在。

如何正确删除?

2 个答案:

答案 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;确定):

enter image description here

答案 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 ++,那么我们每次删除一个

时都可以跳过一个