SSRS Report Custom Sort Order - sorting

I am having some problem for a custom sorting required for one of row groups that I have in a SSRS table.
The logic for the custom sort order -
If the row group value contains a particular value then it should always be displayed at the bottom and all the other values have to be displayed in the ascending order.
For e.g. -
Suppose from the list of values A,E,G,D,C,and F, "D" should be always be displayed last and the other elements are to be sorted in asc order.
So, the above list should be sorted in the following order -
A,B,C,E,F,G,D
Or if the list of elements is - P,J,M,N,D,C,K
the required sort order is -
C,J,K,M,N,P and D.
This logic has to be implemented for the row group data which gets displayed in the report.
Would appreciate if someone can help me out on this.
Thank you.

Try using the following expression in the Sorting setting.
=IIF(
Fields!YourField.Value="D","ZZZZ" & Fields!YourField.Value,
Fields!YourField.Value
)
This will sort your group if you don't have groups whose four first letters are ZZZZ.
Let me know if this helps.

I use an IIF (or multiple IIFs) to do custom sorts like this.
For your situation:
A,E,G,D,C,and F, D should be always be displayed last and the other
elements are to be sorted in asc
I would first do a custom sort:
=IIF(Fields!MyFIeld.Value = "D", 2, 1)
This would sort the D first.
Then add second Sort that just uses the field (Myfield) to sort the rest by the field.
For the second situation:
if the list of elements is - P,J,M,N,D,C,K the required sort order is C,J,K,M,N,P and D
Then I would make a single custom sort with multiple IIFs:
=IIF(Fields!MyFIeld.Value = "C", 1,
IIF(Fields!MyFIeld.Value = "J", 2,
IIF(Fields!MyFIeld.Value = "K", 3,
IIF(Fields!MyFIeld.Value = "M", 4,
IIF(Fields!MyFIeld.Value = "N", 5,
IIF(Fields!MyFIeld.Value = "P", 6,
IIF(Fields!MyFIeld.Value = "D", 7, 8)))))))
-

I created a tablix with totals and I was able to sort by alphabetic order, total(ascending), total(descending). First I create a Dataset like this:
Select 'Name' as Order_Col, 1 as Order_Num
union
Select 'Ascending' as Order_Col, 2 as Order_Num
union
Select 'Descending' as Order_Col, 3 as Order_Num
order by 2
Then in the column group section, group properties I insert the following expression in the sorting options:
=Switch(Parameters!SortOrder.Value = 1,Fields!Name.Value
,Parameters!SortOrder.Value = 3,(Fields!TtlRef.Value)*-1
,Parameters!SortOrder.Value = 2,Fields!TtlRef.Value)
Create a Parameter named SortOrder where the Value is Order_Num and Label is Order_Col.
You can make a default using a value of 1.

Related

(Power Query) Complicated sort

I have a complicated sorting that I want, and I'm just not sure how to get power query to do it. The TLDR version is "oldest new ones first, then newest old ones." So I want to split the sort between ascending/descending depending on what data are in the columns.
Certain columns on my sheet (I through K) contain the word 'Yes' if it is a new item, otherwise blank. Possible combinations of columns that have 'yes' in them:
I only, J only, K only, I + J, J + K, I + J + K
Here's the sort logic I want:
All rows with a Yes in K are listed first, ascending by date (column H), whether they have 'Yes' in columns I or J or not.
Then, Of only the rows that are left, all rows with a Yes in J, ascending by date (column H)
Next, Of only the rows that are left, all rows with a Yes in I, ascending by date (column H)
Finally, the only rows left should not have a Yes in any columns I-K. Of those rows, DEscending by date (Column H).
I can sort of maybe figure out how to do the sort up through step 3 by creating a custom column to label and identifying whether the row will go in the first, second, or third sort, then sorting by that custom column before sorting the others.
But step 4 is stumping me because of the reverse to descending instead of ascending. I'm thinking maybe grouping the data, sorting it within the group descending and outside the group ascending (as a 4th entry in the custom column that sorted the first 3), and then expanding it back out again after the external sort, or something?
Please help!
Currently I'm only able to sort the sheet ascending and can't sort part of it descending.
Filter a column, then sort it. Filter another column and sort it. etc. Put them together
Load your data into powerquery (data ... from table/range ... )and use code below pasted into home ... advanced editor.... It assumes your data is loaded as Table1 with column headers A,H,I,J,K, so change that to reflect your actual table name and column names. If you have your own code, remove the first row and change the Source in the second row to reflect your #"PriorStepName"
sample code to transform image below on left to image on right:
let Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"A", Int64.Type}, {"H", type date}, {"I", type text}, {"J", type text}, {"K", type text}}),
Part1 = Table.Sort(Table.SelectRows(#"Changed Type", each ([K] = "Yes")),{{"H", Order.Ascending}}),
Part2 = Table.Sort(Table.SelectRows(#"Changed Type", each ([K] <> "Yes" and [J] = "Yes")),{{"H", Order.Ascending}}),
Part3 = Table.Sort(Table.SelectRows(#"Changed Type", each ([K] <> "Yes" and [J] <> "Yes" and [I] = "Yes")),{{"H", Order.Ascending}}),
Part4 = Table.Sort(Table.SelectRows(#"Changed Type", each ([K] <> "Yes" and [J] <> "Yes" and [I] <> "Yes")),{{"H", Order.Descending}}),
Combined = Table.Combine({Part1,Part2,Part3,Part4})
in Combined

Google App Script: Remove blank rows from range selection for sorting

I want to sort real-time when a number is calculated in a "Total" column, which is a sum based on other cells, inputted by the user. The sort should be descending and I did achieve this functionality using the following:
function onEdit(event){
var sheet = event.source.getActiveSheet();
var range = sheet.getDataRange();
var columnToSortBy = 6;
range.sort( { column : columnToSortBy, ascending: false } );
}
It's short and sweet, however empty cells in the total column which contain the following formula, blanking itself if the sum result is a zero, otherwise printing the result:
=IF(SUM(C2:E2)=0,"",SUM(C2:E2))
It causes these rows with an invisible formula to be included in the range selection and upon descending sort, they get slapped up top for some reason. I want these blank rows either sorted to the bottom, or in an ideal scenario removed from the range itself (Without deleting them and the formula they contain from the sheet) prior to sorting.
Or maybe some better way which doesn't require me dragging a formula across an entire column of mostly empty rows. I've currently resorted to adding the formula manually one by one as new entries come in, but I'd rather avoid this.
EDIT: Upon request find below a screenshot of the sheet. As per below image, the 6th column of total points needs to be sorted descending, with winner on top. This should have a pre-pasted formula running lengthwise which sums up the preceding columns for each participant.
The column preceding it (Points for Tiers) is automatically calculated by multiplying the "Tiers" column by 10 to get final points. This column could be eliminated and everything shifted once left, but it's nice to maintain a visual of the actual points awarded. User input is entered in the 3 white columns.
You want to sort the sheet by the column "F" as the descending order.
You want to sort the sheet by ignoring the empty cells in the column "F".
You want to move the empty rows to the bottom of row.
You don't want to change the formulas at the column "F".
You want to achieve this using Google Apps Script.
If my understanding is correct, how about this answer?
Issue and workaround:
In the current stage, when the empty cells are scattered at the column "F", I think that the built-in method of "sort" of Class Range cannot be directly used. The empty cells are moved to the top of row like your issue. So in this answer, I would like to propose to use the sort method of JavaScript for this situation.
Modified script:
In order to run this function, please edit a cell.
function onEdit(event){
const columnToSortBy = 6; // Column "F"
const headerRow = 1; // 1st header is the header row.
const sheet = event.source.getActiveSheet();
const values = sheet.getRange(1 + headerRow, 1, sheet.getLastRow() - headerRow, sheet.getLastColumn())
.getValues()
.sort((a, b) => a[columnToSortBy - 1] > b[columnToSortBy - 1] ? -1 : 1)
.reduce((o, e) => {
o.a.push(e.splice(0, columnToSortBy - 1));
e.splice(0, 1);
if (e.length > 0) o.b.push(e);
return o;
}, {a: [], b: []});
sheet.getRange(1 + headerRow, 1, values.a.length, values.a[0].length).setValues(values.a);
if (values.b.length > 0) {
sheet.getRange(1 + headerRow, columnToSortBy + 1, values.b.length, values.b[0].length).setValues(values.b);
}
}
In this sample script, it supposes that the header row is the 1st row. If in your situation, no header row is used, please modify to const headerRow = 0;.
From your question, I couldn't understand about the columns except for the column "F". So in this sample script, all columns in the data range except for the column "F" is replaced by sorting. Please be careful this.
Note:
Please use this sample script with enabling V8.
References:
sort(sortSpecObj)
sort()
Added:
You want to sort the sheet by the column "F" as the descending order.
You want to sort the sheet by ignoring the empty cells in the column "F".
You want to move the empty rows to the bottom of row.
In your situation, there are the values in the column "A" to "F".
The formulas are included in not only the column "F", but also other columns.
You don't want to change the formulas.
You want to achieve this using Google Apps Script.
From your replying and updated question, I could understand like above. Try this sample script:
Sample script:
function onEdit(event){
const columnToSortBy = 6; // Column "F"
const headerRow = 1; // 1st header is the header row.
const sheet = event.source.getActiveSheet();
const range = sheet.getRange(1 + headerRow, 1, sheet.getLastRow() - headerRow, 6);
const formulas = range.getFormulas();
const values = range.getValues().sort((a, b) => a[columnToSortBy - 1] > b[columnToSortBy - 1] ? -1 : 1);
range.setValues(values.map((r, i) => r.map((c, j) => formulas[i][j] || c)));
}
A much simpler way to fix this is to just change
=IF(SUM(C2:E2)=0,"",SUM(C2:E2))
to
=IF(SUM(C2:E2)=0,,SUM(C2:E2))
The cells that are made blank when the sum is zero will then be treated as truly empty and they will be excluded from sort, so only cells with content will appear sorted at the top of the sheet.
Why your original formula doesn't work that way is because using "" actually causes the cell contain content so it's not treated as a blank cell anymore. You can test this by entering ISBLANK(F1) into another cell and check the difference between the two formulas.

Delete rows based on certain logic in power query

I need to delete rows based on the below logic:
Sum of column B for the same product, to compare with one of the values in column D for this product.
If the sum value < the value in column D, then delete the rows with extra ReceiptQty. In this case, for product AAA, receiptQty =12000, which is >10000, then delete the row 7.
Is there any way to achieve this in power query? Thanks~
This code should work:
let
Source = Excel.CurrentWorkbook(){[Name="Data"]}[Content],
group = Table.Group(Source, {"ProductID"}, {"temp", each _}),
list = Table.AddColumn(group, "list", each List.Skip(List.Accumulate([temp][ReceiptQty], {0}, (a, b) => a & {List.Last(a) + b}))),
table = Table.AddColumn(list, "table", each Table.FromColumns(Table.ToColumns([temp])&{[list]}, Table.ColumnNames(Source)&{"RunningQty"})),
final = Table.SelectRows(Table.Combine(table[table]), each [OnhandQty] >= [RunningQty])
in
final

How can I expand all lists in a row of lists at the same time without repeating values?

In response to this question regarding how to expand all lists in a row of lists at the same time, #Carl Walsh kindly provided this succinct and helpful code:
let
Source = #table({"A", "B"}, {{ {1,2}, {3,4}} }),
Expanded = List.Accumulate(
Table.ColumnNames(Source),
Source,
(state, column) => Table.ExpandListColumn(state, column))
in
Expanded
Which yields this:
I would like to get this result instead:
I don't want values repeated in previously processed columns as each follow-on column is processed.
Is there a simple modification to Carl's code that will get me there?
Maybe not really simple, but effective: the code below combines the columns with adjusted code so the lists are zipped and the inner lists are transformed into records. Next the list column is expanded, resulting in a column with nested records which are subsequently expanded.
Unfortunately, you can't use combine columns with nested lists, so I created some dummy text columns first that I combined in order to generate the base code, which I subsequently adjusted and I removed the steps with the dummy columns.
let
Source = #table({"A", "B"}, {{ {1,2}, {3,4}} }),
#"Merged Columns" = Table.CombineColumns(Source,{"A", "B"}, each List.Transform(List.Zip(_), each Record.FromList(_,{"A","B"})),"Merged"),
#"Expanded Merged" = Table.ExpandListColumn(#"Merged Columns", "Merged"),
#"Expanded Merged1" = Table.ExpandRecordColumn(#"Expanded Merged", "Merged", {"A", "B"}, {"A", "B"})
in
#"Expanded Merged1"

LINQ sorting by number of appearances

I need to sort a list by numer od appearances and show repeating items only once. For example I have a following list : "a", "b", "a", "a", "c", "d", "c". I want it to be sorted like this: "a","c","b",d". How can I achieve this?
That is what I made:
var something = from c in db.Letters
group c by c.letter into p
orderby p.Count()
select new
{
p.letter
};
But expression p.letter cannot be used.
var resunt = from c in db.Letters
group c by c.letter into p
orderby p.Count() descending
select p.Key;
When you use GroupBy you get an IGroupping object that contains a property of the Key object that you've grouped by and a collection of the values in the group. In your case you want to return the Key - the c.letter

Resources