I am working on google spreadsheets, user connect its spreadsheet, and the system pushed data to user connected spreadsheet at day end.
here are spreadsheet columns
The sequence of columns is
"PatientName","DOB","StripeId","Card","ChargeCreated","Status","Amount"
here is the code is used
var GoogleSpreadSheetData = db.GoogleSpreadSheetDatas
.ToList()
.Select(x => new List<string>{
x.PatientName.Trim(),
x.DOB.Trim(),
x.StripeId.Trim(),
x.Card.Trim(),
x.ChargeCreated.Trim(),
x.Status.Trim(),
x.Amount.Trim(),
})
.ToList();
the sequence of google spread sheet columns and query return is same sequence like
"PatientName","DOB","StripeId","Card","ChargeCreated","Status","Amount"
and data will mapped on exact column in spread sheet Reference image.
if user changes sequence of columns like this image, replaced PatientName column to DOB. when next time data push to spreadsheet PatientName data is pushed in the DOB column and vice versa.
Before pushing data to the spreadsheet, firstly I call google API(using Developer Metadata) to get a sequence of that spreadsheet, I got the updated column sequence in response.
My question is
How can I change the sequence on query select?
Can I rearrange the list on query select or after?
Please help to solve this problem.
Thank you.
Assuming your MetaData query provides you with a List<string> of column names:
List<string> spreadsheetColSeq;
Then you can query the database to retrieve the rows:
var dbData = db.GoogleSpreadSheetDatas
.Select(x => new List<string> {
x.PatientName.Trim(),
x.DOB.Trim(),
x.StripeId.Trim(),
x.Card.Trim(),
x.ChargeCreated.Trim(),
x.Status.Trim(),
x.Amount.Trim(),
})
.ToList();
And then you can create a mapping from the query order to the spreadsheet order and reorder the each row's List<string> to match the new order:
var origSeq = new[] { "PatientName", "DOB", "StripeId", "Card", "ChargeCreated", "Status", "Amount" };
var colOrder = spreadsheetColSeq
.Select(colName => Array.IndexOf(origSeq, colName))
.ToList();
var GoogleSpreadSheetData = dbData
.Select(row => colOrder.Select(idx => row[idx]).ToList())
.ToList();
Note: If columns may be deleted, this will crash since Array.IndexOf will return -1 for a missing value. You could filter colOrder by adding .Where(idx => idx > -1) before the ToList() to skip missing columns.
Related
I have a one generic datatable which contains any number of columns and any number of rows, which i want to update at once through linq query if a row's column contains a quote (").
e.g.
A quick brown "fox" jumps over the lazy "dog"
I want this to be
A quick brown fox jumps over the lazy dog
Snapshot
I have tried
var rows = dt.AsEnumerable().Where(r => r.Field<string>("display").Contains("\""));
In this case column name is "display" is the column name, which I don't want to mention. Because this is not fixed as this quote (") could be in any column's row.
My problem is that I cannot find that specific columns for which I have tried this. It will give me all columns but not that specific columns.
string[] columnNames = dt.Columns.Cast<DataColumn>().Select(x => x.ColumnName).ToArray();
Any hints? I don't want this to be done with traditional foreach loop over columns and then on rows and replace text then.
You can do something like this:
//get columns which are of type "string" and then get their names
var columnNames = dt.Columns.OfType<DataColumn>().Where(c => c.DataType == typeof(string)).Select(c => c.ColumnName).ToList();
//get all dataTable's rows and with each column name (from previous step) get row's value of that column
// and if that value contains double qoutes, replace it with empty char :)
dt.AsEnumerable().ToList().ForEach(
r => columnNames.ForEach(c => r.SetField<string>(c, r.Field<string>(c).Replace("\"", ""))));
//or, as one-liner :)
dt.AsEnumerable().ToList()
.ForEach(r => dt.Columns.OfType<DataColumn>()
.Where(c => c.DataType == typeof(string))
.Select(c => c.ColumnName).ToList()
.ForEach(c => r.SetField<string>(c, r.Field<string>(c).Replace("\"", ""))));
I'm guessing that could be achieved a bit more simplier, but this can give you an idea :)
This is another way to get a list of all cells that contain a quote in your dataTable.
You can then do a ForEach on the result to get rid of the quotes.
var result = (from DataColumn column in table.Columns
let columnName = column.ColumnName
from DataRow row in table.AsEnumerable()
where row[columnName].ToString().Contains("\"")
select row[columnName]).ToList();
I use following code to combine(using comma) input records which have same Symptom_Type. The problem is now I can combine and insert records into DB, but how to remove those uncombined records from "nPG_Chemical.NPG_Chemical_Symptoms"?
var SymptomType = nPG_Chemical.NPG_Chemical_Symptoms.GroupBy(Type => Type.Symptom_Type);
foreach (var type in SymptomType)
{
var text = String.Join(", ", type.Select(x => x.Symptom_Text.ToString()).ToArray());
nPG_Chemical.NPG_Chemical_Symptoms.Add(new NPG_Chemical_Symptom
{
Symptom_Type = type.Key.ToString(),
Symptom_Text = text
});
db.SaveChanges();
}
I'm not sure if I understood your requirement correctly. It seems like all you want is
After you have combined records by Symptom_Type, and inserted them into database, you want to delete the original records.
If that's what you want, you can do this
db.YourTable
.RemoveRange(db.YourTable
.Where(x => !x.Symptom_Text.Contains(",")));
For each base record find all records where base.Symptom_Type contains Symptom_Type from currently verifying record.
Hi I am currently working on a project using asp.net MVC 5, I have come across an issue with the query where I cannot seem to count the all my rows and group them into a their related catagories
My SQL Statement Looks like this and it returns a count of orders which is grouped by the status.
SELECT COUNT(OrderID) as 'Orders' ,order_status FROM [ORDER]
group by order_status;
I'm looking to populate my Chart by using JSON currently in my controller I have the return Json
public ActionResult GetChart()
{
var orders = db.Order.GroupBy(i => i.order_status).Select(i => new { Amount = i.Sum(b => b.OrderID), Name = i.Key }).OrderBy(i => i.Amount).Count();
return Json(orders, JsonRequestBehavior.AllowGet);
}
The chart draws well although there are no bars which are being displayed on the chart. Please help me out
Thanks in advance .
*I am still a beginner at this please bear in mind
You have a call to Count() at the end of your query, which simply returns the number of elements in the IEnumerable. The type of your orders is actually int right now. If you remove the call, you will return the actual data, not just the amount of elements.
var orders = db.Order.GroupBy(i => i.order_status).Select(i => new { Amount = i.Sum(b => b.OrderID), Name = i.Key }).OrderBy(i => i.Amount);
The count of the orderIds is done in the Sum call, no need to count again.
I'm getting a collection of records in a DataTable and binding it to a grid control. Before binding it I'm sorting the data based on few conditions. For brevity I'm will explain a test scenario.
I've two fields Category and Country. I want to first sort the records based on category and then by country. But the catch here is I want to push all the empty category values to the end and then sort based on the alphabetical order.
For that I'm doing -
var rows = dt.AsEnumerable()
.OrderBy(r => string.IsNullOrEmpty(Convert.ToString(r["Category"]))) //push empty values to bottom
.ThenBy(r => Convert.ToString(r["Category"]))
.ThenBy(r => Convert.ToString(r["Country"]))
But now, the fields based on which I need to sort, is dynamic which I'm having in an array.
How can I use the lambda expressions to order the records dynamically based on the fields? (pushing the empty values to the end)
I assume the array you're talking about is an array of strings.
var columns = new string[] { "Category", "Country" };
var rows = dt.AsEnumerable().OrderBy(x => 0);
foreach(var columnName in columns)
{
rows = rows.ThenBy(r => string.IsNullOrEmpty(Convert.ToString(r[category])))
.ThenBy(r => Convert.ToString(r[category]));
}
Because LINQ uses deferred execution, your query will not be evaluated until you actually need results. That's why you can construct it in multiple steps like in the example above.
I have a datatable that I have grouped as follows:
var result = from data in view.AsEnumerable()
group data by new {Group = data.Field<string>("group_no")}
into grp
select new
{
Group = grp.Key.Group,
PRAS = grp.Average(c => Convert.ToDouble(c.Field<string>("pAKT Total")))
};
Now, the average function is also counting the empty cells in it's calculation. For example, there are 10 cells with only 5 populated with values. I want the average to be the sum of the 5 values divided by 5.
How can I ensure that it does what I want?
Thanks.
Maybe something like this:
PRAS = grp.Select(row => row.Field<string>("pAKT Total"))
.Where(s => !String.IsNullOrEmpty(s))
.Select(Convert.ToDouble)
.Average()
To my knowledge, that's not possible with the Average method.
You can however achieve the result you want to, with the following substitute:
PRAS = grp.Sum(c => Convert.ToDouble(c.Field<string>("pAKT Total"))) / grp.Count(c => !c.IsDBNull)
This only makes sense, when you want to select the "empty" rows in the group, but just don't want to include them in your average. If you don't need the "empty" rows at all, don't select them in the first place, i.e. add a where clause that excludes them.