【问题标题】:Reading Excel Files as a Server Process将 Excel 文件作为服务器进程读取
【发布时间】:2009-08-13 16:31:59
【问题描述】:

我正在尝试找到一种合适的方法来读取 NT 服务器操作系统上的 Excel 文件的内容。我在使用 Excel API 时遇到了很多问题,然后遇到了官方的Microsoft on Office Automation,它指出 Excel API 不适合 Excel 自动化。我看到的各种问题与文章中描述的问题相似。

是否有另一种方法可以让我在服务器(无 UI)上读取 Excel 文件(xls、xlsx、xlsm),而不会遇到与Excel API?

【问题讨论】:

  • 我试图让这个问题更合适。这是一个相当古老的版本,所以我无法提供任何示例代码/异常,但我相信对其他用户来说可能是值得的。

标签: c# excel windows-services


【解决方案1】:

有许多由不同用户突出显示的库,它们允许所需的功能。我在这里列出了它们,其中一些已经过评估,因此我在适当的时候尝试放下有趣的 cmets 来比较它们。我所包含的细节完全基于意见,但是这些库中的任何一个都可能实现所需的目标。

SpreadsheetGear.Net
(因采购成本高,未评价)

Aspose.Cells
(由一位同事评估。似乎实现起来相当简单,性能与 Excel 互操作相当)。

GemBox
(未评价)

Excel Services
(似乎只包含在 SharePoint 2007 中)

Excel Mapper (未评估,因为它需要导入不符合我要求的强类型对象)。

SmartXls
(未评估,因为它需要导入不符合我要求的强类型对象)。

ActiveXls
(相当容易使用,缺少属性会引发问题,他们偏爱方法来进行琐碎的操作。尽管声称便宜的 FlexCel 每秒执行 100 万条记录。已决定帮助/API 手册几乎没用。)

Koogra
(因未找到任何文件/信息而未评估)

FileHelpers
(未评价)

Flexcel
(找到了成本最低的解决方案,性能良好,易于实施,与 Excel 互操作结构非常接近。还收到了支持人员对技术问题的快速回复。可能是我的选择.)

SyncFusion BackOffice
(中等成本,结构合理。不幸的是,在运行单元测试时实现起来更加困难,结果不一致。还收到了一些“尝试读取受保护的内存”错误,这并不鼓励我使用纯托管库。)

【讨论】:

  • 出色的工作伊恩。您可能想要突出显示 Flexcel,因为它是您选择的选项。看起来很不错。
  • 嗨,Ian,感谢您提供的精彩列表。您知道这些库是否支持计算包含宏/VBA 函数的电子表格?我很难找到....
  • @Marc:恐怕我不知道 - 我没有深入了解高级用法。我相信 FlexCel 有一些注册自定义事件 + 代码的方法,但基本上必须在你的 C# 代码库中复制。
  • 嗨伊恩,没关系,非常感谢!这份清单真的很有帮助!我已经尝试了几乎所有方法,但似乎没有一个支持 VBA 的计算......祝你好运!
【解决方案2】:

我以前使用 ADO.NET 从 xls 中获取数据。我不确定这将支持的所有 Excel Doc 类型,但请查看 Reading and Writing Excel Spreadsheets Using ADO.NET C# DbProviderFactory

Here is some code 也来自一个 SO 问题。

我无需安装 Office 或任何第三方工具即可读写 Excel。

【讨论】:

  • ADO.NET 实际上可以很好地解决这个问题,根本不需要安装 Excel...
  • 不幸的是,ADO 不能满足我们的需要。我不确定细节,但另一个开发人员无法让它完全按照我们想要的方式工作,所以 ADO 是不行的。不过感谢您的帖子。
  • 如果您能获得更多信息,我们或许可以帮助您解决您在 ADO.NET 中遇到的问题。
  • Excel 的 OLEDB/ODBC 接口不支持 SpreadsheetML 或 OpenXML 格式,存在工作表和命名范围与某些命名约定不匹配的问题,并且如果列的前几行可能会导致截断not 包括长度大于 255 个字符的数据,后跟 do 在这些列中具有较长字符串的行。这些只是我在做这件事时记得的几个问题。现在我只导出和导入 SpreadsheetML——对用户的培训问题很小,但对应用程序稳定性有很大好处。
【解决方案3】:

要在不安装 Excel 的情况下使用 C# 读取 Excel 文件,您可以使用 Apache 的 POI。

这是一个用于读写 MS Office 格式的 java 库。由于它是 java 并且您使用的是 C#,因此您需要 IKVM 和来自 POI Project 的 java 类。

但是,最简单的方法是下载 Jon Iles excelent MPXJ project,然后你就搞定了。只需设置对IKVM.OpendJDK.ClassLibrary.dllIKVM.Runtime.dllpoi-3.2-FINAL-20081019.dll 的引用

我编写了一个快速控制台应用程序,向您展示了一种读取 Excel .xls 工作表的简单方法。它只读取第一张表,不使用行或单元格迭代器,但它做得很好。

注意:您需要查看org.apache.poi.ss 以确保您可以阅读.xlsx 等文件。

//C# code for using the Apache POI libraries
using System;
using System.Collections.Generic;
using System.Text;


// poi for xls
using org.apache.poi;
using org.apache.poi.poifs;
using org.apache.poi.poifs.filesystem;
using org.apache.poi.hssf;
using org.apache.poi.hssf.usermodel;
using org.apache.poi.ss;

namespace ConsoleApplication1
{
    class Test
    {
        static void Main(string[] args)
        {

            if (args.Length != 1)
            {
                Console.Out.WriteLine("Usage: XLSReadTest <xls file>");
            }
            else
            {
                XLSRead x = new XLSRead();
                x.Process(args[0]);
                //x.Process("c:\\temp\\testfile.xls");
            }




        }
    }


    class XLSRead
    {
        public void Process(string inputFile)
        {


            int r = 0;


            Console.Out.WriteLine("Reading input file started.");
            DateTime start = DateTime.Now;

            java.io.InputStream inputStream = new java.io.FileInputStream(inputFile);
            POIFSFileSystem fs = new POIFSFileSystem(inputStream);

            HSSFWorkbook wb = new HSSFWorkbook(fs);
            HSSFSheet sh = wb.getSheetAt(0);


            r = sh.getFirstRowNum();
            while (r <= sh.getLastRowNum())
            {
                HSSFRow row = sh.getRow(r);
                int c = row.getFirstCellNum();
                string val = "";

                while (c < row.getLastCellNum())
                {
                    HSSFCell cell = row.getCell(c);
                    switch(cell.getCellType())
                    {
                      case HSSFCell.CELL_TYPE_NUMERIC:
                          val = cell.getNumericCellValue().ToString();
                          break;
                      case HSSFCell.CELL_TYPE_STRING:
                          val = cell.getStringCellValue();
                          break;
                    }
                    Console.Out.WriteLine("Row: " + r + ", Cell: " + c + " = " + val);
                    c++;
                }
                r++;
            }

            long elapsed = DateTime.Now.Ticks - start.Ticks;
            String seconds = String.Format("{0:n}", elapsed / 1000000);
            Console.Out.WriteLine("\r\n\r\nReading input file completed in " + seconds + "s." + "\r\n");



        }
    }
}

【讨论】:

  • 马克,我将添加到读者列表中。老实说,对于我正在从事的项目,我们可能不想采用该路线,因为涉及更多的库,这会导致更多的维护等。我们需要以合理的成本实现/维护简单且免版税的东西。这些是我一直在评估可能性的一些事情,我认为这可能有点过于复杂了。
【解决方案4】:

我不确定为什么 SO 上的广告与您的问题不相关。

微软有类似的东西叫做 Excel Services。我想,这可以让你以 web 服务风格使用 Excel。我认为 SpreadSheetGear 是微软用来展示的广告。 :)

【讨论】:

    【解决方案5】:

    Excel。

    多年来试图阻止人们在服务器上使用 Excel 之后,他们已经放弃/接受了市场需求并开始支持这一点。

    2007 在这方面有一些改进,而 Excel 2010 应该有更多。

    【讨论】:

    • Scott,我们至少要支持 Excel 2003(可能是 2000)。我们需要支持的至少一个版本不能在 Vista 服务器上运行。所以根本没有帮助,如果我们可以使用 Excel,我们会的。
    【解决方案6】:

    这是可以读取 .xls 和 xlsx 文件的东西。它是开源的。 http://code.google.com/p/excelmapper/.

    它基本上是一个 ORM,所以你只需要处理对象而不是 OleDB。

    【讨论】:

    • 我实际上是在发布后发现的。还没有机会研究它,但谢谢。
    • 不幸的是,我不认为这是我想做的事情。查看 Excel 映射器,它似乎只导入到具有给定结构的对象中,因此有很多强类型字段需要填充。我的数据一开始是未知类型,然后我需要读取 Excel 并从中确定类型,所以我认为这不适合该任务。
    • Ian,ExcelMapper 下载包含一个 exe (BuildDTOsFromExcel),您可以在 excel 文件上运行它以生成强类型对象。它将根据列数据找出数据类型。正如您所提到的,这里的问题是每次更改数据类型时都必须运行它,因此在某种程度上它必须事先知道数据类型。
    • 这很公平,但是我们已经有一个通用系统来执行此操作,并且需要读取我可能应该在我的原始帖子中建议的原始数据。
    【解决方案7】:

    你试过SmartXLS for .net吗?

    ActiveXLS?

    【讨论】:

    • 不,我没有。感谢您的建议。
    【解决方案8】:

    我认为为了这个线程的利益,我必须提到 EPPlus。它是一个开源项目,可在codeplex 找到。

    我在多个项目中使用过它,从来没有遇到过问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-05
      • 2015-03-17
      相关资源
      最近更新 更多