错误:在DataGridView中计算多个列时,输入字符串不是正确的格式

发布于 2025-01-29 04:53:19 字数 3940 浏览 5 评论 0原文

我想计算DataGridView中3个单元格的值

计算:

sdi =(((结果 - 平均) / sd)

我尝试了以下代码:

private void dgvResult_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            string result = dgvResult.CurrentRow.Cells[5].Value.ToString();
            string mean = dgvResult.CurrentRow.Cells[6].Value.ToString();
            string sd = dgvResult.CurrentRow.Cells[7].Value.ToString();
           
            dgvResult.CurrentRow.Cells[16].Value = (Convert.ToDecimal(result) - Convert.ToDecimal(mean)) ;
          //  dgvResult.CurrentRow.Cells[8].Value = (Convert.ToDecimal(dgvResult.CurrentRow.Cells[16].Value.ToString()) / Convert.ToDecimal(sd));
                        
        }

此代码行正确工作并计算第一部分:

 dgvResult.CurrentRow.Cells[16].Value = (Convert.ToDecimal(result) - Convert.ToDecimal(mean)) ;

result - mean 

但是当添加最后一行代码

时,出现了 错误 但是,当我在平均字段中删除最后一行的代码和键入数字时,它计算了

dgvResult.CurrentRow.Cells[8].Value = (Convert.ToDecimal(dgvResult.CurrentRow.Cells[16].Value.ToString()) / Convert.ToDecimal(sd));

如何解决此错误的值?

我通过使用搜索按钮在单击按钮时使用搜索按钮填充了数据 这是代码:

  private void btnSearch_Click(object sender, EventArgs e)
        {


            string sql = @" SELECT samples.name as 'Sample No',
       [program_id] as 'Program',
       RESULTS.TESTID,
       testname as 'Test',
       TestsUnits.UnitName as 'Unit',
       results.RESULT as 'Result',
       RESULTS.mean as 'Mean',
       RESULTS.sd as 'Standard Deviation',
       RESULTS.sdi as 'Standard Deviation Index',
       results.low_limit as 'Low Limit' , 
       RESULTS.high_limit as 'High Limit' , 
       RESULTS.perf_id as 'Performance',
       results.APPROVED_DATE as 'Result Date',
       Machines.Machine_name,
       results.[Machine_id],
       sys_users.user_full_name,
       '' as 'RM'

  FROM [dbo].[RESULTS]
  inner join labtests on RESULTS.testid = labtests.testid 
  inner join machines on RESULTS.Machine_id = Machines.Machine_id 
  inner join TestsUnits on labtests.UnitId = TestsUnits.UnitId
  inner join sys_users on results.custid = sys_users.user_id
  inner join samples on results.sample_id = samples.id 
  
  where  1=1 ";

            string condition = "";


            DateTime fromDate;
            DateTime toDate;


            if (!DateTime.TryParse(dtFromDate.Value.ToString(), out fromDate))
            {
                System.Windows.Forms.MessageBox.Show("Invalid From Date");
            }
            else if (!DateTime.TryParse(dtToDate.Value.ToString(), out toDate))
            {
                System.Windows.Forms.MessageBox.Show("Invalid to Date");
            }
            else
            {
                condition += " and cast(results.APPROVED_DATE as date) between '" + fromDate + "' and '" + toDate + "'";
            }


            if (textCustId.Text != "")
            {
                condition += " and RESULTS.custid = '" + textCustId.Text + "'";
            }

            if (comboProgram.Text != "")
            {
                condition += " and results.program_id = '" + comboProgram.SelectedValue + "'";
            }


            DataTable dt = data.fireDatatable(string.Format(sql + condition));
            dgvResult.DataSource = dt;
            dgvResult.Refresh();
            //  dgvResult.DataSource = test.GET_RESULTS(Convert.ToInt32(comboProgram.SelectedValue),Convert.ToDateTime(dtFromDate.Text.ToString()),Convert.ToInt32(textCustId.Text));

            dgvResult.Columns["Performance"].DefaultCellStyle.NullValue = "1";
          //  dgvResult.Columns["Standard Deviation"].DefaultCellStyle.NullValue = "1";
           // dgvResult.Columns["Mean"].DefaultCellStyle.NullValue = "1";
           // dgvResult.Columns["RM"].DefaultCellStyle.NullValue = "1";

        }

I want to calculate the value of 3 cells in DATAGRIDVIEW

the calculation :

SDI = ((result - mean ) / SD)

I tried the following code :

private void dgvResult_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            string result = dgvResult.CurrentRow.Cells[5].Value.ToString();
            string mean = dgvResult.CurrentRow.Cells[6].Value.ToString();
            string sd = dgvResult.CurrentRow.Cells[7].Value.ToString();
           
            dgvResult.CurrentRow.Cells[16].Value = (Convert.ToDecimal(result) - Convert.ToDecimal(mean)) ;
          //  dgvResult.CurrentRow.Cells[8].Value = (Convert.ToDecimal(dgvResult.CurrentRow.Cells[16].Value.ToString()) / Convert.ToDecimal(sd));
                        
        }

This line of code working correct and calculate first part :

 dgvResult.CurrentRow.Cells[16].Value = (Convert.ToDecimal(result) - Convert.ToDecimal(mean)) ;

result - mean 

enter image description here

But the error appeared when added the last line of code

when type the number in the mean cell error appeared
but when i remove the last line of code and type numbers in the mean field its calculating the value

dgvResult.CurrentRow.Cells[8].Value = (Convert.ToDecimal(dgvResult.CurrentRow.Cells[16].Value.ToString()) / Convert.ToDecimal(sd));

How to solve this error please ?

I populated the data in grid by using search button when click the button
this is the code :

  private void btnSearch_Click(object sender, EventArgs e)
        {


            string sql = @" SELECT samples.name as 'Sample No',
       [program_id] as 'Program',
       RESULTS.TESTID,
       testname as 'Test',
       TestsUnits.UnitName as 'Unit',
       results.RESULT as 'Result',
       RESULTS.mean as 'Mean',
       RESULTS.sd as 'Standard Deviation',
       RESULTS.sdi as 'Standard Deviation Index',
       results.low_limit as 'Low Limit' , 
       RESULTS.high_limit as 'High Limit' , 
       RESULTS.perf_id as 'Performance',
       results.APPROVED_DATE as 'Result Date',
       Machines.Machine_name,
       results.[Machine_id],
       sys_users.user_full_name,
       '' as 'RM'

  FROM [dbo].[RESULTS]
  inner join labtests on RESULTS.testid = labtests.testid 
  inner join machines on RESULTS.Machine_id = Machines.Machine_id 
  inner join TestsUnits on labtests.UnitId = TestsUnits.UnitId
  inner join sys_users on results.custid = sys_users.user_id
  inner join samples on results.sample_id = samples.id 
  
  where  1=1 ";

            string condition = "";


            DateTime fromDate;
            DateTime toDate;


            if (!DateTime.TryParse(dtFromDate.Value.ToString(), out fromDate))
            {
                System.Windows.Forms.MessageBox.Show("Invalid From Date");
            }
            else if (!DateTime.TryParse(dtToDate.Value.ToString(), out toDate))
            {
                System.Windows.Forms.MessageBox.Show("Invalid to Date");
            }
            else
            {
                condition += " and cast(results.APPROVED_DATE as date) between '" + fromDate + "' and '" + toDate + "'";
            }


            if (textCustId.Text != "")
            {
                condition += " and RESULTS.custid = '" + textCustId.Text + "'";
            }

            if (comboProgram.Text != "")
            {
                condition += " and results.program_id = '" + comboProgram.SelectedValue + "'";
            }


            DataTable dt = data.fireDatatable(string.Format(sql + condition));
            dgvResult.DataSource = dt;
            dgvResult.Refresh();
            //  dgvResult.DataSource = test.GET_RESULTS(Convert.ToInt32(comboProgram.SelectedValue),Convert.ToDateTime(dtFromDate.Text.ToString()),Convert.ToInt32(textCustId.Text));

            dgvResult.Columns["Performance"].DefaultCellStyle.NullValue = "1";
          //  dgvResult.Columns["Standard Deviation"].DefaultCellStyle.NullValue = "1";
           // dgvResult.Columns["Mean"].DefaultCellStyle.NullValue = "1";
           // dgvResult.Columns["RM"].DefaultCellStyle.NullValue = "1";

        }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

浅唱々樱花落 2025-02-05 04:53:20

目前尚不清楚网格如何用数据填充。但是,当您要基于同一行中的其他单元格中“计算”网格单元格中的值时,应该考虑使用dataTable和a expression 列列或计算SDI值的类班级的财产。

您可以按照自己的使用,并使用一些从网格到“手动”计算值的事件,但是有一种更简单的方法如上所述。在下面的示例中,我将DataTable与表达列使用。这还将将网格列类型设置为小数

使用您的示例,将有一个DECIMAL列,用于“结果”,“均值”和“标准删除”值。然后,我们可以将“表达式”列添加到dataTable中,看起来像…。

dt.Columns.Add("SDI", typeof(decimal), "(Result - Mean) / StandardDeviation");

“表达式”是最后一个参数…
“(结果 - 平均值) /标准驱动”,

结果是该行上的结果单元格中的值,而相同的列则适用于其他列名“平均值”和“标准驱动”。

由于这些列是十进制列,我们可以限制值的转换/解析。关于这里唯一的问题是,如果“标准驱动”单元格值为零(0),则网格将抛出一个明显的dataError,因为这将导致零表达式的鸿沟,这显然会失败。因此,我们将不得不寻找这个。

为了提供帮助,我建议我们将网格cellValidating事件连接。进行更改后,当用户试图离开单元时,此事件会发射。如果我们查看“ StandardDeviation”单元格中的值并检查值是否为零,则可以弹出一个消息框并注意,该值不允许零作为该单元格中的值。然后将单元格还原回其原始值并取消编辑。这应该有助于避免可能划分为零的情况。

接下来,如果用户开始使用网格的新行(如果可用)使用网格defaultValueseed事件,我们还可以通过设置一些有效的默认值来帮助用户。

此外,我们还可以将单元格键>键>事件连接起来,以便仅允许数字和一个小数点键入单元格。这将阻止用户将alpha字符键入单元格。注意:即使我们阻止用户“键入”无效的字符……用户仍然可以“粘贴”无效的值。幸运的是,cellvalidating事件将为我们抓住这一点。

设置事件是使用两个事件完成的。第一个是网格编辑controlshowing事件。当此事件启动时,单元格将进入“编辑”模式。在这种情况下,我们要做的就是将单元格投入常规文本框单元格,然后订阅文本框键>键事件。然后,当用户将字符键入单元格时,事件将发射,我们显然会检查并忽略任何无效的字符。

以下是上述内容的示例。创建一个新的Winforms解决方案,然后将DataGridView删除到表单上,以查看此操作。

DataTable GridDT;
TextBox CurrentEditedCell;

public Form1() {
  InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e) {
  GridDT = GetGridDT();
  dataGridView1.DataSource = GridDT;
}


private DataTable GetGridDT() {
  DataTable dt = new DataTable();
  dt.Columns.Add("Result", typeof(decimal));
  dt.Columns.Add("Mean", typeof(decimal));
  dt.Columns.Add("StandardDeviation", typeof(decimal));
  dt.Columns.Add("SDI", typeof(decimal), "(Result - Mean) / StandardDeviation");
  dt.Rows.Add(1, 1, 1);
  dt.Rows.Add(2, 1, 1);
  dt.Rows.Add(3, 1, 1);
  dt.Rows.Add(4, 1, 1);
  dt.Rows.Add(5, 1, 1);
  dt.Rows.Add(6, 1, 1);
  return dt;
}


private void dataGridView1_DefaultValuesNeeded(object sender, DataGridViewRowEventArgs e) {
  e.Row.Cells["Result"].Value = "1";
  e.Row.Cells["Mean"].Value = "1";
  e.Row.Cells["StandardDeviation"].Value = "1";
}


private void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e) {
  if (dataGridView1.Columns[e.ColumnIndex].Name == "StandardDeviation") {
    string userInput = dataGridView1.Rows[e.RowIndex].Cells["StandardDeviation"].EditedFormattedValue.ToString();
    if (!decimal.TryParse(userInput, out decimal dValue) || dValue == 0.0M) {
      dataGridView1.CancelEdit();
      MessageBox.Show("Standard Deviation can not be zero and must be a valid decimal number");
    }
  }
}


private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) {
  if (dataGridView1.Columns[dataGridView1.CurrentCell.ColumnIndex].Name == "StandardDeviation") {
    CurrentEditedCell = (TextBox)e.Control;
    if (CurrentEditedCell != null) {
      CurrentEditedCell.KeyPress -= new KeyPressEventHandler(DecimalNumbersOnlyCell_KeyPress);
      CurrentEditedCell.KeyPress += new KeyPressEventHandler(DecimalNumbersOnlyCell_KeyPress);
    }
  }
}

private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e) {
  if (CurrentEditedCell != null) {
    CurrentEditedCell.KeyPress -= new KeyPressEventHandler(DecimalNumbersOnlyCell_KeyPress);
  }
}


private void DecimalNumbersOnlyCell_KeyPress(object sender, KeyPressEventArgs e) {
  if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) && e.KeyChar != '.') {
    e.Handled = true;
  }
  if (e.KeyChar == '.' && (sender as TextBox).Text.IndexOf('.') > -1) {
    e.Handled = true;
  }
}

我希望这有意义并有所帮助。

It is unclear how the grid is populated with data. However, when you want to “calculate” a value in a grid cell based on other cells in the same row, then, you should consider using a DataTable and a Expression column OR a Class that computes the SDI value as a property of the Class.

You could do as you have and use some events from the grid to “manually” compute the value, however there is an easier way as described above. In the example below I used a DataTable with an expression column. This will also set the grids column types to decimals.

Using your example, there would be a decimal column for the “Result”, “Mean” and “StandardDeviation” values. Then we could add the “expression” column to the DataTable and it may look something like….

dt.Columns.Add("SDI", typeof(decimal), "(Result - Mean) / StandardDeviation");

The “expression” is the last parameter…
"(Result - Mean) / StandardDeviation"

Where Result is the value in the Results cell on that row and the same applies to the other column names “Mean” and “StandardDeviation”.

Since those columns are decimal columns we can limit the conversion/parsing of the values. About the only issue here is that if the “StandardDeviation” cell value is zero (0) then the grid will throw an obvious DataError since this would lead to a divide by zero expression which will obviously fail. So, we are going to have to look for this.

To help, I suggest we wire up the grids CellValidating event. This event fires when the user tries to leave a cell after making changes. If we look at the value in the “StandardDeviation” cell and check to see if the value is zero, then we could pop up a message box and note that a zero is not allowed as a value in that cell. Then revert the cell back to its original value and cancel the edit. This should help avoiding the possible divide by zero situations.

Next, we could also help the user by setting some valid default values if the user starts typing into the grid’s new row (if available) using the grids DefaultValuesNeeded event.

And further we could also wire up the cells KeyPress event to only allow for numbers and a single decimal point to be typed into the cell. This will prevent the user from typing alpha characters into the cell. NOTE: even though we prevent the user from “typing” invalid characters… the user can still “paste” invalid values. Fortunately, the CellValidating event will catch this for us.

Setting up the KeyPress event is accomplished using two events. The first is the grids EditingControlShowing event. When this event fires, the cell is going into “edit” mode. In this case, all we want to do is cast the cell to a regular TextBox cell and subscribe to the text boxes KeyPress event. The KeyPress event will then fire when the user types characters into the cell, which we will obviously check and ignore any invalid characters.

Below is an example of what is described above. Create a new winforms solution and drop a DataGridView onto the form to see this in action.

DataTable GridDT;
TextBox CurrentEditedCell;

public Form1() {
  InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e) {
  GridDT = GetGridDT();
  dataGridView1.DataSource = GridDT;
}


private DataTable GetGridDT() {
  DataTable dt = new DataTable();
  dt.Columns.Add("Result", typeof(decimal));
  dt.Columns.Add("Mean", typeof(decimal));
  dt.Columns.Add("StandardDeviation", typeof(decimal));
  dt.Columns.Add("SDI", typeof(decimal), "(Result - Mean) / StandardDeviation");
  dt.Rows.Add(1, 1, 1);
  dt.Rows.Add(2, 1, 1);
  dt.Rows.Add(3, 1, 1);
  dt.Rows.Add(4, 1, 1);
  dt.Rows.Add(5, 1, 1);
  dt.Rows.Add(6, 1, 1);
  return dt;
}


private void dataGridView1_DefaultValuesNeeded(object sender, DataGridViewRowEventArgs e) {
  e.Row.Cells["Result"].Value = "1";
  e.Row.Cells["Mean"].Value = "1";
  e.Row.Cells["StandardDeviation"].Value = "1";
}


private void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e) {
  if (dataGridView1.Columns[e.ColumnIndex].Name == "StandardDeviation") {
    string userInput = dataGridView1.Rows[e.RowIndex].Cells["StandardDeviation"].EditedFormattedValue.ToString();
    if (!decimal.TryParse(userInput, out decimal dValue) || dValue == 0.0M) {
      dataGridView1.CancelEdit();
      MessageBox.Show("Standard Deviation can not be zero and must be a valid decimal number");
    }
  }
}


private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) {
  if (dataGridView1.Columns[dataGridView1.CurrentCell.ColumnIndex].Name == "StandardDeviation") {
    CurrentEditedCell = (TextBox)e.Control;
    if (CurrentEditedCell != null) {
      CurrentEditedCell.KeyPress -= new KeyPressEventHandler(DecimalNumbersOnlyCell_KeyPress);
      CurrentEditedCell.KeyPress += new KeyPressEventHandler(DecimalNumbersOnlyCell_KeyPress);
    }
  }
}

private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e) {
  if (CurrentEditedCell != null) {
    CurrentEditedCell.KeyPress -= new KeyPressEventHandler(DecimalNumbersOnlyCell_KeyPress);
  }
}


private void DecimalNumbersOnlyCell_KeyPress(object sender, KeyPressEventArgs e) {
  if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) && e.KeyChar != '.') {
    e.Handled = true;
  }
  if (e.KeyChar == '.' && (sender as TextBox).Text.IndexOf('.') > -1) {
    e.Handled = true;
  }
}

I hope this makes sense and helps.

没有你我更好 2025-02-05 04:53:20

由于原因不同,可能会发生此错误,但我建议您:

  • 检查输入字符串是否可以通过功能接受。
  • 即使输入字符串可以接受转换,您要转换的十进制也可以是太大或太小,或者精确的问题可能是问题,请检查您是否超出了限制。

我还建议使用,它将使您的代码更耐用。

This error can occur because of different reasons, but I suggest you to:

  • Check if the input strings are acceptable by the function.
  • Even if the input strings are acceptable for conversion, the decimal you are trying to convert could be too big or too small, or precisions could be the problem, check if you exceed the limits.

I also suggest using Decimal.TryParse, it'll make your code more durable.

圈圈圆圆圈圈 2025-02-05 04:53:20

使用LINQ

foreach (DataGridViewRow dgvrow in dataGridView1.Rows)
        {
            //Set the column indexes what you want to sum
            double result = ((Convert.ToDouble(dgvrow.Cells[0].Value) - Convert.ToDouble(dgvrow.Cells[1].Value)) / Convert.ToDouble(dgvrow.Cells[2].Value));

            dgvrow.Cells.Cast<DataGridViewCell>()
            .Select(s => s).ToList<DataGridViewCell>()
            .ForEach(f => 
            {
                if (f.ColumnIndex == 3 && f.Value != null) //column index where to place your sum
                {
                    //have negative results
                    f.Value = Math.Round(result, 2)
                    .ToString();
                    
                    //negative results turn to 0
                    //f.Value = Math.Round(((result < 0) ? 0 : result), 2)
                    //.ToString();
                }
            });
        }

有两种结果,具有负面。这取决于您将要使用的东西。我希望它有帮助!

Using LINQ

foreach (DataGridViewRow dgvrow in dataGridView1.Rows)
        {
            //Set the column indexes what you want to sum
            double result = ((Convert.ToDouble(dgvrow.Cells[0].Value) - Convert.ToDouble(dgvrow.Cells[1].Value)) / Convert.ToDouble(dgvrow.Cells[2].Value));

            dgvrow.Cells.Cast<DataGridViewCell>()
            .Select(s => s).ToList<DataGridViewCell>()
            .ForEach(f => 
            {
                if (f.ColumnIndex == 3 && f.Value != null) //column index where to place your sum
                {
                    //have negative results
                    f.Value = Math.Round(result, 2)
                    .ToString();
                    
                    //negative results turn to 0
                    //f.Value = Math.Round(((result < 0) ? 0 : result), 2)
                    //.ToString();
                }
            });
        }

There are 2 types of result, having negative or not. It's up to you what you're going to use. I hope it helps!

安穩 2025-02-05 04:53:20

首先,您应该确保您的字符串确实可转换为十进制。看来SD无法转换为十进制。

要检查此问题,您可以使用DECIMAL.TRYPARSE。即

Decimal n;

(Convert.ToDecimal(dgvResult.CurrentRow.Cells[16].Value.ToString()) / Decimal.TryParse(sd, out n) ? n : 1 /* Default Value */)

,还有一件事最好检查sd在分配之前,它不应为零(我将默认值设置为1)。

请检查 https:https:https:https:https: //www.educative.io/edpresso/how-to-to-convert-a-string-to-a-decimal-in-c-sharp ,有关decimal.tryparse的更多信息。

You should first make sure that your string is really convertible to decimal. It seems that sd is not convertible to decimal.

To check this, you can use Decimal.TryParse. i.e

Decimal n;

(Convert.ToDecimal(dgvResult.CurrentRow.Cells[16].Value.ToString()) / Decimal.TryParse(sd, out n) ? n : 1 /* Default Value */)

And one more thing it's better to check sd before dividing, it should not be ZERO (I've set default value to 1).

Kindly check https://www.educative.io/edpresso/how-to-convert-a-string-to-a-decimal-in-c-sharp, for more information about Decimal.TryParse.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文