Replace any index in a text frame with output of a method - c#

I design a frame for message with a some index in it for each person in list. like the one bellow:
Dear {0}
Hi,
the total amount of Draft is {1}.
amount of prm is {2}
yesterday amount is {3}
I wrote a method witch return all different type of amount and insert the out put of method in a list . I want to replace each item of text frame with the correct amount .
for example the output like the list bellow :
sale
reject amount
damage amount
1230
56555
79646354
my method like bellow :
public List<outputList1> listAmount()
{
var amounts = (from p in db.FactTotalAmount
group p by p.FromDate into g
select new outputList1
{
YesterdaySalesPrm = g.Sum(x =>
x.YesterdaySalesPrm),
YesterdayDraftAmount = g.Sum(x =>
x.YesterdayDraftAmount),
PrmSales = g.Sum(x => x.PrmSales),
DraftAmount = g.Sum(x => x.DraftAmount)
}).ToList();
return amounts;
}
would you please help me what should I do

I'm going to teach you to fish.
There are two main ways to build a string using a template - formatting and interpolation.
Option one: use string.Format:
string output = string.Format("Today is {0}. Weather is {1} at {2}°.", "Monday", "rain", 75.2);
// result is "Today is Monday. Weather is rain at 75.2°."
Option two: use C# 6 string interpolation:
string dayOfWeek = "Monday";
string weather = "rain";
decimal temp = 75.2;
// Notice the "$" at the start of the string literal
string output = $"Today is {dayOfWeek}. Weather is {weather} at {temp}°.";
So, you have a model - the data you've collected - and a format string. Combine those together with one of these options to produce the final output string.

Related

Dynamically extract the name, day and hour from a string[] array like this: JOHN=MO10:00-12:00,TU10:00-12:00

The text file can be like this:
JOHN=MO10:00-12:00,TU10:00-12:00
PETER=TU10:00-12:00,WE10:00-12:00,TH10:00-12:00,FR10:00-12:00
LEE=MO10:00-12:00,TU10:00-12:00,SA10:00-12:00,SU10:00-12:00
LOVELY=TH10:00-12:00,FR10:00-12:00,SA10:00-12:00,SU10:00-12:00
The data will come from a text file with multiple line, the string[]
array could be different for each line. I want to extract each line to
get the Name, Day, Hour. I want to do is it using C# without any
library help.
I got the Name like this:
var employeeNames = employeeName.Split('=')[0];
Split accepts multiple characters
var result = line.Split('=', ',');
If you use that form then you'll get:
result[0]: PETER
result[1]: TU10:00-12:00
result[2]: WE10:00-12:00
result[3]: TH10:00-12:00
result[4]: FR10:00-12:00
The length of the resulting array will vary, but all elements after 0 can be treated the same: the first two chars define the day, chars 2-7 the start time and 8-13 the end time
foreach(var x in result.Skip(1)){
var day = x[..2];
var fromTime = x[2..7];
var endTime = x[8..13];
var fromHour = x[2..4];
var toHour = x[8..10];
}
You can then parse the times to a timespan maybe, use an if or a dictionary to turn the day into a DayOfWeek enum.. (you didn't say what you wanted to do with them)
The "indexing a string using two numbers in brackets" is a feature of more recent c#. If it doesn't work because the project you're doing it in uses a too-old c# version you can use the .Substring(startIndex, length) approach instead
var fromTime = x.Substring(2, 5);
Now we know what you want to do with this info, make a class Person with string Name, double HourlyRate and List<TimeSpan> WorkHours properties. Create a new Person instance on each pass of the loop
Parse your times inside the loop that is extracting the days and name, with var fromTs = TimeSpan.Parse(fromTime) and similar for the toTime
Do var worked = toTs - fromTs; to generate a TimeSpan of eg 8 hours and add it to the WorkHours list
Print a message of the name, and the WorkHours.Sum().TotalHours * HourlyRate
At the end of it you have some code like
for each line in the file
split the line
make a new person, set the name, rate
for each of the days
extract the from and to times
parse to TimeSpans
add the difference between the spans to the work hours list
print the name and the sum of hours times hourly rate

In C#, what is the best way to read in a text file with thiis format and convert to list of objects?

I am reading in a text file of bank transactions and the file is in a specific format to parse. I ultimately want to read in this file and convert the data into a list of BankTransactions objects where this is the definition of a bankTransaction:
public class BankTransaction
{
public DateTime Date;
public string Description;
public Decimal Amount;
public string Category;
}
The tricky part is that the text file data is grouped by category and then it lists out all of the transactions. So for example, the contents of a file might look like this
Food
Date
Description
Amount
1/1/2018
First Purchase
10.00
1/2/2018
Second Purchase
12.00
Homegoods
Date
Description
Amount
1/3/2018
First Purchase
144.00
1/5/2018
Second Purchase
1444.00
so the template is
The first line is Category name
The next 3 lines are headings (Date, Description, Amount)
The next 3 lines are all attributes of the first transaction and then that repeats for all of the transactions in that category .
Once all of the transactions are complete for that category, the next line is the next category name.
When I read in the textfile, i just get an array of string (one for each line).
string[] lines = System.IO.File.ReadAllLines(#"C:\Bank\transactions.txt");
Can anyone suggest the best way to take this array of lines and convert into the structure above so I can then convert into this array of banktransaction objects?
The main problem is the presence of the category name before the headers and data. This creates a condition to consider while looping over the lines because when we read a category name we need to consider 4 rows while when reading the transaction data we have to loop over 3 rows.
However there is a pattern in the data that we could exploit with a normal loop. If every 3 rows we can convert the line to a datetime then we could procede to create a BankTransaction with the other two lines, otherwise we could read the category name and skip the next 3 lines.
List<BankTransaction> result = new List<BankTransaction>();
string currentCat = string.Empty;
for (int x = 0; x < lines.Length; x += 3)
{
DateTime dt;
string line = lines[x];
// If we can convert the line to a date, we are to the beginning
// of a BankTransaction for the current category
if (DateTime.TryParse(line, out dt))
{
// We never enter this if on the first line
// according to your sample text.
BankTransaction bt = new BankTransaction()
{
Date = dt,
Description = lines[x+1],
Amount = Convert.ToDecimal(lines[x+2]),
Category = currentCat
};
result.Add(bt);
}
else
{
// We are on the category line, get the name and add
// 1 more line to the 3 skipped in the loop
currentCat = line;
x++;
}
}

Format unstructured string

I have tried several methods (by position, by white space, regex) but cannot figure how to best parse the following lines as a table. For e.g. let's say the two lines I want to parse are:
Bonds Bid Offer (mm) (mm) Chng
STACR 2015-HQA1 M1 125 120 5 x 1.5 0
STACR 2015-HQA12 2M2 265 5 x -2
I want that it should parse as follows for [BondName] [Bid] [Offer]:
[STACR 2015-HQA1 M1] [125] [120]
[STACR 2015-HQA12 2M2] [265] [null]
Notice the null which is an actual value and also the spaces should be retained in the bond name. FYI, the number of spaces in the Bond Name will be 2 as in the above examples.
Edit: Since many of you have asked for code here it is. The spaces between the points can range from 1-5 so I cannot reply on spaces (it was straightforward then).
string bondName = quoteLine.Substring(0, 19);
string bid = quoteLine.Substring(19, 5).Trim();
string offer = quoteLine.Substring(24, 6).Trim();
The only way I can see this working is that:
1st data point is STACR (Type)
2nd data point is the year and Series
(e.g. 2015-HQA1)
3rd data point is Tranche (M1)
4th data point is bid
(e.g. 125 ** bid is always available **)
5th data point is offer (e.g. 120 but can be blank
or whitespace which introduces complexity)
With the current set of requirements, I'm assuming the following
1. String starts with 3 part bond name
2. Followed by bid
3. Followed by offer (optional)
4. After that, we'll have something like ... x ... ... (we'll use x as reference)
Given they are valid, you can use the following code
var str = "STACR 2015-HQA1 M1 125 120 5 x 1.5 0"; //your data
var parts = str.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList();
//we'll use this pattern : <3 part bond name> <bid> <offer/null> <something x ....>
var xIsAt = parts.IndexOf("x"); //we'll use x as reference
if (xIsAt > 2) //first three are BondName
parts.RemoveRange(xIsAt - 1, parts.Count - xIsAt + 1); //remove "5 x 1.5 ..."
var bond = string.Join(" ", parts.Take(3)); //first 3 parts are bond
var bid = parts.Count > 3 ? parts.ElementAt(3) : null; //4th is bid
var offer = parts.Count > 4 ? parts.ElementAt(4) : null; //5th is offer
[EDIT]
I did not account for the blank 'Offer' so this method will fail on a blank 'Offer'. Looks like someone already has a working answer, but i'll leave the linq example for anyone that finds it useful.
[END EDIT]
Linq based option.
Split the string by spaces, and remove empty spaces. Then reverse the order so you can start from the back and work your way forward. The data appears more normalized at the end of the string.
For each successive part of the line, you skip the previous options and only take what you need. For the last part which is the long string, you skip what you don't need, then reverse the order back to normal, and join the segments together with spaces.
string test = "STACR 2015-HQA1 M1 125 120 5 x 1.5 0";
var split_string_remove_empty = test.Split(new char[]{ ' ' }, StringSplitOptions.RemoveEmptyEntries).Reverse();
var change = split_string_remove_empty.Take(1)
.SingleOrDefault();
var mm2 = split_string_remove_empty.Skip(1)
.Take(1)
.SingleOrDefault();
var mm3 = split_string_remove_empty.Skip(3)
.Take(1)
.SingleOrDefault();
var offer = split_string_remove_empty.Skip(4)
.Take(1)
.SingleOrDefault();
var bid = split_string_remove_empty.Skip(5)
.Take(1)
.SingleOrDefault();
var bonds = string.Join(" ", split_string_remove_empty.Skip(6)
.Reverse());
Output:

Concatenate strings together starting at specific position

I want to concatenate multiple strings together but shown in a neat way.
Example
Record[1] Title : xxxxxx Date : dd/mm/yy
Record[1000] Title : xxxxxx Date : dd/mm/yy
If i just concatenate the strings together as the record number increases the Title and Date would be pushed across the screen looking messy(shown above). I want the Title and Date to always start at certain position (say position 25) in the string so no matter the number of the record length is the Title and Date will align down the page.
This string will update the Treeview node text.
Consider using composite formatting, specifically the alignment parameter of the format string.
The optional alignment component is a signed integer indicating the preferred formatted field width. If the value of alignment is less than the length of the formatted string, alignment is ignored and the length of the formatted string is used as the field width. The formatted data in the field is right-aligned if alignment is positive and left-aligned if alignment is negative. If padding is necessary, white space is used. The comma is required if alignment is specified.
var s="";
foreach (var item in col) {
s += String.Format("Record[{0,-6}] Title: {1,-15} Date: {2}", item.ID, item.Title, item.Date);
}
Example using StringBuilder for effeciency:
var sb = new StringBuilder();
foreach (var item in col) {
sb.AppendFormat("Record[{0,-6}] Title: {1,-15} Date: {2}", item.ID, item.Title, item.Date);
}
You can use PadRight() to ensure your first string has the right length:
var record = "Record[1]";
var title = "Title : xxxxxx Date : dd/mm/yy .";
var output = record.PadRight(25) + title;
This works for me:
var paddingRecord = items.Select(x => x.Record.ToString().Length).Max();
var paddingTitle = items.Select(x => x.Title.Length).Max();
var result =
String.Join(Environment.NewLine,
items.Select(x =>
String.Format(
"Record[{0}]{1} Title : {2}{3} Date : {4:dd/MM/yy}",
x.Record,
"".PadLeft(paddingRecord - x.Record.ToString().Length),
x.Title,
"".PadLeft(paddingTitle - x.Title.Length),
x.Date)));
I get this for result:
Record[1] Title : Foo Date : 23/05/14
Record[1000] Title : Foo Bar Date : 23/05/14

Searching for data in a console App!

using System;
using System.IO;
using System.Collections;
namespace ReadFiles
{
class Program
{
static void Main(string[] args)
{
StreamReader objstream = new StreamReader("c:\\documents and settings\\btallos\\desktop\\Company.txt");
string sLine ="";
ArrayList arrText = new ArrayList();
while (sLine != null)
{
sLine = objstream.ReadLine();
if (sLine != null)
arrText.Add(sLine);
}
objstream.Close();
foreach (string sOutput in arrText)
Console.WriteLine(sOutput);
Console.ReadLine();
}
}
}
I wrote a console app that displays information from a local file on my desktop and displays the content within the file. I was wondering how can I create a function that can search for keywords and only display the words, I want it to search for?
Can anyone help me out?
You should use the generic List instead of an ArrayList. You can then use the Where method and provide a string to search for, like this:
var lines = File.ReadAllLines("filename").ToList(); // Read all lines and cast it to a List<string>
var matches = lines.Where(x => x == "query");
foerach(var match in matches)
{
Console.WriteLine(match);
}
This will find all items equal to your query.
You can easily expand this to search for items containing your query by switching x => x == "query" to x => x.Contains("query")
I would start with File.ReadAllText and the push on to System.Text.RegularExpressions.Regex
Fuzzy requirements, but this is the solution from what I understood:
var keywords = new string[] {"some", "keywords"};
var foundKeywords = File.ReadAllLines("filename").
SelectMany(line => keywords.Where(keyword => line.Contains(keyword))).
Distinct();
The criteria can be improved (with a regular expression, for example). Currently it will also return you the keywords that are substrings of other words.
I'm going to try to put this content into a database - And then search for the content I want it to display.
* ZIP Codes
* Area Codes
* City Name
* State Name
* Two digit State Code
* City Type
* City Alias Abbrev.
* County Name
* State FIPS
* County FIPS
* Time Zone
* Daylight Savings Indicator
* Number of Businesses
* Q1 Payroll
* Annual Payroll
* Number of Employees
* Employment Flag
* County Growth Rate
You could figure out how you want to highlight the text you want to search in a console app (say be pre/postpending $$search text$$). Open each document and run a regex replace. If that returns a string length different than original, you have matches. If you don't want to show the whole document, I would get 50 characters before, and 50 after for example, but that might take a bit more work. Crude, but simple.

Categories