Could someone tell me why I get the error "Operation failed:Index and lengt must refer to a location within the string Parameter:Length". It happened at this line: TheDataGridView.Rows[j].Cells[i].Value = tmpStr.Substring(0, 709);

                    tmpSize = g.MeasureString("Anything", tmpFont);
                    RowsHeight.Add(tmpSize.Height);

                    tmpSize = g.MeasureString(TheDataGridView.Rows[j].Cells[i].EditedFormattedValue.ToString(), tmpFont);
                    if (tmpSize.Width > 710)
                    {
                        string tmpStr = TheDataGridView.Rows[j].Cells[i].ToString();
                        TheDataGridView.Rows[j].Cells[i].Value = tmpStr.Substring(0, 709);
                        tmpSize = g.MeasureString(TheDataGridView.Rows[j].Cells[i].EditedFormattedValue.ToString(), tmpFont);
                        //tmpWidth = tmpSize.Width;

                        //MessageBox.Show(tmpStr);

                        //g.MeasureString(TheDataGridView.Rows[j].Cells[i]
                    }

Dani AI

Generated

Two separate issues produce the exception in 's snippet: calling Cells[i].ToString() (which returns the cell object description, not the cell text) and calling Substring(0, 709) without guaranteeing the string actually has 709 characters. correctly flagged the length check; correctly pointed out that pixel width (what MeasureString returns) is not the same as character count, so deciding "709 characters" from a measured width is unreliable.

A safer, minimal pattern for extracting and truncating the cell text by character count:

string GetCellText(DataGridViewCell cell)
{
    // prefer EditedFormattedValue when present, fall back to Value
    return Convert.ToString(cell?.EditedFormattedValue ?? cell?.Value) ?? string.Empty;
}

int maxChars = 709;
var text = GetCellText(TheDataGridView.Rows[j].Cells[i]);
var truncated = text.Length <= maxChars ? text : text.Substring(0, maxChars);
TheDataGridView.Rows[j].Cells[i].Value = truncated;

When the goal is "fit into X pixels", measure with the same rendering API that Paint uses and use a fast search for the largest substring that fits. A binary-search approach reduces MeasureText calls from O(n) to O(log n):

using System.Drawing;
using System.Windows.Forms;

static string TruncateToPixelWidth(string text, Font font, int pixelWidth)
{
    if (string.IsNullOrEmpty(text)) return string.Empty;
    int lo = 0, hi = text.Length;
    while (lo < hi)
    {
        int mid = (lo + hi + 1) / 2;
        Size s = TextRenderer.MeasureText(text.Substring(0, mid), font, new Size(int.MaxValue, int.MaxValue),
                                          TextFormatFlags.NoPadding | TextFormatFlags.SingleLine);
        if (s.Width <= pixelWidth) lo = mid;
        else hi = mid - 1;
    }
    return text.Substring(0, lo);
}

Notes and cautions: measure with the exact Font and the same TextFormatFlags used by the DataGridView cell; include column padding when comparing to column width; guard against null Value/EditedFormattedValue; consider adding an ellipsis after truncation for UX.

Recommended Answers

All 2 Replies

The reason is because tmpString is less than 710 characters so it can not get a sub string with a length of 709 characters starting with the first one.

Try this:

string tmpStr = "This is a test.";

if (tmpStr.Length < 709)
{
    //MessageBox.Show("The string is too short.");
}
else
{
    string subStr = tmpStr.Substring(0, 709);
}

in line 4 you are getting the size of the string measured in (most likely) pixels. A single character occupies more than one pixel in width, so there aren't 709 characters available, but more than 709 pixels of width. If you are trying to get the longest string with less than 710 pixels of width you'd do something like

g.MeasureString(TheDataGridView.Rows[j].Cells[i].EditedFormattedValue.ToString(), tmpFont);

String str = TheDataGridView.Rows[j].Cells[i].EditedFormattedValue.ToString();

int p = str.Length;
while (g.MeasureString(str.Substring(0, p).Width, tmpFont) > 710) {
    p--;
}

str = str.SubString(0, p);

At the end of this code, 'str' would contain the longest string shorter than 710 pixels.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.