【问题标题】:How to set XLSX cell width with EPPlus?如何使用 EPPlus 设置 XLSX 单元格宽度?
【发布时间】:2012-02-24 03:41:45
【问题描述】:

您好,我有这段代码,我在其中创建了一个 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);

【问题讨论】:

    标签: c# .net epplus


    【解决方案1】:

    我发现在填写工作表上的所有数据后设置列宽是可行的:

    ws.Column(1).Width = 50;
    

    还有 autoFitColumns 方法,但这会忽略带有公式和换行文本的单元格,所以它对我不起作用。

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

    【讨论】:

    • 我会补充一点,如果您想自动调整工作表中的所有列,请执行此操作for (i = 1; i <= ws.Dimension.End.Column; i++) { ws.Column(i).AutoFit(); }
    • 它可以工作,但设置不同的值,例如我想将列的宽度设置为 7.86,但它设置为 7.14,对于 3.5,它设置为 2.71
    • 自动调整所有列的更简单方法是使用:ws.Cells[ws.Dimension.Address].AutoFitColumns()
    • 我正在使用 EPPlus 4.0.5,这对我有用:ws.Cells.AutoFitColumns();只需确保在创建所有单元格之后放置它即可。
    • @Jonah:是的,请参阅下面的答案如何解决它。
    【解决方案2】:

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

    我从this epp reported issue 中找到了以下代码,以根据需要获取壁橱可能的列宽。

    //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 + 2 / 3) == 1; (7 / 256) == 0; (12 / 256 == 0)
    【解决方案3】:

    Mubashar Ahmad 的回答帮助了我,谢谢。我想包括我如何在我的项目中使用它。我已经把它做成了扩展方法并重构了。

    这里是实现,它设置工作表中第一列的单元格宽度。

        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 / 2567 / 25612 / 2562 / 12 应该变为 1D / 2567D / 256、@987654329 @ 和 2D / 12)。遗憾的是,stackoverflow 不允许我编辑回答说 “建议的编辑队列已满”
    【解决方案4】:

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

    worksheet.DefaultColWidth = 25;
    

    【讨论】:

      【解决方案5】:

      有一个更简单的方法。 Excel 将量化传入的列宽以显示低于 1 的 12 和高于 7 的显示。这意味着无法生成阶梯结果和许多最终值(例如 3.5、4.5 等)。

      要预先补偿宽度,以下就足够了。

      如果 DesiredWidth

      AdjustedWidth = 12/7 * DesiredWidth

      否则

      AdjustedWidth = DesiredWidth + 5/7

      ENDIF

      使用 EPPLUS 编写 Worksheet.Column(i).Width = AdjustedWidth

      这是一个单调的调整,Excel 会在打开/保存时完成所有量化。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-18
        • 1970-01-01
        • 1970-01-01
        • 2018-09-02
        • 2013-03-23
        • 2017-08-20
        相关资源
        最近更新 更多