你的位置:首页 > ASP.net教程

[ASP.net教程]关于OpenXml SpreadSheet列宽根据内容的Auto


      因为之前接到的一个需求,让excel的宽度自动适应。所以最近一直在看Excel相关内容,从结构到.net的两个类库Open  这次学习花费了很多东西,主要陷入了两个误区,一个是一开始先入为主的认为Open后来终于找到了可爱的Columns类和Column类,然而。。。仔细阅读,逐个属性、方法的检查之后,居然没有解决方案,Width属性要给具体值(然而当初脑补的有个什么AutoFit()这种名字的方法。。。too naive)。
  后来在StackOverflow上找到了半个答案。大概意思就是:BestFit 属性是信息属性 (可能由 Excel 优化)。开发者仍然需要为该列提供宽度。这意味着你必须实际计算列宽度,根据单元格的内容。打开  
根据官方的文档中BestFit属性给出最后的解决方案如下:
 
  首先得到数据源中每一列的最大值。
列宽单位:一个列宽单位等于一个常规样式中一个字符的宽度,excel里面用像素和宽度来共同描述宽度。
                至于常规样式。。。(工具---选项---常规中的标准字体(当然与字大小也有关))

  上面中间的就是
  顺便说一下像素和厘米的换算吧  这里还要引入一个像素精度的概念dpi,如果显示器的像素精度是96dpi,其实就是96像素每英寸。像素精度是由显示设备的分辨率来的。下面放个截图(磅是行高单位) PS:鼠标上的DPI就是这个概念

 
  在常规样式字体下,列宽度的值是根据0,1,2,...,9这是个字符的平均值或最大值(Open  列宽度 = Truncate([{字符数} * {最大数字宽度像素} + {4+1个像素}]/{最大数字宽度}*256)/256
[示例: 使用宋体字体为例,11号字体大小的最大单个字符宽度是7个像素在96 dpi时。事实上,每个数字在设置为此字体时是相同的宽度。因此,如果值的宽度是 8 个字符宽,列宽的值也就是 Truncate([8*7+5]/7*256)/256 = 8.7109375个字符宽度]
 
要转化为列宽度的值在运行时 (以像素为单位表示) 的文件中的宽度值,请使用此公式:
= Truncate (((256 * {列宽度} + Truncate(128 / {最大数字宽度})) / 256) * {最大数字宽度})
[示例: 如上使用同一示例,计算将是 Truncate(((256*8.7109375+Truncate(128/7))/256)*7) = 61 像素。]
 
若要将像素转换为字符数,请使用此公式:
= Truncate(({像素数}-5) / {最大数字宽度像素} * 100 + 0.5) / 100
 
最后给出一个Demo
 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using DocumentFormat.Open 5 using DocumentFormat.Open 6 using DocumentFormat.Open 7  8 namespace Open 9 { 10   class Program 11   { 12     static void Main() 13     { 14       CreateSpreadSheet(); 15     } 16  17     private static void CreateSpreadSheet() 18     { 19       string fileName = "X:\\01.xlsx"; 20       string sheetName = "测试表格sheet—1"; 21       using (SpreadsheetDocument spreadSheet = SpreadsheetDocument.Create(fileName, SpreadsheetDocumentType.Workbook)) 22       { 23         spreadSheet.AddWorkbookPart(); 24         spreadSheet.WorkbookPart.Workbook = new Workbook(); 25  26         WorksheetPart worksheetPart1 = spreadSheet.WorkbookPart.AddNewPart<WorksheetPart>(); 27         worksheetPart1.Worksheet = new Worksheet(); 28         SheetData sheetData = new SheetData(); 29         ProductData(sheetData); 30         worksheetPart1.Worksheet.AppendChild(AutoFit(sheetData)); 31         worksheetPart1.Worksheet.AppendChild(sheetData); 32  33         spreadSheet.WorkbookPart.WorksheetParts.ElementAt(0).Worksheet.Save(); 34  35         spreadSheet.WorkbookPart.Workbook.AppendChild(new Sheets()); 36         spreadSheet.WorkbookPart.Workbook.GetFirstChild<Sheets>().AppendChild(new Sheet() 37         { 38           Id = spreadSheet.WorkbookPart.GetIdOfPart(spreadSheet.WorkbookPart.WorksheetParts.First()), 39           SheetId = 1, 40           Name = sheetName 41         }); 42  43         spreadSheet.WorkbookPart.Workbook.Save(); 44       } 45     } 46  47     private static void ProductData(SheetData sheetData) 48     { 49       for (uint rowIndex = 1; rowIndex < 5; rowIndex++) 50       { 51         Row row = new Row() { RowIndex = rowIndex }; 52         for (char cellIndex = 'A'; cellIndex < 'F'; cellIndex++) 53         { 54           Cell cell = new Cell(); 55           string innerText = "12234433433"; 56           cell.CellValue = new CellValue(innerText); 57           cell.DataType = new EnumValue<CellValues>(CellValues.String); 58           row.Append(cell); 59         } 60         for (char cellIndex = 'F'; cellIndex < 'K'; cellIndex++) 61         { 62           Cell cell = new Cell(); 63           string innerText = "12234"; 64           cell.CellValue = new CellValue(innerText); 65           cell.DataType = new EnumValue<CellValues>(CellValues.String); 66           row.Append(cell); 67         } 68         sheetData.Append(row); 69       } 70     } 71  72     private static Columns AutoFit(SheetData sheetData) 73     { 74       var maxColWidth = GetMaxCharacterWidth(sheetData); 75  76       Columns columns = new Columns(); 77  78       double maxWidth = 7; 79       foreach (var item in maxColWidth) 80       { 81         /*三种单位宽度公式*/ 82         double width = Math.Truncate((item.Value * maxWidth + 5) / maxWidth * 256) / 256; 83         double pixels = Math.Truncate(((256 * width + Math.Truncate(128 / maxWidth)) / 256) * maxWidth); 84         double charWidth = Math.Truncate((pixels - 5) / maxWidth * 100 + 0.5) / 100; 85  86         Column col = new Column() { BestFit = true, Min = (UInt32)(item.Key + 1), Max = (UInt32)(item.Key + 1), CustomWidth = true, Width = (DoubleValue)width }; 87         columns.Append(col); 88       } 89       return columns; 90     } 91  92     private static Dictionary<int, int> GetMaxCharacterWidth(SheetData sheetData) 93     { 94       Dictionary<int, int> maxColWidth = new Dictionary<int, int>(); 95       var rows = sheetData.Elements<Row>(); 96       foreach (var r in rows) 97       { 98         var cells = r.Elements<Cell>().ToArray(); 99         for (int i = 0; i < cells.Length; i++)100         {101           var cell = cells[i];102           var cellValue = cell.CellValue == null ? string.Empty : cell.CellValue.InnerText;103           var cellTextLength = cellValue.Length;104           if (maxColWidth.ContainsKey(i))105           {106             var current = maxColWidth[i];107             if (cellTextLength > current)108             {109               maxColWidth[i] = cellTextLength;110             }111           }112           else113           {114             maxColWidth.Add(i, cellTextLength);115           }116         }117       }118       return maxColWidth;119     }120   }121 }

View Code

 





现在去法国旅游多少钱法国旅游几月份最好法国旅游怎么样几月去法国旅游最便宜怎样去法国旅游台山凤凰峡漂流和月亮湾漂流哪个好玩?凤凰峡和月亮湾漂流有什么特色? 广东桂山大峡谷漂流开放时间?广东河源桂山大峡谷漂流旅游攻略? 广东桂山大峡谷漂流怎么样?桂山大峡谷漂流一天游攻略? 广东桂山大峡谷漂流在哪里?桂山大峡谷漂流好玩么? 2015云浮蟠龙洞门票怎么预订?云浮蟠龙洞风景区订票? 云浮蟠龙洞地址?云浮蟠龙洞风景区旅游攻略? 怀集燕岩图片?肇庆怀集燕岩风景区路线? 怀集燕岩风景图片?燕岩景区怎么走? 七仙岭君澜度假酒店9月优惠活动?保亭七仙岭君澜酒店有什么优惠? 知青逛公园 漫游明孝陵 三亚鹿回头山顶公园景点介绍?鹿回头山顶公园有什么好玩的? 海南鹿回头山顶公园地址?鹿回头山顶公园自己坐车怎么去? 越南小吃 水上木偶剧 越南旅游美食总汇 越南土特产品 ISL9012IRCCZ-T Datasheet ISL9012IRCCZ-T Datasheet ISL6622CRZ-T Datasheet ISL6622CRZ-T Datasheet ISL9011AIRNNZ-T Datasheet ISL9011AIRNNZ-T Datasheet 大兴安岭到香港澳门旅游报价 大兴安岭到香港澳门旅游报价 大兴安岭到香港澳门旅游报价 长春到港澳游报价 长春到港澳游报价 长春到港澳游报价 从吉林到香港旅游报价 从吉林到香港旅游报价 从吉林到香港旅游报价