I have this code to find duplicate values in DataGridView and mark them with different colors.
var rows = dataGridView1.Rows.OfType<DataGridViewRow>().Reverse().Skip(1);
var dupRos = rows.GroupBy(r => r.Cells["Date"].Value.ToString()).Where(g =>
g.Count() > 1).SelectMany(r => r.ToList());
foreach (var r in dupRos)
{
r.DefaultCellStyle.BackColor = Color.Pink;
}
foreach (var r in rows.Except(dupRos))
{
r.DefaultCellStyle.BackColor = Color.Cyan;
}
The code works fine.
I have changed the code so it will write in the second column the word Unique or Duplicate and a counter number for the duplicate cells.
int counter = 1;
var rows = dataGridView1.Rows.OfType<DataGridViewRow>().Reverse().Skip(1);
//ignore the last empty line
var dupRos = rows.GroupBy(r => r.Cells["Date"].Value.ToString()).Where(g =>
g.Count() > 1).SelectMany(r => r.ToList());
foreach (var r in dupRos)
{
r.DefaultCellStyle.BackColor = Color.Pink;
r.Cells["Time"].Value = "Dup" + counter;
counter++;
}
foreach (var r in rows.Except(dupRos))
{
r.DefaultCellStyle.BackColor = Color.Cyan;
r.Cells["Time"].Value = "Unick";
}
My problem is that the counter continues to count for all the duplicate groups and not reset itself every time its start with a different group of duplicate values.
How can I fix it?
Please try this one. If it works you can replace string type for lastDupRowDate with actual date type.
int counter = 1;
var rows = dataGridView1.Rows.OfType<DataGridViewRow>().Reverse().Skip(1);
//ignore the last empty line
var dupRos = rows.GroupBy(r => r.Cells["Date"].Value.ToString()).Where(g =>
g.Count() > 1).SelectMany(r => r.ToList());
string lastDupRowDate = null;
foreach (var r in dupRos)
{
r.DefaultCellStyle.BackColor = Color.Pink;
counter = lastDupRowDate == r.Cells["Date"].Value.ToString() ? count + 1 : 1;
lastDupRowDate = r.Cells["Date"].Value.ToString();
r.Cells["Time"].Value = "Dup" + counter;
}
foreach (var r in rows.Except(dupRos))
{
r.DefaultCellStyle.BackColor = Color.Cyan;
r.Cells["Time"].Value = "Unick";
}
Related
I have xamarin app and I am using SQLite for saving data, if I have 3 rows and delete second row, then data will delete but row will be blank and its still here and problem is, that I need to load one column from every row. I am using for cycle and count to set maximum for it. But count says I have two rows so for cycle load just first and not second because second is on third line and second is blank.
I need to delete blank rows or to discover another solution how to load it. How can i delete blank DB?
Counting algorythm:
public int GetNumberPhotos()
{
var db = new SQLiteConnection(_dbPath);
db.CreateTable<Airplane>();
int count = 0;
if (db.Table<Airplane>().FirstOrDefault(l => l.Id == 1) != null)
count = db.Table<Airplane>().Count();
return count;
}
loading:
public int BetterUniReg()
{
int numberPhotos = GetNumberPhotos();
string[] allReg = new string[numberPhotos];
string[] uniReg = new string[numberPhotos];
int uniRegCnt = 0;
var db = new SQLiteConnection(_dbPath);
//db fill
for (int i = 0; i <= numberPhotos; i++)
{
if (db.Table<Airplane>().FirstOrDefault(b => b.Id == i) != null)
{
var rowData = db.Table<Airplane>().FirstOrDefault(c => c.Id == i);
i--;
allReg[i] = rowData.Registration;
i++;
}
}
Here is delete code:
private async void deleteButton_Clicked(object sender, EventArgs e)
{
var action = await DisplayAlert("Delete", "Do you want delete picture?", "Cancel", "Delete");
if (action)
{
}
else
{
var butto = sender as Button;
var frame = butto.Parent.Parent.Parent.Parent as Frame;
await frame.FadeTo(0, 600);
var button = (Button)sender;
var plane = (Airplane)button.BindingContext;
var db = new SQLiteConnection(_dbPath);
db.Delete<Airplane>(plane.Id);
Refresh();
}
}
I have done walkaround by adding if its last row and its null then do one more cycle.
Here is code:
for (int i = 1; i <= numberPhotos; i++)
{
if (db.Table<Airplane>().FirstOrDefault(c => c.Id == i) != null)
{
var rowData = db.Table<Airplane>().FirstOrDefault(c => c.Id == i);
allReg[regnumber] = rowData.Registration;
regnumber++;
}
if (db.Table<Airplane>().FirstOrDefault(c => c.Id == i) == null && i == numberPhotos)
{
numberPhotos = numberPhotos + 1;
}
}
I did pivot table from normal datatable using linq. However sometimes, i get an errors like;
There is no row at position 5(or any number like 7,8,11 etc..)
-----------------------------------------------------------
object reference not set to an instance of an object
What i didn't understand it, Why sometimes it works very well, with the same conditions like 'sample_time' etc. and why sometimes doesn't work.
Here is the my code to swap rows to columns with linq. Also when i debug, I found the part that throws an error.
var dtExist = dtTopAll.AsEnumerable().Where(l => l.Field<DateTime>("SAMPLE_TIME") >= minDate && l.Field<DateTime>("SAMPLE_TIME") <= maxDate).Any();
if (dtExist == true)
{
var dt = (from dr1 in dtTopAll.AsEnumerable()
where dr1.Field<DateTime>("SAMPLE_TIME") >= minDate && dr1.Field<DateTime>("SAMPLE_TIME") <= maxDate
group dr1 by new
{
WAIT_CLASS = dr1.Field<string>("WAIT_CLASS"),
SAMPLE_TIME = dr1.Field<DateTime>("SAMPLE_TIME")
} into g
select new
{
SAMPLE_TIME = g.Key.SAMPLE_TIME,
WAIT_CLASS = g.Key.WAIT_CLASS,
WAITS = g.Sum(z => z.Field<double>("WAITS") / 100)
}).ToDataTable();
var groups = dt.AsEnumerable().GroupBy(x => x.Field<DateTime>("SAMPLE_TIME")).ToList();
foreach (var group in groups) // From this line to end, throws an error .
{
DataRow newRow = dtPivotCustom.Rows.Add();
newRow[0] = group.Key;
foreach (string item in items)
{
newRow[item] = group.Where(x => x.Field<string>("WAIT_CLASS") == item).Select(x => x.Field<double>("WAITS")).Sum();
}
}
}
So I have my report printing out exactly what I want (almost). Now I just have to get one feature finished. I have a number that is generated and placed into a variable called percentage.
percentage equals the the rounded number of all the licenses in the database that allAttendeeLicenseNos pulls in multiplied by the number that is entered in by the user multiplied .01 to make it a percentage.
So my goal is to see all the attendees, and say okay this person only wants a percentage of them, but it doesn't matter which ones so I am going to grab random rows until the percentage number is there.
Again, please be patient as I am very new to C# and am learning.
var percentage = Math.Round(allAttendeeLicenseNos.Count() * Percentage * 0.01);
var allAttendeeData = _mii.LicenseeRecords.Where(r => allAttendeeLicenseNos.Contains(r.LicenseNumber)).Where(i => i.LicenseStatus.Equals(chosenLicenseStatus)).ToList();
var retval = _mapper.Map<List<DLILicense>, List<RandomAuditViewModel>>(allAttendeeData);
using (var exs = new ExcelPackage())
{
var worksheet = exs.Workbook.Worksheets.Add("RandomAuditReport");
var row = 1;
var col = 1;
var properties = typeof(RandomAuditViewModel).GetProperties();
foreach (var field in properties)
{
worksheet.Cells[row, col].Style.Font.Bold = true;
var displayName = field.GetCustomAttribute<DisplayAttribute>() != null ?
field.GetCustomAttribute<DisplayAttribute>().GetName() :
field.Name;
worksheet.SetValue(row, col, displayName);
col++;
}
col = 1;
row++;
retval.ForEach(i =>
{
var periodOrdinal = _ce.Events
.Where(e => e.Attendees.Select(a => a.LicenseNumber).Contains(i.LicenseNumber))
.Select(e => e.Course.CertificationPeriod)
.OrderBy(p => p.StartDate)
.ToList()
.IndexOf(thePeriod) + 1;
i.MetRequirements = determineIfCeMet(i.LicenseNumber, i.LicenseTypeCode, i.DateOfOriginalLicensure, periodOrdinal, thePeriod.Id, thePeriod.EndDate, thePeriod.Board);
foreach (var field in properties)
{
if (field.GetCustomAttribute<DataTypeAttribute>().DataType.Equals(DataType.Date))
{
var value = ((DateTime)field.GetValue(i));
worksheet.Cells[row, col].Style.Numberformat.Format = "MM/dd/yyyy";
worksheet.Cells[row, col].Formula = "=DATE(" + value.Year + "," + value.Month + "," + value.Day + ")";
}
else worksheet.SetValue(row, col, field.GetValue(i));
col++;
}
col = 1;
row++;
});
return exs.GetAsByteArray();
Something like below?
retval.ForEach(i =>
{
if(retval.IndexOf(i) == percentage)
break;
var periodOrdinal = _ce.Events
.Where(e => e.Attendees.Select(a => a.LicenseNumber).Contains(i.LicenseNumber))
.Select(e => e.Course.CertificationPeriod)
.OrderBy(p => p.StartDate)
.ToList()
.IndexOf(thePeriod) + 1;
i.MetRequirements = determineIfCeMet(i.LicenseNumber, i.LicenseTypeCode, i.DateOfOriginalLicensure, periodOrdinal, thePeriod.Id, thePeriod.EndDate, thePeriod.Board);
foreach (var field in properties)
{
if (field.GetCustomAttribute<DataTypeAttribute>().DataType.Equals(DataType.Date))
{
var value = ((DateTime)field.GetValue(i));
worksheet.Cells[row, col].Style.Numberformat.Format = "MM/dd/yyyy";
worksheet.Cells[row, col].Formula = "=DATE(" + value.Year + "," + value.Month + "," + value.Day + ")";
}
else worksheet.SetValue(row, col, field.GetValue(i));
col++;
}
col = 1;
row++;
})
Where you're using this
if(retval.IndexOf(i) == percentage)
break;
to determine if you've hit the percentage, then breaking out of the ForEach.
I want to subtract from the line with oldest date and where counter > 0, and when it reaches 0 I want to subtract from the next oldest line with the same itemId and do some other updates on other tables.
My question is if there is a better way to do it and if my code has no bad efficiency. If it breaks down, will the code do a rollback? Do I need try/catch? Please if any suggestions, provide with some code.
Here is my code:
public static int insertOrder(Order order)
{
using (var db = new AWarehouseDataClassesDataContext())
{
using (TransactionScope ts = new TransactionScope())
{
tblOrder row = generateOrderToBeInserted(order);
db.tblOrders.InsertOnSubmit(row);
db.SubmitChanges();
order.orderId = row.OrderId;
foreach(var x in order.insertList)
{
int qt = x.qty;
while (qt > 0)
{
var line = db.tblInsertLines.First(r => r.ItemId == x.itemId && r.Counter > 0);
int c = line.Counter;
for (int a = c; a > 0 && qt > 0; a--)
{
line.Counter = line.Counter - 1;
qt--;
}
db.SubmitChanges();
}
tblOrderLine orderLine = generateOrderLine(order, x);
db.tblOrderLines.InsertOnSubmit(orderLine);
db.SubmitChanges();
var item = db.tblItems.Single(i => i.ItemId == x.itemId);
item.Qty = item.Qty - x.qty;
item.LastUpdate = order.orderDate;
item.UpdatedBy = order.user;
db.SubmitChanges();
}
ts.Complete();
return order.orderId;
}
}
}
SO I have a range that I loop through and then add the values to a list. I want to skip the first value because it is a header. How Could I go about doing that? AS it stands I am adding all the value
{
var cellValues = new List<string>();
//var rowsCount = worksheet.UsedRange.Rows.Count;
var columnRange = worksheet.UsedRange.Columns[1];
foreach (var item in columnRange)
{
foreach (var cellValue in item.Value)
{
cellValues.Add(cellValue.ToString());
}
}
return cellValues;
}
You can use for loop instead of foreach:
for (int a = 1; a < columnRange.Count; a++)
{
for (int b = 0; b < columnRange[a].Value.Count; b++)
{
cellValues.Add(columnRange[a].Value[b].ToString());
}
}
or
var cellValues = new List<string>();
//var rowsCount = worksheet.UsedRange.Rows.Count;
var columnRange = worksheet.UsedRange.Columns[1];
bool first = true;
foreach (var item in columnRange)
{
if (first)
{
first = false;
}
else
{
foreach (var cellValue in item.Value)
{
cellValues.Add(cellValue.ToString());
}
}
}
return cellValues;
or Skip() as mentioned by ramin.
You can use LINQ's Skip function.
var cellValues = new List<string>();
//var rowsCount = worksheet.UsedRange.Rows.Count;
var columnRange = worksheet.UsedRange.Columns[1];
foreach (var item in columnRange)
{
foreach (var cellValue in ((object[,])item.Value).Cast<object>().Skip(1))
{
cellValues.Add(cellValue.ToString());
}
}
return cellValues;
But because item.Value is a dynamic type, we need to cast it in order to use an extension method, and because it's a jagged array we need to use Cast<object>().