Созданный файл Excel с использованием Open XML нуждается в восстановлении при открытии в Excel - PullRequest
0 голосов
/ 13 марта 2020

Я пытаюсь вставить ячейку файла Excel (.xlsx), используя C# open XML,

, но когда я открываю созданный файл Excel, его необходимо исправить, показав следующую ошибку

Восстановленные записи: информация о ячейке из /xl/worksheets/sheet1.xml part

Вот мой код.

    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);
    }

Может кто-нибудь помочь мне решить эту проблему?

1 Ответ

0 голосов
/ 22 марта 2020

Есть несколько проблем с новой ячейкой, которую вы создаете. Во-первых, вы устанавливаете для свойства StyleIndex (атрибут ssml:s) значение 1U без WorkbookStylesPart, содержащего ссылочный стиль ячейки. Во-вторых, вы устанавливаете для свойства DataType (атрибут ssml:t) значение CellValues.SharedString (т.е. "s"), не имея SharedStringTablePart. Свойство CellValue (элемент ssml:v) должно быть нулевым индексом SharedStringItem (ssml:si элемент) в пределах SharedStringTable (ssml:sst элемент) вместо "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);
}
...