c# - 使用 Open Xml 将列添加到现有 Excel 2007 工作簿

标签 c# .net openxml openxml-sdk

我有一个预定义的 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 );
    }

最佳答案

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

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

  • 那么,您认为 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);

}

I'm still confused on how to perform column insert. Says I have columns A, B and C, I want to insert three columns between B and C, ending up with columns A,B,C,D,E,F. How can i achieve it?

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

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

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

此类任务可以使用 Office.Interop 或 EEPlusClosedXml 等库轻松完成。

关于c# - 使用 Open Xml 将列添加到现有 Excel 2007 工作簿,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24038689/

相关文章:

.net - 选择哪个数据库以及如何压缩它

c# - Linq 'Index was outside the bounds of the array'问题

c# - 复制 Entity Framework 对象

c# - 如何使用 TSQL 语法将 .bak 恢复到新数据库?

c# - OnSerializing/OnSerialized/OnDeserializing/OnDeserialized 为什么不是一个接口(interface)?

c# - 具有自动实现属性和构造函数初始值设定项的结构

c# - 使用 OpenXML 打开 Excel 工作表时文件包含损坏的数据错误

c# - OpenXml 和无法创建互斥量

c# - 在 .NET 中使用 DataSet.WriteXml 时的自定义日期时间格式

c# - 如何在生成 Excel 工作表时为列值添加颜色?