#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. Идеально! теперь это работает нормально!! Большое спасибо!