【问题标题】:Retain same Excel styles when merging sheets using C# and OpenXML使用 C# 和 OpenXML 合并工作表时保持相同的 Excel 样式
【发布时间】:2016-08-23 13:12:43
【问题描述】:

在 C# 中将多个 Excel 工作表合并到一个 Excel 文档时遇到问题。所以本质上它是一个包含多张工作表的工作簿。但是,这有效

问题在于它没有保留格式和样式。第一张表格的格式正确,但是它在整个表格中复制了不应该的相同样式。

我在合并工作表和保持相同的样式和格式方面需要帮助。

循环遍历工作表 C#

// For each worksheet in the child workbook...
                    foreach (Sheet childSheet in childWorkbookSheets)
                    {
                        // Get a worksheet part for the child worksheet using
                        // it's relationship Id.
                        childWorksheetPart = (WorksheetPart)childWorkbook.WorkbookPart.GetPartById(childSheet.Id);

                        // Add a worksheet part to the merged workbook based on
                        // the child worksheet.
                        mergedWorksheetPart = mergedWorkbookPart.AddPart<WorksheetPart>(childWorksheetPart);

                        //There should be only one worksheet that is set
                        //as the main view.
                        CleanView(mergedWorksheetPart);

                        // Create a Sheet element for the new sheet in the
                        // merged workbook.
                        newMergedSheet = new Sheet();

                        // Set the Name, Id, and SheetId attributes of the
                        // new Sheet element.
                        newMergedSheet.Name = GenerateWorksheetName(mergedWorkbookSheets, childSheet.Name.Value);

                        newMergedSheet.Id = mergedWorkbookPart.GetIdOfPart(mergedWorksheetPart);

                        newMergedSheet.SheetId = (uint)mergedWorkbookSheets.ChildElements.Count + 1;

                        // Add the new Sheet element to the Sheets element in the
                        // merged workbook.
                        mergedWorkbookSheets.Append(newMergedSheet);

                        // Get the SheetData element of the new worksheet part
                        // in the merged workbook.
                        mergedSheetData = mergedWorksheetPart.Worksheet.GetFirstChild<SheetData>();

                        if (styleCounter == 0)
                        {
                            mergedWorkbook.WorkbookPart.AddPart<WorkbookStylesPart>(childSharedStylePart);
                        }

                        styleCounter++;

                        // For each row of data...
                        foreach (Row row in mergedSheetData.Elements<Row>())
                        {
                            // For each cell in the row...
                            foreach (Cell cell in row.Elements<Cell>())
                            {
                                // If the cell is using a shared string, merge
                                // the string from the child workbook into the merged
                                // workbook.
                                CellFormat cellFormat = cell.StyleIndex != null ? GetCellFormat(mergedWorkbookPart, cell.StyleIndex).CloneNode(true) as CellFormat : new CellFormat();
                                GetCellFormat(mergedWorkbookPart, cell.StyleIndex);
                                if (cell.DataType != null &&
                                    cell.DataType.Value == CellValues.SharedString)
                                {
                                    ProcessCellSharedString(mergedWorksheetPart, cell, mergedSharedStringTablePart, childSharedStringTablePart);
                                }
                                cell.StyleIndex = InsertCellFormat(mergedWorkbookPart, cellFormat);

                                mergedSheetData.AppendChild(new Cell());
                                mergedCellformat = GetCellFormat(mergedWorkbookPart, cell.StyleIndex);

                                //cellFormat.ReplaceChild(mergedCellformat,mergedCellformat);

                                //attempt to add styling to the other worksheets
                                mergedCellformat.FillId.Value = (cellFormat.FillId.Value);
                                mergedCellformat.BorderId.Value = (cellFormat.BorderId.Value);
                                mergedCellformat.FontId.Value = (cellFormat.FontId.Value);
                                //mergedCellformat.FormatId = (cellFormat.FormatId.Value);

                                //cellFormat.AppendChild(mergedCellformat);
                                //cellFormat.Append(mergedCellformat);
                            }
                        }

第一张纸很完美,它保留了格式和正确性。 其余的表格到处都是它的格式。不一样。

private static CellFormat GetCellFormat(WorkbookPart workbookPart, uint styleIndex)
{
    return workbookPart.WorkbookStylesPart.Stylesheet.Elements<CellFormats>().First().Elements<CellFormat>().ElementAt((int)styleIndex);
}

private static uint InsertCellFormat(WorkbookPart workbookPart, CellFormat cellFormat)
{
    CellFormats cellFormats = workbookPart.WorkbookStylesPart.Stylesheet.Elements<CellFormats>().First();
    cellFormats.Append(cellFormat);
    return (uint)cellFormats.Count++;
}

【问题讨论】:

  • 任何时候格式化都是拼图的关键部分,图片是值得赞赏的。您能否添加一些当前(错误)行为和预期行为的图像?
  • @Mikegrann 嗨,第一张图片显示了工作表的第一张。它保留相同的格式并且很好。但是其他工作表不是,格式不正确并且没有被保留。
  • 你能展示你的GetCellFormatInsertCellFormat方法吗?
  • @petelids 我已将它们添加到上面的代码中
  • 我怀疑这是您的(整个)问题,但 return (uint)cellFormats.Count++; 对我来说看起来不对。这将返回Count,然后在返回它之后增加计数。这是故意的吗?

标签: c# xml excel openxml openxml-sdk


【解决方案1】:

我不知道你是否可以这样做,但我会尝试从选择范围的角度来解决这个问题,并使用下面引用的“PasteSpecial”的 OPENXML 等效项:

How to apply cell style to each cell in new row from previous row

因此,与其尝试单独获取格式,不如创建单元格,填充数据,然后复制格式...

定义一个源 RangeSet。 https://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.rangeset_members.aspx

CloneNode(true) 的那个。 然后将其插入合并的工作表中。 (因为这应该复制有关范围的所有内容,包括样式)。

(免责声明:我没有时间对此进行测试,但希望该建议有助于找到一条替代途径)

【讨论】:

    【解决方案2】:

    我会考虑创建一个Worksheet Template

    使用模板创建新工作表涉及如下 (VBA) 代码:

    'Insert sheet template
    With ThisWorkbook
        Set sh = Sheets.Add(Type:=Application.TemplatesPath & shName, _
                            after:=.Sheets(.Sheets.Count))
    End With
    

    然后只需用原始数据填充它(无论是通过 (VBA) .PasteSpecial Paste:=xlPasteValues 还是直接将值分配给单元格)并命名它。

    上述代码的 OpenXML 等效项应该很容易找到。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-18
      • 1970-01-01
      相关资源
      最近更新 更多