OpenXML: ширина столбца автоматического размера в Excel
Я написал код для создания файла Excel с помощью OpenXML. Ниже приведен код, который генерирует столбцы в Excel.
Worksheet worksheet = new Worksheet();
Columns columns = new Columns();
int numCols = dt1.Columns.Count;
for (int col = 0; col < numCols; col++)
{
Column c = CreateColumnData((UInt32)col + 1, (UInt32)numCols + 1, 20.42578125D);
columns.Append(c);
}
worksheet.Append(columns);
кроме того, я попытался ниже строки создать столбцы.
Column c = new Column
{
Min = (UInt32Value)1U,
Max = (UInt32Value)1U,
Width = 25.42578125D,
BestFit = true,
CustomWidth = true
};
Я думал, что с помощью BestFit
он должен работать. Но он не устанавливает размер auto.
4 ответов
свойство BestFit является информационным свойством (возможно, для оптимизации Excel). Вам все равно нужно указать ширину столбца. Это означает, что вы должны реально рассчитать ширину столбца в зависимости от содержимого ячейки. Open XML SDK не делает это автоматически для вас, поэтому лучше использовать стороннюю библиотеку для этого.
вы должны рассчитать его самостоятельно, к сожалению
вот что у меня есть. Он работает для моих данных, табличных с некоторым дополнительным кодом, чтобы позаботиться о некоторых стилях, которые я установил. Это не идеально, но работает для того,что мне нужно.
private WorksheetPart mySheetPart;
private void WriteToTable()
{
//Get your sheet data - write Rows and Cells
SheetData sheetData = GetSheetData();
//get your columns (where your width is set)
Columns columns = AutoSize(sheetData);
//add to a WorksheetPart.WorkSheet
mySheetPart.Worksheet = new Worksheet();
mySheetPart.Worksheet.Append(columns);
mySheetPart.Worksheet.Append(sheetData);
}
private Columns AutoSize(SheetData sheetData)
{
var maxColWidth = GetMaxCharacterWidth(sheetData);
Columns columns = new Columns();
//this is the width of my font - yours may be different
double maxWidth = 7;
foreach (var item in maxColWidth)
{
//width = Truncate([{Number of Characters} * {Maximum Digit Width} + {5 pixel padding}]/{Maximum Digit Width}*256)/256
double width = Math.Truncate((item.Value * maxWidth + 5) / maxWidth * 256) / 256;
//pixels=Truncate(((256 * {width} + Truncate(128/{Maximum Digit Width}))/256)*{Maximum Digit Width})
double pixels = Math.Truncate(((256 * width + Math.Truncate(128 / maxWidth)) / 256) * maxWidth);
//character width=Truncate(({pixels}-5)/{Maximum Digit Width} * 100+0.5)/100
double charWidth = Math.Truncate((pixels - 5) / maxWidth * 100 + 0.5) / 100;
Column col = new Column() { BestFit = true, Min = (UInt32)(item.Key + 1), Max = (UInt32)(item.Key + 1), CustomWidth = true, Width = (DoubleValue)width };
columns.Append(col);
}
return columns;
}
private Dictionary<int, int> GetMaxCharacterWidth(SheetData sheetData)
{
//iterate over all cells getting a max char value for each column
Dictionary<int, int> maxColWidth = new Dictionary<int, int>();
var rows = sheetData.Elements<Row>();
UInt32[] numberStyles = new UInt32[] { 5, 6, 7, 8 }; //styles that will add extra chars
UInt32[] boldStyles = new UInt32[] { 1, 2, 3, 4, 6, 7, 8 }; //styles that will bold
foreach (var r in rows)
{
var cells = r.Elements<Cell>().ToArray();
//using cell index as my column
for (int i = 0; i < cells.Length; i++)
{
var cell = cells[i];
var cellValue = cell.CellValue == null ? string.Empty : cell.CellValue.InnerText;
var cellTextLength = cellValue.Length;
if (cell.StyleIndex != null && numberStyles.Contains(cell.StyleIndex))
{
int thousandCount = (int)Math.Truncate((double)cellTextLength / 4);
//add 3 for '.00'
cellTextLength += (3 + thousandCount);
}
if (cell.StyleIndex != null && boldStyles.Contains(cell.StyleIndex))
{
//add an extra char for bold - not 100% acurate but good enough for what i need.
cellTextLength += 1;
}
if (maxColWidth.ContainsKey(i))
{
var current = maxColWidth[i];
if (cellTextLength > current)
{
maxColWidth[i] = cellTextLength;
}
}
else
{
maxColWidth.Add(i, cellTextLength);
}
}
}
return maxColWidth;
}
у меня не было времени, чтобы изучить его, но вместо того, чтобы просто оставить комментарий и ссылка, Я думал, что поделюсь комментарием от кого-то, кто, казалось бы, сделал некоторые исследования по этому поводу.
у меня лично были проблемы с получением официальные формулы чтобы соответствовать реальности. Т. е. Короткие строки получили слишком маленькие ячейки, более длинные строки получили слишком большие ячейки, и, самое главное, значение, представленное в Excel, было пропорционально меньше значения, которое я вставил в DocumentFormat.OpenXml.Spreadsheet.Column
' s Width
-недвижимость. Мое решение было просто иметь минимальную ширину.
В любом случае, вот комментарий:
мне пришлось сделать это в конце концов, потому что файлы xlsx, которые меня интересуют, автоматически генерируются и должны выглядеть хорошо, как только они будут открыты, поэтому я посмотрел на это немного дальше и обнаружил, что есть несколько вопросов для точного определения размеров столбцов в Excel.
потребность использовать точный размер характера, который означает, что вместо использования MeasureString вам нужно использовать MeasureCharacterRanges, см. http://groups.google.com/group/microsoft.public.office.developer.com.add_ins/browse_thread/thread/2fc33557feb72ab4/adaddc50480b8cff?lnk=raot
несмотря на спецификацию, говорящую о добавлении 5 пикселей (1 Для границы и 2 для каждого бокового поля), Excel, похоже, использует 9-1 Для границы, 5 для ведущего пространства и 3 для конечного пространства – я нашел это только с помощью приложение доступность. Увеличитель и подсчет пикселей после использования Excel для автоматической подгонки столбцов
на самом деле я основывал свои вычисления на базовых метриках шрифта, поэтому я фактически не использую ни MeasureCharacterRanges, ни MeasureString. Если кто-то заинтересован в этом из метрик шрифта, то:
Width = Truncate( {DesiredWidth} + 9 / {MaxDigitWidth} ) / 256
{MaxDigitWidth} - целое число, округленное до ближайшего пикселя любого из 0..9 цифр при 96 dpi {DesiredWidth} является сумма сложения всех Ширин символов вместе, где каждая ширина символа-это ширина символа при 96 dpi, округленная до ближайшего целого числа. Обратите внимание, что каждый символ округляется не общая сумма
здесь можно формулу width = усечение ([{количество символов} * {максимальная ширина цифр} + {5 пикселей)] / {максимальная ширина цифр} * 256) / 256