【问题标题】:Better option for hosting MS Office documents in custom app?在自定义应用程序中托管 MS Office 文档的更好选择?
【发布时间】:2010-08-05 16:05:06
【问题描述】:

我目前在 .NET (2.0) 表单中托管一个 IE 浏览器控件,并使用它来加载 Office 文件,例如 Excel 和 Word:

_ieCtrl.Navigate("C:\\test.xls", False);

托管和加载运行良好,除非每当我导航到一个文件时,我都会看到一个对话框,询问我是要保存还是打开文件。 (这是标准的 IE 文件下载行为。)当然我总是想打开它,我不想显示对话框。

另一个问题是,当我关闭承载 IE 控件和 Office doc 的窗口时,该文档不会关闭并在磁盘上保持打开状态。这意味着后续尝试通过我的应用程序或本机办公应用程序打开同一文件将由于共享冲突而失败。

是否有一种程序化方法可以避免此对话框并在之后清理资源?我要求一个程序化的答案,因为网络研究只产生了需要修改操作系统级别设置的解决方案。

赏金注意:

我愿意接受任何解决此问题的方法,只要我能够:

  • 在我的应用程序中托管一个 Excel 电子表格
  • 工作相当透明(避免上述可用性问题)
  • 避免进行任何可能影响其他应用程序(尤其包括 IE)的特定于操作系统的更改
  • 零附加成本(请不要使用许可的 3rd 方库)代码项目和其他开源资源都可以
  • 不要乱用 DSO Framer ActiveX 控件,除非开发/发现了稳定版本

【问题讨论】:

    标签: c# .net vb.net winforms webbrowser-control


    【解决方案1】:

    您是否打算让用户能够以类似 Excel 的方式(即列、行、公式等)处理 Excel 文件,并可能将其保存回来?如果是这种情况,如果不依赖 COM Interop 与 Excel 对象模型或集成第三方库以使用 Excel 工作表,我看不出如何很好地解决这个问题。我知道您说没有付费解决方案,但有一些功能丰富的第三方控件仅用于在应用程序中处理 Excel 文件。

    我在您对SLaks 的评论中注意到最终产品是“各种仪表板”。如果您打算设计一个自定义仪表板应用程序,您是否考虑过解析 Excel 文件以提取数据,然后在您的应用程序中以逻辑方式呈现它。这消除了直接显示和使用 Excel 文件 的需要,同时仍然允许您使用该文件中的 数据。如果您试图从文件中获取数据,这里有两种方法:

    • 您可以考虑使用 Excel 对象模型和 COM 互操作将 Excel 文件中的数据读取到您的应用程序中。当然,这包括对正在安装的 Excel 的依赖,但这是可能的。 This article 有一些很棒的代码,用于开始以这种方式读取 Excel 文件。
    • 更好的方法可能是使用不依赖于本地系统上安装的 Excel 的库。 This answer 建议使用 CodePlex 上的 Excel Data Reader library

    我知道这个答案避开了您最初的“在 [a] 自定义应用程序中托管 MS Office 文档”的答案,但如果您真正感兴趣的是那些 Excel 中的 数据文件,希望这个答案会有所帮助。

    【讨论】:

    • 很棒的选项,谢谢!我会检查他们。此外,对安装 Excel 的依赖并不是真正的问题。如果我能避免它,那就太好了,如果不能,也没什么大不了的。
    • @Paul 每当我将 Excel 数据读入 .NET(这非常罕见)时,我都依赖于 Excel 互操作库。但是,即使您可以在计划部署应用程序的每台计算机上都使用 Excel,您仍然需要注意它们运行的​​ Excel 的哪个版本。我认为引用的库是完全不同的,所以如果你需要处理不同的版本,你必须弄清楚如何在运行时处理对不同文件的引用。解决这个问题可能有更简单的方法,但无论哪种方式都很难。
    • @Paul 如果我刚开始,我会先看看其他独立于 Excel 的解决方案,看看是否能让我获得所需的信息,然后看看 Excel 互操作是否有其他解决方案短。
    【解决方案2】:

    这是一个可怕的黑客攻击,只能作为最后的手段:SendKeys.Send("{O}");

    http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys%28VS.71%29.aspx

    类似于
    _ieCtrl.Navigate("C:\\test.xls", False);
    (code to sleep or wait may be needed here)
    SendKeys.Send("{O}");

    基本上,您将“o”键发送到对话框,以便它按下“打开”选项。您正在模拟键盘按下以单击“打开”按钮。这是 hackey 因为

    • 1) 您可能需要在两者之间等待 来电。如果您之前发送 o 键 对话框已启动,它将被错过。 希望对话框弹出时导航调用完成(不知道 c# 中的控制行为)。您可能需要试验时间,因为不同的计算机会打开得更快\更慢
    • 2) 如果对话框未显示在 计算机,您将插入“o” 进去。这可能会导致问题 退出,因为它可能会弹出另一个对话框来尝试保存 变化。可以通过以只读模式打开它来防止这种情况
    • 3) 不同的版本或窗口可能需要不同的 sendkeys 命令。例如,您可能需要发送“o”和“{enter}”键
    • 4) 可能更多:)

    【讨论】:

    • 您介意对此进行扩展吗?例如。更多代码,文档链接等。现在有赏金,无论是否破解,您的解决方案是迄今为止最好的选择。 ;-)
    • 也许我可以在调用 Navigate 后进入一个紧凑的循环寻找要打开的窗口,而不是睡觉?这应该比等待某个任意时间段然后盲目地将点击发送到恰好位于最顶部的任何窗口更稳定和确定?
    • 这可行!我可能会为我的程序看类似的东西:)
    • 你可以在你的循环中使用 doevents,但我认为在邪恶的规模上,sendkeys 和 doevents 并列在 11。我希望有一种方法可以避免这两个函数,但有时它是不可避免的。
    【解决方案3】:

    如果要在单独的 Excel 实例中打开文件(未嵌入到 WebBrowser 控件中),只需调用

    Process.Start(@"C:\Test.xls");
    

    【讨论】:

    • 这很好,但最终产品是一个仪表板,需要将许多不同类型的数据分组到一个表单中,因此我需要托管一个能够显示 MS Office 文档的控件. (欢迎提出允许相同类型托管的变通办法。)
    【解决方案4】:

    Office was never meant to run in embedded mode,不在网页或 ActiveX 文档宿主中。微软一次又一次地向我们发出警告。从从知识库中提取 dsoframer 到跳过 Office 2007 中的 BrowserFlags 注册表项。 尽快迁移到 Office 加载项、Excel Web Access 或 Office Web Apps。

    【讨论】:

      猜你喜欢
      • 2011-07-06
      • 2011-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多