以下是我尝试的方法:
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组件是否有解决方法?我这里没有提出主观问题。当我使用上述三种研究工具时,我想知道技术障碍。
提前致谢
答案 0 :(得分:0)
关键是Interop你必须安装办公室。所以直截了当地说,你不能使用Interop。如果您只需要支持xlsx文件,则可以在xml中执行。
有关解压缩xlsx文件,编辑和重新打包的详细信息,请参阅this和this链接。你需要的唯一东西是解压缩它和你自己的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布局 - 最有帮助。