Salesforce Apex -- Better way at achieving a nested table output - salesforce

public pageReference getData(){
date sd = date.parse(sDate).toStartOfWeek();
date ed = date.parse(eDate);
hList = new list<Hours__c>([SELECT Name,Employee__r.Id,Date_worked__c,Employee__r.Offshore__c,Employee__r.Name,Employee__r.Department__c,Employee_Name__c,hours__c,Minutes__c,Hours_Decimal__c FROM Hours__c WHERE Type_of_Hours__c = 'Work' AND Date_worked__c >= :sd AND Date_worked__c <= :ed AND Employee__r.Department__c IN :selected ORDER BY Employee__r.Department__c,Date_worked__c,Employee__r.Name LIMIT 3000]);
wrap = new list<wrapper>();
string tempDepartment;
string tempEmpName;
date tempWorkDate;
date tempStart = sd;
decimal offshore = 0;
decimal onshore = 0;
decimal totalOffshore = 0;
decimal totalOnShore = 0;
decimal dateCount = 0;
decimal aggreagteTotal = 0;
integer hitLimit = 3000;
integer rpwp = 0;
integer compareRPWP = 0;
boolean fired = false;
boolean dateChanged = false;
boolean dateCountis13 = false;
map<date,integer> mapDateCount = new map<date,integer>();
if(hList.size() > 0 && hList.size() < hitLimit){
noResults = false;
for(Hours__c h: hList){
//initiate a new wrapper for each department as a primary header
if( (h.Employee__r.Department__c != null && ((tempDepartment != null && tempDepartment != h.Employee__r.Department__c) || ( tempDepartment == null)) ) ){
fired = true;
tempDepartment = h.Employee__r.Department__c;
wrap.add(new wrapper(null,null,null,null,null,tempDepartment,'','','',null,'',''));
}else{
fired = false;
}
if(fired || dateCountis13){
dateCountis13 = false;
dateCount = 0;
totalOffshore = 0;
totalOnShore = 0;
}
//initiate a new wrapper for each new week period, total employee hours for each week period for each department
if(fired || (h.Date_worked__c != null && ((tempWorkDate != null && tempWorkDate != h.Date_worked__c) || ( tempWorkDate == null)) ) || (h.Employee__r.Department__c != null && ((tempDepartment != null && tempDepartment != h.Employee__r.Department__c) || ( tempDepartment == null)) ) ){
dateChanged = true;
tempWorkDate = h.Date_worked__c;
offshore = 0;
onshore = 0;
rpwp = 0;
dateCount++;
for(Hours__c h1: hList){
//get count of each record that is inside a given week period
if(h1.Date_worked__c == tempWorkDate && h1.Employee__r.Department__c == tempDepartment){
rpwp++;
}
//logic for totaling offshore hours by date and department
if(h1.Date_worked__c == tempWorkDate && h1.Employee__r.Offshore__c && h1.Employee__r.Department__c == tempDepartment){
offshore += h1.Hours_Decimal__c != null ? h1.Hours_Decimal__c : 0;
}
//logic for totaling onshore hours by date and department
if(h1.Date_worked__c == tempWorkDate && h1.Employee__r.Offshore__c == false && h1.Employee__r.Department__c == tempDepartment){
onshore += h1.Hours_Decimal__c != null ? h1.Hours_Decimal__c : 0;
}
}
system.debug('rpwp: ' + rpwp);
wrap.add(new wrapper(h.Date_worked__c.toStartOfWeek(),h.Date_worked__c,onshore,offshore,null,'total','','','',null,'',''));
totalOffshore += offshore;
totalOnShore += onshore;
system.debug('OffShore: ' + offshore + ' ' + tempWorkDate.format());
system.debug('OnShore: ' + onshore + ' ' + tempWorkDate.format());
}else{
dateChanged = false;
}
//initiate a new wrapper for each record and give the ability to open and collapse all records under a given total week period
// functionality now does an aggregate total of employee's that have multiple hour entrees for each week period.
if( dateChanged || (h.Employee__r.Name != null && ((tempEmpName != null && tempEmpName != h.Employee__r.Name) || ( tempEmpName == null)) ) ){
tempEmpName = h.Employee__r.Name;
aggreagteTotal = 0;
for(Hours__c h2: hList){
if(tempEmpName == h2.Employee__r.Name && tempWorkDate == h2.Date_worked__c){
aggreagteTotal += h2.Hours_Decimal__c;
}
}
if(h.Employee__r.Offshore__c){
wrap.add(new wrapper(h.Date_worked__c.toStartOfWeek(),h.Date_worked__c,0,h.hours__c,aggreagteTotal,'collapse',h.Employee__r.Name,h.Employee__r.Id,h.Name,h.Employee__r.Offshore__c,h.Employee__r.Department__c,h.Date_worked__c.format() ));
}else{
wrap.add(new wrapper(h.Date_worked__c.toStartOfWeek(),h.Date_worked__c,h.hours__c,0,aggreagteTotal,'collapse',h.Employee__r.Name,h.Employee__r.Id,h.Name,h.Employee__r.Offshore__c,h.Employee__r.Department__c,h.Date_worked__c.format() ));
}
}
//compare record count on the outside loop to record count on the inner loop and set compare iterator to 0 if the date changes
if(dateChanged){
compareRPWP = 0;
}
compareRPWP++;
system.debug('compareRPWP: ' + compareRPWP );
//if on the 13th week -- initiate a new wrapper and get quarterly totals -- compare record count so that inner loop matches outer loop
if( (dateCount == 13 && compareRPWP == rpwp) ){
system.debug('totalOffshore: ' + totalOffshore );
system.debug('totalOnShore: ' + totalOnShore );
dateCountis13 = true;
wrap.add(new wrapper(null,null,totalOnShore,totalOffshore,null,'quarter',tempDepartment,'','',null,'',''));
}
}
}else if(hList.size() <= 0){
noResults = true;
bannerMessage = 'Oops! No record found.';
}else if(hList.size() >= hitLimit){
noResults = true;
bannerMessage = 'Oops! 3000 Record limit hit.';
}else{
noResults = true;
bannerMessage = 'Oops! 50000 record limit hit.';
}
system.debug('wrap: ' + wrap);
system.debug('hList: ' + hList);
return null;
}
Here is my working method inside my class. Essentially I am doing a query on a custom object Hours__c. What I want to do is have the output on the table be first nested by each employee department. Then Nested by each work period, with all hours worked by that department for each work period. I essentially achieved this from the start by ordering the query that way. Now it was about how to make the logic grab it at the time I needed. But it also needed to aggregate the total hours if employees had more than one hour record per week period. I also finally after every 13 weeks output a total of hours for that quarter.
Here is a screencast of my custom report if you are interested in seeing what I achieved on the front-end but what I want to achieve on the backend and in a more effecient manner. The problem with my logic, is while it works, if there is a lot of data being queried. This logic is pretty slow. Because first it loops the query results once. but inside the first for loop I loop the same query 2 different times... ::slaps head:: ...I know it is terrible.
So I want to see maybe if there is a more effecient way of achieving this with potentially a map or another wrapper class? Because it is all in one wrapper class too. I use front end logic to sort out the table based on results in the wrapper class. I just hide and show rows. Like i said, it works just not as effecient as I would like my logic to run.
here is the screen cast:
https://screencast-o-matic.com/watch/cF60cwYAiB

My first idea is about preparing new Map<Date, List<Hour__c>> dateWorkedToHoursMap map in controller just after your SOQL. With this map you will be able to get quickly Hour__c records by specic Date (Date_worked__c) and go only through them in your sub for loops.
public class Controller {
// (...)
Map<Date, List<Hour__c>> dateWorkedToHoursMap; // New map in controller
// (...)
// Updated "getData()" method which will prepare "dateWorkedToHoursMap"
// map just after SOQL and then will use in both sub for loops
public pageReference getData() {
// (...)
// Your SOQL for Hour__c records
// dateWorkedToHoursMap = prepareDateWorkedToHoursMap(hList);
// (...)
// main for through hList
// (...)
// 1 sub for through list returned by: dateWorkedToHoursMap.get(h.Date_worked__c)
// (...)
// 2 sub for through list returned by: dateWorkedToHoursMap.get(h.Date_worked__c)
// (...)
// end of main for
}
// New "prepareDateWorkedToHoursMap()" method used to prepare "dateWorkedToHoursMap" map
private void prepareDateWorkedToHoursMap(List<Hour__c> hours) {
dateWorkedToHoursMap = new Map<Date, List<Hour__c>>();
for(Hour__c hour : hours) {
if(hour.Date_worked__c != null) {
if(!dateWorkedToHoursMap.containsKey(hour.Date_worked__c)) {
dateWorkedToHoursMap.put(hour.Date_worked__c, new List<Hour__c>());
}
dateWorkedToHoursMap.get(hour.Date_worked__c).add(h);
}
}
}
}
If you think that it will be better then you can try to prepare map like:
Map<String, Map<Date, List<Hour__c>>> departmentToDateWorkedToHoursMap
And then you should be able to quickly get the list of Hour__c records based on DEPARTMENT and DATE WORKED.

Related

google apps script refactor repetitive code

What's a smarter way of doing this? Code works fine but is klunky.
function removeEmptyPending(){
for(var row=2;row<=lastRow;row++){
if( (tkhContact.getRange('A'+row+':A'+row).getValue() == "") &&
(tkhContact.getRange('C'+row+':C'+row).getValue() == "") &&
(tkhContact.getRange('D'+row+':D'+row).getValue() == "") &&
(tkhContact.getRange('E'+row+':E'+row).getValue() == "") &&
(tkhContact.getRange('F'+row+':F'+row).getValue() == "") &&
(tkhContact.getRange('G'+row+':G'+row).getValue() == "") &&
(tkhContact.getRange('H'+row+':H'+row).getValue() == "") &&
(tkhContact.getRange('I'+row+':I'+row).getValue() == "") &&
(tkhContact.getRange('J'+row+':J'+row).getValue() == "") &&
(tkhContact.getRange('K'+row+':K'+row).getValue() == "") &&
(tkhContact.getRange('L'+row+':L'+row).getValue() == "") &&
(tkhContact.getRange('M'+row+':M'+row).getValue() == "") &&
(tkhContact.getRange('N'+row+':N'+row).getValue() == "") &&
(tkhContact.getRange('O'+row+':O'+row).getValue() == "") &&
(tkhContact.getRange('P'+row+':P'+row).getValue() == "") &&
(tkhContact.getRange('Q'+row+':Q'+row).getValue() == "") )
{
tkhContact.deleteRow(row); // tkhContact.getRange('R'+row+':R'+row).setValue("");
}
}
}
I need to skip column B since there is a formula there so it's never really blank.
Use #is_Blank()
function removeEmptyPending(){
for(var row=lastRow;row>=2;row--){
if( (tkhContact.getRange('A'+row+':A'+row).isBlank()) &&
(tkhContact.getRange('C'+row+':Q'+row).isBlank()) &&
){
tkhContact.deleteRow(row); //tkhContact.getRange('R'+row+':R'+row).setValue("");
}
}
}
This code gets all the data from row 2 to the last row, including columns A through Q. And then goes through the data. So, it gets all the data in one operation. The rows need to be deleted individually, and they must be deleted from the bottom up. That means that the outer "for" loop must decrement the counter. If you start deleting from the top down, then the row numbers from the last row deleted, change their row number.
function removeEmptyPending() {
var data,i,j,L,L2,lastRow,row,thisRow,thisValue;
data = tkhContact.getRange(2,1,lastRow-1,17).getValues();//Get all the data from row 2 to the last row
//including column A to column Q
L = data.length;//The number of inner arrays in the outer array
for (i=L;i>0,i--){//Loop through all the rows from last to row 2
thisRow = data[i];//Get one inner array which is one row of data
L2 = thisRow.length;
for (j=0;j<L2,j++){//Loop through each element of the inner array which is the column value
if (j === 1) {continue;} //Skip the second element which is column B
thisValue = thisRow[j];//The value for this column
if (thisValue) {continue;}//The value for this cell is not undefined null or empty string so continue
tkhContact.deleteRow(i+2); // tkhContact.getRange('R'+row+':R'+row).setValue("");
}
}
}

extjs calendar 4.1.1 restricted time slot for booking

I am using extjs 4.1.1 calendar ( scheduler ) for keeping the track of people schedule but i can into trouble as i cant figure out how to restrict the booking time slot for individual
example.
User A can book the slot between 3pm to 4 pm on monday to wednesday.
User B Can book slots between 1 am to 5 am on monday and saturday
image link
http://i.stack.imgur.com/tuCVV.png
This may be more complicated than you really want to work with, but we had to do this in our app, the only real way to do it is to override their Extensible.calendar.dd.DropZone class and overwrite the onNodeOver method with your own logic, hope you understand the Extjs well :) :
Ext.override("Extensible.calendar.dd.DropZone", {
onNodeOver : function(n, dd, e, data){
//change anything in this logic with the logic you want....
//but preferrably, don't change anything and use callOverridden and then add your stuff as extras
var D = Extensible.Date,
start = data.type == 'eventdrag' ? n.date : D.min(data.start, n.date),
end = data.type == 'eventdrag' ? D.add(n.date, {days: D.diffDays(data.eventStart, data.eventEnd)}) :
D.max(data.start, n.date);
if(!this.dragStartDate || !this.dragEndDate || (D.diffDays(start, this.dragStartDate) != 0) || (D.diffDays(end, this.dragEndDate) != 0)){
this.dragStartDate = start;
this.dragEndDate = D.add(end, {days: 1, millis: -1, clearTime: true});
this.shim(start, end);
var range = Ext.Date.format(start, this.dateFormat);
if(D.diffDays(start, end) > 0){
end = Ext.Date.format(end, this.dateFormat);
range = Ext.String.format(this.dateRangeFormat, range, end);
}
var msg = Ext.String.format(data.type == 'eventdrag' ? this.moveText : this.createText, range);
data.proxy.updateMsg(msg);
}
return this.dropAllowed;
}
});

Evaluating equality in perl using elements taken from an array ref

I have a small perl script that needs to evaluate the equality of two parameters and a small return from the database.
my ($firstId, $secondId, $firstReturnedId, $secondReturnedId, $picCount);
my $pics = $dbh->prepare(qq[select id from pictures limit 10]);
$firstId = q->param('firstId');
$secondId = q->param('secondId');
$pics->execute or die;
my $picids = $pics->fetchall_arrayref;
$picCount = scalar(#{$picids});
$firstReturnedId = $picCount > 0 ? shift(#{$picids}) : 0;
$secondReturnedId = $picCount > 1 ? pop(#{$picids}) : $firstReturnedId;
Here, a quick look at my debugger shows that $picCount = 1 and $firstReturnedId = 9020 and $secondReturnedId = 9020. However, they are both denoted as
ARRAY(0x9e79184)
0 9020
in the debugger so when I perform the final check
my $result = (($firstId == $firstReturnedId) && ($secondId == $secondReturnedId)) ? 1 : 0;
I get $result = 0, which is not what I want.
What am I doing wrong?
DBI::fetchall_arrayref returns a reference to a list of "row results". But since there could be more than one value in a row result (e.g., your query could have been select id,other_field from pictures), each row result is also a reference to a list. This means you have one more dereferencing to do in order to get the result you want. Try:
$picCount = scalar(#{$picids});
if ($picCount > 0) {
my $result = shift #{$picids};
$firstReturnedId = $result->[0];
} else {
$firstReturnedId = 0;
}
if ($picCount > 1) {
my $result = pop #{$picids};
$secondReturnedId = $result->[0];
} else {
$secondReturnedId = $firstReturnedId;
}
or if you still want to use a concise style:
$firstReturnedId = $picCount > 0 ? shift(#{$picids})->[0] : 0;
$secondReturnedId = $picCount > 1 ? pop(#{$picids})->[0] : $firstReturnedId;

Mom file creation (5 product limit)

Ok, I realize this is a very niche issue, but I'm hoping the process is straight forward enough...
I'm tasked with creating a data file out of Customer/Order information. Problem is, the datafile has a 5 product max limit.
Basically, I get my data, group by cust_id, create the file structure, within that loop, group by product_id, rewrite the fields in previous file_struct with new product info. That's worked all well and good until a user exceeded that max.
A brief example.. (keep in mind, the structure of the array is set by another process, this CANNOT change)
orderArray = arranyew(2);
set order = 1;
loop over cust_id;
field[order][1] = "field(1)"; // cust_id
field[order][2] = "field(2)"; // name
field[order][3] = "field(3)"; // phone
field[order][4] = ""; // product_1
field[order][5] = ""; // quantity_1
field[order][6] = ""; // product_2
field[order][7] = ""; // quantity_2
field[order][8] = ""; // product_3
field[order][9] = ""; // quantity_3
field[order][10] = ""; // product_4
field[order][11] = ""; // quantity_4
field[order][12] = ""; // product_5
field[order][13] = ""; // quantity_5
field[order][14] = "field(4)"; // trx_id
field[order][15] = "field(5)"; // total_cost
counter = 0;
loop over product_id
field[order[4+counter] = productCode;
field[order[5+counter] = quantity;
counter = counter + 2;
end inner loop;
order = order + 1;
end outer loop;
Like I said, this worked fine until I had a user who ordered more than 5 products.
What I basically want to do is check the number of products for each user if that number is greater than 5, start a new line in the text field, but I'm stufk on how to get there.
I've tried numerous fixes, but nothing gives the results I need.
I can send the entire file if It can help, but I don't want to post it all here.
You need to move the inserting of the header and footer fields into product loop eg. the custid and trx_id fields.
Here's a rough idea of one why you can go about this based on the pseudo code you provided. I'm sure that there are more elegant ways that you could code this.
set order = 0;
loop over cust_id;
counter = 1;
order = order + 1;
loop over product_id
if (counter == 1 || counter == 6) {
if (counter == 6) {
counter == 1;
order= order+1;
}
field[order][1] = "field(1)"; // cust_id
field[order][2] = "field(2)"; // name
field[order][3] = "field(3)"; // phone
}
field[order][counter+3] = productCode; // product_1
field[order][counter+4] = quantity; // quantity_1
counter = counter + 1;
if (counter == 6) {
field[order][14] = "field(4)"; // trx_id
field[order][15] = "field(5)"; // total_cost
}
end inner loop;
if (counter == 6) {
// loop here to insert blank columns and the totals field to fill out the row.
}
end outer loop;
One thing goes concern me. If you start a new line every five products then your transaction id and total cost is going to be entered into the file more than once. You know the receiving system. It may be a non-issue.
Hope this helps
As you put the data into the row, you need check if there are more than 5 products and then create an additional line.
loop over product_id
if (counter mod 10 == 0 and counter > 0) {
// create the new row, and mark it as a continuation of the previous order
counter = 0;
order = order + 1;
field[order][1] = "";
...
field[order][15] = "";
}
field[order[4+counter] = productCode;
field[order[5+counter] = quantity;
counter = counter + 2;
end inner loop;
I've actually done the export from an ecommerce system to MOM, but that code has since been lost. I have samples of code in classic ASP.

"Week of the year" Algorithm needs improvements

I have an algorithm which scans through data read from a .csv file(approx 3700 lines) and assess's which trading week of the year each entry is in by running a count++ for every Sunday of that year and assigning the count value as the trading week when the date falls within that week.
It's working but performance is lagging. It is the 3rd function running using Task.Factory.StartNew (I have also tried parallel.Invoke).
Results of timing tests.
before: 00:00:05.58
after: 00:00:23.27
UPDATE
Added break after each trading week is set. Time improved but still slow.
new time: 00:00:15.74
For our purposes the 1st week of the year is week 1(not 0) and is defined as from the first day of the year until the Sunday. If the first day of the year is a Sunday the length of week 1 is 1 day.
private void SetDefiniteWeeks()
{
string FileLoc = FilePath + Market + ".csv";
string[] Data = File.ReadAllLines(FileLoc);
var FileData = from D in Data
let DataSplit = D.Split(',')
select new
{
Date = DateTime.Parse(DataSplit[0]),
ClosingPrice = double.Parse(DataSplit[4])
};
//assign each date to it's relevant week
TradingWeek TW;
List<TradingWeek> tradingWeek = new List<TradingWeek>();
foreach (var pe in FileData)
{
// DateTime dt = pe.Date;
int Year = pe.Date.Year;
string End_of_Week = "Sunday";
int WeekCount = 0;
DateTime LoopDate_Begin = new DateTime(Year,1,1);
DateTime LoopDate_End = new DateTime(Year,12,31);
do
{
if (LoopDate_Begin.DayOfWeek.ToString() == End_of_Week)
{
WeekCount++;
if (LoopDate_Begin.DayOfYear > pe.Date.DayOfYear && LoopDate_Begin.DayOfYear < (pe.Date.DayOfYear + 7))
{
TW = new TradingWeek { Week = WeekCount, Date = pe.Date };
tradingWeek.Add(TW);
break;
}
}
LoopDate_Begin = LoopDate_Begin.AddDays(1);
} while (LoopDate_Begin.Date.ToString() != LoopDate_End.Date.ToString());
}
}
Please help.
UPDATE
NEW TIME
00:00:06.686
A vast improvement. Thanks all for your help.
Revised code:
CalendarWeekRule cw = CalendarWeekRule.FirstDay;
var calendar = CultureInfo.CurrentCulture.Calendar;
var trad_Week = (from pe in FileData
select new TradingWeek
{
Date = pe.Date,
Week = (calendar.GetWeekOfYear(pe.Date, cw,DayOfWeek.Sunday))
}).ToList();
Im not sure if this is what you want but after reading the comments I got the feeling that this might work (?)
var calendar = CultureInfo.CurrentCulture.Calendar;
var tradingWeek = (from pe in FileData
select new TradingWeek
{
Date = pe.Date,
Week = calendar.GetWeekOfYear(pe.Date, CalendarWeekRule.FirstDay, DayOfWeek.Sunday);
}).ToList();
Edit: Changed to CalendarWeekRule.FirstDay since it's (more?) what OP is looking for.
Three quick thoughts:
Why are you only adding one day each time and checking to see if it's Sunday. Surely once you have found your first Sunday you can add seven days to find the next one?
If you order your pes by DateTime before you start then you don't need to restart at the beginning of the year for each one, you can pick up where you left off.
As Nicolas says, break after adding the trading week. No need to go through the rest of the year after you already know what the answer is.
I guess you'll end up with something like this (may or may not actually work, but should be close enough)
TradingWeek TW;
List<TradingWeek> tradingWeek = new List<TradingWeek>();
string End_of_Week = "Sunday";
var orderedData = FileData.OrderBy(x => x.Date)
DateTime LoopDate_Begin = new DateTime(orderedData[0].Date.Year,1,1);
int WeekCount = 1;
while (LoopDate_Begin.DayOfWeek.ToString() != End_of_Week)
{
LoopDate_Begin = LoopDate_Begin.AddDays(1);
}
foreach (var pe in orderedData)
{
do
{
if (LoopDate_Begin.DayOfYear > pe.Date.DayOfYear && LoopDate_Begin.DayOfYear < (pe.Date.DayOfYear + 7))
{
TW = new TradingWeek { Week = WeekCount, Date = pe.Date };
tradingWeek.Add(TW);
break;
}
WeekCount++;
LoopDate_Begin = LoopDate_Begin.AddDays(7);
} while (true); //need to be careful here
}
if I get you correctly, you don't need to look any further as soon as you've added your TradingWeek
So, you can
break;
after
tradingWeek.Add(TW);
You could then even leave out the
&& LoopDate_Begin.DayOfYear < (pe.Date.DayOfYear + 7)
condition since the first part is going to be true only once: for your desired interval.
You might even go for a loopless approach by dividing the number of days since your starting week by 7 - and doing some cleaning up work ;)
Can you get rid of your do loop altogether by calculating the Week Number directly? Something like the accepted answer here.
Following #nicolas78's response, something like this should work
int Year = pe.Date.Year;
DateTime Year_Begin = new DateTime(Year,1,1);
int Jan1DayOfWeek = Year_Begin.DayOfWeek;
foreach (var pe in FileData)
{
int WeekCount = (pe.Date.DayOfYear - Jan1DayOfWeek) % 7 + 1;
TradingWeek TW = new TradingWeek { Week = WeekCount, Date = pe.Date };
tradingWeek.Add(TW);
}
Depending on how DayOfWeek and DayOfYear count, that is from 0 or 1, and how your mod operation work, you may need to tweak the WeekCount computation a bit.
There's a built-in feature to get the week of the year based on the date in .NET. An example is shown below, but it may need some tweaking to fit your business scenario:
System.Globalization.CultureInfo myCI = new System.Globalization.CultureInfo("en-US");
int week = myCI.Calendar.GetWeekOfYear(DateTime.Now.ToUniversalTime(), System.Globalization.CalendarWeekRule.FirstFourDayWeek, System.DayOfWeek.Sunday);
You don't need to count at all - just do a quick calculation. This assumes that a partial week at the start of the year is week 1 and week 2 begins on the first Monday.
List<TradingWeek> tradingWeek = new List<TradingWeek>();
foreach (var pe in FileData)
{
var date = pe.Date;
while (date.DayOfWeek != DayOfWeek.Sunday)
date = date.AddDays(1);
var week = date.DayOfYear/7+1;
var TW = new TradingWeek {Week = week, Date = pe.Date};
tradingWeek.Add(TW);
}

Resources