如何使用EPPlus设置XLSX单元格宽度?

91

你好,我有这样一段代码,其中我创建了一个xlsx文件,并且需要预先设置xlsx工作表单元格的宽度。实际问题是,当我打开Excel时,我需要用鼠标双击列之间的间隙才能展开列并查看隐藏的数据。是否有一种用Epplus编程实现的方法来解决这个问题?

using (ExcelPackage p = new ExcelPackage())
            {
                String filepath = "C://StatsYellowPages.csv";
                DataSet ds = ExportCSVFileToDataset(filepath, "tblCustomers", "\t");
                //Here setting some document properties              
                p.Workbook.Properties.Title = "StatsYellowPages";

                //Create a sheet
                p.Workbook.Worksheets.Add("Sample WorkSheet");
                ExcelWorksheet ws = p.Workbook.Worksheets[1];
                ws.Name = "StatsYellowPages"; //Setting Sheet's name

                //Merging cells and create a center heading for out table
                ws.Cells[1, 1].Value = "StatsYellowPages";
                ws.Cells[1, 1, 1, ds.Tables[0].Columns.Count].Merge = true;
                ws.Cells[1, 1, 1, ds.Tables[0].Columns.Count].Style.Font.Bold = true;
                ws.Cells[1, 1, 1, ds.Tables[0].Columns.Count].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;

                int colIndex = 1;
                int rowIndex = 2;

                foreach (DataColumn dc in ds.Tables[0].Columns) //Creating Headings
                {
                    var cell = ws.Cells[rowIndex, colIndex];

                    //Setting the background color of header cells to Gray
                    var fill = cell.Style.Fill;
                    fill.PatternType = ExcelFillStyle.Solid;
                    fill.BackgroundColor.SetColor(Color.Gray);


                    //Setting Top/left,right/bottom borders.
                    var border = cell.Style.Border;
                    border.Bottom.Style = ExcelBorderStyle.Thin;
                    border.Top.Style = ExcelBorderStyle.Thin;
                    border.Left.Style = ExcelBorderStyle.Thin;
                    border.Right.Style = ExcelBorderStyle.Thin;

                    //Setting Heading Value in cell
                    cell.Value = dc.ColumnName;

                    colIndex++;
                }

                foreach (DataRow dr in ds.Tables[0].Rows) // Adding Data into rows
                {
                    colIndex = 1;
                    rowIndex++;
                    foreach (DataColumn dc in ds.Tables[0].Columns)
                    {
                        var cell = ws.Cells[rowIndex, colIndex];
                        //Setting Value in cell
                        cell.Value = dr[dc.ColumnName].ToString();
                        //Setting borders of cell
                        var border = cell.Style.Border;                      
                        colIndex++;
                    }
                }


                //Generate A File with Random name
                Byte[] bin = p.GetAsByteArray();
                string file = "c:\\StatsYellowPages.xlsx";
                File.WriteAllBytes(file, bin);
5个回答

170

我发现在填写完工作表上的所有数据之后设置列宽度最为有效:

ws.Column(1).Width = 50;

另外还有autoFitColumns方法,但是它会忽略带有公式和换行文本的单元格,所以对我没用。

ws.Cells["A1:K20"].AutoFitColumns();

12
若要自动调整工作表中所有列的宽度,请执行以下操作:for (i = 1; i <= ws.Dimension.End.Column; i++) { ws.Column(i).AutoFit(); } - FarFigNewton
3
它能够正常工作,但当我想设置不同的值时出现问题。例如,我想将列的宽度设置为7.86,但实际设定值为7.14;又比如,当我想将其设置为3.5时,它实际设定值为2.71。 - Mubashar
8
自适应所有列宽的更简单方式是使用:ws.Cells[ws.Dimension.Address].AutoFitColumns()。 - Tevin
4
我使用的是EPPlus 4.0.5,这个方法对我可行:ws.Cells.AutoFitColumns(); 确保在创建完所有单元格后再执行此操作。 - Baxter
1
@Jonah:是的,请看下面的答案,了解如何修复它。 - Mubashar
显示剩余4条评论

31

实际答案已经被标记,那是设置列宽度的正确方式,但有一个问题是,当文档在Excel中第一次打开时,它会重新计算列的宽度(不知道为什么),所以如我在下面的评论中所提到的,当我将列宽度设置为7.86时,它会重置为7.14,而10.43则变成了9.7x。

我从此 epp 报告的问题中找到了以下代码,以获取最接近所需列宽的值。

//get 7.14 in excel
ws.Column(1).Width = 7.86;

//get 7.86 in excel
ws.Column(1).Width = GetTrueColumnWidth(7.86);

public static double GetTrueColumnWidth(double width)
        {
            //DEDUCE WHAT THE COLUMN WIDTH WOULD REALLY GET SET TO
            double z = 1d;
            if (width >= (1 + 2 / 3))
            {
                z = Math.Round((Math.Round(7 * (width - 1 / 256), 0) - 5) / 7, 2);
            }
            else
            {
                z = Math.Round((Math.Round(12 * (width - 1 / 256), 0) - Math.Round(5 * width, 0)) / 12, 2);
            }

            //HOW FAR OFF? (WILL BE LESS THAN 1)
            double errorAmt = width - z;

            //CALCULATE WHAT AMOUNT TO TACK ONTO THE ORIGINAL AMOUNT TO RESULT IN THE CLOSEST POSSIBLE SETTING 
            double adj = 0d;
            if (width >= (1 + 2 / 3))
            {
                adj = (Math.Round(7 * errorAmt - 7 / 256, 0)) / 7;
            }
            else
            {
                adj = ((Math.Round(12 * errorAmt - 12 / 256, 0)) / 12) + (2 / 12);
            }

            //RETURN A SCALED-VALUE THAT SHOULD RESULT IN THE NEAREST POSSIBLE VALUE TO THE TRUE DESIRED SETTING
            if (z > 0)
            {
                return width + adj;
            }

            return 0d;
        }

1
(1 + 2 / 3) == 1; (7 / 256) == 0; (12 / 256 == 0)(1 + 2 / 3) 等于 1;(7 / 256) 等于 0;(12 / 256 == 0) - tibx

11

这是实现方式,用于设置工作表中第一列的单元格宽度。

    worksheet.Column(1).SetTrueColumnWidth(28);

这是用于在EPPlus Excel文件中设置更精确列宽的扩展方法,需要注意该方法必须位于静态类中:

    public static void SetTrueColumnWidth(this ExcelColumn column, double width)
    {
        // Deduce what the column width would really get set to.
        var z = width >= (1 + 2 / 3)
            ? Math.Round((Math.Round(7 * (width - 1 / 256), 0) - 5) / 7, 2)
            : Math.Round((Math.Round(12 * (width - 1 / 256), 0) - Math.Round(5 * width, 0)) / 12, 2);

        // How far off? (will be less than 1)
        var errorAmt = width - z;

        // Calculate what amount to tack onto the original amount to result in the closest possible setting.
        var adj = width >= 1 + 2 / 3
            ? Math.Round(7 * errorAmt - 7 / 256, 0) / 7
            : Math.Round(12 * errorAmt - 12 / 256, 0) / 12 + (2 / 12);

        // Set width to a scaled-value that should result in the nearest possible value to the true desired setting.
        if (z > 0)
        {
            column.Width = width + adj;
            return;
        }

        column.Width = 0d;
    }

1
请注意,在进行数学舍入时,您应该修复那些整数分数(例如1/2567/25612/2562/12应变为1D/2567D/25612D/2562D/12)。不幸的是,stackoverflow不允许我编辑答案,显示“建议的编辑队列已满”。 - Francesco Cattoni

2

您可以通过更改 DefaultColWidth 属性来更改工作表中所有列的默认宽度:

worksheet.DefaultColWidth = 25;

1
有一种更简单的方法。Excel会将传入的列宽量化为小于1的12分之一和大于1的7分之一。这意味着会产生阶梯状的结果,许多结束值无法实现(例如3.5、4.5等)。
要预先补偿宽度,以下内容就足够了。
如果DesiredWidth < 1,则
AdjustedWidth = 12/7 * DesiredWidth
否则,
AdjustedWidth = DesiredWidth + 5/7
写入Worksheet.Column(i).Width = AdjustedWidth以使用EPPLUS。
这是一个单调的调整,Excel在打开/保存时进行所有的量化。

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