编辑现有的Excel文件ASP.Net而不丢失格式

时间:2018-08-01 21:18:09

标签: asp.net excel vb.net closedxml

我遇到一种情况,我需要使用Excel模板并插入值,然后允许用户下载更新的文件。我已经使用ClosedXML完成了此操作,但是由于它使用xlsx的非本机格式,因此在打开下载的文档时会出现格式错误,并且文档的已保存实例会丢失模板中的所有格式。

我需要一个输出xlsx文档的解决方案,该文档是原始模板,格式以及全部内容的副本,并带有附加的插入值。如有必要,我可以在服务器上制作模板的临时副本。

有没有可以用于此目的的工具?

1 个答案:

答案 0 :(得分:0)

我最终使用了OpenXML。我正在为此项目使用VB.Net,因为我在VB中发现的示例代码很少(主要是Java或C#),所以我将其附加起来,以便可以用作参考。

关于它的真正好处是,您从其中获得的文档没有任何验证错误或任何内容,并且所有工作表格式(文本对齐方式,字体样式等)都可以保留。

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load

    Dim path = Server.MapPath("~/ExcelTemplates/rfi.xlsx")

    Dim templateBytes As Byte() = System.IO.File.ReadAllBytes(path)
    Using templateStream As MemoryStream = New MemoryStream

        templateStream.Write(templateBytes, 0, templateBytes.Length)

        Using sheetInstance As SpreadsheetDocument = SpreadsheetDocument.Open(templateStream, True)

            Dim worksheetPart As WorksheetPart = GetWorksheetPartByName(sheetInstance, "Sheet1")

            If worksheetPart IsNot Nothing Then

                'this writes "Test!!!" to cell C7
                'Dim cell As Cell = GetCell(worksheetPart.Worksheet, "C", 7)
                'cell.CellValue = New CellValue("Test!!!")

                'another way of doing it
                GetCell(worksheetPart.Worksheet, "C", 7).CellValue = New CellValue("Test12")

                'this next line would change the cell's contents data type
                'cell.DataType = New EnumValue(Of CellValues)(CellValues.String)

                worksheetPart.Worksheet.Save()
                templateStream.Position = 0

                Using ms As MemoryStream = New MemoryStream

                    templateStream.CopyTo(ms)
                    Response.Buffer = True
                    Response.Clear()
                    Response.ContentType = "application/vnd.ms-excel"
                    Response.AppendHeader("Content-Disposition", "filename=RFI.xlsx")
                    ms.WriteTo(Response.OutputStream)
                    Response.End()

                End Using

            End If


        End Using


    End Using

End Sub

Private Shared Function GetWorksheetPartByName(ByVal document As SpreadsheetDocument, ByVal sheetName As String) As WorksheetPart
    Dim sheets As IEnumerable(Of Sheet) = document.WorkbookPart.Workbook.GetFirstChild(Of Sheets)().Elements(Of Sheet)().Where(Function(s) s.Name = sheetName)

    If sheets.Count() = 0 Then
        Return Nothing
    End If

    Dim relationshipId As String = sheets.First().Id.Value
    Dim worksheetPart As WorksheetPart = CType(document.WorkbookPart.GetPartById(relationshipId), WorksheetPart)
    Return worksheetPart
End Function

Private Shared Function GetCell(ByVal worksheet As Worksheet, ByVal columnName As String, ByVal rowIndex As UInteger) As Cell
    Dim row As Row = GetRow(worksheet, rowIndex)
    If row Is Nothing Then Return Nothing
    Return row.Elements(Of Cell)().Where(Function(c) String.Compare(c.CellReference.Value, columnName & rowIndex, True) = 0).First()
End Function

Private Shared Function GetRow(ByVal worksheet As Worksheet, ByVal rowIndex As UInteger) As Row
    Return worksheet.GetFirstChild(Of SheetData)().Elements(Of Row)().Where(Function(r) CType(r.RowIndex, UInteger) = rowIndex).First()
End Function