如何在不安装 Microsoft Office 的情况下使用 C# 创建 Excel (.XLS 和 .XLSX) 文件?

2156

我如何在不需要安装Excel的计算机上使用C#创建Excel电子表格?


68
“不需要安装Excel”并不意味着不专业。这是关于依赖性的问题。原始问题的文本为:“理想情况下,我希望使用开源代码,这样我就不必添加任何第三方依赖项,并且我想避免直接使用Excel创建文件(使用OLE自动化)。”不幸的是,问题被大幅简化了。 - Tony
10
假设您想要做一些不使用库或外部代码的事情,我无法对 xls 文件进行说明,但对于 xlsx 文件,为什么不从一个现有的文件开始,将其重命名为 zip 文件并探索其内容呢?进行一点反向工程将会告诉您很多信息。各个文件夹和子文件夹中有几个不同的 xml 文件和 rels 文件。尝试探索一下,看看是否可以复制它,或者找到关于各种 xml 命名空间/模式的文档。 - Alexander Ryan Baggett
48个回答

16

15

我想再添加一个第三方解决方案的参考,可以直接解决您的问题:http://www.officewriter.com

(免责声明:我在SoftArtisans工作,这是OfficeWriter的制造公司)


14
public class GridViewExportUtil
{
    public static void Export(string fileName, GridView gv)
    {
        HttpContext.Current.Response.Clear();
        HttpContext.Current.Response.AddHeader(
            "content-disposition", string.Format("attachment; filename={0}", fileName));
        HttpContext.Current.Response.ContentType = "application/ms-excel";

        using (StringWriter sw = new StringWriter())
        {
            using (HtmlTextWriter htw = new HtmlTextWriter(sw))
            {
                //  Create a form to contain the grid
                Table table = new Table();

                //  add the header row to the table
                if (gv.HeaderRow != null)
                {
                    GridViewExportUtil.PrepareControlForExport(gv.HeaderRow);
                    table.Rows.Add(gv.HeaderRow);
                }

                //  add each of the data rows to the table
                foreach (GridViewRow row in gv.Rows)
                {
                    GridViewExportUtil.PrepareControlForExport(row);
                    table.Rows.Add(row);
                }

                //  add the footer row to the table
                if (gv.FooterRow != null)
                {
                    GridViewExportUtil.PrepareControlForExport(gv.FooterRow);
                    table.Rows.Add(gv.FooterRow);
                }

                //  render the table into the htmlwriter
                table.RenderControl(htw);

                //  render the htmlwriter into the response
                HttpContext.Current.Response.Write(sw.ToString());
                HttpContext.Current.Response.End();
            }
        }
    }

    /// <summary>
    /// Replace any of the contained controls with literals
    /// </summary>
    /// <param name="control"></param>
    private static void PrepareControlForExport(Control control)
    {
        for (int i = 0; i < control.Controls.Count; i++)
        {
            Control current = control.Controls[i];
            if (current is LinkButton)
            {
                control.Controls.Remove(current);
                control.Controls.AddAt(i, new LiteralControl((current as LinkButton).Text));
            }
            else if (current is ImageButton)
            {
                control.Controls.Remove(current);
                control.Controls.AddAt(i, new LiteralControl((current as ImageButton).AlternateText));
            }
            else if (current is HyperLink)
            {
                control.Controls.Remove(current);
                control.Controls.AddAt(i, new LiteralControl((current as HyperLink).Text));
            }
            else if (current is DropDownList)
            {
                control.Controls.Remove(current);
                control.Controls.AddAt(i, new LiteralControl((current as DropDownList).SelectedItem.Text));
            }
            else if (current is CheckBox)
            {
                control.Controls.Remove(current);
                control.Controls.AddAt(i, new LiteralControl((current as CheckBox).Checked ? "True" : "False"));
            }

            if (current.HasControls())
            {
                GridViewExportUtil.PrepareControlForExport(current);
            }
        }
    }
}

嗨,这个解决方案是将您的网格视图导出到Excel文件中,它可能会帮助您。


7
不,这会生成标记为 Excel 文件的 HTML,而不是真正的 Excel 文件。是的,Excel 本身可以打开它,但消费电子表格的其他程序(包括微软的免费 Excel 查看器)将无法接受它。最好使用此处的库之一创建真正的 Excel 文件。 - Rup
你应该使用System.Net.Mime.ContentDisposition来生成content-disposition头部文本,而不是字符串拼接——这样可以正确处理包含空格等特殊字符的文件名。 - Rup
GridViewExportUtil仅适用于Web。那么对于Windows Forms、WPF、Console、Service Windows、Unit Test或Addin呢? - Kiquenet

13

从C#创建Excel文件的最简单和最快的方法是使用Open XML Productivity Tool。该工具随Open XML SDK安装一起提供。该工具将任何Excel文件反向工程为C#代码。然后可以使用该C#代码重新生成该文件。

涉及的过程概述如下:

  1. 安装带有该工具的Open XML SDK。
  2. 使用最新的Excel客户端创建所需外观的Excel文件。将其命名为DesiredLook.xlsx
  3. 打开工具,打开DesiredLook.xlsx,并单击顶部附近的Reflect Code按钮。 enter image description here
  4. 您的文件的C#代码将在工具的右窗格中生成。将其添加到C#解决方案中,并使用所需的外观生成文件。

作为额外奖励,此方法适用于任何Word和PowerPoint文件。作为C#开发人员,您将更改代码以适应自己的需求。

我已经在Github上开发了一个简单的WPF应用程序,可以在Windows上运行。有一个叫做GeneratedClass的占位符类,您可以将生成的代码粘贴到其中。如果您返回文件的上一个版本,它会生成一个像这样的Excel文件:

enter image description here


1
我还没有尝试过这个Open XML SDK解决方案,但是哇,我一定会去看看的。我已经使用类似的工具工作了很多年,但不知道有这个。我已经发布了自己简单的FOSS,用于将文件转换为带有.NET的XLSX:https://github.com/TonyGravagno/NebulaXConvert - TonyG

13

一些第三方组件供应商,例如Infragistics或Syncfusion,提供非常出色的Excel导出功能,无需安装Microsoft Excel。

由于这些供应商还提供高级UI网格组件,因此如果您想要使Excel导出的样式和布局模仿应用程序用户界面中网格的当前状态,则这些组件特别方便。

如果您的导出旨在在服务器端执行,重点是要导出数据,并且与用户界面无关联,则我会选择其中一个免费的开源选项(例如ExcelLibrary)。

我之前曾参与过尝试在Microsoft Office套件上使用服务器端自动化的项目。基于这个经验,我强烈不建议采用那种方法。


13
你可以使用这个库来创建格式漂亮的Excel文件: http://officehelper.codeplex.com/documentation
请参考下面的示例:
using (ExcelHelper helper = new ExcelHelper(TEMPLATE_FILE_NAME, GENERATED_FILE_NAME))
{
    helper.Direction = ExcelHelper.DirectionType.TOP_TO_DOWN;
    helper.CurrentSheetName = "Sheet1";
    helper.CurrentPosition = new CellRef("C3");

    //the template xlsx should contains the named range "header"; use the command "insert"/"name".
    helper.InsertRange("header");

    //the template xlsx should contains the named range "sample1";
    //inside this range you should have cells with these values:
    //<name> , <value> and <comment>, which will be replaced by the values from the getSample()
    CellRangeTemplate sample1 = helper.CreateCellRangeTemplate("sample1", new List<string> {"name", "value", "comment"}); 
    helper.InsertRange(sample1, getSample());

    //you could use here other named ranges to insert new cells and call InsertRange as many times you want, 
    //it will be copied one after another;
    //even you can change direction or the current cell/sheet before you insert

    //typically you put all your "template ranges" (the names) on the same sheet and then you just delete it
    helper.DeleteSheet("Sheet3");
}        

样例看起来像这样:

private IEnumerable<List<object>> getSample()
{
    var random = new Random();

    for (int loop = 0; loop < 3000; loop++)
    {
        yield return new List<object> {"test", DateTime.Now.AddDays(random.NextDouble()*100 - 50), loop};
    }
}

12

IKVM + POI

意味着结合使用IKVM和POI,或者您可以使用Interop...。

12

以下是使用LINQ to XML的一种方法,附有示例代码:

使用LINQ to XML快速导入和导出Excel数据

这个方法有点复杂,因为你需要导入命名空间等等,但它确实可以避免任何外部依赖。

(当然,这是VB .NET而不是C#,但你可以将VB .NET的内容隔离到自己的项目中使用XML Literals,并在C#中完成其他所有操作。)


8
Java的开源解决方案是Apache POI。也许有一种方法可以在这里设置Interop,但我不了解足够的Java来回答这个问题。
当我探索这个问题时,我最终使用了Interop程序集。

7

你有没有试过Sylk?

我们以前在经典ASP中生成Sylk格式的Excel表格,现在我们正在寻找一种新的Excel生成器。

Sylk的优点是可以格式化单元格。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接