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


当前回答

一些第三方组件供应商,如Infregistics或Syncfusion,提供了非常好的Excel导出功能,不需要安装Microsoft Excel。

由于这些供应商还提供高级UI网格组件,如果您希望excel导出的样式和布局模拟应用程序用户界面中网格的当前状态,这些组件特别方便。

如果您的导出是在服务器端执行的,重点是要导出的数据,并且没有到UI的链接,那么我会选择一个免费的开源选项(例如ExcelLibrary)。

我以前参与过一些试图在Microsoft Office套件上使用服务器端自动化的项目。根据这一经验,我强烈建议反对这种做法。

其他回答

一个非常轻量级的选项可能是使用HTML表。只需在文件中创建head、body和table标记,然后将其另存为扩展名为.xls的文件。您可以使用Microsoft特定的属性来设置输出样式,包括公式。

我意识到,您可能没有在web应用程序中对此进行编码,但这里有一个通过HTML表组成Excel文件的示例。如果您正在编写控制台应用程序、桌面应用程序或服务,则可以使用此技术。

我最近刚刚使用了FlexCel.NET,发现它是一个优秀的库!我对太多的软件产品不这么说。在这里进行整个销售宣传没有意义,你可以阅读他们网站上的所有功能。

这是一个商业产品,但如果你购买它,你会得到完整的源代码。所以我想,如果你真的想,你可以将它编译成你的程序集。否则,它只是一个额外的程序集来xcopy-没有配置或安装或类似的东西。

我认为,如果没有第三方库,您将找不到任何方法来做到这一点,因为.NET框架显然没有内置的支持,OLE自动化只是一个痛苦的世界。

一些第三方组件供应商,如Infregistics或Syncfusion,提供了非常好的Excel导出功能,不需要安装Microsoft Excel。

由于这些供应商还提供高级UI网格组件,如果您希望excel导出的样式和布局模拟应用程序用户界面中网格的当前状态,这些组件特别方便。

如果您的导出是在服务器端执行的,重点是要导出的数据,并且没有到UI的链接,那么我会选择一个免费的开源选项(例如ExcelLibrary)。

我以前参与过一些试图在Microsoft Office套件上使用服务器端自动化的项目。根据这一经验,我强烈建议反对这种做法。

实际上,您可能想查看C#中可用的互操作类(例如Microsoft.Office.interop.Excel)。您可以说没有OLE(这不是),但互操作类非常容易使用。在这里查看C#文档(Interop for Excel从C#PDF的第1072页开始)。

如果你没有尝试过,你可能会印象深刻。

请注意Microsoft对此的立场:

Microsoft当前不建议也不支持,从任何无人值守、,非交互式客户端应用程序或组件(包括ASP,ASP.NET、DCOM和NT服务),因为Office可能表现出不稳定Office在此环境中运行时的行为和/或死锁。

您可以在Visual Studio上安装OpenXml nuget包。以下是将数据表导出到excel文件的代码:

Imports DocumentFormat.OpenXml
Imports DocumentFormat.OpenXml.Packaging
Imports DocumentFormat.OpenXml.Spreadsheet

Public Class ExportExcelClass
    Public Sub New()

    End Sub

    Public Sub ExportDataTable(ByVal table As DataTable, ByVal exportFile As String)
        ' Create a spreadsheet document by supplying the filepath.
        ' By default, AutoSave = true, Editable = true, and Type = xlsx.
        Dim spreadsheetDocument As SpreadsheetDocument = spreadsheetDocument.Create(exportFile, SpreadsheetDocumentType.Workbook)

        ' Add a WorkbookPart to the document.
        Dim workbook As WorkbookPart = spreadsheetDocument.AddWorkbookPart
        workbook.Workbook = New Workbook

        ' Add a WorksheetPart to the WorkbookPart.
        Dim Worksheet As WorksheetPart = workbook.AddNewPart(Of WorksheetPart)()
        Worksheet.Worksheet = New Worksheet(New SheetData())

        ' Add Sheets to the Workbook.
        Dim sheets As Sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild(Of Sheets)(New Sheets())

        Dim data As SheetData = Worksheet.Worksheet.GetFirstChild(Of SheetData)()
        Dim Header As Row = New Row()
        Header.RowIndex = CType(1, UInt32)

        For Each column As DataColumn In table.Columns
            Dim headerCell As Cell = createTextCell(table.Columns.IndexOf(column) + 1, 1, column.ColumnName)
            Header.AppendChild(headerCell)
        Next

        data.AppendChild(Header)

        Dim contentRow As DataRow
        For i As Integer = 0 To table.Rows.Count - 1
            contentRow = table.Rows(i)
            data.AppendChild(createContentRow(contentRow, i + 2))
        Next

    End Sub

    Private Function createTextCell(ByVal columnIndex As Integer, ByVal rowIndex As Integer, ByVal cellValue As Object) As Cell
        Dim cell As Cell = New Cell()
        cell.DataType = CellValues.InlineString

        cell.CellReference = getColumnName(columnIndex) + rowIndex.ToString

        Dim inlineString As InlineString = New InlineString()
        Dim t As Text = New Text()
        t.Text = cellValue.ToString()
        inlineString.AppendChild(t)
        cell.AppendChild(inlineString)
        Return cell
    End Function

    Private Function createContentRow(ByVal dataRow As DataRow, ByVal rowIndex As Integer) As Row
        Dim row As Row = New Row With {
            .rowIndex = CType(rowIndex, UInt32)
        }

        For i As Integer = 0 To dataRow.Table.Columns.Count - 1
            Dim dataCell As Cell = createTextCell(i + 1, rowIndex, dataRow(i))
            row.AppendChild(dataCell)
        Next

        Return row
    End Function

    Private Function getColumnName(ByVal columnIndex As Integer) As String
        Dim dividend As Integer = columnIndex
        Dim columnName As String = String.Empty
        Dim modifier As Integer

        While dividend > 0
            modifier = (dividend - 1) Mod 26
            columnName = Convert.ToChar(65 + modifier).ToString() & columnName
            dividend = CInt(((dividend - modifier) / 26))
        End While

        Return columnName
    End Function
End Class