• Utilizar un gestor de BBDD como Lita para administrar los datos cómodamente.
  • El uso de semilla (salt) en la encriptación aumenta la seguridad pero vincula la clave al equipo donde se ha generado. La librería as3corelib genera una clave con una semilla (salt) que se almacena en elEncrypted Local Store
    (ELS - C:\Users\{user}\AppData\Roaming\Adobe\AIR\ELS) para cada aplicación. Usando esta semilla (o una por defecto si no se utiliza) se genera un valor aleatorio que forma parte de la clave para hacerla más segura. Para hacer la clave transportable utilizar Base64.
  • Usar as3corelib y la semilla (salt) No deja copiar (attach) una BBDD con una clave as3corelib. Lo que hacemos es cambiar-operar-restaurar la clave.
  • Usar el método connection.attach para abrir las dos bases de datos a la vez y copiar una en otra. Si hay problemas de integridad “malformed database” se puede corregir usando un admin que no sea Lita. (Usé SharpPlus SQLite Developer para borrar los trigger que daban problemas en una importación)
  • Runtime errors
  • Si usas as3corelib ten cuidado porque una misma cadena de texto genera claves diferentes en aplicaciones distintas.

Enlaces útiles:
Using the encrypted local store feature
Using encryption with SQL databases
Strategies for working with SQL databases

  • Share/Bookmark

Función que permite registrar eventos de teclado fácilmente y referenciarlos a la función que debe gestionarlos.
Permite aplicar atajos de teclados usando cualquier combinación de teclas.

registerKey({component}, [Keyboard.CONTROL, Keyboard.TAB], {function}, true);
/**
 * Register, capture and manage keys event for each component
 *
 * @param target Component whit key events to manage
 * @param shortcuts Array of keyBoard codes to apply shortcuts
 * @param handle Function that process key event
 * @param param Boolean to indicate if return event param
 *
 */
public static function registerKey (target:UIComponent,
    shortcuts:Array, handle:Function, returnParam:Boolean=true):void {
	var keys:Array = new Array();

	target.addEventListener(KeyboardEvent.KEY_DOWN,
           function (event:KeyboardEvent):void {
		if (keys.indexOf(event.keyCode) == -1) {
			keys.push(event.keyCode);
		}

		if (keys.length == shortcuts.length) {
			var result:Boolean = true;
			for each (var shortcut:int in shortcuts) {
				if (keys.indexOf(shortcut) == -1) {
					result = false;
					break;
				}
			}
			if (result) {
				if (returnParam) {
					handle.call(target, event);
				} else {
					handle.call(target);
				}
				event.preventDefault();
			}
		}
	});

	// Remove key on keyUp
	target.addEventListener(KeyboardEvent.KEY_UP,
           function (event:KeyboardEvent):void {
		var index:int = keys.indexOf(event.keyCode);
		if (index != -1) {
			keys.splice(index,1);
		}
	});

	// Remove all keys saved to return to initial state on 'focus in'
	target.addEventListener(FocusEvent.FOCUS_OUT,
           function (event:FocusEvent):void {
		keys = new Array();
	});
}
  • Share/Bookmark

Aquí dejo un pequeño truco para redimensionar automáticamente, en base a proporciones relativas, las columnas de un Spark Datagrid:

private const DATAGRID_SCROLL:int = 16;
[Bindable]
private var scrollGap:int = DATAGRID_SCROLL;

<s:DataGrid id="dt" width="100%" height="100%" ...>
<s:columns>
<s:ArrayList>
		<s:GridColumn dataField="title" headerText="MyTitle"
		      width="{(dt.scroller.verticalScrollBar.visible==true)
		      ? (dt.width-DATAGRID_SCROLL)*0.47
		      : (dt.width-scrollGap)*0.47}">
		</s:GridColumn>
</s:ArrayList>
</s:columns>
</s:DataGrid>
  • Share/Bookmark

Ejemplo de reordenación sobre un Datagrid Spark aplicando técnicas de Drag&Drop.

Código fuenteHaz clic con el botón derecho para obtener el código fuente.

Alex’s Flex Closet ofrece otro ejemplo de Drag and Drop con el componente Spark Datagrid.

  • Share/Bookmark

Adaptación a spark DataGrid del método de exportación a Excel usando formatters:

package es.util {
	import com.as3xls.xls.ExcelFile;
	import com.as3xls.xls.Sheet;

	import flash.errors.IllegalOperationError;
	import flash.net.FileReference;
	import flash.utils.ByteArray;

	import mx.controls.dataGridClasses.DataGridListData;

	import spark.components.DataGrid;
	import spark.components.gridClasses.GridColumn;

	public class FlexToExcel {
		public function FlexToExcel() {
			throw new IllegalOperationError ("Class "ExcelExporterUtil" is static. You can't instance this");
		}

		static public function exportDataGrid (dt:DataGrid, filename:String="excel.xls",
											   listData:DataGridListData=null):void {
			var head:Array = new Array();
			for each (var item:GridColumn in dt.columns.toArray()) {
				head.push(item.headerText);
			}

			var data:Array = new Array();

			for each (var obj:Object in dt.dataProvider) {
				var arr:Array=new Array();
				for each (var hd:GridColumn in dt.columns.toArray()) {
					arr.push(hd.itemToLabel(obj));
				}
				data.push(arr);
			}
			export(head,data,filename);
		}

		static private function export(head:Array, data:Array,filename:String):void {
			// Create sheet
			var cols:int = head.length;
			var rows:int = data.length+1;
			var sheet:Sheet = new Sheet();
			sheet.resize(rows,cols);

			// Header
			var row:int=0;
			var col:int=0;
			for each (var item:String in head) {
				sheet.setCell(row,col,item);
				col++;
			}

			// Data
			row=1;
			col=0;
			for each (var dataRow:Array in data) {
				for each (var dataCol:String in dataRow) {
					sheet.setCell(row,col,dataCol);
					col++;
				}
				col=0;
				row++;
			}

			// Add sheet
			var xls:ExcelFile = new ExcelFile();
			xls.sheets.addItem(sheet);
			var bytes:ByteArray = xls.saveToByteArray();
			// Generate file
			var fr:FileReference = new FileReference();
			fr.save(bytes, filename);
		}
	}
}

Y una aplicación de uso:

<?xml version="1.0"?>
<s:Application
	xmlns:fx="http://ns.adobe.com/mxml/2009"
	xmlns:s="library://ns.adobe.com/flex/spark"
	xmlns:mx="library://ns.adobe.com/flex/mx">

	<s:layout>
		<s:VerticalLayout/>
	</s:layout>

	<fx:Script>
		<![CDATA[
			import es.util.FlexToExcel;
			import mx.collections.ArrayCollection;
			import spark.components.gridClasses.GridColumn;

			[Bindable]
			private var items:ArrayCollection = new ArrayCollection([
				{nombre:"Andrés", apellido:"Sánchez", date:new Date()},
				{nombre:"Mónica", apellido:"Sánchez", date:new Date()},
				{nombre:"Agustina", apellido:"Sánchez", date:new Date()},
				{nombre:"Pablo", apellido:"Sánchez", date:new Date()},
				{nombre:"Magalí", apellido:"Sánchez", date:new Date()}
			]);

			private function exportToExcel():void {
				FlexToExcel.exportDataGrid(dt);
			}

			private function getCompleteLabel (item:Object, column:GridColumn):String {
				var result:String = "";
				if (item != null) {
					result = item.nombre + " " + item.apellido;
				}
				return result;
			}
		]]>
	</fx:Script>

	<fx:Declarations>
		<s:DateTimeFormatter id="myFormatter" dateTimePattern="dd/MM/yyyy"
							 errorText="test error!"/>
	</fx:Declarations>

	<s:DataGrid id="dt" dataProvider="{items}" width="100%" height="100%">
		<s:columns>
			<s:ArrayList>
				<s:GridColumn dataField="nombre" headerText="Nombre"/>
				<s:GridColumn dataField="apellido" headerText="Apellido"/>
				<s:GridColumn headerText="Completo" labelFunction="getCompleteLabel"/>
				<s:GridColumn headerText="Fecha" dataField="date" itemRenderer="es.renderer.DateRenderer"
							  formatter="{myFormatter}"/>
			</s:ArrayList>
		</s:columns>
	</s:DataGrid>

	<s:Button label="Export" click="exportToExcel();" />
</s:Application>

Es importante, para los datos con caracteres no ASCII usar la versión de la librería de dwj que corrije los problemas para estos caracteres (eñes, tildes, etc.).

Para los datos complejos con itemRenderer es aconsejable utilizar Formatter en el GridColumn para proporcionar la cadena del método itemToLabel.

  • Share/Bookmark
Creative Commons License
Esta obra está bajo una licencia de Creative Commons, excepto donde se indique expresamente lo contrario.
Special thanks to Mark James for the icon set used in this blog.