Как добавить условие «Где не равно» в запрос Linq

#c# #linq #datagridview #casting

Вопрос:

Я использую этот код для cast своего DataGridView , а затем отображаю результаты в другом DataGridView .

В принципе, я получаю некоторые значения int и вычисляю их сумму, а также группирую эти значения GroupBy .

Я показываю результаты в другом DataGridView , например, так:

 datagridview2.DataSource= Su.ToList();
 

Моя проблема в том, что запрос, похоже, останавливается, если в ячейке есть строковое значение.

Я попытался добавить условие « where не», чтобы исключить строки, содержащие строковые значения несколькими различными способами, но не преуспел.

Вот пример условия, которое я пробовал:

 .Where(row => !row.Cells[2].Value.ToString().Equals("example"))
 

Этот код содержится в datagridview_cellvaluechanged методе:

     try
{
    var Su = dataGridView1.Rows.Cast<DataGridViewRow>()
    .Where(row => row.Cells[8].Value != null)
    .Where(row => row.Cells[2].Value != null)
    .GroupBy(row => row.Cells[8].Value.ToString()) 
    .Select(g => new
    {
        Gruppo = g.Key,
        Serie = g.Sum(row => Convert.ToInt32(row.Cells[2].Value)),
        Reps = g.Sum(row => Convert.ToInt32(row.Cells[3].Value) * Convert.ToInt32(row.Cells[2].Value)),
        Percent = (g.Sum(row => Convert.ToDecimal(row.Cells[2].Value)) / Convert.ToDecimal(label15.Text)) * 100
    });
}
catch (FormatException)
{
    //MessageBox.Show("Formato non corretto");
}
 

Вот как должно выглядеть представление DataGrid, если оно будет успешным; dgv1:

 column 1 | column 2 |column 3
  2          3        group1
  3          5        group1
  4          6        group2
  3          4        group3
 

И я вижу это в результате на dgv2:

     column 1 | column 2 |column 3
      5          8        group1
      4          6        group2
      3          4        group3
 

Но если я добавлю строковое значение в столбец 2, как это:

 column 1 | column 2 |column 3
  2          3        group1
  3          5        group1
  4        string     group2
  3          4        group3
 

Затем я вижу это в результате на dgv2:

 column 1 | column 2 |column 3
  5          8        group1
 

Комментарии:

1. Что вы подразумеваете под «затем запрос прекращается»?

2. @faso Я имею в виду, что приведение останавливается на строке, в которой найдена строка. Так, например, если в datagridview1 у меня 5 строк, а в строке 4 есть строка, приведение останавливается на этой строке. Даже если я изменю некоторые значения до или после этой строки (которые имеют строковое значение), я не увижу никаких изменений в dgv, где я отображаю результат

3. Преобразовать. ToInt32 не будет рад, если у вас есть значение для ячеек[2].значение, которое нельзя преобразовать в целое число. Я думаю, именно поэтому вы пытаетесь проверить ячейки[2].значение. Если вы ищете что-нибудь, что можно преобразовать в целое число, вы можете попробовать (строка => int. Попробуйте проанализировать(строка.Ячейки[2].Значение, out_)), который должен выбрать все строки, которые могут быть преобразованы в целое число

4. @MarkRabjohn Я отредактировал вопрос, чтобы лучше объяснить. Я попробовал ваше предложение, но я получаю эту ошибку: «невозможно преобразовать объект в строку». Куда я должен его положить?

5. сначала вы должны решить, что должно произойти, если указано недопустимое значение. Должно ли это просто прекратиться? Должен ли он игнорировать весь ряд?

Ответ №1:

Хотя я все еще не совсем уверен, в чем проблема, я попытаюсь ответить на ваш вопрос.

Во-первых, если вы не на 100% уверены, что конкретная ячейка содержит значение Int, вам не следует просто слепо преобразовывать ее.

Есть способы проверить, является ли это int, прежде чем конвертировать его. Один из способов заключается в следующем:

 
    try
{
    var Su = dataGridView1.Rows.Cast<DataGridViewRow>()
    .Where(row => row.Cells[8].Value != null)
    .Where(row => row.Cells[2].Value != null)
    .GroupBy(row => row.Cells[8].Value.ToString()) 
    .Select(g => new
    {
        Gruppo = g.Key,
        Serie = g.Sum(row => {
            if(row.Cells[2].Value is int rowInteger)
                return rowInteger;

            // if it is not an integer then try to convert
            // return a default value (in this case -1) if it can't be converted
            else
            {
                try
                {
                    return Convert.ToInt32(row)
                }
                catch(Exception)
                {
                    return -1;
                }
            }
        },
        Reps = g.Sum(row => Convert.ToInt32(row.Cells[3].Value) * Convert.ToInt32(row.Cells[2].Value)),
        Percent = (g.Sum(row => Convert.ToDecimal(row.Cells[2].Value)) / Convert.ToDecimal(label15.Text)) * 100
    });
}
catch (FormatException)
{
    //MessageBox.Show("Formato non corretto");
}

 

Это позволит убедиться, что все строки сохранены, но рассчитываются только те строки, которые являются допустимыми.

Более простой подход, который не сохранит исходное количество строк, заключается в том, чтобы проверить, является ли значение ячейки значением int или может быть преобразовано в значение int, чтобы добавить следующее Where утверждение:

 Where(row => row.Cells[2].Value is int || int.TryParse((row.Cells[2].Value as string), out var result))
 

Обратите внимание, что вы фактически анализируете значение на каждой итерации и отбрасываете результат, это, конечно, далеко не оптимизировано, но даст вам желаемый результат.

Комментарии:

1. Второй пример выдает мне эту ошибку: «невозможно преобразовать из «объекта» в «строку», и если я добавлю строку после строки. Ячейки[2].Значение Я не вижу ошибки, но запрос не работает (он останавливается, как и раньше). Я не уверен, куда добавить код первого примера. Оно заканчивается на «если(вар» ?

2. замените свою Serie = g.Sum функцию на первый пример.

3. @Gabriele Я отредактировал свой ответ, чтобы показать, куда он должен идти. Я изменил второй пример, чтобы также преобразовать объект в строку. Вы можете попробовать второй пример еще раз.

4. Идеально! теперь это работает нормально!! Большое спасибо!