Application Development and Automation Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

Alphanumeric Sorting

Former Member
0 Likes
3,855

Hi..

I need to sort projects in an internal table.

project(PROJ-PSPID).

Suppose that in one internal table t_proj we have three entries

EC-000293-A8

EC-000293-A17

EC-000293-A15

Afther sorting ascending the ouput will be

SORT t_proj Ascending.

EC-000293-A15

EC-000293-A17

EC-000293-A8

But my required output shoud be

EC-000293-A8

EC-000293-A15

EC-000293-A17

Can anyone pls help me in sorting like this

Thanks in Advance

Edited by: Sheeba Bhaskaran on Jan 9, 2008 12:15 PM

Edited by: Sheeba Bhaskaran on Jan 9, 2008 12:16 PM

1 ACCEPTED SOLUTION
Read only

Former Member
0 Likes
2,174

Sorry,

Little modification in logic i have give above

field1 field2

EC-000293-A 8

EC-000293-A 17

EC-000293-A 15

In new internal table you can just define 2 field.

Sort new internal table by field1 and field2 (basically this will seperate characters and numbers)..

you can simply concatenate them in new field to get your required sorting.

Regards,

Mohaiyuddin

12 REPLIES 12
Read only

Former Member
0 Likes
2,174

Try this

SORT t_proj Descending.

awrd points if helpful

Bhupal

Read only

Former Member
0 Likes
2,174

Hi,

The field which u r sorting is Character , so it will do the same as below.

SORT t_proj Ascending.

EC-000293-A15

EC-000293-A17

EC-000293-A8

To over come this, try to move this field to NUMC type.

It cant be moved directly , u can use WRITE ..TO statement.

and do sorting.

Revrt back if still not working.

Regards,

naveen

Edited by: Naveen Deva on Jan 9, 2008 7:51 AM

Read only

0 Likes
2,174

Hi Naveen..

Thanks for the reply

Project is alphanumeric string..

then how is it possible to move it to a numeric type.?

Regards,

Sheeba

Read only

0 Likes
2,174

U sort ur itab by this field Descending.

awrd points if useful

Bhupal

Read only

0 Likes
2,174

Hi Bapul

I think u dint get my requirement

i want values to be ascending

EC-000293-A8

EC-000293-A15

EC-000293-A17

like this

since normal sorting is based on string comparison it is sorting like this

EC-000293-A15

EC-000293-A17

EC-000293-A8

A8 is considerd as higher value since A8 is compared with A1 first.

hop u understood

Read only

Former Member
0 Likes
2,174

Hi Sheeba,

TableSorter.java code is here.

create a java file in ur WD project in ur pacakages folder. let it be in subfolde 'com' of ur project's packages folder.

then code is

code

package com;

import java.sql.Date;

import java.text.Collator;

import java.util.ArrayList;

import java.util.Collection;

import java.util.Comparator;

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;

import java.util.StringTokenizer;

import com.sap.tc.webdynpro.clientserver.uielib.standard.api.IWDAbstractDropDownByIndex;

import com.sap.tc.webdynpro.clientserver.uielib.standard.api.IWDAbstractDropDownByKey;

import com.sap.tc.webdynpro.clientserver.uielib.standard.api.IWDAbstractInputField;

import com.sap.tc.webdynpro.clientserver.uielib.standard.api.IWDAbstractTableColumn;

import com.sap.tc.webdynpro.clientserver.uielib.standard.api.IWDCaption;

import com.sap.tc.webdynpro.clientserver.uielib.standard.api.IWDCheckBox;

import com.sap.tc.webdynpro.clientserver.uielib.standard.api.IWDLink;

import com.sap.tc.webdynpro.clientserver.uielib.standard.api.IWDProgressIndicator;

import com.sap.tc.webdynpro.clientserver.uielib.standard.api.IWDRadioButton;

import com.sap.tc.webdynpro.clientserver.uielib.standard.api.IWDTable;

import com.sap.tc.webdynpro.clientserver.uielib.standard.api.IWDTableCellEditor;

import com.sap.tc.webdynpro.clientserver.uielib.standard.api.IWDTableColumn;

import com.sap.tc.webdynpro.clientserver.uielib.standard.api.IWDTableColumnGroup;

import com.sap.tc.webdynpro.clientserver.uielib.standard.api.IWDTextEdit;

import com.sap.tc.webdynpro.clientserver.uielib.standard.api.IWDTextView;

import com.sap.tc.webdynpro.clientserver.uielib.standard.api.WDTableColumnSortDirection;

import com.sap.tc.webdynpro.progmodel.api.IWDAction;

import com.sap.tc.webdynpro.progmodel.api.IWDCustomEvent;

import com.sap.tc.webdynpro.progmodel.api.IWDNode;

import com.sap.tc.webdynpro.progmodel.api.IWDNodeElement;

import com.sap.tc.webdynpro.progmodel.api.IWDViewElement;

import com.sap.tc.webdynpro.services.sal.localization.api.WDResourceHandler;

/**

  • Helper class that makes a Web Dynpro table UI element sortable (column-wise).

*/

public final class TableSorter {

/**

  • @param table

  • @param sortAction

  • @param comparators

*/

/**

  • Creates a table sorter for the given table using the given sort action.

  • This constructor must be called from <code>wdDoModifyView()</code>, but

  • usually only when that hook is called for the first time. Store the newly

  • created instance in a context attribute with Java native type

  • <code>com.sap.tc.webdynpro.tests.utils.TableSorter</code>.

  • The given sort action's event handler will be bound to the <code>onSort</code>

  • event of the table and must at least call this table sorter's

  • <code>sort(wdEvent)</code> method.

  • Every column of the table is made sortable if possible according to the

  • following rules.

  • If a comparator is given for a column's ID and it is a

  • <code>NodeElementByAttributeComparator</code>, then that comparator defines

  • both the attribute and the ordering used to sort that column.

  • If any other comparator is given and an attribute can be determined from

  • that column's table cell editor, then that attribute is used to sort that

  • column according to the ordering imposed by the given comparator.

  • If no comparator is given but an attribute can be determined from

  • that column's table cell editor, then that attribute is used to sort that

  • column according to the natural ordering of that attribute's type.

  • Else that column is left untouched.

  • Additionally it is possible to define the sortable columns by their

  • TableColumn UI element ids.

  • @see sort()

  • @see NodeElementByAttributeComparator

  • @see com.sap.tc.webdynpro.clientserver.uielib.standard.api.IWDTable

*/

public TableSorter(IWDTable table, IWDAction sortAction, Map comparators) {

init(table, sortAction, comparators, null);

}

public TableSorter(IWDTable table, IWDAction sortAction, Map comparators, String[] sortableColumns) {

init(table, sortAction, comparators, sortableColumns);

}

/**

  • Initialisation stuff

*/

private void init(IWDTable table, IWDAction sortAction, Map comparators, String[] sortableColumns){

this.table = table;

if(sortableColumns == null){

sortableCols = null;

}else{

sortableCols = new HashMap();

for (int i = 0; i < sortableColumns.length; i++) {

sortableCols.put(sortableColumns, sortableColumns);

}

}

// sanity checks

if (sortAction == null)

throw new IllegalArgumentException("Sort action must be given");

if (table == null)

throw new IllegalArgumentException("Table must be given");

if (table.bindingOfDataSource() == null)

throw new IllegalArgumentException(

"Data source of table with id '" + table.getId() + "' must be bound");

// make the columns sortable

String dataSourcePrefix = table.bindingOfDataSource() + ".";

//TODO: remove the following line since this method is not longer available in later releases

setComparatorsForColumns(dataSourcePrefix, table.iterateColumns(), comparators);

setComparatorsForColumns(dataSourcePrefix, table.iterateGroupedColumns(), comparators);

//set up the table properties

table.setOnSort(sortAction);

table.mappingOfOnSort().addSourceMapping(IWDTable.IWDOnSort.COL, "selectedColumn");

table.mappingOfOnSort().addSourceMapping(IWDTable.IWDOnSort.DIRECTION, "sortDirection");

}

/**

  • Try to make the given columns sortable (recusivly, if necessary)

*/

private void setComparatorsForColumns(String dataSourcePrefix, Iterator columnIterator, Map comparators){

int index = 0;

for (Iterator it = columnIterator; it.hasNext(); ++index) { // for every column: try to make it bindable

IWDAbstractTableColumn abstractColumn = (IWDAbstractTableColumn) it.next();

if(abstractColumn instanceof IWDTableColumn){

IWDTableColumn column = (IWDTableColumn)abstractColumn;

if(sortableCols == null || sortableCols.containsKey(column.getId())){

//try to make this column sortable

Comparator comparator = null;

if (comparators != null){

comparator = (Comparator)comparators.get(column.getId());

}

NodeElementByAttributeComparator elementComparator = null;

if (comparator instanceof NodeElementByAttributeComparator) {

// the easy one, attribute and ordering are given

elementComparator = (NodeElementByAttributeComparator)comparator;

} else { // attribute must be determined

String bindingOfPrimaryProperty = bindingOfPrimaryProperty(column.getTableCellEditor());

if (bindingOfPrimaryProperty == null || !bindingOfPrimaryProperty.startsWith(dataSourcePrefix)){

//no attribute found or outside of data source

column.setSortState(WDTableColumnSortDirection.NOT_SORTABLE);

continue;

}

String attributeName = bindingOfPrimaryProperty.substring(dataSourcePrefix.length());

Collection subnodes = new ArrayList();

if (attributeName.indexOf('.') >= 0){

//attribute not immediately below data source

String[] tokens = tokenize (attributeName, ".");

for(int i=0; i<tokens.length-1; i++){

subnodes.add(tokens);

}

attributeName = tokenshttp://tokens.length-1;

}

if(subnodes.size() == 0){

elementComparator = new NodeElementByAttributeComparator(attributeName, comparator);

}else{

elementComparator = new NodeElementByAttributeComparator(attributeName, comparator, subnodes);

}

}

// set up internal data structures

comparatorForColumn.put(column, elementComparator);

//set sort state

column.setSortState(WDTableColumnSortDirection.NONE);

}else{

//column should not be sortable

column.setSortState(WDTableColumnSortDirection.NOT_SORTABLE);

}

}else if (abstractColumn instanceof IWDTableColumnGroup){

//it's just a column group -> try to bind the columns of the column group

IWDTableColumnGroup columnGroup = (IWDTableColumnGroup)abstractColumn;

setComparatorsForColumns(dataSourcePrefix, columnGroup.iterateColumns(), comparators);

}

}

}

/**

  • Tokenizes the input string according to the given delimiters. The delimiters will be left out.

  • Example: tokenize("Hello_World", "_") results \"Hello\", \"World\"

*/

private String[] tokenize (String input, String delim){

StringTokenizer tokenizer = new StringTokenizer(input, delim);

String[] tokens = new Stringhttp://tokenizer.countTokens();

int index = 0;

while(tokenizer.hasMoreTokens()){

tokensindex = tokenizer.nextToken();

index++;

}

return tokens;

}

/**

  • This method must be called from the event handler of this table sorter's

  • sort action. It performs the actual sort operation.

*/

public void sort(IWDCustomEvent wdEvent, IWDNode dataSource) {

// find the things we need

String columnId = wdEvent.getString("selectedColumn");

String direction = wdEvent.getString("sortDirection");

IWDTableColumn column = (IWDTableColumn) table.getView().getElement(columnId);

NodeElementByAttributeComparator elementComparator = (NodeElementByAttributeComparator) comparatorForColumn.get(column);

if (elementComparator == null){

//not a sortable column

column.setSortState(WDTableColumnSortDirection.NOT_SORTABLE);

return;

}

// sorting

elementComparator.setSortDirection(WDTableColumnSortDirection.valueOf(direction));

dataSource.sortElements(elementComparator);

}

/**

  • Returns the binding of the given table cell editor's property that is

  • considered "primary" or <code>null</code> if no such binding exists or no

  • such property can be determined.

*/

private static final String bindingOfPrimaryProperty(IWDTableCellEditor editor) {

return editor instanceof IWDViewElement ? bindingOfPrimaryProperty((IWDViewElement) editor) : null;

}

/**

  • Returns the binding of the given view element's property that is

  • considered "primary" or <code>null</code> if no such binding exists or no

  • such property can be determined.

*/

private static final String bindingOfPrimaryProperty(IWDViewElement element) {

if (element instanceof IWDAbstractDropDownByIndex)

return ((IWDAbstractDropDownByIndex) element).bindingOfTexts();

if (element instanceof IWDAbstractDropDownByKey)

return ((IWDAbstractDropDownByKey) element).bindingOfSelectedKey();

if (element instanceof IWDAbstractInputField)

return ((IWDAbstractInputField) element).bindingOfValue();

if (element instanceof IWDCaption)

return ((IWDCaption) element).bindingOfText();

if (element instanceof IWDCheckBox)

return ((IWDCheckBox) element).bindingOfChecked();

if (element instanceof IWDLink)

return ((IWDLink) element).bindingOfText();

if (element instanceof IWDProgressIndicator)

return ((IWDProgressIndicator) element).bindingOfPercentValue();

if (element instanceof IWDRadioButton)

return ((IWDRadioButton) element).bindingOfSelectedKey();

if (element instanceof IWDTextEdit)

return ((IWDTextEdit) element).bindingOfValue();

if (element instanceof IWDTextView)

return ((IWDTextView) element).bindingOfText();

return null;

}

/**

  • Instance of a comparator according to the ordering imposed by the

  • implementation of <code>Comparable</code>.

*/

private static final Comparator DEFAULT = new Comparator() {

/**

  • Compares the given objects according to the ordering imposed by the first

  • ones <code>compareTo(Object)</code> function. Furthermore, <code>null</code>

  • is treated to be less than any object.

  • @see java.lang.Comparable#compareTo(java.lang.Object)

  • @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)

*/

public int compare(Object o1, Object o2) {

if (o1 == null && o2 == null)

return 0;

if (o1 == null)

return -1;

if (o2 == null)

return +1;

if (o1 instanceof Boolean && o2 instanceof Boolean)

return o1.toString().compareTo(o2.toString()); // false < true

if (o1 instanceof String && o2 instanceof String){

//Use a Collator for sorting according to the given Locale

Collator collate = Collator.getInstance(WDResourceHandler.getCurrentSessionLocale());

return collate.compare(o1, o2);

}

return ((Comparable) o1).compareTo((Comparable) o2);

}

};

/**

  • Map of table column to comparator (<code>ReversableComparator</code>)

  • used for sorting that column (sortable columns only).

*/

private Map comparatorForColumn = new HashMap();

/**

  • The table to be sorted.

*/

private IWDTable table = null;

/**

  • Column-IDs of the columns, which should be sortable

*/

private Map sortableCols = null;

/**

  • Generic comparator that compares node elements by a given attribute with

  • the help of a given comparator.

*/

public final class NodeElementByAttributeComparator implements Comparator {

/**

  • Creates a new comparator for the given attribute name that compares values

  • of that attribute according to the natural ordering of that attribute's

  • type (which must implement <code>java.lang.Comparable</code>).

*/

public NodeElementByAttributeComparator(String attributeName) {

this(attributeName, null, false, new ArrayList());

}

/**

  • Creates a new comparator for the given attribute name that compares values

  • of that attribute with the help of the given comparator. If no comparator

  • is given, the natural ordering of that attribute's type is used.

*/

public NodeElementByAttributeComparator(String attributeName, Comparator comparator) {

this(attributeName, comparator, false, new ArrayList());

}

/**

  • Creates a new comparator for the given attribute name that compares values

  • of that attribute either as objects (i.e. "in internal format") or as text

  • (i.e. "in external format") as indicated. The ordering is the natural

  • ordering of that attribute's type (which must implement

  • <code>java.lang.Comparable</code>) in case objects are compared or the

  • natural ordering of <code>java.lang.String</code> in case texts are compared.

*/

public NodeElementByAttributeComparator(String attributeName, boolean compareAsText) {

this(attributeName, null, compareAsText, new ArrayList());

}

/**

  • Creates a new comparator for the given attribute name that compares values

  • of that attribute according to the natural ordering of that attribute's

  • type (which must implement <code>java.lang.Comparable</code>). In addition it is possible

  • to define the path to a child node with the <code>java.util.Collection</code> subnodes.

  • (List of child node names in the correct order)

*/

public NodeElementByAttributeComparator(String attributeName, Collection subnodes) {

this(attributeName, null, false, subnodes);

}

/**

  • Creates a new comparator for the given attribute name that compares values

  • of that attribute with the help of the given comparator. If no comparator

  • is given, the natural ordering of that attribute's type is used. In addition it is possible

  • to define the path to a child node with the <code>java.util.Collection</code> subnodes.

  • (List of child node names in the correct order)

*/

public NodeElementByAttributeComparator(String attributeName, Comparator comparator, Collection subnodes) {

this(attributeName, comparator, false, subnodes);

}

/**

  • Creates a new comparator for the given attribute name that compares values

  • of that attribute either as objects (i.e. "in internal format") or as text

  • (i.e. "in external format") as indicated. The ordering is the natural

  • ordering of that attribute's type (which must implement

  • <code>java.lang.Comparable</code>) in case objects are compared or the

  • natural ordering of <code>java.lang.String</code> in case texts are compared. In addition it is possible

  • to define the path to a child node with the <code>java.util.Collection</code> subnodes.

  • (List of child node names in the correct order)

*/

public NodeElementByAttributeComparator(String attributeName, boolean compareAsText, Collection subnodes) {

this(attributeName, null, compareAsText, subnodes);

}

/**

  • Internal constructor.

*/

private NodeElementByAttributeComparator(

String attributeName,

Comparator comparator,

boolean compareAsText,

Collection subNodes) {

if (attributeName == null)

throw new IllegalArgumentException("Attribute name must not be null");

if (comparator == null)

comparator = DEFAULT;

this.attributeName = attributeName;

this.comparator = comparator;

this.compareAsText = compareAsText;

this.sortDirection = true;

this.subNodes = subNodes;

}

/**

  • Sets the sort direction of this comparator to the given direction. The comparator sort in ascending order by default.

  • @see com.sap.tc.webdynpro.clientserver.uielib.standard.api.WDTableColumnSortDirection

*/

public void setSortDirection(WDTableColumnSortDirection direction){

if(direction.equals(WDTableColumnSortDirection.UP)){

sortDirection = true;

}else if(direction.equals(WDTableColumnSortDirection.DOWN)){

sortDirection = false;

}

}

/**

  • Compares the given objects which must be instances of <code>IWDNodeElement</code>

  • according to the values of the attribute given at construction time

  • with the help of the comparator given at construction time.

  • @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)

  • @see com.sap.tc.webdynpro.progmodel.api.IWDNodeElement

*/

public int compare(Object o1, Object o2) {

IWDNodeElement element1 = (IWDNodeElement) o1;

IWDNodeElement element2 = (IWDNodeElement) o2;

if(subNodes.size() > 0){

element1 = getSubNodeElement(element1, 0);

element2 = getSubNodeElement(element2, 0);

}

Object attributeValue1 = null;

Object attributeValue2 = null;

if(element1 != null){

attributeValue1 =

compareAsText

? element1.getAttributeAsText(attributeName)

: element1.getAttributeValue(attributeName);

}

if(element2 != null){

attributeValue2 =

compareAsText

? element2.getAttributeAsText(attributeName)

: element2.getAttributeValue(attributeName);

}

if(sortDirection){

return comparator.compare(attributeValue1, attributeValue2);

}else{

return comparator.compare(attributeValue2, attributeValue1);

}

}

/**

  • Determines recursivly the child node, which have an attribute with the given name.

  • The path to this child node must be specified in the subnodes property of this comparator.

  • Start this method with index = 0.

*/

private IWDNodeElement getSubNodeElement(IWDNodeElement currentElement, int index){

if(currentElement == null || index >= subNodes.size()){

//end of recursion

return currentElement;

}else{

return getSubNodeElement(currentElement.node().getChildNode((String)subNodes.toArray()index, currentElement.index()).getCurrentElement(), index+1);

//return getSubNodeElement(currentElement.node().getChildNode((String)subNodes.toArray()index, currentElement.index()).getElementAt(0), index+1);

}

}

/**

  • Name of the attribute used for comparisons.

*/

private final String attributeName;

/**

  • Comparator used for comparing the attribute's values.

*/

private final Comparator comparator;

/**

  • Indicates whether attribute values are compared as text (as opposed to

  • "as objects").

*/

private final boolean compareAsText;

/**

  • Sort direction (true = ascending order, false = descending order)

*/

private boolean sortDirection;

/**

  • List of child node names

  • (Description of the path from the given context node to the specified attribute)

*/

private Collection subNodes;

}

}

[/code]

kindly reward if helpful.

cheers,

Hema.

Read only

Former Member
0 Likes
2,174

Define new internal table with 4 fields.

loop at your table and split values in new internal table as

field1 field2 field3

EC 000293 A8

EC 000293 A17

EC 000293 A15

Sort new internal table by field1 field2 field3.

4th field will be same as old internal table filed.

loop at new internal table.

concatenate field1 field2 field3 seperated by '-'.

condense 4th field.

modify.

endloop.

4th field in new internal table will be sorted as per your requirement.

Regards,

Mohaiyuddin

Read only

Former Member
0 Likes
2,175

Sorry,

Little modification in logic i have give above

field1 field2

EC-000293-A 8

EC-000293-A 17

EC-000293-A 15

In new internal table you can just define 2 field.

Sort new internal table by field1 and field2 (basically this will seperate characters and numbers)..

you can simply concatenate them in new field to get your required sorting.

Regards,

Mohaiyuddin

Read only

0 Likes
2,174

Hi Mohaiyuddin,

But i can have projects in any format not neccesarly

EC-000293-A 8

it can be

EC-000293-AB12C

EC-000293-A12

EC-000293-B43C

EC-000293-AABC12

so it will be a problem

Read only

0 Likes
2,174

Hi Sheeba

I hope below code can help you understand in handling your case.


types: begin of t_proj,
         pspid type ps_pspid,
         len  type i,
       end of t_proj.

data: i_proj type standard table of t_proj,
      wa_proj type t_proj.

start-of-selection.

perform append_data using: 'EC-000293-A8',
                           'EC-000293-A17',
                           'EC-000293-A15'.

sort i_proj by len pspid.

loop at i_proj into wa_proj.
   write:/ wa_proj-pspid.
endloop.

*&---------------------------------------------------------------------*
*&      Form  APPEND_DATA
*&---------------------------------------------------------------------*
form APPEND_DATA  using    p_proj type ps_pspid.

  clear: wa_proj.
  wa_proj-pspid = p_proj.
  wa_proj-len   = strlen( p_proj ).
  append wa_proj to i_proj.

endform.                    " APPEND_DATA

Kind Regards

Eswar

Read only

0 Likes
2,174

Thank you Eswar...

Points given...

Read only

Former Member
0 Likes
2,174

Hi Sheeba,

In that case, i don't think there is direct way to doing it...

splitting in single character after common pattern can be only option, but that will be too complex as that will also require logic to sort - will not be able to use sort directly.

Regards,

Mohaiyuddin