OpenXml 总是创建损坏的 .xlsx 文件 C#(.Net NuGet 包)

问题描述 投票:0回答:1

我遇到了 DocumentFormat.OpenXml NuGet 包的问题。虽然

CloseDocument()
函数显示数据正在进入 Excel 工作簿,但当我尝试将其加载到 Excel 中时,它会抛出有关工作表充满错误并需要删除的错误。我查看了多个有关创建 Excel 文件问题的教程和其他帖子,但没有一个能够帮助解决此问题。

创建 Excel 文件:

Excel NewExcel = new Excel(FileName);

NewExcel.CreateSheet("Test Sheet");
NewExcel.PrepareColumn(1, 80, true, 55.5);
NewExcel.CreateRow(20.2);
NewExcel.SetCell("Test 1", 1, "A");
NewExcel.SetCell(new DateTime(2010, 7, 14), 1, "B");
NewExcel.FinishSheet();
NewExcel.SaveFile();
NewExcel.CloseDocument();

错误:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<recoveryLog xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><logFileName>error133640_01.xml</logFileName><summary>Errors were detected in file 'C:\Users\Frasher Gray\Documents\NsPaintRequest-20240702.xlsx'</summary><removedRecords><removedRecord>Removed Records: Worksheet properties from /xl/workbook.xml part (Workbook)</removedRecord></removedRecords></recoveryLog>

Excel 文件创建:

    public class Excel
    {
        public string FileName { get; set; }

        private SpreadsheetDocument ExcelWorkbook;

        private WorksheetPart? CurrentWorksheet;

        private Columns ColumnsInProgress;

        private List<Row> RowsInProgress;

        public Excel(string FileName = "Default File Name")
        {
            this.FileName = FileName;
            ExcelWorkbook = SpreadsheetDocument.Create($"C://Users/Frasher Gray/Documents/{FileName}.xlsx", SpreadsheetDocumentType.Workbook);

            ExcelWorkbook.AddWorkbookPart();
            ExcelWorkbook.WorkbookPart.Workbook = new Workbook();

            ColumnsInProgress = new Columns();
            RowsInProgress = new List<Row>();
        }

        public void PrepareColumn(int FirstColumnAffected, int LastColumnAffected, bool UseCustomWidth = false, double CustomWidth = 0)
        {
            if (UseCustomWidth)
                ColumnsInProgress.Append(new Column() { Min = new UInt32Value((uint)FirstColumnAffected), Max = new UInt32Value((uint)LastColumnAffected), CustomWidth = true, Width = new DoubleValue(CustomWidth) });
            else
                ColumnsInProgress.Append(new Column() { Min = new UInt32Value((uint)FirstColumnAffected), Max = new UInt32Value((uint)LastColumnAffected) });
        }

        public void CreateRow(double? CustomHeight = null)
        {
            SheetData SheetData = CurrentWorksheet.Worksheet.GetFirstChild<SheetData>() ?? CurrentWorksheet.Worksheet.AppendChild(new SheetData());
            Row NewRow = new Row() { RowIndex = new UInt32Value((uint)SheetData.Count() + 1) };
            if (CustomHeight != null)
                NewRow.Height = CustomHeight;
            RowsInProgress.Add(NewRow);
            SheetData.Append(NewRow);
        }

        public void SetCell<T>(T CellValue, int Row, string Column)
        {
            Cell NewCell = new Cell() { CellReference = $"{Column}{Row}" };
            if (CellValue.GetType() == typeof(string))
            {
                NewCell.DataType = new EnumValue<CellValues>(CellValues.String);
                NewCell.CellValue = new CellValue(CellValue.ToString() ?? string.Empty);
            }
            else if (CellValue.GetType() == typeof(DateTime))
            {
                NewCell.DataType = new EnumValue<CellValues>(CellValues.Date);
                NewCell.CellValue = new CellValue(Convert.ToDateTime(CellValue));
            }
            else
            {
                NewCell.DataType = new EnumValue<CellValues>(CellValues.Number);
                NewCell.CellValue = new CellValue(Convert.ToDouble(CellValue));
            }

            if (RowsInProgress[Row - 1].Elements<Cell>().Count() > 0)
            {
                RowsInProgress[Row - 1].InsertAfter(NewCell, RowsInProgress[Row - 1].Elements<Cell>().Last());
            }
            else
            {
                RowsInProgress[Row - 1].AddChild(NewCell);
            }
            CurrentWorksheet.Worksheet.Save();
        }

        public void CreateSheet(string SheetName)
        {
            CurrentWorksheet = ExcelWorkbook.WorkbookPart.AddNewPart<WorksheetPart>();
            CurrentWorksheet.Worksheet = new Worksheet(new SheetData());

            Sheets Sheets = ExcelWorkbook.WorkbookPart.Workbook.GetFirstChild<Sheets>() ?? ExcelWorkbook.WorkbookPart.Workbook.AppendChild(new Sheets());
            uint SheetId = (uint)(Sheets.Elements<Sheet>().Count() + 1);
            Sheet Sheet = new Sheet() { Id = ExcelWorkbook.GetIdOfPart(ExcelWorkbook.WorkbookPart), SheetId = SheetId, Name = SheetName };
            Sheets.Append(Sheet);
        }

        public void FinishSheet()
        {
            CurrentWorksheet.Worksheet.InsertAt(ColumnsInProgress, 0);
            ColumnsInProgress = new Columns();
            RowsInProgress.Clear();
            CurrentWorksheet.Worksheet.Save();
        }

        public void SaveFile()
        {
            ExcelWorkbook.WorkbookPart.Workbook.Save();
        }

        public void CloseDocument()
        {
            foreach (Row R in ExcelWorkbook.WorkbookPart.WorksheetParts.FirstOrDefault().Worksheet.GetFirstChild<SheetData>())
            {
                foreach (Cell P in R.ChildElements)
                {
                    Console.WriteLine(P.InnerText + " " + P.CellReference);
                }
            }
            ExcelWorkbook.Dispose();
        }
    }

将我从这篇博文借用的验证代码添加到

CloseDocument()
函数中,给出了额外的错误信息:

文档有 1 个验证错误

描述:属性“http://schemas.openxmlformats.org/officeDocument/2006/relationships:id”引用的关系“R2c7e7002bf544f0d”不存在。

错误类型:语义

节点:DocumentFormat.OpenXml.Spreadsheet.Sheet

路径:/x:workbook[1]/x:sheets[1]/x:sheet[1]

部分:/xl/workbook.xml

我尝试在完成工作表后删除

ColumnsInProgress = new Columns()
调用,但这并没有改变任何东西。不幸的是,我的知识不足以真正理解该错误的含义。

c# .net-8.0 openxml-sdk
1个回答
0
投票

在尽可能多地减少函数调用以查看引用错误开始出现的位置后,我发现我完全错误地分配了工作表的 ID。应该是这样的:

Sheet Sheet = new Sheet() { Id = ExcelWorkbook.WorkbookPart.GetIdOfPart(CurrentWorksheet), SheetId = SheetId, Name = SheetName };
© www.soinside.com 2019 - 2024. All rights reserved.