【问题标题】:Creating custom column widths in OpenXML (excel)在 OpenXML (excel) 中创建自定义列宽
【发布时间】:2015-12-19 19:57:24
【问题描述】:

我是 OpenXML (v. 2.5) 的新手,我可以创建行和单元格,但我需要能够设置列宽,但由于某种原因我无法正确设置。

没有这个代码:

        Columns cols = new Columns();

        Column c1 = new Column()
        {
            CustomWidth = true,
            Width = 20
        };

        cols.Append(c1);
        wspart.Worksheet.Append(cols);

程序运行,生成excel文件正常。

下面的代码符合并运行,但给我留下了一个损坏的 excel 文档。当我尝试添加列时,我做错了什么?

    public static void createExcel() //TODO change to private
    {
        //create the spreadsheet document with openxml See https://msdn.microsoft.com/en-us/library/office/ff478153.aspx
        SpreadsheetDocument spreadsheetDoc = SpreadsheetDocument.Create(@"C:\Users\Reid\Documents\BLA\test.xlsx", SpreadsheetDocumentType.Workbook); //TODO change path

        //add a workbook part
        WorkbookPart wbpart = spreadsheetDoc.AddWorkbookPart();
        wbpart.Workbook = new Workbook();

        //add a worksheet part
        WorksheetPart wspart = wbpart.AddNewPart<WorksheetPart>();
        Worksheet ws = new Worksheet(new SheetData());
        wspart.Worksheet = ws;

        //create a new sheets array
        Sheets sheets = spreadsheetDoc.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets());

        //create a new sheet
        Sheet sheet = new Sheet()
        {
            Id = spreadsheetDoc.WorkbookPart.GetIdOfPart(wspart),
            SheetId = 1,
            Name = "mySheet" //TODO change name
        };

        //add the sheet to the workbook sheet aray
        sheets.Append(sheet);

        SheetData shData = wspart.Worksheet.GetFirstChild<SheetData>();

        //////////////////////////////////row and col widths//////////////////////
        Columns cols = new Columns();

        Column c1 = new Column()
        {
            CustomWidth = true,
            Width = 20
        };

        cols.Append(c1);
        wspart.Worksheet.Append(cols);

        //create the first row
        Row r1 = new Row
        {
            RowIndex = 1,
            CustomHeight = true,
            Height = 71.25 //change height based on info
        };
        shData.Append(r1);
  ////////////////////////cell data/////////////////////////////////

        // In the new row, find the column location to insert a cell in A1.
        Cell refCell = null;
        foreach (Cell cell in r1.Elements<Cell>())
        {
            if (string.Compare(cell.CellReference.Value, "A1", true) > 0)
            {
                refCell = cell;
                break;
            }
        }
        // Add the cell to the cell table at A1.
        Cell newCell = new Cell() {
            CellReference = "A1",
        };
        r1.InsertBefore(newCell, refCell);

        // Set the cell value to be a numeric value of 100.
        newCell.CellValue = new CellValue("100");


        //TODO add in standard things (text that is always the same, headers, logos, etc.)

        //TODO add in dynamic text

        //TODO create and add in barcodes

        //Save and close the document
        wbpart.Workbook.Save();
        spreadsheetDoc.Close();

        //TODO send document to database
    }

【问题讨论】:

    标签: c# excel openxml openxml-sdk


    【解决方案1】:

    上面选择的答案并没有解决我的问题,但我终于想通了。我的问题是当我调用该行时:Columns columns1=worksheet1.GetFirstChild&lt;Columns&gt;(); 工作表中当前没有Columns 子项,因此返回的对象为空,当我尝试将列附加到Columns 对象时出现运行时错误。

    问题在于 Excel 非常挑剔。实际 sheet.xml 文件中的 columns 元素必须位于 sheetdata 元素之前。尝试将我的自定义列附加到工作表会导致文件损坏,因为它将列元素放置在 sheetdata 元素之后。因为我知道它必须在 sheetdata 元素之前,所以我必须将它插入到工作表的开头,而不是将其附加到工作表中。这是对我有用的代码:

    // Save the stylesheet formats
    stylesPart.Stylesheet.Save();
    
    // Create custom widths for columns
    Columns lstColumns = worksheetPart.Worksheet.GetFirstChild<Columns>();
    Boolean needToInsertColumns = false;
    if (lstColumns == null)
    {
        lstColumns = new Columns();
        needToInsertColumns = true;
    }
    // Min = 1, Max = 1 ==> Apply this to column 1 (A)
    // Min = 2, Max = 2 ==> Apply this to column 2 (B)
    // Width = 25 ==> Set the width to 25
    // CustomWidth = true ==> Tell Excel to use the custom width
    lstColumns.Append(new Column() { Min = 1, Max = 1, Width = 25, CustomWidth = true });
    lstColumns.Append(new Column() { Min = 2, Max = 2, Width = 9, CustomWidth = true });
    lstColumns.Append(new Column() { Min = 3, Max = 3, Width = 9, CustomWidth = true });
    lstColumns.Append(new Column() { Min = 4, Max = 4, Width = 9, CustomWidth = true });
    lstColumns.Append(new Column() { Min = 5, Max = 5, Width = 13, CustomWidth = true });
    lstColumns.Append(new Column() { Min = 6, Max = 6, Width = 17, CustomWidth = true });
    lstColumns.Append(new Column() { Min = 7, Max = 7, Width = 12, CustomWidth = true });
    // Only insert the columns if we had to create a new columns element
    if (needToInsertColumns)
        worksheetPart.Worksheet.InsertAt(lstColumns, 0);
    
    // Get the sheetData cells
    SheetData sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>();
    

    希望这对某人有所帮助!

    【讨论】:

    • 另一个需要注意的重要事情是必须将列列表插入到工作表 XML 中在工作表数据之前。如果你之后插入它,那么在打开电子表格时会出错。此示例以这种方式工作,但对于在填充工作表数据时计算最大列长度的任何人来说仅供参考。
    • @BateTech 注释很受赞赏,但显然您没有阅读我的全部答案。我实际上是在第二段中说的。
    • 实际上是“最佳”答案 - 从头开始​​创建的 OpenXML 文件不太可能具有预先存在的“列”元素。感谢您提供非常有用的帖子!
    • @FoggyDay 没问题!很高兴它有帮助!
    • @compman2408 谢谢。我不知道InsertAt() 可以将列放在已经存在的 SheetData 之前。我发现的所有示例都使用Append()
    【解决方案2】:

    我认为您遇到的问题是创建新列元素并将其附加到现有工作表内容。我相信您需要将新列附加到现有的列元素。

    我创建了一个工作簿,保存它,在一个空列中添加内容,然后以新名称保存工作簿并关闭它。

    使用 Open XML SDK 2.5 Productivity Tool 的“比较”功能,我选择了包含差异的工作表部分,选择它,然后单击“查看包代码”。使用原始文件中的新列生成更改文件的代码向我展示了:

    Columns columns1=worksheet1.GetFirstChild<Columns>();
    //other code here
    Column column1 = new Column(){ Min = (UInt32Value)5U, Max = (UInt32Value)5U, Width = 16D, CustomWidth = true };
    columns1.Append(column1);
    

    请注意,您似乎还需要指定新列的列范围。

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题,.GetFirstChild&lt;Columns&gt; 为空。创建 Columns 对象并在索引 0 处插入(与其他答案一样)使 Excel 抱怨该文件无效。相反,它似乎想要在 SheetData 部分之前的列定义:

      if (needToInsertColumns)
      {
          var sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>();
          worksheetPart.Worksheet.InsertBefore(columnsList, sheetData);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多