Формула для преобразования пикселей .NET в ширину Excel в формате OpenXML

Я потратил много часов, пытаясь определить формулу для преобразования пикселей .NET в ширину столбца Excel с использованием формата OpenXML. Я использую EPPlus для создания документов xmls. Я пытаюсь определить ширину для столбца, который должен быть автоматическим. Я получаю количество пикселей, измеряя строку, а затем пытаюсь преобразовать ее в ширину столбца для OpenXML, которая измеряется в символах, которые я думаю.

Я прочитал документацию Microsoft о том, как ее преобразовать, и попробовал предложенную им формулу, но она даже не близка к точности:

http://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.column.aspx

Здесь мой код, используя их формулу:

    public double GetCharacterWidth(string Text, Font f, Graphics g)
    {
        float MaxDigitWidth = g.MeasureString("0", f).Width;
        float Pixels = g.MeasureString(Text, f).Width;

        return ((Pixels - 5) / MaxDigitWidth * 100 + 0.5) / 100;
    }

Любые идеи?

Ответ 1

Сначала нам нужно установить, как Excel выполняет преобразование (поскольку мы вручную изменяем размер в приложении Excel):

//Use 7d to promote to double, otherwise int will truncate.
ExcelWidth = (Pixels - 12) / 7d +  1;//From pixels to inches.

Предостережение. Формулы не работают для 0 (ноль) Ширина или пиксели.
Для этих сценариев используйте оператор" if", чтобы проверить, равен ли он нулю и вернуть ноль.

Он тоже бросил меня за петлю. Вместо того, чтобы пытаться вычислить Pixels per Width, я посмотрел разницу в пикселях между каждым числом Width и обнаружил, что это всегда 7. Исключение составляло от 0 до 1 Width; где было 12 пикселей для ширины 1.00. Оттуда я смог придумать формулы выше, легкомысленные.

Теперь эти цифры сохраняются в мире Excel, но если вы устанавливаете ширину столбцов непосредственно в документе OpenXml, это немного другая история. Вот почему: В документации, на которую вы ссылаетесь, говорится об этом 5 пикселей:

Имеется 4 пикселя отступности по краям (по две с каждой стороны), плюс 1 пиксельная прокладка для линий сетки.

Теперь все это означает, что Excel предполагает, что вы учли эти 5 пикселей в ширинах, которые вы предоставляете. Когда вы откроете свой документ в excel и измените размер столбцов, вы увидите, что ширина на 5 пикселей меньше, чем вы его установили.

Чтобы настроить это, вы можете обновить формулы следующим образом:

//Use 7d to promote to double, otherwise int will truncate.
OpenXmlWidth = (Pixels - 12 + 5) / 7d + 1;//From pixels to inches.

Это отвечает заголовку вашего вопроса:
" Формула для преобразования пикселей .NET в ширину Excel в формате OpenXML"

Если вы хотите узнать, как определить приближение ширины столбца, чтобы автоматически подогнать столбец на основе содержимого (и шрифта) одной ячейки, то это совершенно другой вопрос. Формулы, предоставленные предоставленной вами ссылкой Microsoft, не будут работать. Введите 10 периодов в одной ячейке и 10 capital-M в другой колонке. Вы увидите, что автоматическая подгонка дает вам 41 пиксель и 129 пикселей соответственно. Формулы, предоставленные ms, не учитывают ширину отдельных символов. Другими словами; они отправили вас на охоту на диких гусей.

Единственный способ автосочетания столбца - просканировать каждую строку в столбце и рассчитать ширину текста на основе символов и шрифта. Вы бы использовали что-то вроде того, что я нашел здесь. Тогда возьмите максимальное значение этого и pad с 5. Я бы избегал этого подхода при обработке электронных таблиц в веб-среде, потому что вы могли экспортировать сотни тысяч строк с десятками столбцов - вы получите эту идею. Лучший подход заключается в том, чтобы установить ширину наилучшей угадывания для ваших столбцов и обучить своих пользователей тому, как автоматически приспосабливаться к excel.

С уважением,
" Обычный человек "



Изменить - 10/26/2011:

Потому что я чувствую себя щедрым, вот пример того, как получить приблизительную ширину для вашего столбца. Я бы предпочел не делать этого для всех строк в столбце, поэтому давайте просто основываем нашу ширину (по умолчанию) на значение в ячейке заголовка. Ниже вы можете сделать это, используя пример, который я связал ранее. Примечание: это приближения, но достаточно близко.

using System.Drawing;
using System.Windows.Forms;//Add Reference.  Test on webserver first.
Font font = new Font("Calibri", 11.0f, FontStyle.Regular);
string header  = "Hello There World!";
int pxBaseline = TextRenderer.MeasureText("__", font).Width;
int pxHeader   = TextRenderer.MeasureText("_" + header + "_"), font).Width;
int pxColumnWidth = pxHeader - pxBaseline + 5;//Pad with 5 for Excel.

Caveat. Если вы используете этот код в том же месте, где используете OpenXml, вам может потребоваться удалить "использование" для System.Drawing и полностью квалифицировать "Шрифт" и "FontStyle" "как System.Drawing.Font и System.Drawing.FontStyle. В противном случае ваш компилятор может принять эти классы как принадлежащие к DocumentFormat.OpenXml.Spreadsheet.

Ответ 2

Формула, которую я придумал для преобразования ширины пикселя в ширину Excel:

    private double PixelWidthToExcel(int pixels)
    {
        var tempWidth = pixels * 0.14099;
        var correction = (tempWidth / 100) * -1.30;

        return tempWidth - correction;
    }

Мне это всегда дает точное преобразование стоимости.

И формула для высоты

    private double PixelHeightToExcel(int pixels)
    {
        return pixels * 0.75;
    }