我无法使用 openxml 在 excel 中一次写入超过 40 列

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

我正在用 openxml 用 c# 编写一个程序,需要将数据逐个单元格写入 Excel 文件。然而,每当我写入超过 40 列(无论行数多少)时,先前写入同一行的数据就会被删除。 因此,如果我的文件中有 140 列,并且我尝试只写入前 40 列,它会正确执行,如果我希望它写入全部,我最终会得到前 100 列为空,最后 40 列正确填充的结果。 你能弄清楚为什么会出现这个问题吗?我附上受影响的代码部分:

for (int i = 0; i < tempName.Length; i++)
{
    if (columnsExcel[Columnindex].ToLower() == tempName[i].ToLower())
    {
        int index = InsertTextExcel.InsertSharedStringItem(tempValue[i].ToString(), ShareStringPart);

        Cell cell = InsertTextExcel.InsertCellInWorksheet(convertlettertonumber(Columnindex + 2), (uint)rowindex, theWorksheet);

        // Set cell value
        cell.CellValue = new CellValue(index.ToString());
        cell.DataType = new EnumValue<CellValues>(CellValues.SharedString);
        theWorksheet.Save();
    }
}

tempvalue 和 tempname 是字符串数组,sharestringpart 定义为:

SharedStringTablePart shareStringPart = doc.WorkbookPart.GetPartsOfType<SharedStringTablePart>().First()

我已经尝试过用逐行、逐列的方式书写,但结果是完全一样的。

c# openxml
1个回答
0
投票

由于您没有显示所有代码(即 Columnindex 和 rowIndex 来自哪里?),我不能完全确定问题是什么,但我有一种预感:行和单元格必须位于xml 中的顺序正确,否则 Excel 将忽略它们。您甚至应该在 Excel 中收到一条错误消息,指出工作簿已损坏,可以通过删除有问题的元素来修复它。

您的函数 InsertCellInWorksheet 只是在末尾附加行。如果你不按顺序调用它,这将不起作用 - 在这种情况下,必须将行插入到正确的位置。细胞也是如此。

下面的代码在正确的位置插入单元格和行。看看是否能解决您的问题。

private DocumentFormat.OpenXml.Spreadsheet.Cell InsertCell(CellAddress address, WorksheetPart OXLWorksheetPart)
{
  DocumentFormat.OpenXml.Spreadsheet.Row row = GetRowByIndex((uint)address.RowIndex, OXLWorksheetPart);

  DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell() { CellReference = address.ToString() };
  // same logic as with rows...find the correct position to insert the cell.
  DocumentFormat.OpenXml.Spreadsheet.Cell insertBeforeCell = row.Elements<DocumentFormat.OpenXml.Spreadsheet.Cell>().FirstOrDefault(c => c.CellReference.Value.Length == cell.CellReference.Value.Length && c.CellReference > cell.CellReference);

  if (insertBeforeCell != null)
  {
      row.InsertBefore(cell, insertBeforeCell);
  }
  else
  {
      row.Append(cell);
  }

  return cell;
}


private DocumentFormat.OpenXml.Spreadsheet.Row GetRowByIndex(uint rowIndex, WorksheetPart OXLWorksheetPart)
{
  SheetData sheetData = OXLWorksheetPart.Worksheet.GetFirstChild<SheetData>();

 // Check if the worksheet contains a row with the specified row index.
 DocumentFormat.OpenXml.Spreadsheet.Row row = sheetData.Elements<DocumentFormat.OpenXml.Spreadsheet.Row>().FirstOrDefault(r => r.RowIndex == rowIndex);
 if (row == null)
 {
     // the row does not exist yet. Since we have to insert the new row at the correct position, find the first row with the index > the index we want to insert
     // and then insert before that row.
     row = new DocumentFormat.OpenXml.Spreadsheet.Row() { RowIndex = rowIndex };
     DocumentFormat.OpenXml.Spreadsheet.Row insertBeforeRow = sheetData.Elements<DocumentFormat.OpenXml.Spreadsheet.Row>().FirstOrDefault(r => r.RowIndex > rowIndex);

     if (insertBeforeRow != null)
     {
         sheetData.InsertBefore(row, insertBeforeRow);
     }
     else
     {
         sheetData.Append(row);
     }
 }

  return row;
}




public class CellAddress
{
 public int ColumnIndex { get; set; }
 public string ColumnName { get; set;}
 public int RowIndex { get; set;}

 public override string ToString() => $"{ColumnName}{RowIndex}";
}
© www.soinside.com 2019 - 2024. All rights reserved.