如何使用OpenXML包自动调整Excel列宽

8

使用openxml包生成Excel电子表格的代码。请问有什么方法可以自动调整列宽度。

OpenXmlPackage.SpreadsheetDocument spreadsheetDocument = OpenXmlPackage.SpreadsheetDocument.Create(downloadFilePath, OpenXml.SpreadsheetDocumentType.Workbook);
// Add a WorkbookPart to the document.
OpenXmlPackage.WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart();
// Add a WorksheetPart to the WorkbookPart.
workbookpart.Workbook = new OpenXmlSpreadsheet.Workbook();
int numDates = datesObject.Length;

// Add Sheets to the Workbook.
OpenXmlSpreadsheet.Sheets sheets = new OpenXmlSpreadsheet.Sheets();
OpenXml.UInt32Value sheetId = 1;

OpenXmlPackage.WorksheetPart firstWorksheetPart = workbookpart.AddNewPart<OpenXmlPackage.WorksheetPart>();
firstWorksheetPart.Worksheet = new OpenXmlSpreadsheet.Worksheet(new OpenXmlSpreadsheet.SheetData());
// Append a new worksheet and associate it with the workbook.
OpenXmlSpreadsheet.Sheet firstSheet = new OpenXmlSpreadsheet.Sheet() { Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(firstWorksheetPart), SheetId = sheetId, Name = "Summary" };
sheets.Append(firstSheet);
sheetId++;

 OpenXmlSpreadsheet.SheetData firstSheetData = firstWorksheetPart.Worksheet.GetFirstChild<OpenXmlSpreadsheet.SheetData>();

 DataTable summaryTable = new DataTable();
 summaryTable.Clear();
 summaryTable.Columns.Add("name");
 summaryTable.Columns.Add("value");

 DataRow _summaryInfo = summaryTable.NewRow();
 _summaryInfo["name"] = "Clinic Name";
 _summaryInfo["value"] = userInfo[0];
 summaryTable.Rows.Add(_summaryInfo);



 int firstRowCount = summaryTable.Rows.Count;

 for (int rowNumber = 1; rowNumber <= firstRowCount; rowNumber++)
 {
      DataRow dataRow = summaryTable.Rows[rowNumber - 1];
      OpenXmlSpreadsheet.Row contentRow = ExcelHandler.createContentRow(dataRow, rowNumber);
      firstSheetData.AppendChild(contentRow);
 }

 firstWorksheetPart.Worksheet.Save();
1个回答

17

自适应逻辑是由微软Excel实现的,不是OpenXML电子表格格式的一部分。自适应包括测量每个单元格中值的宽度(或高度)并找到最大值。

要在自己的代码中实现自适应,您将需要手动测量文本; 您可以使用或 与适当的格式标志(禁用前缀字符)。 这将为您提供像素大小,您需要将其转换为Excel的复杂列宽度单位。其公式如下:

width = Truncate([{Number of Characters} * {Maximum Digit Width} + {5 pixel padding}]/{Maximum Digit Width}*256)/256

此引自这篇文章: Column Class(DocumentFormat.OpenXml.Spreadsheet)

(最大数字宽度可以通过使用工作簿的默认字体测量“0”字符的宽度来确定 - 告诉你它很复杂!)

获取了此公式的单元格宽度后,您可以找到最大值并将其应用于属性。

Microsoft Excel在呈现文本方面存在微妙的差异(与GDI / GDI +的方式相比),因此该方法并不百分之百准确 - 但对于大多数目的来说足够了,并且您始终可以添加一些额外的填充以确保适当的适合。


Truncate 究竟是什么,为什么需要它? - Emaborsa
1
@Emaborsa Truncate 函数会舍弃数字的小数部分,相当于将其四舍五入到最接近的整数。这是必要的,因为像素值通常表示为整数。 - Bradley Smith
好的,但是Column.Width属性需要一个double(我认为是以点为单位),而不是像素的int - Emaborsa
抱歉,我的上一条评论是错误的;Column.Width属性是以Excel的列宽度单位(而不是像素或点)来衡量的。因此,“Truncate”函数纯粹是因为Microsoft决定在除以256之前丢弃结果的小数部分 - 也许这是出于精度原因?无论如何,这对最终数字并没有太大影响。 - Bradley Smith
@Prakash Gupta,请看一下我的答案。发布的代码是DOM方法,但我也用SAX方法创建了一个解决方案,结果非常出色——没有内存泄漏(直接从DataReader写入),比Interop库快得多。唯一的缺点是自适应调整大小——您必须读取相同的数据两次。 - Lucy82

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