如何从Excel工作表中删除字符?

时间:2012-03-30 14:57:20

标签: c# xml excel

我的整体问题是我有一个大型Excel文件(列A-S,85000行),我想将其转换为XML。单元格中的数据都是文本。

我现在使用的过程是手动将excel文件保存为csv,然后在我自己的c#程序中解析它以将其转换为XML。如果您有更好的建议,请推荐。我搜索了SO,我发现直接转换为XML的唯一 fast 方法要求我的数据都是数字的。 (逐个细胞读取细胞,需要3天才能处理)

因此,除非您能为我推荐一种不同的解决方法,否则我希望能够以编程方式从excel表中删除所有逗号,<,>,'和“。

2 个答案:

答案 0 :(得分:2)

有许多选项可供阅读/编辑/创建Excel文件:

MS提供免费的OpenXML SDK V 2.0 - 请参阅http://msdn.microsoft.com/en-us/library/bb448854%28office.14%29.aspx(仅限XLSX)

这可以读取+写入MS Office文件(包括Excel)。

另一个免费选项见http://www.codeproject.com/KB/office/OpenXML.aspx(仅限XLSX)

如果你需要更多像处理旧的Excel版本(如XLS,不仅仅是XLSX),渲染,创建PDF,公式等,那么有不同的免费和商业库,如ClosedXML(免费,仅限XLSX), EPPlus(免费,仅限XLSX),Aspose.CellsSpreadsheetGearLibXLFlexcel等。

另一个选项是Interop,它要求在本地安装Excel但Interop is not supported in sever-scenarios by MS

根据我的经验,任何基于库的直接处理Excel文件的方法都比Interop快......

答案 1 :(得分:1)

我会使用Microsoft.Office.Interop.ExcelXmlSerializer的组合来完成工作。

这是因为a)您正在使用控制台应用程序,以及b)互操作程序集很容易集成到解决方案中(只需 References-> Add )。

我假设您在运行该过程的机器中安装了Excel副本(您提到您当前手动打开工作簿,因此假设)。

代码看起来像这样:

可序列化层

public class TestClass
{
    public List<TestLineItem> LineItems { get; set; }

    public TestClass()
    {
        LineItems = new List<TestLineItem>();
    }
}

public class TestLineItem
{
    private string SanitizeText(string input)
    {
        return input.Replace(",", "")
            .Replace(".", "")
            .Replace("<", "")
            .Replace(">", "")
            .Replace("'", "")
            .Replace("\"", "");
    }

    private string m_field1;
    private string m_field2;

    public string Field1 
    {
        get { return m_field1; }
        set { m_field1 = SanitizeText(value); }
    }

    public string Field2 
    {
        get { return m_field2; }
        set { m_field2 = SanitizeText(value); }
    }

    public decimal Field3 { get; set; }

    public TestLineItem() { }

    public TestLineItem(object field1, object field2, object field3)
    {
        m_field1 = (field1 ?? "").ToString();
        m_field2 = (field2 ?? "").ToString();

        if (field3 == null || field3.ToString() == "")
            Field3 = 0m;
        else
            Field3 = Convert.ToDecimal(field3.ToString());
    }
}

然后打开工作表并加载到2D数组

// using OExcel = Microsoft.Office.Interop.Excel;
var app = new OEXcel.Application();
var wbPath = Path.Combine(
    Environment.GetFolderPath(
        Environment.SpecialFolder.MyDocuments), "Book1.xls");

var wb = app.Workbooks.Open(wbPath);
var ws = (OEXcel.Worksheet)wb.ActiveSheet;

// there are better ways to do this... 
// this one's just off the top of my head
var rngTopLine = ws.get_Range("A1", "C1");
var rngEndLine = rngTopLine.get_End(OEXcel.XlDirection.xlDown);
var rngData = ws.get_Range(rngTopLine, rngEndLine);
var arrayData = (object[,])rngData.Value2;

var tc = new TestClass();

// since you're enumerating an array, the operation will run much faster
// than reading the worksheet line by line.
for (int i = arrayData.GetLowerBound(0); i <= arrayData.GetUpperBound(0); i++)
{
    tc.LineItems.Add(
        new TestLineItem(arrayData[i, 1], arrayData[i, 2], arrayData[i, 3]));
}

var xs = new XmlSerializer(typeof(TestClass));
var fs = File.Create(Path.Combine(
    Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
    "Book1.xml"));
xs.Serialize(fs, tc);

wb.Close();
app.Quit();

生成的XML输出将类似于

<TestClass>
  <LineItems>
    <TestLineItem>
      <Field1>test1</Field1>
      <Field2>some&amp;lt;encoded&amp;gt; stuff here</Field2>
      <Field3>123456.789</Field3>
    </TestLineItem>
    <TestLineItem>
      <Field1>test2</Field1>
      <Field2>testing some commas, and periods.</Field2>
      <Field3>23456789.12</Field3>
    </TestLineItem>
    <TestLineItem>
      <Field1>test3</Field1>
      <Field2>text in &amp;quot;quotes&amp;quot; and &amp;#39;single quotes&amp;#39;</Field2>
      <Field3>0</Field3>
    </TestLineItem>
  </LineItems>
</TestClass>