C# Crystal Reports Removing Duplicates - c#

I am generating a report base on projects and their data, the original result for this is:
But as you can see there are a lot of duplicates...
I resolved this by using the following formula in the section expert for supressing:
{Projecten1.Project ID} = next({Projecten1.Project ID})
Now the result is:
This is exactly what I want it to be however, the prices are no longer correct...
I would like the prices to add up if there are duplicates so that:
160629 = 2312,5
170109 = 125,0
The current formula I have for the prices is:
if {Gegevens1.OpLocatie} = 1 and(DATE(ToText({Gegevens1.Datum}, "dd/MM/yyyy")) >= DATE({?ParStart}) and DATE(ToText({Gegevens1.Datum}, "dd/MM/yyyy")) <= DATE({?ParStop})) Then
(ToNumber({#fUren}) * {?ParTariefLocatie}) + {#fBerekeningen} + {#fKM}
Else if {Gegevens1.OpLocatie} = 0 and (DATE(ToText({Gegevens1.Datum}, "dd/MM/yyyy")) >= DATE({?ParStart}) and DATE(ToText({Gegevens1.Datum}, "dd/MM/yyyy")) <= DATE({?ParStop})) Then
(ToNumber({#fUren}) * {?ParTariefKantoor}) + {#fBerekeningen} + {#fKM}
Else
0
In case you are wondering, the prices are linked to the data (hours worked) for each project, like this:
So that's why it's duping the projects
Is there any way to remove the duplicates AND add up the prices if there are duplicates?
Thanks

You can use Group expert and Running total by using the created Group.
1. right click blank white section of your report > Report > Group Expert.
2. create new in running total.
3.select field to summarize.
4.Sum
5.for each record.
6.on group change.

Related

How to perform addition to number rather than appending to end in Linq

Trying to update a table in ASP.net MVC with a Linq query. It works fine in terms of actually doing the update, but I can't figure out how to mathematically update it. For example, the Printer Credit Fund was set to "50", added 12 to it then sets it "5012" as opposed to "62". The following is the code that is doing the update:
tblOption fund = (
from n in db.tblOptions
where n.ID == 1
select n).First();
fund.PrinterCreditFund = fund.PrinterCreditFund + tblPrinterCredit.Money;
We're using Entity Framework if that makes any sort of a difference.
Any tips towards the right direction of doing a mathematical update rather than appending the value would be hugely appreciated.
Many thanks
That's it. Convert fund.PrinterCreditFund and tblPrinterCredit.Money to using Convert.ToInt32() and also make sure fund.PrinterCreditFund is also int type
tblOption fund = (
from n in db.tblOptions
where n.ID == 1
select n).First();
fund.PrinterCreditFund = Convert.ToInt32( fund.PrinterCreditFund) + Convert.ToInt32( tblPrinterCredit.Money);
I guess that either Money is a string. Then the + operator concats them instead of summing the values. So both must be a numeric type, for example int:
fund.PrinterCreditFund = fund.PrinterCreditFund + int.Parse(tblPrinterCredit.Money);
Of course it would be better to not store a number as string in the first place.

Sum up every x values in a row

I have a column calendar week and a column amount. Now I want to sum up the amount for every 4 calendar weeks starting from the first calendar week in April. E.g. if I have 52 (rows) calendar weeks in my initial table I would have 13 (rows) weeks in my final table (I talk about table here since I will try to bind the outcome later to a DGV).
I am using Linq-to-dataset and tried different sources to get a hint how to solve this but group by, aggregate couldnt help me but maybe there are some applications of them that I dont understand so I hope one of you Linq-Experts can help me.
Usually I post code but I can just give you the backbone since I have no starting point.
_dataset = New Dataset1
_adapter.Fill(_dataset.Table1)
dim query = from dt in _dataset.Table1.AsEnumerable()
Divide the week by four (using integer division to truncate the result) to generate a value that you can group on.
You can group by anything you like. You could, theoretically, use a simple incrementing number for that:
var groups = dt
.Select((row, i) => Tuple.Create(row, i / 4))
.GroupBy(t => t.Item2);
(c# notation)
Then you can calculate the sum for each group:
var sums = groups
.Select(g => g.Sum(t => t.Item1.Amount));
You mention you want to start at a certain month, e.g. April. You can skip rows by using Skip or Where:
dt.Skip(12).Select(...)
i will always start at 0, making sure your first group contains 4 weeks. However, to know exactly how many weeks to skip or where to start you need more calendar information. I presume you have some fields in your rows that mention the corresponding week's start date:
dt.Where(row => row.StartDate >= firstOfApril).Select(...)
first convert the data into a lookup with the month and then the amount. Note your columns need to be called CalendarWeek and Amount. Then convert to a dictionary and sum the values per key:
var grouped = dt.AsEnumerable().ToLookup(o => Math.Ceiling((double) o.Field<int>("CalendarWeek")/4), o => o.Field<double>("Amount"));
var results = grouped.ToDictionary(result => result.Key, result => result.Sum());

Generate Short Random Uniquer Promotional Codes

On a C# application I need to create UNIQUE Promotional codes.
The promotional codes will be store in a SQL Table (SQL Server 2012).
Initially I though of GUIDS but they are to long to give to users.
I am considering a 6 alphanumeric code resulting in 52 521 875 unique combinations.
What do you think?
But how to generate the code so it is UNIQUE? I am considering:
Use random;
Use ticks of current datetime
Pre generate all codes in the database and pick it randomly ...
This approach has the problem of occupying two much space.
What would be a good approach to generate the random unique code?
UPDATE 1
For the approach in 1 I came up with the following C# code:
Random random = new Random();
Int32 count = 20;
Int32 length = 5;
List<String> codes = new List<String>();
Char[] keys = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".ToCharArray();
while (codes.Count < count) {
var code = Enumerable.Range(1, length)
.Select(k => keys[random.Next(0, keys.Length - 1)]) // Generate random char
.Aggregate("", (e, c) => e + c); // Join into a string
codes.Add(code);
}
UPDATE 2
String source = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
while (codes.Count < count) {
length = 5;
StringBuilder builder = new StringBuilder(5);
while (length-- > 0)
builder.Append(source[random.Next(source.Length)]);
codes.Add(builder.ToString());
}
Which approach do you think is faster?
Thank You,
Miguel
Eric Lippert showed how to use a multiplicative inverse to obfuscate sequential keys. Basically, the idea is to generate sequential keys (i.e. 1, 2, 3, 4, etc.) and then obfuscate them.
I showed a more convoluted way to do it in my article series Obfuscating Sequential Keys.
The beauty of this approach is that the keys appear random, but all you have to keep track of is a single number: the next sequential value to be generated.
YouTube uses a similar technique to generate their video IDs.
Don't worry about generating a unique code. Instead . . .
Generate a random code.
Insert that code into a database. It belongs in a column that has a unique index.
Trap the error that results from trying to insert a duplicate value.
If you get a duplicate value error, generate another random code, and try again.
I'd go for number 1.
Number 2 is not that random (you have lower and upper limit), number 3 is an overkill.
Maybe you can use something like this:
DECLARE #VALUES varchar(100)
SET #VALUES = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
SELECT SUBSTRING(#Values, CAST(FLOOR(RAND()*LEN(#Values)) + 1 AS int), 1) +
SUBSTRING(#Values, CAST(FLOOR(RAND()*LEN(#Values)) + 1 AS int), 1) +
SUBSTRING(#Values, CAST(FLOOR(RAND()*LEN(#Values)) + 1 AS int), 1) +
SUBSTRING(#Values, CAST(FLOOR(RAND()*LEN(#Values)) + 1 AS int), 1) +
SUBSTRING(#Values, CAST(FLOOR(RAND()*LEN(#Values)) + 1 AS int), 1) +
SUBSTRING(#Values, CAST(FLOOR(RAND()*LEN(#Values)) + 1 AS int), 1)
Use a table for storing previously generated codes to check for uniqeness.

multiple hits in loop after the break command

I've got a strange problem. I'm creating a NUI for application and I binded some simple gestures to right and left arrow. The problem is when I start application. When I make gesture for the first time my application is hitting 2 times in a row. After that it works 100% as I want. Only the start is the problem.
I'm adding two Joints and timestamp to my history struct which is put into the ArrayList
this._history.Add(new HistoryItem()
{
timestamp = timestamp,
activeHand = hand,
controlJoint = controlJoint
}
);
then in foreach loop I'm comparing data
if (Math.Abs((hand.Position.X - item.controlJoint.Position.X)) < MainWindow.treshold && Math.Abs((hand.Position.Y - item.controlJoint.Position.Y)) < MainWindow.verticalTreshold)
If it hits I instantly break the lopp with
break;
after that I clear the history ArrayList
this._history.Clear();
So I don't get it. Why after the start it hits two times in a row ?
// edit
history ArrayList initialization
private List<HistoryItem> _history = new List<HistoryItem>(16);
in loop
foreach (HistoryItem item in this._history)
{
if ((hand.Position.X - item.controlJoint.Position.X) < MainWindow.treshold)
{
float tmp = (hand.Position.X - controlJoint.Position.X);
MainWindow.slideNumber++;
this._logger.Log("Next slide: " + MainWindow.slideNumber);
this._logger.Log(hand.Position.X + " - " + controlJoint.Position.X + " = " + tmp + " | " + MainWindow.treshold);
this.startTime = 0;
this.gestureStart = false;
answerFlag = true;
System.Windows.Forms.SendKeys.SendWait("{Right}");
break;
}
}
Now. As you can see i'm breaking here. So this code shouldn't be invoked second time in a row
How this clears something
// edit 2
I'll also add that to get into this part of code the gestureStart flag need to be set to true. As you can see after getting into the 'if' part here I'm setting it to false. So it is impossible that the code instantly can get to this part
// edit 3 WORKING WORKAROUND
I've created kind of workaround. I've added time control. I'm comparing timestamp of invoking the code and timestamp of last gesture recognition. If its too fast ( i meen couple of ms which it impossible to make ) I don't allow to hit an arrow. I'm not sure if it's a perfect solution but it is a working solution
Ok my problem was the code. Ofc a small bug untracable in the debug. I used one function to analyse a history of frames.
The method was working in 2 modes. I`ve detached that and created 2 diffrent methods, each for each task and now it works great

Do a Range Search for a Alphabetic Field

I have a application that I save this in the database:
FromLetter ToLetter
AAA AAZ
ABC MNL
what I need is to search like this AAC and returns record 1 and FBC and return record 2.
Is the same functionality if instead of letter I save dates. I need to do the same query.
I am using SQL Server and Entity Framework, any Idea how to do this?
Should be pretty straight forward. Here is a Linq to Entities solution, ignoring case:
Entity Framework/Linq solution strings:
string yourValue = somevalue;
var result = (from r in db.ExampleTable
where String.Compare(yourValue, r.FromLetter, true) == 1
&& String.Compare(yourValue, r.ToLetter, true) == -1
select r).First();
Dates:
DateTime yourValue = somevalue;
var result = (from r in db.ExampleTable
where yourValue >= r.FromDate
&& yourValue <= r.ToDate
select r).First();
I think it would be much easier to represent the FromLetter and ToLetter attributes using an integer. Especially if the length of the string is always just 3 - you can simply encode the number as:
(((letter1 - 'A') * 26 + (letter2 - 'A')) * 26) + (letter3 - 'A')
This will give you a number between 0 and 26^3 that represents the tripple and can be easily converted back to the string (using modulo and division as when converting numbers between numeric bases). This number fits into Int32 comfortably (up to 6 letters).
Searching for a string within a specified range would then be a simple search for an integer within a numeric range (which is easy to do and efficient).
Genius solution given by.... bunglestink
I wasted plenty of time in researching implementation of "between" clause for string in EF. This is helpful.

Categories