jueves, 27 de enero de 2022

Office Scripts: Classes y el método Constructor

Seguimos avanzando en el amplio mundo de Office Scripts...
Hoy toca hablar de la instrucción class y de uno de sus métodos: constructor.

Pero ¿qué son las 'classes'?.
Una Class es una declaración que nos permite definir o crear objetos, proporcionando ciertos valores iniciales (variables) e implementaciones de comportamiento (como funciones o métodos - por ejemplo, el método Constructor).
Al igual que haríamos en VBA creando un Módulo de clase, la idea es la misma... si necesitamos trabajar constantemente sobre una misma idea, i.e., sobre un mismo objeto o del mismo tipo, entonces tiene bastante sentido declarar una Class propia

Una sintáxis normal de una declaración de class sería:
class MyClass {
  // métodos o funciones de la Class
  constructor() { ... }
  método1() { ... }
  ....
  métodoN() { ... }
  // NOTA!!! sin ; entre los métodos y /o funciones!!!
}

Veamos un ejemplo sencillo para obtener un descuento sobre un importe:
function main(workbook: ExcelScript.Workbook)
{
  class Descuento {
    descontado: number
    constructor(base: number, porc: number ) {
      this.descontado = base * (1-porc);
    }
  }
  console.log(new Descuento(100, 0.15).descontado);
}

Office Scripts: Classes y el método Constructor


Lo que realmente está ocurriendo es que nuestra class 'Descuento' está generando una 'especie' de función, donde declaramos dos variables (Base y Porcentaje) con su método asociado constructor.

Una curiosidad de la declaración de 'class' es que, al igual que una función tradicional, las podemos definir dentro de otra expresión.
Por ejemplo:
function main(workbook: ExcelScript.Workbook) {
  let ClassExpresion = class MyClass {
    visible() {
    console.log("Éxito... mi class es visible");
    }
  };
  //caso 1
  new ClassExpresion().visible(); 
  //caso 2
  console.log(MyClass); // error, MyClass no se reconoce fuera de su contexto... y devuelve error: 'MyClass is not defined
}

Office Scripts: Classes y el método Constructor


Un último ejemplo usando la declaración de class para extenderla y utilizarla en otra posterior!!.
 function main(workbook: ExcelScript.Workbook) 
{
class triangulo 
{
  nombre: string; alto: number ; base: number;
  constructor(alto: number , base: number) {
    this.nombre = 'Triangulo';
    this.base = base;
    this.alto = alto;  }
}
class TRI extends triangulo 
{
  nombre: string; alto: number; base: number;color: string;  final: string;
  constructor(alto: number, base: number, color: string) {
    //'super' se usa para acceder y llamar funciones en el parent (nivel superior) del objeto.
    //además solo se puede usar en 'constructores' y se debe llamar antes de la palabra clave 'this'
    super(alto, base);
    this.nombre = 'Area triangulo';
    this.color = color;
    this.final="Triangulo de color " + color + " y area " + alto * base /2 ;  }
}
  console.log(new TRI(10,5,"rojo").final)
}

Office Scripts: Classes y el método Constructor


Como hemos observado en los ejemplos dispuestos el método 'constructor' es un método especial de una class destinado crear e inicializar una instancia de objeto de nuestra clase.
En definitiva un 'constructor' nos permite proporcionar cualquier inicialización personalizada que tenga que realizarse antes de llamar a cualquier otro método en un objeto.

Finalizar el artículo de hoy mencionando brevemente un par de palabras clave interesantes:super y this.
'super': se usa para acceder y llamar funciones en el parent (nivel superior) del objeto.
Además solo se puede usar en 'constructores' y se debe llamar antes de la palabra clave 'this'. 'this': se refiere al objeto al que pertenece.
Toma diferentes valores dependiendo de dónde se utilice:
1. En un método, esto se refiere al objeto propietario.
2. Si aparece solo, se refiere al objeto global.
3. Si lo usamos en una función, se referirá al objeto global.

martes, 25 de enero de 2022

Office Scripts: Arrow Functions

Las Arrow Functions o Funciones Flecha son esas funciones 'personalizadas' dentro del código de Office Scripts que nos permiten actuar bajo ciertas condiciones sobre nuestros objetos...
Podemos decir que sería como una alternativa a las funciones 'clásicas o tradicionales', pero más abreviadas y fáciles de aplicar.

Debemos tener claro que NO siempre podremos emplear estas funciones propias!!.
De hecho en la documentación de Microsoft ya nos advierten de que 'Nuestros Scripts solo pueden usar 'funciones flecha' cuando se proporcionan argumentos de devolución de llamada para métodos de matriz.
Además no se puede pasar ningún tipo de identificador o función 'tradicional' a estos métodos. (leer doc aquí)

Estas funciones admiten un número distintos de argumentos, incluso podemos operar sin ellos!!.

Como indicación general debemos tener siempre presente que:
-Usando la fat arrow =>, eliminamos la necesidad de usar la palabra clave function.
-Los parámetros se pasan entre paréntesis () y
-la expresión de la función se incluye entre llaves { }.

Un breve resumen de cómo escribir estas funciones flecha sería, todos ellos dentro del contexto adecuado:
Caso 1: función con un solo argumento.
Con una expresión simple ni parentesis ni se necesita indicar la palabra 'return':
argumento => expression

Caso 2: función con varios argumentos.
En este caso si se requieren paréntesis para delimitar estos argumentos. Si trabajamos con una expresión simple no se necesitaremos 'return':
(argumento1, argumento2) => expression

Caso 3: función con una expresión de varios lineas.
Se necesita incluir entre llaves la expresión y añadir la palabra 'return':
argumento => {
let x = 1;
return x + y;
}
Caso 4: función con una expresión de varios lineas y varios argumentos.
incluiremos paréntesis para los argumentos, y las declaraciones de varias líneas para la expresión de la función irán entre llaves y usaremos la palabra clave 'return':
(argumento1, argumento2) => {
let x = 1;
return x + y;
}


Veamos unos cuantos ejemplo.

Ejemplo 1:
function main(workbook: ExcelScript.Workbook) 
{
  let saludo = (texto:string): string => 
    {
    return "Bienvenido a " + texto;
    };
  console.log (saludo("Excelforo"));
}

En este ejemplo vemos como con let damos nombre a la función
let saludo = ...
Como entre paréntesis indicamos el parámetro, definiendo además el tipo de dato (string para el ejemplo)
(texto:string) ...
Y finalmente entre llaves qué hace la función. Para nuestro ejemplo concatena el parámetro a otro texto fijo
{ return "Bienvenido a " + texto; };
Acabamos devolviendo el resultado a la console llamando o haciendo uso de nuestro función:
console.log (saludo("Excelforo"))

Una alternativa de la misma función en su forma tradicional podría ser:
function main(workbook: ExcelScript.Workbook) 
{
let saludo = function (texto:string):string
{
  return "Bienvenido a " + texto
};
  console.log(saludo("Excelforo"));
}


Ejemplo 2:
Una función flecha sin parámetros...
function main(workbook: ExcelScript.Workbook) 
{
  let SinParametro = () => console.log("Bienvenidos a Excelforo");

  SinParametro()
}


Ejemplo 3:
Un punto curioso es que si el cuerpo de la función consta de una sola instrucción, no se necesitan llaves, ni la palabra clave 'return':
function main(workbook: ExcelScript.Workbook) 
{
  let sumando = (x: number, y: number):number => 
        console.log (x + y);

  sumando(10, 3); 
}


Ejemplo 4:
Un ejemplo más elaborado haciendo uso de algunas instrucciones que ya veremos en futuros artículos...
function main(workbook: ExcelScript.Workbook) 
{
class Trabajador {
  empApellido: string;
  empNombre: string;

  constructor(apellido: string, nombre: string) 
  {
    this.empNombre = nombre;
    this.empApellido = apellido;
  }

  NombreCompleto = () => console.log("Sr/a. " + this.empApellido + ', ' + this.empNombre)
}
let Trab = new Trabajador("Excelforo", "Ismael");
Trab

Office Scripts: Arrow Functions


En próximas entradas profundizaré en aspectos más avanzados de las funciones flecha.

martes, 18 de enero de 2022

Office Scripts: Operadores

Tras repasar de manera introductoria los tipos de datos y las formas de declarar variables en Office Scripts para Excel, llega el momento de ver algunos de los operadores más frecuentes...
Sabiendo que habitualmente podemos trabajar con dos tipologías de operadores: UNARIA y BINARIA
Un operador binario requiere dos operandos, uno antes del operando y otro después del operador:
operando1 operador operando2
Por ejemplo, 21-13 o a*b

Mientras que un operador unario solo necesita un operando, antes o después del operador:
operador operando1 o operando1 operador
Por ejemplo, x++ o ++x.

Si navegas un poco por internet encontraras diferentes clasificaciones de estos operadores, y una lista larga de todos ellos... pero al final todo se resume en:
1-operadores de asignación: donde se asigna un valor a su operando izquierdo basándose en el valor de su operando derecho. Ejemplo Y = X
NombreForma…Significado
Asignaciónx = yx = y
Asignación de adiciónx += yx = x + y
Asignación de restax -= yx = x - y
Asignación de multiplicaciónx *= yx = x * y
Asignación de divisiónx /= yx = x / y
Asignación de residuox %= yx = x % y
Asignación de exponenciaciónx **= yx = x ** y

2-operadores de comparación: donde se comparan dos operadores, recuperando un verdadero o falso.
OperadorForma…Significado
Igual (==)x == yDevuelve true si los operandos son iguales.
No es igual (!=)x != yDevuelve true si los operandos no son iguales.
Estrictamente igual (===)x === yDevuelve true si los operandos son iguales y del mismo tipo.
Desigualdad estricta (!==)x !== yDevuelve true si los operandos son del mismo tipo pero no iguales, o son de diferente tipo.
Mayor que (>)x > yDevuelve true si el operando izquierdo es mayor que el operando derecho.
Mayor o igual que (>=)x >= yDevuelve true si el operando izquierdo es mayor o igual que el operando derecho.
Menor que (<)x < yDevuelve true si el operando izquierdo es menor que el operando derecho.
Menor o igual (<=)x <= yDevuelve true si el operando izquierdo es menor o igual que el operando derecho.

3-operadores aritméticos: que toma valores numéricos (ya sean literales o variables) como sus operandos y devuelve un solo valor numérico como resultado.
OperadorForma...Significado
Residuo (%)x % y // 20 % 3 = 2Operador binario. Devuelve el resto entero de dividir los dos operandos.
Incremento (++)x=3 // ++x = 4 Operador unario. Agrega uno a su operando. Si se usa como operador prefijo (++x), devuelve el valor de su operando después de agregar uno; si se usa como operador sufijo (x++), devuelve el valor de su operando antes de agregar uno.
Decremento (--)x=9 // --x = 8Operador unario. Resta uno de su operando. El valor de retorno es análogo al del operador de incremento.
Negación unaria (-)x=5 // -x = -5Operador unario. Devuelve la negación de su operando.
Positivo unario (+)x='13' // +x = 13Operador unario. Intenta convertir el operando en un número, si aún no lo es.
Operador de exponenciación (**)3 ** 3 = 27Calcula la base a la potencia de exponente, es decir, baseexponente

4-operadores lógicos: se utilizan normalmente con valores booleanos (true o false).
OperadorForma…Significado
AND Lógico (&&)expr1 && expr2Devuelve expr1 si se puede convertir a false; de lo contrario, devuelve expr2. Por lo tanto, cuando se usa con valores booleanos, && devuelve true si ambos operandos son true; de lo contrario, devuelve false.
OR lógico (||)expr1 || expr2Devuelve expr1 si se puede convertir a true; de lo contrario, devuelve expr2. Por lo tanto, cuando se usa con valores booleanos, || devuelve true si alguno de los operandos es true; si ambos son falsos, devuelve false.
NOT lógico (!)!exprDevuelve false si su único operando se puede convertir a true; de lo contrario, devuelve true.

5-operador de cadena: el operador de concatenación (+) concatena dos valores de cadena, devolviendo otra cadena que es la unión de los dos operandos dados.
OperadorForma…Significado
más (+)expr1 + expr2 // expr1 += expr2Concatena ambas expresiones

Por supuesto existen más categorías, pero he optado por detallar los principales o más habituales.

Algunos ejemplos de estos operadores...
function main(workbook: ExcelScript.Workbook)
{
  let v1: string ='1';
  let v2: number = 1;
  let txt3: string='Romero';
  let txt4='año ';
  let anyo=2022;
  let mes=1;
  let dia1=31;
  let dia2=10;
//
console.log(v1 == v2);
console.log(v1 === v2);
console.log(+v1 === v1);
console.log(dia2 % dia1);
console.log( txt4 += anyo);
}

Office Scripts: Operadores

El primer ejemplo v1 == v2 compara el '1' (texto) con 1 (número), retornando true, ya que el valor es el mismo.
Sin embargo v1 === v2 compara y verifica valor y tipo de dato, por lo que devuelve false.
Otro ejemplo curios es el operador de cadena +=, donde sobre la variable txt4 añadimos otra subcadena 'anyo', obteniendo ahora una cadena completa asociada a txt4...

NOTA FINAL: OJO con los operadores, ya que nos son iguales, ni en forma ni en comportamiento, a los de otros lenguajes (como VBA) en todos los casos!!!

jueves, 13 de enero de 2022

Office Scripts: Declaración de variables

En la entrada anterior del blog vimos cuáles eran los tipos de datos más frecuentes en nuestros Scripts... pero ¿qué formas existen de asignar a nuestras constantes y variables esos tipos de datos?.
Pues disponemos de tres formas de declarar variables. Que veremos de forma introductoria:
var: nos permite declarar una variable 'local' y 'global' dependiendo del contexto de ejecución, donde opcionalmente le asignaremos un valor.
let: declaramos una variable local con 'ámbito de bloque', e igual que var, opcionalmente asignamos un valor de inicio.
const: nombre de constante local de solo lectura y ámbito de bloque.
Como curiosidad, la sintaxis de un identificador de constante es la misma que la de cualquier identificador de variable: debe comenzar con una letra, un subrayado o un signo de dólar ($).
Como podemos entrever let es similar a var en muchos aspectos; y const incrementa las posibilidades de let evitando, además, la reasignación a una variable.
Es recomendable, en general, emplear 'let' y 'const' frente a 'var'.

Mencionar brevemente algo respecto al ámbito de las variables.
Cuando declaramos una variable fuera de cualquier función, se denomina variable global, ya que está disponible para cualquier otro código en el documento actual.
Por contra, cuando declaramos una variable dentro de una función, se llama variable local, porque solo está disponible dentro de esa función.

Veamos algunos ejemplos sencillos de declaración de variables:
function main(workbook: ExcelScript.Workbook)
{
  var a = 1313;
  var mensaje = "algo de texto";
  console.log(a + mensaje);
////
  let b = 1234;
  let texto = "algo más de texto";
  console.log(b + texto);
////
  const n=1;
  const nombre_completo = {nombre:'Ismael', apellido: "Romero"}; 
  console.log(nombre_completo.nombre + ' ' + nombre_completo.apellido);

}

Office Scripts: Declaración de variables


Como se observa todo depende de dónde declaremos nuestras variables para determinar su tipo (global o local) e incluso su ámbito.

martes, 11 de enero de 2022

Office Scripts: Tipos de datos

Un aspecto básico al programar en cualquier lenguaje es aplicar correctamente a constantes y/o variables el tipo de dato asociado a ésta... y por supuesto, Office Scripts no es la excepción.
Hoy repasaremos los distintos tipos de datos que nos podemos encontrar al programar con Office Script.

En la distinta documentación existente al respecto dividen los tipos de datos en dos grandes categorías:
i) primitivos,
ii) objetos.

Si bien nos centraremos en los tipos de datos primitivos, esto es, lo más esenciales que serían: Number, Boolean, String, Symbol, Void, Null y Undefined... además de los definidos por el usuario: enum.
Finalmente, para emplear en nuestra programación alguna de estas categorías deberemos emplear una clave de tipo de datos concreta: number, boolean, string, symbol, void, null y undefined respectivamente...

Por comentar los más frecuentes:
Tipo de datos boolean: el más simple... permite valores true y false.
Tipo de datos number: un número entero o un número con coma flotante.
Tipo de datos string: secuencia de caracteres que representan un valor de texto. NOTA. Se asigna valor entre comillas simples o dobles !!!.
Tipo de datos null: en minúscula... representa el valor vacío, sin dato.
Tipo de datos undefined: valores sin tipo de datos asignado.
Tipo de datos personalizado enum: empleado para asignar nombres, más sencillos de recordar, a los conjuntos de valores (numéricos o de texto).
Por comentar brevemente los objetos, diré que este tipo de dato se usa habitualmente para guardar una colección de datos definidos o entidades más complejas.

Un comentario general es que en Office Scripts, igual que en otros lenguajes, NO es necesario especificar el tipo de dato de una variable cuando la declaramos!!.
Otra ventaja es que los tipos de datos se convierten automáticamente según sea necesario durante la ejecución de nuestros Scripts, pasando si fuera necesario de un tipo de datos a otro.

Veamos en la práctica cómo definir y asignar tipos de datos a variables o constantes.
Por suerte no hay una sola manera ;-)
Una estructura o sintáxis general es:
let/var/const 'nombre variable': tipo de dato = valor dado a la variable
let/var/const 'nombre variable' = valor dado a la variable

Ejemplos:
function main(workbook: ExcelScript.Workbook)
{
  let texto: string = "Excel";
  let num: number = 1234;
  let t_f: boolean = true;
  let sin_dato: null = null;
  enum apps { Excel, Word, Access, Outlook };
  let w: apps = apps.Word;
///
// otra forma de trabajar, sin asignar tipos de datos
let texto2 = 'Excel';
let num2 = 1234;
let verdadero = true;
/// Conversiones...
  let y = num.toFixed(2);
  let t = texto.charAt(2);
  let p_i=parseInt('123.45',0);
  let p_f = parseFloat('123.45');
  let mas= +'3.14'+ +'3.14';

  console.log(num2 + 2);
  console.log(texto2 + 2);
  console.log(w + 2);
  // conversiones
  console.log(y);
  console.log(t);
  console.log(p_i);
  console.log(p_f);
  // más
  console.log(mas);
}

Office Scripts: Tipos de datos

Mencionar algunas funciones que nos permitirán tratar o pasar de un tipo de datos a otro:
Numero.toFixed(num_decimales): devuelve el valor numérico como un TEXTO, con las posiciones decimales indicadas.
Texto.CharAt(posción-en base cero): devuelve la posición indicada (en base cero), obviamente como un TEXTO
.parseInt: convierte un número almacenado como texto a número ENTERO!!.
.parseFloat: convierte un número almacenado como texto a número DECIMAL!!.
Uso del operador +: convierte un número almacenado como texto a número!!. (let mas= +'3.14'+ +'3.14';)

martes, 4 de enero de 2022

Office Scripts: IF ELSE y SWITCH Condicionales

En las entradas del blog previas hemos repasado como construir nuestros bucles (FOR o WHILE), lo que nos permite recorrer partes o elementos de nuestros objetos...
Eso está muy bien, pero sin aplicar condiciones que segmenten los valores recorridos, poco podremos hacer.
Y aquí es, entre otras muchas y distintas casuísticas, donde entran en juego los condicionales:
IF ELSE y SWITCH
.

La instrucción IF ELSE normalmente se emplea para verficiar ciertas condiciones... y en otros casos cuando necesitamos ejecutar otras rutinas cuando se den las condiciones especificadas.
La sintaxis de la sentencia de control sería, en su forma simple:
if (Condición_Prueba Lógica)
{
// nuestro código a procesar si cumple la condición
}

O bien en su forma más completa, donde indicamos la acción en caso de no cumplir la condición dada:
if (Condición_Prueba Lógica)
{
// nuestro código a procesar si cumple la condición
else
// nuestro código a procesar si NO cumple la condición
}

Veamos un ejemplo donde evaluaremos el valor de cada celda de un rango dado, verificando si el valor es mayor o menor a 18:
function main(workbook: ExcelScript.Workbook)
{
  let Hoja = workbook.getActiveWorksheet();
  let Edades = Hoja.getRange("A1:A10").getValues(); 
  let texto: string;
  
  Edades.forEach(edad => 
    {
      if (+edad < 18)
        texto = 'Menor de edad';
      else
        texto = 'Mayor de edad';

      console.log( texto );
    });
}

Office Scripts: IF ELSE y SWITCH Condicionales

Por supuesto podemos incorporar tantas respuestas 'else' como sean necesarias (sujetas a otras tantas condiciones)...:
if (condición1)
//código a procesar si cumple la condición1
else if(condición2)
//código a procesar si cumple la condición2
else if(condición3)
//código a procesar si cumple la condición
....
else
//código a procesar si NO cumple ninguna de las condiciones anteriores


La otra instrucción condicional es SWITCH CASE (equivalente al SELECT CASE de VBA), con sintaxis:
switch (expresión a evaluar) {
case case1:
statements1
[break;]
case case2:
statements2
[break;]
...
default
: default statements
[break;]
}

Un 'pequeño problema' (hasta donde he podido analizar) de SWITCH es que no admite operadores de comparación como < o > :'(
En estos casos mejor emplear IF ELSE
... o bien aplicar un truco 'booleano'.
Veamoslo en el siguiente ejemplo:
function main(workbook: ExcelScript.Workbook) {
  let Hoja = workbook.getActiveWorksheet();
  let Edades = Hoja.getRange("A1:A10").getValues() ;
  let texto: string;

  Edades.forEach(edad  => {
    switch (true) {
        case (edad < 18) : 
          texto ="Menor de edad";
          break; 
        case (edad < 30 ): 
          texto = "Joven";
          break;
        case (edad < 60): 
          texto = "Maduro" ;
          break;
        default :
          texto="Senior";
          break;     }
    console.log(texto);
  });
}

La lógica inicial hubiera sido:
Edades.forEach(edad => {
switch (edad) {
case ( < 18) :
texto ="Menor de edad";
break;
case ( < 30 ):
texto = "Joven";
break;
case ( < 60):
texto = "Maduro" ;
break;
default :
texto="Senior";
break; }
console.log(texto);
});

pero esta construcción genera error y no ejecuta correctamente el proceso.

Continuaremos con Office Scripts en siguientes artículos...