You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用OpenXML SDK实现Excel导出数据后合并指定行的技术问询

使用OpenXML SDK导出Excel后合并最后一行下方的10行单元格

我来帮你搞定这个合并单元格的需求!首先咱们理清楚流程:你已经通过模板复制生成了新的Excel文件,接下来要做的就是定位到数据的最后一行,然后把它下面的10行单元格合并起来。以下是完整的实现方案:

核心思路

  • 打开生成的Excel文档,定位到目标工作表
  • 确定数据区域的最后一行行号
  • 计算要合并的行范围:从最后一行+1最后一行+10
  • 为每一行添加单元格合并规则(如果需要合并整行所有列,需先获取工作表的最后一列)

完整代码实现

string templatePath = Server.MapPath("~/Content/Reports/Formate/someReport.xlsx");
string download_file_name = "Some__Report_" + Guid.NewGuid().ToString() + ".xlsx";
string newFilePath = Server.MapPath("~/Content/Reports/TempData/" + download_file_name);
System.IO.File.Copy(templatePath, newFilePath, true);

// 打开Excel文档,using语句会自动处理资源释放
using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(newFilePath, true))
{
    // 获取工作簿和目标工作表(这里默认取第一个工作表,可根据实际修改)
    WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
    WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
    Worksheet worksheet = worksheetPart.Worksheet;

    // 1. 找到数据区域的最后一行行号
    SheetData sheetData = worksheet.GetFirstChild<SheetData>();
    uint lastDataRowNumber = sheetData.Elements<Row>().Max(row => row.RowIndex.Value);

    // 2. 定义要合并的行范围:从最后一行下一行开始,共10行
    uint startMergeRow = lastDataRowNumber + 1;
    uint endMergeRow = lastDataRowNumber + 10;

    // 3. 获取工作表的最后一列(如果需要合并整行所有列)
    uint lastColumnNumber = GetLastColumnNumber(sheetData);
    string startColumn = GetColumnName(1); // 从A列开始
    string endColumn = GetColumnName(lastColumnNumber); // 到最后一列结束

    // 4. 处理MergeCells元素,不存在则创建
    MergeCells mergeCells = worksheet.GetFirstChild<MergeCells>();
    if (mergeCells == null)
    {
        mergeCells = new MergeCells();
        worksheet.Append(mergeCells);
    }

    // 5. 为每一行添加合并规则
    for (uint row = startMergeRow; row <= endMergeRow; row++)
    {
        string mergeRange = $"{startColumn}{row}:{endColumn}{row}";
        mergeCells.Append(new MergeCell() { Reference = mergeRange });
    }

    // 保存工作表更改
    worksheet.Save();
}

辅助方法(列号与列名转换)

// 将数字列号转换为Excel列名(比如1→A,26→Z,27→AA)
private string GetColumnName(uint columnNumber)
{
    string columnName = "";
    while (columnNumber > 0)
    {
        uint modulo = (columnNumber - 1) % 26;
        columnName = Convert.ToChar('A' + modulo) + columnName;
        columnNumber = (columnNumber - modulo) / 26;
    }
    return columnName;
}

// 获取SheetData中的最后一列号
private uint GetLastColumnNumber(SheetData sheetData)
{
    uint maxColumn = 0;
    foreach (Row row in sheetData.Elements<Row>())
    {
        if (row.Elements<Cell>().Any())
        {
            uint currentMaxColumn = row.Elements<Cell>().Max(cell => GetColumnNumber(cell.CellReference));
            if (currentMaxColumn > maxColumn)
            {
                maxColumn = currentMaxColumn;
            }
        }
    }
    return maxColumn;
}

// 从单元格引用中提取列号(比如A1→1,B2→2)
private uint GetColumnNumber(string cellReference)
{
    string columnName = new string(cellReference.TakeWhile(c => char.IsLetter(c)).ToArray());
    uint columnNumber = 0;
    foreach (char c in columnName)
    {
        columnNumber = columnNumber * 26 + (uint)(c - 'A' + 1);
    }
    return columnNumber;
}

注意事项

  • 如果只需要合并特定列(比如A到D列),直接把startColumnendColumn改成固定值即可,比如startColumn = "A"endColumn = "D"
  • 若模板有多个工作表,不要直接取第一个,建议通过Sheet的名称定位对应的WorksheetPart
  • 所有操作都包裹在using语句中,确保文档自动关闭和资源释放

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

火山引擎 最新活动