使用Open XML向现有的Excel 2007工作簿添加列

3
我有一个预定义的Excel工作簿,其中所有工作表都已设置好,我需要向其写入内容。我已经成功地写入单元格。
问题是在特定的工作表中,我需要添加三列。在下面的代码中,首先我获取工作表,然后继续添加列。这段代码运行良好,也就是说,没有抛出异常,但当我尝试打开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 );
    }

编辑:根据Chris关于列概念的解释

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 );
    }
1个回答

5

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

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

  • 然后,您假设Columns集合还不存在...

  • 最后,重点是如果在SheetData之后追加Columns集合,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六列。 我该如何实现呢? - E-Bat
从原始问题和初始示例代码中,我认为您只想定义列的宽度。但是根据您的评论,我会说太宽泛了 - Chris
1
@Elio.Batista 插入列就像你想象的那样,使用OpenXmlSDK是一个非常大的操作。从我对这个问题的理解来看,这意味着你将不得不找到所有单元格并更改它们的引用(例如,在插入3列后,具有引用“B1”的单元格将变为“F1”...)。这意味着你将不得不改变很多其他东西(例如公式中单元格的引用)。这种类型的操作可以使用Interop或可能使用EEPlus或ClosedXml等库完成。 - Chris
非常感谢,EEPlus太棒了,它做到了。 - E-Bat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接