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

使用C# DocumentFormat.OpenXml删除Excel行遇问题求助

问题分析
  1. 空行无法被找到的原因:在OpenXml规范中,Excel仅会将包含内容、格式或其他属性的行存储为<Row>元素,纯粹的空行(无任何内容和格式)不会在XML结构中生成,因此sheetData.Elements<Row>()无法获取到这类空行,也无需主动删除它们——Excel会自动渲染这些空行,只要删除所有实际存在的行号大于93的<Row>元素即可。
  2. 现有代码的问题:
    • 逻辑方向有误:你的代码是删除startRow到endRow范围内的行,而非所有行号大于93的行
    • 循环删除时可能因为集合实时变更导致漏删
    • 针对末尾行删除的场景,无需调整剩余行的索引(剩余行的行号本身就≤93,不需要偏移)
解决方案代码

以下是实现需求的修正版代码,同时处理了合并单元格等关联内容,避免Excel打开时出现异常:

static void DeleteRowsAboveThreshold(string filePath, string sheetName, int thresholdRow)
{
    using (SpreadsheetDocument document = SpreadsheetDocument.Open(filePath, true))
    {
        WorkbookPart workbookPart = document.WorkbookPart;
        var sheet = workbookPart.Workbook.Descendants<Sheet>().FirstOrDefault(s => s.Name == sheetName);
        if (sheet == null)
        {
            throw new Exception("指定工作表不存在");
        }

        WorksheetPart worksheetPart = (WorksheetPart)workbookPart.GetPartById(sheet.Id);
        Worksheet worksheet = worksheetPart.Worksheet;
        SheetData sheetData = worksheet.GetFirstChild<SheetData>();

        // 1. 删除所有行号大于阈值的Row元素
        var rowsToDelete = sheetData.Elements<Row>().Where(r => r.RowIndex > thresholdRow).ToList();
        foreach (var row in rowsToDelete)
        {
            row.Remove();
        }

        // 2. 清理涉及被删除行的合并单元格
        var mergeCells = worksheet.GetFirstChild<MergeCells>();
        if (mergeCells != null)
        {
            var mergesToDelete = mergeCells.Elements<MergeCell>()
                .Where(m => GetRowIndexFromCellRef(m.Reference.Value.Split(':')[0]) > thresholdRow
                         || GetRowIndexFromCellRef(m.Reference.Value.Split(':')[1]) > thresholdRow)
                .ToList();
            foreach (var merge in mergesToDelete)
            {
                merge.Remove();
            }
            // 如果合并单元格集合为空,移除整个MergeCells元素
            if (!mergeCells.HasChildren)
            {
                mergeCells.Remove();
            }
        }

        // 3. 清理行格式中涉及被删除行的内容
        var rowFormats = worksheetPart.Worksheet.Descendants<RowFormat>().Where(rf => rf.RowIndex > thresholdRow).ToList();
        foreach (var rf in rowFormats)
        {
            rf.Remove();
        }

        worksheet.Save();
    }
}

// 辅助方法:从单元格引用中提取行号
static int GetRowIndexFromCellRef(string cellRef)
{
    return int.Parse(new string(cellRef.Where(char.IsDigit).ToArray()));
}
使用方式

调用时直接传入阈值93即可:

DeleteRowsAboveThreshold("你的Excel文件路径.xlsx", "目标工作表名称", 93);
关键说明
  • 批量删除行:先将需要删除的行存入列表再遍历删除,避免因集合实时变更导致的漏删问题
  • 关联内容清理:删除行后必须清理涉及这些行的合并单元格、行格式等,否则Excel打开时可能出现结构错误
  • 空行处理:无需额外处理纯粹的空行,因为它们并未在OpenXml中存储,删除所有行号>93的实际行后,Excel不会再渲染这些行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 19:57:28