cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - Stay updated on what is happening on the PTC Community by subscribing to PTC Community Announcements. X

table sort

douglaswade1
1-Visitor

table sort

I just got stumped. A user wants to sort a table by column. I have no clue
if that is possible. I am using version 5.2. Our data is SGML.

d
5 REPLIES 5

Hi Doug-



It's not there out of the box, but I know it can be done. A while back a
few of us tried our hand at different approaches, and found several that
worked. Someone did one that was pure ACL, another person did one based
on XSLT, and IIRC I did one that was all AOM. Unfortunately I can't find
those files any more, so I can't post a sample. But here's the basic
approach I'd take from an AOM perspective:



1) Write a function that can sort a table based on values in a
particular column, given that the cursor is in a table header cell for
that column

2) Use an event listener to capture a double-click on a table row
header that triggers the function you wrote in step 1.

3) OR, alternatively, add an entry to the editor window context
menu to let them sort by right-clicking a table cell header.



--Clay


Hi Doug-



I did manage to dig up an early version of the code. This one requires
you to select the table and then invoke the sort function (which you
could do from a command line or from a custom menu item, etc.). It's
pretty basic, there are a number of ways you could spruce it up. The UI
in particular is very bare bones; it basically presents you with a list
of the entries in the first row of the table and wants you to give it a
number corresponding to the column on which you want to sort. But
hopefully it will get you started.



--Clay



// ---------------- pasted code -----------------//



// type="text/jscript"



// adds ability to sort a table

// version 0.1 is fairly rudimentary, it will get confused by spanned
cells and other

// such complexities, it is meant strictly for a straightforward
rectangular table where

// all rows have the same number of cells



var tableSortColumnIndex;



function sortTable() {

TABLE_TYPE = 2;

doc = Application.activeDocument;

// if selection is not a table or part of one, abort

if (doc.selectionType != TABLE_TYPE) {

Application.alert("Table must be selected before it can be sorted");

return;

}

// get the current table

selection = doc.tableSelection;

trect = selection.rectangle(1);

// get array of column headings for prompt

headings = new Array();

for (i=0;i < trect.width;i++) {

headings.push(trect.cells.item(i).column.topCell.contents.toString()
+ " (" + (i+1) + ")");

}

// prompt user

sortcol = promptTableSort(headings);

// check user selection to make sure it's feasible

if (canSort(trect,sortcol)) {

// stuff table rows in an array so we can sort them

tableSortColumnIndex = sortcol;

rows = new Array();

firstrow = trect.upperLeft.row.index;

for (i=0;(rowcell = trect.cellsOnLeftEdge.item(i));i++) {

rows.push(rowcell.row);

}

// sort rows in the array

rows.sort(compareRows);

// insert sorted rows after selection

tgrid = trect.upperLeft.grid;

targetrow = trect.lowerLeft.row;

for (i=0; (row = rows[i]); i++) {

// skip if source row is a header row

if (row.getAttribute("header_level")=="0") {

targetrow = tgrid.addRow(targetrow);

for (j=1; j <= row.cellCount; j++) {


targetrow.cell(j).contents.insertNode(row.cell(j).contents.extractConten
ts());

}

}

}

// now delete the originals (except for header rows)

for (i=0; (row = rows[i]); i++) {

if (row.getAttribute("header_level")=="0") {

tgrid.deleteRow(row);

}

}



}

else {

// give error

Application.alert("Invalid sort column, select a number from 1 to "
+ trect.width + ".");

}

}



function promptTableSort(headings) {

// need to polish this!

response = Application.prompt(headings.join(","),"1");

if (response==null) return null;

else return parseInt(response);

}



function canSort(rect,sortcol) {

if (sortcol == null) return false;

if (sortcol <= rect.width) return true;

else return false;

}



function compareRows(a,b) {

if (a.cell(tableSortColumnIndex).contents.toString().toLowerCase() <
b.cell(tableSortColumnIndex).contents.toString().toLowerCase()) return
-1;

else if
(a.cell(tableSortColumnIndex).contents.toString().toLowerCase() >
b.cell(tableSortColumnIndex).contents.toString().toLowerCase()) return
1;

else return 0;

}




Here is an ACL-only, sorts on first column only, table sort package. I think
it is at least based on, if not totally lifted from, the experiment Clay
mentioned.

package table_sort

function table_sort() {
if (oid_xpath_boolean(oid_caret(),'ancestor::tbody')) {
local chgtrk = option("changetracking")
set changetracking = off;

while (oid_name(oid_parent(oid_caret())) != 'tbody') {
goto_oid(oid_parent(oid_caret()));
}
goto_oid(oid_parent(oid_caret()));

if (oid_find_child_attrs(oid_caret(), morerowsarr, 'morerows')) {
response('Tables with vertical spans can not be sorted.');
set changetracking = $chgtrk;
return;
} # if


rows = oid_find_children(oid_caret(), rowarr, "row");

if ($rows > 0) {
for (i = 1; i <= $rows; i++) {
if (store_rows_arr[oid_content(oid_child($rowarr[$i],1))] == '') {
store_rows_arr[oid_content(oid_child($rowarr[$i],1))] =
oid_content($rowarr[$i],0x1);
sort_rows_arr[$i] = oid_content(oid_child($rowarr[$i],1));
} # if
else {
tempkey = oid_content(oid_child($rowarr[$i],1)) . $i;
store_rows_arr[$tempkey] = oid_content($rowarr[$i],0x1);
sort_rows_arr[$i] = $tempkey;
} # else
} # for

qsort(sort_rows_arr);

for (i = 1; i <= count($sort_rows_arr); i++) {
insert(store_rows_arr[$sort_rows_arr[$i]]);
}

for (i = 1; i <= $rows; i++) {
oid_delete($rowarr[$i]);
} # for
message "$rows rows sorted.";
beep;
} # if
else {
response('No rows found to sort. Interesting. Let your administrator
know.');
}

delete(store_rows_arr);
delete(sort_rows_arr);
set changetracking = $chgtrk;
} # if
else {
response('Place your cursor in the body (tbody) of the table or
informaltable to be sorted before attempting to Sort Table.');
} # else

} # table_sort

This is for the record. I don't know if it is practical.

FOSI indexing performs sorting. Help 70-1 describes sorting a FOSI-generated
table. Help 1239 describes how to rename preliminary and final index markup. It
seem to me it should be possible to rename preliminary index markup to the
appropriate table markup. I'm thinking a system-func in the FOSI could call ACL
to determine and return to the FOSI the number of the column with the cursor.

With this approach, print/PDF output should be straightforward, but there would
be two tables in the Edit window, the unsorted input table and the sorted output
gentable. Only the input table could be edited. I'm not certain, but I think the
output gentable would automatically update/re-sort when the input table was
edited. If not, update gentext would be needed to show the changes in the output
table.

Standard disclaimer: I have not tried this. If it works, please share!

Good luck!

Suzanne Napoleon
www.FOSIexpert.com
"WYSIWYG is last-century technology!"


Thanks to all:

I am using the ACL version. The only issue is the qsort works with column
one. So the user must move the column to the first position and run the
sort. Then move it back to the real position. That is all good, it is not
that often we need to do this.

d


On Wed, Aug 4, 2010 at 8:37 PM, Suzanne Napoleon <
SuzanneNapoleon@fosiexpert.com> wrote:

> This is for the record. I don't know if it is practical.
>
> FOSI indexing performs sorting. Help 70-1 describes sorting a
> FOSI-generated table. Help 1239 describes how to rename preliminary and
> final index markup. It seem to me it should be possible to rename
> preliminary index markup to the appropriate table markup. I'm thinking a
> system-func in the FOSI could call ACL to determine and return to the FOSI
> the number of the column with the cursor.
>
> With this approach, print/PDF output should be straightforward, but there
> would be two tables in the Edit window, the unsorted input table and the
> sorted output gentable. Only the input table could be edited. I'm not
> certain, but I think the output gentable would automatically update/re-sort
> when the input table was edited. If not, update gentext would be needed to
> show the changes in the output table.
>
> Standard disclaimer: I have not tried this. If it works, please share!
>
> Good luck!
>
> Suzanne Napoleon
> www.FOSIexpert.com
> "WYSIWYG is last-century technology!"
>
Announcements

Top Tags