diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties
index 43c4beaef..bb61f70e6 100644
--- a/core/resources/l10n/messages.properties
+++ b/core/resources/l10n/messages.properties
@@ -1593,6 +1593,9 @@ ComponentPresetChooserDialog.title = Choose component preset
 ComponentPresetChooserDialog.filter.label = Filter:
 ComponentPresetChooserDialog.checkbox.filterAftDiameter = Match aft diameter
 ComponentPresetChooserDialog.checkbox.filterForeDiameter = Match fore diameter
+ComponentPresetChooserDialog.menu.sortAsc = Sort Ascending
+ComponentPresetChooserDialog.menu.sortDesc = Sort Descending
+ComponentPresetChooserDialog.menu.units = Units
 table.column.Favorite = Favorite
 table.column.Manufacturer = Manufacturer
 table.column.PartNo = Part Number
diff --git a/core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetChooserDialog.java b/core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetChooserDialog.java
index c2a6ccb0c..4c967a92c 100644
--- a/core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetChooserDialog.java
+++ b/core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetChooserDialog.java
@@ -8,6 +8,7 @@ import java.awt.event.ActionListener;
 import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 import javax.swing.JButton;
@@ -44,8 +45,8 @@ public class ComponentPresetChooserDialog extends JDialog {
 	
 	private final RocketComponent component;
 	
-	private final JTable componentSelectionTable;
-	private final TableRowSorter<TableModel> sorter;
+	private ComponentPresetTable componentSelectionTable;
+//	private final JTable componentSelectionTable;
 	private final JTextField filterText;
 	private final JCheckBox foreDiameterFilterCheckBox;
 	private final JCheckBox aftDiameterFilterCheckBox;
@@ -70,29 +71,6 @@ public class ComponentPresetChooserDialog extends JDialog {
 
 		presets = Application.getComponentPresetDao().listForType(component.getPresetType());
 
-		/*
-		 * Set up the Column Table model
-		 */
-		final Column[] columns = new Column[columnKeys.length+1];
-		
-		columns[0] = new Column(trans.get("table.column.Favorite") ) {
-			@Override
-			public Object getValueAt(int row) {
-				return Boolean.valueOf(ComponentPresetChooserDialog.this.presets.get(row).isFavorite());
-			}
-			
-			@Override
-			public void setValueAt(int row, Object value) {
-				Application.getComponentPresetDao().setFavorite(ComponentPresetChooserDialog.this.presets.get(row), (Boolean) value);
-			}
-
-			@Override
-			public Class<?> getColumnClass() {
-				return Boolean.class;
-			}
-			
-		};
-
 		for (int i = 0; i < columnKeys.length; i++) {
 			final TypedKey<?> key = columnKeys[i];
 			if ( key == ComponentPreset.OUTER_DIAMETER ) {
@@ -103,21 +81,6 @@ public class ComponentPresetChooserDialog extends JDialog {
 				// magic +1 is because we have inserted the column for favorites above.
 				foreDiameterColumnIndex = i+1;
 			}
-			columns[i+1] = new Column(trans.get("table.column." + key.getName())) {
-				@Override
-				public Object getValueAt(int row) {
-					ComponentPreset preset = ComponentPresetChooserDialog.this.presets.get(row);
-					if ( ! preset.has(key) ) {
-						return null;
-					}
-					Object value = preset.get(key);
-					if (key.getType() == Double.class && key.getUnitGroup() != null) {
-						return new Value( (Double) value, key.getUnitGroup() );
-					} else {
-						return value;
-					}
-				}
-			};
 		}
 		
 		/*
@@ -132,20 +95,6 @@ public class ComponentPresetChooserDialog extends JDialog {
 			foreDiameterColumnIndex = aftDiameterColumnIndex;
 		}
 		
-		ColumnTableModel tableModel = new ColumnTableModel(columns) {
-			@Override
-			public int getRowCount() {
-				return ComponentPresetChooserDialog.this.presets.size();
-			}
-
-			@Override
-			public boolean isCellEditable(int rowIndex, int columnIndex) {
-				return columnIndex == 0;
-			}
-			
-		};
-		
-
 		/*
 		 * Add filter by text.
 		 */
@@ -205,12 +154,8 @@ public class ComponentPresetChooserDialog extends JDialog {
 			aftDiameterFilterCheckBox.setVisible(false);
 		}
 		
-		componentSelectionTable = new JTable( tableModel );
+		componentSelectionTable = new ComponentPresetTable( presets, Arrays.<TypedKey<?>>asList(columnKeys) );
 		
-		componentSelectionTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-
-		sorter = new TableRowSorter<TableModel>(tableModel);
-		componentSelectionTable.setRowSorter(sorter);
 
 		JScrollPane scrollpane = new JScrollPane();
 		scrollpane.setViewportView(componentSelectionTable);
@@ -319,6 +264,6 @@ public class ComponentPresetChooserDialog extends JDialog {
 			}
 		}
 		
-		sorter.setRowFilter( RowFilter.andFilter(filters) );
+		componentSelectionTable.setRowFilter( RowFilter.andFilter(filters) );
 	}
 }
diff --git a/core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetTable.java b/core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetTable.java
new file mode 100644
index 000000000..9f319fdcc
--- /dev/null
+++ b/core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetTable.java
@@ -0,0 +1,253 @@
+package net.sf.openrocket.gui.dialogs.preset;
+
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.RowFilter;
+import javax.swing.RowSorter.SortKey;
+import javax.swing.SortOrder;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.JTableHeader;
+import javax.swing.table.TableColumn;
+import javax.swing.table.TableModel;
+import javax.swing.table.TableRowSorter;
+
+import net.sf.openrocket.l10n.Translator;
+import net.sf.openrocket.preset.ComponentPreset;
+import net.sf.openrocket.preset.TypedKey;
+import net.sf.openrocket.startup.Application;
+import net.sf.openrocket.unit.Unit;
+import net.sf.openrocket.unit.UnitGroup;
+
+public class ComponentPresetTable extends JTable {
+
+	private static final Translator trans = Application.getTranslator();
+
+	private final TableRowSorter<TableModel> sorter;
+	private final List<ComponentPreset> presets;
+	private final AbstractTableModel tableModel;
+	private final XTableColumnModel tableColumnModel;
+	private final ComponentPresetTableColumn[] columns;
+
+	public ComponentPresetTable(List<ComponentPreset> presets, List<TypedKey<?>> visibleColumnKeys) {
+		super();
+		this.presets = presets;
+		this.columns = new ComponentPresetTableColumn[ComponentPreset.orderedKeyList.size()+1];
+
+		tableColumnModel = new XTableColumnModel();
+
+		/*
+		 * Set up the Column Table model
+		 */
+		columns[0] = new ComponentPresetTableColumn.Favorite(0);
+		tableColumnModel.addColumn(columns[0]);
+
+		List<TableColumn> hiddenColumns = new ArrayList<TableColumn>();
+		{
+			int index = 1;
+			for (final TypedKey<?> key: ComponentPreset.orderedKeyList ) {
+				if ( key.getType() == Double.class && key.getUnitGroup() != null ) {
+					columns[index] = new ComponentPresetTableColumn.DoubleWithUnit((TypedKey<Double>)key,index);
+				} else {
+					columns[index] = new ComponentPresetTableColumn.Parameter(key,index);
+				}
+				tableColumnModel.addColumn(columns[index]);
+				if ( visibleColumnKeys.indexOf(key) < 0 ) {
+					hiddenColumns.add(columns[index]);
+				}
+				index ++;
+			}
+		}
+
+
+		tableModel = new AbstractTableModel() {
+			final ComponentPresetTableColumn[] myColumns = columns;
+			@Override
+			public int getRowCount() {
+				return ComponentPresetTable.this.presets.size();
+			}
+
+			@Override
+			public int getColumnCount() {
+				return myColumns.length;
+			}
+
+			@Override
+			public Object getValueAt(int rowIndex, int columnIndex) {
+				return myColumns[columnIndex].getValueFromPreset(ComponentPresetTable.this.presets.get(rowIndex));
+			}
+
+			@Override
+			public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+				// Only support favorite
+				if ( columnIndex != 0 ) {
+					return;
+				}
+				ComponentPreset preset = ComponentPresetTable.this.presets.get(rowIndex);
+				Application.getComponentPresetDao().setFavorite(preset, (Boolean) aValue);
+			}
+
+			@Override
+			public boolean isCellEditable(int rowIndex, int columnIndex) {
+				return columnIndex == 0;
+			}
+
+			@Override
+			public Class<?> getColumnClass(int columnIndex) {
+				return columnIndex == 0 ? Boolean.class : Object.class;
+			}
+
+		};
+
+		this.setAutoCreateColumnsFromModel(false);
+		this.setColumnModel( tableColumnModel );
+		this.setModel(tableModel);
+		this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+		for ( TableColumn hiddenColumn : hiddenColumns ) {
+			tableColumnModel.setColumnVisible(hiddenColumn, false);
+		}
+
+		sorter = new TableRowSorter<TableModel>(tableModel);
+		this.setRowSorter(sorter);
+
+		JTableHeader header = this.getTableHeader();
+		
+		header.setReorderingAllowed(true);
+
+		header.addMouseListener( new MouseAdapter() {
+
+			@Override
+			public void mousePressed(MouseEvent e) {
+				if ( e.isPopupTrigger() ) {
+					doPopup(e);
+				}
+			}
+			@Override
+			public void mouseReleased(MouseEvent e) {
+				if ( e.isPopupTrigger() ) {
+					doPopup(e);
+				}
+			}
+		});
+	}
+
+	public void setRowFilter( RowFilter<? super TableModel ,? super Integer> filter ) {
+		sorter.setRowFilter( filter );
+	}
+
+	private void doPopup(MouseEvent evt ) {
+		
+		// Figure out what column header was clicked on.
+		int colIndex = tableColumnModel.getColumnIndexAtX( evt.getX() );
+		ComponentPresetTableColumn colClicked = null;
+		if ( colIndex >=0 ) {
+			colClicked = (ComponentPresetTableColumn) tableColumnModel.getColumn(colIndex);
+		}
+		
+		JPopupMenu columnMenu = new ColumnPopupMenu(colClicked, colIndex);
+		columnMenu.show(evt.getComponent(),evt.getX(),evt.getY());
+	}
+
+	private class ColumnPopupMenu extends JPopupMenu {
+
+		ColumnPopupMenu(ComponentPresetTableColumn colClicked, int colClickedIndex) {
+			if ( colClickedIndex >= 0 ) {
+				JCheckBoxMenuItem item = new SortAscColumnMenuItem(colClickedIndex);
+				this.add(item);
+				item = new SortDescColumnMenuItem(colClickedIndex);
+				this.add(item);
+				this.addSeparator();
+				if ( colClicked instanceof ComponentPresetTableColumn.DoubleWithUnit ) {
+					this.add( new UnitSelectorMenuItem( (ComponentPresetTableColumn.DoubleWithUnit) colClicked ));
+					this.addSeparator();
+				}
+			}
+			for( TableColumn c: columns ) {
+				JCheckBoxMenuItem item = new ToggleColumnMenuItem(c);
+				this.add(item);
+			}
+		}
+
+
+		private class SortAscColumnMenuItem extends JCheckBoxMenuItem implements ItemListener {
+			private int columnClicked;
+			SortAscColumnMenuItem(int columnClicked) {
+				super( trans.get("ComponentPresetChooserDialog.menu.sortAsc") );
+				this.addItemListener(this);
+				this.columnClicked = columnClicked;
+			}
+			@Override
+			public void itemStateChanged(ItemEvent e) {
+				sorter.setSortKeys( Collections.singletonList( new SortKey(columnClicked, SortOrder.ASCENDING)));
+			}
+		}
+		
+		private class SortDescColumnMenuItem extends JCheckBoxMenuItem implements ItemListener {
+			private int columnClicked;
+			SortDescColumnMenuItem(int columnClicked) {
+				super( trans.get("ComponentPresetChooserDialog.menu.sortDesc") );
+				this.addItemListener(this);
+				this.columnClicked = columnClicked;
+			}
+			@Override
+			public void itemStateChanged(ItemEvent e) {
+				sorter.setSortKeys( Collections.singletonList( new SortKey(columnClicked, SortOrder.DESCENDING)));
+			}
+		}
+		
+		private class ToggleColumnMenuItem extends JCheckBoxMenuItem implements ItemListener {
+			TableColumn col;
+			ToggleColumnMenuItem( TableColumn col ) {
+				super( String.valueOf(col.getHeaderValue()), tableColumnModel.isColumnVisible(col));
+				this.addItemListener(this);
+				this.col = col;
+			}
+			@Override
+			public void itemStateChanged(ItemEvent e) {
+				tableColumnModel.setColumnVisible(col, !tableColumnModel.isColumnVisible(col));
+			}
+		}
+		
+		private class UnitSelectorMenuItem extends JMenu implements ItemListener {
+			ComponentPresetTableColumn.DoubleWithUnit col;
+			UnitSelectorMenuItem( ComponentPresetTableColumn.DoubleWithUnit col ) {
+				super(trans.get("ComponentPresetChooserDialog.menu.units"));
+				this.col = col;
+				UnitGroup group = col.unitGroup;
+				Unit selectedUnit = col.selectedUnit;
+				for( Unit u : group.getUnits() ) {
+					JCheckBoxMenuItem item = new JCheckBoxMenuItem( u.toString() );
+					if ( u == selectedUnit ) {
+						item.setSelected(true);
+					}
+					item.addItemListener(this);
+					this.add(item);
+				}
+				
+			}
+			@Override
+			public void itemStateChanged(ItemEvent e) {
+				JCheckBoxMenuItem item = (JCheckBoxMenuItem) e.getItem();
+				String val = item.getText();
+				col.selectedUnit = col.unitGroup.findApproximate(val);
+				ComponentPresetTable.this.tableModel.fireTableDataChanged();
+				return;
+			}
+
+		}
+		
+	}
+}
diff --git a/core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetTableColumn.java b/core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetTableColumn.java
new file mode 100644
index 000000000..70878f5ab
--- /dev/null
+++ b/core/src/net/sf/openrocket/gui/dialogs/preset/ComponentPresetTableColumn.java
@@ -0,0 +1,83 @@
+package net.sf.openrocket.gui.dialogs.preset;
+
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableColumn;
+
+import net.sf.openrocket.l10n.Translator;
+import net.sf.openrocket.preset.ComponentPreset;
+import net.sf.openrocket.preset.TypedKey;
+import net.sf.openrocket.startup.Application;
+import net.sf.openrocket.unit.Unit;
+import net.sf.openrocket.unit.UnitGroup;
+import net.sf.openrocket.unit.Value;
+
+public abstract class ComponentPresetTableColumn extends TableColumn {
+
+	private static final Translator trans = Application.getTranslator();
+
+	protected ComponentPresetTableColumn( String header, int modelIndex ) {
+		this.setHeaderValue(header);
+		this.setModelIndex(modelIndex);
+	
+	}
+	
+	public abstract Object getValueFromPreset( ComponentPreset preset );
+	
+	public static class Favorite extends ComponentPresetTableColumn {
+
+		public Favorite(int modelIndex) {
+			super(trans.get("table.column.Favorite"), modelIndex);
+		}
+		
+		@Override
+		public Object getValueFromPreset( ComponentPreset preset ) {
+			return Boolean.valueOf(preset.isFavorite());
+		}
+
+	}
+
+	public static class Parameter extends ComponentPresetTableColumn {
+
+		protected final TypedKey<?> key;
+		
+		public Parameter( TypedKey<?> key, int modelIndex ) {
+			super( trans.get("table.column." + key.getName()), modelIndex );
+			this.key = key;
+		}
+
+		@Override
+		public Object getValueFromPreset(ComponentPreset preset) {
+			return preset.has(key) ? preset.get(key) : null;
+		}
+		
+	}
+
+
+	public static class DoubleWithUnit extends Parameter {
+
+		UnitGroup unitGroup;
+		Unit selectedUnit;
+		
+		public DoubleWithUnit( TypedKey<Double> key, int modelIndex ) {
+			super(key,modelIndex);
+			this.unitGroup = key.getUnitGroup();
+			this.selectedUnit = unitGroup.getDefaultUnit();
+		}
+
+		@Override
+		public Object getValueFromPreset(ComponentPreset preset) {
+			Double value = (Double) super.getValueFromPreset(preset);
+			if ( value != null ) {
+				return new Value((Double)super.getValueFromPreset(preset),selectedUnit);
+			} else {
+				return null;
+			}
+		}
+		
+		
+	}
+
+}
+
+
+
diff --git a/core/src/net/sf/openrocket/gui/dialogs/preset/XTableColumnModel.java b/core/src/net/sf/openrocket/gui/dialogs/preset/XTableColumnModel.java
new file mode 100644
index 000000000..9968e2472
--- /dev/null
+++ b/core/src/net/sf/openrocket/gui/dialogs/preset/XTableColumnModel.java
@@ -0,0 +1,241 @@
+package net.sf.openrocket.gui.dialogs.preset;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import javax.swing.table.DefaultTableColumnModel;
+import javax.swing.table.TableColumn;
+
+public class XTableColumnModel extends DefaultTableColumnModel  {
+
+	/** Array of TableColumn objects in this model.
+	 *  Holds all column objects, regardless of their visibility
+	 */
+	protected Vector<TableColumn> allTableColumns = new Vector<TableColumn>();
+
+	/**
+	 * Creates an extended table column model.
+	 */
+	XTableColumnModel() {
+		super();
+	}
+
+	/**
+	 * Sets the visibility of the specified TableColumn.
+	 * The call is ignored if the TableColumn is not found in this column model
+	 * or its visibility status did not change.
+	 * <p>
+	 *
+	 * @param aColumn        the column to show/hide
+	 * @param visible its new visibility status
+	 */
+	// listeners will receive columnAdded()/columnRemoved() event
+	public void setColumnVisible(TableColumn column, boolean visible) {
+		if(!visible) {
+			super.removeColumn(column);
+		}
+		else {
+			// find the visible index of the column:
+			// iterate through both collections of visible and all columns, counting
+			// visible columns up to the one that's about to be shown again
+			int noVisibleColumns    = tableColumns.size();
+			int noInvisibleColumns  = allTableColumns.size();
+			int visibleIndex        = 0;
+
+			for(int invisibleIndex = 0; invisibleIndex < noInvisibleColumns; ++invisibleIndex) {
+				TableColumn visibleColumn   = (visibleIndex < noVisibleColumns ? (TableColumn)tableColumns.get(visibleIndex) : null);
+				TableColumn testColumn      = (TableColumn)allTableColumns.get(invisibleIndex);
+
+				if(testColumn == column) {
+					if(visibleColumn != column) {
+						super.addColumn(column);
+						super.moveColumn(tableColumns.size() - 1, visibleIndex);
+					}
+					return; // ####################
+				}
+				if(testColumn == visibleColumn) {
+					++visibleIndex;
+				}
+			}
+		}
+	}
+
+	/**
+	 * Makes all columns in this model visible
+	 */
+	public void setAllColumnsVisible(boolean visible) {
+		int noColumns       = allTableColumns.size();
+
+		for(int columnIndex = 0; columnIndex < noColumns; ++columnIndex) {
+			TableColumn visibleColumn = (columnIndex < tableColumns.size() ? (TableColumn)tableColumns.get(columnIndex) : null);
+			TableColumn invisibleColumn = (TableColumn)allTableColumns.get(columnIndex);
+			if ( visible ) {
+
+				if(visibleColumn != invisibleColumn) {
+					super.addColumn(invisibleColumn);
+					super.moveColumn(tableColumns.size() - 1, columnIndex);
+				}
+			} else {
+				super.removeColumn(invisibleColumn);
+			}
+		}
+	}
+
+	/**
+	 * Maps the index of the column in the table model at
+	 * <code>modelColumnIndex</code> to the TableColumn object.
+	 * There may me multiple TableColumn objects showing the same model column, though this is uncommon.
+	 * This method will always return the first visible or else the first invisible column with the specified index.
+	 * @param modelColumnIndex index of column in table model
+	 * @return table column object or null if no such column in this column model
+	 */
+	public TableColumn getColumnByModelIndex(int modelColumnIndex) {
+		for (int columnIndex = 0; columnIndex < allTableColumns.size(); ++columnIndex) {
+			TableColumn column = (TableColumn)allTableColumns.get(columnIndex);
+			if(column.getModelIndex() == modelColumnIndex) {
+				return column;
+			}
+		}
+		return null;
+	}
+
+	/** Checks wether the specified column is currently visible.
+	 * @param aColumn column to check
+	 * @return visibility of specified column (false if there is no such column at all. [It's not visible, right?])
+	 */    
+	public boolean isColumnVisible(TableColumn aColumn) {
+		return (tableColumns.indexOf(aColumn) >= 0);
+	}
+
+	/** Append <code>column</code> to the right of exisiting columns.
+	 * Posts <code>columnAdded</code> event.
+	 * @param column The column to be added
+	 * @see #removeColumn
+	 * @exception IllegalArgumentException if <code>column</code> is <code>null</code>
+	 */    
+	@Override
+	public void addColumn(TableColumn column) {
+		allTableColumns.add(column);
+		super.addColumn(column);
+	}
+
+	/** Removes <code>column</code> from this column model.
+	 * Posts <code>columnRemoved</code> event.
+	 * Will do nothing if the column is not in this model.
+	 * @param column the column to be added
+	 * @see #addColumn
+	 */    
+	@Override
+	public void removeColumn(TableColumn column) {
+		int allColumnsIndex = allTableColumns.indexOf(column);
+		if(allColumnsIndex != -1) {
+			allTableColumns.remove(allColumnsIndex);
+		}
+		super.removeColumn(column);
+	}
+
+	/** Moves the column from <code>oldIndex</code> to <code>newIndex</code>.
+	 * Posts  <code>columnMoved</code> event.
+	 * Will not move any columns if <code>oldIndex</code> equals <code>newIndex</code>.
+	 *
+	 * @param	oldIndex			index of column to be moved
+	 * @param	newIndex			new index of the column
+	 * @exception IllegalArgumentException	if either <code>oldIndex</code> or
+	 * 						<code>newIndex</code>
+	 *						are not in [0, getColumnCount() - 1]
+	 */
+	@Override
+	public void moveColumn(int oldIndex, int newIndex) {
+		if ((oldIndex < 0) || (oldIndex >= getColumnCount()) ||
+				(newIndex < 0) || (newIndex >= getColumnCount()))
+			throw new IllegalArgumentException("moveColumn() - Index out of range");
+
+		TableColumn fromColumn  = (TableColumn) tableColumns.get(oldIndex);
+		TableColumn toColumn    = (TableColumn) tableColumns.get(newIndex);
+
+		int allColumnsOldIndex  = allTableColumns.indexOf(fromColumn);
+		int allColumnsNewIndex  = allTableColumns.indexOf(toColumn);
+
+		if(oldIndex != newIndex) {
+			allTableColumns.remove(allColumnsOldIndex);
+			allTableColumns.add(allColumnsNewIndex, fromColumn);
+		}
+
+		super.moveColumn(oldIndex, newIndex);
+	}
+
+	/**
+	 * Returns the total number of columns in this model.
+	 *
+	 * @param   onlyVisible   if set only visible columns will be counted
+	 * @return	the number of columns in the <code>tableColumns</code> array
+	 * @see	#getColumns
+	 */
+	public int getColumnCount(boolean onlyVisible) {
+		Vector<TableColumn> columns = (onlyVisible ? tableColumns : allTableColumns);
+		return columns.size();
+	}
+
+	/**
+	 * Returns an <code>Enumeration</code> of all the columns in the model.
+	 *
+	 * @param   onlyVisible   if set all invisible columns will be missing from the enumeration.
+	 * @return an <code>Enumeration</code> of the columns in the model
+	 */
+	public Enumeration<TableColumn> getColumns(boolean onlyVisible) {
+		Vector<TableColumn> columns = (onlyVisible ? tableColumns : allTableColumns);
+
+		return columns.elements();
+	}
+
+	/**
+	 * Returns the position of the first column whose identifier equals <code>identifier</code>.
+	 * Position is the the index in all visible columns if <code>onlyVisible</code> is true or
+	 * else the index in all columns.
+	 *
+	 * @param	identifier   the identifier object to search for
+	 * @param	onlyVisible  if set searches only visible columns
+	 *
+	 * @return		the index of the first column whose identifier
+	 *			equals <code>identifier</code>
+	 *
+	 * @exception       IllegalArgumentException  if <code>identifier</code>
+	 *				is <code>null</code>, or if no
+	 *				<code>TableColumn</code> has this
+	 *				<code>identifier</code>
+	 * @see		#getColumn
+	 */
+	public int getColumnIndex(Object identifier, boolean onlyVisible) {
+		if (identifier == null) {
+			throw new IllegalArgumentException("Identifier is null");
+		}
+
+		Vector<TableColumn>      columns     = (onlyVisible ? tableColumns : allTableColumns);
+		int         noColumns   = columns.size();
+		TableColumn column;
+
+		for(int columnIndex = 0; columnIndex < noColumns; ++columnIndex) {
+			column = (TableColumn)columns.get(columnIndex);
+
+			if(identifier.equals(column.getIdentifier()))
+				return columnIndex;
+		}
+
+		throw new IllegalArgumentException("Identifier not found");
+	}
+
+	/**
+	 * Returns the <code>TableColumn</code> object for the column
+	 * at <code>columnIndex</code>.
+	 *
+	 * @param	columnIndex	the index of the column desired
+	 * @param	onlyVisible	if set columnIndex is meant to be relative to all visible columns only
+	 *                          else it is the index in all columns
+	 *
+	 * @return	the <code>TableColumn</code> object for the column
+	 *				at <code>columnIndex</code>
+	 */
+	public TableColumn getColumn(int columnIndex, boolean onlyVisible) {
+		return (TableColumn)tableColumns.elementAt(columnIndex);
+	}
+}
diff --git a/core/src/net/sf/openrocket/preset/ComponentPreset.java b/core/src/net/sf/openrocket/preset/ComponentPreset.java
index 410470e73..5c42e7bd4 100644
--- a/core/src/net/sf/openrocket/preset/ComponentPreset.java
+++ b/core/src/net/sf/openrocket/preset/ComponentPreset.java
@@ -4,6 +4,7 @@ import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
 import java.security.MessageDigest;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
@@ -148,6 +149,26 @@ public class ComponentPreset implements Comparable<ComponentPreset> {
 		keyMap.put(MASS.getName(), MASS);
 	}
 
+	public final static List<TypedKey<?>> orderedKeyList = Arrays.<TypedKey<?>>asList(
+			MANUFACTURER,
+			PARTNO,
+			DESCRIPTION,
+			OUTER_DIAMETER,
+			INNER_DIAMETER,
+			LENGTH,
+			SHOULDER_DIAMETER,
+			SHOULDER_LENGTH,
+			FORE_SHOULDER_DIAMETER,
+			FORE_SHOULDER_LENGTH,
+			SHAPE,
+			THICKNESS,
+			FILLED,
+			MASS,
+			FINISH,
+			MATERIAL
+			);
+	
+	
 	// package scope constructor to encourage use of factory.
 	ComponentPreset() {
 	}