You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Microsoft OpenXML写入Excel单元格无内容问题求助

OpenXML生成XLS文件无法写入内容的问题

首次接触Microsoft OpenXML,遇到功能异常:创建xls文件后,向指定单元格写入值并保存,但代码仅能生成空文件,无法写入任何内容。以下是我的代码(已补充InsertCellInWorksheet函数):

Sub Main()
    CreateSpreadsheetWorkbook("IMPOVO.XLS")
    Dim spreadSheet As SpreadsheetDocument = SpreadsheetDocument.Open("IMPOVO.XLS", True)
    Using (spreadSheet)

        Dim worksheetPart As WorksheetPart = spreadSheet.WorkbookPart.WorksheetParts.First
        Dim cell As Cell = InsertCellInWorksheet("A", 1, worksheetPart)

        ' 设置单元格A1的值
        cell.CellValue = New CellValue("Hi World")
        cell.DataType = New EnumValue(Of CellValues)(CellValues.SharedString)

        ' 保存新工作表
        worksheetPart.Worksheet.Save()
        
    End Using
End Sub

Public Sub CreateSpreadsheetWorkbook(ByVal filepath As String)
    ' 通过路径创建电子表格文档,默认AutoSave=true、Editable=true、类型为xlsx
    Dim spreadsheetDocument As SpreadsheetDocument =
    SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook)
    
    ' 向文档添加WorkbookPart
    Dim workbookpart As WorkbookPart = spreadsheetDocument.AddWorkbookPart
    workbookpart.Workbook = New Workbook
    
    ' 向WorkbookPart添加WorksheetPart
    Dim worksheetPart As WorksheetPart = workbookpart.AddNewPart(Of WorksheetPart)()
    worksheetPart.Worksheet = New Worksheet(New SheetData())
    
    ' 向Workbook添加Sheets集合
    Dim sheets As Sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild(Of Sheets)(New Sheets())
    
    ' 添加新工作表并关联到工作簿
    Dim sheet As Sheet = New Sheet
    sheet.Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart)
    sheet.SheetId = 1
    
    sheets.Append(sheet)
    
    workbookpart.Workbook.Save()
    
    ' 关闭文档
    spreadsheetDocument.Close()
End Sub

Private Function InsertCellInWorksheet(ByVal columnName As String, ByVal rowIndex As UInteger, ByVal worksheetPart As WorksheetPart) As Cell
    Dim worksheet As Worksheet = worksheetPart.Worksheet
    Dim sheetData As SheetData = worksheet.GetFirstChild(Of SheetData)()
    Dim cellReference As String = (columnName + rowIndex.ToString())

    ' 如果工作表中没有指定索引的行,插入新行
    Dim row As Row
    If (sheetData.Elements(Of Row).Where(Function(r) r.RowIndex.Value = rowIndex).Count() <> 0) Then
        row = sheetData.Elements(Of Row).Where(Function(r) r.RowIndex.Value = rowIndex).First()
    Else
        row = New Row()
        row.RowIndex = rowIndex
        sheetData.Append(row)
    End If

    ' 如果行中没有指定列的单元格,插入新单元格
    If (row.Elements(Of Cell).Where(Function(c) c.CellReference.Value = columnName + rowIndex.ToString()).Count() > 0) Then
        Return row.Elements(Of Cell).Where(Function(c) c.CellReference.Value = cellReference).First()
    Else
        ' 单元格必须按CellReference顺序排列,确定新单元格的插入位置
        Dim refCell As Cell = Nothing
        For Each cell As Cell In row.Elements(Of Cell)()
            If (String.Compare(cell.CellReference.Value, cellReference, True) > 0) Then
                refCell = cell
                Exit For
            End If
        Next

        Dim newCell As Cell = New Cell
        newCell.CellReference = cellReference

        row.InsertBefore(newCell, refCell)
        worksheet.Save()

        Return newCell
    End If
End Function

问题根源及修复方案

1. 共享字符串类型使用错误

你设置了cell.DataType = CellValues.SharedString,但OpenXML要求使用共享字符串时,必须先创建SharedStringTablePart并将字符串添加到该表中,不能直接给CellValue赋值文本。

如果只是简单写入文本,更简单的方式是直接使用CellValues.String类型,无需维护共享字符串表:

' 直接使用String类型,无需共享字符串
cell.CellValue = New CellValue("Hi World")
cell.DataType = New EnumValue(Of CellValues)(CellValues.String)

如果一定要用共享字符串,需要在创建工作簿时添加SharedStringTablePart,并将字符串存入表中:

' 在CreateSpreadsheetWorkbook方法中添加SharedStringTablePart
Dim sharedStringPart As SharedStringTablePart = workbookpart.AddNewPart(Of SharedStringTablePart)()
sharedStringPart.SharedStringTable = New SharedStringTable()

' 在Main方法中写入共享字符串
Dim sharedStringPart As SharedStringTablePart = spreadSheet.WorkbookPart.GetPartsOfType(Of SharedStringTablePart)().First()
Dim stringItem As SharedStringItem = New SharedStringItem(New Text("Hi World"))
sharedStringPart.SharedStringTable.AppendChild(stringItem)
sharedStringPart.SharedStringTable.Save()

' 单元格值为共享字符串在表中的索引
cell.CellValue = New CellValue((sharedStringPart.SharedStringTable.Elements.Count - 1).ToString())
cell.DataType = New EnumValue(Of CellValues)(CellValues.SharedString)

2. 文件格式不匹配

你创建的是SpreadsheetDocumentType.Workbook(对应XLSX格式),但文件名使用.XLS(旧版二进制格式),这会导致Excel识别文件格式异常,建议统一使用.xlsx后缀:

CreateSpreadsheetWorkbook("IMPOVO.XLSX")
Dim spreadSheet As SpreadsheetDocument = SpreadsheetDocument.Open("IMPOVO.XLSX", True)

3. 未完整保存工作簿变更

仅保存worksheetPart.Worksheet不够,还需要保存WorkbookPart确保所有变更生效:

' 在Main方法的Using块内添加
worksheetPart.Worksheet.Save()
spreadSheet.WorkbookPart.Workbook.Save()

4. 工作表未命名(可选)

建议给Sheet添加Name属性,避免Excel打开文件时出现警告:

' 在CreateSpreadsheetWorkbook方法中
sheet.Name = "Sheet1"

修复后的完整示例(简化版)

Sub Main()
    CreateSpreadsheetWorkbook("IMPOVO.XLSX")
    Dim spreadSheet As SpreadsheetDocument = SpreadsheetDocument.Open("IMPOVO.XLSX", True)
    Using (spreadSheet)
        Dim worksheetPart As WorksheetPart = spreadSheet.WorkbookPart.WorksheetParts.First
        Dim cell As Cell = InsertCellInWorksheet("A", 1, worksheetPart)

        ' 直接写入字符串
        cell.CellValue = New CellValue("Hi World")
        cell.DataType = New EnumValue(Of CellValues)(CellValues.String)

        ' 保存工作表和工作簿
        worksheetPart.Worksheet.Save()
        spreadSheet.WorkbookPart.Workbook.Save()
    End Using
End Sub

Public Sub CreateSpreadsheetWorkbook(ByVal filepath As String)
    Dim spreadsheetDocument As SpreadsheetDocument = SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook)
    
    Dim workbookpart As WorkbookPart = spreadsheetDocument.AddWorkbookPart
    workbookpart.Workbook = New Workbook
    
    ' 添加SharedStringTablePart(如果后续要用共享字符串)
    Dim sharedStringPart As SharedStringTablePart = workbookpart.AddNewPart(Of SharedStringTablePart)()
    sharedStringPart.SharedStringTable = New SharedStringTable()
    
    Dim worksheetPart As WorksheetPart = workbookpart.AddNewPart(Of WorksheetPart)()
    worksheetPart.Worksheet = New Worksheet(New SheetData())
    
    Dim sheets As Sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild(Of Sheets)(New Sheets())
    
    Dim sheet As Sheet = New Sheet
    sheet.Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart)
    sheet.SheetId = 1
    sheet.Name = "Sheet1"
    
    sheets.Append(sheet)
    
    workbookpart.Workbook.Save()
    spreadsheetDocument.Close()
End Sub

' InsertCellInWorksheet函数保持不变
Private Function InsertCellInWorksheet(ByVal columnName As String, ByVal rowIndex As UInteger, ByVal worksheetPart As WorksheetPart) As Cell
    Dim worksheet As Worksheet = worksheetPart.Worksheet
    Dim sheetData As SheetData = worksheet.GetFirstChild(Of SheetData)()
    Dim cellReference As String = (columnName + rowIndex.ToString())

    Dim row As Row
    If (sheetData.Elements(Of Row).Where(Function(r) r.RowIndex.Value = rowIndex).Count() <> 0) Then
        row = sheetData.Elements(Of Row).Where(Function(r) r.RowIndex.Value = rowIndex).First()
    Else
        row = New Row()
        row.RowIndex = rowIndex
        sheetData.Append(row)
    End If

    If (row.Elements(Of Cell).Where(Function(c) c.CellReference.Value = columnName + rowIndex.ToString()).Count() > 0) Then
        Return row.Elements(Of Cell).Where(Function(c) c.CellReference.Value = cellReference).First()
    Else
        Dim refCell As Cell = Nothing
        For Each cell As Cell In row.Elements(Of Cell)()
            If (String.Compare(cell.CellReference.Value, cellReference, True) > 0) Then
                refCell = cell
                Exit For
            End If
        Next

        Dim newCell As Cell = New Cell
        newCell.CellReference = cellReference

        row.InsertBefore(newCell, refCell)
        worksheet.Save()

        Return newCell
    End If
End Function

内容的提问来源于stack exchange,提问作者Gabriele Cozzolino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 02:10:34