How to custom sort strings and numbers in VBA - excel

I'm trying to sort a column in my excel spreadsheet that contains numbers ,strings and "empty". My goal is to sort the numbers descending, followed by empty, followed by strings descending as well.
Sample data with 4 rows is in the table below.
Columns("A:A").Sort key1:=Range("A2"), order1:=xlDescending
With a normal column sort, I can get the numbers and the "empty" in the right order (Failed Code). However, the String keeps on appearing before the numbers when sorting descending.
Initial Failed_Code Desired_Output
1 6566 String 6566
2 6566 700
3 700 700
4 String String

Normally you can specify the sorting order in a list and use the OrderCustom parameter of VBA sort, an example is in the accepted answer of Code an Excel VBA sort with a custom order and a value containing commas. However as you are sorting integers and strings the usually adviced helper/auxiliary column ( Custom sort in Excel by first character and user-defined non-alphabetical order., ) is an easier solution here too, especially as in custom lists no wildcards are possible (https://www.mrexcel.com/board/threads/custom-sort.471612/).
As ! is the first character following the control characters in ASCII table and Windows sorting order (What is the first character in the sort order used by Windows Explorer?) write a macro that creates the auxiliary column according to the first character in the cells you want to sort (How to check first character in a cell value), if this first character is a letter prepend an !, then sort by the auxiliary column in descending order.
An alternative an possibly easiest solution, would be in your case to first sort the entire column ascending, then determine the index where is the 'border' between integers and strings by checking the first character (How to check first character in a cell value) and then sort the integers and strings separately descending, because you can always specify the sorting range you do not have to necessarily sort tte entire column.

Related

If second two characters equal this then that

I have a string of letters and numbers, where if the second two characters of the string equal a certain value, then a location value should be shown in the corresponding column.
I have used the MID function to essentially extract the characters of the string that I want to use MID(A2,2,2) but now I can't figure out how to compare what is returned to a list of options that those two characters could be without typing in each option in an extremely long formula.
Here are possible strings that are situated in a column:
3PH356969
MSFFACEBUS
MBH0007398
MBH0007402
I am extracting the second two characters of these, to compare to a list similar to this
PH
SF
BH
PG
HR
These values then correspond to location (below), which would optimally be returned:
Philadelphia
Bay Area
Birmingham
Western PA
Hartford
I can write =IF(MID(A2,2,2)="PH","Philadelphia",else...) but then the else-ifs will go on for 76 more 2-character strings to compare against. I'm hoping there is a more optimal way for this.
Expected results should be the location corresponding to the string, or just "error" displayed.
Basically we need to use a lookup/reference table, but instead of a much more common VLOOKUP function we can use a much faster INDEX + MATCH combo.
Formula in B1:
=INDEX($E$1:$E$6,MATCH(MID(A1,2,2),$D$1:$D$6;0))
I would use a VLOOKUP, personally. Although it would require a separate lookup table, just feed your MID result as the VLOOKUP key. Then you could easily add/remove locations, and there will be an #N/A error if the key's not there.
If you don't want a separate lookup table, you may try it this way:
=IFERROR(INDEX({"Philadelphia","Bay Area","Birmingham","Western PA","Hartford"},MATCH(MID(A2,2,2),{"PH","SF","BH","PG","HR"},0)),"Not found")

excel if and if error formula that has used 140 times and it throws an errors saying we can use it only 64 times

I have 140 unique numbers and trying to find that through the list which can be used in vba
The formula works fine till 64 ifs are used, later I am having a trouble
=IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IFERROR(IF(FIND("5216",A2,1)>0,"00000A-5216",""),IF(FIND("5140",A2,1)>0,"00000B-5140","")),IF(FIND("5148",A2,1)>0,"00000C-5148","")),IF(FIND("5117",A2,1)>0,"00000D-5117","")),IF(FIND("5204",A2,1)>0,"00000E-5204","")),IF(FIND("5238",A2,1)>0,"00000F-5238","")),IF(FIND("5203",A2,1)>0,"00000G-5203","")),IF(FIND("5237",A2,1)>0,"00000H-5237","")),IF(FIND("5051",A2,1)>0,"5051","")),IF(FIND("0101",A2,1)>0,"0101","")),IF(FIND("0700",A2,1)>0,"0700","")),IF(FIND("3208",A2,1)>0,"3208","")),IF(FIND("3209",A2,1)>0,"3209","")),IF(FIND("3900",A2,1)>0,"3900","")),IF(FIND("3901",A2,1)>0,"3901","")),IF(FIND("5029",A2,1)>0,"5029","")),IF(FIND("5030",A2,1)>0,"5030","")),IF(FIND("5032",A2,1)>0,"5032","")),IF(FIND("5033",A2,1)>0,"5033","")),IF(FIND("5036",A2,1)>0,"5036","")),IF(FIND("5049",A2,1)>0,"5049","")),IF(FIND("5067",A2,1)>0,"5067","")),IF(FIND("5068",A2,1)>0,"5068","")),IF(FIND("5069",A2,1)>0,"5069","")),IF(FIND("5072",A2,1)>0,"5072","")),IF(FIND("5073",A2,1)>0,"5073","")),IF(FIND("5075",A2,1)>0,"5075","")),IF(FIND("5076",A2,1)>0,"5076","")),IF(FIND("5078",A2,1)>0,"5078","")),
IF(FIND("5079",A2,1)>0,"5079","")),IF(FIND("5080",A2,1)>0,"5080","")),IF(FIND("5081",A2,1)>0,"5081","")),IF(FIND("5082",A2,1)>0,"5082","")),IF(FIND("5083",A2,1)>0,"5083","")),IF(FIND("5090",A2,1)>0,"5090","")),IF(FIND("5094",A2,1)>0,"5094","")),IF(FIND("5095",A2,1)>0,"5095","")),IF(FIND("5100",A2,1)>0,"5100","")),IF(FIND("5106",A2,1)>0,"5106","")),IF(FIND("5124",A2,1)>0,"5124","")),IF(FIND("5125",A2,1)>0,"5125","")),IF(FIND("5126",A2,1)>0,"5126","")),IF(FIND("5147",A2,1)>0,"5147","")),IF(FIND("5150",A2,1)>0,"5150","")),IF(FIND("5151",A2,1)>0,"5151","")),IF(FIND("5155",A2,1)>0,"5155","")),IF(FIND("5156",A2,1)>0,"5156","")),IF(FIND("5157",A2,1)>0,"5157","")),IF(FIND("5158",A2,1)>0,"5158","")),IF(FIND("5159",A2,1)>0,"5159","")),IF(FIND("5194",A2,1)>0,"5194","")),IF(FIND("5195",A2,1)>0,"5195","")),IF(FIND("5196",A2,1)>0,"5196","")),IF(FIND("5205",A2,1)>0,"5205","")),IF(FIND("5227",A2,1)>0,"5227","")),IF(FIND("5228",A2,1)>0,"5228",""))IF(FIND("5229",A2,1)>0,"5229","")),IF(FIND("5234",A2,1)>0,"5234","")),IF(FIND("5241",A2,1)>0,"5241","")),IF(FIND("5242",A2,1)>0,"5242","")),IF(FIND("5243",A2,1)>0,"5243","")),IF(FIND("5244",A2,1)>0,"5244","")),IF(FIND("5254",A2,1)>0,"5254","")),IF(FIND("5255",A2,1)>0,"5255","")),IF(FIND("5267",A2,1)>0,"5267","")),IF(FIND("5269",A2,1)>0,"5269","")),IF(FIND("5271",A2,1)>0,"5271","")),IF(FIND("5278",A2,1)>0,"5278","")),IF(FIND("5280",A2,1)>0,"5280","")),IF(FIND("5286",A2,1)>0,"5286","")),IF(FIND("5297",A2,1)>0,"5297","")),IF(FIND("5305",A2,1)>0,"5305","")),IF(FIND("5306",A2,1)>0,"5306","")),IF(FIND("5310",A2,1)>0,"5310","")),IF(FIND("5315",A2,1)>0,"5315","")),IF(FIND("5316",A2,1)>0,"5316","")),IF(FIND("5318",A2,1)>0,"5318","")),IF(FIND("5321",A2,1)>0,"5321","")),IF(FIND("5322",A2,1)>0,"5322","")),IF(FIND("5324",A2,1)>0,"5324","")),IF(FIND("5325",A2,1)>0,"5325","")),IF(FIND("5326",A2,1)>0,"5326","")),IF(FIND("5327",A2,1)>0,"5327","")),IF(FIND("5328",A2,1)>0,"5328","")),IF(FIND("5336",A2,1)>0,"5336","")),IF(FIND("5337",A2,1)>0,"5337","")),IF(FIND("5339",A2,1)>0,"5339","")),IF(FIND("5341",A2,1)>0,"5341","")),IF(FIND("5350",A2,1)>0,"5350",""))IF(FIND("5351",A2,1)>0,"5351","")),IF(FIND("5352",A2,1)>0,"5352","")),IF(FIND("5353",A2,1)>0,"5353","")),IF(FIND("5356",A2,1)>0,"5356","")),IF(FIND("5357",A2,1)>0,"5357","")),IF(FIND("5358",A2,1)>0,"5358","")),IF(FIND("5359",A2,1)>0,"5359","")),IF(FIND("5360",A2,1)>0,"5360","")),IF(FIND("5361",A2,1)>0,"5361","")),IF(FIND("5362",A2,1)>0,"5362","")),IF(FIND("5363",A2,1)>0,"5363","")),IF(FIND("5378",A2,1)>0,"5378","")),IF(FIND("5379",A2,1)>0,"5379","")),IF(FIND("5380",A2,1)>0,"5380","")),IF(FIND("5381",A2,1)>0,"5381","")),IF(FIND("5382",A2,1)>0,"5382","")),IF(FIND("5383",A2,1)>0,"5383","")),IF(FIND("5389",A2,1)>0,"5389",""))IF(FIND("5390",A2,1)>0,"5390","")),IF(FIND("5392",A2,1)>0,"5392","")),IF(FIND("6000",A2,1)>0,"6000","")),IF(FIND("6001",A2,1)>0,"6002","""")),IF(FIND("6003",A2,1)>0,"6003","")),IF(FIND("6004",A2,1)>0,"6004","")),IF(FIND("6005",A2,1)>0,"6005","")),IF(FIND("6006",A2,1)>0,"6006","")),IF(FIND("6653",A2,1)>0,"6653","")),IF(FIND("6654",A2,1)>0,"6654","")),IF(FIND("6655",A2,1)>0,"6655","")),IF(FIND("6656",A2,1)>0,"6656","")),IF(FIND("6657",A2,1)>0,"6657","")),IF(FIND("9202",A2,1)>0,"9202","")),IF(FIND("9401",A2,1)>0,"9401","")),RIGHT(A2,3,4))"
the result should return the number mentioned and I am planning to sort them in ascending order.
The value in A2 looks like PMGAG5216GC, PMG005216GC, PMGVV5140GC, PMG005140GC, PMGVV5148GCW, PMGAG5117GCW, PMG005117GCW, PMGAG5204GCB, PMG005204GCB, PMGAG5238GCB, PMGVV5238GCB, PMG005238GCB, PMGAG5203GCB, etc. these are some sample order numbers that are being updated and the numbers 5238 is a number that I have to find from that order to sort them in ascending order. In the same way, I have 140 numbers that have to found to sort them accordingly. The 4 digit numbers are fixed in the orders and it should be one from the 140 number list that I had mentioned
Rule of thumb, if you see yourself nesting anything deeper than 5 or 6 levels, stop and take the time to see if there wouldn't be a more easily maintainable way to do the same thing. Hitting hard limits (e.g. 64 levels of nesting) is rarely a sign that things are done in an optimal fashion.
PMGAG5216GC PMG005216GC PMGVV5140GC PMG005140GC PMGVV5148GCW PMGAG5117GCW PMG005117GCW PMGAG5204GCB PMG005204GCB PMGAG5238GCB PMGVV5238GCB PMG005238GCB PMGAG5203GCB
Assuming the format is consistently the same, you can grab the 4 characters starting at the 6th position, and then verify if these 4 characters exist in a lookup table that contains the 140 values you're interested in. The MID function can be used to do this.
You could leverage the fact that VLOOKUP in the first column of the lookup table would return the lookup value itself, and a lookup failure would be #N/A, so wrapping it with IFERROR to turn that into an empty string would look like this:
=IFERROR(VLOOKUP(MID(A2,6,4),theLookupTable[TheLookupColumn],1,FALSE),"")
Now, if looks like some of the values need a prefix e.g. "00000A-"; include that prefix (with the dash, so you don't have to conditionally add it in the formula) in the lookup table (say, in some [Prefix] column) where it's needed, and just concatenate it after the lookup.
=IFERROR(VLOOKUP(MID(A2,6,4),theLookupTable[TheLookupColumn],1,FALSE) & VLOOKUP(MID(A2,6,4),theLookupTable[#[TheLookupColumn]:[ThePrefixColumn]],2,FALSE),"")
Better if you can turn the MID(A2,6,4) part into a helper cell instead of computing it twice - use that MID function on your source data to populate the lookup table.
The lookup table might look like this:
TheLookupColumn ThePrefixColumn
5216 00000A-
5140 00000B-
5148 00000C-
...
3901
...
Sort the table by TheLookupColumn, and the lookups should be pretty fast.
If you just want to show the first number from your lookup list which is contained in any given order number you can do something like this:
It's an array formula so you need to enter it using Ctrl + Shift + Enter
Assumes there can be only one match per order number and that none of the items in your lookup list are substrings of another item (though a workaround for that would be to sort your lookup list in descending order of item length)

Excel Advanced Filter not working with Wildcard (* asterisk) using regular numbers and hyphenated number system

I have set up an advanced filter in Excel. I can not get the advanced filter to produce any output when using wildcard asterisks (*), using a source list that contains numbers and hyphenated numbers, OR alternatively when using a separate list which is producing a number from a formula. All adv.filter headers are properly placed and named; the filter works fine not using wildcards.
Original List:
10
10-1
11
11-1
100
I am using a formula to convert these hyphenated numbers to ignore the dashes so they will sort properly (smallest to largest) in my list:
=IF(A1="","",IFERROR(VALUE(LEFT(A1,FIND("-",A1)-1)),VALUE(A1)))
This results in a secondary column (which is the advanced filter source data):
10
10
11
11
100
My advanced filter criteria then becomes *10* with wildcards, with the output header being the original list with dashes included. I am expecting the wildcard to show both 10 and 100 in the output when user types in 10. There is no output data, however, when using the wildcard. There is exact match output data when I just type in 10 with no asterisks.
Any ideas for why wildcards aren't working? I tried formatting the source data and criteria data as both text, number, and general; none made any difference with wildcards. Thanks for the help!!!!
You had the right idea when you tried formatting as text: wildcards don't work on numeric values.
Where you're running into trouble is that formatting as text doesn't change numbers to text retroactively; only numbers entered after the format change get converted. Instead convert your data to strings first using the TEXT function in another location, and then filter that result.
Depending on exactly what you're doing with the VALUE function in your formula, you might even be able to use TEXT in there.

Sharepoint calculated field get number only

I have a SharePoint list with a field, Field A, holding values such as "Text-11" or "DifferentText-150" and I want a new calculated field, Field B, that only shows the numeric part of Field A (i.e. "11", "150").
The number can be between 1 and 9999 so I canĀ“t take always the last 2 digits.
Does anyone have an idea how to realize that with the calculated field function of SharePoint?
You will need to use several different functions to accomplish this. Your primary function will be MID which will allow you to grab a part of the original text but then you will also need to use SEARCH for your starting point and LEN to get the correct number of characters. Here are the steps for making your formula:
You will need the index of the first character in the number. This can be achieved by finding the first character after the dash ('-'). Remember that indexes in SharePoint calculated fields start at 1 and not 0.
SEARCH("-",[Title],1)
Next you need to get the length of the number part of your string. This can be achieved by getting the length of the whole string and subtracting the index of the dash ('-').
LEN([Title]) - SEARCH("-",[Title],1)
Finally you can get the number part of the string by using the MID function and passing in the index of the first character in the number (Part 1) and the length of the number part (Part 2).
MID([Title],SEARCH("-",[Title],1) + 1,LEN([Title]) - SEARCH("-",[Title],1))
Note: Title is just the name of the test column that I used.

Sorting of links with numbers in Excel

I have a list of similiar links of website with equal base in Excel. At the and of the link there is numbers, e.g. *_100, *_1013, *_14 and so on.
I need to sort the list descending like
*_1013
*_100
*_14
(first 4-digit links, then 3-digit, then 2-digit)
Is there any possibility in Excel to sort this array in right way?
From your question the "*_XXX" is at the end of the string. So to get the values you need to
Indentify where the *_ occurs and extract that
Remove the *- from the extracted string (which I used SUBSTITUTE to do), then convert it to a value
=IFERROR(VALUE(SUBSTITUTE(RIGHT(A1,LEN(A1)-FIND("*_",A1)-1),"*_","")),"no match")
If you don't mind an extra column you can extract the number, make it a real number with =value() and then simply sort largest to smallest. (note: prepending 0s, if any exist, would be lost during call to value function)

Resources