【问题标题】:Add Columns to Existing Excel 2007 workbook using Open Xml使用 Open Xml 向现有 Excel 2007 工作簿添加列
【发布时间】:2014-06-05 18:34:49
【问题描述】:

我有一个预定义的 Excel 工作簿,其中包含所有工作表,我需要向其中写入内容。我成功写入单元格。

问题出在我需要向其中添加三列的特定工作表中。在下面的代码中,首先我获取Worksheet,然后我继续添加列。这段代码运行良好,我的意思是,没有抛出异常,但是当我尝试打开 Excel 文件时出现错误,指出有一些内容无法读取,并且此特定工作表的所有内容都已清除。

我知道问题出在此操作上,因为如果我注释掉那些添加列的行,工作簿就会很好地打开,而我从代码中写入的所有单元格值都在原位。

这是相关代码,出于测试目的,我尝试添加 3 列:

using (SpreadsheetDocument document = SpreadsheetDocument.Open(outputPath, true)){
        Sheet sheet2 = document.WorkbookPart.Workbook.Descendants<Sheet>().Single( s => s.Name == "Miscellaneous Credit" );

        Worksheet workSheet2 = ( (WorksheetPart)document.WorkbookPart.GetPartById( sheet2.Id ) ).Worksheet;

        Columns cs = new Columns();
        for ( var y = 1; y <= 3; y++ ) {                    
            Column c = new Column()
            {
                Min = (UInt32Value)1U,
                Max = (UInt32Value)1U,
                Width = 44.33203125D,
                CustomWidth = true
            };
            cs.Append( c );
        }
        workSheet2.Append( cs );
    }

编辑:根据克里斯对列概念的解释

using (SpreadsheetDocument document = SpreadsheetDocument.Open(outputPath, true)){
        Sheet sheet2 = document.WorkbookPart.Workbook.Descendants<Sheet>().Single( s => s.Name == "Miscellaneous Credit" );

        Worksheet workSheet2 = ( (WorksheetPart)document.WorkbookPart.GetPartById( sheet2.Id ) ).Worksheet;

       // Check if the column collection exists
            Columns cs = workSheet2.Elements<Columns>().FirstOrDefault();
            if ( ( cs == null ) ) {
                // If Columns appended to worksheet after sheetdata Excel will throw an error.
                SheetData sd = workSheet2.Elements<SheetData>().FirstOrDefault();
                if ( ( sd != null ) ) {
                    cs = workSheet2.InsertBefore( new Columns(), sd );
                }
                else {
                    cs = new Columns();
                    workSheet2.Append( cs );
                }
            }

            //create a column object to define the width of columns 1 to 3  
            Column c = new Column
            {
                Min = (UInt32Value)1U,
                Max = (UInt32Value)3U,
                Width = 44.33203125,
                CustomWidth = true
            };
            cs.Append( c );
    }

【问题讨论】:

    标签: c# .net openxml openxml-sdk


    【解决方案1】:

    答案的第一部分涉及如何设置列宽(根据最初的示例代码,我认为您只想定义列的宽度)。

    • 首先,您似乎误解了 Column 对象的 Min 和 Max 属性。它们分别代表受此“列信息”记录影响的第一列和最后一列。因此,如果您有一组具有相同宽度的连续列,则可以使用一个 Column 类设置该宽度。在您的 sn-p 中,您定义了同一列(索引 1)宽度的 3 倍。

    • 那么,你假设Columns集合还不存在...

    • 最后,重点是如果Columns 集合附加在SheetData 之后,Excel 将抛出错误

    适合我的最终代码(Open XML SDK 2.0)

    using (SpreadsheetDocument document = SpreadsheetDocument.Open(outputPath, true)) {
        Sheet sheet2 = document.WorkbookPart.Workbook.Descendants<Sheet>().Single(s => s.Name == "Your sheet name");
    
        Worksheet workSheet2 = ((WorksheetPart)document.WorkbookPart.GetPartById(sheet2.Id)).Worksheet;
    
        // Check if the column collection exists
        Columns cs = workSheet2.Elements<Columns>().FirstOrDefault();
    
        if ((cs == null)) {
            // If Columns appended to worksheet after sheetdata Excel will throw an error.
            SheetData sd = workSheet2.Elements<SheetData>().FirstOrDefault();
            if ((sd != null)) {
                cs = workSheet2.InsertBefore(new Columns(), sd);
            } else {
                cs = new Columns();
                workSheet2.Append(cs);
            }
        }
    
        //create a column object to define the width of columns 1 to 3  
        Column c = new Column {
            Min = (UInt32Value)1U,
            Max = (UInt32Value)3U,
            Width = 44.33203125,
            CustomWidth = true
        };
        cs.Append(c);
    
    }
    

    我仍然对如何执行列插入感到困惑。说我有 A、B 和 C 列,我想在 B 和 C 之间插入三列, 以 A、B、C、D、E、F 列结束。我怎样才能实现它?

    OpenXml SDK 中的Columns 对象用于存储列的样式和宽度信息。在集合中插入 Column 不会在工作表中“插入”一列。

    像您所说的“插入”列是 OpenXmlSDK 的一项非常庞大且复杂的任务。

    根据我对问题的理解,这意味着您必须找到所有单元格并通过更改它们的引用来移动它们(例如,在插入 3 列后,带有引用“B1”的单元格将变为“F1”,等等...... )。这意味着您将不得不更改许多其他内容(例如,在公式中引用单元格)。

    这种任务可以使用 Office.Interop 或可能使用 EEPlusClosedXml 等库轻松完成。

    【讨论】:

    • +1。你让我走上了正确的道路。我仍然对如何执行列插入感到困惑。说我有 A、B 和 C 列,我想在 B 和 C 之间插入三列,最后是 A、B、C、D、E、F 列。我怎样才能实现它?
    • @Elio.Batista 从原始问题和初始示例代码中,我认为您只想定义列的宽度。但从您的评论中,我会说 TOO BROAD
    • @Elio.Batista “插入”您的意思的列是 OpenXmlSDK 的一项非常大的操作。根据我对问题的理解,这意味着您必须找到所有单元格并更改它们的引用(例如,在插入 3 列后,引用为“B1”的单元格将是“F1”......) .这意味着您将不得不更改许多其他内容(例如,在公式中引用单元格)。这种类型的操作可以使用 Interop 或可能使用 EEPlus 或 ClosedXml 等库来完成。
    • 非常感谢,EEPlus 很棒,它成功了。
    猜你喜欢
    • 2015-07-06
    • 2013-04-10
    • 1970-01-01
    • 2011-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多