zoukankan      html  css  js  c++  java
  • 【EPplus】Column width discrepancy

    description

    Hi Jan,

    I have noticed that when I set a column width there is a 
    discrepancy between the width that I set in code and what 
    Excel reports.

    From the code below, Excel reports the width to be 11.27.

    Excel reports the height to be exactly what I set.

    oSheet.Column(1).Width = 12.0d;
    oSheet.Row(1).Height = 27.75d;

    Duardo
    Closed Nov 10, 2010 at 3:00 PM by 
    This is the OOXML value. You can have a look at it if you rename your document *.zip, extract it and look in the xlworksheetssheetX.xml file. I think Excel recalculates it in some way on startup. 
    Anyway, I can't change it since a lot of people use it.

    comments

    TomDierickx wrote Apr 9, 2012 at 8:32 PM

    For anybody else who runs into this, by some lengthy trial-and-error experimentation, I believe whatever Column width you think you are setting, it narrows it by approx 0.667 and then rounds to the nearest 1/7th and if you are trying to set a value lower than 1.667, it starts rounding down about 50% to the nearest 12th.

    So, for X >= 1.667, you will probably see a true column width of [ROUND(7 * (X - 1/256)) - 5] / 7 rounding this to two decimal places. For example, let's say you try setting the column width to 10 (i.e. X=10), then you will likely really see a value of "ROUND(7 * (10 - 1/256))" = 70 - 5 = 65 / 7 = 9.29

    One workaround that seems to work for a variety of sample widths is to create a custom function to "adjust up" the value you think you're setting by an amount that will result in a net value to get you as close as possible (to the nearest 1/7th if > 1.6667 or to the nearest 1/2th if < 1.6667):

    oSheet.Column(1).Width = 10 'really ends up being 9.29
    oSheet.Column(2).Width = SetTrueColumnWidth(10) ' really ends up being 10.00 

    where the following function takes your desired column width and modifies it by enough such that the net result of setting the column width will actually end up being what you want it to be:

    Private Function SetTrueColumnWidth(ByVal dblWidth As Double) As Double

    'DEDUCE WHAT THE COLUMN WIDTH WOULD REALLY GET SET TO
    Dim z As Double = 1
    If (dblWidth >= (1 + 2 / 3)) Then
      z = Math.Round((Math.Round(7 * (dblWidth - 1 / 256), 0) - 5) / 7, 2)
    Else
      z = Math.Round((Math.Round(12 * (dblWidth - 1 / 256), 0) - Math.Round(5 * dblWidth, 0)) / 12, 2)
    End If

    'HOW FAR OFF? (WILL BE LESS THAN 1)
    Dim errorAmt As Double = 0
    errorAmt = dblWidth - z

    'CALCULATE WHAT AMOUNT TO TACK ONTO THE ORIGINAL AMOUNT TO RESULT IN THE CLOSEST POSSIBLE SETTING 
    Dim adjAmt As Double = 0
    If (dblWidth >= (1 + 2 / 3)) Then
      adjAmt = (Math.Round(7 * errorAmt - 7 / 256, 0)) / 7
    Else
      adjAmt = ((Math.Round(12 * errorAmt - 12 / 256, 0)) / 12) + (2 / 12)
    End If

    'RETURN A SCALED-VALUE THAT SHOULD RESULT IN THE NEAREST POSSIBLE VALUE TO THE TRUE DESIRED SETTING
    If (z > 0) Then
      Return dblWidth + adjAmt
    Else
      Return 0
    End If

    End Function

    grimmdp wrote Apr 2, 2013 at 1:42 PM

    Hi Tom,
    Thanks a bunch for posting this, it helped me a ton. Here it is in C# for anyone who need it:

    Dean
            public static double GetTrueColumnWidth(double dblWidth)
            {
                //DEDUCE WHAT THE COLUMN WIDTH WOULD REALLY GET SET TO
                double z = 1d;
                if (dblWidth >= (1 + 2 / 3)) 
                    z = Math.Round((Math.Round(7 * (dblWidth - 1 / 256), 0) - 5) / 7, 2);
                else
                    z = Math.Round((Math.Round(12 * (dblWidth - 1 / 256), 0) - Math.Round(5 * dblWidth, 0)) / 12, 2);
     
                //HOW FAR OFF? (WILL BE LESS THAN 1)
                double errorAmt = dblWidth - z;
     
                //CALCULATE WHAT AMOUNT TO TACK ONTO THE ORIGINAL AMOUNT TO RESULT IN THE CLOSEST POSSIBLE SETTING 
                double adjAmt = 0d;
                if (dblWidth >= (1 + 2 / 3)) 
                    adjAmt = (Math.Round(7 * errorAmt - 7 / 256, 0)) / 7; 
                else
                    adjAmt = ((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 dblWidth + adjAmt;
                return 0d;
     
            }
    

      

    redaxe wrote Jul 28, 2013 at 8:38 AM

    Saved my day thanks a lot,
    only one issue 3.5 is being calculated as 3.57 but its fine for me. :)

    Christophe_ wrote Jan 7, 2015 at 9:07 AM

    Also saved some time on our project, thanks !
  • 相关阅读:
    [原创]软件性能测试培训
    100w条记录分页,可以有多快?—— DataReader分页与SQL语句分页的对比测试(在线演示)
    【自然框架】注册会员活动——第一份代码的修改建议(第一版)
    加班有几种情况?兼谈讨论的方式。
    衔着树枝飞跃太平洋的傻鸟!(童话版)
    参加活动的好处。
    【自然框架】开源社区活动,会员注册的第一份代码!
    【自然框架】数据访问之精雕细琢(一)存储过程的参数
    自然框架开发系列(一):自然框架 和 AgileEAS.NET 合作,开发b/s的药店系统!
    自然框架开源社区的第一次活动——实现会员注册
  • 原文地址:https://www.cnblogs.com/hardsoftware/p/5796731.html
Copyright © 2011-2022 走看看