从Excel中删除行

时间:2014-05-06 07:24:46

标签: c# excel openxml-sdk epplus npoi

以下是我尝试的方法:

A)我尝试使用Microsoft.Office.Interop.Excel从Excel工作表中删除行。 我在SSIS包中的脚本任务中执行此操作。

我将库添加到GAC,因为它引发了错误:Could not load Library

现在它提出了这个错误:Retrieving the COM class factory for component with CLSID {00024500-0000-0000-C000-000000000046} failed due to the following error: 80040154

谷歌搜索告诉我,我需要安装MS Office才能工作,我不想要因为我部署此解决方案的服务器绝对不会安装MS Office。我不是专家,但我想知道为什么这样的操作不可能,只需添加对dll的引用?为什么必须安装MS Office。

B)我也试过Oledb jet提供程序,但是这个不允许删除行。 它支持的唯一操作是Insert,Update和Select。

我在网上遇到过的事情:

A)SO Questions'答案建议使用Npoi,但我无法完全依赖它,因为今天的免费图书馆将来可以获得付款。

B)我也遇到了EPP Plus图书馆。我已经使用它并了解它基于GNU公共许可证,但我对使用它感到担心,因为它可能会成为未来的付费工具。

C)我也遇到过微软使用Open XML SDK的人。在我弄清楚之前,如果有人在前面告诉我是否应该使用它,我会很高兴。并不是说我懒得自己尝试一下,但是在我开始之前对我有帮助的是,这个SDK是否需要在机器上安装任何外部程序。因为它需要我安装一个msi才能使用它。

使用Microsoft COM组件是否有解决方法?我这里没有提出主观问题。当我使用上述三种研究工具时,我想知道技术障碍。

提前致谢

3 个答案:

答案 0 :(得分:0)

关键是Interop你必须安装办公室。所以直截了当地说,你不能使用Interop。如果您只需要支持xlsx文件,则可以在xml中执行。

有关解压缩xlsx文件,编辑和重新打包的详细信息,请参阅thisthis链接。你需要的唯一东西是解压缩它和你自己的xml处理代码。

如果要求也支持xls文件,则会遇到一些问题。我在过去尝试了这个,没有任何额外的安装,但没有成功,所以我决定只支持xlsx。我要么在服务器上安装了一些.msi文件或办公室。

答案 1 :(得分:0)

你说你在SSIS中使用脚本任务;那么为什么不导入要从中删除值的excel文件(最好是数据库或将其缓存到数据表中)然后生成一个新的xls文件,只包含你想要保存的数据。

或者根本不使用脚本任务,并在数据流中使用配置的excel源和脚本组件(这与脚本任务基本相同,只是你可以在数据流)并在那里完成所有工作。如果您具有与excel文件的动态连接,则始终可以使用变量(参数,如果您使用的是DataTools)来配置此类连接。

祝你好运!

答案 2 :(得分:0)

如果您想使用Microsoft.Office.Interop.Excel,是的,您确实需要在服务器上使用Excel。因此,只要您只想处理基于xlsx的工作簿/ 2007+,我就会建议OpenXML是可行的方法。这是一个学习曲线,你会发现Excel在后台为你做了多少工作,但是一旦你习惯了它就不会太糟糕。

LINQPad中的一个非常快速的样本:

void Main()
{
    string fileName = @"c:\temp\delete-row-openxml.xlsx";

    using (SpreadsheetDocument doc = SpreadsheetDocument.Open(fileName, true))
    {
        // Get the necessary bits of the doc
        WorkbookPart workbookPart = doc.WorkbookPart;
        SharedStringTablePart sstpart = workbookPart.GetPartsOfType<SharedStringTablePart>().First();
        SharedStringTable sst = sstpart.SharedStringTable;

        // Get the first worksheet
        WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
        Worksheet sheet = worksheetPart.Worksheet;

        var rows = sheet.Descendants<Row>();

        foreach (Row row in rows.Where(r => ShouldDeleteRow(r, sst)))
        {
            row.Remove();
        }
    }
}

private bool ShouldDeleteRow(Row row, SharedStringTable sst)
{
    // Whatever logic to apply to decide whether to remove a row or not
    string txt = GetCellText(row.Elements<Cell>().FirstOrDefault(), sst);
    return (txt == "Row 3");
}

// Basic way to get the text of a cell - need to use the SharedStringTable
private string GetCellText(Cell cell, SharedStringTable sst)
{
    if (cell == null)
        return "";

    if ((cell.DataType != null) && (cell.DataType == CellValues.SharedString))
    {
        int ssid = int.Parse(cell.CellValue.Text);
        string str = sst.ChildElements[ssid].InnerText;
        return str;
    }
    else if (cell.CellValue != null)
    {
        return cell.CellValue.Text;
    }
    return "";
}

请注意,这将清除该行,而不是将所有其他行混乱。为此,您需要提供一些逻辑来调整剩余行的行索引。

为了回答一些OP问题 - 除了标准的.Net框架之外,还需要OpenXML msi。该示例需要对打包API的WindowsBase.dll的引用,并使用DocumentFormat.OpenXml.Packaging和DocumentFormat.OpenXml.Spreadsheet的语句。 OpenXML API包也可以在VS中通过Nuget引用,所以如果你不想要,你甚至不需要安装msi。但这样做是有意义的恕我直言。

另一个你会发现非常有用的项目是OpenXML工具msi。这使您可以打开Word或Excel文档并查看内部的XML布局 - 最有帮助。