Sort a spread sheet via gspread - python-3.x

I have a Google spreadsheet full of names, dates, and some other numbers.
I made an desktop application that provides a nice UI for said info.
After using the application a bit I became slightly annoyed with the order the data was being displayed.
I have been researching all day and I cannot seem to find anything on the topic of sorting the spreadsheet from a python script.
All I need is some function that I can call every time someone adds something to it to re-sort the sheet.
I would very much appreciate it if someone could help me out.
Thanks in advance.

GSpread has a .sort() method to sort a worksheet using given sort orders. Here's how you can use it (Source - GSpread Docs):
Parameters:
specs (list) – The sort order per column. Each sort order represented by a tuple where the first element is a column index and the second element is the order itself: ‘asc’ or ‘des’.
range (str) – The range to sort in A1 notation. By default sorts the whole sheet excluding frozen rows.
Example:
# Sort sheet A -> Z by column 'B'
wks.sort((2, 'asc'))
# Sort range A2:G8 basing on column 'G' A -> Z
# and column 'B' Z -> A
wks.sort((7, 'asc'), (2, 'des'), range='A2:G8')

You can use PyGsheets lib. It uses sheets API v4 on lower level.
my_worksheet.sort_range() function will help you but it has some specialities
Numbering in start and end cells start with 1 but
basecolumnindex starts with 0.
You can pass the cell's address in 2 ways: text index (like "A3") or tuple with 2 elements (like (1, 3)). The second way doesn't work for me.
The range limited by start and end cells should contain column passed in basecolumnindex

Related

EXCEL: How to automatically add serial number in Excel Table using formula that is immune to filtering / sorting?

I want to create an Excel Table where the first column is the "SL" (serial number) column that starts from 1 and then increases by 1 for each subsequent entry. I want the serial number to automatically increase as I add more rows to the table.
I have tried using all manners of "=ROWS" functions, all manners of "=COUNTA" functions, and all other functions used in tutorial that I found in the web. None of them are immune from sorting or filtering. That is, if I sort the "Name" column from A to Z, the serial number that was assigned to its respective row entry changes because of how these formulae are written. For example:
This is the Original List. As you can see, Dragon Fruit's serial number is 1. I have used the "=COUNTA(B$2:[#[NAME]])" function in this example.
As you can see, when I sorted the "Name" column from A to Z, Dragon Fruit's serial number went from 1 to 2, Acai went from 4 to 1, Guava went from 9 to 3, and so on. But I want the serial numbers to be static and locked to their corresponding "Name".
Is this possible to do in Excel without manually typing the numbers in the SL column?
Good question and a tricky situation to deal with. I'm not sure if the question is better suited for SuperUser though.
The trick here is to somehow use absolute cell-references instead of relative ones. As you have now experienced, Excel filters won't work well with relative references. However, manually adding absolute references is not what we want to do.
To mimic the absolute cell-reference behaviour you can preceed the row reference with a sheet-reference which magically should counter the normal formula-behaviour and turn them into actual absolute cell-references:
Formula in A2 (which will auto-fill the 'SL' column):
=ROW(Sheet1!A1)
Data when filtered A-Z on 'Name':
Data when tabbed a new row:
You could use PowerQuery in Excel to add an index in front.
Remove the ID from your source.
Make your source a table
Import into PowerQuery and add an index
Load the output to another sheet. In this sheet you can filter and sort and everything you want.

Excel multilevel array formula with partial string matches to sum resultant cells

I've been trying to sort this for over a day now without much luck. I have successfully used SUMIFS, INDEX, MATCH, COUNTIF, "--" etc array functions previously and am not a novice, but also not an expert on these. I can't seem to weave these together correctly, and likely on an altogether incorrect path.
Basically, I am trying to aggregate data from multiple spreadsheets, requiring a mapping of various items (rows) into a canonical form for summing.
The image here shows a representative, but simplified version of my quest. Each "region" on this example spreadsheet (Final..., Mapping, DataSet1, DataSet2) is actually in different spreadsheets, and there are several sheets with 50-150 rows in each xlsx.
Note that the names in Column B are quite arbitrary (meaning not all P1's have an 'x' pattern, like shown here as x1, x2, etc. Do not rely on any pattern in the names, except the x, y , z in the Mapping table are substrings (case insensitive, trailing match) of the names in Column B in the DataSets.
And in the image, the Final Result Table (summed manually) is what I want to compute via(an array) formula: A single formula would be ideal (given I have many spreadsheets from which the monthly data is being pulled from, so I can't readily modify but can create an interim spreadsheet if required, so open to helper columns or helper rows).
Here's the process - For each name (B3-B5) in the Final Result Table, I want to sum the name from it's components as follows:
Lookup all the matches in the Mapping Table (so for P1, the formula =IF($C$10:$C$15=$B3, $B$10:$B$15,"") gives {"x1";"";"";"x2";"";"x3"}.
I then want to search each of x1, x2, and x3 in B19:B26 to get rows 21, 22, 24, 25, 26 in DataSet1 and B31:B35 to get row 32 in DataSet2, to then add up the Jan totals into C3. (Effectively,
C3=C21+C22+C24+C25+C26+C32). Same for P2 and P3, and thru Feb, Mar, ...
I am stuck on how to remove blank or 0 or Div0 or such "error rows" from the interim result in 2, and also need to use 2 arrays of different sizes (3 valid rows in example 2 above, ignoring blanks) to search many rows in DataSets. I tried SEARCH("*"&IF($C$10:$C$15=$B3, $B$10:$B$15,""), $B$19:$B$26) but get unexpected results. I have tried to replace text in the interim result {"x1";"";"";"x2";"";"x3"} with TRUE/FALSE, and 1/0, etc. to help with INDEX or MATCH, but am stymied by errors in downstream ("surrounding") formulas.
Thanks in advance.
Here is a solution without resorting to nasty (imo) CSE formulas.
= SUMPRODUCT($C$19:$F$26*(COUNTIFS($B$10:$B$15, RIGHT($B$19:$B$26,2),$C$10:$C$15,$B3)>0)*($C$18:$F$18=C$2))
+
SUMPRODUCT($C$31:$F$35*(COUNTIFS($B$10:$B$15, RIGHT($B$31:$B$35,2),$C$10:$C$15,$B3)>0)*($C$30:$F$30=C$2))
There is one SUMPRODUCT for each data set. If possible, it would be better to put all your data sets into a single table with a column identify which data set it is a part of.
The way it works is to takes each values in your data set and multiplies it by whether the 2 right most character appear in your mapping table for that P code, multiplied by whether the value is in the correct month. So it returns 0 if either of those conditions are false. Then returns the sum.
UPDATE IN RESPONSE TO OP COMMENTS
If, the X,Y, Z codes are not always 2 digits but the first part is ALWAYS 8 digits, you can easily amend the:
RIGHT($B$19:$B$26,2)
to be:
RIGHT($B$19:$B$26,LEN($B$19:$B$26)-8)
Making the formula for the first data set:
=SUMPRODUCT($C$19:$F$26*(COUNTIFS($B$10:$B$15, RIGHT($B$19:$B$26,LEN($B$19:$B$26)-8),$C$10:$C$15,$B3)>0)*($C$18:$F$18=C$2))
And you can amend for other data sets and simply add them together.
Nice challenge! Are you willing to drop all your tables (DataSet1, DataSet2...) into one spreadsheet, so that we can refer just one single range for each month?
Here's one solution (hopefully a good starting point) - array formula (Ctrl+Shift+Enter):
=SUMPRODUCT(IFERROR(IF(TRANSPOSE(IF($B3=$C$10:$C$15,$B$10:$B$15,""))=RIGHT($B$18:$B$36,2),C$18:C$36,0),0))

Attempting to sort a list that is generated from a unique point extraction of an array

The issue is sorting an array that is generated automatically from an data source using a formula that extracts unique data points. (Data points are date/time)
The data is being extracted with this fomula.
=INDEX(Table_ExternalData_1[SampleDateTime],MATCH(0,INDEX(COUNTIF($G$2:G2,Table_ExternalData_1[SampleDateTime]),0,0),0))
Once extracted, the data is not sorted right away. The current data is extracted from a database via an SQL string that pulls in data corresponding to the data and time that the data point was created.
Because of this, the extracted points are not in the correct order. I am attempting to sort the extracted data points from earliest to latest to continue with the data sorting, but need the date/times to be sorted in a separate row.
I have attempted to use a pivot table, but it isn't exactly what I need and ends up being a messier end product than I need.
All assistance is appreciated.
Example is below.
1
2
3
5
1
2
3
4
6
5
3
I need this.
1
2
3
4
5
6
I did end up finding a solution that I will be able to modify. Using a single row of a pivot table, I took just the date/time column and had the PivotTable function sort the data to be utilized as necessary.
Thank you.
The fact that the range in the example you give:
1) Consists of entries of a numeric datatype only
2) Does not contain any blanks
means that the solution is relatively simple.
Assuming that data is in A1:A11, first use a single cell somewhere within the worksheet to count the number of expected returns. For example, using B1 for this purpose, enter this formula in that cell:
=SUM(IF(FREQUENCY(A1:A11,A1:A11),1))
Your main formula is then:
=IF(ROWS($1:1)>B$1,"",SMALL(IF(FREQUENCY(A$1:A$11,A$1:A$11),A$1:A$11),ROWS($1:1)))
the latter being copied down until you start to get blanks for the results.
Regards

using conditional named range in excel

Let me try this again, I've been searching the web and can't seem to find anything. What i'm trying to do is in excel have a bunc of named range list conditional based on a value of another cell. The problem I'm running into character limit when I setup the data validation and put all my IF statements in source textbox. If i just put two conditions it seems to work fine, but that won't work for me. Here is my example data, based on the B column value I want to display the valid sub-items for it. Like I mentioned I have 20 or so different possible values that could be in column B.
B C
1 ENG dropdown of all engineering sub-categories
2 PRO dropdown of all production sub-categories
3 PER ...
4 PAY
5 ENG dropdown of all engineering sub-categories
6 ENG dropdown of all engineering sub-categories
When i try to setup my data validation list on column C1, I put in the following...
=IF($E$5="CAR", CA,
IF($E$5="DCC", DCC,
IF($E$5="ENG", ENG,
IF$E$5="ENV", ENV,
IF$E$5="FBI", BI,
IF$E$5="FGL", GL,
IF$E$5="FAP", AP,
IF$E$5="FRE", AR,
IF$E$5="FTX", Tax,
IF$E$5="ORM", OAR,
IF$E$5="PAY", PAY,
IF$E$5="PIR", PER,
IF$E$5="PRO", PRO,
IF$E$5="PUR", PUR,
IF$E$5="RSK", RM,
IF$E$5="SLM", Sales,
IF$E$5="WFS", WAR)))))))))))))))))
I'm only able to type in maybe half of my IF condition. I tried VLOOKUP but that only allows for 1 value to be put in column C, and I want it to be a dropdown. Any help would be much apprecriated.
You can do this in a much shorter formula by combining VLOOKUP and INDIRECT:
Have you list of of potential names in column B and their corresponding range names somewhere in two columns, e.g. column X & Y:
Col X Col Y
CAR CA
DCC DCC
ENG ENG
ENV ENV
FBI BI
...
Then use the following formula as the source of the list in the Data Validation:
=INDIRECT(VLOOKUP($E$5,$X:$Y,2,0))
Actually, with this approach you can potential even save the effort of naming and maintaining the manual range names! Instead, just replace the name of the named range with the real address - which - with a bit of luck and smart formula engineering - you can derive automatically. This depends on your data structure, but most likely the functions ADDRESS, COUNTA, OFFSET, INDEX and MATCH will be helpful.
E.g. if your lists would be stored in another worksheet with the name of the list in the first row and the elements listed below each header, this example file will provide you the example formulas. One step further, it'll also use conditional highlighting to mark any entry that is invalid, e.g. because the type was changed after the selection:

How to search for a partial and an absolute in excel to get an answer?

I have a worksheet, in where I need a search that does more than one query. The problem I am running into is this:
On the workbook there are two tabs, the first is Jobs, the second is OOR. In OOR there are multiple columns empty, Order Qty., Orig Promise Date, and Shop Order.
Now I know there are duplicates, and this is fine, what I am looking at now is to use Column B in OOR is a refrence. So in this case use B3 as the refrence point. which is a partial number of 48900421 Rev 2. What I want to do is this, use two refrence points.
I want to look up B3 in OOR, and use two points of refrence to gurantee the correct job is refrenced. Those two columns to refrence is in Jobs. The first is Column B which will always equal Dakota Systems, Inc., and the other will reference Column C, but this is where I don't know what to do here, I since C3 in OOR only shows 48900421, it will never find 48900421 Rev 2I thought about using something like this:
=IFERROR(INDEX(Jobs!$E:$E,MATCH(1,INDEX((OOR!$C:$C=$B3)*(Jobs!$C:$C="Dakota Systems, Inc."),1),0)),"")
But for some reason I am getting a blank when I don't think I should be. I'm loosing my sanity this late in the week, can someone help?
https://dl.dropbox.com/u/3327208/Excel/twosearches.xlsx
You don't seem to be referencing the right columns....and also you need a zero in the second INDEX function, not a 1
Try this version in in OOR!I3 copied down, using ISNUMBER(FIND to find your part number within other text:
=IFERROR(INDEX(Jobs!E$3:E$1000,MATCH(1,INDEX(ISNUMBER(FIND(B3,Jobs!C$3:C$1000))*(Jobs!B$3:B$1000="Dakota Systems, Inc."),0),0)),"")
format in required date format
Revised re comment below:
=IFERROR(INDEX(Jobs!E$3:E$1000,MATCH(1,INDEX(ISNUMBER(FIND(B3,Jobs!C$3:C$1000))*(Jobs!B$3:B$1000="Dakota Systems, Inc.")*(Jobs!A$3:A$1000=M3),0),0)),"")

Resources