I just started working on csvhelper library today and new help with how to add entries in the next column. Say I have three datasets composed of (ABC Office, Sarah's office and Brian's office) These are Building names...For each building I have TaskName, PointName, DataName and then Local and Value data of rows.
Each building will have 2 columns, There can be 10 or 20 buildings (Dynamic)
and each building can be 1000's of data rows below local and Value row.
I have the following code
using (var writer = new StreamWriter(filePath))
using (var csv1 = new CsvWriter(writer))
{
foreach (var point in this.Points)
{
csv1.WriteField(point.BuildingName);
csv1.WriteField(" ");
csv1.NextRecord();
csv1.WriteField(point.TaskName);
csv1.WriteField(" ");
csv1.NextRecord();
csv1.WriteField(point.PointName);
csv1.WriteField(" ");
csv1.NextRecord();
csv1.WriteField(point.DataName);
csv1.WriteField(" ");
csv1.NextRecord();
}
}
The problem is that it puts all the points information in first column and then ' ' in the second field.
What I need is something like this eventually.
After the point information added, I want to be able to append a data set of Local and Value column under each point.
Is this formatting in CSV possible using CSVHelper?
Update:
So far I have gotten this far.. Using String builder added first 5 rows of data.
Now I need to be able to append a dataset of columns Local and Value under each Office. Is there a way in CSVHeper library that I can specify where to append the dataset. First 5 rows I am getting like this.
var row1 = new StringBuilder();
var row2 = new StringBuilder();
var row3 = new StringBuilder();
var row4 = new StringBuilder();
foreach (var point in this.Points)
{
row1.Append($"{ point.BuildingName},,");
row2.Append($"{point.TaskName},,");
row3.Append($"{ point.PointName},,");
row4.Append($"{ point.DataName},,");
}
//StreamWriter sw = new StreamWriter("filePath", true);
using (StreamWriter sw = new StreamWriter(filePath1))
{
sw.Write(row1.ToString());
sw.WriteLine();
sw.Write(row2.ToString());
sw.WriteLine();
sw.Write(row3.ToString());
sw.WriteLine();
sw.Write(row4.ToString());
sw.WriteLine();
sw.Close();
}
What you are trying create is not the standard CSV file that CsvHelper was built to create. A CSV file has one row of headers followed by rows of data. You appear to be creating an Excel report using comma separated values. CsvHelper can help you write the fields, but you are going to have to supply the logic for writing the report format. The following is one way that you could do it.
public static void Main(string[] args)
{
var points = new List<Point>
{
new Point
{
BuildingName = "ABC Office",
TaskName = "Temperature",
PointName = "14",
DataName = "Temperature: Degrees F",
Results = new List<Result> {
new Result { Local = new DateTime(2019, 1,1), Value = 2},
new Result { Local = new DateTime(2019, 1, 2), Value = 23}
}
},
new Point
{
BuildingName = "Sarah's Office",
TaskName = "Fan",
PointName = "33",
DataName = "0=Stop;1=Run",
Results = new List<Result> {
new Result { Local = new DateTime(2019, 1,1), Value = 2},
new Result { Local = new DateTime(2019, 1, 2), Value = 23},
new Result { Local = new DateTime(2019, 1, 3), Value = 45},
new Result { Local = new DateTime(2019, 1, 4), Value = 34},
new Result { Local = new DateTime(2019, 1, 5), Value = 36}
}
},
new Point
{
BuildingName = "Brian's Office",
TaskName = "Fan",
PointName = "35",
DataName = "Humidity",
Results = new List<Result> {
new Result { Local = new DateTime(2019, 1,1), Value = 2},
new Result { Local = new DateTime(2019, 1, 2), Value = 23},
new Result { Local = new DateTime(2019, 1, 3), Value = 45},
new Result { Local = new DateTime(2019, 1, 4), Value = 34},
new Result { Local = new DateTime(2019, 1, 5), Value = 36},
new Result { Local = new DateTime(2019, 1, 6), Value = 56},
new Result { Local = new DateTime(2019, 1, 7), Value = 92}
}
},
};
using (var writer = new StreamWriter(filePath))
using (var csv = new CsvWriter(writer))
{
// Print buildings
foreach (var point in points)
{
csv.WriteField(point.BuildingName);
csv.WriteField("");
}
csv.NextRecord();
// Print Tasks
foreach (var point in points)
{
csv.WriteField(point.TaskName);
csv.WriteField("");
}
csv.NextRecord();
// Print Points
foreach (var point in points)
{
csv.WriteField(point.PointName);
csv.WriteField("");
}
csv.NextRecord();
// Print DataNames
foreach (var point in points)
{
csv.WriteField(point.DataName);
csv.WriteField("");
}
csv.NextRecord();
// Print value titles
foreach (var point in points)
{
csv.WriteField("Local");
csv.WriteField("Value");
}
csv.NextRecord();
var endReached = false;
var pointIndex = 0;
// Print values
while (!endReached)
{
endReached = true;
foreach (var point in points)
{
if (point.Results.Count > pointIndex)
{
csv.WriteField(point.Results[pointIndex].Local);
csv.WriteField(point.Results[pointIndex].Value);
if (point.Results.Count > pointIndex + 1)
{
endReached = false;
}
}
else
{
csv.WriteField("");
csv.WriteField("");
}
}
csv.NextRecord();
pointIndex += 1;
}
}
}
public class Point
{
public string BuildingName { get; set; }
public string TaskName { get; set; }
public string PointName { get; set; }
public string DataName { get; set; }
public List<Result> Results { get; set; }
}
public class Result
{
public DateTime Local { get; set; }
public int Value { get; set; }
}
Related
I have 3 methods that do same stuff. One difference, they work with different models.
Here is the methods code:
public IEnumerable<PropertyImportDto> ImportStandardCsv(string fileData)
{
List<PropertyImportDto> data;
using (var memoryStream =
new MemoryStream(Convert.FromBase64String(fileData.Substring(fileData.IndexOf(',') + 1))))
{
using (var streamWriter = new StreamReader(memoryStream))
using (var csvReader = new CsvReader(streamWriter))
{
var records = csvReader.GetRecords<PropertyImportDto>();
data = records.ToList();
}
}
return data;
}
public IEnumerable<ArthurPropertiesImportDto> ImportArthurCsv(string fileData)
{
List<ArthurPropertiesImportDto> data;
using (var memoryStream =
new MemoryStream(Convert.FromBase64String(fileData.Substring(fileData.IndexOf(',') + 1))))
{
using (var streamWriter = new StreamReader(memoryStream))
using (var csvReader = new CsvReader(streamWriter))
{
var records = csvReader.GetRecords<ArthurPropertiesImportDto>();
data = records.ToList();
}
}
return data;
}
public IEnumerable<LandlordVisionImportDto> ImportLandlordVision(string fileData)
{
List<LandlordVisionImportDto> data;
using (var memoryStream =
new MemoryStream(Convert.FromBase64String(fileData.Substring(fileData.IndexOf(',') + 1))))
{
using (var streamWriter = new StreamReader(memoryStream))
using (var csvReader = new CsvReader(streamWriter))
{
var records = csvReader.GetRecords<LandlordVisionImportDto>();
data = records.ToList();
}
}
return data;
}
And I call it like this
public async Task ImportProperties(PM101ImportDto input)
{
switch (input.fileTypeId)
{
case 1:
{
var properties = _csvAppService.ImportStandardCsv(input.FileBase64);
foreach (var item in properties)
{
var property = new Property
{
PropertyTypeId = 1,
BuildingTypeId = 12,
PhoneNumber = item.PhoneNumber,
PropertyTitleId = 1,
AccountManagerId = AbpSession.TenantId,
Addresses = new List<PropertyAddress>
{
new PropertyAddress
{
Line1 = item.Line1,
Line2 = item.Line2,
Line3 = item.Line3,
PostCode = item.PostalCode,
PostTown = item.Town,
Country = item.Country,
County = item.County,
Latitude = item.Latitude,
Longitude = item.Longitude
},
},
Sites = new List<Site>
{
new Site
{
NumberOfWindows = 0,
NumberOfBedRooms = 0,
ApproximateYearBuilt = 1970,
PropertyAge = 50,
FuelTypeId = 1,
ParkingTypeId = 1,
FurnishingTypeId = 1
}
},
MarketingInformation = new List<PropertyMarketingInformation>
{
new PropertyMarketingInformation
{
MarketingDescription = "", IsBillsIncluded = false
}
}
};
await _propertyRepository.InsertAsync(property);
}
break;
}
case 2:
{
var properties = _csvAppService.ImportLandlordVision(input.FileBase64);
foreach (var item in properties)
{
var property = new Property
{
PropertyTypeId = 1,
BuildingTypeId = 12,
PropertyTitleId = 1,
AccountManagerId = AbpSession.TenantId,
Addresses = new List<PropertyAddress>
{
new PropertyAddress
{
Line1 = item.Line1,
Line2 = item.Line2,
PostCode = item.PostCode,
PostTown = item.Town,
County = item.County
}
},
Sites = new List<Site>
{
new Site
{
NumberOfWindows = 0,
NumberOfBedRooms = 0,
ApproximateYearBuilt = 1970,
PropertyAge = 50,
FuelTypeId = 1,
ParkingTypeId = 1,
FurnishingTypeId = 1
}
},
MarketingInformation = new List<PropertyMarketingInformation>
{
new PropertyMarketingInformation
{
MarketingDescription = "", IsBillsIncluded = false
}
}
};
await _propertyRepository.InsertAsync(property);
}
break;
}
case 3:
{
var properties = _csvAppService.ImportArthurCsv(input.FileBase64);
foreach (var item in properties)
{
var property = new Property
{
PropertyTypeId = 1,
BuildingTypeId = 12,
PropertyTitleId = 1,
AccountManagerId = AbpSession.TenantId,
Addresses = new List<PropertyAddress>
{
new PropertyAddress
{
Line1 = item.Line1,
Line2 = item.Line2,
Line3 = item.Line3,
PostCode = item.PostCode,
PostTown = item.City,
County = item.County,
Country = item.Country,
Latitude = item.Latitude,
Longitude = item.Longitude
}
},
Sites = new List<Site>
{
new Site
{
NumberOfWindows = 0,
NumberOfBedRooms = 0,
ApproximateYearBuilt = 1970,
PropertyAge = 50,
FuelTypeId = 1,
ParkingTypeId = 1,
FurnishingTypeId = 1
}
},
MarketingInformation = new List<PropertyMarketingInformation>
{
new PropertyMarketingInformation
{
MarketingDescription = "", IsBillsIncluded = false
}
}
};
await _propertyRepository.InsertAsync(property);
}
}
break;
}
}
How I can rewrite those 3 methods to one gneric method?
Typical use case for generic type parameters
public IEnumerable<T> ImportStandardCsv<T>(string fileData)
{
var bytes = Convert.FromBase64String(fileData.Substring(fileData.IndexOf(',') + 1));
using (var memoryStream = new MemoryStream(bytes))
using (var streamReader = new StreamReader(memoryStream))
using (var csvReader = new CsvReader(streamReader))
return csvReader.GetRecords<T>();
}
call
IEnumerable<PropertyImportDto> result = ImportStandardCsv<PropertyImportDto>(input.FileBase64);
I'm using the following code:
DynamoDBContextConfig config = new DynamoDBContextConfig()
{
ConsistentRead = false,
Conversion = DynamoDBEntryConversion.V2
};
using (DynamoDBContext context = new DynamoDBContext(config))
{
long unixTimestamp = (long)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
QTrackStatus qTrackStatus = new QTrackStatus()
{
Key = "m#m.com",
EventCode = "CC",
EventDateTime = "2019-09-09 14:00:30",
EventLocation = "BFS",
EventLastUpdate = unixTimestamp
};
DynamoDBOperationConfig dynamoDBOperationConfig = new DynamoDBOperationConfig()
{
QueryFilter = new List<ScanCondition>()
{
{ new ScanCondition("EventCode", ScanOperator.NotEqual, "CC") }
},
ConditionalOperator = ConditionalOperatorValues.And
};
await context.SaveAsync(qTrackStatus, dynamoDBOperationConfig);
}
What I'm trying to do is only save the record if the EventCode is not CC. Currently it's always saving. I could retrieve the record first, do a check and then call SaveAsync if required - however I'd like to do it all in the SaveAsync call. Is this possible?
Unless I've missed something, it doesn't look like this is possible with the higher level api. I ended up re-factoring to the following:
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
UpdateItemRequest updateItemRequest = new UpdateItemRequest()
{
TableName = "QTrackStatus",
ReturnValues = ReturnValue.ALL_NEW,
ConditionExpression = "EventCode <> :ec",
UpdateExpression = "SET EventCode = :ec, EventDateTime = :edt, EventLocation = :el, EventLastUpdate = :elu",
ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
{
{ ":ec", new AttributeValue("CC") },
{ ":edt", new AttributeValue("2019-09-09 14:00:30") },
{ ":el", new AttributeValue("BFS") },
{ ":elu", new AttributeValue() { N = ((long)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds).ToString() } }
},
Key = new Dictionary<string, AttributeValue>()
{
{ "Key", new AttributeValue("m#m.com") }
}
};
try
{
UpdateItemResponse updateItemResponse = await client.UpdateItemAsync(updateItemRequest);
}
catch(ConditionalCheckFailedException e)
{
}
This allows me to achieve my goal.
I am trying to run or start an existing task definition within ECS but the documentation is lacking and I cant seem to find any examples online. I have hit a wall and I was wondering if anyone else has done a similar thing.
I am using the AWSSDK.ECS packages.
var request = JsonConvert.DeserializeObject<Request>(record.Sns.Message);
var task = new RunTaskRequest
{
Count = 1,
NetworkConfiguration = new NetworkConfiguration
{
AwsvpcConfiguration = new AwsVpcConfiguration
{
Subnets = new List<string>() { request.SubnetId},
SecurityGroups = new List<string>() { request.SecurityGroupId},
AssignPublicIp = AssignPublicIp.DISABLED
}
},
Cluster = request.Cluster,
LaunchType = LaunchType.FARGATE,
Overrides = new TaskOverride
{
ContainerOverrides = new List<ContainerOverride>
{
new ContainerOverride
{
Name = request.ContainerName,
Environment = request.EnvironmentVariables
.Select(kvp => new Amazon.ECS.Model.KeyValuePair()
{
Name = kvp.Key,
Value = kvp.Value
}).ToList()
}
}
},
TaskDefinition = request.TaskDefinitionUri
};
await new AmazonEcsClient().RunTaskAsync(task);
Check on your task definition. If the NetworkMode is awsvpc, then you must provide NetworkConfiguration parameter. This works for me:
var runTaskRequest = new ECSModel.RunTaskRequest
{
Cluster = "cluster-name",
Count = 1,
LaunchType = LaunchType.FARGATE,
TaskDefinition = "task-definition",
NetworkConfiguration = new ECSModel.NetworkConfiguration
{
AwsvpcConfiguration = new ECSModel.AwsVpcConfiguration
{
SecurityGroups = new List<string> { "security-group" },
Subnets = new List<string> { "subnet" }
}
},
Overrides = new ECSModel.TaskOverride
{
ContainerOverrides = new List<ECSModel.ContainerOverride>
{
new ECSModel.ContainerOverride
{
Name = "container-name",
Command = new List<string>
{
// In case if you need to pass parameters to your instance:
"parameter-one", "parameter-two", "etc"
}
}
}
}
};
await new AmazonEcsClient().RunTaskAsync(runTaskRequest);
What am I doing wrong?
I've got error when inserting data to GoogleFit (last line).
I know that C# API doesn't include detailed error information but I don't know how to send it through google console website.
Google.GoogleApiException HResult=0x80131500
Message=Google.Apis.Requests.RequestError Bad Request [400] Errors
[Message[Bad Request] Location[ - ] Reason[invalidArgument]
Domain[global]]
using Google.Apis.Auth.OAuth2;
using Google.Apis.Fitness.v1;
using Google.Apis.Fitness.v1.Data;
using Google.Apis.Services;
using Google.Apis.Util.Store;
using System;
using System.Collections.Generic;
using System.Threading;
namespace GoogleFitImport
{
class Program
{
static void Main(string[] args)
{
GoogleFitImport.InsertToGoogleFit();
}
}
public class GoogleFitImport
{
private static readonly DateTime zero = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public static long ToJavaMiliseconds(DateTime dt)
{
return (long)(dt - zero).TotalMilliseconds;
}
public static long ToJavaNanoseconds(DateTime dt)
{
return (long)(dt - zero).TotalMilliseconds * 10 ^ 6;
}
public static DateTime FromJavaNanoseconds(long? nanoseconds)
{
if (nanoseconds == null)
nanoseconds = 0;
return FromJavaMiliseconds((nanoseconds.Value / (10 ^ 6)));
}
public static DateTime FromJavaMiliseconds(long mili)
{
return zero.AddMilliseconds((double)mili);
}
public static void InsertToGoogleFit()
{
string UserId = "me";
List<KeyValuePair<DateTime, float>> measures = new List<KeyValuePair<DateTime, float>>();
measures.Add(new KeyValuePair<DateTime, float>(new DateTime(2000, 01, 01, 12, 0, 0, DateTimeKind.Utc), 10.1f));
measures.Add(new KeyValuePair<DateTime, float>(new DateTime(2000, 01, 02, 12, 0, 0, DateTimeKind.Utc), 10.2f));
measures.Add(new KeyValuePair<DateTime, float>(new DateTime(2000, 01, 03, 12, 0, 0, DateTimeKind.Utc), 10.3f));
// https://www.googleapis.com/auth/fitness.body.write
var clientId = "000000000000-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com"; // From https://console.developers.google.com
var clientSecret = "XXXXXXXXXXXXXXXXXXXXXXXX"; // From https://console.developers.google.com
//Scopes for use with the Google Drive API
string[] scopes = new string[]
{
FitnessService.Scope.FitnessBodyWrite,
FitnessService.Scope.FitnessBodyRead,
};
// here is where we Request the user to give us access, or use the Refresh Token that was previously stored in %AppData%
var credential = GoogleWebAuthorizationBroker.AuthorizeAsync
(
new ClientSecrets
{
ClientId = clientId,
ClientSecret = clientSecret
},
scopes,
Environment.UserName,
CancellationToken.None,
new FileDataStore("Google.Fitness.Auth", false)
).Result;
FitnessService fitnessService = new FitnessService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "FromLibraCsvToGoogleFit" //Assembly.GetExecutingAssembly().GetName().Name,
});
DataSource dataSource = new DataSource()
{
Type = "raw", //""derived",
Application = new Google.Apis.Fitness.v1.Data.Application()
{
Name = "maweightimport"
},
DataType = new DataType()
{
Name = "com.google.weight",
Field = new List<DataTypeField>()
{
new DataTypeField() {Name = "weight", Format = "floatPoint"}
}
},
Device = new Device()
{
Type = "scale",
Manufacturer = "unknown",
Model = "unknown",
Uid = "maweightimport",
Version = "1.0"
}
};
//string dataSourceId = "derived:com.google.weight:{clientId}:unknown:unknown:maweightimport"
string dataSourceId =
$"{dataSource.Type}:{dataSource.DataType.Name}:{clientId.Split('-')[0]}:{dataSource.Device.Manufacturer}:{dataSource.Device.Model}:{dataSource.Device.Uid}";
try
{
DataSource googleDataSource = fitnessService.Users.DataSources.Get(UserId, dataSourceId).Execute();
}
catch (Exception ex) //create if not exists
{
Console.WriteLine(ex);
DataSource googleDataSource = fitnessService.Users.DataSources.Create(dataSource, UserId).Execute();
}
Google.Apis.Fitness.v1.Data.Dataset weightsDataSource = new Google.Apis.Fitness.v1.Data.Dataset()
{
DataSourceId = dataSourceId,
Point = new List<DataPoint>()
};
DateTime minDateTime = DateTime.MaxValue;
DateTime maxDateTime = DateTime.MinValue;
foreach (var weight in measures)
{
long ts = ToJavaNanoseconds(weight.Key);
weightsDataSource.Point.Add
(
new DataPoint()
{
DataTypeName = "com.google.weight",
StartTimeNanos = ts,
EndTimeNanos = ts,
Value = new List<Value>()
{
new Value()
{
FpVal = weight.Value
}
}
}
);
if (minDateTime > weight.Key)
minDateTime = weight.Key;
if (maxDateTime < weight.Key)
maxDateTime = weight.Key;
}
weightsDataSource.MinStartTimeNs = ToJavaNanoseconds(minDateTime);
weightsDataSource.MaxEndTimeNs = ToJavaNanoseconds(maxDateTime);
string dataSetId = "2000.01.01-2000.01.03";
var save = fitnessService.Users.DataSources.Datasets.Patch(weightsDataSource, UserId, dataSourceId, dataSetId).Execute(); //ERROR HERE !
//var read = fitnessService.Users.DataSources.Datasets.Get(UserId, dataSourceId, dataSetId).Execute();
}
}
}
string dataSetId = "2000.01.01-2000.01.03";
Has to be in Nanos.
Good day all,
would like request to how to convert table format to string
eg:
Material Control August
Development September
Planning August
HR September
to
September: Development, HR
August : Material Control, Planning
List<String> returnvalueStringMonth = new List<String>();
List<String> returnvalueStringDept = new List<String>();
foreach (DataRow dr in dsSeries.Tables[0].Rows)
{
string newmanout = dr["MonthNames"].ToString();
returnvalueStringMonth.Add(newmanout);
string Departs = dr["Depart"].ToString();
returnvalueStringMonth.Add(Departs);
//var DDLName = dr["Depart"];
//Label dynamicLabel = new Label();
//dynamicLabel.Text = DDLName.ToString() + ",";
//div1.Controls.Add(dynamicLabel);
//var sumPlus = Convert.ToDouble(newmanout) +",";
}
List<string> b = new List<string>();
b.AddRange(returnvalueStringMonth.Distinct());
for (int cs = 0; cs < b.Count; cs++)
{
//Panel aspPanel = new Panel();
Label dynamicLabel = new Label();
dynamicLabel.Text = b[cs].ToString()+":" + "<br/>";
div1.Controls.Add(dynamicLabel);
}
I able achive until month only, then i realize made mistake.
So, please advise how to achive this.
The code below will fill a list of strings with your desired output. You can change the second loop to do what you want.
var monthList = new Dictionary<String, List<String>>();
foreach (DataRow dr in dsSeries.Tables[0].Rows)
{
var key = dr["MonthName"].ToString();
var value = dr["Department"].ToString();
if (!monthList.ContainsKey(key))
{
monthList.Add(key, new List<string>());
}
monthList[key].Add(value);
}
List<string> b = new List<String>();
foreach (var month in monthList.Keys)
{
b.Add(month + ": " + String.Join(", ", monthList[month])");
}
If you would rather use LINQ, you can do this instead:
var q = from row in dsSeries.Tables[0].AsEnumerable()
group row by row["Month"] into qGrouped
orderby qGrouped.Key
select String.Format("{0}: {1}", qGrouped.Key,
String.Join(", ", Array.ConvertAll(qGrouped.ToArray(), r => r["Department"])));
var b = q.ToList();
public class TestClass
{
public string S1 { get; set; }
public string S2 { get; set; }
}
[TestMethod]
public void MyTest()
{
// Material Control August
//Development September
//Planning August
//HR September
var list = new List<TestClass>
{
new TestClass {S1 = "Material Control", S2 = "August"},
new TestClass {S1 = "Development", S2 = "September"},
new TestClass {S1 = "Planning", S2 = "August"},
new TestClass {S1 = "HR", S2 = "September"}
};
var listGroupByMonth = list.GroupBy(l => l.S2);
foreach (var lstByMonth in listGroupByMonth)
{
var key = lstByMonth.Key;
var finalValue = string.Join(", ", lstByMonth.ToList().Select(lbm => lbm.S1));
}
}