Sign in Join
Wiki copytemporary

FPSpreadsheet tutorial: Writing a mini spreadsheet application/es: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11## Introducción
22
33   FPSpreadsheet es un paquete potente para la lectura y escritura de ficheros de Hoja de cálculo (*spreadsheet*). La intención principal es aportar una plataforma capaz de exportar e importar de forma nativa datos a/desde los más importantes formatos de fichero de hojas de cálculo sin tener que instalar aplicaciones adicionales.
44
55   Pronto, como siempre, surge el deseo de utilizar este paquete también para editar el contenido y formato. Para este propósito, la librería contiene un control rejilla (FPSpreadSheetGrid) dedicado, que nos recuerda las características de una hoja de trabajo (*WorkSheet*) de las aplicaciones de hojas de cálculo. Junto a un conjunto de opciones de formato, esta demo todavía viene a tener 1400 líneas de código en su unidad de formulario principal. Por lo tanto, se ha diseñado un conjunto de controles visuales que simplifican ampliamente la creación de aplicaciones de hoja de cálculo (*SpreadSheets*).
66
77   La intención de esta tutoría es escribir un programa de hoja de cálculo simple en base a estos controles.
88
99   Aunque la mayor parte de la estructura interna de la librería FPSpreadsheet está cubierta mediante los controles visuales sigue siendo recomendable tener algún conocimiento de FPSpreadsheet. Por supuesto debería tenerse un conocimiento básico de Lazarus o FPC y sobre como trabajar con el inspector de objetos de Lazarus.
1010
1111## Controles Visuales FPSpreadSheet
1212
1313   FPSpreadsheet expone clases no visuales, tales como TsWorkbook, TsWorksheet etc. Esto mantiene la librería suficientemente generalizada para todo tipo de programas Pascal. Por otro lado, para programas con Interfaz Gráfica de Usuario (GUI: Graphic Unit Interface), se necesita algo de infraestructura que relacione los SpreadSheets con los formularios, grids y otros controles.
1414
1515### TsWorkbookSource
1616
1717   ![](/wiki-images/e/e0/TSWORKBOOKSOURCE.png) El corazón de los controles visuales FPSpreadSheet es la clase **TsWorkBookSource** que aporta un enlace entre los datos no visuales spreadsheet y los controles visuales del formulario. Su propósito es similar al que tiene el componente TDataSource en aplicaciones de base de datos que enlazan las tablas de las bases de datos o consultas (queries) a controles orientados a datos (data-aware).
1818
1919   Todos los controles visuales FPSpreadSheet tienen una propiedad `WorkbookSource` que los enlaza con la cadena de información aportada por TsWorkbookSource. WorkbookSource mantiene un listado de todos los controles vinculados. Estos controles se llaman internamente "listeners" porque se encuentran en modo escucha de la informa distribuida por WorkbookSource.
2020
2121   El libro de trabajo (WorkBook) y las hojas de trabajo (WorkSheets) que contiene, utilizan eventos para notificar a WorkBookSource todos los cambios relevantes: cambios en el contenido de las celdas o su formato, selección de otras celdas, añadir o borrar hojas de trabajo, etc. La información de estos cambios se pasa a través de los controles "listening" y reaccionan a su propio modo especializado a dichos cambios. Si por ejemplo se añade una hoja de trabajo a un libro, entonces el control visual TsWorkBookTabControl crea una nueva solapa para la hoja de trabajo y el control grid "TsWorksheetGrid" carga la nueva hoja de trabajo dentro de la grid.
2222
2323### Control TsWorkbookTabControl
2424
2525   ![](/wiki-images/c/cc/TSWORKBOOKTABCONTROL.png) Es un control tipo solapa (tabcontrol) que provee una solapa para cada hoja de trabajo (WorkSheet)del actual libro de trabajo (WorkBook). Los nombres de las solapas son idénticas a los nombres de las hojas de trabajo. La selección de cualquier otra solapa es comunicada a los otros controles del SpreadSheet a través de WorkbookSource.
2626
2727### TsWorksheetGrid
2828
2929   ![](/wiki-images/0/0b/TSWORKSHEETGRID.png%E2%80%8E) Es un DrawGrid personalizado descendiente del LCL y muestra celdas de la hoja de trabajo actual seleccionada. El texto no se almacena en la grid (como haría un StringGrid), pero se toman de la estructura de datos de TsWorksheet. Similarmente, la hoja de trabajo aporta la información de como está formateada cada celda. Como cualquier otra grid del LCL tiene un conjunto de propiedades y se puede tunear por parte de las aplicaciones adaptando sus `Options`. La más importante se describe abajo.
3030
3131### TsCellEdit
3232
3333   ![](/wiki-images/f/fa/TSCELLEDIT.png) Las aplicaciones de hoja de cálculo típicas proveen un línea para la edición de fórmulas y contenido de las celdas. Este es el propósito de **TsCellEdit**. Esto muestra el contenido de la celda activa dentro de la hoja de trabajo la cual es la misma que la que se encuentra activa en el grid de la hoja de trabajo (WorksheetGrid). Si se finaliza la edición (presionando `Enter`, o seleccionando otra celda en la grid)entonces se transfiere a la hoja de trabajo el nuevo valor de la celda. El control TsCellEdit es internamente del tipo memo que por ejemplo es capaz de procesar múltiples líneas de texto correctamente. Para insertar un forced line-break se puede pulsar la secuencia `Ctrl`+`Enter`.
3434
3535### TsCellIndicator
3636
3737   ![](/wiki-images/e/eb/TSCELLINDICATOR.png) Este es un control TEdit que muestra la dirección de la celda, seleccionada actualmente, en notación Excel, e.g. 'A1' Si la celda activa se encuentra en la primera fila y primera columna (row = 0, column = 0). A la inversa, si se introduce una dirección de celda válida dentro de este control, entonces la correspondiente celda se hace activa.
3838
3939### TsCellCombobox
4040
4141   ![](/wiki-images/3/3c/TSCELLCOMBOBOX.png) Este combobox se puede utilizar para modificar varias propiedades de la celda seleccionando sus valores de una lista desplegable. La propiedad afectada viene determinada por el `CellFormatItem` del combobox:
4242
4343- `cfiFontName`: el listado contiene los nombres de todas las fuentes disponibles en el sistema. Si se selecciona un elemento de ese listado entonces el tipo de fuente que se ha seleccionado se utiliza para dar formato a la/las celdas que tuviésemos seleccionadas antes de desplegar sus propiedades para cambiarlas.
4444- `cfiFontSize`: este listado contiene los tamaños de fuente más comúnmente utilizados en hojas de cálculo. Seleccionando un elemento de los disponibles se establece por tanto el tamaño de fuente para la/las celda(s) seleccionadas.
4545- `cfiFontColor`: este listado contiene todos los colores disponibles en la paleta del libro de trabaja (workbook). El color seleccionado se asigna a la fuente de la/las celda(s) seleccionada.
4646- `cfiBackgroundColor`: similar a `cfiFontColor` - se utiliza el color seleccionado como color de relleno de fondo de la/las celda(s) seleccionadas.
4747
4848### TsSpreadsheetInspector
4949
5050   ![](/wiki-images/b/b8/TSSPREADSHEETINSPECTOR.png) Hereda de TValueListEditor y muestra pares nombre-valor (name-value) para propiedades del libro de trabajo, la hoja de trabajo y el contenido y formateado de la celda activa. Su propósito principal es ayudar con el depurado (debugging).
5151
5252## Escribiendo una aplicación de hoja de cálculo
5353
5454   Bueno suficiente teoría hasta aquí, comencemos. Vamos a escribir una pequeña aplicación de hoja de cálculo. Cierto, no va a competir con las principales aplicaciones ofimáticas como Excel u OpenOffice/LibreOffice, pero tiene todos los ingredientes principales asociados a FPSpreadsheet. Y utilizando controles FPSpreadsheet nos permite conseguir esto con unas mínimas líneas de código.
5555
5656### Preparativos
5757
58-   <img src="fpspreadsheetcontrols_preparations.png‎" title="fpspreadsheetcontrols_preparations.png‎" width="400" alt="fpspreadsheetcontrols_preparations.png‎" />
58+   ![](/wiki-images/8/86/Fpspreadsheetcontrols_preparations.png%E2%80%8E)
5959
6060   Primero de todo vamos a crear un nuevo proyecto y lo almacenamos en alguna carpeta de nuestra elección.
6161
6262   Ya que las aplicaciones ofimáticas tienen un menú y una barra de utilidades (toolbar) añadimos al formulario los correspondientes componentes **TMainMenu** y **TToolbar**
6363
6464   (Se puede incluso mimetizar el ribete del interfaz de usuario de las nuevas aplicaciones de Microsoft añadiendo un **TSpkToolbar** de [Lazarus Code and Components Repository](http://sourceforge.net/p/lazarus-ccr/svn/HEAD/tree/components/spktoolbar/), pero ten en cuenta que este componente no provee todavía todas las características de una barra de menú estándar).
6565
6666   En efecto, necesitaremos **otra toolbar** para la línea del editor de fórmulas. Como verás más adelante, será redimensionable; como control de tamaño añade un **TSplitter** al formulario con una alineación top de tal manera que esté posicionado debajo de las dos barras de utilidades. En orden a mantener un tamaño mínimo para la toolbar se establecen restricciones: Mira la altura actual de la toolbar e introduce su valor numérico dentro del campo `MinHeight` de la propiedad `Constraints` en la toolbar. Para separar la barra de utilidades (toolbar) de fórmulas del resto del formulario principal, activamos la opción `ebBottom` de la propiedad `EdgeBorders` de la segunda toolbar.
6767
6868   Debido a que tanto el menú como las barras de utilidades tienen que manejar las mismas acciones de usuario resulta ventajoso aportar un **TActionList** para almacenar todas las posibles acciones. Si se asigna a los elementos del menú y a los pulsadores de utilidades (ToolButtons) entonces ambos reaccionarán a la interacción del usuario de la misma manera sin necesidad de código adicional. Y: además los controles visuales del paquete FPSpreadsheet contienen un montón de acciones estándar listas para usar.
6969
7070   La barra de utilidades de la aplicación completa va a contener un montón de iconos. Por tanto necesitamos un componente **TImageList** el cual tiene que ser enlazado a la propiedad `Images` del menú principal (TMainMenu), las barras de utilidades (TToolbars), y los listados de acciones (TActionList). A la pregunta de donde obtener iconos la respuesta más fácil es buscar en la carpeta `images` de la propia instalación de Lazarus donde podemos encontrar iconos estándar para cargar, salvar, salir, flechas, imprimir,configurar,.... Es un subconjunto de la [librería de iconos famfamfam SILK](http://www.famfamfam.com/lab/icons/silk/). Otra enorme colección se encuentra en [la colección de iconos Fugue](http://p.yusukekamiyamane.com/). Ambas colecciones están licenciadas como "Creative commons" y son libres incluso para su uso comercial, añadiendo la referencia apropiada en los programas creados. Cuando selecciones iconos procura que tengan el formato de imagen png y asegúrate de utilizar siempre el mismo tamaño, usualmente 16x16 pixels.
7171
7272### Configurando visualmente el *workbook*
7373
7474#### TsWorkbookSource
7575
7676   Tal como se ha descrito en la sección de introducción, el componente **TsWorkbookSource** es el interface entre WorkBook y los controles de interfaz de usuario. Se añade por tanto este componente al formulario y se le asigna un nombre decente (en este caso dejaremos el nombre que tiene por defecto `sWorkbookSource1`). Como veremos en breve, este componente tendrá que ser asignado a la propiedad `WorkbookSource` de todos los controles del paquete visual FPSpreadsheet_visual.
7777
7878   WorkBookSource se encarga de la carga y escritura de datos desde/hacia el fichero y de la comunicación con WorkBook. Por tanto, posee un conjunto de opciones que se pasan al WorkBook y controla estos procesos:
7979
8080``` pascal
8181 type
8282 TsWorkbookOption = (boVirtualMode, boBufStream, boAutoCalc, boCalcBeforeSaving, boReadFormulas);
8383 TsWorkbookOptions = set of TsWorkbookOption;
8484```
8585
86-<img src="sTabControl.png" title="sTabControl.png" width="400" />
86+![](/wiki-images/0/03/STabControl.png)
8787
8888   Los más importantes son:
8989
9090- `boAutoCalc`: activa el cálculo automático de las fórmulas en el momento que cambia el contenido de las celdas.
9191- `boCalcBeforeSaving`: calcula las fórmulas antes de que el WorkBook se escriba al fichero.
9292- `boReadFormulas`: si se establece entonces se leen las fórmulas del fichero, de otro modo solamente el resultado de la fórmula.
9393- `boBufStream` y `boVirtualMode`: en programas no visuales estas opciones pueden ayudar si las aplicaciones se quedan sin memoria en el caso de workbooks extensos. `boVirtualMode`, en particular, no es utilizable para aplicaciones visuales, porque evita guardar datos en las celdas de la hoja de trabajo. Ver también [[FPSpreadsheet|FPSpreadsheet#Virtual_mode]].
9494
9595   En este tutorial se asume que las opciones `boAutoCalc` y `boReadFormulas` se encuentran activas.
9696
9797#### TsWorkbookTabControl
9898
9999   El primer control visual utilizado en el formulario es un **TsWorkbookTabControl** - lo emplazamos en el formulario (dentro del espacio no ocupado por la ToolBar). Client-align it within the form, this shows the TabControl as a bright rectangle only. Ahora vinculamos su propiedad `WorkbookSource` al componente TsWorkbookSource que hemos añadido previamente. Ahora TabControl muestra una solapa llamada "Sheet1". Esto es debido a que TsWorkbookSource ha creado WorkBook vacío conteniendo una sola hoja (WorkSheet) "Sheet1". WorkbookSource sincroniza este WorkBook interno con TabControl (y el resto de elementos visuales asociados) tal como se muestra la hoja como solapa.
100100
101101   En Excel las solapas de las hojas se encuentran al fondo del formulario - para lograr este efecto se puede establecer la propiedad `TabPosition` del control TabControl a `tpBottom`; hay algunas incidencias para el dibujado del LCL con TabPosition, aunque, de antemano, yo prefiero los valores por defecto, `tpTop`.
102102
103103   El pantallazo muestra lo que obtenemos.\
104104
105105#### TsWorksheetGrid
106106
107-   <img src="sWorksheetGrid.png" title="sWorksheetGrid.png" width="400" alt="sWorksheetGrid.png" /> Ahora añadimos un control **TsWorksheetGrid**. Lo emplazamos en algún lugar dentro del espacio ocupado por el control TabControl. De esta forma viene a colgar de TabControl. Al hacer esto podremos ver algo parecido a un componente grid de cadenas (StringGrid). Enlazamos su propiedad `WorkbookSource` a la fuente añadida al principio y entonces la rejilla se parece más a una hoja de cálculo (SpreadSheet): están las cabeceras de las columnas etiquetadas con letras "A", "B", etc, y las filas etiquetadas con números "1", "2", etc; la celda activa, A1, está remarcada por el borde grueso.
107+   ![](/wiki-images/7/73/SWorksheetGrid.png) Ahora añadimos un control **TsWorksheetGrid**. Lo emplazamos en algún lugar dentro del espacio ocupado por el control TabControl. De esta forma viene a colgar de TabControl. Al hacer esto podremos ver algo parecido a un componente grid de cadenas (StringGrid). Enlazamos su propiedad `WorkbookSource` a la fuente añadida al principio y entonces la rejilla se parece más a una hoja de cálculo (SpreadSheet): están las cabeceras de las columnas etiquetadas con letras "A", "B", etc, y las filas etiquetadas con números "1", "2", etc; la celda activa, A1, está remarcada por el borde grueso.
108108
109109   Puede que se necesite cambiar `TitleStyle` a `tsNative` en la grid para lograr el themed painting de la cabecera de la fila y columna. Y aquí también es un buen lugar para adaptar las `Options` de la grid para activar algunas características bien conocidas de las hojas de cálculo:
110110
111111- `goEditing` debe estar activo, de otra manera el contenido de la grid no se podrá modificar.
112112- `goAlwaysShowEditor` debe estar off porque interfiere con la convención de edición de las aplicaciones de hojas de cálculo.
113113- `goColSizing` habilita cambiar el ancho de columna a través del dragging de la línea divisoria que encontramos en las cabeceras de las columnas adyacentes.. Dragging tiene lugar con el pulsador izquierdo del ratón presionado.
114114- `goRowSizing` realiza lo mismo con la altura de las filas.
115115- `goDblAutoResize` activa la característica de optimización de ancho de columna que se obtiene haciendo doble click en la línea divisoria del encabezado de la columna que se situa hacia al siguente columna. La "optimum" ancho de columna es tal que no se trunca el contenido de la celda y no se muestra espacio extra sobrante.
116116- `goHeaderHotTack` nos da información adicional si se pasa el cursor del ratón por encima de la cabecera de las celdas.
117117- `goRangeSelect` (se encuentra "on" por defecto) y habilita la selección de un rango rectangular de celdas haciendo click con el pulsador izquierdo del ratón y sin soltarlo arrastrandolo hasta completar la selección de celdas (en definitiva de esquina a esquina opuesta del rectángulo). Si se tiene una versión de Lazarus del trunk y incluso se puede realizar una selección multiple de areas rectangulares manteniendo pulsada la tecla CTRL antes de seleccionar el siguente rectángulo - en la versión 1.2.6 de Lazarus (en el momento de estribir esto) solamente se permite la selección de un rango.
118118- `goThumbTracking` activa el scrolling inmediato de la hoja (Worksheet) si una de las barras de desplazamiento es arrastrada con el ratón. Las aplicaciones ofimáticas usualmente desplazan por líneas, lo cual se puede conseguir estableciendo a off `goSmoothScroll`.
119119
120120   En adición a estas `Options` heredada de `TCustomGrid` existen más opciones especializadas para operar con hojas de cálculo:
121121
122122- `ShowGridLines`, si se establece a `false` oculta la fila y columna en la rejilla.
123123- `ShowHeaders` puede establecerse a `false` para ocultar las cabeceras de fila y columna. (Se puede conseguir esto mismo por medio de la desfasada propiedad `DisplayFixedColRow`).
124124- Las grids del LCL normalmente truncan el texto al borde de la celda cuando es más largo que el ancho de la celda. Si se establece `TextOverflow` al valor `true` entonces el texto se expande a las celdas adyacentes.
125125
126126   Las propiedades `AutoCalc` y `ReadFormulas` están pensadas para su uso independientemente de la grid de la hoja de cálculo (WorkSheetGrid)(e.g. sin un TsWorkbookSource). Por favor utilizar las opciones correspondientes del WorkbookSource en su lugar. (`AutoCalc` habilita el cálculo automático de fórmulas cada vez que cambia el contenido de la celda. `ReadFormulas` activa la lectura de fórmulas desde ficheros, de otro modo la rejilla solamente mostraría el resultado de la fórmula).
127127
128128### Edición de valores y fórmulas, Navegación
129129
130130   Cuando se compile y arranque el programa se tendrá disponible entrar datos en el grid. Simplemente hay que seleccionar una celda que se necesita editar haciendo click sobre ella o bien desplazándose a la misma con las teclas de cursor, hasta que sea resaltada con el borde ancho, en ese momento ya se pueden editar. A continuación seleccionamos otra celda o bien presionamos la tecla `ENTER`. Utilizando `Enter` automáticamente seleccionamos la siguiente celda en la grid. La propiedad de la rejilla `AutoAdvance` define lo que se conoce como "próxima celda": por defecto, `Enter` mueve a la siguiente celda situada debajo (`aaDown`), pero se puede mover también a la derecha (`aaRight`), o dejar esta característica apagada (`aaNone`) - ver el tipo `TAutoAdvance` definido en la unidad `grids.pas` para más opciones.
131131
132132   Si -como vimos antes- se habilita la opción WorkbookSource `boAutoCalc` entonces la hoja soporta automáticamente el cálculo de **formulas**. Por poner un ejemplo, vayamos a la celda A1, entra el número `10`, a continuación vamos a la celda A2 y entramos la fórmula `=A1+10`. La fórmula automáticamente se evalúa y se muestra el resultado `20`, que se muestra en la celda A2.
133133
134134   Cuando navegamos por la grid podemos notar que la celda A2 únicamente muestra el resultado de la fórmula, parece que no hay forma de modificar la fórmula una vez que se introduce. No hay necesidad de preocuparse - presionamos la tecla `F2` o hacemos click en la celda una segunda vez de entrar **enhanced edit mode** momento en el cual las fórmulas estarán visibles en la celda.
135135
136-<img src="sCellIndicator_sCellEdit.png‎" title="sCellIndicator_sCellEdit.png‎" width="400" alt="sCellIndicator_sCellEdit.png‎" />    En orden a editar las fórmulas, las aplicaciones ofimáticas ofrecen una barra dedicada a la edición de fórmulas. Por supuesto, fpspreadsheet tiene esta característica también. Se encuentra implementado dentro del componente **TsCellEdit** que está establecido para mostrar siempre el contenido completo de la fórmula. Si recuerdas la segunda barra de utilidades de la sección "Preparativos", pues ahí se situará TsCellEdit. Pero, un momento, - hay algo más que considerar: Debido a que las fórmulas ocasionalmente tienden a ser bastante más largas de lo que el control puede mostrar, entonces es necesario que soporte varias líneas de edición, lo mismo que con texto multi-línea. TsCellEdit puede hacer esto puesto que hereda de TCustomMemo el cual es un control multi-línea. También hay que recordar que añadimos un separador al formulario de la segunda barra de utilidades. Esto lo necesitamos para los ajustes verticales en caso de necesitar el uso de la característica multilínea de TsCellEdit: simplemente presiona y mantén pulsado el separador para mostrar más líneas, o atrástralo hasta graduar la altura a las necesidades de una simple línea de acuerdo a las restricciones de MinHeight que hemos asignado a la barra de utiliddes.
136+![](/wiki-images/1/1a/SCellIndicator_sCellEdit.png%E2%80%8E)    En orden a editar las fórmulas, las aplicaciones ofimáticas ofrecen una barra dedicada a la edición de fórmulas. Por supuesto, fpspreadsheet tiene esta característica también. Se encuentra implementado dentro del componente **TsCellEdit** que está establecido para mostrar siempre el contenido completo de la fórmula. Si recuerdas la segunda barra de utilidades de la sección "Preparativos", pues ahí se situará TsCellEdit. Pero, un momento, - hay algo más que considerar: Debido a que las fórmulas ocasionalmente tienden a ser bastante más largas de lo que el control puede mostrar, entonces es necesario que soporte varias líneas de edición, lo mismo que con texto multi-línea. TsCellEdit puede hacer esto puesto que hereda de TCustomMemo el cual es un control multi-línea. También hay que recordar que añadimos un separador al formulario de la segunda barra de utilidades. Esto lo necesitamos para los ajustes verticales en caso de necesitar el uso de la característica multilínea de TsCellEdit: simplemente presiona y mantén pulsado el separador para mostrar más líneas, o atrástralo hasta graduar la altura a las necesidades de una simple línea de acuerdo a las restricciones de MinHeight que hemos asignado a la barra de utiliddes.
137137
138138   TsCellEdit cubrirá todo el espacio disponible en la segunda barra de utilidades. Antes de añadir TsCellEdit podemos hacer la vidda más fácil si pensamos un poco sobre que otras cosas podemos añadir en esta segunda barra de utilidades. En Excel hay un indicador que muestra la dirección de la celda activa actual. Este es el propósito de **TsCellIndicator**. Since its height should not change when the toolbar is dragged down we first add a **TPanel** to the second toolbar; reduce su `Width` sobre 100 pixels, remueve su `Caption` y establece `BevelOuter` a `bvNone`.
139139
140140   Añade TsCellIndicator a este panel y alinealo al tope del panel. Conecta su `WorkBookSource` al control TsWorkbookSource del formulario e inmediatamente aparecerá el texto "A1", la dirección de la celda actualmente seleccionada.
141141
142142   Algunas veces resulta deseable cambiar la anchura de este cuadro en tiempo de ejecución, por lo cual ¿porqué no añadir un separador a esta segunda barra?, pues podemos hacerlo estableciendo su propiedad `Align` a `alLeft`. El resultado es un poco extraño: el separador (splitter) se ubica a su borde izquierdo aunque se esperaba encontrar a la derecha del panel. Esto es debido a que el panel no está alineado por defecto. Hay que establecer la propiedad `Align` del panel a `alLeft`, y arrastrar sin soltar el separador hacia la derecha del panel. Ahora el separador lo tenemos en la posición correcta.
143143
144144   Casi todo hecho... Finalmente añadimos un componente TsCellEdit al espacio vacío de la barra. La alineación del cliente es tal que rellena el resto del espacio de la barra. Como suele ser habitual, establecemos su propiedad `WorkBookSource` a la instancia de TsWorkbookSource en el formulario.
145145
146146   Compila y ejecuta. Juega con el programa:
147147
148148- Enter some dummy data. Navega por el worksheet. Verás que el CellIndicator siempre muestra la dirección de la celda activa. El contenido de la celda activa se muestra en la caja de CellEdit. El indicador CellIndicator aparte de mostrar el contenido de la celda activa también permite editarlo. Teclea en la dirección de la celda que necesitas tener activa, presiona `Enter`, y observa que sucede...
149149- Entra una fórmula. Navega de nuevo dentro dentro de la celda de formulas - se muestra la fórmula en el editor de fórmulas (CellEdit) donde se puede modificar rápidamente.
150150- Introduce texto multilínea - you can enforce a lineending in the CellEdit manteniendo la tecla `Ctrl`pulsada mientras presionas `ENTER`. La celda muestra solamente una línea de texto. Arrastra el horizontal splitter underneath the second toolbar down - the CellEdit muestra todas las líneas. Otra forma de ver todas las líneas de texto, es ajustar la altura de celda. Debes tener activada la `Option` `goRowSizing` de la rejilla. Entonces ya puedes arrastrar la línea divisoria inferior de fila de la celda multilínea más hacia abajo para incrementar el alto de fila - de esta forma ya aparecen en la celda las líneas perdidas.
151151
152152### Formateado de las celdas
153153
154154   Adicionalmente a entrar datos, el usuario habitualmente necesita aplicar formateado a las celdas para afianzarlas o agruparlas. El worksheet se establece de tal manera que sus celdas muestran el formato tomado del workbook. Además los controles visuales FPSpreadsheet son capaces de almacenar los atributos de formato dentro de la celda. Debido al mecanismo de notificación a través de la WorkbookSource estos formatos se devuelven a la WorksheetGrid para la visualización
155155
156156#### Añadiendo comboboxes para nombre de fuente, tamaño de fuente, y color de fuente
157157
158-<img src="sCellFontCombobox.png‎" title="sCellFontCombobox.png‎" width="400" alt="sCellFontCombobox.png‎" />    En esta sección cubrimos la necesidad de modificar la fuente del texto de la celda a través de una selección de nombre, tamaño y/o color. El FPSpreadsheet visual aporta el flexible **TsCellCombobox** para este propósito. Tiene la propiedad `CellFormatItem`, la cual define que atributo controla:
158+![](/wiki-images/c/ce/SCellFontCombobox.png%E2%80%8E)    En esta sección cubrimos la necesidad de modificar la fuente del texto de la celda a través de una selección de nombre, tamaño y/o color. El FPSpreadsheet visual aporta el flexible **TsCellCombobox** para este propósito. Tiene la propiedad `CellFormatItem`, la cual define que atributo controla:
159159
160160- `cfiFontName`: Esta opción rellena el combobox con todas las fuentes disponibles en el sistema. El elemento seleccionado se utilza como tipo de fuente en las celdas seleccionadas.
161161- `cfiFontSize` rellena el combobox con los tamaños de fuente más utilizadas (tamaño en puntos). De nuevo, el elemento seleccionado define el tamaño de fuente de las celdas seleccionadas.
162162- `cfiFontColor` añade todos los colores pre-definidos ("la paleta de colores") del libro al combobox para establecer el color del texto de las celdas seleccionadas. Los elementos del combobox consisten en un pequeño recuadro de colores junto a su correspondiente nombre de color. Si el `ColorRectWidth` se encuentra establecido a `-1` el nombre de color es dropped.
163163- `cfiBackgroundColor`, lo mismo con el color de fondo de las celdas seleccionadas.
164164- `cfiCellBorderColor`, lo mismo con el color del borde de las celdas seleccionadas - esta característica no está soportada todavía actualmente.
165165
166166   Añade tres TsCellComboboxes a la primera barra de herranmientas y establece para la propiedad `CellFormatItem` los valores `cfiFontname` , `cfiFontSize`, y `cfiFontColor`, respectivamente. Enlaza la propiedad `WorkbookSource` al TsWorkbookSource del formulario. Es posible que desee aumentar el ancho del cuadro combinado del nombre de la fuente de tal manera que los nombres de las fuentes más largas no se corten; los demás cuadros combinados pueden llegar a ser más estrechos. También es posible que desee desactivar los nombres de los colores del tercer combobox estableciendo su `ColorRechtWidth` a `-1`.
167167
168168   Esto es todo para modificar fuentes. Compilar y ejecutar. Entrar algo de texto y jugar con estas nuevas características del programa.
169169
170170#### Utilizando acciones estandar
171171
172-<img src="sFontStyleAction_selected.png" title="sFontStyleAction_selected.png" width="300" alt="sFontStyleAction_selected.png" />    FPSpreadsheet soporta un montón de formatos que se pueden aplicar a las celdas, tales como alineación de texto, rotación de texto, fuente de texto, o bien los colores de fondo y bordes. Las aplicaciones de Interface Graficas de Usuario (GUI) típicas tienen mandatos de menú y/o barras de utilidades con pulsadores que se asignan a cada una de esas propiedades y permiten realizarlas mediante un simple click de ratón. Adicionalmente, el estado de estos controles a menudo reflejan las propiedades de la celda activa. Por ejemplo, si hay un pulsador para usar el formato de fuente negrita (bold)entonces dicho pulsador debe aplicar el formato al ser pulsado si no tiene activo dicho formato y revertir el formato a normal si ya se encuentra en negrita. Para simplificar la codificación de estas tareas se han añadido una gran cantidad de acciones estandar a la librería.
172+![](/wiki-images/3/39/SFontStyleAction_selected.png)    FPSpreadsheet soporta un montón de formatos que se pueden aplicar a las celdas, tales como alineación de texto, rotación de texto, fuente de texto, o bien los colores de fondo y bordes. Las aplicaciones de Interface Graficas de Usuario (GUI) típicas tienen mandatos de menú y/o barras de utilidades con pulsadores que se asignan a cada una de esas propiedades y permiten realizarlas mediante un simple click de ratón. Adicionalmente, el estado de estos controles a menudo reflejan las propiedades de la celda activa. Por ejemplo, si hay un pulsador para usar el formato de fuente negrita (bold)entonces dicho pulsador debe aplicar el formato al ser pulsado si no tiene activo dicho formato y revertir el formato a normal si ya se encuentra en negrita. Para simplificar la codificación de estas tareas se han añadido una gran cantidad de acciones estandar a la librería.
173173
174174- **TsWorksheetAddAction**: añade una hoja vacía al libro. Especifica su nombre en la propiedad `NameMask`. El `NameMask` debe contener el especificador de formato `%d` que es reemplazado en tiempo de ejecución por un número de tal manera que el nombre de la hoja sea único.
175175
176176- **TsWorksheetDeleteAction**: borra la hoja activa del libro después de confirmar en el cuadro de diálogo. La última hoja no puede borrarse.
177177
178178- **TsWorksheetRenameAction**: renombra la hoja activa.
179179
180180- **TsCopyAction**: Copia las celdas actualmente seleccionadas a un listado interno ("CellClipboard") desde donde pueden volverse a pegar dentro de la hoja de cálculo en otra ubicación. El proceso puede realizarse al estilo del portapapeles ("copia"/"corta", luego "pega") o como "copy brush" de las aplicaciones ofimáticas. La propiedad `CopyItem` determina la manera en que se transfiere la celda entera, o solamente valores de la celda, o el formato de las celdas.
181181
182182- **TsFontStyleAction**: Modifica el estilo de la fuente de la(s) celda(s) seleccionada(s). La propiedad `FontStyle` define como la acción establece la fuente a negrita(bold), itálica(italic), subrayada(underlined) o tachada(striked-out). Normalmente cada estilo de fuente se maneja mediante su propia acción. Ver ejemplo más abajo.
183183
184184- **TsHorAlignmentAction**: Se puede utilizar para modificar la alineación horizontal del texto de las celdas seleccionadas. Selecciona `HorAlignment` para definir el tipo de alineación (left, center, right) con esta acción. Se aportan varias acciones para ofrecer todos los alineamientos disponibles mediante TsFontStyleAction. Están agrupadas de modos de selección exclusivos tales como radiobuttons.
185185
186186- **TsVertAlignmentAction**: Cambia la alineación vertical del texto de las celdas seleccionadas: el tipo de alineación se define en la propiedad `VertAlignment`. Nuevamente estas acciones funcionan como radiobuttons.
187187
188188- **TsTextRotationAction**: Permite especificar la orientación del texto en las celdas seleccionadas tal como se define en la propiedad `TextRotation` en un modo mutuamente exclusivo.
189189
190190- **TsWordWrapAction**: Activa la característica word-wrapping para las celdas seleccionadas: si el texto es más largo que el ancho de celda (o alto si el texto se rota), entonces se wrapped en múltiples filas.
191191
192192- **TsNumberFormatAction**: Define el formato de número que se utilizará en las celdas seleccionadas. El formato a utilizar se define en las propiedades `NumberFormat` (tal como `nfFixed`) for built-in formats, y `NumberFormatStr` para formato especializado.
193193
194194- **TsDecimalsAction**: Permite incremetnar o decrementar el número de dígitos decimales que se mostrarán en las celdas seleccionadas. La propiedad `Delta` controla cuando se necesita un incremento (+1) o un decremento (-1).
195195
196196- **TsCellBorderAction**: Permite especificar si se dibujará un borde alrrededor e las celdas seleccionadas. Las subpropiedadesThe `East`, `West`, `North`, `South`, `InnerHor`, `InnerVert` del borde `Borders` define que aspecto tendrá en cada lado del rango de celdas. Fíjate que cada rango rectangular de celdas se considera un bloque; las propiedades `East`, `West`, `North` y `South` son responsables de los bordes externos del bloque completo, los bordes internos se define mediante `InnerHor` y `InnerVert`. Utilizando estas propiedades se pueden conmutar los bordes **on** y **off**(`Visible`), y adicionalmente se puede cambiar el estilo de línea y su color.
197197
198198- **TsMergeAction**: Si se encuentra marcada entonces las celdas de cada rango rectangular seleccionado se fusionan en un solo bloque. Desmarcandolo, la acción separa los bloques individuales que componen el bloque. Fíjate que el contenido y formato del bloque se define mediante la celda superior izquierda de cada bloque; el contenido y formato de las otras celdas se pierde.
199199
200200#### Adding buttons for "Bold", "Italic", and "Underline"
201201
202-<img src="sFontStyleAction_in_ActionListEditor.png" title="sFontStyleAction_in_ActionListEditor.png" width="350" alt="sFontStyleAction_in_ActionListEditor.png" />    Si no has trabadajo nunca antes con **acciones estandar** aquí tienes algunos detalles **instrucciones paso a paso**. Fijémonos en el siguiente ejemplo que nos permitirá cambiar el estilo de fuente de las celdas seleccionadas a **negrita**. La acción estandar que es responsable de esta característica es `TsFontStyleAction`.
202+![](/wiki-images/d/d0/SFontStyleAction_in_ActionListEditor.png)    Si no has trabadajo nunca antes con **acciones estandar** aquí tienes algunos detalles **instrucciones paso a paso**. Fijémonos en el siguiente ejemplo que nos permitirá cambiar el estilo de fuente de las celdas seleccionadas a **negrita**. La acción estandar que es responsable de esta característica es `TsFontStyleAction`.
203203
204204- En primer lugar, añadimos esta acción al formulario: Doble-click en **TActionList** para abrir el "Editor ActionList".
205205- Click flecha hacia abajo próximo al botóne "+" , y selecciona el elemento "Nueva acción estandar" desde el menú drop-down.
206206- Esto abre un diálogo con el listado de "Standard Action Classes" registradas.
207207- Desplaza hacia abajo hasta que encuentres un grupo llamado "FPSpreadsheet".
208208- En este grupo, selecciona el elemento "TsFontStyleAction" haciendo doble-click.
209209- Ahora aparece un elemento `sFontStyleAction1` en el editor de ActionLis.
210210- It should already be selected like in the screenshot a la derecha. Si no, entonces selecciona select `sFontStyleAction1` en el Editor de ActionList para traerlo hacia arriba en el Inspector de Objetos y establecer sus propiedades.
211211 - Use the text "Bold" for the `Caption` - this is the text that will be assigned to the corresponding menu item.
212212 - Similarly, assign "Bold font" to the `Hint` property.
213213 - Establece `ImageIndex` al índice del icono del listado de imágenes (ImageList) del formulario que deseas ver en la toolbar.
214214 - Asegúrate de que el elemento `fssBold` se encuentra resaltado in the dropdown list de la propiedad `FontStyle`. Si no, seleccionalo. Desde `TsFontStyleAction` se pueden manejar varios estilos de fuentes (bold, italic, underline, strikeout) con la que tendremos que indicar a la acción de que estilo de fuente será responsable.
215215 - De igual manera que con los controles visuales, no te olvides asignar el TsWorkbookSource a la propiedad correspondiente `WorkbookSource` de la acción. Esto activa la comunicación por un lado entre worksheet/workbook , y la acción y controles relacionados por el otro.
216216
217217   Having set up the standard action we add a menu item to the form's **MainMenu**. Double-click on the TMainMenu of the form to bring up the "Menu Editor". Since the menu is empty so far there is only a dummy item, "New item1". This will become our "Format" menu. Select the item, and type "Format" into the `Caption` property field. Now the dummy item is re-labelled as "Format". Right-click on this "Format" item, and select "Create submenu" from the popup menu which brings up another new menu item, "New item2". Select it. In the dropdown list de la propiedad `Action` del inspector de objetos, pick the `sFontStyle1` action - esta es justamente la acción que hemos establecido - y el elemento de menú muestra automáticamente el caption aportado por la acción del componente, "negrita".
218218
219219   Finally we add a **toolbar button** for the "bold" action. Right-click onto the TToolbar, and add a new toolbutton seleccionando el elemento "New button" del menú emergente (popup). Ve a la propiedad `Action` de nuevo en el inspector de objetos, pick the `sFontStyle1` item, y esto es suficiente para dotar a los botones de utilidad (tool buttons) de la habilidad de establecer la fuente de las celdas a negrita.
220220
221221   Repite el proceso con otros dos botones. Diséñalos para establecer el estilo de fuente a **cursiva** y **subrayado**.
222222
223223   Prueba el programa compilándolo. Teclea algo de texto en las celdas. Selecciona una de ellas y haz click en el toolbutton "Negrita" y ¡voila!, la celda muestra el contenido en negrita. Selecciona otra celda. Fíjate que el toolbutton se dibuja automáticamente en el estado hundido si la celda tiene fuente en negrita. Repítelo con los otros botones.
224224
225225### Salvando a fichero
226226
227227   Después de añadir datos a la rejilla (grid)vamos a necesitar **guardar su contenido a un fichero de hoja de cálculo**. Lazarus nos aporta toda la infraestructura de salvado necesaria que tiene disponible en las acciones estandar `TFileSaveAs`. Esta accción abre automáticamente un diálogo del tipo **FileDialog** para que podamos poner el nombre del fichero.
228228
229229   Selecciona la acción estándar `TFileSaveAs` de la lista de clases de acciones. No está en la categpría "FPSpreadsheet", está en el grupo "File" ya que es una acción estándard de la LCL.
230230
231-<img src="sFileFormatsForSaving.png‎" title="sFileFormatsForSaving.png‎" width="400" />
231+![](/wiki-images/7/76/SFileFormatsForSaving.png%E2%80%8E)
232232
233233   Primeramente especifiquemos las propiedades del diálogo `Dialog` FileDialog. En concreto la propiedad de la acción `TFileSaveAs` en el inspector de objetos. Es conveniente conveniente tener la posibilidad de salvar el fichero de la hoja de cálculo en varios formatos; esto lo podemos conseguir preparando un listado de formatos de fichero para la propiedad `Filter` del diálogo. Pega el texto siguiente dentro del valor para esta propiedad:
234234
235235
236236`Excel XML spreadsheet (*.xlsx)|*.xlsx|Excel 97-2003 spreadsheets (*.xls)|*.xls|Excel 5 spreadsheet (*.xls)|*.xls|Excel 2.1 spreadsheets (*.xls)|*.xls|LibreOffice/OpenOffice spreadsheet (*.ods)|*.ods|Comma-delimited files (*.csv)|*.csv|WikiTable (WikiMedia-Format, *.wikitable_wikimedia)|*.wikitable_wikimedia`
237237
238238   Cuando hacemos click en el pulsador que tiene los puntos suspensivos próximos a `Filter` entonces aparece el listado de ficheros en un diálogo más claramente ordenado mostrado a la derecha.
239239
240240   Establece una de las extensiones de fichero disponibles para que sea la que tengamos por defecto, (e.g. xlsx para este índice de ficheros de diálogo). Para ello utilizamos la propiedad `FilterIndex`. Una vez establecido su valor cuando se abra ese diálogo nos mostrara de forma predeterminada aquellos ficheros que tengan la extensión .xlsx. Es necesario poner a 1 la propiedad `FilterIndex` ya que es el número de orden de dicho listado que se corresponde con .xlsx.
241241
242242   A continuación definimos que sucede después de seleccionar un nombre de fichero en el cuadro de diálogo. Para este propósito la acción `TFileSaveAs` aporta el evento `OnAccept`. Este es uno de los pocos lugares donde tenemos que escribir código en el proyecto..... pero es corto,: chequeamos que formato de fichero se ha seleccionado del listado y escribimos la correspondiente hoja de cálculo llamando al método `SaveToSpreadsheetFile` del TWorkbookSource:
243243
244244``` pascal
245245 uses
246246 ..., fpspreadsheet, ...; // for TsSpreadsheetFormat
247247
248248 procedure TForm1.FileSaveAs1Accept(Sender: TObject);
249249 var
250250 fmt: TsSpreadsheetFormat;
251251 begin
252252 Screen.Cursor := crHourglass;
253253 try
254254 case FileSaveAs1.Dialog.FilterIndex of
255255 1: fmt := sfOOXML; // Note: Indexes are 1-based here!
256256 2: fmt := sfExcel8;
257257 3: fmt := sfExcel5;
258258 4: fmt := sfExcel2;
259259 5: fmt := sfOpenDocument;
260260 6: fmt := sfCSV;
261261 7: fmt := sfWikiTable_WikiMedia;
262262 end;
263263 sWorkbookSource1.SaveToSpreadsheetFile(FileSaveAs1.Dialog.FileName, fmt);
264264 finally
265265 Screen.Cursor := crDefault;
266266 end;
267267 end;
268268```
269269
270270Hacemos disponible la acción FileSaveAs en la toolbar y en el menú:
271271
272272- **Toolbar**: Añadir un TToolButton a la primera toolbar y arrastrar a su borde izquierdo. Asignar la acción FileSaveAs a su propiedad `Action`.
273273- **Menu**: El mandato "Save" está habitualmente en un submenú llamado "File". Por tanto hacer doble click en TMainMenu, pulsador derecho del ratón en el elemento "Format" e insertar un nuevo elemento "antes" del actual. Llámalo "File". Añádele un submenú. Haz Click sobre el elemento por defecto y asigna la acción FileSaveAs a su propiedad `Action`.
274274
275275### Leyendo desde ficheros
276276
277277Lo que resta es **leer un fichero de hoja de cálculo** desde nuestra aplicación. Por supuesto, FPSpreadsheet está completamente preparado para esta tarea. Las operaciones son muy similares al salvado. En lugar de utilizar una acción estandar TFileSaveAs utilizamos la acción **TFileOpen** también estandar. De nuevo, esta acción estandar tiene su propio diálogo de fichero donde podemos establecer la extensión por defecto`DefaultExtension` (".xls" o ".xlsx", más probablemente) y el formato `Filter`:
278278
279279
280280`All spreadsheet files|*.xls;*.xlsx;*.ods;*.csv|All Excel files (*.xls, *.xlsx)|*.xls;*.xlsx|Excel XML spreadsheet (*.xlsx)|*.xlsx|Excel 97-2003 spreadsheets (*.xls)|*.xls|Excel 5 spreadsheet (*.xls)|*.xls|Excel 2.1 spreadsheets (*.xls)|*.xls|LibreOffice/OpenOffice spreadsheet (*.ods)|*.ods|Comma-delimited files (*.csv)|*.csv`
281281
282282(Copia esta cadena dentro del campo `Filter` de la acción `Dialog`). Como habras podido darte cuenta el filtro `Filter` contiene selecciones que comprenden varios formatos de fichero, tales como "All spreadsheet files", o "All Excel files". Esto es posible porque TsWorkbookSource tiene una propiedad para la detección automática del formato de SpreadSheet `AutoDetectFormat`. En el resto de casos, tales como los correspondientes a "Libre/OpenOffice", podemos especificar el formato explícitamente, `sfOpenDocument`. La evaluación del formato de fichero y su lectura tiene lugar mediante la acción del manejador de eventos `OnAccept`:
283283
284284``` pascal
285285{ Carga el fichero de hoja de cálculo seleccionado por la acción estandar FileOpen }
286286procedure TForm1.FileOpen1Accept(Sender: TObject);
287287begin
288288 sWorkbookSource1.AutodetectFormat := false;
289289 case FileOpen1.Dialog.FilterIndex of
290290 1: sWorkbookSource1.AutoDetectFormat := true; // Todos los ficheros de hoja de cálculo soportados.
291291 2: sWorkbookSource1.AutoDetectFormat := true; // Todos los ficheros Excel.
292292 3: sWorkbookSource1.FileFormat := sfOOXML; // Excel 2007+.
293293 4: sWorkbookSource1.FileFormat := sfExcel8; // Excel 97-2003.
294294 5: sWorkbookSource1.FileFormat := sfExcel5; // Excel 5.0.
295295 6: sWorkbookSource1.FileFormat := sfExcel2; // Excel 2.1.
296296 7: sWorkbookSource1.FileFormat := sfOpenDocument; // OpenOffice / LibreOffice.
297297 8: sWorkbookSource1.FileFormat := sfCSV; // Ficheros de texto CSV.
298298 end;
299299 sWorkbookSource1.FileName :=FileOpen1.Dialog.FileName; // Esto finalmente carga del fichero.
300300end;
301301```
302302
303303En orden a ver esta acción tanto en la toolbar como en el menú, añade un TToolButton a **toolbar** y asigna el TFileOpenAction a la propiedad de `Action`. En el **menu**, añade un nuevo elemento antes del elemento "Save as" , y asigna acordemente `Action`.
304304
305305## Summario
306306
307307Si has seguido todos los pasos de este tutorial entonces has sido capaz de programar una interface gráfica de usuario de hoja de cálculo compleja sin apenas haber tenido que escribir una línea de código (con la excepción de las rutinas de carga y salvado). En caso contrario puedes echar un vistazo a la demo "fps_ctrls" que se encuentra en la carpeta de ejemplos *examples* de la carpeta de instalación de FPSpreadsheet donde se muestra el resultado de este tutorial con algunos añadidos extra.
308308
309309---
310310*From the Free Pascal wiki, page "FPSpreadsheet tutorial: Writing a mini spreadsheet application/es", as it stood on 2020-02-16 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history