在C#中打印DataGridView时如何计算单元格高度[有长文本] [英] How to calculate cell height [that has long text] when printing DataGridView in C#

查看:53
本文介绍了在C#中打印DataGridView时如何计算单元格高度[有长文本]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当单元格有长文本时,我搜索但没有找到如何在打印DataGridView时设置单元格高度.

我没有找到一个专注于如何计算长文本高度的结果.而且我不想使用以正确的单元格高度打印它的第 3 方 DLL 文件.

我使用此代码来计算高度,但文本总是被剪切,短文本的单元格高度低于 DGV.

var tallestHeight = 0;foreach(GridRow.Cells 中的 DataGridViewCell 单元格){if (!cell.Visible) { 继续;}var s = e.Graphics.MeasureString(cell.FormattedValue.ToString(), dataGridView1.Font);var tempHeight = (int)(s.Height * Math.Ceiling(s.Width/dataGridView1.Columns[cell.ColumnIndex].Width));如果(临时高度 > 最高高度){最高高度 = 临时高度;}最高高度 = (最高高度 <22) ?22:最高高度;}iCellHeight = 最高高度;

我希望当我将 DataGridView 打印到打印机时,可以在不剪切的情况下显示所有单元格中的所有文本.长文本增加行高,如果没有长文本行高保持不变.

我的行高 = 22

我的 DataGridView 的

Text wrapenabled

编辑 1:

这是我的

打印预览

黄色突出显示的文本不完整全文是First Middle lastname-some text-0130011511478- تجربةة 7427/01300/8346584584563846

下面的文字完成.

如何完整显示第一行?

解决方案

除了网格设置之外,您还需要使用输出大小来计算每行的足够高度以适合其内容.此外,调用采用

I searched but didn't find how to set the cell height when printing DataGridView when the cell has long text.

I didn't find one result that concentrate how to calculate the height with long text. And I don't want to use 3rd party DLL file that print it with right cell height.

I use this code to calculate the height but text always cut and short text has lower cell height that on DGV.

var tallestHeight = 0;
foreach (DataGridViewCell cell in GridRow.Cells)
{
    if (!cell.Visible) { continue; }
    var s = e.Graphics.MeasureString(cell.FormattedValue.ToString(), dataGridView1.Font);
    var tempHeight = (int)(s.Height * Math.Ceiling(s.Width / dataGridView1.Columns[cell.ColumnIndex].Width));
    if (tempHeight > tallestHeight)
    {
        tallestHeight = tempHeight;
    }
    tallestHeight = (tallestHeight < 22) ? 22 : tallestHeight;
}
iCellHeight = tallestHeight;

I want when I print DataGridView to printer to show all the text in all cells without cutting. Long text increase the row height and if no long text row's height stays unchanged.

I have row height = 22

Text wrap for my DataGridView is enabled

Edit1:

Here is my DataGridView properties

Here is how i print my DataGridView: PrintDGV Class that i use

My DGV appears

Print preview

Yellow highlighted text isn't complete Full text is First Middle lastname- some text- 0130011511478- تجربةة 7427/01300/8346584584563846

The text below it complete.

How to show the first row at full?

解决方案

Apart from the grid settings, you need to use the output sizes to calculate the adequate height of each row to fit their contents. Also, calling a MeasureString method overload that takes StringFormat is necessary to get more accurate result.

I see in the printout image above you are dividing the MarginBounds.Width by the visible cells. Thus, the following:


Calculate


Create a method to calculate and return the proper height of each row.

// +
using System.Linq;

private int GetRowHeight(
    Graphics g, 
    DataGridViewRow row, 
    Rectangle bounds, 
    StringFormat sf, 
    int minHeight = 22)
{
    var cells = row.Cells.OfType<DataGridViewTextBoxCell>()
        .Where(c => c.Visible);

    if (cells == null) return minHeight;

    var cell = cells.Aggregate((DataGridViewTextBoxCell)null, (x, y) => x != null && 
    x.FormattedValue.ToString().Length > y.FormattedValue.ToString().Length ? x : y);

    if (cell == null) return minHeight;

    var h = g.MeasureString(cell.FormattedValue.ToString(),
        row.DataGridView.Font,
        new SizeF(bounds.Width / cells.Count(), bounds.Height),
        sf).ToSize().Height;

    return Math.Max(h + 6, minHeight); // 6 for top and bottom margins...
}


Call


Caller example and class variables to track the printing...

// +
using System.Drawing.Printing;

private int rowIndex;
private int cellCount;
private int pageNumber;
private readonly PrintDocument printDoc;
// ...

// ctor
public YourForm()
{
    InitializeComponent();

    printDoc = new PrintDocument();
    printDoc.PrintPage += OnPrintPage;
}

// Cleanup
private void YourForm_FormClosed(object sender, FormClosedEventArgs e)
{
    printDoc.Dispose();
}

// Preview
private void btnPrintPreview(object sender, EventArgs e) => Print(true);

// Print
private void btnPrint(object sender, EventArgs e) => Print();

// Print Routine
private void Print(bool preview = false)
{
    rowIndex = 0;
    cellCount = 0;
    pageNumber = 0;

    var rows = dataGridView1.Rows
        .Cast<DataGridViewRow>()
        .FirstOrDefault(r => !r.IsNewRow);

    if (rows != null)
        cellCount = rows.Cells
            .OfType<DataGridViewTextBoxCell>()
            .Where(c => c.Visible)
            .Count();

    if (cellCount == 0)
    {
        MessageBox.Show("Nothing to print...");
        return;
    }

    printDoc.DefaultPageSettings.Landscape = true;

    if (preview)
    {
        using (var pd = new PrintPreviewDialog())
        {
                    
            pd.Document = printDoc;
            pd.ShowDialog();
        }
    }
    else
    {
        using (var pd = new PrintDialog())
        {
            pd.Document = printDoc;
            if (pd.ShowDialog() == DialogResult.OK)
                pd.Document.Print();
        }
    }
}


Print


PrintDocument.PrintPage event example.

// +
using System.Drawing.Text;

private void OnPrintPage(object sender, PrintPageEventArgs e)
{
    var w = e.MarginBounds.Width / cellCount;
    var x = e.MarginBounds.X;
    var y = e.MarginBounds.Y;
    int h;
    Rectangle rec;

    using (var sf = new StringFormat())
    {
        sf.Alignment = StringAlignment.Center;
        sf.LineAlignment = StringAlignment.Center;

        // Maybe you need to set this? I see Arabic text in the images.
        // sf.FormatFlags = StringFormatFlags.DirectionRightToLeft;

        e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;

        // Uncomment to print the headers in the first page only.
        //if (pageNumber == 0)
        //{
        h = dataGridView1.RowTemplate.Height;

        foreach (var col in dataGridView1.Columns
        .OfType<DataGridViewTextBoxColumn>()
        .Where(c => c.Visible))
        {
            rec = new Rectangle(x, y, w, h);

            e.Graphics.FillRectangle(Brushes.Gainsboro, rec);
            e.Graphics.DrawString(
                col.HeaderText, 
                col.DataGridView.Font, 
                Brushes.Black, 
                rec, 
                sf);
            e.Graphics.DrawRectangle(Pens.Black, rec);

            x += w;
        }
                    
        x = e.MarginBounds.X;
        y += h;                    
        //}

        for (var i = rowIndex; i < dataGridView1.RowCount; i++)
        {
            var row = dataGridView1.Rows[i];

            if (row.IsNewRow) break;

            h = GetRowHeight(e.Graphics, row, e.MarginBounds, sf);

            if (h > e.MarginBounds.Height)
            {
                MessageBox.Show("Insufficient height.");
                e.Cancel = true;
                return;
            }

            foreach (var cell in row.Cells
                .OfType<DataGridViewTextBoxCell>()
                .Where(c => c.Visible))
            {
                rec = new Rectangle(x, y, w, h);

                if (rec.Bottom > e.MarginBounds.Bottom)
                {
                    pageNumber++;
                    rowIndex = i;
                    e.HasMorePages = true;
                    return;
                }

                e.Graphics.DrawString(
                    cell.FormattedValue.ToString(), 
                    dataGridView1.Font, 
                    Brushes.Black, 
                    rec, 
                    sf);
                e.Graphics.DrawRectangle(Pens.Black, rec);

                x += rec.Width;
            }

            x = e.MarginBounds.X;
            y += h;                    
        }
    }
}


Output


这篇关于在C#中打印DataGridView时如何计算单元格高度[有长文本]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆