【问题标题】:Created Excel file using OpenXML needs repair when opened in Excel使用 OpenXML 创建的 Excel 文件在 Excel 中打开时需要修复
【发布时间】:2020-03-13 06:12:10
【问题描述】:

我正在尝试使用 C# openXML 插入 Excel 文件 (.xlsx) 单元格,

但是当我打开创建的 Excel 文件时,需要通过显示以下错误来修复它,

修复的记录:来自 /xl/worksheets/sheet1.xml 部分的单元格信息

这是我的代码。

    public void InsertText(TestModelList data)
    {
        var date_time = DateTime.Now.ToString().Replace("/", "_").Replace(":", "_");
        string OutputFileDirectory = "E:\\TEST";
        string fileFullName = Path.Combine(OutputFileDirectory, "Output.xlsx");
        if (File.Exists(fileFullName))
        {
            fileFullName = Path.Combine(OutputFileDirectory, "Output_" + date_time + ".xlsx");
        }

        using (SpreadsheetDocument spreadSheet = SpreadsheetDocument.Create(fileFullName, SpreadsheetDocumentType.Workbook))
        {
            WorkbookPart wbp = spreadSheet.AddWorkbookPart();
            WorksheetPart wsp = wbp.AddNewPart<WorksheetPart>();
            Workbook wb = new Workbook();
            Worksheet ws = new Worksheet();
            SheetData sd = new SheetData();
            InsertToCell(1, "C", "1C", sd);
            ws.Append(sd);
            wsp.Worksheet = ws;
            wsp.Worksheet.Save();
            Sheets sheets = new Sheets();
            Sheet sheet = new Sheet()
            {
                Id = wbp.GetIdOfPart(wsp),
                Name  = "test",
                SheetId = 1
            };

            sheets.Append(sheet);
            wb.Append(sheets);
            spreadSheet.WorkbookPart.Workbook = wb;
            spreadSheet.WorkbookPart.Workbook.Save();
        }
    }

    private void InsertToCell(uint rowIndex, string col, string value, SheetData sd)
    {
        var row = new Row() { RowIndex = rowIndex };

        var cellReference = col + rowIndex;

        Cell newCell = new Cell
        {
            StyleIndex = (UInt32Value)1U,
            CellValue = new CellValue(value),
            DataType = CellValues.SharedString,
            CellReference = cellReference
        };
        row.InsertBefore(newCell, null);
        sd.Append(row);
    }

谁能帮我解决这个问题?

【问题讨论】:

  • 选择开修有用吗?如果是,则将该结果保存为新文件名,然后关闭。在 Open XML sDK 生产力工具中打开原始文件。对修复的文件使用比较功能。检查用于从原始代码创建该代码的代码,并将其与您的代码正在执行的操作进行比较。这至少应该缩小问题所在。
  • 您使用哪个版本的 Open XML SDK?
  • OpenXMl v2.10.1
  • @Ravihansa,好的,我问这个问题是因为 v2.10.0 存在可能导致此类错误消息的问题。现在,在更详细地查看了您的代码后,我发现了一些问题,并在下面的回答中提供了解决方案。

标签: excel cell openxml


【解决方案1】:

您正在创建的新单元存在一些问题。首先,您将StyleIndex 属性(ssml:s 属性)设置为1U 的值,而没有包含可引用单元格样式的WorkbookStylesPart。其次,您将DataType 属性(ssml:t 属性)设置为CellValues.SharedString(即"s")的值,而没有SharedStringTablePartCellValue 属性(ssml:v 元素)应该是 SharedStringTablessml:sst 元素)中 SharedStringItemssml:si 元素)的从零开始的索引,而不是 "1C"

以下是一些以工作单元测试形式的示例代码,演示了如何实现您想要实现的目标:

[Fact]
public void CanInsertCell()
{
    using var stream = new MemoryStream();
    using (var spreadsheetDocument =
        SpreadsheetDocument.Create(stream, SpreadsheetDocumentType.Workbook))
    {
        // Create an empty workbook.
        WorkbookPart workbookPart = spreadsheetDocument.AddWorkbookPart();
        workbookPart.Workbook = new Workbook(new Sheets());

        // Create an empty worksheet and add the worksheet to the workbook.
        var worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
        worksheetPart.Worksheet = new Worksheet(new SheetData());
        workbookPart.Workbook.Sheets.AppendChild(new Sheet
        {
            Id = workbookPart.GetIdOfPart(worksheetPart),
            Name = "Test",
            SheetId = 1
        });

        // This example correctly inserts a cell with an inline string,
        // noting that Excel always inserts shared strings as shown in
        // the next example.
        InsertCellWithInlineString(worksheetPart.Worksheet, 1, "C", "1C");

        // This example inserts a cell with a shared string that is
        // contained in the SharedStringTablePart. Note that the cell
        // value is the zero-based index of the SharedStringItem
        // contained in the SharedStringTable.
        var sharedStringTablePart = workbookPart.AddNewPart<SharedStringTablePart>();
        sharedStringTablePart.SharedStringTable =
            new SharedStringTable(
                new SharedStringItem(
                    new Text("2C")));

        InsertCellWithSharedString(worksheetPart.Worksheet, 2, "C", 0);
    }

    File.WriteAllBytes("WorkbookWithNewCells.xlsx", stream.ToArray());
}

private static void InsertCellWithInlineString(
    Worksheet worksheet,
    uint rowIndex,
    string columnName,
    string value)
{
    InsertCell(worksheet, rowIndex, new Cell
    {
        CellReference = columnName + rowIndex,
        DataType = CellValues.InlineString,
        InlineString = new InlineString(new Text(value)),
    });
}

private static void InsertCellWithSharedString(
    Worksheet worksheet,
    uint rowIndex,
    string columnName,
    uint value)

{
    InsertCell(worksheet, rowIndex, new Cell
    {
        CellReference = columnName + rowIndex,
        DataType = CellValues.SharedString,
        CellValue = new CellValue(value.ToString())
    });
}

private static void InsertCell(Worksheet worksheet, uint rowIndex, Cell cell)
{
    SheetData sheetData = worksheet.Elements<SheetData>().Single();

    // Get or create a Row with the given rowIndex.
    Row row = sheetData.Elements<Row>().FirstOrDefault(r => r.RowIndex == rowIndex);
    if (row == null)
    {
        row = new Row { RowIndex = rowIndex };

        // The sample assumes that the newRow can simply be appended,
        // e.g., because rows are added in ascending order only.
        sheetData.AppendChild(row);
    }

    // The sample assumes two things: First, no cell with the same cell
    // reference exists. Second, cells are added in ascending order.
    // If that is not the case, you need to deal with that situation.
    row.AppendChild(cell);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多