I'm trying to create a windows service that detects if there are new CSV files in a folder and parse those files. CsvHelper seems to not be able to read the CSV file. All the parameters that I try to populate are empty.
Is there something wrong in the code? The GetField method does not return any values and If I print the parameters are all empty.
The path is correct and the csv files paths are also correct.
public class CSVBatch
{
public string MaterialID { get; set; }
public string MaterialName { get; set; }
public string Location { get; set; }
public string Quantity { get; set; }
public string BatchID { get; set; }
public string ProcessOrder { get; set; }
public string Recipe { get; set; }
public List<CSVRawMaterial> CSVRawMaterials { get; set; }
public class CSVRawMaterial
{
public string MaterialID { get; set; }
public string MaterialName { get; set; }
public string Location { get; set; }
public string Quantity { get; set; }
public string BatchID { get; set; }
public string ProcessOrder { get; set; }
public string Recipe { get; set; }
}
}
protected override void OnStart(string[] args)
{
var folder = "C:\\BOM";
FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(folder);
var fw = fileSystemWatcher;
fw.IncludeSubdirectories = true;
fw.EnableRaisingEvents = true;
fw.Created += Newfileevent;
}
static void Newfileevent(object sender, FileSystemEventArgs e)
{
string[] filePaths = Directory.GetFiles("C:\\BOM");
foreach (string s in filePaths)
{
var config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
Delimiter = ",",
MissingFieldFound = null,
TrimOptions = TrimOptions.Trim,
HeaderValidated = null,
HasHeaderRecord = true
};
using (var reader = new StringReader(s))
using (var csv = new CsvReader(reader, config))
{
csv.Read();
var batch = new CSVBatch
{
MaterialID = csv.GetField<string>(0),
MaterialName = csv.GetField<string>(1),
Location = csv.GetField<string>(2),
Quantity = csv.GetField<string>(3),
BatchID = csv.GetField<string>(4),
ProcessOrder = csv.GetField<string>(5),
Recipe = csv.GetField<string>(6)
};
csv.Read();
var rawMaterials = new List<CSVRawMaterial>();
while (csv.Read())
{
var rawmaterial = new CSVRawMaterial
{
MaterialID = csv.GetField<string>(0),
MaterialName = csv.GetField<string>(1),
Location = csv.GetField<string>(2),
Quantity = csv.GetField<string>(3)
};
rawMaterials.Add(rawmaterial);
}
batch.CSVRawMaterials = rawMaterials;
}
}
CSV File:
You have 2 issues.
You are using StringReader instead of StreamReader. It should be:
using (var reader = new StreamReader(s))
If you have a header row, you also have to specifically read the header when reading by hand.
using (var reader = new StreamReader(s))
using (var csv = new CsvReader(reader, config))
{
csv.Read();
csv.ReadHeader();
csv.Read();
batch = new CSVBatch
{
Related
I have a lot of CSV files without header and need to read it in C#. I manually added header to one of these files and with the following code using CSVHelper I can read the files and show them in a GridView.
Now my question is, how can I read these files without a header? Or how can I add a header (a new record) using CSVHelper in the first line?
public Form1()
{
InitializeComponent();
List<Festival> records;
var config = new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = ";" };
using (var reader = new StreamReader(#"File8.csv"))
using(var csv = new CsvReader(reader, config))
{
records = csv.GetRecords<Festival>().ToList();
}
dataGridView1.DataSource = records;
}
Class
public class Festival
{
public string Day { get; set; }
public string Start { get; set; }
public int Lenght { get; set; }
public string FilmName { get; set; }
public float Rating { get; set; }
}
csv sample
Mi;22:15;110;A;8
Mi;19:00;106;B;8
Mi;19:15;97;C;8.2
Add column-index mapping attributes to the target members:
public class Festival
{
[Index(0)]
public string Day { get; set; }
[Index(1)]
public string Start { get; set; }
[Index(2)]
public int Lenght { get; set; }
[Index(3)]
public string FilmName { get; set; }
[Index(4)]
public float Rating { get; set; }
}
And specify HasHeaderRecord = false in the config:
var config = new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = ";", HasHeaderRecord = false };
If modifying the target model isn't desirable, implement a ClassMap instead:
public sealed class FestivalMap : ClassMap<Festival>
{
public FestivalMap()
{
Map(f => f.Day).Index(0);
Map(f => f.Start).Index(1);
Map(f => f.Lenght).Index(2);
Map(f => f.FilmName).Index(3);
Map(f => f.Rating).Index(4);
}
}
And register it like this before fetching the records (you still need to specify HasHeaderRecord = false in the config):
csv.Context.RegisterClassMap<FestivalMap>();
records = csv.GetRecords<Festival>().ToList();
I am using csvhelper to import certain fields in a datagridview with no issues and then I have other columns added that has user imputed data. That part works.
Now when I try to write the datagridview to a new csv file and I get no data just headers that I have from the class. So where am I going wrong?
My write to code:
private void SchedSaveBtn_Click(object sender, EventArgs e)
{
var records = new List<WriteCsvschedule>
{
new WriteCsvschedule { EmpName = "1", EmpPayrollID = "2" },
};
using (var writer = new StreamWriter(#"c:\rcs\export\sched.csv"))
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
csv.WriteRecords(records);
}
}
and my class:
public class WriteCsvschedule
{
[Index(0)]
public string EmpName { get; set; }
[Index(1)]
public string EmpPayrollID { get; set; }
[Index(2)]
public string JobName { get; set; }
}
I am a C# beginner programmer. I have a text file, which is my source, with multiple rows of data. I want to create one xml file with multiple xml documents inside the file. The xml documents are generated from the rows of data in the text file. I can only get one xml document to generate in the A0x.xml file that is created. My code only reads the first row of data and generates one xml document instead to multiple xml documents. Below are 8 rows from the M24EX.txt file. Please help!!
A0ASMSS3110004624190 EA00008FB239980940001RAIR A30 0120505 18094133644FT
A0ASMSS5340011122822 HD00001FB239981000001RAIR A6C 0120503 18100124741FT
A0ASMSS5365002870093 EA00003FB239981000002RAIR A6C 0120503 18100125431FT
A0ASMS 5365001671717 EA00005FB239981010001REY2550A6C 0120503133 18101075536SF
A0ASMS 5365001671717 EA00011FB239981010002RGE A6C 0120505129 18101105015FT
A0AFLZ 6625013922071 EA00001FB239981070001RGRN D6C 0120505110 18107150014FT
A0AFLZ 6650013204283 EA00003FB239981070002NGRN D6C 0120504777 18107151015FT
A0ASMSS1650009937278 EA00006FB239981080001RAIR A6C 0120505 18108082906FT
And the code:
Public class Program
{
public static void Main(string[] arg)
{
XDocument A0x = new XDocument();
var IdCode = "511";
var CtrlNbr = "0001";
var PurposeCode = "00";
var TypeCode = "A0";
var EntyIdCode = "OB";
var IdCodeQlfr = "10";
var EntyIdCode1 = "FR";
var DocNbr = "TN";
var AssignNbr = "1";
var NSN = "FS";
var DD = "74";
var AgncyQlfrCode = "DF";
var LstQlfrCode = "0";
DateTime saveUtcNow = DateTime.UtcNow;
DateTime saveNow = DateTime.Now;
var field = new ParseTextFile().Parse();
var tagBuilder = new TagBuilder();
var parent = tagBuilder.BuildParent("File");
var subParent = tagBuilder.BuildParent("T_Requisition_511");
var ParentST = tagBuilder.BuildParent("S_Transaction_Set_Header");
var ST01 = tagBuilder.BuildChild("E_Transaction_Set_Identifier_Code", IdCode);
var ST02 = tagBuilder.BuildChild("E_Transaction_Set_Control_Number", CtrlNbr);
var ParentBR = tagBuilder.BuildParent("S_Beginning_Segment_for_Material_Management");
var BR01 = tagBuilder.BuildChild("E_Transaction_Set_Purpose_Code", PurposeCode);
var BR02 = tagBuilder.BuildChild("E_Transaction_Type_Code", TypeCode);
var BR03 = tagBuilder.BuildChild("E_Date", saveUtcNow.ToString("yyyyMMdd"));
var BR09 = tagBuilder.BuildChild("E_Time", saveUtcNow.ToString("hhmmss"));
var ParentN1 = tagBuilder.BuildParent("L_Name");
var ParentS = tagBuilder.BuildParent("S_Name");
var N101 = tagBuilder.BuildChild("E_Entity_Identifier_Code", EntyIdCode);
var N103 = tagBuilder.BuildChild("E_Identification_Code_Qualifier", IdCodeQlfr);
var N104 = tagBuilder.BuildChild("E_Identification_Code", field.SRAN);
var N106 = tagBuilder.BuildChild("E_Entity_Identifier_Code_1", EntyIdCode1);
var ParentLX = tagBuilder.BuildParent("L_Assigned_Number");
var ParentAN = tagBuilder.BuildParent("S_Assigned_Number");
var LX01 = tagBuilder.BuildChild("E_Assigned_Number", AssignNbr);
var ParentN9 = tagBuilder.BuildParent("S_Reference_Identification");
var N901 = tagBuilder.BuildChild("E_Reference_Identification_Qualifier", DocNbr);
var N902 = tagBuilder.BuildChild("E_Reference_Identification", field.DocumentNumber);
var ParentPO1 = tagBuilder.BuildParent("S_Baseline_Item_Data");
var PO102 = tagBuilder.BuildChild("E_Quantity_Ordered", Convert.ToString(field.Quantity));
var PO103 = tagBuilder.BuildChild("E_Unit_or_Basis_for_Measurement_Code", field.UnitofIssue);
var PO106 = tagBuilder.BuildChild("E_Product_Service_ID_Qualifier", NSN);
var PO107 = tagBuilder.BuildChild("E_Product_Service_ID", field.StockNumber);
var ParentSE = tagBuilder.BuildParent("S_Transaction_Set_Trailer");
var SE01 = tagBuilder.BuildChild("E_Number_of_Included_Segments", new CountSegmentTags().CountSgmts().ToString());
var SE02 = tagBuilder.BuildChild("E_Transaction_Set_Control_Number", CtrlNbr);
parent.Add(subParent);
subParent.Add(ParentST);
ParentST.Add(ST01);
ParentST.Add(ST02);
subParent.Add(ParentBR);
ParentBR.Add(BR01);
ParentBR.Add(BR02);
ParentBR.Add(BR03);
ParentBR.Add(BR09);
subParent.Add(ParentN1);
ParentN1.Add(ParentS);
ParentS.Add(N101);
ParentS.Add(N103);
ParentS.Add(N104);
ParentS.Add(N106);
subParent.Add(ParentLX);
ParentLX.Add(ParentAN);
ParentAN.Add(LX01);
ParentLX.Add(ParentN9);
ParentN9.Add(N901);
ParentN9.Add(N902);
ParentLX.Add(ParentPO1);
ParentPO1.Add(PO102);
ParentPO1.Add(PO103);
ParentPO1.Add(PO106);
ParentPO1.Add(PO107);
ParentSE.Add(SE01);
ParentSE.Add(SE02);
A0x.Add(parent);
A0x.Declaration = new XDeclaration("1.0", "utf-8", "true");
A0x.Save("M24EX.xml");
}
public class TagBuilder
{
public XElement BuildParent(string name)
{
return new XElement(name);
}
public XElement BuildChild(string name, string value)
{
var tag = new XElement(name);
tag.Add(value);
return tag;
}
}
public void Read()
{
int counter = 0;
string line;
StreamReader file = new StreamReader("M24EX.txt");
while ((line = file.ReadLine()) != null)
if (line.StartsWith("A0")) // only pull "A0x" records
{
counter++;
Console.WriteLine("{0}:{1}", counter, line);
}
file.Close();
}
public class ParseTextFile
{
public TransactionFields Parse()
{
StreamReader file = new StreamReader("M24Ex.txt");
string line;
int counter = 0;
var field = new TransactionFields();
while ((line = file.ReadLine()) != null)
if (line.StartsWith("A0"))
{
//Assigns field to the Transaction field names
field.DocumentIdentifier = line.Substring(0, 3).Trim(); // Tric
field.RoutingIdentifier = line.Substring(4, 3).Trim();
field.MediaStatusCode = line.Substring(7, 1).Trim();
field.StockNumber = line.Substring(7, 15).Trim();
field.UnitofIssue = line.Substring(22, 2).Trim();
field.Quantity = Convert.ToInt32(line.Substring(24, 5));
field.DocumentNumber = line.Substring(29, 14).Trim();
field.SRAN = line.Substring(29, 6).Trim();
field.DemandCode = line.Substring(44, 1).Trim();
field.SupplementaryAddress = line.Substring(45, 6).Trim();
field.SignalCode = line.Substring(51, 1).Trim();
field.FundCode = line.Substring(52, 2).Trim();
field.DistributionCode = line.Substring(54, 3).Trim();
field.ProjectCode = line.Substring(57, 3).Trim();
field.Priority = line.Substring(60, 2).Trim();
field.ReqDeliveryDate = line.Substring(62, 3).Trim();
field.AdviceCode = line.Substring(65, 2).Trim();
field.DateReceiptofReq = line.Substring(67, 3).Trim();
field.PurposeCode = line.Substring(70, 1).Trim();
field.ConditionCode = line.Substring(71, 1).Trim();
field.MgmtCode = line.Substring(72, 1).Trim();
}
file.Close();
return field;
}
}
public class ConvertXmlToText
{
public void ConvertXmlDoc()
{
string onlyContent = string.Empty;
XmlDocument xdoc = new XmlDocument();
xdoc.Load("A0x.xml");
var file = xdoc.SelectNodes("File/T_Requisition_511");
for (int i = 0; i < file.Count; i++)
{
onlyContent += string.Format("\n", i);
foreach (XmlNode node in file[i].ChildNodes)
onlyContent += string.Format("{0},", node.InnerText);
}
File.WriteAllText("A0x.txt", onlyContent);
}
}
public class TransactionFields
{
public string DocumentIdentifier { get; set; }
public string RoutingIdentifier { get; set; }
public string MediaStatusCode { get; set; }
public string StockNumber { get; set; }
public string UnitofIssue { get; set; }
public int Quantity { get; set; }
public string DocumentNumber { get; set; }
public string SRAN { get; set; }
public string DemandCode { get; set; }
public string SupplementaryAddress { get; set; }
public string SignalCode { get; set; }
public string FundCode { get; set; }
public string DistributionCode { get; set; }
public string ProjectCode { get; set; }
public string Priority { get; set; }
public double UnitPrice { get; set; }
public string Date { get; set; }
public string Time { get; set; }
}
public class kingdomAddModel
{
public string title { get; set; }
public string details { get; set; }
//public HttpPostedFileBase fileUpload { get; set; }
//public string retrieveFile { get; set; }
public FileAttr files { get; set; }
}
public class FileAttr
{
public HttpPostedFileBase fileUpload { get; set; }
public string retrieveFile { get; set; }
}
var getDailyDevotions = db.DailyDevotions.Select(d => new { title = d.DevotionsTitle, details = d.DevotionsDetails, retriveFileAudio = d.VoiceNotes });
List<kingdomAddModel> listdevotions = new List<kingdomAddModel>();
foreach (var getDevotions in getDailyDevotions)
{
kingdomlist = new kingdomAddModel();
kingdomlist.title = getDevotions.title;
kingdomlist.details = getDevotions.details;
fileattr = new FileAttr();
fileattr.retrieveFile = getDevotions.retriveFileAudio;
kingdomlist.files.retrieveFile = fileattr.retrieveFile; //erros appears here!
}
The line line kingdomlist.files.retrieveFile throws the exception, tried googling but I dont get simular problem. I just want to assign the value and will pull on my view.
Do not access properties of FileAttr directly, only use files with the instance of kingdomAddModel. Don't mixup them
Replace
foreach (var getDevotions in getDailyDevotions)
{
kingdomlist = new kingdomAddModel();
kingdomlist.title = getDevotions.title;
kingdomlist.details = getDevotions.details;
fileattr = new FileAttr();
fileattr.retrieveFile = getDevotions.retriveFileAudio;
kingdomlist.files.retrieveFile = fileattr.retrieveFile; //erros appears here!
}
with
foreach (var getDevotions in getDailyDevotions)
{
kingdomlist = new kingdomAddModel
{
title = getDevotions.title,
details = getDevotions.details,
files = new FileAttr
{
retrieveFile = getDevotions.retriveFileAudio,
//fileUpload = some value here
}
};
listdevotions.Add(kingdomlist);
}
OR use Linq
listdevotions = (from getDevotions in getDailyDevotions
select new kingdomAddModel
{
title = getDevotions.title,
details = getDevotions.details,
files = new FileAttr
{
retrieveFile = getDevotions.retriveFileAudio,
//fileUpload = some value here
}
}).ToList();
I'm currently working on parsing a csv file that was exported by another application. This application exported the data in a strange way. This export is from accoutning and it looks similar to this..
I'm trying to figure out a way to read the csv file, then split up the multiple 'All Accounts' values and 'Amt' Values so that M200 and 300.89 is another entry, M300 and 400.54 are another entry, and M400 and 100.00 are another entry. So after inserting this single row into the database, I should actually have 4 rows like so..
This is how I'm currently reading and inserting into the database.
List<RawData> data = new List<RawData>();
try
{
string text = File.ReadAllText(lblFileName.Text);
string[] lines = text.Split('\n');
int total = 0, reduced = 0;
foreach (string line in lines)
{
RawData temp = new RawData(line);
total++;
if (!(temp.FirstAccount.Length == 0 || temp.FirstAccount == "1ST-ACCT-NO"))
{
reduced++;
data.Add(temp);
}
}
}
catch (IOException ex)
{
Console.WriteLine("Unable to read file. " + ex.ToString());
MessageBox.Show(ex.ToString());
}
try
{
foreach (RawData rData in data)
{
tCarsInTransit cit = new tCarsInTransit
{
FIRST_ACCT_NO = rData.FirstAccount,
ACCOUNT_NO_DV = rData.AccountNoDv,
ACCT_NO = rData.AcctNo,
ACCT_NO_L = rData.AccNoL,
ACCT_NUM_DV = rData.AcctNumDv,
ACCT_PFX = rData.AcctPfx,
ACCT_PFX_PRT = rData.AcctPfxPrt,
ACCT_TYPE_DV = rData.AcctTypeDv,
ADV_NO = rData.AdvNo,
ALL_PRT_FLAG = rData.AllPrtFlag,
AMT = rData.Amt,
AMT_GLE = rData.AmtGle,
BASE_GLE = rData.BaseGle,
CNT_CAT = rData.CntCat,
COLD_PRT_FLAG = rData.ColdPrtFlag,
COST_DV = rData.CostDv,
COST_OVRD_FLAG_DV = rData.CostOvrdFlagDv,
CR_ACCT_DV = rData.CrAcctDv,
CR_ACCT_DV_GLE = rData.CrAcctDvGle,
CROSS_POSTING_FLAG = rData.CrossPostingFlag,
CROSS_POST_CAT = rData.CrossPostCat,
CTRL_NO = rData.CtrlNo,
CTRL_TYPE_DV = rData.CtrlTypeDv,
DESC_REQD_DV = rData.DescReqdDv,
DR_ACCT_DV = rData.DrAcctDv,
GL_DIST_ACCT_DV = rData.GLDistAcctDv,
GL_DIST_DV = rData.GLDistDv,
GRP_NO_DV = rData.GrpNoDv,
ID_PORT_DATE_TIME_FMT_CAT = rData.IdPortDateTimeFmtCat,
INACTIVITY_DV = rData.InactivityDv,
JOIN_COL = rData.JoinCol,
JRNL_DATE = rData.JrnlDate,
JRNL_PFX = rData.JrnlPfx
};
tCIT.tCarsInTransits.Add(cit);
tCIT.SaveChanges();
lblMessage.ForeColor = System.Drawing.Color.Green;
lblMessage.Text = "Finished uploading. ";
}
}
catch (DbEntityValidationException ex)
{
foreach (var eve in ex.EntityValidationErrors)
{
Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
eve.Entry.Entity.GetType().Name, eve.Entry.State);
foreach (var ve in eve.ValidationErrors)
{
Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
ve.PropertyName, ve.ErrorMessage);
}
}
throw;
}
I am not sure how to accomplish this. The above currently inserts the csv file into Sql Server the exact way the csv file was exported. Any ideas would greatly be appreciated! Thanks!
EDIT: Here is the RawData class.
class RawData
{
public string FirstAccount { get; set; }
public string AccountNoDv { get; set; }
public string AcctNo { get; set; }
public string AccNoL { get; set; }
public string AcctNumDv { get; set; }
public string AcctPfx { get; set; }
public string AcctPfxPrt { get; set; }
public string AcctTypeDv { get; set; }
public string AdvNo { get; set; }
public string AllPrtFlag { get; set; }
public string Amt { get; set; }
public string AmtGle { get; set; }
public string BaseGle { get; set; }
public string CntCat { get; set; }
public string ColdPrtFlag { get; set; }
public string CostDv { get; set; }
public string CostOvrdFlagDv { get; set; }
public string CrAcctDv { get; set; }
public string CrAcctDvGle { get; set; }
public string CrossPostingFlag { get; set; }
public string CrossPostCat { get; set; }
public string CtrlNo { get; set; }
public string CtrlTypeDv { get; set; }
public string DescReqdDv { get; set; }
public string DrAcctDv { get; set; }
public string GLDistAcctDv { get; set; }
public string GLDistDv { get; set; }
public string GrpNoDv { get; set; }
public string IdPortDateTimeFmtCat { get; set; }
public string InactivityDv { get; set; }
public string JoinCol { get; set; }
public string JrnlDate { get; set; }
public string JrnlPfx { get; set; }
public RawData(string csvString)
{
string[] citData = csvString.Replace(", ", "").Replace(".,", ".").Split(',');
try
{
FirstAccount = citData[0];
AccountNoDv = citData[1];
AcctNo = citData[2];
AccNoL = citData[3];
AcctNumDv = citData[4];
AcctPfx = citData[5];
AcctPfxPrt = citData[6];
AcctTypeDv = citData[7];
AdvNo = citData[8];
AllPrtFlag = citData[9];
Amt = citData[10];
AmtGle = citData[11];
BaseGle = citData[12];
CntCat = citData[13];
ColdPrtFlag = citData[14];
CostDv = citData[15];
CostOvrdFlagDv = citData[16];
CrAcctDv = citData[17];
CrAcctDvGle = citData[18];
CrossPostingFlag = citData[19];
CrossPostCat = citData[20];
CtrlNo = citData[21];
CtrlTypeDv = citData[22];
DescReqdDv = citData[23];
DrAcctDv = citData[24];
GLDistAcctDv = citData[25];
GLDistDv = citData[26];
GrpNoDv = citData[27];
IdPortDateTimeFmtCat = citData[28];
InactivityDv = citData[29];
JoinCol = citData[30];
JrnlDate = citData[31];
JrnlPfx = citData[32];
}
catch (Exception ex)
{
Console.WriteLine("Something went wrong. " + ex.ToString());
}
}
}
EDIT 2: AllAccounts in the images is acutally 'AccountNoDv' and there are actually many different fields that have multiples like 'AccountNoDv'(AllAccounts) but we might be removing those as this is not a final export. As of right now the two fields I'm worried most about are AccountNoDv and Amt.
Try something like this:
foreach (string line in lines)
{
RawData temp = new RawData(line);
var AllAccounts = temp.AccountNoDv.split(' ');
var Amts = temp.Amt.split(' ');
if (AllAccounts.Length() == Amts.Length() && Amts.Length() > 1) {
// We have multiple values!
reduced++;
for (int i = 0; i < AllAccounts.Length(); i++) {
RawData temp2 = RawDataCopy(temp); // Copy the RawData object
temp2.AccountNoDv = AllAccounts[i];
temp2.Amt = Amts[i];
total++;
data.Add(temp2);
}
}
else {
total++;
if (!(temp.FirstAccount.Length == 0 || temp.FirstAccount == "1ST-ACCT-NO"))
{
reduced++;
data.Add(temp);
}
}
}
And:
private RawData RawDataCopy(RawData copyfrom) {
// Write a function here that returns an exact copy from the one provided
// You might have to create a parameterless constructor for RawData
RawData RawDataCopy = new RawData();
RawDataCopy.FirstAccount = copyfrom.FirstAccount;
RawDataCopy.AccountNoDv = copyfrom.AccountNoDv;
RawDataCopy.AcctNo = copyfrom.AcctNo;
// . . . . . . . .
RawDataCopy.JrnlPfx = copyfrom.JrnlPfx;
return RawDataCopy;
}
Then also add a parameterless constructor to your RawData class:
public RawData()
{
}
Perhaps it would be sexier to implement the ICloneable interface and call the Clone() function instead of the RawDataCopy function, but it gets the idea across.
In Linq you can use SelectMany to increase the number of elements in a list. Here is a rough example of how this could be done. I make the assumption that the number of sub elements in AllAccounts and Amt is the same. A more robust solution would check for these issues.
So after you have loaded your data list:
var expandedData =
data.SelectMany(item =>
// split amount (will just return one item if no spaces)
item.Amt.Split(" ".ToCharArray())
// join this to the split of all accounts
.Zip(item.AllAccounts.Split(" ".ToCharArray()),
// return the joined item as a new anon object
(a,b) => new { amt=a, all=b }),
// take the original list item and the anon object and return our new item
(full,pair) => { full.Amt = pair.amt; full.AllAccounts = pair.all; return full; }));
You will now have a list of your data items with the multiple items expanded into the list.
I don't have test data to test so I might have some minor typos -- but I put in lots of comments to make the Linq as clear as possible.
Here is is simple example I wrote in LinqPad for myself to make sure I understood how SelectMany worked:
string [] list = { "a b c d","e","f g" };
var result = list.SelectMany((e) =>
e.Split(" ".ToCharArray()),
(o,item) => new { org = o, item = item}).Dump();