It appears as though I'm real late to reply to this thread, but I also had to setup an alphabetical sort for a central monitoring system in our facility. I was tasked with setting up a system that would monitor all the test cells within the facility and send out emails and text messages via email to engineers who were responsible for that cell with a logix5000 controller and a panelview 1500 for an HMI for them to edit their person information from.
Some folks earlier were talking about what sorting method to use, I ended up using a shaker sort and started at the high end of the array. (If you want to take a look at what a shaker sort is just hit up wikipedia. They may have called it a ****tail shaker sort) I picked this style sort because it's pretty easy to setup, and at any given point in time there will only be one person added or taken away from the array, so it pretty well negates all the arguments about how inefficient it is to sort things like that. Even if the array is massive, it only has to scan through the thing once and it's done. You just have to setup a little bit of logic to kick the thing out of the sort once it's made a full scan through the array without making any swaps.
Also, as some folks mentioned, I had a second array of Index values that I was actually manipulating rather than messing with the array of strings. So say you have the array of strings (Eng_Name[250]) you setup a second array of DINTS (Eng_Name_Inx[250]) then have a buffer location for the screen of strings. In my case I had a list of names they'd run through to find themselves that was 15 people long. (Eng_Name_Disp_Alph[15]). I didn't get as fancy as Ken was talking about with a deal to type a name in to find it, but I think the premise would be easy to follow once you get this first bit done. Something else to note, strings really do a number on the processor memory. Because what I was using was going to be short names I made a string of only 43 characters. Seems silly, but between cell names, engineer names, shutdown messages and display strings, memory gets used up pretty quickly. The 43 was pretty much arbitrary. I found a length of string display that made sense for the screen, found the max characters that'd fit in it and went with that.
So the root of the thing, without looking back in the program, was this. I setup a subroutine (Shaker_Sort) because I planned on using it for multiple lists. I'd tell it the array length, the lowest point to check and a highest point to check. I also setup a first scan bit to reset the program before executing and a move enable bit coming out showing it's completed and you can start to fill the displays with the alphabetized names. (The lowest value to check was called out because I'd setup the the monitoring system itself as a test cell in the 0 slot of the array, and I didn't want to be alphabetizing that out of order into the field where people could see it. The high point was added because other lists, such as engineers to contact list, might not have the full available amount of engineers in it, so scanning the whole list wasn't necessary) I would only run the subroutine when things needed alphabetized. So if the engineer sent them to a screen that would have a list that'd need alphabetized I'd command the sort to start and would hold it in until the move enable bit was set.
Inside the subroutine was relatively easy. I had a UDT for the JSR in and out parameters to make life a little easier on me, but that may not be necessary for everyone. Essentially I had a scanner that'd start at the High_Check point at the beginning of the routine and a second scanner based off the original one just minus 1. I would take those to indexes and look at there respective points in the Eng_Name_Inx[250] array and write the high point to a new index. Sort_Check_A and Sort_Check_B. From here, ASCII characters have different values if they're capital or not capital. So do the UPPER or LOWER instruction and dump the name into a buffer tag to do compares on -
Eng_Name[Sort_Check_A] -> Sort_Name_A
Eng_Name[Sort_Check_B] -> Sort_Name_B
Then I would compare letter by letter of the engineer names based on those. So...
Sort_Name_A.Data[Sort_Letter] > Sort_Name_B.Data[Sort_Letter] Swap A and B in Eng_Name_Inx.
The sort letter deal I setup in a way that some folks may not really like. I would say...
Sort_Name_A.Data[Sort_Letter] = Sort_Name_B.Data[Sort_Letter] add 1 to sort_letter and re-scan the rung
I just put a JMP right under the add to the sort_letter and put the LBL at the beginning of the same rung. This worked for me, but you'll want to test this before you can feel confident in putting it in service. Take 2 identical strings and compare them to see if the watchdog trips. No one want a faulted processor because you're trying to alphabetize something.
You'll also want to move un-used array slots to the end. So if Sort_Name_A.LEN = 0 and Sort_Name_B.LEN <> 0 then swap em.
You'll have to add in something so if the 2 names are identical, or at least start with the same letters until one of the strings runs out of characters, you'll stop once Sort_Letter is equal to the lowest length value for the a and b strings.
So once you've proven whether the words need to be swapped you can increment the scanner values from before and scan through the subroutine again. If you're scanning downwards and Sort_Check_A = the lowest point then you'l switch directions and start again, then add 1 to your low check (because you now know that the lowest check point is now setup with the lowest value). The same goes for the upward direction. Once Sort_Check_B = highest point to check, switch directions and subtract 1 from the highest point to check.
The last basic part of it was I setup a verification counter. So if you're highest element to check is 250 and the lowest is 1 the verification preset is set to 250. if you scan all the way up or down and don't see a swap in that you know you're sorted entirely and can kick on the move enable bit to update your screen, or even just an alphabetized array of strings for troubleshooting the setup.
I can't off hand remember if there's anything else I've forgotten. I would suggest setting up the program in a timed task at first so you can setup a trend and watch the stuff move through. Not only is it fun to watch the lines go up and down, but if you setup that stuff in the continuous task it moves a little too quick to see. Once it's function drop that puppy in the continuous and let'r eat.